X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/2abdfa491ccf46320cd813764ca8ca49073388ed..53f7c75a38a18e79313e7bd5f664a11a73db5307:/armsrc/mifarecmd.c

diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c
index 423b6e95..49730af9 100644
--- a/armsrc/mifarecmd.c
+++ b/armsrc/mifarecmd.c
@@ -4,7 +4,7 @@
 // Hagen Fritsch - June 2010
 // Midnitesnake - Dec 2013
 // Andy Davies  - Apr 2014
-// Iceman - May 2014
+// Iceman - May 2014,2015,2016
 //
 // 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
@@ -75,7 +75,6 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 		break;
 	}
 	
-	//  ----------------------------- crypto1 destroy
 	crypto1_destroy(pcs);
 	
 	if (MF_DBGLEVEL >= 2)	DbpString("READ BLOCK FINISHED");
@@ -235,18 +234,17 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 		if (MF_DBGLEVEL >= 1)	Dbprintf("Halt error");
 	}
 
-	//  ----------------------------- crypto1 destroy
-	crypto1_destroy(pcs);
-	
 	if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED");
 
+	crypto1_destroy(pcs);
+
 	LED_B_ON();
 	cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo));
 	LED_B_OFF();
 
-	// Thats it...
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 	LEDsoff();
+	set_tracing(FALSE);
 }
 
 // arg0 = blockNo (start)
@@ -345,6 +343,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 	LEDsoff();
 	BigBuf_free();
+	set_tracing(FALSE);
 }
 
 //-----------------------------------------------------------------------------
@@ -380,7 +379,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 	LED_C_OFF();
 
 	while (true) {
-			if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
+		if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
 			if (MF_DBGLEVEL >= 1)	Dbprintf("Can't select card");
 			break;
 		};
@@ -404,19 +403,15 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 		break;
 	}
 	
-	//  ----------------------------- crypto1 destroy
 	crypto1_destroy(pcs);
 	
 	if (MF_DBGLEVEL >= 2)	DbpString("WRITE BLOCK FINISHED");
 
-	LED_B_ON();
 	cmd_send(CMD_ACK,isOK,0,0,0,0);
-	LED_B_OFF();
-
 
-	// Thats it...
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 	LEDsoff();
+	set_tracing(FALSE);
 }
 
 /* // Command not needed but left for future testing 
@@ -527,6 +522,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
 	cmd_send(CMD_ACK,1,0,0,0,0);
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 	LEDsoff();
+	set_tracing(FALSE);
 }
 
 void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
@@ -597,6 +593,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
 	cmd_send(CMD_ACK,1,0,0,0,0);
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 	LEDsoff();
+	set_tracing(FALSE);
 }
 
 // Return 1 if the nonce is invalid else return 0
@@ -613,6 +610,9 @@ int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) {
 // Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on 
 // Computer and Communications Security, 2015
 //-----------------------------------------------------------------------------
+#define AUTHENTICATION_TIMEOUT  848 //848			// card times out 1ms after wrong authentication (according to NXP documentation)
+#define PRE_AUTHENTICATION_LEADTIME 400		// some (non standard) cards need a pause after select before they are ready for first authentication 
+
 void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain)
 {
 	uint64_t ui64Key = 0;
@@ -638,9 +638,6 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
 	bool slow = flags & 0x0002;
 	bool field_off = flags & 0x0004;
 	
-	#define AUTHENTICATION_TIMEOUT 848			// card times out 1ms after wrong authentication (according to NXP documentation)
-	#define PRE_AUTHENTICATION_LEADTIME 400		// some (non standard) cards need a pause after select before they are ready for first authentication 
-	
 	LED_A_ON();
 	LED_C_OFF();
 
@@ -716,10 +713,8 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
 			memcpy(buf+i+8, &nt_par_enc, 1);
 			i += 9;
 		}
-
 		// wait for the card to become ready again
-		while(GetCountSspClk() < timeout);
-	
+		while(GetCountSspClk() < timeout);	
 	}
 
 	LED_C_OFF();
@@ -735,6 +730,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
 	if (field_off) {
 		FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 		LEDsoff();
+		set_tracing(FALSE);
 	}
 }
 
@@ -940,7 +936,6 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
 
 	LED_C_OFF();
 	
-	//  ----------------------------- crypto1 destroy
 	crypto1_destroy(pcs);
 	
 	byte_t buf[4 + 4 * 4] = {0};
@@ -965,16 +960,17 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
 // MIFARE check keys. key count up to 85. 
 // 
 //-----------------------------------------------------------------------------
-void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
-{
-  // params
+void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
 	uint8_t blockNo = arg0 & 0xff;
 	uint8_t keyType = (arg0 >> 8) & 0xff;
 	bool clearTrace = arg1;
 	uint8_t keyCount = arg2;
 	uint64_t ui64Key = 0;
 	
-	// variables
+	bool have_uid = FALSE;
+	uint8_t cascade_levels = 0;
+	uint32_t timeout = 0;
+	
 	int i;
 	byte_t isOK = 0;
 	uint8_t uid[10] = {0x00};
@@ -999,16 +995,42 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 	
 	for (i = 0; i < keyCount; ++i) {
 
-		mifare_classic_halt(pcs, cuid);
-	
-		if (!iso14443a_select_card(uid, NULL, &cuid, true, 0))
-			break;
+		//mifare_classic_halt(pcs, cuid);
 
+		// this part is from Piwi's faster nonce collecting part in Hardnested.
+		if (!have_uid) { // need a full select cycle to get the uid first
+			iso14a_card_select_t card_info;		
+			if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0)) {
+				if (MF_DBGLEVEL >= 1)	Dbprintf("ChkKeys: Can't select card (ALL)");
+				break;
+			}
+			switch (card_info.uidlen) {
+				case 4 : cascade_levels = 1; break;
+				case 7 : cascade_levels = 2; break;
+				case 10: cascade_levels = 3; break;
+				default: break;
+			}
+			have_uid = TRUE;	
+		} else { // no need for anticollision. We can directly select the card
+			if(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels)) {
+				if (MF_DBGLEVEL >= 1)	Dbprintf("ChkKeys: Can't select card (UID)");
+				continue;
+			}
+		}
+	
 		ui64Key = bytes_to_num(datain + i * 6, 6);
 		
-		if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST))
+		if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
+
+			uint8_t dummy_answer = 0;
+			ReaderTransmit(&dummy_answer, 1, NULL);
+			timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT;
+			
+			// wait for the card to become ready again
+			while(GetCountSspClk() < timeout);
+			
 			continue;
-		
+		}
 		isOK = 1;
 		break;
 	}
@@ -1373,16 +1395,10 @@ void OnErrorMagic(uint8_t reason){
 	cmd_send(CMD_ACK,0,reason,0,0,0);
 	OnSuccessMagic();
 }
-
-void MifareCollectNonces(uint32_t arg0, uint32_t arg1){
-}
-
 //
 // DESFIRE
 //
-
 void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
-
 	byte_t dataout[12] = {0x00};
 	uint8_t uid[10] = {0x00};
 	uint32_t cuid = 0;
@@ -1405,11 +1421,10 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
 	}
 
 	if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");
-    cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));
+    cmd_send(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout));
 }
 
 void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
-
 	uint32_t cuid = arg0;
 	uint8_t key[16] = {0x00};
 	byte_t dataout[12] = {0x00};
@@ -1430,4 +1445,5 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
 	cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 	LEDsoff();
+	set_tracing(FALSE);
 }
\ No newline at end of file