From 905c55de2bbe642412b47ed4e92344096c817fac Mon Sep 17 00:00:00 2001
From: iceman1001 <iceman@iuse.se>
Date: Fri, 10 Mar 2017 09:48:36 +0100
Subject: [PATCH] ADD: `analyse nuid` - generates NUID 4byte from a UID 7byte. 
  Mifare Classic Ev1 has this option as a activation sequences.  This NUID is
 also used for authenticate (cuid),  not the block0 data. ref:
 http://www.gorferay.com/mifare-and-handling-of-uids/

---
 client/cmdanalyse.c  | 68 +++++++++++++++++++++++++++++++++++++++++---
 client/cmdanalyse.h  |  7 +++--
 common/iso14443crc.c |  2 +-
 common/iso14443crc.h |  1 +
 4 files changed, 71 insertions(+), 7 deletions(-)

diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c
index a8deb67f..a7004293 100644
--- a/client/cmdanalyse.c
+++ b/client/cmdanalyse.c
@@ -22,7 +22,7 @@ int usage_analyse_lcr(void) {
 	PrintAndLog("           <bytes>    bytes to calc missing XOR in a LCR");
 	PrintAndLog("");
 	PrintAndLog("Samples:");
-	PrintAndLog("           analyse lcr 04008064BA");
+	PrintAndLog("      analyse lcr 04008064BA");
 	PrintAndLog("expected output: Target (BA) requires final LRC XOR byte value: 5A");
 	return 0;
 }
@@ -38,7 +38,7 @@ int usage_analyse_checksum(void) {
 	PrintAndLog("           m <mask>   bit mask to limit the outpuyt");
 	PrintAndLog("");
 	PrintAndLog("Samples:");
-	PrintAndLog("           analyse chksum b 137AF00A0A0D m FF");
+	PrintAndLog("      analyse chksum b 137AF00A0A0D m FF");
 	PrintAndLog("expected output: 0x61");
 	return 0;
 }
@@ -51,7 +51,7 @@ int usage_analyse_crc(void){
 	PrintAndLog("           <bytes>    bytes to calc crc");
 	PrintAndLog("");
 	PrintAndLog("Samples:");
-	PrintAndLog("           analyse crc 137AF00A0A0D");
+	PrintAndLog("      analyse crc 137AF00A0A0D");
 	return 0;
 }
 int usage_analyse_hid(void){
@@ -65,7 +65,19 @@ int usage_analyse_hid(void){
 	PrintAndLog("           <bytes>    input bytes");
 	PrintAndLog("");
 	PrintAndLog("Samples:");
-	PrintAndLog("           analyse hid r 0123456789abcdef");
+	PrintAndLog("      analyse hid r 0123456789abcdef");
+	return 0;
+}
+int usage_analyse_nuid(void){
+	PrintAndLog("Generate 4byte NUID from 7byte UID");
+	PrintAndLog("");
+	PrintAndLog("Usage:  analyse hid [h] <bytes>");
+	PrintAndLog("Options:");
+	PrintAndLog("           h          This help");
+	PrintAndLog("           <bytes>  input bytes (14 hexsymbols)");
+	PrintAndLog("");
+	PrintAndLog("Samples:");
+	PrintAndLog("      analyse nuid 11223344556677");
 	return 0;
 }
 
@@ -521,6 +533,53 @@ int CmdAnalyseHid(const char *Cmd){
 	return 0;
 }
 
+void generate4bNUID(uint8_t *uid, uint8_t *nuid){
+	uint16_t crc;
+	uint8_t first, second;
+		
+	ComputeCrc14443(CRC_14443_A, uid, 3, &first, &second);
+	nuid[0] |= (second & 0xE0) | 0xF;
+	nuid[1] = first;
+	
+	crc = first;
+	crc |= second << 8;
+	
+	UpdateCrc14443(uid[3], &crc);
+	UpdateCrc14443(uid[4], &crc);
+	UpdateCrc14443(uid[5], &crc);
+	UpdateCrc14443(uid[6], &crc);
+		
+	nuid[2] = (crc >> 8) & 0xFF ;
+	nuid[3] = crc & 0xFF;
+}
+
+int CmdAnalyseNuid(const char *Cmd){
+	uint8_t nuid[4] = {0};	
+	uint8_t uid[7] = {0};
+	int len = 0;
+	char cmdp = param_getchar(Cmd, 0);
+	if (strlen(Cmd) == 0|| cmdp == 'h' || cmdp == 'H') return usage_analyse_nuid();
+
+	/* selftest  UID 040D681AB52281  -> NUID 8F430FEF */
+	if (cmdp == 't' || cmdp == 'T') {
+		memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7);
+		generate4bNUID(uid, nuid);
+		if ( 0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4))
+			printf("Selftest OK\n");
+		else
+			printf("Selftest Failed\n");
+		return 0;
+	}
+
+	param_gethex_ex(Cmd, 0, uid, &len);
+	if ( len%2  || len != 14) return usage_analyse_nuid();
+
+	generate4bNUID(uid, nuid);
+	
+	printf("UID  | %s \n", sprint_hex(uid, 7));
+	printf("NUID | %s \n", sprint_hex(nuid, 4));
+	return 0;
+}
 static command_t CommandTable[] = {
 	{"help",	CmdHelp,            1, "This help"},
 	{"lcr",		CmdAnalyseLCR,		1, "Generate final byte for XOR LRC"},
@@ -531,6 +590,7 @@ static command_t CommandTable[] = {
 	{"lfsr",	CmdAnalyseLfsr,		1,	"LFSR tests"},
 	{"a",		CmdAnalyseA,		1,	"num bits test"},
 	{"hid",		CmdAnalyseHid,		1,	"Permute function from 'heart of darkness' paper"},
+	{"nuid",	CmdAnalyseNuid,		1,	"create NUID from 7byte UID"},
 	{NULL, NULL, 0, NULL}
 };
 
diff --git a/client/cmdanalyse.h b/client/cmdanalyse.h
index 70e472cd..adef8ce1 100644
--- a/client/cmdanalyse.h
+++ b/client/cmdanalyse.h
@@ -18,15 +18,17 @@
 #include "ui.h"		// PrintAndLog
 #include "util.h"
 #include "crc.h"
-#include "../common/iso15693tools.h"
+#include "iso15693tools.h"	//
+#include "iso14443crc.h"	// crc 14a
 #include "tea.h"
-#include "../include/legic_prng.h"
+#include "legic_prng.h"
 #include "loclass/elite_crack.h"
 
 int usage_analyse_lcr(void);
 int usage_analyse_checksum(void);
 int usage_analyse_crc(void);
 int usage_analyse_hid(void);
+int usage_analyse_nuid(void);
 
 int CmdAnalyse(const char *Cmd);
 int CmdAnalyseLCR(const char *Cmd);
@@ -36,4 +38,5 @@ int CmdAnalyseCRC(const char *Cmd);
 int CmdAnalyseTEASelfTest(const char *Cmd);
 int CmdAnalyseLfsr(const char *Cmd);
 int CmdAnalyseHid(const char *Cmd);
+int CmdAnalyseNuid(const char *Cmd);
 #endif
diff --git a/common/iso14443crc.c b/common/iso14443crc.c
index a6def1a9..d07a2871 100644
--- a/common/iso14443crc.c
+++ b/common/iso14443crc.c
@@ -8,7 +8,7 @@
 
 #include "iso14443crc.h"
 
-static unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc)
+unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc)
 {
     ch = (ch ^ (unsigned char) ((*lpwCrc) & 0x00FF));
     ch = (ch ^ (ch << 4));
diff --git a/common/iso14443crc.h b/common/iso14443crc.h
index 4b1fb7e8..9373d951 100644
--- a/common/iso14443crc.h
+++ b/common/iso14443crc.h
@@ -18,6 +18,7 @@
 #define	CRC_14443_B	0xFFFF  /* ISO/IEC 13239 (formerly ISO/IEC 3309) */
 #define CRC_ICLASS	0xE012  /* ICLASS PREFIX */
 
+unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc);
 void ComputeCrc14443(int CrcType,
                      const unsigned char *Data, int Length,
                      unsigned char *TransmitFirst,
-- 
2.39.5