From 1a5a73abaeeac821208e676b003571ece7725212 Mon Sep 17 00:00:00 2001
From: marshmellow42 <marshmellowrf@gmail.com>
Date: Wed, 7 Oct 2015 00:24:55 -0400
Subject: [PATCH 1/1] Add mifare crypto trace decryption utility

allows manual decryption of hf 14a snoop traces of a mf card.
someday we should fix hf mf sniff...
---
 client/cmdhfmf.c    |  8 ++++++++
 client/mifarehost.c | 20 ++++++++++++++++++++
 client/mifarehost.h |  1 +
 client/util.c       | 21 +++++++++++++++++++++
 client/util.h       |  1 +
 5 files changed, 51 insertions(+)

diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c
index 16612cba..c4a0aeeb 100644
--- a/client/cmdhfmf.c
+++ b/client/cmdhfmf.c
@@ -1949,6 +1949,13 @@ int CmdHF14AMfSniff(const char *Cmd){
 	return 0;
 }
 
+//needs nt, ar, at, Data to decrypt
+int CmdDecryptTraceCmds(const char *Cmd){
+	uint8_t data[50];
+	int len = 0;
+	param_gethex_ex(Cmd,3,data,&len);
+	return tryDecryptWord(param_get32ex(Cmd,0,0,16),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),data,len/2);
+}
 
 static command_t CommandTable[] =
 {
@@ -1977,6 +1984,7 @@ static command_t CommandTable[] =
   {"cgetsc",	CmdHF14AMfCGetSc,		0, "Read sector - Magic Chinese card"},
   {"cload",		CmdHF14AMfCLoad,		0, "Load dump into magic Chinese card"},
   {"csave",		CmdHF14AMfCSave,		0, "Save dump from magic Chinese card into file or emulator"},
+  {"decrypt", CmdDecryptTraceCmds,1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"},
   {NULL, NULL, 0, NULL}
 };
 
diff --git a/client/mifarehost.c b/client/mifarehost.c
index eb145123..4abb1137 100644
--- a/client/mifarehost.c
+++ b/client/mifarehost.c
@@ -619,3 +619,23 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
 
 	return 0;
 }
+
+int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){
+	/*
+	uint32_t nt;      // tag challenge
+	uint32_t ar_enc;  // encrypted reader response
+	uint32_t at_enc;  // encrypted tag response
+	*/
+	if (traceCrypto1) {
+		crypto1_destroy(traceCrypto1);
+	}
+	ks2 = ar_enc ^ prng_successor(nt, 64);
+	ks3 = at_enc ^ prng_successor(nt, 96);
+	traceCrypto1 = lfsr_recovery64(ks2, ks3);
+
+	mf_crypto1_decrypt(traceCrypto1, data, len, 0);
+
+	PrintAndLog("Decrypted data: [%s]", sprint_hex(data,len) );
+	crypto1_destroy(traceCrypto1);
+	return 0;
+}
diff --git a/client/mifarehost.h b/client/mifarehost.h
index f6ffab3f..9ccb8960 100644
--- a/client/mifarehost.h
+++ b/client/mifarehost.h
@@ -67,3 +67,4 @@ int isBlockEmpty(int blockN);
 int isBlockTrailer(int blockN);
 int loadTraceCard(uint8_t *tuid);
 int saveTraceCard(void);
+int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len);
diff --git a/client/util.c b/client/util.c
index 9f2142c6..5e9fce85 100644
--- a/client/util.c
+++ b/client/util.c
@@ -333,7 +333,28 @@ int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
 
 	return 0;
 }
+int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt)
+{
+	int bg, en, temp, i;
+
+	//if (hexcnt % 2)
+	//	return 1;
+	
+	if (param_getptr(line, &bg, &en, paramnum)) return 1;
+
+	*hexcnt = en - bg + 1;
+	if (*hexcnt % 2) //error if not complete hex bytes
+		return 1;
 
+	for(i = 0; i < *hexcnt; i += 2) {
+		if (!(isxdigit(line[bg + i]) && isxdigit(line[bg + i + 1])) )	return 1;
+		
+		sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp);
+		data[i / 2] = temp & 0xff;
+	}	
+
+	return 0;
+}
 int param_getstr(const char *line, int paramnum, char * str)
 {
 	int bg, en;
diff --git a/client/util.h b/client/util.h
index 2d2beaf4..19c34604 100644
--- a/client/util.h
+++ b/client/util.h
@@ -54,6 +54,7 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base);
 uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination);
 uint8_t param_isdec(const char *line, int paramnum);
 int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt);
+int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt);
 int param_getstr(const char *line, int paramnum, char * str);
 
  int hextobinarray( char *target,  char *source);
-- 
2.39.5