X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/874572d4197e2a02152ea8c2185df90531b576c3..f3ffd5a24f6e4488505ff1c98bc6512dff5a69ed:/client/cmdhficlass.c?ds=inline

diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c
index 60713a01..d42f7eef 100644
--- a/client/cmdhficlass.c
+++ b/client/cmdhficlass.c
@@ -14,6 +14,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <sys/stat.h>
+#include <ctype.h>
 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
 #include "data.h"
 #include "proxmark3.h"
@@ -32,6 +33,7 @@
 #include "protocols.h"
 #include "usb_cmd.h"
 #include "cmdhfmfu.h"
+#include "util_posix.h"
 
 static int CmdHelp(const char *Cmd);
 
@@ -51,6 +53,20 @@ typedef struct iclass_block {
     uint8_t d[8];
 } iclass_block_t;
 
+int usage_hf_iclass_chk(void) {
+	PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");	
+	PrintAndLog("Usage: hf iclass chk [h|e|r] <f  (*.dic)>");
+	PrintAndLog("Options:");
+	PrintAndLog("h             Show this help");
+	PrintAndLog("f <filename>  Dictionary file with default iclass keys");
+	PrintAndLog("      e             target Elite / High security key scheme");
+	PrintAndLog("      r             interpret dictionary file as raw (diversified keys)");
+	PrintAndLog("Samples:");
+	PrintAndLog("		 hf iclass chk f default_iclass_keys.dic");	
+	PrintAndLog("		 hf iclass chk f default_iclass_keys.dic e");	
+	return 0;
+}
+
 int xorbits_8(uint8_t val) {
 	uint8_t res = val ^ (val >> 1); //1st pass
 	res = res ^ (res >> 1); 		// 2nd pass
@@ -531,7 +547,7 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
 		memcpy(div_key, KEY, 8);
 	else
 		HFiClassCalcDivKey(CSN, KEY, div_key, elite);
-	PrintAndLog("Authing with %s: %02x%02x%02x%02x%02x%02x%02x%02x", rawkey ? "raw key" : "diversified key", div_key[0],div_key[1],div_key[2],div_key[3],div_key[4],div_key[5],div_key[6],div_key[7]);
+	 if (verbose) PrintAndLog("Authing with %s: %02x%02x%02x%02x%02x%02x%02x%02x", rawkey ? "raw key" : "diversified key", div_key[0],div_key[1],div_key[2],div_key[3],div_key[4],div_key[5],div_key[6],div_key[7]);
 
 	doMAC(CCNR, div_key, MAC);
 	UsbCommand resp;
@@ -541,12 +557,12 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
 	SendCommand(&d);
 	if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
 	{
-		PrintAndLog("Auth Command execute timeout");
+		if (verbose) PrintAndLog("Auth Command execute timeout");
 		return false;
 	}
 	uint8_t isOK = resp.arg[0] & 0xff;
 	if (!isOK) {
-		PrintAndLog("Authentication error");
+		if (verbose) PrintAndLog("Authentication error");
 		return false;
 	}
 	return true;
@@ -1699,10 +1715,152 @@ int CmdHFiClassManageKeys(const char *Cmd) {
 	return 0;
 }
 
+int CmdHFiClassCheckKeys(const char *Cmd) {
+
+	uint8_t mac[4] = {0x00,0x00,0x00,0x00};
+	uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+	uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+	// elite key,  raw key, standard key
+	bool use_elite = false;
+	bool use_raw = false;	
+	bool found_debit = false;
+	bool found_credit = false;	
+	bool errors = false;
+	uint8_t cmdp = 0x00;
+	FILE * f;
+	char filename[FILE_PATH_SIZE] = {0};
+	uint8_t fileNameLen = 0;
+	char buf[17];
+	uint8_t *keyBlock = NULL, *p;
+	int keyitems = 0, keycnt = 0;
+
+	while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
+		switch (param_getchar(Cmd, cmdp)) {
+		case 'h':
+		case 'H':
+			return usage_hf_iclass_chk();
+		case 'f':
+		case 'F':
+			fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); 
+			if (fileNameLen < 1) {
+				PrintAndLog("No filename found after f");
+				errors = true;
+			}
+			cmdp += 2;
+			break;
+		case 'e':
+		case 'E':
+			use_elite = true;
+			cmdp++;
+			break;
+		case 'r':
+		case 'R':
+			use_raw = true;
+			cmdp++;
+			break;
+		default:
+			PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
+			errors = true;
+			break;
+		}
+	}
+	if (errors) return usage_hf_iclass_chk();	
+			
+	if ( !(f = fopen( filename , "r")) ) {
+		PrintAndLog("File: %s: not found or locked.", filename);
+		return 1;
+	}
+
+	while( fgets(buf, sizeof(buf), f) ){
+		if (strlen(buf) < 16 || buf[15] == '\n')
+			continue;
+	
+		while (fgetc(f) != '\n' && !feof(f)) ;  //goto next line
+		
+		if( buf[0]=='#' ) continue;	//The line start with # is comment, skip
+
+		if (!isxdigit(buf[0])){
+			PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf);
+			continue;
+		}
+		
+		buf[16] = 0;
+
+		p = realloc(keyBlock, 8 * (keyitems += 64));
+		if (!p) {
+			PrintAndLog("Cannot allocate memory for default keys");
+			free(keyBlock);
+			fclose(f);
+			return 2;
+		}
+		keyBlock = p;
+
+		memset(keyBlock + 8 * keycnt, 0, 8);
+		num_to_bytes(strtoull(buf, NULL, 16), 8, keyBlock + 8 * keycnt);
+
+		//PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
+		keycnt++;
+		memset(buf, 0, sizeof(buf));
+	}
+	fclose(f);
+	PrintAndLog("Loaded %2d keys from %s", keycnt, filename);
+	
+	// time
+	uint64_t t1 = msclock();
+				
+	for (uint32_t c = 0; c < keycnt; c += 1) {
+			printf("."); fflush(stdout);			
+			if (ukbhit()) {
+				int gc = getchar(); (void)gc;
+				printf("\naborted via keyboard!\n");
+				break;
+			}
+			
+			memcpy(key, keyBlock + 8 * c , 8); 
+
+			// debit key. try twice
+			for (int foo = 0; foo < 2 && !found_debit; foo++) {
+				if (!select_and_auth(key, mac, div_key, false, use_elite, use_raw, false))
+					continue;
+
+				// key found.
+				PrintAndLog("\n--------------------------------------------------------");
+			PrintAndLog("   Found AA1 debit key\t\t[%s]", sprint_hex(key, 8));
+				found_debit = true;
+			}
+			
+			// credit key. try twice
+			for (int foo = 0; foo < 2 && !found_credit; foo++) {
+				if (!select_and_auth(key, mac, div_key, true, use_elite, use_raw, false))
+					continue;
+				
+				// key found
+				PrintAndLog("\n--------------------------------------------------------");
+				PrintAndLog("   Found AA2 credit key\t\t[%s]", sprint_hex(key, 8));
+				found_credit = true;
+			}
+			
+			// both keys found.
+			if ( found_debit && found_credit )
+				break;
+	}
+
+	t1 = msclock() - t1;
+
+	PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1/1000.0);
+	
+	DropField();
+	free(keyBlock);
+	PrintAndLog("");
+	return 0;
+}
+
 static command_t CommandTable[] = 
 {
 	{"help",        CmdHelp,                    	1,	"This help"},
 	{"calcnewkey",  CmdHFiClassCalcNewKey,      	1,	"[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
+	{"chk",         CmdHFiClassCheckKeys,        	0,	"            Check keys"},	
 	{"clone",       CmdHFiClassCloneTag,        	0,	"[options..] Authenticate and Clone from iClass bin file"},
 	{"decrypt",     CmdHFiClassDecrypt,         	1,	"[f <fname>] Decrypt tagdump" },
 	{"dump",        CmdHFiClassReader_Dump,     	0,	"[options..] Authenticate and Dump iClass tag's AA1"},
@@ -1723,6 +1881,7 @@ static command_t CommandTable[] =
 
 int CmdHFiClass(const char *Cmd)
 {
+	clearCommandBuffer();	
 	CmdsParse(CommandTable, Cmd);
 	return 0;
 }