From: pwpiwi <pwpiwi@users.noreply.github.com>
Date: Sun, 1 Oct 2017 15:52:10 +0000 (+0200)
Subject: Don't do iso14443-4 select for mifare emulations on processor cards (IDPrime, SmartMX... 
X-Git-Tag: v3.1.0~162^2~2
X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/c04a4b60cefc545641582da165c42b3023f5f753?hp=--cc

Don't do iso14443-4 select for mifare emulations on processor cards (IDPrime, SmartMX, ...)
---

c04a4b60cefc545641582da165c42b3023f5f753
diff --git a/armsrc/appmain.c b/armsrc/appmain.c
index b375c3ce..e292483b 100644
--- a/armsrc/appmain.c
+++ b/armsrc/appmain.c
@@ -450,7 +450,7 @@ void StandAloneMode14a()
 						SpinDelay(300);
 					}
 				}
-				if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid, true, 0))
+				if (!iso14443a_select_card(uid, &hi14a_card[selected], &cuid, true, 0, true))
 					continue;
 				else
 				{
diff --git a/armsrc/epa.c b/armsrc/epa.c
index f434aa34..fd71430b 100644
--- a/armsrc/epa.c
+++ b/armsrc/epa.c
@@ -530,7 +530,7 @@ int EPA_Setup()
 	// power up the field
 	iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
 	// select the card
-	return_code = iso14443a_select_card(uid, &card_select_info, NULL, true, 0);
+	return_code = iso14443a_select_card(uid, &card_select_info, NULL, true, 0, false);
 	if (return_code == 1) {
 		// send the PPS request
 		ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c
index 29b23833..e9ad2535 100644
--- a/armsrc/iso14443a.c
+++ b/armsrc/iso14443a.c
@@ -1733,7 +1733,8 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity)
 // fills the card info record unless NULL
 // if anticollision is false, then the UID must be provided in uid_ptr[] 
 // and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID)
-int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades) {
+// requests ATS unless no_rats is true
+int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) {
 	uint8_t wupa[]       = { 0x52 };  // 0x26 - REQA  0x52 - WAKE-UP
 	uint8_t sel_all[]    = { 0x93,0x20 };
 	uint8_t sel_uid[]    = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
@@ -1868,24 +1869,24 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
 	// non iso14443a compliant tag
 	if( (sak & 0x20) == 0) return 2; 
 
-	// Request for answer to select
-	AppendCrc14443a(rats, 2);
-	ReaderTransmit(rats, sizeof(rats), NULL);
+	if (!no_rats) {
+		// Request for answer to select
+		AppendCrc14443a(rats, 2);
+		ReaderTransmit(rats, sizeof(rats), NULL);
 
-	if (!(len = ReaderReceive(resp, resp_par))) return 0;
+		if (!(len = ReaderReceive(resp, resp_par))) return 0;
 
-	
-	if(p_hi14a_card) {
-		memcpy(p_hi14a_card->ats, resp, sizeof(p_hi14a_card->ats));
-		p_hi14a_card->ats_len = len;
-	}
-
-	// reset the PCB block number
-	iso14_pcb_blocknum = 0;
+		if(p_hi14a_card) {
+			memcpy(p_hi14a_card->ats, resp, len);
+			p_hi14a_card->ats_len = len;
+		}
 
-	// set default timeout based on ATS
-	iso14a_set_ATS_timeout(resp);
+		// reset the PCB block number
+		iso14_pcb_blocknum = 0;
 
+		// set default timeout based on ATS
+		iso14a_set_ATS_timeout(resp);
+	}
 	return 1;	
 }
 
@@ -1971,7 +1972,7 @@ void ReaderIso14443a(UsbCommand *c)
 		iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
 		if(!(param & ISO14A_NO_SELECT)) {
 			iso14a_card_select_t *card = (iso14a_card_select_t*)buf;
-			arg0 = iso14443a_select_card(NULL, card, NULL, true, 0);
+			arg0 = iso14443a_select_card(NULL, card, NULL, true, 0, param & ISO14A_NO_RATS);
 			cmd_send(CMD_ACK,arg0,card->uidlen,0,buf,sizeof(iso14a_card_select_t));
 		}
 	}
@@ -2168,7 +2169,7 @@ void ReaderMifare(bool first_try)
 			SpinDelay(100);
 		}
 		
-		if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
+		if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
 			if (MF_DBGLEVEL >= 1)	Dbprintf("Mifare: Can't select card");
 			continue;
 		}
diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h
index 658216e7..10e50e0f 100644
--- a/armsrc/iso14443a.h
+++ b/armsrc/iso14443a.h
@@ -27,6 +27,6 @@ extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
 
 extern void iso14443a_setup(uint8_t fpga_minor_mode);
 extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data);
-extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades);
+extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
 extern void iso14a_set_trigger(bool enable);
 #endif /* __ISO14443A_H */
diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c
index 60a85c80..a3f0d374 100644
--- a/armsrc/mifarecmd.c
+++ b/armsrc/mifarecmd.c
@@ -59,7 +59,7 @@ void MifareReadBlock(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, true)) {
 			if (MF_DBGLEVEL >= 1)	Dbprintf("Can't select card");
 			break;
 		};
@@ -106,7 +106,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){
 
 	clear_trace();
 
-	if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) {
+	if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
 		if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");
 		OnError(0);
 		return;
@@ -141,7 +141,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
 
 	clear_trace();
 
-	int len = iso14443a_select_card(NULL, NULL, NULL, true, 0);
+	int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
 	if(!len) {
 		if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len);
 		OnError(1);
@@ -217,7 +217,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 	LED_C_OFF();
 
 	isOK = 1;
-	if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
+	if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
 		isOK = 0;
 		if (MF_DBGLEVEL >= 1)	Dbprintf("Can't select card");
 	}
@@ -281,7 +281,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)
 		return;
 	}
 
-	int len = iso14443a_select_card(NULL, NULL, NULL, true, 0);
+	int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
 	if (!len) {
 		if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len);
 		OnError(1);
@@ -383,7 +383,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, true)) {
 			if (MF_DBGLEVEL >= 1)	Dbprintf("Can't select card");
 			break;
 		};
@@ -483,7 +483,7 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)
 
 	clear_trace();
 
-	if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) {
+	if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
 		if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
 		OnError(0);
 		return;
@@ -542,7 +542,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){
 
 	clear_trace();
 
-	if(!iso14443a_select_card(NULL, NULL, NULL, true, 0)) {
+	if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) {
 		if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");
 		OnError(0);
 		return;
@@ -662,7 +662,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
 
 		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(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
 				if (MF_DBGLEVEL >= 1)	Dbprintf("AcquireNonces: Can't select card (ALL)");
 				continue;
 			}
@@ -674,7 +674,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
 			}
 			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(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) {
 				if (MF_DBGLEVEL >= 1)	Dbprintf("AcquireNonces: Can't select card (UID)");
 				continue;
 			}
@@ -807,7 +807,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
 				continue;
 			}
 
-			if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
+			if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
 				if (MF_DBGLEVEL >= 1)	Dbprintf("Nested: Can't select card");
 				rtr--;
 				continue;
@@ -881,7 +881,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat
 				continue;
 			}
 
-			if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
+			if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
 				if (MF_DBGLEVEL >= 1)	Dbprintf("Nested: Can't select card");
 				continue;
 			};
@@ -1000,7 +1000,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 		// Iceman: use 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(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) {
 				if (OLD_MF_DBGLEVEL >= 1) 	Dbprintf("ChkKeys: Can't select card");
 				--i; // try same key once again
 				continue;
@@ -1013,7 +1013,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 			}
 			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(!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) {
 				if (OLD_MF_DBGLEVEL >= 1)	Dbprintf("ChkKeys: Can't select card (UID)");
 				--i; // try same key once again
 				continue;
@@ -1111,7 +1111,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
 
 	bool isOK = true;
 
-	if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
+	if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
 		isOK = false;
 		if (MF_DBGLEVEL >= 1)	Dbprintf("Can't select card");
 	}
@@ -1349,7 +1349,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
 
 		// get UID from chip
 		if (workFlags & 0x01) {
-			if(!iso14443a_select_card(uid, NULL, &cuid, true, 0)) {
+			if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) {
 				if (MF_DBGLEVEL >= 1)	Dbprintf("Can't select card");
 				// Continue, if we set wrong UID or wrong UID checksum or some ATQA or SAK we will can't select card. But we need to write block 0 to make card work.
 				//break;
@@ -1573,7 +1573,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
 	iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
 	clear_trace();
 
-	int len = iso14443a_select_card(uid, NULL, &cuid, true, 0);
+	int len = iso14443a_select_card(uid, NULL, &cuid, true, 0, true);
 	if(!len) {
 		if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");
 		OnError(1);
diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c
index b75215a0..db9ce46e 100644
--- a/client/cmdhf14a.c
+++ b/client/cmdhf14a.c
@@ -442,7 +442,7 @@ int CmdHF14ACUIDs(const char *Cmd)
 	// repeat n times
 	for (int i = 0; i < n; i++) {
 		// execute anticollision procedure
-		UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}};
+		UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}};
 		SendCommand(&c);
     
 		UsbCommand resp;
@@ -581,6 +581,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
 	bool power = false;
 	bool active = false;
 	bool active_select = false;
+	bool no_rats = false;
 	uint16_t numbits = 0;
 	bool bTimeout = false;
 	uint32_t timeout = 0;
@@ -601,6 +602,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
 		PrintAndLog("       -b    number of bits to send. Useful for send partial byte");
 		PrintAndLog("       -t    timeout in ms");
 		PrintAndLog("       -T    use Topaz protocol to send command");
+		PrintAndLog("       -3    ISO14443-3 select only (skip RATS)");
 		return 0;
 	}
 
@@ -645,6 +647,9 @@ int CmdHF14ACmdRaw(const char *cmd) {
 				case 'T':
 					topazmode = true;
 					break;
+				case '3':
+					no_rats = true;
+					break;
 				default:
 					PrintAndLog("Invalid option");
 					return 0;
@@ -718,6 +723,10 @@ int CmdHF14ACmdRaw(const char *cmd) {
 		c.arg[0] |= ISO14A_TOPAZMODE;
 	}
 
+	if(no_rats) {
+		c.arg[0] |= ISO14A_NO_RATS;
+	}
+
 	// Max buffer is USB_CMD_DATA_SIZE (512)
 	c.arg[1] = (datalen & 0xFFFF) | ((uint32_t)numbits << 16);
 	memcpy(c.d.asBytes,data,datalen);
diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c
index ca4544f3..3021631a 100644
--- a/client/cmdhfmfu.c
+++ b/client/cmdhfmfu.c
@@ -108,7 +108,7 @@ char *getUlev1CardSizeStr( uint8_t fsize ){
 }
 
 static void ul_switch_on_field(void) {
-	UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
+	UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 0, 0}};
 	clearCommandBuffer();
 	SendCommand(&c);
 }
diff --git a/client/mifarehost.c b/client/mifarehost.c
index 8a840d47..629c8feb 100644
--- a/client/mifarehost.c
+++ b/client/mifarehost.c
@@ -519,20 +519,20 @@ int mfCIdentify()
 	UsbCommand resp;
 	WaitForResponse(CMD_ACK,&resp);
 
-	iso14a_card_select_t card;
-	memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
-
-	uint64_t select_status = resp.arg[0];		// 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
-
-	if(select_status != 0) {
-		uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
-		c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
-		c.arg[1] = 2;
-		c.arg[2] = 0;
-		memcpy(c.d.asBytes, rats, 2);
-		SendCommand(&c);
-		WaitForResponse(CMD_ACK,&resp);
-	}
+	// iso14a_card_select_t card;
+	// memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
+
+	// uint64_t select_status = resp.arg[0];		// 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
+
+	// if(select_status != 0) {
+		// uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0
+		// c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
+		// c.arg[1] = 2;
+		// c.arg[2] = 0;
+		// memcpy(c.d.asBytes, rats, 2);
+		// SendCommand(&c);
+		// WaitForResponse(CMD_ACK,&resp);
+	// }
 
 	c.cmd = CMD_MIFARE_CIDENT;
 	c.arg[0] = 0;
diff --git a/include/mifare.h b/include/mifare.h
index e2386cd5..bede67a9 100644
--- a/include/mifare.h
+++ b/include/mifare.h
@@ -34,7 +34,8 @@ typedef enum ISO14A_COMMAND {
 	ISO14A_APPEND_CRC =			(1 << 5),
 	ISO14A_SET_TIMEOUT =		(1 << 6),
 	ISO14A_NO_SELECT =			(1 << 7),
-	ISO14A_TOPAZMODE =			(1 << 8)
+	ISO14A_TOPAZMODE =			(1 << 8),
+	ISO14A_NO_RATS =			(1 << 9)
 } iso14a_command_t;
 
 typedef struct {