X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/838c15a6433b1cf1726aede99fa8dcdc7862473a..2deea574d37b80c819f54459d064841f1572d7b0:/armsrc/mifarecmd.c?ds=inline

diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c
index c097cfd5..238bdf8f 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)
@@ -260,7 +258,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
 	iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
 
 	// free eventually allocated BigBuf memory
-	BigBuf_free();
+	BigBuf_free(); BigBuf_Clear_ext(false);
 	clear_trace();
 	set_tracing(true);
 	
@@ -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);
 }
 
 //-----------------------------------------------------------------------------
@@ -413,10 +412,9 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 	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 +525,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 +596,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 +613,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 +641,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 +716,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 +733,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
 	if (field_off) {
 		FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 		LEDsoff();
+		set_tracing(FALSE);
 	}
 }
 
@@ -778,8 +777,8 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
 	iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
 
 	// free eventually allocated BigBuf memory
-	BigBuf_free();
-
+	BigBuf_free(); BigBuf_Clear_ext(false);
+	
 	if (calibrate) clear_trace();
 	set_tracing(true);
 
@@ -832,7 +831,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
 
 			nttmp = prng_successor(nt1, 100);				//NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160
 			for (i = 101; i < 1200; i++) {
-				nttmp = prng_successor_one(nttmp);
+				nttmp = prng_successor(nttmp, 1);
 				if (nttmp == nt2) break;
 			}
 
@@ -914,7 +913,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
 			ncount = 0;
 			nttest = prng_successor(nt1, dmin - 1);
 			for (j = dmin; j < dmax + 1; j++) {
-				nttest = prng_successor_one(nttest);
+				nttest = prng_successor(nttest, 1);
 				ks1 = nt2 ^ nttest;
 
 				if (valid_nonce(nttest, nt2, ks1, par_array)){
@@ -940,7 +939,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 +963,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};
@@ -983,7 +982,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 	struct Crypto1State *pcs;
 	pcs = &mpcs;
 	
-	// clear debug level
+	// save old debuglevel, and tempory turn off dbg printing. speedissues.
 	int OLD_MF_DBGLEVEL = MF_DBGLEVEL;	
 	MF_DBGLEVEL = MF_DBG_NONE;
 	
@@ -996,35 +995,59 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 		clear_trace();
 	
 	set_tracing(TRUE);
-
+	
 	for (i = 0; i < keyCount; ++i) {
 
-		if (!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
-			if (OLD_MF_DBGLEVEL >= 1)	Dbprintf("ChkKeys: Can't select card");
-			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_halt(pcs, cuid))
-				if (MF_DBGLEVEL >= 1)	Dbprintf("ChkKeys: Halt error");
+
+			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;
 	}
 	
 	LED_B_ON();
-    cmd_send(CMD_ACK,isOK,0,0,datain + i * 6,6);
+    cmd_send(CMD_ACK, isOK, 0, 0, datain + i * 6, 6);
 
+	// restore debug level
+	MF_DBGLEVEL = OLD_MF_DBGLEVEL;	
+	
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 	LEDsoff();
 	set_tracing(FALSE);
 	crypto1_destroy(pcs);
-	
-	// restore debug level
-	MF_DBGLEVEL = OLD_MF_DBGLEVEL;	
 }
 
 //-----------------------------------------------------------------------------
@@ -1205,7 +1228,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){
 	
 		// wipe tag, fill it with zeros
 		if (workFlags & MAGIC_WIPE){
-			ReaderTransmitBitsPar(wupC1,7,0, NULL);
+			ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
 			if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
 				if (MF_DBGLEVEL >= MF_DBG_ERROR)	Dbprintf("wupC1 error");
 				errormsg = MAGIC_WIPE;
@@ -1224,7 +1247,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){
 
 		// write block
 		if (workFlags & MAGIC_WUPC) {
-			ReaderTransmitBitsPar(wupC1,7,0, NULL);
+			ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
 			if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
 				if (MF_DBGLEVEL >= MF_DBG_ERROR)	Dbprintf("wupC1 error");
 				errormsg = MAGIC_WUPC;
@@ -1297,7 +1320,7 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){
 	//loop doesn't loop just breaks out if error or done
 	while (true) {
 		if (workFlags & MAGIC_WUPC) {
-			ReaderTransmitBitsPar(wupC1,7,0, NULL);
+			ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
 			if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
 				if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error");
 				errormsg = MAGIC_WUPC;
@@ -1322,10 +1345,9 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){
 		memcpy(data, receivedAnswer, sizeof(data));
 		
 		// send HALT
-		if (workFlags & MAGIC_HALT) {
+		if (workFlags & MAGIC_HALT)
 			mifare_classic_halt_ex(NULL);
-			break;
-		}
+
 		isOK = true;
 		break;
 	}
@@ -1351,7 +1373,7 @@ void MifareCIdent(){
 	uint8_t receivedAnswer[1] = {0x00};
 	uint8_t receivedAnswerPar[1] = {0x00};
 
-	ReaderTransmitBitsPar(wupC1,7,0, NULL);
+	ReaderTransmitBitsPar(wupC1, 7, NULL, NULL);
 	if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
 		isOK = false;
 	}
@@ -1376,16 +1398,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;
@@ -1408,11 +1424,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};
@@ -1433,4 +1448,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