X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/aaa1a9a2dcb8b9f2b6acd937f84464daa50ecad6..c840385effee20347ec8179a393bf109c681de9d:/armsrc/mifarecmd.c

diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c
index c0e357b8..f906099c 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,20 +638,20 @@ 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();
 
+	BigBuf_free(); BigBuf_Clear_ext(false);	
+	clear_trace();
+	set_tracing(FALSE);
+	
 	if (initialize) {
 		iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
-		clear_trace();
-		set_tracing(true);
 	}
 	
 	LED_C_ON();
 	
+	uint8_t dummy_answer = 0;	
 	uint16_t num_nonces = 0;
 	bool have_uid = false;
 	for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) {
@@ -702,7 +702,6 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
 		}
 	
 		// send a dummy byte as reader response in order to trigger the cards authentication timeout
-		uint8_t dummy_answer = 0;
 		ReaderTransmit(&dummy_answer, 1, NULL);
 		timeout = GetCountSspClk() + AUTHENTICATION_TIMEOUT;
 		
@@ -711,21 +710,17 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
 			memcpy(buf+i, receivedAnswer, 4);
 			nt_par_enc = par_enc[0] & 0xf0;
 		} else {
-			nt_par_enc |= par_enc[0] >> 4;
+			nt_par_enc |= par_enc[0]  >> 4;
 			memcpy(buf+i+4, receivedAnswer, 4);
 			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();
-	
-	crypto1_destroy(pcs);
-	
+	crypto1_destroy(pcs);	
 	LED_B_ON();
 	cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf));
 	LED_B_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);
 	}
 }
 
@@ -832,7 +828,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 +910,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 +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};
@@ -983,7 +979,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 +992,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;	
 }
 
 //-----------------------------------------------------------------------------
@@ -1197,15 +1217,14 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){
 			if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
 				if (MF_DBGLEVEL >= MF_DBG_ERROR)	Dbprintf("Can't select card");
 				errormsg = MAGIC_UID;
-				// break;
 			}
-			
-			if ( mifare_classic_halt_ex(NULL) ) break;
+			mifare_classic_halt_ex(NULL);
+			break;
 		}
 	
 		// 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;
@@ -1219,12 +1238,12 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){
 				break;
 			}
 
-			if ( mifare_classic_halt_ex(NULL) ) break;
+			mifare_classic_halt_ex(NULL);
 		}	
 
 		// 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;
@@ -1256,7 +1275,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){
 		}	
 	
 		if (workFlags & MAGIC_OFF) 
-			if ( mifare_classic_halt_ex(NULL) ) break;
+			mifare_classic_halt_ex(NULL);
 		
 		isOK = true;
 		break;
@@ -1297,7 +1316,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;
@@ -1350,7 +1369,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;
 	}
@@ -1375,16 +1394,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;
@@ -1407,11 +1420,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};
@@ -1432,4 +1444,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