From b62a5a8444db6dcfad2b491f3283f43378c630cf Mon Sep 17 00:00:00 2001
From: "Merlokbr@gmail.com"
 <Merlokbr@gmail.com@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Date: Fri, 6 Jul 2012 16:19:05 +0000
Subject: [PATCH] small improvements, added new command `hf mf sniff` (there
 will be cool sniffer). But now... here is optimized hf 14a snoop. As I see it
 works the same as th old version.

---
 armsrc/Makefile      |   2 +-
 armsrc/appmain.c     |   5 ++
 armsrc/apps.h        |   1 +
 armsrc/iso14443a.c   | 187 ++++++++++++++++++++++++++++++-------------
 armsrc/iso14443a.h   |  54 +++++++++++++
 armsrc/mifarecmd.c   |   2 +-
 armsrc/mifaresniff.c |  15 ++++
 armsrc/mifaresniff.h |  26 ++++++
 armsrc/mifareutil.c  |   2 +-
 client/cmdhfmf.c     |  17 +++-
 client/mifarehost.c  |   2 +-
 include/usb_cmd.h    |   2 +
 12 files changed, 255 insertions(+), 60 deletions(-)
 create mode 100644 armsrc/mifaresniff.c
 create mode 100644 armsrc/mifaresniff.h

diff --git a/armsrc/Makefile b/armsrc/Makefile
index d4927225..249cf5a9 100644
--- a/armsrc/Makefile
+++ b/armsrc/Makefile
@@ -16,7 +16,7 @@ APP_CFLAGS	= -O2 -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DW
 #SRC_LCD = fonts.c LCD.c
 SRC_LF = lfops.c hitag2.c
 SRC_ISO15693 = iso15693.c iso15693tools.c 
-SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c
+SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
 SRC_ISO14443b = iso14443.c
 SRC_CRAPTO1 = crapto1.c crypto1.c
 
diff --git a/armsrc/appmain.c b/armsrc/appmain.c
index 3fdbed5c..25b3c51c 100644
--- a/armsrc/appmain.c
+++ b/armsrc/appmain.c
@@ -761,6 +761,11 @@ void UsbPacketReceived(uint8_t *packet, int len)
 		case CMD_MIFARE_EML_CGETBLOCK:
 			MifareCGetBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
 			break;
+			
+		// mifare sniffer
+		case CMD_MIFARE_SNIFFER:
+			SniffMifare();
+			break;
 #endif
 
 #ifdef WITH_ICLASS
diff --git a/armsrc/apps.h b/armsrc/apps.h
index 7ed2867d..05037421 100644
--- a/armsrc/apps.h
+++ b/armsrc/apps.h
@@ -135,6 +135,7 @@ uint32_t GetParity(const uint8_t * pbtCmd, int iLen);
 void iso14a_set_trigger(int enable);
 void iso14a_clear_tracelen(void);
 void iso14a_set_tracing(int enable);
+void RAMFUNC SniffMifare(void);
 
 // mifarecmd.h
 void ReaderMifare(uint32_t parameter);
diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c
index bae80b8e..a82c2899 100644
--- a/armsrc/iso14443a.c
+++ b/armsrc/iso14443a.c
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// Merlok - June 2011
+// Merlok - June 2011, 2012
 // Gerhard de Koning Gans - May 2008
 // Hagen Fritsch - June 2010
 //
@@ -129,32 +129,7 @@ int LogTrace(const uint8_t * btBytes, int iLen, int iSamples, uint32_t dwParity,
 // The software UART that receives commands from the reader, and its state
 // variables.
 //-----------------------------------------------------------------------------
-static struct {
-    enum {
-        STATE_UNSYNCD,
-        STATE_START_OF_COMMUNICATION,
-		STATE_MILLER_X,
-		STATE_MILLER_Y,
-		STATE_MILLER_Z,
-        STATE_ERROR_WAIT
-    }       state;
-    uint16_t    shiftReg;
-    int     bitCnt;
-    int     byteCnt;
-    int     byteCntMax;
-    int     posCnt;
-    int     syncBit;
-	int     parityBits;
-	int     samples;
-    int     highCnt;
-    int     bitBuffer;
-	enum {
-		DROP_NONE,
-		DROP_FIRST_HALF,
-		DROP_SECOND_HALF
-	}		drop;
-    uint8_t   *output;
-} Uart;
+static tUart Uart;
 
 static RAMFUNC int MillerDecoding(int bit)
 {
@@ -393,32 +368,7 @@ static RAMFUNC int MillerDecoding(int bit)
 //=============================================================================
 // ISO 14443 Type A - Manchester
 //=============================================================================
-
-static struct {
-    enum {
-        DEMOD_UNSYNCD,
-		DEMOD_START_OF_COMMUNICATION,
-		DEMOD_MANCHESTER_D,
-		DEMOD_MANCHESTER_E,
-		DEMOD_MANCHESTER_F,
-        DEMOD_ERROR_WAIT
-    }       state;
-    int     bitCount;
-    int     posCount;
-	int     syncBit;
-	int     parityBits;
-    uint16_t    shiftReg;
-	int     buffer;
-	int     buff;
-	int     samples;
-    int     len;
-	enum {
-		SUB_NONE,
-		SUB_FIRST_HALF,
-		SUB_SECOND_HALF
-	}		sub;
-    uint8_t   *output;
-} Demod;
+static tDemod Demod;
 
 static RAMFUNC int ManchesterDecoding(int v)
 {
@@ -2402,9 +2352,7 @@ lbWORK:	if (len == 0) break;
 				cardSTATE = MFEMUL_WORK;
 				break;
 			}
-		
 		}
-	
 	}
 
 	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
@@ -2416,3 +2364,132 @@ lbWORK:	if (len == 0) break;
 
 	if (MF_DBGLEVEL >= 1)	Dbprintf("Emulator stopped. Tracing: %d  trace length: %d ",	tracing, traceLen);
 }
+
+//-----------------------------------------------------------------------------
+// MIFARE sniffer. 
+// 
+//-----------------------------------------------------------------------------
+void RAMFUNC SniffMifare(void) {
+	LEDsoff();
+	// init trace buffer
+	traceLen = 0;
+	memset(trace, 0x44, TRACE_SIZE);
+
+	// We won't start recording the frames that we acquire until we trigger;
+	// a good trigger condition to get started is probably when we see a
+	// response from the tag.
+	int triggered = FALSE; // FALSE to wait first for card
+
+	// The command (reader -> tag) that we're receiving.
+	// The length of a received command will in most cases be no more than 18 bytes.
+	// So 32 should be enough!
+	uint8_t *receivedCmd = (((uint8_t *)BigBuf) + RECV_CMD_OFFSET);
+	// The response (tag -> reader) that we're receiving.
+	uint8_t *receivedResponse = (((uint8_t *)BigBuf) + RECV_RES_OFFSET);
+
+	// As we receive stuff, we copy it from receivedCmd or receivedResponse
+	// into trace, along with its length and other annotations.
+	//uint8_t *trace = (uint8_t *)BigBuf;
+	
+	// The DMA buffer, used to stream samples from the FPGA
+	int8_t *dmaBuf = ((int8_t *)BigBuf) + DMA_BUFFER_OFFSET;
+	int lastRxCounter;
+	int8_t *upTo;
+	int smpl;
+	int maxBehindBy = 0;
+
+	// Set up the demodulator for tag -> reader responses.
+	Demod.output = receivedResponse;
+	Demod.len = 0;
+	Demod.state = DEMOD_UNSYNCD;
+
+	// Set up the demodulator for the reader -> tag commands
+	memset(&Uart, 0, sizeof(Uart));
+	Uart.output = receivedCmd;
+	Uart.byteCntMax = 32; // was 100 (greg)//////////////////
+	Uart.state = STATE_UNSYNCD;
+
+	// Setup for the DMA.
+	FpgaSetupSsc();
+	upTo = dmaBuf;
+	lastRxCounter = DMA_BUFFER_SIZE;
+	FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE);
+
+	// And put the FPGA in the appropriate mode
+	// Signal field is off with the appropriate LED
+	LED_D_OFF();
+	FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER);
+	SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+
+	// Count of samples received so far, so that we can include timing
+	// information in the trace buffer.
+	rsamples = 0;
+	// And now we loop, receiving samples.
+	while(true) {
+		LED_A_ON();
+		WDT_HIT();
+		int behindBy = (lastRxCounter - AT91C_BASE_PDC_SSC->PDC_RCR) &
+									(DMA_BUFFER_SIZE-1);
+		if(behindBy > maxBehindBy) {
+			maxBehindBy = behindBy;
+			if(behindBy > 400) {
+				Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
+				goto done;
+			}
+		}
+		if(behindBy < 1) continue;
+
+		LED_A_OFF();
+		
+		smpl = upTo[0];
+		upTo++;
+		lastRxCounter -= 1;
+		if(upTo - dmaBuf > DMA_BUFFER_SIZE) {
+			upTo -= DMA_BUFFER_SIZE;
+			lastRxCounter += DMA_BUFFER_SIZE;
+			AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
+			AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
+		}
+		
+		rsamples += 4;
+		if(MillerDecoding((smpl & 0xF0) >> 4)) {
+			LED_C_ON();
+			if(triggered) {
+				if (!LogTrace(receivedCmd, Uart.byteCnt, -1 * Uart.samples, Uart.parityBits, TRUE)) break;
+			}
+			/* And ready to receive another command. */
+			Uart.state = STATE_UNSYNCD;
+			/* And also reset the demod code, which might have been */
+			/* false-triggered by the commands from the reader. */
+			Demod.state = DEMOD_UNSYNCD;
+			LED_B_OFF();
+		}
+
+		if(ManchesterDecoding(smpl & 0x0F)) {
+			LED_B_ON();
+
+			if (!LogTrace(receivedResponse, Demod.len, -1 * Demod.samples, Demod.parityBits, FALSE)) break;
+
+			triggered = TRUE;
+
+			// And ready to receive another response.
+			memset(&Demod, 0, sizeof(Demod));
+			Demod.output = receivedResponse;
+			Demod.state = DEMOD_UNSYNCD;
+			LED_C_OFF();
+		}
+
+		if(BUTTON_PRESS()) {
+			DbpString("button cancelled");
+			goto done;
+		}
+	} // main cycle
+
+	DbpString("COMMAND FINISHED");
+
+done:
+	AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+	Dbprintf("maxBehindBy=%x, Uart.state=%x, Uart.byteCnt=%x", maxBehindBy, Uart.state, Uart.byteCnt);
+	Dbprintf("Uart.byteCntMax=%x, traceLen=%x, Uart.output[0]=%x", Uart.byteCntMax, traceLen, (int)Uart.output[0]);
+	LEDsoff();
+}
\ No newline at end of file
diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h
index 28184bb9..40c87ae9 100644
--- a/armsrc/iso14443a.h
+++ b/armsrc/iso14443a.h
@@ -23,6 +23,60 @@
 
 typedef struct nestedVector { uint32_t nt, ks1; } nestedVector;
 
+typedef struct {
+	enum {
+		DEMOD_UNSYNCD,
+		DEMOD_START_OF_COMMUNICATION,
+		DEMOD_MANCHESTER_D,
+		DEMOD_MANCHESTER_E,
+		DEMOD_MANCHESTER_F,
+		DEMOD_ERROR_WAIT
+	}       state;
+	int     bitCount;
+	int     posCount;
+	int     syncBit;
+	int     parityBits;
+	uint16_t    shiftReg;
+	int     buffer;
+	int     buff;
+	int     samples;
+	int     len;
+	enum {
+		SUB_NONE,
+		SUB_FIRST_HALF,
+		SUB_SECOND_HALF
+	}		sub;
+	uint8_t   *output;
+} tDemod;
+
+typedef struct {
+	enum {
+		STATE_UNSYNCD,
+		STATE_START_OF_COMMUNICATION,
+		STATE_MILLER_X,
+		STATE_MILLER_Y,
+		STATE_MILLER_Z,
+		STATE_ERROR_WAIT
+		}		state;
+		uint16_t    shiftReg;
+		int	bitCnt;
+		int	byteCnt;
+		int	byteCntMax;
+		int	posCnt;
+		int	syncBit;
+		int	parityBits;
+		int	samples;
+		int	highCnt;
+		int	bitBuffer;
+	enum {
+		DROP_NONE,
+		DROP_FIRST_HALF,
+		DROP_SECOND_HALF
+	}		drop;
+    uint8_t   *output;
+} tUart;
+
+
 extern byte_t oddparity (const byte_t bt);
 extern uint32_t GetParity(const uint8_t * pbtCmd, int iLen);
 extern void AppendCrc14443a(uint8_t* data, int len);
diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c
index d63b58e9..daecf541 100644
--- a/armsrc/mifarecmd.c
+++ b/armsrc/mifarecmd.c
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// Merlok - June 2011
+// Merlok - June 2011, 2012
 // Gerhard de Koning Gans - May 2008
 // Hagen Fritsch - June 2010
 //
diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c
new file mode 100644
index 00000000..25c7780d
--- /dev/null
+++ b/armsrc/mifaresniff.c
@@ -0,0 +1,15 @@
+//-----------------------------------------------------------------------------
+// Merlok - 2012
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Routines to support mifare classic sniffer.
+//-----------------------------------------------------------------------------
+
+#include "mifaresniff.h"
+#include "apps.h"
+
+
+
diff --git a/armsrc/mifaresniff.h b/armsrc/mifaresniff.h
new file mode 100644
index 00000000..21692aec
--- /dev/null
+++ b/armsrc/mifaresniff.h
@@ -0,0 +1,26 @@
+//-----------------------------------------------------------------------------
+// Merlok - June 2012
+//
+// This code is licensed to you under the terms of the GNU GPL, version 2 or,
+// at your option, any later version. See the LICENSE.txt file for the text of
+// the license.
+//-----------------------------------------------------------------------------
+// Routines to support mifare classic sniffer.
+//-----------------------------------------------------------------------------
+
+#ifndef __MIFARESNIFF_H
+#define __MIFARESNIFF_H
+
+#include "proxmark3.h"
+#include "apps.h"
+#include "util.h"
+#include "string.h"
+
+#include "iso14443crc.h"
+#include "iso14443a.h"
+#include "crapto1.h"
+#include "mifareutil.h"
+#include "common.h"
+
+
+#endif
\ No newline at end of file
diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c
index c20a387a..085531f4 100644
--- a/armsrc/mifareutil.c
+++ b/armsrc/mifareutil.c
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// Merlok, May 2011
+// Merlok, May 2011, 2012
 // Many authors, whom made it possible
 //
 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c
index b4450d54..8dc59f49 100644
--- a/client/cmdhfmf.c
+++ b/client/cmdhfmf.c
@@ -1,5 +1,5 @@
 //-----------------------------------------------------------------------------
-// Copyright (C) 2011 Merlok
+// Copyright (C) 2011,2012 Merlok
 //
 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
 // at your option, any later version. See the LICENSE.txt file for the text of
@@ -1542,6 +1542,20 @@ int CmdHF14AMfCSave(const char *Cmd) {
 	}
 }
 
+int CmdHF14AMfSniff(const char *Cmd){
+	
+	if (param_getchar(Cmd, 0) == 'h') {
+		PrintAndLog("Usage:  hf mf sniff ");
+		PrintAndLog("        sample: hf mf sniff ");
+		return 0;
+	}	
+	
+  UsbCommand c = {CMD_MIFARE_SNIFFER, {0, 0, 0}};
+  SendCommand(&c);
+
+  return 0;
+}
+
 static command_t CommandTable[] =
 {
   {"help",		CmdHelp,						1, "This help"},
@@ -1554,6 +1568,7 @@ static command_t CommandTable[] =
   {"chk",			CmdHF14AMfChk,			0, "Test block keys"},
   {"mifare",	CmdHF14AMifare,			0, "Read parity error messages. param - <used card nonce>"},
   {"nested",	CmdHF14AMfNested,		0, "Test nested authentication"},
+  {"sniff",		CmdHF14AMfSniff,		0, "Sniff card-reader communication"},
   {"sim",			CmdHF14AMf1kSim,		0, "Simulate MIFARE card"},
   {"eclr",		CmdHF14AMfEClear,		0, "Clear simulator memory block"},
   {"eget",		CmdHF14AMfEGet,			0, "Get simulator memory block"},
diff --git a/client/mifarehost.c b/client/mifarehost.c
index 11859e02..fb6a4bdb 100644
--- a/client/mifarehost.c
+++ b/client/mifarehost.c
@@ -1,4 +1,4 @@
-// Merlok, 2011
+// Merlok, 2011, 2012
 // people from mifare@nethemba.com, 2010
 //
 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
diff --git a/include/usb_cmd.h b/include/usb_cmd.h
index 4cd6da74..2969ed4e 100644
--- a/include/usb_cmd.h
+++ b/include/usb_cmd.h
@@ -127,6 +127,8 @@ typedef struct {
 #define CMD_MIFARE_WRITEBL							0x0622
 #define CMD_MIFARE_CHKKEYS							0x0623
 
+#define CMD_MIFARE_SNIFFER							0x0630
+
 #define CMD_UNKNOWN											0xFFFF
 
 // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions:
-- 
2.39.5