X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/8dd0118673540f4f0ca39ae2332dcb3f4bc17c27..refs/pull/462/head:/client/mifarehost.c

diff --git a/client/mifarehost.c b/client/mifarehost.c
index ca5d97e1..67277b59 100644
--- a/client/mifarehost.c
+++ b/client/mifarehost.c
@@ -540,35 +540,10 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID) {
 	return 0;
 }
 
-int mfCIdentify()
-{
-  UsbCommand c;
-//	UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}};
-//	SendCommand(&c);
-
-  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);
-	// }
-
-	c.cmd = CMD_MIFARE_CIDENT;
-	c.arg[0] = 0;
-	c.arg[1] = 0;
-	c.arg[2] = 0;
+int mfCIdentify() {
+	UsbCommand c = {CMD_MIFARE_CIDENT, {0, 0, 0}};
 	SendCommand(&c);
+	UsbCommand resp;
 	WaitForResponse(CMD_ACK,&resp);
 
 	uint8_t isGeneration = resp.arg[0] & 0xff;
@@ -578,13 +553,6 @@ int mfCIdentify()
 		default: PrintAndLog("No chinese magic backdoor command detected"); break;
 	}
 
-	// disconnect
-//	c.cmd = CMD_READER_ISO_14443a;
-//	c.arg[0] = 0;
-//	c.arg[1] = 0;
-//	c.arg[2] = 0;
-//	SendCommand(&c);
-
 	return (int) isGeneration;
 }
 
@@ -935,3 +903,72 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data,
 	return 0;
 }
 
+/** validate_prng_nonce
+ * Determine if nonce is deterministic. ie: Suspectable to Darkside attack.
+ * returns
+ *   true = weak prng
+ *   false = hardend prng
+ */
+bool validate_prng_nonce(uint32_t nonce) {
+	uint16_t *dist = 0;
+	uint16_t x, i;
+
+	dist = malloc(2 << 16);
+	if(!dist)
+		return -1;
+
+	// init prng table:
+	for (x = i = 1; i; ++i) {
+		dist[(x & 0xff) << 8 | x >> 8] = i;
+		x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15;
+	}
+	
+	uint32_t res = (65535 - dist[nonce >> 16] + dist[nonce & 0xffff]) % 65535;
+	
+	free(dist);	
+	return (res == 16);
+}
+
+/* Detect Tag Prng, 
+* function performs a partial AUTH,  where it tries to authenticate against block0, key A, but only collects tag nonce.
+* the tag nonce is check to see if it has a predictable PRNG.
+* @returns 
+*	TRUE if tag uses WEAK prng (ie Now the NACK bug also needs to be present for Darkside attack)
+*   FALSE is tag uses HARDEND prng (ie hardnested attack possible, with known key)
+*/
+int DetectClassicPrng(void){
+
+	UsbCommand resp, respA;	
+	uint8_t cmd[] = {0x60, 0x00}; // MIFARE_AUTH_KEYA
+	uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS;
+	
+	UsbCommand c = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}};
+	memcpy(c.d.asBytes, cmd, sizeof(cmd));
+
+	clearCommandBuffer();
+	SendCommand(&c);
+	if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
+        PrintAndLog("PRNG UID: Reply timeout.");
+		return -1;
+	}
+	
+	// if select tag failed.
+	if (resp.arg[0] == 0) {
+		PrintAndLog("PRNG error: selecting tag failed, can't detect prng.");
+		return -1;
+	}
+	
+	if (!WaitForResponseTimeout(CMD_ACK, &respA, 5000)) {
+        PrintAndLog("PRNG data: Reply timeout.");
+		return -1;
+	}
+
+	// check respA
+	if (respA.arg[0] != 4) {
+		PrintAndLog("PRNG data error: Wrong length: %d", respA.arg[0]);
+		return -1;
+	}
+
+	uint32_t nonce = bytes_to_num(respA.d.asBytes, respA.arg[0]);
+	return validate_prng_nonce(nonce);
+}