From: roel@libnfc.org <roel@libnfc.org@ef4ab9da-24cd-11de-8aaa-f3a34680c41f>
Date: Wed, 30 Dec 2009 00:11:50 +0000 (+0000)
Subject: mifare firmware update
X-Git-Tag: v1.0.0~421
X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/32cfae439e0e2270638617fa09bf1026b0cf0e50?ds=sidebyside

mifare firmware update
---

diff --git a/armsrc/appmain.c b/armsrc/appmain.c
index 9026f721..11047b1c 100644
--- a/armsrc/appmain.c
+++ b/armsrc/appmain.c
@@ -593,6 +593,12 @@ void UsbPacketReceived(BYTE *packet, int len)
 			break;
 #endif
 
+#ifdef WITH_ISO14443a
+		case CMD_READER_MIFARE:
+			ReaderMifare(c->arg[0]);
+			break;
+#endif
+      
 #ifdef WITH_ISO14443b
 		case CMD_SNOOP_ISO_14443:
 			SnoopIso14443();
diff --git a/armsrc/apps.h b/armsrc/apps.h
index d90d595a..95080eae 100644
--- a/armsrc/apps.h
+++ b/armsrc/apps.h
@@ -7,6 +7,10 @@
 #ifndef __APPS_H
 #define __APPS_H
 
+#include "stdint.h"
+#include "stddef.h"
+typedef unsigned char byte_t;
+
 // The large multi-purpose buffer, typically used to hold A/D samples,
 // maybe processed in some way.
 DWORD BigBuf[12000];
@@ -82,14 +86,15 @@ void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
 void SimulateIso14443Tag(void);
 void AcquireRawAdcSamplesIso14443(DWORD parameter);
 void ReadSRI512Iso14443(DWORD parameter);
-void ReadSRIX4KIso14443(DWORD parameter);
-void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast);
+void ReadSRIX4KIso14443(DWORD parameter);
+void ReadSTMemoryIso14443(DWORD parameter,DWORD dwLast);
 void SnoopIso14443(void);
 
 /// iso14443a.h
 void SnoopIso14443a(void);
 void SimulateIso14443aTag(int tagType, int TagUid);	// ## simulate iso14443a tag
 void ReaderIso14443a(DWORD parameter);
+void ReaderMifare(DWORD parameter);
 
 /// iso15693.h
 void AcquireRawAdcSamplesIso15693(void);
@@ -111,6 +116,9 @@ void *memcpy(void *dest, const void *src, int len);
 void *memset(void *dest, int c, int len);
 int memcmp(const void *av, const void *bv, int len);
 char *strncat(char *dest, const char *src, unsigned int n);
+void num_to_bytes(uint64_t n, size_t len, byte_t* dest);
+uint64_t bytes_to_num(byte_t* src, size_t len);
+
 void SpinDelay(int ms);
 void SpinDelayUs(int us);
 void LED(int led, int ms);
diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c
index d39fbdd4..4c04571e 100644
--- a/armsrc/iso14443a.c
+++ b/armsrc/iso14443a.c
@@ -10,6 +10,7 @@
 static BYTE *trace = (BYTE *) BigBuf;
 static int traceLen = 0;
 static int rsamples = 0;
+static BOOL tracing = TRUE;
 
 typedef enum {
 	SEC_D = 1,
@@ -92,6 +93,11 @@ BOOL LogTrace(const BYTE * btBytes, int iLen, int iSamples, DWORD dwParity, BOOL
   return TRUE;
 }
 
+BOOL LogTraceInfo(byte_t* data, size_t len)
+{
+  return LogTrace(data,len,0,GetParity(data,len),TRUE);
+}
+
 //-----------------------------------------------------------------------------
 // The software UART that receives commands from the reader, and its state
 // variables.
@@ -1548,7 +1554,7 @@ void ReaderTransmitShort(const BYTE* bt)
   TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);		
   
   // Store reader command in buffer
-  LogTrace(bt,1,0,GetParity(bt,1),TRUE);
+  if (tracing) LogTrace(bt,1,0,GetParity(bt,1),TRUE);
 }
 
 void ReaderTransmitPar(BYTE* frame, int len, DWORD par)
@@ -1558,14 +1564,13 @@ void ReaderTransmitPar(BYTE* frame, int len, DWORD par)
   
   // This is tied to other size changes
   // 	BYTE* frame_addr = ((BYTE*)BigBuf) + 2024; 
-  
   CodeIso14443aAsReaderPar(frame,len,par);
   
   // Select the card
   TransmitFor14443a(ToSend, ToSendMax, &samples, &wait);		
   
   // Store reader command in buffer
-  LogTrace(frame,len,0,par,TRUE);
+  if (tracing) LogTrace(frame,len,0,par,TRUE);
 }
 
 
@@ -1579,7 +1584,7 @@ BOOL ReaderReceive(BYTE* receivedAnswer)
 {
   int samples = 0;
   if (!GetIso14443aAnswerFromTag(receivedAnswer,100,&samples,0)) return FALSE;
-  LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE);
+  if (tracing) LogTrace(receivedAnswer,Demod.len,samples,Demod.parityBits,FALSE);
   return TRUE;
 }
 
@@ -1692,3 +1697,157 @@ void ReaderIso14443a(DWORD parameter)
 	DbpIntegers(rsamples, 0xCC, 0xCC);
 	DbpString("ready..");
 }
+
+//-----------------------------------------------------------------------------
+// Read an ISO 14443a tag. Send out commands and store answers.
+//
+//-----------------------------------------------------------------------------
+void ReaderMifare(DWORD parameter)
+{
+  
+	// Anticollision
+	BYTE wupa[]       = { 0x52 };
+	BYTE sel_all[]    = { 0x93,0x20 };
+	BYTE sel_uid[]    = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
+  
+	// Mifare AUTH
+	BYTE mf_auth[]    = { 0x60,0x00,0xf5,0x7b };
+  BYTE mf_nr_ar[]   = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
+  
+  BYTE* receivedAnswer = (((BYTE *)BigBuf) + 3560);	// was 3560 - tied to other size changes
+  traceLen = 0;
+  tracing = false;
+  
+	// Setup SSC
+	FpgaSetupSsc();
+  
+	// Start from off (no field generated)
+  // Signal field is off with the appropriate LED
+  LED_D_OFF();
+  FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+  SpinDelay(200);
+  
+  SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+  FpgaSetupSsc();
+  
+	// Now give it time to spin up.
+  // Signal field is on with the appropriate LED
+  LED_D_ON();
+  FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
+	SpinDelay(200);
+  
+	LED_A_ON();
+	LED_B_OFF();
+	LED_C_OFF();
+  
+  // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
+  ReaderTransmitShort(wupa);
+  // Receive the ATQA
+  ReaderReceive(receivedAnswer);
+  // Transmit SELECT_ALL
+  ReaderTransmit(sel_all,sizeof(sel_all));
+  // Receive the UID
+  ReaderReceive(receivedAnswer);
+  // Construct SELECT UID command
+  // First copy the 5 bytes (Mifare Classic) after the 93 70
+  memcpy(sel_uid+2,receivedAnswer,5);
+  // Secondly compute the two CRC bytes at the end
+  AppendCrc14443a(sel_uid,7);
+    
+  byte_t nt_diff = 0;
+  LED_A_OFF();
+  byte_t par = 0;
+  byte_t par_mask = 0xff;
+  byte_t par_low = 0;
+  BOOL led_on = TRUE;
+  
+  tracing = FALSE;
+  byte_t nt[4];
+  byte_t nt_attacked[4];
+  byte_t par_list[8];
+  byte_t ks_list[8];
+  num_to_bytes(parameter,4,nt_attacked);
+
+  while(TRUE)
+  {
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+    SpinDelay(200);
+    FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
+    
+    // Broadcast for a card, WUPA (0x52) will force response from all cards in the field
+    ReaderTransmitShort(wupa);
+    
+    // Test if the action was cancelled
+    if(BUTTON_PRESS()) {
+      break;
+    }
+    
+    // Receive the ATQA
+    if (!ReaderReceive(receivedAnswer)) continue;
+    
+    // Transmit SELECT_ALL
+    ReaderTransmit(sel_all,sizeof(sel_all));
+    
+    // Receive the UID
+    if (!ReaderReceive(receivedAnswer)) continue;
+    
+    // Transmit SELECT_UID
+    ReaderTransmit(sel_uid,sizeof(sel_uid));
+    
+    // Receive the SAK
+    if (!ReaderReceive(receivedAnswer)) continue;
+    
+    // Transmit MIFARE_CLASSIC_AUTH
+    ReaderTransmit(mf_auth,sizeof(mf_auth));
+    
+    // Receive the (16 bit) "random" nonce
+    if (!ReaderReceive(receivedAnswer)) continue;
+    memcpy(nt,receivedAnswer,4);
+
+    // Transmit reader nonce and reader answer
+    ReaderTransmitPar(mf_nr_ar,sizeof(mf_nr_ar),par);
+    
+    // Receive 4 bit answer
+    if (ReaderReceive(receivedAnswer))
+    {
+      if (nt_diff == 0)        
+      {
+        LED_A_ON();
+        memcpy(nt_attacked,nt,4);
+        par_mask = 0xf8;
+        par_low = par & 0x07;
+      }
+
+      if (memcmp(nt,nt_attacked,4) != 0) continue;
+
+      led_on = !led_on;
+      if(led_on) LED_B_ON(); else LED_B_OFF();
+      par_list[nt_diff] = par;
+      ks_list[nt_diff] = receivedAnswer[0]^0x05;
+      
+      // Test if the information is complete
+      if (nt_diff == 0x07) break;
+      
+      nt_diff = (nt_diff+1) & 0x07;
+      mf_nr_ar[3] = nt_diff << 5;
+      par = par_low;
+    } else {
+      if (nt_diff == 0)
+      {
+        par++;
+      } else {
+        par = (((par>>3)+1) << 3) | par_low;
+      }
+    }
+  }
+  
+  LogTraceInfo(sel_uid+2,4);
+  LogTraceInfo(nt,4);
+  LogTraceInfo(par_list,8);
+  LogTraceInfo(ks_list,8);
+  
+  // Thats it...
+	FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+	LEDsoff();
+  tracing = TRUE;
+}
diff --git a/armsrc/util.c b/armsrc/util.c
index 3cad25f4..e6332a7b 100644
--- a/armsrc/util.c
+++ b/armsrc/util.c
@@ -64,6 +64,24 @@ char* strncat(char *dest, const char *src, unsigned int n)
 	return dest;
 }
 
+void num_to_bytes(uint64_t n, size_t len, byte_t* dest)
+{
+	while (len--) {
+		dest[len] = (byte_t) n;
+		n >>= 8;
+	}
+}
+
+uint64_t bytes_to_num(byte_t* src, size_t len)
+{
+	uint64_t num = 0;
+	while (len--)
+	{
+		num = (num << 8) | (*src);
+		src++;
+	}
+	return num;
+}
 
 void LEDsoff()
 {