From 59f726c989e93a7a29fd23a442bd173839bfc845 Mon Sep 17 00:00:00 2001
From: marshmellow42 <marshmellowrf@gmail.com>
Date: Wed, 15 Feb 2017 23:27:15 -0500
Subject: [PATCH] EM4x05/EM4x69 continued  + a couple of icemans utils.

---
 client/cmdlfem4x.c | 73 ++++++++++++++++++++++++++++++++------------
 client/util.c      | 76 ++++++++++++++++++++++++++++++++++++++++++++--
 client/util.h      |  6 +++-
 common/lfdemod.c   |  3 ++
 4 files changed, 134 insertions(+), 24 deletions(-)

diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c
index 820b24e9..7d8d2931 100644
--- a/client/cmdlfem4x.c
+++ b/client/cmdlfem4x.c
@@ -533,6 +533,9 @@ uint8_t EMpreambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, siz
 	return 0;
 }
 
+// FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE 
+// should cover 90% of known used configs
+// the rest will need to be manually demoded for now...
 int demodEM4x05resp(uint8_t bitsNeeded) {
 	int ans = 0;
 	bool demodFound = false;
@@ -546,7 +549,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) {
 		ans = FSKrawDemod("0 0", false);
 		if (!ans) {
 			if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: FSK Demod failed");
-			//return -1;
 		} else {
 			// set size to 10 to only test first 4 positions for the preamble
 			size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10;
@@ -557,7 +559,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) {
 			uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx);
 			if ( errChk == 0) {
 				if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
-				//return -1;
 			} else {
 				//can't test size because the preamble doesn't repeat :(
 				//meaning chances of false positives are high.
@@ -565,10 +566,37 @@ int demodEM4x05resp(uint8_t bitsNeeded) {
 			}
 		}
 	}
+	// PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... )
+	if (!demodFound) {
+		ans = GetPskClock("", FALSE, FALSE);
+		if (ans>0) {
+			PrintAndLog("PSK response possibly found, run `data rawd p1` to attempt to demod");
+		}
+	}
 
-	ans = GetPskClock("", FALSE, FALSE);
-	if (ans>0) {
-		PrintAndLog("PSK response possibly found, run `data rawd p1` to attempt to demod");
+	// more common than biphase
+	if (!demodFound) {
+		DemodBufferLen = 0x00;
+		// try manchester - NOTE: ST only applies to T55x7 tags.
+		ans = ASKDemod_ext("0,0,1", false, false, 1, false);
+		if (!ans) {
+			if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed");
+		} else {
+			// set size to 10 to only test first 4 positions for the preamble
+			size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10;
+			size_t startIdx = 0; 
+
+			if (g_debugMode) PrintAndLog("ANS: %d | %u | %u", ans, startIdx, size);
+
+			uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx);
+			if ( errChk == 0) {
+				if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
+			} else {
+				//can't test size because the preamble doesn't repeat :(
+				//meaning chances of false positives are high.
+				demodFound = true;
+			}
+		}
 	}
 
 	if (!demodFound) {
@@ -577,7 +605,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) {
 		ans = ASKbiphaseDemod("0 0 1", FALSE);
 		if (!ans) { 
 			if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed");
-			//return -1;
 		} else {
 			// set size to 10 to only test first 4 positions for the preamble
 			size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10;
@@ -588,7 +615,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) {
 			uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx);
 			if ( errChk == 0) {
 				if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
-				//return -1;
 			} else {
 				//can't test size because the preamble doesn't repeat :(
 				//meaning chances of false positives are high.
@@ -599,11 +625,10 @@ int demodEM4x05resp(uint8_t bitsNeeded) {
 
 	if (!demodFound) {
 		DemodBufferLen = 0x00;
-		// try manchester - NOTE: ST only applies to T55x7 tags.
-		ans = ASKDemod_ext("0,0,1", false, false, 1, false);
-		if (!ans) {
-			if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/Manchester Demod failed");
-			//return -1;
+		//try diphase (differential biphase or inverted)
+		ans = ASKbiphaseDemod("0 1 1", FALSE);
+		if (!ans) { 
+			if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305: ASK/biphase Demod failed");
 		} else {
 			// set size to 10 to only test first 4 positions for the preamble
 			size_t size = (10 > DemodBufferLen) ? DemodBufferLen : 10;
@@ -614,7 +639,6 @@ int demodEM4x05resp(uint8_t bitsNeeded) {
 			uint8_t errChk = !EMpreambleSearch(DemodBuffer, preamble, sizeof(preamble), size, &startIdx);
 			if ( errChk == 0) {
 				if (g_debugMode) PrintAndLog("DEBUG: Error - EM4305 preamble not found :: %d", startIdx);
-				//return -1;
 			} else {
 				//can't test size because the preamble doesn't repeat :(
 				//meaning chances of false positives are high.
@@ -624,8 +648,10 @@ int demodEM4x05resp(uint8_t bitsNeeded) {
 	}
 
 	if (demodFound && bitsNeeded < DemodBufferLen) {
-		setDemodBuf(DemodBuffer + ans + sizeof(preamble), bitsNeeded, 0);
-		CmdPrintDemodBuff("x");
+		if (bitsNeeded > 0) {
+			setDemodBuf(DemodBuffer + ans + sizeof(preamble), bitsNeeded, 0);
+			CmdPrintDemodBuff("x");			
+		}
 		return 1;
 	}
 	return -1;
@@ -673,10 +699,9 @@ int CmdReadWord(const char *Cmd) {
 		return -1;
 	}
 
-	//need 32 bits for read word
-	demodEM4x05resp(32);
-
-	return 1;
+	//attempt demod:
+	//need 32 bits from a read word
+	return demodEM4x05resp(32);
 }
 
 int usage_lf_em_write(void) {
@@ -693,6 +718,7 @@ int usage_lf_em_write(void) {
 	PrintAndLog("      lf em writeword 1 deadc0de 11223344");
 	return 0;
 }
+
 int CmdWriteWord(const char *Cmd) {
 	uint8_t ctmp = param_getchar(Cmd, 0);
 	if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em_write();
@@ -738,7 +764,14 @@ int CmdWriteWord(const char *Cmd) {
 	}
 	setGraphBuf(got, sizeof(got));
 	//todo: check response for 00001010 then write data for write confirmation!
-	return 0;
+	
+	//attempt demod:
+	//need 0 bits demoded (after preamble) to verify write cmd
+	int result = demodEM4x05resp(0);
+	if (result == 1) {
+		PrintAndLog("Write Verified");
+	}
+	return result;
 }
 
 /*
diff --git a/client/util.c b/client/util.c
index e4add6c0..374ae397 100644
--- a/client/util.c
+++ b/client/util.c
@@ -110,6 +110,23 @@ void print_hex(const uint8_t * data, const size_t len)
 	printf("\n");
 }
 
+void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) {
+
+	int rownum = 0;
+	printf("[%02d] | ", rownum);
+	for (int i = 0; i < len; ++i) {
+
+		printf("%02X ", data[i]);
+		
+		// check if a line break is needed
+		if ( breaks > 0 && !((i+1) % breaks) && (i+1 < len) ) {
+			++rownum;
+			printf("\n[%02d] | ", rownum);
+		}
+	}
+	printf("\n");
+}
+
 char *sprint_hex(const uint8_t *data, const size_t len) {
 	
 	int maxLen = ( len > 1024/3) ? 1024/3 : len;
@@ -139,7 +156,7 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea
 
 	size_t in_index = 0;
 	// loop through the out_index to make sure we don't go too far
-	for (size_t out_index=0; out_index < max_len; out_index++) {
+	for (size_t out_index=0; out_index < max_len-1; out_index++) {
 		// set character - (should be binary but verify it isn't more than 1 digit)
 		if (data[in_index]<10)
 			sprintf(tmp++, "%u", (unsigned int) data[in_index]);
@@ -158,6 +175,41 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea
 char *sprint_bin(const uint8_t *data, const size_t len) {
 	return sprint_bin_break(data, len, 0);
 }
+
+char *sprint_hex_ascii(const uint8_t *data, const size_t len) {
+	static char buf[1024];
+	char *tmp = buf;
+	memset(buf, 0x00, 1024);
+	size_t max_len = (len > 1010) ? 1010 : len;
+
+	sprintf(tmp, "%s| ", sprint_hex(data, max_len) );
+	
+	size_t i = 0;
+	size_t pos = (max_len * 3)+2;
+	while(i < max_len){
+		char c = data[i];
+		if ( (c < 32) || (c == 127))
+			c = '.';
+		sprintf(tmp+pos+i, "%c",  c);
+		++i;
+	}
+	return buf;
+}
+
+char *sprint_ascii(const uint8_t *data, const size_t len) {
+	static char buf[1024];
+	char *tmp = buf;
+	memset(buf, 0x00, 1024);
+	size_t max_len = (len > 1010) ? 1010 : len;
+	size_t i = 0;
+	while(i < max_len){
+		char c = data[i];
+		tmp[i] = ((c < 32) || (c == 127)) ? '.' : c;
+		++i;
+	}
+	return buf;
+}
+
 void num_to_bytes(uint64_t n, size_t len, uint8_t* dest)
 {
 	while (len--) {
@@ -184,6 +236,15 @@ void num_to_bytebits(uint64_t	n, size_t len, uint8_t *dest) {
 	}
 }
 
+//least significant bit first
+void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest) {
+	for(int i = 0 ; i < len ; ++i) {
+		dest[i] =  n & 1;
+		n >>= 1;
+	}
+}
+
+
 // aa,bb,cc,dd,ee,ff,gg,hh, ii,jj,kk,ll,mm,nn,oo,pp
 // to
 // hh,gg,ff,ee,dd,cc,bb,aa, pp,oo,nn,mm,ll,kk,jj,ii
@@ -200,6 +261,16 @@ uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockS
 	return tmp;
 }
 
+// takes a uint8_t src array, for len items and reverses the byte order in blocksizes (8,16,32,64), 
+// returns: the dest array contains the reordered src array.
+void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest){
+	for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){
+		for (size_t i = 0; i < blockSize; i++){
+			dest[i+(blockSize*block)] = src[(blockSize-1-i)+(blockSize*block)];
+		}
+	}
+}
+
 //assumes little endian
 char * printBits(size_t const size, void const * const ptr)
 {
@@ -332,8 +403,6 @@ uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base)
 		return strtoull(&line[bg], NULL, base);
 	else
 		return deflt;
-
-	return 0;
 }
 
 int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt)
@@ -490,6 +559,7 @@ void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length)
     *(target)= GetParity(source + length / 2, ODD, length / 2);
 }
 
+// xor two arrays together for len items.  The dst array contains the new xored values.
 void xor(unsigned char *dst, unsigned char *src, size_t len) {
    for( ; len > 0; len--,dst++,src++)
        *dst ^= *src;
diff --git a/client/util.h b/client/util.h
index 1b6b2fb1..8c0ed950 100644
--- a/client/util.h
+++ b/client/util.h
@@ -13,7 +13,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <ctype.h>
-#include <time.h>
+#include <time.h>    //time, gmtime
 #include "data.h"    //for FILE_PATH_SIZE
 
 #ifndef ROTR
@@ -42,12 +42,16 @@ void print_hex(const uint8_t * data, const size_t len);
 char * sprint_hex(const uint8_t * data, const size_t len);
 char * sprint_bin(const uint8_t * data, const size_t len);
 char * sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks);
+char * sprint_hex_ascii(const uint8_t *data, const size_t len);
+char * sprint_ascii(const uint8_t *data, const size_t len);
 
 void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
 uint64_t bytes_to_num(uint8_t* src, size_t len);
 void num_to_bytebits(uint64_t	n, size_t len, uint8_t *dest);
+void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest);
 char * printBits(size_t const size, void const * const ptr);
 uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize);
+void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest);
 
 char param_getchar(const char *line, int paramnum);
 int param_getptr(const char *line, int *bg, int *en, int paramnum);
diff --git a/common/lfdemod.c b/common/lfdemod.c
index 8324c440..6c09c9ee 100644
--- a/common/lfdemod.c
+++ b/common/lfdemod.c
@@ -148,6 +148,9 @@ uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits)
 //search for given preamble in given BitStream and return success=1 or fail=0 and startIndex and length
 uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx)
 {
+	// Sanity check.  If preamble length is bigger than bitstream length.
+	if ( *size <= pLen ) return 0;
+
 	uint8_t foundCnt=0;
 	for (int idx=0; idx < *size - pLen; idx++){
 		if (memcmp(BitStream+idx, preamble, pLen) == 0){
-- 
2.39.5