]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge branch 'master' of https://github.com/Proxmark/proxmark3
authoriceman1001 <iceman@iuse.se>
Mon, 30 Mar 2015 19:11:37 +0000 (21:11 +0200)
committericeman1001 <iceman@iuse.se>
Mon, 30 Mar 2015 19:11:37 +0000 (21:11 +0200)
Conflicts:
armsrc/iclass.c
armsrc/lfops.c
client/cmdlf.c
common/lfdemod.c
include/usb_cmd.h

97 files changed:
README.txt
armsrc/BigBuf.c
armsrc/LCD.c
armsrc/Makefile
armsrc/appmain.c
armsrc/apps.h
armsrc/crapto1.c
armsrc/des.c
armsrc/des.h
armsrc/desfire_crypto.c [new file with mode: 0644]
armsrc/desfire_crypto.h [new file with mode: 0644]
armsrc/desfire_key.c [new file with mode: 0644]
armsrc/desfire_key.h [new file with mode: 0644]
armsrc/epa.c
armsrc/fpgaloader.c
armsrc/hitag2.c
armsrc/iclass.c
armsrc/iso14443.c
armsrc/iso14443a.c
armsrc/iso14443a.h
armsrc/legicrf.c
armsrc/mifarecmd.c
armsrc/mifarecmd.h
armsrc/mifaredesfire.c [new file with mode: 0644]
armsrc/mifaredesfire.h [new file with mode: 0644]
armsrc/mifaresniff.h
armsrc/mifareutil.c
armsrc/mifareutil.h
armsrc/start.c
armsrc/util.c
bootrom/bootrom.c
client/Makefile
client/cmddata.h
client/cmdhf.c
client/cmdhf14a.c
client/cmdhf15.c
client/cmdhfdes.c [new file with mode: 0644]
client/cmdhfdes.h [new file with mode: 0644]
client/cmdhfepa.c
client/cmdhfmf.c
client/cmdhfmf.h
client/cmdhfmfdes.c [new file with mode: 0644]
client/cmdhfmfdes.h [new file with mode: 0644]
client/cmdhfmfdesfire.c [new file with mode: 0644]
client/cmdhfmfdesfire.h [new file with mode: 0644]
client/cmdhfmfu.c
client/cmdhfmfu.h
client/cmdhw.c
client/cmdlf.c
client/cmdlfawid26.c [new file with mode: 0644]
client/cmdlfawid26.h [new file with mode: 0644]
client/cmdlfem4x.c
client/cmdlfem4x.h
client/cmdlft55xx.c
client/cmdmain.h
client/flasher.c
client/graph.c
client/loclass/cipher.c
client/loclass/fileutils.h
client/loclass/hash1_brute.c [new file with mode: 0644]
client/loclass/hash1_brute.h [new file with mode: 0644]
client/lualibs/commands.lua
client/lualibs/default_toys.lua
client/lualibs/html_dumplib.lua
client/lualibs/md5.lua [new file with mode: 0644]
client/lualibs/mf_default_keys.lua
client/lualibs/precalc.lua [new file with mode: 0644]
client/lualibs/utils.lua
client/mifarehost.c
client/nonce2key/crapto1.c
client/proxmark3.c
client/proxmark3.h
client/scripting.c
client/scripts/formatMifare.lua
client/scripts/test.lua [deleted file]
client/scripts/test_t55x7_bi.lua
client/scripts/tnp3clone.lua [new file with mode: 0644]
client/scripts/tnp3dump.lua
client/scripts/tnp3sim.lua
client/ui.c
client/ui.h
common/Makefile.common
common/crc64.c [new file with mode: 0644]
common/crc64.h [new file with mode: 0644]
common/desfire.h [new file with mode: 0644]
common/iso14443crc.c
common/iso14443crc.h
common/iso15693tools.c
common/ldscript.common
common/legic_prng.c
common/lfdemod.h
common/protocols.h
cp2tau [new file with mode: 0644]
iceman.txt [new file with mode: 0644]
include/mifare.h
include/usb_cmd.h
tools/mkversion.pl

index cb2c7f3c783a137b43f99c7d14010d611bfa49ee..05829dac22cd2123610b2982daa3d4b4b6181e03 100644 (file)
@@ -1,87 +1,68 @@
-NOTICE:
-(2014-03-26)
-This is now the official Proxmark repository!
-
-INTRODUCTION:
-
-The proxmark3 is a powerful general purpose RFID tool, the size of a deck
-of cards, designed to snoop, listen and emulate everything from
-Low Frequency (125kHz) to High Frequency (13.56MHz) tags.
-
-This repository contains enough software, logic (for the FPGA), and design
-documentation for the hardware that you could, at least in theory,
-do something useful with a proxmark3.
-
-RESOURCES:
-
-   * This repository!
-      https://github.com/Proxmark/proxmark3
-      
-   * The Wiki
-      https://github.com/Proxmark/proxmark3/wiki
-      
-   * The GitHub page
-      http://proxmark.github.io/proxmark3/
-      
-   * The Forum
-      http://www.proxmark.org/forum
-      
-   * The IRC chanel
-       irc.freenode.org #proxmark3
-       -or-
-       http://webchat.freenode.net/?channels=#proxmark3
-   
-DEVELOPMENT:
-
-The tools required to build  or run the project will vary depending on
-your operating system. Please refer to the Wiki for details.
+The iceman fork.
 
-   * https://github.com/Proxmark/proxmark3/wiki
-
-OBTAINING HARDWARE:
-
-The Proxmark 3 is available for purcahse (assembled and tested) from the
-following locations:
-
-   * http://proxmark3.com/
-   * http://www.xfpga.com/
-
-Most of the ultra-low-volume contract assemblers could put
-something like this together with a reasonable yield. A run of around
-a dozen units is probably cost-effective. The BOM includes (possibly-
-outdated) component pricing, and everything is available from Digikey
-and the usual distributors.
-
-If you've never assembled a modern circuit board by hand, then this is
-not a good place to start. Some of the components (e.g. the crystals)
-must not be assembled with a soldering iron, and require hot air.
-
-The schematics are included; the component values given are not
-necessarily correct for all situations, but it should be possible to do
-nearly anything you would want with appropriate population options.
+NOTICE:
 
-The printed circuit board artwork is also available, as Gerbers and an
-Excellon drill file.
+The official Proxmark repository is found here: https://github.com/Proxmark/proxmark3
 
 
-LICENSING:
+NEWS:      
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+Whats in this fork?  I have scraped the web for different enhancements to the PM3 source code and not all of them ever found their way to the master branch. 
+Among the stuff is
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+       * Jonor's hf 14a raw timing patch
+       * Piwi's updates. (usually gets into the master)
+       * Holiman's iclass, (usually gets into the master)
+       * Marshmellow's LF fixes
+       * Midnitesnake's Ultralight,  Ultralight-c enhancements
+       * Izsh's lf peak modification / iir-filtering
+       * Aspers's tips and tricks from inside the PM3-gui-tool, settings.xml and other stuff.
+       * My own desfire, Ultralight extras, LF T55xx enhancements, bugs fixes (filelength, hf mf commands ), TNP3xxx lua scripts,  Awid26,  skidata scripts (will come)
+       * other obscure patches like for the sammy-mode,  (offline you know), tagidentifications, defaultkeys. 
+       
+Give me a hint, and I'll see if I can't merge in the stuff you have. 
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+I don't actually know how to make small pull-request to github :( and that is the number one reason for me not pushing a lot of things back to the PM3 master.
+       
+PM3 GUI:
 
+I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry*     
 
-Jonathan Westhues
-user jwesthues, at host cq.cx
+         
+DEVELOPMENT:
 
-May 2007, Cambridge MA
+This fork is adjusted to compile on windows/mingw environment with Qt5.3.1 & GCC 4.8
+For people with linux you will need to patch some source code and some small change to one makefile.  If you are lazy, you google the forum and find asper's or holimans makefile or you find your solution below.
+
+Common errors linux/macOS finds
+Error:
+       * loclass/fileutils.c:15:2: warning: implicit declaration of function â€˜_stat’ [-Wimplicit-function-declaration]
+Solution:
+       * Remove the "unscore" sign.   In linux you use without underscore, in windows you need a underscore. 
+       
+Error:  
+       * \client\makefile  the parameter -lgdi32 
+Solution:
+       * Remove parameter.
+       
+Error:  
+       * Using older Qt4.6 gives compilation errors.  
+Solution
+       * Upgrade to Qt5.3.1 
+       OR 
+       * Change these two line in  \client\makefile
+               CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets  -I/mingw/include
+               QTLDLIBS = -L$(QTDIR)/lib  -lQt5Core -lQt5Gui -lQt5Widgets 
+               
+               TO
+               
+               CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
+               QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
+       
+
+An old Qt4 version makefile is found here: http://www.icesql.se/proxmark3/code/linuxmakefile.txt  but this one doesn't have all new files in it. So I don't recommend it.
+
+
+
+January 2015, Sweden
+iceman at host iuse.se
\ No newline at end of file
index 703ade658da348db04f80b2824269a32c738cb55..2fb50a47ea2e4cee910a84c333f4f90d28153ece 100644 (file)
@@ -171,18 +171,19 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
        traceLen += iLen;
 
        // parity bytes
-       if (parity != NULL && iLen != 0) {
+       if (iLen != 0) {
+               if (parity != NULL) {
                memcpy(trace + traceLen, parity, num_paritybytes);
+               } else {
+                       memset(trace + traceLen, 0x00, num_paritybytes);
+               }
        }
        traceLen += num_paritybytes;
 
-       if(traceLen +4 < max_traceLen)
-       {       //If it hadn't been cleared, for whatever reason..
-               memset(trace+traceLen,0x44, 4);
-       }
-
        return TRUE;
 }
+
+
 int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag)
 {
        /**
@@ -224,6 +225,8 @@ int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwP
 
        return TRUE;
 }
+
+
 // Emulator memory
 uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
        uint8_t* mem = BigBuf_get_EM_addr();
index 65d64ac90ed9d87c831a568020669d824d98e98f..87be5e3aec468e64d33de09cad26bada7fb83e29 100644 (file)
@@ -6,7 +6,7 @@
 // LCD code
 //-----------------------------------------------------------------------------
 
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
 #include "apps.h"
 #include "LCD.h"
 #include "fonts.h"
index 75ccdece2c3b130d395d83e677ae5c90a7bf4e3e..1c03e5a3b17275124dcb3070e69c5a774d38ba1a 100644 (file)
@@ -10,7 +10,7 @@ APP_INCLUDES = apps.h
 
 #remove one of the following defines and comment out the relevant line
 #in the next section to remove that particular feature from compilation  
-APP_CFLAGS     = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG  -DWITH_CRC -DON_DEVICE -fno-strict-aliasing
+APP_CFLAGS     = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG  -DWITH_CRC -DON_DEVICE -fno-strict-aliasing -O2
 #-DWITH_LCD 
 
 #SRC_LCD = fonts.c LCD.c
@@ -18,7 +18,7 @@ SRC_LF = lfops.c hitag2.c lfsampling.c
 SRC_ISO15693 = iso15693.c iso15693tools.c
 SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
 SRC_ISO14443b = iso14443.c
-SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c 
+SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c
 SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c 
 
 THUMBSRC = start.c \
@@ -45,6 +45,7 @@ ARMSRC = fpgaloader.c \
        BigBuf.c \
        optimized_cipher.c
 
+
 # stdint.h provided locally until GCC 4.5 becomes C99 compliant
 APP_CFLAGS += -I.
 
index 6e0b58b3da84fa7bc3e2463c47fd10bc285a9eb8..f3136fa06cd38336f1f3ddd7b160c86b3a9cc2fa 100644 (file)
 // executes.
 //-----------------------------------------------------------------------------
 
-#include "usb_cdc.h"
-#include "cmd.h"
-
-#include "proxmark3.h"
+#include "../common/usb_cdc.h"
+#include "../common/cmd.h"
+#include "../include/proxmark3.h"
+#include "../include/hitag2.h"
 #include "apps.h"
 #include "util.h"
 #include "printf.h"
 #include "string.h"
-
 #include <stdarg.h>
-
 #include "legicrf.h"
-#include <hitag2.h>
 #include "lfsampling.h"
 #include "BigBuf.h"
+
 #ifdef WITH_LCD
  #include "LCD.h"
 #endif
@@ -180,7 +178,7 @@ void MeasureAntennaTuning(void)
        int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0 
        int vLf125 = 0, vLf134 = 0, vHf = 0;    // in mV
 
-       LED_B_ON();
+  LED_B_ON();
 
 /*
  * Sweeps the useful LF range of the proxmark from
@@ -212,7 +210,7 @@ void MeasureAntennaTuning(void)
 
        for (i=18; i >= 0; i--) LF_Results[i] = 0;
        
-       LED_A_ON();
+  LED_A_ON();
        // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
        FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
@@ -221,9 +219,9 @@ void MeasureAntennaTuning(void)
 
        cmd_send(CMD_MEASURED_ANTENNA_TUNING, vLf125 | (vLf134<<16), vHf, peakf | (peakv<<16), LF_Results, 256);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-       LED_A_OFF();
-       LED_B_OFF();
-       return;
+  LED_A_OFF();
+  LED_B_OFF();
+  return;
 }
 
 void MeasureAntennaTuningHf(void)
@@ -370,7 +368,7 @@ void SamyRun()
        for (;;)
        {
                usb_poll();
-    WDT_HIT();
+               WDT_HIT();
 
                // Was our button held down or pressed?
                int button_pressed = BUTTON_HELD(1000);
@@ -640,7 +638,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
 {
        UsbCommand *c = (UsbCommand *)packet;
 
-//  Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]);
+  //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]);
   
        switch(c->cmd) {
 #ifdef WITH_LF
@@ -693,9 +691,8 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        WriteTItag(c->arg[0],c->arg[1],c->arg[2]);
                        break;
                case CMD_SIMULATE_TAG_125K:
-                       LED_A_ON();
-                       SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);
-                       LED_A_OFF();
+                       SimulateTagLowFrequency(c->arg[0], c->arg[1], 0);
+                       //SimulateTagLowFrequencyA(c->arg[0], c->arg[1]);
                        break;
                case CMD_LF_SIMULATE_BIDIR:
                        SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);
@@ -817,6 +814,10 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        EPA_PACE_Collect_Nonce(c);
                        break;
                        
+               // case CMD_EPA_:
+               //      EpaFoo(c);
+               // break;
+                       
                case CMD_READER_MIFARE:
             ReaderMifare(c->arg[0]);
                        break;
@@ -824,7 +825,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        break;
                case CMD_MIFAREU_READBL:
-                       MifareUReadBlock(c->arg[0],c->d.asBytes);
+                       MifareUReadBlock(c->arg[0],c->arg[1], c->d.asBytes);
                        break;
                case CMD_MIFAREUC_AUTH1:
                        MifareUC_Auth1(c->arg[0],c->d.asBytes);
@@ -834,10 +835,16 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        break;
                case CMD_MIFAREU_READCARD:
                        MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes);
-                       break;
+            break;
                case CMD_MIFAREUC_READCARD:
                        MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes);
+                       break;          
+               case CMD_MIFAREUC_SETPWD: 
+                       MifareUSetPwd(c->arg[0], c->d.asBytes);
                        break;
+               //case CMD_MIFAREU_SETUID: 
+                       //MifareUSetUid(c->arg[0], c->d.asBytes);
+                       //break;                
                case CMD_MIFARE_READSC:
                        MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        break;
@@ -846,10 +853,10 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        break;
                case CMD_MIFAREU_WRITEBL_COMPAT:
                        MifareUWriteBlock(c->arg[0], c->d.asBytes);
-                        break;
+            break;
                case CMD_MIFAREU_WRITEBL:
-                        MifareUWriteBlock_Special(c->arg[0], c->d.asBytes);
-                        break;
+                       MifareUWriteBlock_Special(c->arg[0], c->d.asBytes);
+                       break;
                case CMD_MIFARE_NESTED:
                        MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        break;
@@ -893,6 +900,25 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        SniffMifare(c->arg[0]);
                        break;
 
+               //mifare desfire
+               case CMD_MIFARE_DESFIRE_READBL: break;
+               case CMD_MIFARE_DESFIRE_WRITEBL: break;
+               case CMD_MIFARE_DESFIRE_AUTH1:
+                       MifareDES_Auth1(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
+                       break;
+               case CMD_MIFARE_DESFIRE_AUTH2:
+                       //MifareDES_Auth2(c->arg[0],c->d.asBytes);
+                       break;
+               case CMD_MIFARE_DES_READER:
+                       //readermifaredes(c->arg[0], c->arg[1], c->d.asBytes);
+                       break;
+               case CMD_MIFARE_DESFIRE_INFO:
+                       MifareDesfireGetInformation();
+                       break;
+               case CMD_MIFARE_DESFIRE:
+                       MifareSendCommand(c->arg[0], c->arg[1], c->d.asBytes);
+                       break;
+
 #endif
 
 #ifdef WITH_ICLASS
@@ -907,7 +933,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        ReaderIClass(c->arg[0]);
                        break;
                case CMD_READER_ICLASS_REPLAY:
-                   ReaderIClass_Replay(c->arg[0], c->d.asBytes);
+                       ReaderIClass_Replay(c->arg[0], c->d.asBytes);
                        break;
        case CMD_ICLASS_EML_MEMSET:
                        emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
@@ -1040,7 +1066,7 @@ void  __attribute__((noreturn)) AppMain(void)
        LED_A_OFF();
 
        // Init USB device
-  usb_enable();
+       usb_enable();
 
        // The FPGA gets its clock from us from PCK0 output, so set that up.
        AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
@@ -1070,12 +1096,12 @@ void  __attribute__((noreturn)) AppMain(void)
        size_t rx_len;
   
        for(;;) {
-    if (usb_poll()) {
-      rx_len = usb_read(rx,sizeof(UsbCommand));
-      if (rx_len) {
-        UsbPacketReceived(rx,rx_len);
-      }
-    }
+               if (usb_poll()) {
+                       rx_len = usb_read(rx,sizeof(UsbCommand));
+                       if (rx_len) {
+                               UsbPacketReceived(rx,rx_len);
+                       }
+               }
                WDT_HIT();
 
 #ifdef WITH_LF
index 928a3075f44391c80e51f9ffc1f6d511225aa2ce..84376ed6d0078ea9a3961cd9fa571f579b1fd596 100644 (file)
 
 #include <stdint.h>
 #include <stddef.h>
-#include "common.h"
-#include "hitag2.h"
-#include "mifare.h"
+#include <stdlib.h>
+#include <sys/types.h>
+#include <string.h>
+#include <strings.h>
 #include "../common/crc32.h"
 #include "BigBuf.h"
+#include "../include/hitag2.h"
+#include "../include/mifare.h"
+//#include "des.h"
+//#include "aes.h"
+#include "desfire.h"
+
 
 extern const uint8_t OddByteParity[256];
 extern int rsamples;   // = 0;
@@ -116,7 +123,9 @@ void ReadTItag(void);
 void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
 void AcquireTiType(void);
 void AcquireRawBitsTI(void);
-void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
+void SimulateTagLowFrequency( uint16_t period, uint32_t gap, uint8_t ledcontrol);
+//void SimulateTagLowFrequencyA(int period, int gap);
+
 void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
 void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
 void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
@@ -133,6 +142,7 @@ void CopyIndala224toT55x7(int uid1, int uid2, int uid3, int uid4, int uid5, int
 void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode);
 void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode );
 void T55xxReadTrace(void);
+void TurnReadLFOn();
 int DemodPCF7931(uint8_t **outBlocks);
 int IsBlock0PCF7931(uint8_t *Block);
 int IsBlock1PCF7931(uint8_t *Block);
@@ -165,7 +175,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand * c);
 void ReaderMifare(bool first_try);
 int32_t dist_nt(uint32_t nt1, uint32_t nt2);
 void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
-void MifareUReadBlock(uint8_t arg0,uint8_t *datain);
+void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
 void MifareUC_Auth1(uint8_t arg0, uint8_t *datain);
 void MifareUC_Auth2(uint32_t arg0, uint8_t *datain);
 void MifareUReadCard(uint8_t arg0, int Pages, uint8_t *datain);
@@ -184,6 +194,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
 void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);  // Work with "magic Chinese" card
 void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
 void MifareCIdent();  // is "magic chinese" card?
+void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
 
 //desfire
 void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain);
@@ -202,6 +213,17 @@ void       OnError(uint8_t reason);
 
 
 
+// desfire_crypto.h
+void   *mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings);
+void    *mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings);
+void    mifare_cypher_single_block (desfirekey_t  key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
+void    mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
+size_t  key_block_size (const desfirekey_t  key);
+size_t  padded_data_length (const size_t nbytes, const size_t block_size);
+size_t  maced_data_length (const desfirekey_t  key, const size_t nbytes);
+size_t  enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings);
+void    cmac_generate_subkeys (desfirekey_t key);
+void    cmac (const desfirekey_t  key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
 
 
 /// iso15693.h
index bcd3117114147a5287eb6c0d694f21abb239d501..2fdeb924241ee0ac30bd631027286c4711c25771 100644 (file)
@@ -1,21 +1,21 @@
 /*  crapto1.c\r
 \r
-       This program is free software; you can redistribute it and/or\r
-       modify it under the terms of the GNU General Public License\r
-       as published by the Free Software Foundation; either version 2\r
-       of the License, or (at your option) any later version.\r
-\r
-       This program is distributed in the hope that it will be useful,\r
-       but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-       GNU General Public License for more details.\r
-\r
-       You should have received a copy of the GNU General Public License\r
-       along with this program; if not, write to the Free Software\r
-       Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
-       Boston, MA  02110-1301, US$\r
-\r
-       Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
+    This program is free software; you can redistribute it and/or\r
+    modify it under the terms of the GNU General Public License\r
+    as published by the Free Software Foundation; either version 2\r
+    of the License, or (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
+    Boston, MA  02110-1301, US$\r
+\r
+    Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
 */\r
 #include "crapto1.h"\r
 #include <stdlib.h>\r
@@ -24,9 +24,9 @@
 static uint8_t filterlut[1 << 20];\r
 static void __attribute__((constructor)) fill_lut()\r
 {\r
-       uint32_t i;\r
-       for(i = 0; i < 1 << 20; ++i)\r
-               filterlut[i] = filter(i);\r
+        uint32_t i;\r
+        for(i = 0; i < 1 << 20; ++i)\r
+                filterlut[i] = filter(i);\r
 }\r
 #define filter(x) (filterlut[(x) & 0xfffff])\r
 #endif\r
@@ -152,12 +152,12 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
                eks >>= 1;\r
                in >>= 2;\r
                extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1,\r
-                                LF_POLY_ODD << 1, 0);\r
+                            LF_POLY_ODD << 1, 0);\r
                if(o_head > o_tail)\r
                        return sl;\r
 \r
                extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD,\r
-                                LF_POLY_EVEN << 1 | 1, in & 3);\r
+                            LF_POLY_EVEN << 1 | 1, in & 3);\r
                if(e_head > e_tail)\r
                        return sl;\r
        }\r
@@ -170,7 +170,7 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
                        o_tail = binsearch(o_head, o = o_tail);\r
                        e_tail = binsearch(e_head, e = e_tail);\r
                        sl = recover(o_tail--, o, oks,\r
-                                        e_tail--, e, eks, rem, sl, in);\r
+                                    e_tail--, e, eks, rem, sl, in);\r
                }\r
                else if(*o_tail > *e_tail)\r
                        o_tail = binsearch(o_head, o_tail) - 1;\r
@@ -424,7 +424,7 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd)
  */\r
 static struct Crypto1State*\r
 check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],\r
-               uint32_t odd, uint32_t even, struct Crypto1State* sl)\r
+               uint32_t odd, uint32_t even, struct Crypto1State* sl)\r
 {\r
        uint32_t ks1, nr, ks2, rr, ks3, c, good = 1;\r
 \r
@@ -464,12 +464,12 @@ lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8])
 \r
        odd = lfsr_prefix_ks(ks, 1);\r
        even = lfsr_prefix_ks(ks, 0);\r
-\r
+       \r
        s = statelist = malloc((sizeof *statelist) << 20);\r
        if(!s || !odd || !even) {\r
                free(statelist);\r
                statelist = 0;\r
-               goto out;\r
+                goto out;\r
        }\r
 \r
        for(o = odd; *o + 1; ++o)\r
index 0a27503e016d197e63d730a557b625cded147e63..cb44751f52288aa0c6de0564138b80dff0e00607 100644 (file)
@@ -378,6 +378,44 @@ void tdes_dec(void* out, void* in, const uint8_t* key){
        des_dec(out, out, (uint8_t*)key + 0);
 }
 
+ void tdes_2key_enc(void* out, const void* in, size_t length, const void* key){
+
+       if( length % 8 ) return; 
+       
+       uint8_t* tin = (uint8_t*) in;
+       uint8_t* tout = (uint8_t*) out;
+       
+       while( length > 0 )
+       {
+               des_enc(tout,  tin, (uint8_t*)key + 0);
+               des_dec(tout, tout, (uint8_t*)key + 8);
+               des_enc(tout, tout, (uint8_t*)key + 0);
+               
+               tin  += 8;
+               tout += 8;
+               length -= 8;
+       }
+ }
+ void tdes_2key_dec(void* out, const void* in, size_t length, const void* key){
+       
+       if( length % 8 ) return; 
+
+       uint8_t* tin = (uint8_t*) in;
+       uint8_t* tout = (uint8_t*) out;
+       
+       while( length > 0 )
+       {
+               des_dec(tout,  tin, (uint8_t*)key + 0);
+               des_enc(tout, tout, (uint8_t*)key + 8);
+               des_dec(tout, tout, (uint8_t*)key + 0);          
+
+               tin  += 8;
+               tout += 8;
+               length -= 8;
+       }
+ }
+
 /******************************************************************************/
 
 
index 652886fd7a523d9aeab176057ac7003d8fd0ba2e..853488c8c354c73a2e72af9392cb8b62dd98f09b 100644 (file)
@@ -96,6 +96,9 @@ void tdes_enc(void* out, const void* in, const void* key);
  * \param key pointer to the key (192 bit = 24 byte)
  */
  void tdes_dec(void* out, const void* in, const void* key);
+ void tdes_2key_enc(void* out, const void* in, size_t length, const void* key);
+ void tdes_2key_dec(void* out, const void* in, size_t length, const void* key);
 
 #endif /*DES_H_*/
 
diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c
new file mode 100644 (file)
index 0000000..9ea0737
--- /dev/null
@@ -0,0 +1,642 @@
+/*-
+ * Copyright (C) 2010, Romain Tartiere.
+ * 
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ * 
+ * $Id$
+ */
+
+/*
+ * This implementation was written based on information provided by the
+ * following documents:
+ *
+ * NIST Special Publication 800-38B
+ * Recommendation for Block Cipher Modes of Operation: The CMAC Mode for Authentication
+ * May 2005
+ */
+#include "desfire_crypto.h"
+
+static void      xor (const uint8_t *ivect, uint8_t *data, const size_t len);
+
+static size_t    key_macing_length (desfirekey_t key);
+
+static void xor (const uint8_t *ivect, uint8_t *data, const size_t len) {
+    for (size_t i = 0; i < len; i++) {
+        data[i] ^= ivect[i];
+    }
+}
+
+void cmac_generate_subkeys ( desfirekey_t key) {
+    int kbs = key_block_size (key);
+    const uint8_t R = (kbs == 8) ? 0x1B : 0x87;
+
+    uint8_t l[kbs];
+    memset (l, 0, kbs);
+
+    uint8_t ivect[kbs];
+    memset (ivect, 0, kbs);
+
+    mifare_cypher_blocks_chained (NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
+
+    bool xor = false;
+
+    // Used to compute CMAC on complete blocks
+    memcpy (key->cmac_sk1, l, kbs);
+    xor = l[0] & 0x80;
+    lsl (key->cmac_sk1, kbs);
+    if (xor)
+        key->cmac_sk1[kbs-1] ^= R;
+
+    // Used to compute CMAC on the last block if non-complete
+    memcpy (key->cmac_sk2, key->cmac_sk1, kbs);
+    xor = key->cmac_sk1[0] & 0x80;
+    lsl (key->cmac_sk2, kbs);
+    if (xor)
+        key->cmac_sk2[kbs-1] ^= R;
+}
+
+void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) {
+    int kbs = key_block_size (key);
+    uint8_t *buffer = malloc (padded_data_length (len, kbs));
+
+    memcpy (buffer, data, len);
+
+    if ((!len) || (len % kbs)) {
+        buffer[len++] = 0x80;
+        while (len % kbs) {
+            buffer[len++] = 0x00;
+        }
+        xor (key->cmac_sk2, buffer + len - kbs, kbs);
+    } else {
+        xor (key->cmac_sk1, buffer + len - kbs, kbs);
+    }
+
+    mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
+
+    memcpy (cmac, ivect, kbs);
+}
+
+size_t key_block_size (const desfirekey_t key) {
+    size_t block_size = 8;
+
+    switch (key->type) {
+               case T_DES:
+               case T_3DES:
+               case T_3K3DES:
+                       block_size = 8;
+                       break;
+               case T_AES:
+                       block_size = 16;
+                       break;
+    }
+
+    return block_size;
+}
+
+/*
+ * Size of MACing produced with the key.
+ */
+static size_t key_macing_length (const desfirekey_t key) {
+    size_t mac_length = MAC_LENGTH;
+
+    switch (key->type) {
+    case T_DES:
+    case T_3DES:
+        mac_length = MAC_LENGTH;
+        break;
+    case T_3K3DES:
+    case T_AES:
+        mac_length = CMAC_LENGTH;
+        break;
+    }
+
+    return mac_length;
+}
+
+/*
+ * Size required to store nbytes of data in a buffer of size n*block_size.
+ */
+size_t padded_data_length (const size_t nbytes, const size_t block_size) {
+    if ((!nbytes) || (nbytes % block_size))
+        return ((nbytes / block_size) + 1) * block_size;
+    else
+        return nbytes;
+}
+
+/*
+ * Buffer size required to MAC nbytes of data
+ */
+size_t maced_data_length (const desfirekey_t key, const size_t nbytes) {
+    return nbytes + key_macing_length (key);
+}
+/*
+ * Buffer size required to encipher nbytes of data and a two bytes CRC.
+ */
+size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings) {
+    size_t crc_length = 0;
+    if (!(communication_settings & NO_CRC)) {
+        switch (DESFIRE(tag)->authentication_scheme) {
+        case AS_LEGACY:
+            crc_length = 2;
+            break;
+        case AS_NEW:
+            crc_length = 4;
+            break;
+        }
+    }
+
+    size_t block_size = DESFIRE(tag)->session_key ? key_block_size (DESFIRE(tag)->session_key) : 1;
+
+    return padded_data_length (nbytes + crc_length, block_size);
+}
+
+void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings) {
+    uint8_t *res = data;
+    uint8_t mac[4];
+    size_t edl;
+    bool append_mac = true;
+    desfirekey_t key = DESFIRE(tag)->session_key;
+
+    if (!key)
+        return data;
+
+    switch (communication_settings & MDCM_MASK) {
+    case MDCM_PLAIN:
+        if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
+            break;
+
+        /*
+         * When using new authentication methods, PLAIN data transmission from
+         * the PICC to the PCD are CMACed, so we have to maintain the
+         * cryptographic initialisation vector up-to-date to check data
+         * integrity later.
+         *
+         * The only difference with CMACed data transmission is that the CMAC
+         * is not apended to the data send by the PCD to the PICC.
+         */
+
+        append_mac = false;
+
+        /* pass through */
+    case MDCM_MACED:
+        switch (DESFIRE(tag)->authentication_scheme) {
+        case AS_LEGACY:
+            if (!(communication_settings & MAC_COMMAND))
+                break;
+
+            /* pass through */
+            edl = padded_data_length (*nbytes - offset, key_block_size (DESFIRE(tag)->session_key)) + offset;
+
+            // Fill in the crypto buffer with data ...
+            memcpy (res, data, *nbytes);
+            // ... and 0 padding
+            memset (res + *nbytes, 0, edl - *nbytes);
+
+            mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER);
+
+            memcpy (mac, res + edl - 8, 4);
+
+            // Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
+            memcpy (res, data, *nbytes);
+
+            if (!(communication_settings & MAC_COMMAND))
+                break;
+            // Append MAC
+            size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset;
+                       bla++;
+
+            memcpy (res + *nbytes, mac, 4);
+
+            *nbytes += 4;
+            break;
+        case AS_NEW:
+            if (!(communication_settings & CMAC_COMMAND))
+                break;
+            cmac (key, DESFIRE (tag)->ivect, res, *nbytes, DESFIRE (tag)->cmac);
+
+            if (append_mac) {
+                maced_data_length (key, *nbytes);
+
+                memcpy (res, data, *nbytes);
+                memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH);
+                *nbytes += CMAC_LENGTH;
+            }
+            break;
+        }
+
+        break;
+    case MDCM_ENCIPHERED:
+        /*  |<-------------- data -------------->|
+         *  |<--- offset -->|                    |
+         *  +---------------+--------------------+-----+---------+
+         *  | CMD + HEADERS | DATA TO BE SECURED | CRC | PADDING |
+         *  +---------------+--------------------+-----+---------+ ----------------
+         *  |               |<~~~~v~~~~~~~~~~~~~>|  ^  |         |   (DES / 3DES)
+         *  |               |     `---- crc16() ----'  |         |
+         *  |               |                    |  ^  |         | ----- *or* -----
+         *  |<~~~~~~~~~~~~~~~~~~~~v~~~~~~~~~~~~~>|  ^  |         |  (3K3DES / AES)
+         *                  |     `---- crc32() ----'  |         |
+         *                  |                                    | ---- *then* ----
+         *                  |<---------------------------------->|
+         *                            encypher()/decypher()
+         */
+
+            if (!(communication_settings & ENC_COMMAND))
+                break;
+            edl = enciphered_data_length (tag, *nbytes - offset, communication_settings) + offset;
+
+            // Fill in the crypto buffer with data ...
+            memcpy (res, data, *nbytes);
+            if (!(communication_settings & NO_CRC)) {
+                // ... CRC ...
+                switch (DESFIRE (tag)->authentication_scheme) {
+                case AS_LEGACY:
+                    AppendCrc14443a(res + offset, *nbytes - offset);
+                    *nbytes += 2;
+                    break;
+                case AS_NEW:
+                    crc32_append (res, *nbytes);
+                    *nbytes += 4;
+                    break;
+                }
+            }
+            // ... and padding
+            memset (res + *nbytes, 0, edl - *nbytes);
+
+            *nbytes = edl;
+
+            mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
+        break;
+    default:
+
+        *nbytes = -1;
+        res = NULL;
+        break;
+    }
+
+    return res;
+
+}
+
+void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings)
+{
+    void *res = data;
+    size_t edl;
+    void *edata = NULL;
+    uint8_t first_cmac_byte = 0x00;
+
+    desfirekey_t key = DESFIRE(tag)->session_key;
+
+    if (!key)
+        return data;
+
+    // Return directly if we just have a status code.
+    if (1 == *nbytes)
+        return res;
+
+    switch (communication_settings & MDCM_MASK) {
+    case MDCM_PLAIN:
+
+        if (AS_LEGACY == DESFIRE(tag)->authentication_scheme)
+            break;
+
+        /* pass through */
+    case MDCM_MACED:
+        switch (DESFIRE (tag)->authentication_scheme) {
+        case AS_LEGACY:
+            if (communication_settings & MAC_VERIFY) {
+                *nbytes -= key_macing_length (key);
+                if (*nbytes <= 0) {
+                    *nbytes = -1;
+                    res = NULL;
+#ifdef WITH_DEBUG
+                    Dbprintf ("No room for MAC!");
+#endif
+                    break;
+                }
+
+                edl = enciphered_data_length (tag, *nbytes - 1, communication_settings);
+                edata = malloc (edl);
+
+                memcpy (edata, data, *nbytes - 1);
+                memset ((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
+
+                mifare_cypher_blocks_chained (tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
+
+                if (0 != memcmp ((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
+#ifdef WITH_DEBUG
+                    Dbprintf ("MACing not verified");
+                    hexdump ((uint8_t *)data + *nbytes - 1, key_macing_length (key), "Expect ", 0);
+                    hexdump ((uint8_t *)edata + edl - 8, key_macing_length (key), "Actual ", 0);
+#endif
+                    DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
+                    *nbytes = -1;
+                    res = NULL;
+                }
+            }
+            break;
+        case AS_NEW:
+            if (!(communication_settings & CMAC_COMMAND))
+                break;
+            if (communication_settings & CMAC_VERIFY) {
+                if (*nbytes < 9) {
+                    *nbytes = -1;
+                    res = NULL;
+                    break;
+                }
+                first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
+                ((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes-1];
+            }
+
+            int n = (communication_settings & CMAC_VERIFY) ? 8 : 0;
+            cmac (key, DESFIRE (tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE (tag)->cmac);
+
+            if (communication_settings & CMAC_VERIFY) {
+                ((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
+                if (0 != memcmp (DESFIRE (tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
+#ifdef WITH_DEBUG
+                    Dbprintf ("CMAC NOT verified :-(");
+                    hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
+                    hexdump (DESFIRE (tag)->cmac, 8, "Actual ", 0);
+#endif
+                    DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
+                    *nbytes = -1;
+                    res = NULL;
+                } else {
+                    *nbytes -= 8;
+                }
+            }
+            break;
+        }
+
+        free (edata);
+
+        break;
+    case MDCM_ENCIPHERED:
+        (*nbytes)--;
+        bool verified = false;
+        int crc_pos = 0x00;
+        int end_crc_pos = 0x00;
+        uint8_t x;
+
+        /*
+         * AS_LEGACY:
+         * ,-----------------+-------------------------------+--------+
+         * \     BLOCK n-1   |              BLOCK n          | STATUS |
+         * /  PAYLOAD | CRC0 | CRC1 | 0x80? | 0x000000000000 | 0x9100 |
+         * `-----------------+-------------------------------+--------+
+         *
+         *         <------------ DATA ------------>
+         * FRAME = PAYLOAD + CRC(PAYLOAD) + PADDING
+         *
+         * AS_NEW:
+         * ,-------------------------------+-----------------------------------------------+--------+
+         * \                 BLOCK n-1     |                  BLOCK n                      | STATUS |
+         * /  PAYLOAD | CRC0 | CRC1 | CRC2 | CRC3 | 0x80? | 0x0000000000000000000000000000 | 0x9100 |
+         * `-------------------------------+-----------------------------------------------+--------+
+         * <----------------------------------- DATA ------------------------------------->|
+         *
+         *         <----------------- DATA ---------------->
+         * FRAME = PAYLOAD + CRC(PAYLOAD + STATUS) + PADDING + STATUS
+         *                                    `------------------'
+         */
+
+        mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
+
+        /*
+         * Look for the CRC and ensure it is followed by NULL padding.  We
+         * can't start by the end because the CRC is supposed to be 0 when
+         * verified, and accumulating 0's in it should not change it.
+         */
+        switch (DESFIRE (tag)->authentication_scheme) {
+        case AS_LEGACY:
+            crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
+            if (crc_pos < 0) {
+                /* Single block */
+                crc_pos = 0;
+            }
+            break;
+        case AS_NEW:
+            /* Move status between payload and CRC */
+            res = DESFIRE (tag)->crypto_buffer;
+            memcpy (res, data, *nbytes);
+
+            crc_pos = (*nbytes) - 16 - 3;
+            if (crc_pos < 0) {
+                /* Single block */
+                crc_pos = 0;
+            }
+            memcpy ((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
+            ((uint8_t *)res)[crc_pos] = 0x00;
+            crc_pos++;
+            *nbytes += 1;
+            break;
+        }
+
+        do {
+            uint16_t crc16 =0x00;
+            uint32_t crc;
+            switch (DESFIRE (tag)->authentication_scheme) {
+            case AS_LEGACY:
+                end_crc_pos = crc_pos + 2;
+                AppendCrc14443a (res, end_crc_pos);
+                               
+                               // 
+                               
+                               
+                crc = crc16;
+                break;
+            case AS_NEW:
+                end_crc_pos = crc_pos + 4;
+                crc32 (res, end_crc_pos, (uint8_t *)&crc);
+                break;
+            }
+            if (!crc) {
+                verified = true;
+                for (int n = end_crc_pos; n < *nbytes - 1; n++) {
+                    uint8_t byte = ((uint8_t *)res)[n];
+                    if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) ))
+                        verified = false;
+                }
+            }
+            if (verified) {
+                *nbytes = crc_pos;
+                switch (DESFIRE (tag)->authentication_scheme) {
+                case AS_LEGACY:
+                    ((uint8_t *)data)[(*nbytes)++] = 0x00;
+                    break;
+                case AS_NEW:
+                    /* The status byte was already before the CRC */
+                    break;
+                }
+            } else {
+                switch (DESFIRE (tag)->authentication_scheme) {
+                case AS_LEGACY:
+                    break;
+                case AS_NEW:
+                    x = ((uint8_t *)res)[crc_pos - 1];
+                    ((uint8_t *)res)[crc_pos - 1] = ((uint8_t *)res)[crc_pos];
+                    ((uint8_t *)res)[crc_pos] = x;
+                    break;
+                }
+                crc_pos++;
+            }
+        } while (!verified && (end_crc_pos < *nbytes));
+
+        if (!verified) {
+#ifdef WITH_DEBUG
+            /* FIXME In some configurations, the file is transmitted PLAIN */
+            Dbprintf("CRC not verified in decyphered stream");
+#endif
+            DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR;
+            *nbytes = -1;
+            res = NULL;
+        }
+
+        break;
+    default:
+        Dbprintf("Unknown communication settings");
+        *nbytes = -1;
+        res = NULL;
+        break;
+
+    }
+    return res;
+}
+
+
+void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size)
+{
+    uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE];
+
+    if (direction == MCD_SEND) {
+        xor (ivect, data, block_size);
+    } else {
+        memcpy (ovect, data, block_size);
+    }
+
+    uint8_t edata[MAX_CRYPTO_BLOCK_SIZE];
+
+    switch (key->type) {
+    case T_DES:
+        switch (operation) {
+        case MCO_ENCYPHER:
+            //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
+                       des_enc(edata, data, key->data);
+            break;
+        case MCO_DECYPHER:
+            //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
+                       des_dec(edata, data, key->data);
+            break;
+        }
+        break;
+    case T_3DES:
+        switch (operation) {
+        case MCO_ENCYPHER:                     
+            // DES_ecb_encrypt ((DES_cblock *) data,  (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
+            // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data,  &(key->ks2), DES_DECRYPT);
+            // DES_ecb_encrypt ((DES_cblock *) data,  (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
+                       tdes_enc(edata,data, key->data);
+            break;
+        case MCO_DECYPHER:
+            // DES_ecb_encrypt ((DES_cblock *) data,  (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
+            // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data,  &(key->ks2), DES_ENCRYPT);
+            // DES_ecb_encrypt ((DES_cblock *) data,  (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
+                       tdes_dec(data, edata, key->data);
+            break;
+        }
+        break;
+    case T_3K3DES:
+        switch (operation) {
+        case MCO_ENCYPHER:
+                       tdes_enc(edata,data, key->data);
+            // DES_ecb_encrypt ((DES_cblock *) data,  (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
+            // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data,  &(key->ks2), DES_DECRYPT);
+            // DES_ecb_encrypt ((DES_cblock *) data,  (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
+            break;
+        case MCO_DECYPHER:
+                       tdes_dec(data, edata, key->data);        
+                       // DES_ecb_encrypt ((DES_cblock *) data,  (DES_cblock *) edata, &(key->ks3), DES_DECRYPT);
+            // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data,  &(key->ks2), DES_ENCRYPT);
+            // DES_ecb_encrypt ((DES_cblock *) data,  (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
+            break;
+        }
+        break;
+    case T_AES:
+        switch (operation) 
+               {
+                       case MCO_ENCYPHER:
+                       {
+                               AesCtx ctx;
+                               AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); 
+                               AesEncrypt(&ctx, data, edata, sizeof(data) );
+                               break;
+                       }
+                       case MCO_DECYPHER:
+                       {
+                               AesCtx ctx;
+                               AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); 
+                               AesDecrypt(&ctx, edata, data, sizeof(edata));
+                               break;
+                       }
+        }
+        break;
+    }
+
+    memcpy (data, edata, block_size);
+
+    if (direction == MCD_SEND) {
+        memcpy (ivect, data, block_size);
+    } else {
+        xor (ivect, data, block_size);
+        memcpy (ivect, ovect, block_size);
+    }
+}
+
+/*
+ * This function performs all CBC cyphering / deciphering.
+ *
+ * The tag argument may be NULL, in which case both key and ivect shall be set.
+ * When using the tag session_key and ivect for processing data, these
+ * arguments should be set to NULL.
+ *
+ * Because the tag may contain additional data, one may need to call this
+ * function with tag, key and ivect defined.
+ */
+void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation) {
+    size_t block_size;
+
+    if (tag) {
+        if (!key)
+            key = DESFIRE (tag)->session_key;
+        if (!ivect)
+            ivect = DESFIRE (tag)->ivect;
+
+        switch (DESFIRE (tag)->authentication_scheme) {
+                       case AS_LEGACY:
+                               memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
+                               break;
+                       case AS_NEW:
+                               break;
+        }
+    }
+
+    block_size = key_block_size (key);
+
+    size_t offset = 0;
+    while (offset < data_size) {
+        mifare_cypher_single_block (key, data + offset, ivect, direction, operation, block_size);
+        offset += block_size;
+    }
+}
\ No newline at end of file
diff --git a/armsrc/desfire_crypto.h b/armsrc/desfire_crypto.h
new file mode 100644 (file)
index 0000000..698f11e
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __DESFIRE_CRYPTO_H
+#define __DESFIRE_CRYPTO_H
+
+#include <string.h>
+#include <strings.h>
+#include <stdarg.h>
+#include "printf.h"
+
+#include "iso14443a.h"
+#include "../common/desfire.h"
+#include "des.h"
+//#include "aes.h"
+
+#endif
diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c
new file mode 100644 (file)
index 0000000..b3aa14e
--- /dev/null
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (C) 2010, Romain Tartiere.
+ * 
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by the
+ * Free Software Foundation, either version 3 of the License, or (at your
+ * option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>
+ * 
+ * $Id$
+ */
+#include <stdlib.h>
+#include "desfire_key.h"
+
+static inline void update_key_schedules (desfirekey_t key);
+
+static inline void update_key_schedules (desfirekey_t key) {
+    // DES_set_key ((DES_cblock *)key->data, &(key->ks1));
+    // DES_set_key ((DES_cblock *)(key->data + 8), &(key->ks2));
+    // if (T_3K3DES == key->type) {
+        // DES_set_key ((DES_cblock *)(key->data + 16), &(key->ks3));
+    // }
+}
+
+void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key) {
+    uint8_t data[8];
+    memcpy (data, value, 8);
+    for (int n=0; n < 8; n++)
+        data[n] &= 0xfe;
+    Desfire_des_key_new_with_version (data, key);
+}
+
+void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key) {
+       if ( key != NULL) {
+               key->type = T_DES;
+               memcpy (key->data, value, 8);
+               memcpy (key->data+8, value, 8);
+               update_key_schedules (key);
+       }
+}
+
+void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) {
+    uint8_t data[16];
+    memcpy (data, value, 16);
+    for (int n=0; n < 8; n++)
+        data[n] &= 0xfe;
+    for (int n=8; n < 16; n++)
+        data[n] |= 0x01;
+    Desfire_3des_key_new_with_version (data, key);
+}
+
+void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key) {
+    if ( key != NULL ){
+               key->type = T_3DES;
+               memcpy (key->data, value, 16);
+               update_key_schedules (key);
+       }
+}
+
+void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) {
+    uint8_t data[24];
+    memcpy (data, value, 24);
+    for (int n=0; n < 8; n++)
+        data[n] &= 0xfe;
+    Desfire_3k3des_key_new_with_version (data, key);
+}
+
+void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key) {
+       if ( key != NULL){
+               key->type = T_3K3DES;
+               memcpy (key->data, value, 24);
+               update_key_schedules (key);
+       }
+}
+
+ void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key) {
+    Desfire_aes_key_new_with_version (value, 0, key);
+}
+
+ void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version, desfirekey_t key) {
+
+       if (key != NULL) {
+               memcpy (key->data, value, 16);
+               key->type = T_AES;
+               key->aes_version = version;
+       }
+}
+
+uint8_t Desfire_key_get_version (desfirekey_t key) {
+    uint8_t version = 0;
+
+    for (int n = 0; n < 8; n++) {
+        version |= ((key->data[n] & 1) << (7 - n));
+    }
+    return version;
+}
+
+void Desfire_key_set_version (desfirekey_t key, uint8_t version)
+{
+    for (int n = 0; n < 8; n++) {
+        uint8_t version_bit = ((version & (1 << (7-n))) >> (7-n));
+        key->data[n] &= 0xfe;
+        key->data[n] |= version_bit;
+        if (key->type == T_DES) {
+            key->data[n+8] = key->data[n];
+        } else {
+            // Write ~version to avoid turning a 3DES key into a DES key
+            key->data[n+8] &= 0xfe;
+            key->data[n+8] |= ~version_bit;
+        }
+    }
+}
+
+void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key) {
+
+    uint8_t buffer[24];
+
+    switch (authkey->type) {
+    case T_DES:
+        memcpy (buffer, rnda, 4);
+        memcpy (buffer+4, rndb, 4);
+        Desfire_des_key_new_with_version (buffer, key);
+        break;
+    case T_3DES:
+        memcpy (buffer, rnda, 4);
+        memcpy (buffer+4, rndb, 4);
+        memcpy (buffer+8, rnda+4, 4);
+        memcpy (buffer+12, rndb+4, 4);
+        Desfire_3des_key_new_with_version (buffer, key);
+        break;
+    case T_3K3DES:
+        memcpy (buffer, rnda, 4);
+        memcpy (buffer+4, rndb, 4);
+        memcpy (buffer+8, rnda+6, 4);
+        memcpy (buffer+12, rndb+6, 4);
+        memcpy (buffer+16, rnda+12, 4);
+        memcpy (buffer+20, rndb+12, 4);
+        Desfire_3k3des_key_new (buffer, key);
+        break;
+    case T_AES:
+        memcpy (buffer, rnda, 4);
+        memcpy (buffer+4, rndb, 4);
+        memcpy (buffer+8, rnda+12, 4);
+        memcpy (buffer+12, rndb+12, 4);
+        Desfire_aes_key_new (buffer, key);
+        break;
+    }
+}
\ No newline at end of file
diff --git a/armsrc/desfire_key.h b/armsrc/desfire_key.h
new file mode 100644 (file)
index 0000000..0d99903
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __DESFIRE_KEY_INCLUDED
+#define __DESFIRE_KEY_INCLUDED
+#include "iso14443a.h"
+// desfire_key.h
+void           Desfire_des_key_new (const uint8_t value[8], desfirekey_t key);
+void           Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key);
+void           Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key);
+void           Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key);
+void           Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key);
+void           Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key);
+void           Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key);
+void           Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version,desfirekey_t key);
+uint8_t        Desfire_key_get_version (desfirekey_t key);
+void           Desfire_key_set_version (desfirekey_t key, uint8_t version);
+void           Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
+
+#endif
\ No newline at end of file
index 0006d59d01c03fd4944caefef829771b1b8068fc..9012bf11a8cb9713e0d5804eee142e86448fbb95 100644 (file)
@@ -13,7 +13,8 @@
 
 #include "iso14443a.h"
 #include "epa.h"
-#include "cmd.h"
+#include "../common/cmd.h"
+
 
 // Protocol and Parameter Selection Request
 // use regular (1x) speed in both directions
@@ -224,7 +225,7 @@ static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return)
        EPA_Finish();
        
        // send the USB packet
-  cmd_send(CMD_ACK,step,func_return,0,0,0);
+       cmd_send(CMD_ACK,step,func_return,0,0,0);
 }
 
 //-----------------------------------------------------------------------------
@@ -252,8 +253,9 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
        
        // set up communication
        func_return = EPA_Setup();
-       if (func_return != 0) {
+       if (func_return != 0) { 
                EPA_PACE_Collect_Nonce_Abort(1, func_return);
+               Dbprintf("epa: setup fucked up! %d", func_return);
                return;
        }
 
@@ -263,10 +265,13 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
        int card_access_length = EPA_Read_CardAccess(card_access, 256);
        // the response has to be at least this big to hold the OID
        if (card_access_length < 18) {
+               Dbprintf("epa: Too small!");
                EPA_PACE_Collect_Nonce_Abort(2, card_access_length);
                return;
        }
 
+       Dbprintf("epa: foo!");
+       
        // this will hold the PACE info of the card
        pace_version_info_t pace_version_info;
        // search for the PACE OID
@@ -278,6 +283,8 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
                return;
        }
        
+       Dbprintf("epa: bar!");
+       
        // initiate the PACE protocol
        // use the CAN for the password since that doesn't change
        func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
@@ -299,7 +306,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
        // save received information
 //     ack->arg[1] = func_return;
 //     memcpy(ack->d.asBytes, nonce, func_return);
-  cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
+       cmd_send(CMD_ACK,0,func_return,0,nonce,func_return);
 }
 
 //-----------------------------------------------------------------------------
@@ -422,7 +429,7 @@ int EPA_Setup()
 
        // power up the field
        iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
-
+       
        // select the card
        return_code = iso14443a_select_card(uid, &card_select_info, NULL);
        if (return_code != 1) {
index 077b378a918b438cb0dc625642d22a7543eaabbf..32e0500ed83f649fe6013ec86445c1fbb13e7298 100644 (file)
@@ -9,7 +9,8 @@
 // Routines to load the FPGA image, and then to configure the FPGA's major
 // mode once it is configured.
 //-----------------------------------------------------------------------------
-#include "proxmark3.h"
+
+#include "../include/proxmark3.h"
 #include "apps.h"
 #include "util.h"
 #include "string.h"
index 4b173d6f223845620eeb47e96e35c89ffb78f628..2d0645658c2dc2d2b68cf35f8f295308cf364925 100644 (file)
 // (c) 2012 Roel Verdult
 //-----------------------------------------------------------------------------
 
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
 #include "apps.h"
 #include "util.h"
-#include "hitag2.h"
+#include "../include/hitag2.h"
 #include "string.h"
 #include "BigBuf.h"
 
@@ -973,7 +973,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
        AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
        AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
        
-  // Disable timer during configuration        
+    // Disable timer during configuration      
        AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
 
        // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
index 7b4daa36bb3b6541e5b77fffbceb84189639ce02..e5bd4f42852ef1682962a48aedccb6be08cd7417 100644 (file)
@@ -36,7 +36,7 @@
 //
 //-----------------------------------------------------------------------------
 
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
 #include "apps.h"
 #include "util.h"
 #include "string.h"
@@ -45,8 +45,9 @@
 // Needed for CRC in emulation mode;
 // same construction as in ISO 14443;
 // different initial value (CRC_ICLASS)
-#include "iso14443crc.h"
-#include "iso15693tools.h"
+#include "../common/iso14443crc.h"
+#include "../common/iso15693tools.h"
+//#include "iso15693tools.h"
 #include "protocols.h"
 #include "optimized_cipher.h"
 
@@ -353,7 +354,7 @@ static struct {
                SUB_SECOND_HALF,
                SUB_BOTH
        }               sub;
-    uint8_t *output;
+    uint8_t   *output;
 } Demod;
 
 static RAMFUNC int ManchesterDecoding(int v)
@@ -658,7 +659,7 @@ void RAMFUNC SnoopIClass(void)
        clear_trace();
     iso14a_set_trigger(FALSE);
 
-       int lastRxCounter;
+    int lastRxCounter;
     uint8_t *upTo;
     int smpl;
     int maxBehindBy = 0;
@@ -774,7 +775,7 @@ void RAMFUNC SnoopIClass(void)
                if(ManchesterDecoding(smpl & 0x0F)) {
                        time_stop = (GetCountSspClk()-time_0) << 4;
 
-                       rsamples = samples - Demod.samples;
+                   rsamples = samples - Demod.samples;
                    LED_B_ON();
 
                        if(tracing)     {
@@ -944,7 +945,7 @@ static void CodeIClassTagAnswer(const uint8_t *cmd, int len)
                uint8_t b = cmd[i];
                ToSend[++ToSendMax] = encode4Bits(b & 0xF); //Least significant half
                ToSend[++ToSendMax] = encode4Bits((b >>4) & 0xF);//Most significant half
-       }
+                       }
 
        // Send EOF
        ToSend[++ToSendMax] = 0xB8;
@@ -1230,24 +1231,24 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf)
                                //exitLoop = true;
                        }else
                        {       //Not fullsim, we don't respond
-                               // We do not know what to answer, so lets keep quiet
+            // We do not know what to answer, so lets keep quiet
                                modulated_response = resp_sof; modulated_response_size = 0;
-                               trace_data = NULL;
-                               trace_data_size = 0;
+                       trace_data = NULL;
+                       trace_data_size = 0;
                                if (simulationMode == MODE_EXIT_AFTER_MAC){
-                                       // dbprintf:ing ...
-                                       Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x"
-                                                          ,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]);
-                                       Dbprintf("RDR:  (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x",len,
-                                                       receivedCmd[0], receivedCmd[1], receivedCmd[2],
-                                                       receivedCmd[3], receivedCmd[4], receivedCmd[5],
-                                                       receivedCmd[6], receivedCmd[7], receivedCmd[8]);
-                                       if (reader_mac_buf != NULL)
-                                       {
-                                               memcpy(reader_mac_buf,receivedCmd+1,8);
-                                       }
-                                       exitLoop = true;
+                               // dbprintf:ing ...
+                               Dbprintf("CSN: %02x %02x %02x %02x %02x %02x %02x %02x"
+                                                  ,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]);
+                               Dbprintf("RDR:  (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x",len,
+                                               receivedCmd[0], receivedCmd[1], receivedCmd[2],
+                                               receivedCmd[3], receivedCmd[4], receivedCmd[5],
+                                               receivedCmd[6], receivedCmd[7], receivedCmd[8]);
+                               if (reader_mac_buf != NULL)
+                               {
+                                       memcpy(reader_mac_buf,receivedCmd+1,8);
                                }
+                               exitLoop = true;
+                       }
                        }
 
                } else if(receivedCmd[0] == ICLASS_CMD_HALT && len == 1) {
@@ -1404,17 +1405,17 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
    {
      if(*wait < 10) *wait = 10;
      
-     for(c = 0; c < *wait;) {
-       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
-         AT91C_BASE_SSC->SSC_THR = 0x00;               // For exact timing!
-         c++;
-       }
-       if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
-         volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
-         (void)r;
-       }
-       WDT_HIT();
-     }
+  for(c = 0; c < *wait;) {
+    if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
+      AT91C_BASE_SSC->SSC_THR = 0x00;          // For exact timing!
+      c++;
+    }
+    if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
+      volatile uint32_t r = AT91C_BASE_SSC->SSC_RHR;
+      (void)r;
+    }
+    WDT_HIT();
+  }
 
    }
 
@@ -1497,18 +1498,18 @@ void CodeIClassCommand(const uint8_t * cmd, int len)
 
 void ReaderTransmitIClass(uint8_t* frame, int len)
 {
-       int wait = 0;
-       int samples = 0;
+  int wait = 0;
+  int samples = 0;
 
-       // This is tied to other size changes
-       CodeIClassCommand(frame,len);
+  // This is tied to other size changes
+  CodeIClassCommand(frame,len);
 
-       // Select the card
-       TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait);
-       if(trigger)
-               LED_A_ON();
+  // Select the card
+  TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait);
+  if(trigger)
+       LED_A_ON();
 
-       // Store reader command in buffer
+  // Store reader command in buffer
        if (tracing) {
                uint8_t par[MAX_PARITY_SIZE];
                GetParity(frame, len, par);
@@ -1544,7 +1545,7 @@ static int GetIClassAnswer(uint8_t *receivedResponse, int maxLen, int *samples,
        for(;;) {
                WDT_HIT();
 
-               if(BUTTON_PRESS()) return FALSE;
+           if(BUTTON_PRESS()) return FALSE;
 
                if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
                        AT91C_BASE_SSC->SSC_THR = 0x00;  // To make use of exact timing of next command from reader!!
@@ -1691,7 +1692,7 @@ void ReaderIClass(uint8_t arg0) {
        set_tracing(TRUE);
     setupIclassReader();
 
-       while(!BUTTON_PRESS())
+    while(!BUTTON_PRESS())
     {
 
                if(!tracing) {
@@ -1742,9 +1743,9 @@ void ReaderIClass(uint8_t arg0) {
                //Then we can 'ship' back the 8 * 5 bytes of data,
                // with 0xFF:s in block 3 and 4.
 
-               LED_B_ON();
-               //Send back to client, but don't bother if we already sent this
-               if(memcmp(last_csn, card_data, 8) != 0)
+                    LED_B_ON();
+                    //Send back to client, but don't bother if we already sent this
+                    if(memcmp(last_csn, card_data, 8) != 0)
                {
                        // If caller requires that we get CC, continue until we got it
                        if( (arg0 & read_status & FLAG_ICLASS_READER_CC) || !(arg0 & FLAG_ICLASS_READER_CC))
@@ -1754,8 +1755,8 @@ void ReaderIClass(uint8_t arg0) {
                                        LED_A_OFF();
                                        return;
                                }
-                               //Save that we already sent this....
-                               memcpy(last_csn, card_data, 8);
+                    //Save that we already sent this....
+                        memcpy(last_csn, card_data, 8);
                        }
 
                }
@@ -1810,20 +1811,20 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
                uint8_t read_status = handshakeIclassTag(card_data);
                if(read_status < 2) continue;
 
-               //for now replay captured auth (as cc not updated)
-               memcpy(check+5,MAC,4);
+                               //for now replay captured auth (as cc not updated)
+                               memcpy(check+5,MAC,4);
 
                if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
                {
-                       Dbprintf("Error: Authentication Fail!");
+                                 Dbprintf("Error: Authentication Fail!");
                        continue;
-               }
+                               }
 
                //first get configuration block (block 1)
                crc = block_crc_LUT[1];
-               read[1]=1;
-               read[2] = crc >> 8;
-               read[3] = crc & 0xff;
+                               read[1]=1;
+                               read[2] = crc >> 8;
+                               read[3] = crc & 0xff;
 
                if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
                {
@@ -1831,12 +1832,12 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
                        continue;
                }
 
-               mem=resp[5];
-               memory.k16= (mem & 0x80);
-               memory.book= (mem & 0x20);
-               memory.k2= (mem & 0x8);
-               memory.lockauth= (mem & 0x2);
-               memory.keyaccess= (mem & 0x1);
+                                        mem=resp[5];
+                                        memory.k16= (mem & 0x80);
+                                        memory.book= (mem & 0x20);
+                                        memory.k2= (mem & 0x8);
+                                        memory.lockauth= (mem & 0x2);
+                                        memory.keyaccess= (mem & 0x1);
 
                cardsize = memory.k16 ? 255 : 32;
                WDT_HIT();
@@ -1844,20 +1845,20 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
                memset(card_data,0x0,USB_CMD_DATA_SIZE);
                uint8_t failedRead =0;
                uint32_t stored_data_length =0;
-               //then loop around remaining blocks
+                               //then loop around remaining blocks
                for(int block=0; block < cardsize; block++){
 
                        read[1]= block;
                        crc = block_crc_LUT[block];
-                       read[2] = crc >> 8;
-                       read[3] = crc & 0xff;
+                                   read[2] = crc >> 8;
+                                   read[3] = crc & 0xff;
 
                        if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
                        {
-                               Dbprintf("     %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
+                                        Dbprintf("     %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
                                                 block, resp[0], resp[1], resp[2],
-                                               resp[3], resp[4], resp[5],
-                                               resp[6], resp[7]);
+                                         resp[3], resp[4], resp[5],
+                                         resp[6], resp[7]);
 
                                //Fill up the buffer
                                memcpy(card_data+stored_data_length,resp,8);
@@ -1921,7 +1922,7 @@ void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_
        uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
 
        // Reset trace buffer
-    memset(trace, 0x44, RECV_CMD_OFFSET);
+       memset(trace, 0x44, RECV_CMD_OFFSET);
        traceLen = 0;
 
        // Setup SSC
index c7f49f14059293dc46e5a8c845175b5c03d8e6a9..d570bf2d000c6cc97e37f8dc9464f9fa0e09cad3 100644 (file)
 // supported.
 //-----------------------------------------------------------------------------
 
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
 #include "apps.h"
 #include "util.h"
 #include "string.h"
 
-#include "iso14443crc.h"
+#include "../common/iso14443crc.h"
 
 //static void GetSamplesFor14443(int weTx, int n);
 
index ac839cfdc081049ac8ceccaa784c41306158c04e..b9fb9baea308d476a961a3c9d1c77c85ce392768 100644 (file)
@@ -15,7 +15,6 @@
 #include "util.h"
 #include "string.h"
 #include "cmd.h"
-
 #include "iso14443crc.h"
 #include "iso14443a.h"
 #include "crapto1.h"
@@ -213,6 +212,12 @@ void AppendCrc14443a(uint8_t* data, int len)
        ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
 }
 
+void AppendCrc14443b(uint8_t* data, int len)
+{
+       ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1);
+}
+
+
 //=============================================================================
 // ISO 14443 Type A - Miller decoder
 //=============================================================================
@@ -232,13 +237,17 @@ void AppendCrc14443a(uint8_t* data, int len)
 static tUart Uart;
 
 // Lookup-Table to decide if 4 raw bits are a modulation.
-// We accept two or three consecutive "0" in any position with the rest "1"
+// We accept the following:
+// 0001  -   a 3 tick wide pause
+// 0011  -   a 2 tick wide pause, or a three tick wide pause shifted left
+// 0111  -   a 2 tick wide pause shifted left
+// 1001  -   a 2 tick wide pause shifted right
 const bool Mod_Miller_LUT[] = {
-       TRUE,  TRUE,  FALSE, TRUE,  FALSE, FALSE, FALSE, FALSE,
-       TRUE,  TRUE,  FALSE, FALSE, TRUE,  FALSE, FALSE, FALSE
+       FALSE,  TRUE, FALSE, TRUE,  FALSE, FALSE, FALSE, TRUE,
+       FALSE,  TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
 };
-#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x00F0) >> 4])
-#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x000F)])
+#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
+#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
 
 void UartReset()
 {
@@ -248,16 +257,19 @@ void UartReset()
        Uart.parityLen = 0;                                     // number of decoded parity bytes
        Uart.shiftReg = 0;                                      // shiftreg to hold decoded data bits
        Uart.parityBits = 0;                            // holds 8 parity bits
-       Uart.twoBits = 0x0000;                          // buffer for 2 Bits
-       Uart.highCnt = 0;
        Uart.startTime = 0;
        Uart.endTime = 0;
+       
+       Uart.byteCntMax = 0;
+       Uart.posCnt = 0;
+       Uart.syncBit = 9999;
 }
 
 void UartInit(uint8_t *data, uint8_t *parity)
 {
        Uart.output = data;
        Uart.parity = parity;
+       Uart.fourBits = 0x00000000;                     // clear the buffer for 4 Bits
        UartReset();
 }
 
@@ -265,40 +277,44 @@ void UartInit(uint8_t *data, uint8_t *parity)
 static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
 {
 
-       Uart.twoBits = (Uart.twoBits << 8) | bit;
+       Uart.fourBits = (Uart.fourBits << 8) | bit;
        
        if (Uart.state == STATE_UNSYNCD) {                                                                                      // not yet synced
        
-               if (Uart.highCnt < 2) {                                                                                                 // wait for a stable unmodulated signal
-                       if (Uart.twoBits == 0xffff) {
-                               Uart.highCnt++;
-                       } else {
-                               Uart.highCnt = 0;
-                       }
-               } else {        
-                       Uart.syncBit = 0xFFFF;                                                                                          // not set
-                                                                                                                                                               // we look for a ...1111111100x11111xxxxxx pattern (the start bit)
-                       if              ((Uart.twoBits & 0xDF00) == 0x1F00) Uart.syncBit = 8;           // mask is   11x11111 xxxxxxxx, 
-                                                                                                                                                               // check for 00x11111 xxxxxxxx
-                       else if ((Uart.twoBits & 0xEF80) == 0x8F80) Uart.syncBit = 7;           // both masks shifted right one bit, left padded with '1'
-                       else if ((Uart.twoBits & 0xF7C0) == 0xC7C0) Uart.syncBit = 6;           // ...
-                       else if ((Uart.twoBits & 0xFBE0) == 0xE3E0) Uart.syncBit = 5;
-                       else if ((Uart.twoBits & 0xFDF0) == 0xF1F0) Uart.syncBit = 4;
-                       else if ((Uart.twoBits & 0xFEF8) == 0xF8F8) Uart.syncBit = 3;
-                       else if ((Uart.twoBits & 0xFF7C) == 0xFC7C) Uart.syncBit = 2;
-                       else if ((Uart.twoBits & 0xFFBE) == 0xFE3E) Uart.syncBit = 1;
-                       if (Uart.syncBit != 0xFFFF) {                                                                           // found a sync bit
+               Uart.syncBit = 9999;                                                                                                    // not set
+               
+               // 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated           Sequence Z (a "0" or "start of communication")
+               // 11111111 8 ticks unmodulation                                                                        Sequence Y (a "0" or "end of communication" or "no information")
+               // 111100x1 4 ticks unmodulated followed by 2|3 ticks pause                     Sequence X (a "1")
+
+               // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
+               // Sequence X followed by Sequence Y followed by Sequence Z     (111100x1 11111111 00x11111)
+               // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern 
+               // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
+               //
+#define ISO14443A_STARTBIT_MASK                0x07FFEF80              // mask is    00001111 11111111 1110 1111 10000000
+#define ISO14443A_STARTBIT_PATTERN     0x07FF8F80              // pattern is 00001111 11111111 1000 1111 10000000
+
+               if              ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7;
+               else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6;
+               else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5;
+               else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4;
+               else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3;
+               else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2;
+               else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1;
+               else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0;
+
+               if (Uart.syncBit != 9999) {                                                                                             // found a sync bit
                                Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
                                Uart.startTime -= Uart.syncBit;
                                Uart.endTime = Uart.startTime;
                                Uart.state = STATE_START_OF_COMMUNICATION;
                        }
-               }
 
        } else {
 
-               if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) {                  
-                       if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) {          // Modulation in both halves - error
+               if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {                 
+                       if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) {         // Modulation in both halves - error
                                UartReset();
                        } else {                                                                                                                        // Modulation in first half = Sequence Z = logic "0"
                                if (Uart.state == STATE_MILLER_X) {                                                             // error - must not follow after X
@@ -322,7 +338,7 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
                                }
                        }
                } else {
-                       if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) {          // Modulation second half = Sequence X = logic "1"
+                       if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) {         // Modulation second half = Sequence X = logic "1"
                                Uart.bitCount++;
                                Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100;                                   // add a 1 to the shiftreg
                                Uart.state = STATE_MILLER_X;
@@ -358,12 +374,10 @@ static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
                                                return TRUE;                                                                                    // we are finished with decoding the raw data sequence
                                        } else {
                                                UartReset();                                                                                    // Nothing received - start over
-                                               Uart.highCnt = 1;
                                        }
                                }
                                if (Uart.state == STATE_START_OF_COMMUNICATION) {                               // error - must not follow directly after SOC
                                        UartReset();
-                                       Uart.highCnt = 1;
                                } else {                                                                                                                // a logic "0"
                                        Uart.bitCount++;
                                        Uart.shiftReg = (Uart.shiftReg >> 1);                                           // add a 0 to the shiftreg
@@ -430,6 +444,11 @@ void DemodReset()
        Demod.highCnt = 0;
        Demod.startTime = 0;
        Demod.endTime = 0;
+       
+       //
+       Demod.bitCount = 0;
+       Demod.syncBit = 0xFFFF;
+       Demod.samples = 0;
 }
 
 void DemodInit(uint8_t *data, uint8_t *parity)
@@ -528,9 +547,7 @@ static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non
                                }
                        }
                }
-                       
        } 
-
     return FALSE;      // not finished yet, need more data
 }
 
@@ -680,6 +697,9 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
 
                                        // And ready to receive another response.
                                        DemodReset();
+                                       // And reset the Miller decoder including itS (now outdated) input buffer
+                                       UartInit(receivedCmd, receivedCmdPar);
+
                                        LED_C_OFF();
                                } 
                                TagIsActive = (Demod.state != DEMOD_UNSYNCD);
@@ -1337,7 +1357,7 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8
                }
 
                // Only transmit parity bit if we transmitted a complete byte
-               if (j == 8) {
+               if (j == 8 && parity != NULL) {
                        // Get the parity bit
                        if (parity[i>>3] & (0x80 >> (i&0x0007))) {
                                // Sequence X
@@ -1601,7 +1621,7 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start
 //-----------------------------------------------------------------------------
 static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset)
 {
-       uint32_t c;
+       uint32_t c = 0x00;
        
        // Set FPGA mode to "reader listen mode", no modulation (listen
        // only, since we are receiving, not transmitting).
@@ -1615,7 +1635,6 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
        // clear RXRDY:
     uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
 
-       c = 0;
        for(;;) {
                WDT_HIT();
 
@@ -1631,6 +1650,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
        }
 }
 
+
 void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing)
 {
        CodeIso14443aBitsAsReaderPar(frame, bits, par);
@@ -1646,11 +1666,13 @@ void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t
        }
 }
 
+
 void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing)
 {
   ReaderTransmitBitsPar(frame, len*8, par, timing);
 }
 
+
 void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
 {
   // Generate parity and redirect
@@ -1659,6 +1681,7 @@ void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
   ReaderTransmitBitsPar(frame, len, par, timing);
 }
 
+
 void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing)
 {
   // Generate parity and redirect
@@ -1719,6 +1742,11 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
                memset(uid_ptr,0,10);
        }
 
+       // check for proprietary anticollision:
+       if ((resp[0] & 0x1F) == 0) {
+               return 3;
+       }
+       
        // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
        // which case we need to make a cascade 2 request and select - this is a long UID
        // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
@@ -1851,7 +1879,7 @@ void iso14443a_setup(uint8_t fpga_minor_mode) {
        DemodReset();
        UartReset();
        NextTransferTime = 2*DELAY_ARM2AIR_AS_READER;
-       iso14a_set_timeout(1050); // 10ms default
+       iso14a_set_timeout(10*106); // 10ms default
 }
 
 int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {
@@ -1927,15 +1955,38 @@ void ReaderIso14443a(UsbCommand *c)
 
        if(param & ISO14A_RAW) {
                if(param & ISO14A_APPEND_CRC) {
+                       if(param & ISO14A_TOPAZMODE) {
+                               AppendCrc14443b(cmd,len);
+                       } else {
                        AppendCrc14443a(cmd,len);
+                       }
                        len += 2;
                        if (lenbits) lenbits += 16;
                }
-               if(lenbits>0) {
+               if(lenbits>0) {                         // want to send a specific number of bits (e.g. short commands)
+                       if(param & ISO14A_TOPAZMODE) {
+                               int bits_to_send = lenbits;
+                               uint16_t i = 0;
+                               ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL);             // first byte is always short (7bits) and no parity
+                               bits_to_send -= 7;
+                               while (bits_to_send > 0) {
+                                       ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL);     // following bytes are 8 bit and no parity
+                                       bits_to_send -= 8;
+                               }
+                       } else {
                        GetParity(cmd, lenbits/8, par);
-                       ReaderTransmitBitsPar(cmd, lenbits, par, NULL);
+                               ReaderTransmitBitsPar(cmd, lenbits, par, NULL);                                                 // bytes are 8 bit with odd parity
+                       }
+               } else {                                        // want to send complete bytes only
+                       if(param & ISO14A_TOPAZMODE) {
+                               uint16_t i = 0;
+                               ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL);                                                // first byte: 7 bits, no paritiy
+                               while (i < len) {
+                                       ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL);                                        // following bytes: 8 bits, no paritiy
+                               }
                } else {
-                       ReaderTransmit(cmd,len, NULL);
+                               ReaderTransmit(cmd,len, NULL);                                                                                  // 8 bits, odd parity
+                       }
                }
                arg0 = ReaderReceive(buf, par);
                cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
@@ -2374,7 +2425,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                uint32_t nr = bytes_to_num(&receivedCmd[4], 4);
 
                                //Collect AR/NR
-                               if(ar_nr_collected < 2){
+                               if(ar_nr_collected < 2 && cardAUTHSC == 2){
                                        if(ar_nr_responses[2] != ar)
                                        {// Avoid duplicates... probably not necessary, ar should vary. 
                                                ar_nr_responses[ar_nr_collected*4] = cuid;
@@ -2382,6 +2433,11 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                                ar_nr_responses[ar_nr_collected*4+2] = ar;
                                                ar_nr_responses[ar_nr_collected*4+3] = nr;
                                                ar_nr_collected++;
+                                       }                                               
+                                       // Interactive mode flag, means we need to send ACK
+                                       if(flags & FLAG_INTERACTIVE && ar_nr_collected == 2)
+                                       {
+                                               finished = true;
                                        }
                                }
 
@@ -2529,7 +2585,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                        mf_crypto1_encrypt(pcs, response, 18, response_par);
                                        EmSendCmdPar(response, 18, response_par);
                                        numReads++;
-                                       if(exitAfterNReads > 0 && numReads == exitAfterNReads) {
+                                       if(exitAfterNReads > 0 && numReads >= exitAfterNReads) {
                                                Dbprintf("%d reads done, exiting", numReads);
                                                finished = true;
                                        }
@@ -2649,12 +2705,12 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
        if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK
        {
                //May just aswell send the collected ar_nr in the response aswell
-               cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_responses,ar_nr_collected*4*4);
+               cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,1,0,&ar_nr_responses,ar_nr_collected*4*4);
        }
 
-       if(flags & FLAG_NR_AR_ATTACK)
+       if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1 )
        {
-               if(ar_nr_collected > 1) {
+               if(ar_nr_collected > 1 ) {
                        Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
                        Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
                                        ar_nr_responses[0], // UID
@@ -2666,7 +2722,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                        );
                } else {
                        Dbprintf("Failed to obtain two AR/NR pairs!");
-                       if(ar_nr_collected >0) {
+                       if(ar_nr_collected > 0 ) {
                                Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x",
                                                ar_nr_responses[0], // UID
                                                ar_nr_responses[1], //NT
@@ -2802,7 +2858,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
                                        if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break;
 
                                        /* And ready to receive another command. */
-                                       UartReset();
+                                       UartInit(receivedCmd, receivedCmdPar);
                                        
                                        /* And also reset the demod code */
                                        DemodReset();
@@ -2819,6 +2875,9 @@ void RAMFUNC SniffMifare(uint8_t param) {
 
                                        // And ready to receive another response.
                                        DemodReset();
+
+                                       // And reset the Miller decoder including its (now outdated) input buffer
+                                       UartInit(receivedCmd, receivedCmdPar);
                                }
                                TagIsActive = (Demod.state != DEMOD_UNSYNCD);
                        }
index 1e978e8808fa683f7744211e8bd4060c32eb59c5..3344de4327a5a7d8fba8e2edb595547d54c39e64 100644 (file)
@@ -12,7 +12,8 @@
 
 #ifndef __ISO14443A_H
 #define __ISO14443A_H
-#include "common.h"
+#include "../include/common.h"
+#include "../include/mifare.h"
 #include "mifaresniff.h"
 
 typedef struct {
@@ -56,15 +57,14 @@ typedef struct {
                // DROP_FIRST_HALF,
                } state;
        uint16_t shiftReg;
-       uint16_t bitCount;
+       int16_t  bitCount;
        uint16_t len;
        uint16_t byteCntMax;
        uint16_t posCnt;
        uint16_t syncBit;
        uint8_t  parityBits;
        uint8_t  parityLen;
-       uint16_t highCnt;
-       uint16_t twoBits;
+       uint32_t fourBits;
        uint32_t startTime, endTime;
     uint8_t *output;
        uint8_t *parity;
index 074a0f7896333bc5ece3020bb63aaa989029eecc..d11436ec72c21905bf89c19764012b3148e80536 100644 (file)
@@ -8,14 +8,14 @@
 // LEGIC RF simulation code
 //-----------------------------------------------------------------------------
 
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
 #include "apps.h"
 #include "util.h"
 #include "string.h"
 
 #include "legicrf.h"
-#include "legic_prng.h"
-#include "crc.h"
+#include "../include/legic_prng.h"
+#include "../common/crc.h"
 
 static struct legic_frame {
        int bits;
index a16cbf16612f9130e29f26ecce116c13669aacfa..a240bed4fa85efe222f8b0e08f23c9d9e6083163 100644 (file)
@@ -16,7 +16,8 @@
 #include "mifarecmd.h"\r
 #include "apps.h"\r
 #include "util.h"\r
-\r
+//#include "../client/loclass/des.h"\r
+#include "des.h"\r
 #include "crc.h"\r
 \r
 //-----------------------------------------------------------------------------\r
@@ -89,108 +90,162 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 \r
 void MifareUC_Auth1(uint8_t arg0, uint8_t *datain){\r
 \r
-       byte_t isOK = 0;\r
        byte_t dataoutbuf[16] = {0x00};\r
        uint8_t uid[10] = {0x00};\r
-       uint32_t cuid;\r
+       uint32_t cuid = 0x00;\r
 \r
-       LED_A_ON();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
+       LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
     \r
        clear_trace();\r
        iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
 \r
        if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Can't select card");\r
-               //OnError(0);\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");\r
+               OnError(0);\r
                return;\r
        };\r
        \r
-       if(mifare_ultra_auth1(cuid, dataoutbuf)){\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)        \r
-                       Dbprintf("Authentication part1: Fail.");\r
-               //OnError(1);\r
+       if(mifare_ultra_auth1(dataoutbuf)){\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail.");\r
+               OnError(1);\r
                return;\r
        }\r
 \r
-       isOK = 1;\r
-       if (MF_DBGLEVEL >= MF_DBG_EXTENDED)\r
-               DbpString("AUTH 1 FINISHED");\r
+       if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");\r
     \r
-    cmd_send(CMD_ACK,isOK,cuid,0,dataoutbuf,11);\r
+    cmd_send(CMD_ACK,1,cuid,0,dataoutbuf,11);\r
        LEDsoff();\r
 }\r
 void MifareUC_Auth2(uint32_t arg0, uint8_t *datain){\r
 \r
-       uint32_t cuid = arg0;\r
        uint8_t key[16] = {0x00};\r
-       byte_t isOK = 0;\r
        byte_t dataoutbuf[16] = {0x00};\r
     \r
        memcpy(key, datain, 16);\r
     \r
-       LED_A_ON();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
+       LED_A_ON();     LED_B_OFF(); LED_C_OFF();\r
        \r
-       if(mifare_ultra_auth2(cuid, key, dataoutbuf)){\r
-           if (MF_DBGLEVEL >= MF_DBG_ERROR) \r
-                       Dbprintf("Authentication part2: Fail...");\r
-               //OnError(1);\r
+       if(mifare_ultra_auth2(key, dataoutbuf)){\r
+           if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part2: Fail...");\r
+               OnError(1);\r
                return;                 \r
        }\r
        \r
-       isOK = 1;\r
-       if (MF_DBGLEVEL >= MF_DBG_EXTENDED)\r
-               DbpString("AUTH 2 FINISHED");\r
+       if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");\r
     \r
-       cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,11);\r
+       cmd_send(CMD_ACK,1,0,0,dataoutbuf,11);\r
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
        LEDsoff();\r
 }\r
 \r
-void MifareUReadBlock(uint8_t arg0,uint8_t *datain)\r
+void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
 {\r
        uint8_t blockNo = arg0;\r
        byte_t dataout[16] = {0x00};\r
        uint8_t uid[10] = {0x00};\r
-       uint32_t cuid;\r
-    \r
-       LED_A_ON();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
+       uint8_t key[16] = {0x00};\r
+    bool usePwd = (arg1 == 1);\r
+       \r
+       LED_A_ON();     LED_B_OFF(); LED_C_OFF();\r
     \r
        clear_trace();\r
        iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
     \r
-       int len = iso14443a_select_card(uid, NULL, &cuid);\r
+       int len = iso14443a_select_card(uid, NULL, NULL);\r
        if(!len) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)        Dbprintf("Can't select card");\r
-               //OnError(1);\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len);\r
+               OnError(1);\r
                return;\r
-               };\r
-        \r
-       len = mifare_ultra_readblock(cuid, blockNo, dataout);\r
-       if(len) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)        Dbprintf("Read block error");\r
-               //OnError(2);\r
+       }\r
+       \r
+        // authenticate here.\r
+       if ( usePwd ) {\r
+               \r
+               memcpy(key, datain, 16);\r
+                \r
+               // Dbprintf("KEY: %02x %02x %02x %02x %02x %02x %02x %02x", key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7] );\r
+               // Dbprintf("KEY: %02x %02x %02x %02x %02x %02x %02x %02x", key[8],key[9],key[10],key[11],key[12],key[13],key[14],key[15] );\r
+\r
+               uint8_t a[8] = {1,1,1,1,1,1,1,1 };\r
+               uint8_t b[8] = {0x00};\r
+               uint8_t enc_b[8] = {0x00};\r
+               uint8_t ab[16] = {0x00};\r
+               uint8_t enc_ab[16] = {0x00};            \r
+               uint8_t enc_key[8] = {0x00};\r
+               \r
+               uint16_t len;\r
+               uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
+               uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
+       \r
+               len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL);\r
+               if (len != 11) {\r
+                       if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
+                       OnError(1);\r
+                       return;\r
+               }\r
+       \r
+               // tag nonce.\r
+               memcpy(enc_b,receivedAnswer+1,8);\r
+\r
+               // decrypt nonce.\r
+               tdes_2key_dec(b, enc_b, 8, key );\r
+\r
+               Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", enc_b[0],enc_b[1],enc_b[2],enc_b[3],enc_b[4],enc_b[5],enc_b[6],enc_b[7] );\r
+               Dbprintf("    B: %02x %02x %02x %02x %02x %02x %02x %02x", b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] );\r
+               rol(b,8);\r
+               \r
+               memcpy(ab  ,a,8);\r
+               memcpy(ab+8,b,8);\r
+\r
+               Dbprintf("AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[0],ab[1],ab[2],ab[3],ab[4],ab[5],ab[6],ab[7] );\r
+               Dbprintf("AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[8],ab[9],ab[10],ab[11],ab[12],ab[13],ab[14],ab[15] );\r
+\r
+               // encrypt\r
+               tdes_2key_enc(enc_ab, ab, 16, key);\r
+\r
+               Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", enc_ab[0],enc_ab[1],enc_ab[2],enc_ab[3],enc_ab[4],enc_ab[5],enc_ab[6],enc_ab[7] );\r
+               Dbprintf("e_enc_ab: %02x %02x %02x %02x %02x %02x %02x %02x", enc_ab[8],enc_ab[9],enc_ab[10],enc_ab[11],enc_ab[12],enc_ab[13],enc_ab[14],enc_ab[15] );\r
+\r
+               len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, enc_ab, receivedAnswer, receivedAnswerPar, NULL);\r
+               if (len != 11) {\r
+                       if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
+                       OnError(1);\r
+                       return;\r
+               }\r
+       \r
+               // the tags' encryption of our nonce, A.\r
+               memcpy(enc_key, receivedAnswer+1, 8);\r
+               \r
+               // clear B.\r
+               memset(b, 0x00, 8);\r
+               \r
+               // decrypt \r
+               tdes_2key_dec(b, enc_key, 8, key );\r
+               if ( memcmp(a, b, 8) == 0 )\r
+                       Dbprintf("Verified key");\r
+               else\r
+                       Dbprintf("failed authentication");\r
+               \r
+               Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7] );\r
+               Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", b[0],b[1],b[2],b[3],b[4],b[5],b[6],b[7] );\r
+       }\r
+               \r
+       if( mifare_ultra_readblock(blockNo, dataout) ) {\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error");\r
+               OnError(2);\r
                return;\r
-               };\r
+       }\r
         \r
-       len = mifare_ultra_halt(cuid);\r
-       if(len) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)        Dbprintf("Halt error");\r
-               //OnError(3);\r
+       if( mifare_ultra_halt() ) {\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
+               OnError(3);\r
                return;\r
-               };\r
+       }\r
                \r
     cmd_send(CMD_ACK,1,0,0,dataout,16);\r
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
        LEDsoff();\r
 }\r
-\r
 //-----------------------------------------------------------------------------\r
 // Select, Authenticate, Read a MIFARE tag. \r
 // read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes)\r
@@ -261,63 +316,50 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 \r
 void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)\r
 {\r
-  // params\r
-        uint8_t sectorNo = arg0;\r
+       // params\r
+       uint8_t sectorNo = arg0;\r
        int Pages = arg1;\r
-       int count_Pages = 0;\r
+       int countpages = 0;\r
        byte_t dataout[176] = {0x00};;\r
-       uint8_t uid[10] = {0x00};\r
-       uint32_t cuid;\r
+       uint32_t cuid = 0x00;\r
 \r
-       LED_A_ON();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
-\r
-       if (MF_DBGLEVEL >= MF_DBG_ALL) \r
-               Dbprintf("Pages %d",Pages);\r
-       \r
+       LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
        clear_trace();\r
        iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
 \r
-       int len = iso14443a_select_card(uid, NULL, &cuid);\r
-       \r
+       int len = iso14443a_select_card(NULL, NULL, &cuid);\r
        if (!len) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Can't select card");\r
-               //OnError(1);\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len);\r
+               OnError(1);\r
                return;\r
        }\r
        \r
        for (int i = 0; i < Pages; i++){\r
        \r
-               len = mifare_ultra_readblock(cuid, sectorNo * 4 + i, dataout + 4 * i);\r
+               len = mifare_ultra_readblock(sectorNo * 4 + i, dataout + 4 * i);\r
                \r
                if (len) {\r
-                       if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                               Dbprintf("Read block %d error",i);\r
-                       //OnError(2);\r
+                       if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i);\r
+                       OnError(2);\r
                        return;\r
                } else {\r
-                       count_Pages++;\r
+                       countpages++;\r
                }\r
        }\r
                \r
-       len = mifare_ultra_halt(cuid);\r
+       len = mifare_ultra_halt();\r
        if (len) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Halt error");\r
-               //OnError(3);\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
+               OnError(3);\r
                return;\r
        }\r
        \r
-       if (MF_DBGLEVEL >= MF_DBG_ALL) {\r
-               Dbprintf("Pages read %d", count_Pages);\r
-       }\r
+       if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Pages read %d", countpages);\r
 \r
        len = 16*4; //64 bytes\r
-       \r
+\r
        // Read a UL-C\r
-       if (Pages == 44 && count_Pages > 16) \r
+       if (Pages == 44 && countpages > 16) \r
                len = 176;\r
 \r
        cmd_send(CMD_ACK, 1, 0, 0, dataout, len);       \r
@@ -400,94 +442,144 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain)
 \r
 void MifareUWriteBlock(uint8_t arg0, uint8_t *datain)\r
 {\r
-        // params\r
-        uint8_t blockNo = arg0;\r
+    uint8_t blockNo = arg0;\r
        byte_t blockdata[16] = {0x00};\r
 \r
-        memcpy(blockdata, datain,16);\r
+    memcpy(blockdata, datain, 16);\r
         \r
-        // variables\r
-        byte_t isOK = 0;\r
        uint8_t uid[10] = {0x00};\r
-        uint32_t cuid;\r
 \r
-               clear_trace();\r
-               iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
+       LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
+               \r
+       clear_trace();\r
+       iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
 \r
-        LED_A_ON();\r
-        LED_B_OFF();\r
-        LED_C_OFF();\r
-\r
-        while (true) {\r
-                if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
-                        if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");\r
-                        break;\r
-                };\r
-\r
-                if(mifare_ultra_writeblock(cuid, blockNo, blockdata)) {\r
-                        if (MF_DBGLEVEL >= 1)   Dbprintf("Write block error");\r
-                        break;\r
-                };\r
-\r
-                if(mifare_ultra_halt(cuid)) {\r
-                        if (MF_DBGLEVEL >= 1)   Dbprintf("Halt error");\r
-                        break;\r
-                };\r
-                \r
-                isOK = 1;\r
-                break;\r
-        }\r
-        \r
-        if (MF_DBGLEVEL >= 2)   DbpString("WRITE BLOCK FINISHED");\r
+       if(!iso14443a_select_card(uid, NULL, NULL)) {\r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");\r
+               OnError(0);\r
+               return;\r
+       };\r
+\r
+       if(mifare_ultra_writeblock(blockNo, blockdata)) {\r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Write block error");\r
+               OnError(0);\r
+               return; };\r
+\r
+       if(mifare_ultra_halt()) {\r
+               if (MF_DBGLEVEL >= 1)   Dbprintf("Halt error");\r
+               OnError(0);\r
+               return;\r
+       };\r
+               \r
+       if (MF_DBGLEVEL >= 2)   DbpString("WRITE BLOCK FINISHED");\r
 \r
-               cmd_send(CMD_ACK,isOK,0,0,0,0);\r
-        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
-        LEDsoff();\r
+       cmd_send(CMD_ACK,1,0,0,0,0);\r
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+       LEDsoff();\r
 }\r
 \r
 void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)\r
 {\r
-       // params\r
        uint8_t blockNo = arg0;\r
        byte_t blockdata[4] = {0x00};\r
        \r
        memcpy(blockdata, datain,4);\r
 \r
-       // variables\r
-       byte_t isOK = 0;\r
        uint8_t uid[10] = {0x00};\r
-       uint32_t cuid;\r
+       \r
+       LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
+       clear_trace();\r
+       iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
 \r
+       if(!iso14443a_select_card(uid, NULL, NULL)) {\r
+               if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+               OnError(0);\r
+               return;\r
+       };\r
+\r
+       if(mifare_ultra_special_writeblock(blockNo, blockdata)) {\r
+               if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
+               OnError(0);\r
+               return;\r
+       };\r
+\r
+       if(mifare_ultra_halt()) {\r
+               if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+               OnError(0);\r
+               return;\r
+       };\r
+\r
+       if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED");\r
+\r
+       cmd_send(CMD_ACK,1,0,0,0,0);\r
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+       LEDsoff();\r
+}\r
+\r
+void MifareUSetPwd(uint8_t arg0, uint8_t *datain){\r
+       \r
+       uint8_t pwd[16] = {0x00};\r
+       byte_t blockdata[4] = {0x00};\r
+       \r
+       memcpy(pwd, datain, 16);\r
+       \r
+       LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
        clear_trace();\r
        iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
 \r
-       LED_A_ON();\r
-       LED_B_OFF();\r
-       LED_C_OFF();\r
+       if(!iso14443a_select_card(NULL, NULL, NULL)) {\r
+               if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
+               OnError(0);\r
+               return;\r
+       };\r
 \r
-       while (true) {\r
-               if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
-                       if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");\r
-                       break;\r
-               };\r
+       blockdata[0] = pwd[7];\r
+       blockdata[1] = pwd[6];\r
+       blockdata[2] = pwd[5];\r
+       blockdata[3] = pwd[4];\r
+       if(mifare_ultra_special_writeblock( 44, blockdata)) {\r
+               if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
+               OnError(44);\r
+               return;\r
+       };\r
 \r
-               if(mifare_ultra_special_writeblock(cuid, blockNo, blockdata)) {\r
-                       if (MF_DBGLEVEL >= 1)   Dbprintf("Write block error");\r
-                       break;\r
-               };\r
+       blockdata[0] = pwd[3];\r
+       blockdata[1] = pwd[2];\r
+       blockdata[2] = pwd[1];\r
+       blockdata[3] = pwd[0];\r
+       if(mifare_ultra_special_writeblock( 45, blockdata)) {\r
+               if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
+               OnError(45);\r
+               return;\r
+       };\r
 \r
-               if(mifare_ultra_halt(cuid)) {\r
-                       if (MF_DBGLEVEL >= 1)   Dbprintf("Halt error");\r
-                       break;\r
-               };\r
+       blockdata[0] = pwd[15];\r
+       blockdata[1] = pwd[14];\r
+       blockdata[2] = pwd[13];\r
+       blockdata[3] = pwd[12];\r
+       if(mifare_ultra_special_writeblock( 46, blockdata)) {\r
+               if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
+               OnError(46);\r
+               return;\r
+       };\r
 \r
-               isOK = 1;\r
-               break;\r
-       }\r
+       blockdata[0] = pwd[11];\r
+       blockdata[1] = pwd[10];\r
+       blockdata[2] = pwd[9];\r
+       blockdata[3] = pwd[8];\r
+       if(mifare_ultra_special_writeblock( 47, blockdata)) {\r
+               if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
+               OnError(47);\r
+               return;\r
+       };      \r
 \r
-       if (MF_DBGLEVEL >= 2)   DbpString("WRITE BLOCK FINISHED");\r
+       if(mifare_ultra_halt()) {\r
+               if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
+               OnError(0);\r
+               return;\r
+       };\r
 \r
-       cmd_send(CMD_ACK,isOK,0,0,0,0);\r
+       cmd_send(CMD_ACK,1,0,0,0,0);\r
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
        LEDsoff();\r
 }\r
@@ -942,12 +1034,12 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai
                if (workFlags & 0x01) {\r
                        if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
                                if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");\r
-                               break;\r
+                               //break;\r
                        };\r
 \r
                        if(mifare_classic_halt(NULL, cuid)) {\r
                                if (MF_DBGLEVEL >= 1)   Dbprintf("Halt error");\r
-                               break;\r
+                               //break;\r
                        };\r
                };\r
        \r
@@ -1134,28 +1226,25 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){
 \r
        byte_t dataout[11] = {0x00};\r
        uint8_t uid[10] = {0x00};\r
-       uint32_t cuid;\r
+       uint32_t cuid = 0x00;\r
     \r
        clear_trace();\r
        iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
 \r
        int len = iso14443a_select_card(uid, NULL, &cuid);\r
        if(!len) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)        \r
-                       Dbprintf("Can't select card");\r
-               //OnError(1);\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card");\r
+               OnError(1);\r
                return;\r
        };\r
 \r
        if(mifare_desfire_des_auth1(cuid, dataout)){\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)        \r
-                       Dbprintf("Authentication part1: Fail.");\r
-               //OnError(4);\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail.");\r
+               OnError(4);\r
                return;\r
        }\r
 \r
        if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED");\r
-    \r
     cmd_send(CMD_ACK,1,cuid,0,dataout, sizeof(dataout));\r
 }\r
 \r
@@ -1163,22 +1252,20 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){
 \r
        uint32_t cuid = arg0;\r
        uint8_t key[16] = {0x00};\r
-       byte_t isOK = 0;\r
        byte_t dataout[12] = {0x00};\r
+       byte_t isOK = 0;\r
     \r
        memcpy(key, datain, 16);\r
        \r
        isOK = mifare_desfire_des_auth2(cuid, key, dataout);\r
        \r
        if( isOK) {\r
-           if (MF_DBGLEVEL >= MF_DBG_EXTENDED) \r
-                       Dbprintf("Authentication part2: Failed");  \r
-               //OnError(4);\r
+           if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");  \r
+               OnError(4);\r
                return;\r
        }\r
 \r
-       if (MF_DBGLEVEL >= MF_DBG_EXTENDED) \r
-               DbpString("AUTH 2 FINISHED");\r
+       if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");\r
 \r
        cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));\r
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
index 3c00a3437b25fc9c48764f96b996a8b2fca86e76..2c5a7e3fcf6484d3783dac57d0b7c9e0634a438f 100644 (file)
 #ifndef __MIFARECMD_H\r
 #define __MIFARECMD_H\r
 \r
-#include "proxmark3.h"\r
+#include "../include/proxmark3.h"\r
 #include "apps.h"\r
 #include "util.h"\r
 #include "string.h"\r
 \r
-#include "iso14443crc.h"\r
+#include "../common/iso14443crc.h"\r
 #include "iso14443a.h"\r
 #include "crapto1.h"\r
 #include "mifareutil.h"\r
-#include "common.h"\r
-\r
+#include "../include/common.h"\r
 \r
 #endif
\ No newline at end of file
diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c
new file mode 100644 (file)
index 0000000..979e2f3
--- /dev/null
@@ -0,0 +1,508 @@
+#include "mifaredesfire.h"
+#include "des.h"
+#include "BigBuf.h"
+
+#define MAX_APPLICATION_COUNT 28
+#define MAX_FILE_COUNT 16
+#define MAX_DESFIRE_FRAME_SIZE 60
+#define NOT_YET_AUTHENTICATED 255
+#define FRAME_PAYLOAD_SIZE (MAX_DESFIRE_FRAME_SIZE - 5)
+#define RECEIVE_SIZE 64
+
+// the block number for the ISO14443-4 PCB
+uint8_t pcb_blocknum = 0;
+// Deselect card by sending a s-block. the crc is precalced for speed
+static  uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
+
+//static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
+/*                                       PCB   CID   CMD    PAYLOAD    */
+//static uint8_t __res[MAX_FRAME_SIZE];
+
+bool InitDesfireCard(){
+       
+       byte_t cardbuf[USB_CMD_DATA_SIZE] = {0x00};
+
+       iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
+       
+       set_tracing(TRUE);
+       iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
+       
+       int len = iso14443a_select_card(NULL,card,NULL);
+
+       if (!len) {
+               if (MF_DBGLEVEL >= MF_DBG_ERROR)
+                       Dbprintf("Can't select card");
+               OnError(1);
+               return false;
+       }
+       return true;
+}
+
+// ARG0 flag enums
+enum  {
+ NONE          =       0x00,
+ INIT          =       0x01,
+ DISCONNECT =  0x02,
+ CLEARTRACE    =       0x04,
+ BAR           =       0x08,
+} CmdOptions ;
+
+void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
+       
+       /* ARG0 contains flags.
+               0x01 = init card.
+               0x02 = Disconnect
+               0x03
+       */
+       uint8_t flags = arg0;
+       size_t datalen = arg1;
+       uint8_t resp[RECEIVE_SIZE];
+       memset(resp,0,sizeof(resp));
+       
+       if (MF_DBGLEVEL >= 4) {
+               Dbprintf(" flags : %02X", flags);
+               Dbprintf(" len   : %02X", datalen);
+               print_result(" RX    : ", datain, datalen);
+       }
+       
+       if ( flags & CLEARTRACE ){
+               clear_trace();
+       }
+       
+       if ( flags & INIT ){
+               if ( !InitDesfireCard() )
+                       return;
+       }
+       
+       int len = DesfireAPDU(datain, datalen, resp);
+       if (MF_DBGLEVEL >= 4) {
+               print_result("ERR <--: ", resp, len);
+       }
+
+       if ( !len ) {
+               OnError(2);
+               return;
+       }
+       
+       // reset the pcb_blocknum,
+       pcb_blocknum = 0;
+       
+       if ( flags & DISCONNECT ){
+               OnSuccess();
+       }
+       
+       cmd_send(CMD_ACK,1,len,0,resp,len);
+}
+
+void MifareDesfireGetInformation(){
+               
+       int len = 0;
+       uint8_t resp[USB_CMD_DATA_SIZE] = {0x00};
+       uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00};
+       byte_t cardbuf[USB_CMD_DATA_SIZE] = {0x00};
+       
+       /*
+               1 = PCB                                 1
+               2 = cid                                 2
+               3 = desfire command             3 
+               4-5 = crc                               4  key
+                                                               5-6 crc                                                         
+               PCB == 0x0A because sending CID byte.
+               CID == 0x00 first card?         
+       */
+       clear_trace();
+       set_tracing(TRUE);
+       iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
+
+       // card select - information
+       iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
+       byte_t isOK = iso14443a_select_card(NULL, card, NULL);
+       if ( isOK == 0) {
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+                       Dbprintf("Can't select card");
+               }
+               OnError(1);
+               return;
+       }
+
+       memcpy(dataout,card->uid,7);
+
+       LED_A_ON();
+       LED_B_OFF();
+       LED_C_OFF();
+       
+       uint8_t cmd[] = {GET_VERSION};  
+       size_t cmd_len = sizeof(cmd);
+       
+       len =  DesfireAPDU(cmd, cmd_len, resp);
+       if ( !len ) {
+               print_result("ERROR <--: ", resp, len); 
+               OnError(2);
+               return;
+       }
+       
+       LED_A_OFF();
+       LED_B_ON();
+       memcpy(dataout+7,resp+3,7);
+       
+       // ADDITION_FRAME 1
+       cmd[0] = ADDITIONAL_FRAME;
+       len =  DesfireAPDU(cmd, cmd_len, resp);
+       if ( !len ) {
+               print_result("ERROR <--: ", resp, len); 
+               OnError(2);
+               return;
+       }       
+       
+       LED_B_OFF();
+       LED_C_ON();
+       memcpy(dataout+7+7,resp+3,7);
+
+       // ADDITION_FRAME 2
+       len =  DesfireAPDU(cmd, cmd_len, resp);
+       if ( !len ) {
+               print_result("ERROR <--: ", resp, len); 
+               OnError(2);
+               return;
+       }
+       
+       memcpy(dataout+7+7+7,resp+3,14);
+       
+       cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout));
+               
+       // reset the pcb_blocknum,
+       pcb_blocknum = 0;
+       OnSuccess();
+}
+
+void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno,  uint8_t *datain){
+
+       int len = 0;
+       //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
+       uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
+       uint8_t null_key_data8[8] = {0x00};
+       //uint8_t null_key_data16[16] = {0x00}; 
+       //uint8_t new_key_data8[8]  = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
+       //uint8_t new_key_data16[16]  = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
+
+       uint8_t resp[256] = {0x00};
+       uint8_t IV[16] = {0x00};
+
+       size_t datalen = datain[0];
+       
+       uint8_t cmd[40] = {0x00};
+       uint8_t encRndB[16] = {0x00};
+       uint8_t decRndB[16] = {0x00};
+       uint8_t nonce[16] = {0x00};
+       uint8_t both[32] = {0x00};
+       uint8_t encBoth[32] = {0x00};
+
+       InitDesfireCard();
+       
+       // 3 olika sätt att authenticera.   AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
+       // 4 olika crypto algo   DES, 3DES, 3K3DES, AES
+       // 3 olika kommunikations sätt,   PLAIN,MAC,CRYPTO
+       
+       // des, nyckel 0, 
+       switch (mode){
+        case 1:{
+            if (algo == 1) {
+
+            uint8_t keybytes[8] = {0x00};
+            uint8_t RndA[8] = {0x00};
+            uint8_t RndB[8] = {0x00};
+            
+            if (datain[1] == 0xff){
+                memcpy(keybytes,null_key_data8,8);
+            } else{
+                memcpy(keybytes, datain+1, datalen);
+            }
+            
+            struct desfire_key defaultkey = {0};
+            desfirekey_t key = &defaultkey;
+            Desfire_des_key_new(keybytes, key);
+            
+            cmd[0] = AUTHENTICATE;
+            cmd[1] = keyno;  //keynumber
+            len = DesfireAPDU(cmd, 2, resp);
+            if ( !len ) {
+                if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+                    DbpString("Authentication failed. Card timeout.");
+                }
+                OnError(3);
+                return;
+            }
+            
+            if ( resp[2] == 0xaf ){
+            } else {
+                DbpString("Authetication failed. Invalid key number.");
+                OnError(3);
+                return;
+            }
+            
+            memcpy( encRndB, resp+3, 8);
+            
+            des_dec(&decRndB, &encRndB, key->data);
+            memcpy(RndB, decRndB, 8);
+            rol(decRndB,8);
+            
+            // This should be random
+            uint8_t decRndA[8] = {0x00};
+            memcpy(RndA, decRndA, 8);
+            uint8_t encRndA[8] = {0x00};
+            
+            des_dec(&encRndA, &decRndA, key->data);
+            
+            memcpy(both, encRndA, 8);
+            
+            for (int x = 0; x < 8; x++) {
+                decRndB[x] = decRndB[x] ^ encRndA[x];
+            }
+            
+            des_dec(&encRndB, &decRndB, key->data);
+            
+            memcpy(both + 8, encRndB, 8);
+            
+            cmd[0] = ADDITIONAL_FRAME;
+            memcpy(cmd+1, both, 16 );
+            
+            len = DesfireAPDU(cmd, 17, resp);
+            if ( !len ) {
+                if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+                    DbpString("Authentication failed. Card timeout.");
+                }
+                OnError(3);
+                return;
+            }
+            
+            if ( resp[2] == 0x00 ){
+                
+                struct desfire_key sessionKey = {0};
+                desfirekey_t skey = &sessionKey;
+                Desfire_session_key_new( RndA, RndB , key, skey );
+                //print_result("SESSION : ", skey->data, 8);
+                
+                memcpy(encRndA, resp+3, 8);
+                des_dec(&encRndA, &encRndA, key->data);
+                rol(decRndA,8);
+                for (int x = 0; x < 8; x++) {
+                    if (decRndA[x] != encRndA[x]) {
+                        DbpString("Authetication failed. Cannot varify PICC.");
+                        OnError(4);
+                        return;
+                    }
+                }
+                
+                //Change the selected key to a new value.
+                /*
+                 
+                cmd[0] = CHANGE_KEY;
+                cmd[1] = keyno;
+                
+                uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
+                
+                uint8_t first, second;
+                uint8_t buff1[8] = {0x00};
+                uint8_t buff2[8] = {0x00};
+                uint8_t buff3[8] = {0x00};
+                
+                memcpy(buff1,newKey, 8);
+                memcpy(buff2,newKey + 8, 8);
+                
+                ComputeCrc14443(CRC_14443_A, newKey, 16, &first, &second);
+                memcpy(buff3, &first, 1);
+                memcpy(buff3 + 1, &second, 1);
+                
+                des_dec(&buff1, &buff1, skey->data);
+                memcpy(cmd+2,buff1,8);
+                
+                for (int x = 0; x < 8; x++) {
+                    buff2[x] = buff2[x] ^ buff1[x];
+                }
+                des_dec(&buff2, &buff2, skey->data);
+                memcpy(cmd+10,buff2,8);
+                
+                for (int x = 0; x < 8; x++) {
+                    buff3[x] = buff3[x] ^ buff2[x];
+                }
+                des_dec(&buff3, &buff3, skey->data);
+                memcpy(cmd+18,buff3,8);
+                
+                // The command always times out on the first attempt, this will retry until a response
+                // is recieved.
+                len = 0;
+                while(!len) {
+                    len = DesfireAPDU(cmd,26,resp);
+                }
+                */
+                
+                OnSuccess();
+                cmd_send(CMD_ACK,1,0,0,skey->data,8);
+                
+            } else {
+                DbpString("Authetication failed.");
+                OnError(6);
+                return;
+            }
+            
+            }
+            }
+                       break;
+               case 2:
+                       //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
+                       break;
+               case 3:{
+               
+                       //defaultkey
+                       uint8_t keybytes[16] = {0x00};
+                       if (datain[1] == 0xff){
+                               memcpy(keybytes,PICC_MASTER_KEY16,16); 
+                       } else{
+                               memcpy(keybytes, datain+1, datalen);
+                       }
+                       
+                       struct desfire_key defaultkey = {0x00};
+                       desfirekey_t key = &defaultkey;
+                       Desfire_aes_key_new( keybytes, key);
+               
+                       AesCtx ctx;
+                       if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){
+                               if( MF_DBGLEVEL >= 4) {
+                                       Dbprintf("AES context failed to init");
+                               }
+                               OnError(7);
+                               return;
+                       }
+                       
+                       cmd[0] = AUTHENTICATE_AES;
+                       cmd[1] = 0x00;  //keynumber
+                       len = DesfireAPDU(cmd, 2, resp);
+                       if ( !len ) {
+                               if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+                                       DbpString("Authentication failed. Card timeout.");
+                               }
+                               OnError(3);
+                               return;
+                       }
+                       
+                       memcpy( encRndB, resp+3, 16);
+               
+                       // dekryptera tagnonce.
+                       AesDecrypt(&ctx, encRndB, decRndB, 16);
+                       rol(decRndB,16);
+                       memcpy(both, nonce,16);
+                       memcpy(both+16, decRndB ,16 );
+                       AesEncrypt(&ctx, both, encBoth, 32 );
+                       
+                       cmd[0] = ADDITIONAL_FRAME;
+                       memcpy(cmd+1, encBoth, 32 );
+                       
+                       len = DesfireAPDU(cmd, 33, resp);  // 1 + 32 == 33
+                       if ( !len ) {
+                               if (MF_DBGLEVEL >= MF_DBG_ERROR) {
+                                       DbpString("Authentication failed. Card timeout.");
+                               }
+                OnError(3);
+                               return;
+                       }
+                       
+                       if ( resp[2] == 0x00 ){
+                               // Create AES Session key               
+                               struct desfire_key sessionKey = {0};
+                               desfirekey_t skey = &sessionKey;
+                               Desfire_session_key_new( nonce, decRndB , key, skey );
+                               print_result("SESSION : ", skey->data, 16);
+                       } else {
+                               DbpString("Authetication failed.");
+                               OnError(7);
+                               return;
+                       }
+                       break;
+               }       
+       }
+       
+       OnSuccess();
+       cmd_send(CMD_ACK,1,len,0,resp,len);
+}
+
+// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
+// cmd  =  cmd bytes to send
+// cmd_len = length of cmd
+// dataout = pointer to response data array
+int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
+
+       size_t len = 0;
+       size_t wrappedLen = 0;
+       uint8_t wCmd[USB_CMD_DATA_SIZE] = {0};
+       
+       uint8_t resp[MAX_FRAME_SIZE];
+    uint8_t par[MAX_PARITY_SIZE];
+       
+       wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
+       
+       if (MF_DBGLEVEL >= 4) {
+               print_result("WCMD <--: ", wCmd, wrappedLen);   
+       }
+       ReaderTransmit( wCmd, wrappedLen, NULL);
+
+       len = ReaderReceive(resp, par);
+       
+       if( len == 0x00 ){
+               if (MF_DBGLEVEL >= 4) {
+                       Dbprintf("fukked");
+               }
+               return FALSE; //DATA LINK ERROR
+       }
+       // if we received an I- or R(ACK)-Block with a block number equal to the
+       // current block number, toggle the current block number
+       else if (len >= 4 // PCB+CID+CRC = 4 bytes
+                && ((resp[0] & 0xC0) == 0 // I-Block
+                    || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
+                && (resp[0] & 0x01) == pcb_blocknum) // equal block numbers
+       {
+               pcb_blocknum ^= 1;  //toggle next block 
+       }
+
+       memcpy(dataout, resp, len);
+       return len;
+}      
+
+// CreateAPDU
+size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
+       
+       size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
+
+       uint8_t cmd[cmdlen];
+       memset(cmd, 0, cmdlen);
+       
+       cmd[0] = 0x0A;  //  0x0A = skicka cid,  0x02 = ingen cid. Särskilda bitar //
+       cmd[0] |= pcb_blocknum; // OR the block number into the PCB     
+       cmd[1] = 0x00;  //  CID: 0x00 //TODO: allow multiple selected cards
+       
+       memcpy(cmd+2, datain, len);
+       AppendCrc14443a(cmd, len+2);
+       
+       memcpy(dataout, cmd, cmdlen);
+       
+       return cmdlen;
+}
+
+       // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
+       // crc_update(&desfire_crc32, addr, addr_sz);
+       // crc_update(&desfire_crc32, byte, 8);
+       // uint32_t crc = crc_finish(&desfire_crc32);
+
+void OnSuccess(){
+       pcb_blocknum = 0;
+       ReaderTransmit(deselect_cmd, 3 , NULL);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       LEDsoff();
+}
+
+void OnError(uint8_t reason){
+       pcb_blocknum = 0;
+       ReaderTransmit(deselect_cmd, 3 , NULL);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       cmd_send(CMD_ACK,0,reason,0,0,0);
+       LEDsoff();
+}
diff --git a/armsrc/mifaredesfire.h b/armsrc/mifaredesfire.h
new file mode 100644 (file)
index 0000000..659e005
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef __MIFAREDESFIRE_H
+#define __MIFAREDESFIRE_H
+
+#include "../include/proxmark3.h"
+#include "apps.h"
+#include "util.h"
+#include "string.h"
+
+#include "../common/iso14443crc.h"
+#include "iso14443a.h"
+#include "desfire_key.h"
+#include "mifareutil.h"
+#include "../include/common.h"
+
+#endif
index 22daffee7b04ec74247b493c99addeb9088e4859..aa2a860f7bcf174b69769f1db4c3d4cc40d651ef 100644 (file)
 #ifndef __MIFARESNIFF_H\r
 #define __MIFARESNIFF_H\r
 \r
-#include "proxmark3.h"\r
+#include "../include/proxmark3.h"\r
 #include "apps.h"\r
 #include "util.h"\r
 #include "string.h"\r
 \r
-#include "iso14443crc.h"\r
+#include "../common/iso14443crc.h"\r
 #include "iso14443a.h"\r
 #include "crapto1.h"\r
 #include "mifareutil.h"\r
-#include "common.h"\r
+#include "../include/common.h"\r
 \r
 #define SNF_INIT                               0\r
 #define SNF_NO_FIELD           1\r
index f79c2ede2d78676ddc6aef7b373129e3198a23ca..8fa5e498062e57f5e5e8795687c36e0c1a0f5a94 100644 (file)
@@ -67,24 +67,24 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
 // send commands\r
 int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)\r
 {\r
-       return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing);
-}
-
-int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)
-{
-       uint8_t dcmd[8];
-    dcmd[0] = cmd;
-    dcmd[1] = data[0];
-       dcmd[2] = data[1];
-       dcmd[3] = data[2];
-       dcmd[4] = data[3];
-       dcmd[5] = data[4];
-       AppendCrc14443a(dcmd, 6);
-       ReaderTransmit(dcmd, sizeof(dcmd), NULL);
-       int len = ReaderReceive(answer, answer_parity);
-       if(!len) {
-                if (MF_DBGLEVEL >= 1)   Dbprintf("Authentication failed. Card timeout.");
-                return 2;
+       return mifare_sendcmd_shortex(pcs, crypted, cmd, data, answer, answer_parity, timing);\r
+}\r
+\r
+int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing)\r
+{\r
+       uint8_t dcmd[8];\r
+    dcmd[0] = cmd;\r
+    dcmd[1] = data[0];\r
+       dcmd[2] = data[1];\r
+       dcmd[3] = data[2];\r
+       dcmd[4] = data[3];\r
+       dcmd[5] = data[4];\r
+       AppendCrc14443a(dcmd, 6);\r
+       ReaderTransmit(dcmd, sizeof(dcmd), NULL);\r
+       int len = ReaderReceive(answer, answer_parity);\r
+       if(!len) {\r
+                if (MF_DBGLEVEL >= 1)   Dbprintf("Authentication failed. Card timeout.");\r
+                return 2;\r
     }\r
        return len;\r
 }\r
@@ -106,13 +106,13 @@ int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uin
     if(len==1) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)   Dbprintf("NAK - Authentication failed.");\r
                return 1;\r
-        }
-       return len;
-}
-
-int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)
-{
-       uint8_t dcmd[4], ecmd[4];
+        }\r
+       return len;\r
+}\r
+\r
+int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing)\r
+{\r
+       uint8_t dcmd[4], ecmd[4];\r
        uint16_t pos, res;\r
        uint8_t par[1];                 // 1 Byte parity is enough here\r
        dcmd[0] = cmd;\r
@@ -284,24 +284,21 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
        }\r
        \r
        memcpy(blockData, receivedAnswer, 16);\r
-       return 0;
-}
-
+       return 0;\r
+}\r
+\r
 // mifare ultralight commands\r
-int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){\r
+int mifare_ultra_auth1(uint8_t *blockData){\r
 \r
        uint16_t len;\r
-       uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
-       uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
+       uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
+       uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
        \r
        len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL);\r
-       if (len == 1) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
+       if (len != 11) {\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
                return 1;\r
        }\r
-       if (len != 11)\r
-               return 1;\r
 \r
        if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {\r
                Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",\r
@@ -313,20 +310,17 @@ int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){
        return 0;\r
 }\r
 \r
-int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){\r
+int mifare_ultra_auth2(uint8_t *key, uint8_t *blockData){\r
 \r
        uint16_t len;\r
-       uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
-       uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
+       uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
+       uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
        \r
        len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, key, receivedAnswer, receivedAnswerPar, NULL);\r
-       if (len == 1) {\r
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
+       if (len != 11) {\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
                return 1;\r
        }\r
-       if (len != 11)\r
-               return 1;       \r
        \r
        if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {\r
                Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",\r
@@ -338,43 +332,38 @@ int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
        return 0;\r
 }\r
 \r
-int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
-{
-       uint16_t len;
-       uint8_t bt[2];
-       uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
-       uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
-       
+int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData)\r
+{\r
+       uint16_t len;\r
+       uint8_t bt[2];\r
+       uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
+       uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
        \r
-       // command MIFARE_CLASSIC_READBLOCK
-       len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);
-       if (len == 1) {
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
-               return 1;
-       }
-       if (len != 18) {
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Cmd Error: card timeout. len: %x", len);
-               return 2;
-       }
-    
-       memcpy(bt, receivedAnswer + 16, 2);
-       AppendCrc14443a(receivedAnswer, 16);
-       if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
-               if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Cmd CRC response error.");
-               return 3;
-       }
-       
-       memcpy(blockData, receivedAnswer, 14);
-       return 0;
-}
-
-
-int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) 
-{
-       // variables
+       len = mifare_sendcmd_short(NULL, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
+       if (len == 1) {\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
+               return 1;\r
+       }\r
+       if (len != 18) {\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len);\r
+               return 2;\r
+       }\r
+    \r
+       memcpy(bt, receivedAnswer + 16, 2);\r
+       AppendCrc14443a(receivedAnswer, 16);\r
+       if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error.");\r
+               return 3;\r
+       }\r
+       \r
+       memcpy(blockData, receivedAnswer, 14);\r
+       return 0;\r
+}\r
+\r
+\r
+int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) \r
+{\r
+       // variables\r
        uint16_t len, i;        \r
        uint32_t pos;\r
        uint8_t par[3] = {0};           // enough for 18 Bytes to send\r
@@ -416,65 +405,65 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
                return 2;\r
        }\r
        \r
-       return 0;
-}
-
-int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData) 
-{
-    uint16_t len;     
-    uint8_t par[3] = {0};  // enough for 18 parity bits
-       uint8_t d_block[18] = {0x00};
-       uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
-       uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
-        
-    // command MIFARE_CLASSIC_WRITEBLOCK
-    len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
-
-    if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK
+       return 0;\r
+}\r
+\r
+int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) \r
+{\r
+    uint16_t len;     \r
+    uint8_t par[3] = {0};  // enough for 18 parity bits\r
+       uint8_t d_block[18] = {0x00};\r
+       uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
+       uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
+        \r
+    // command MIFARE_CLASSIC_WRITEBLOCK\r
+    len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
+\r
+    if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);  
-        return 1;
-    }
-
-       memcpy(d_block, blockData, 16);
-    AppendCrc14443a(d_block, 16);
-
-       ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);
-
-    len = ReaderReceive(receivedAnswer, receivedAnswerPar);    
-
-       if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK
+                       Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);  \r
+        return 1;\r
+    }\r
+\r
+       memcpy(d_block, blockData, 16);\r
+    AppendCrc14443a(d_block, 16);\r
+\r
+       ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);\r
+\r
+    len = ReaderReceive(receivedAnswer, receivedAnswerPar);    \r
+\r
+       if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
-        return 2;
-    }        
-    return 0;
-} 
-
-int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData)
-{
-    uint16_t len;
-       uint8_t d_block[8] = {0x00};
+                       Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);\r
+        return 2;\r
+    }        \r
+    return 0;\r
+} \r
+\r
+int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData)\r
+{\r
+    uint16_t len;\r
+       uint8_t d_block[8] = {0x00};\r
        uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
        uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
-
-    // command MIFARE_CLASSIC_WRITEBLOCK
-       d_block[0]= blockNo;
-       memcpy(d_block+1,blockData,4);
-       AppendCrc14443a(d_block, 6);
-
-    len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);
-
-    if (receivedAnswer[0] != 0x0A) {   //  0x0a - ACK
+\r
+    // command MIFARE_CLASSIC_WRITEBLOCK\r
+       d_block[0]= blockNo;\r
+       memcpy(d_block+1,blockData,4);\r
+       AppendCrc14443a(d_block, 6);\r
+\r
+    len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);\r
+\r
+    if (receivedAnswer[0] != 0x0A) {   //  0x0a - ACK\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);
-        return 1;
-    }
-\r    return 0;
-}
-
-int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) 
-{
+                       Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);\r
+        return 1;\r
+    }\r
+    return 0;\r
+}\r
+\r
+int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) \r
+{\r
        uint16_t len;   \r
        uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
        uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
@@ -486,24 +475,24 @@ int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
                return 1;\r
        }\r
 \r
-       return 0;
-}
-
-int mifare_ultra_halt(uint32_t uid)
-{
-       uint16_t len;
+       return 0;\r
+}\r
+\r
+int mifare_ultra_halt()\r
+{\r
+       uint16_t len;\r
        uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
        uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
-    
-       len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
-       if (len != 0) {
+    \r
+       len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);\r
+       if (len != 0) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("halt error. response len: %x", len);
-               return 1;
-       }
-       return 0;
-}
-
+                       Dbprintf("halt error. response len: %x", len);\r
+               return 1;\r
+       }\r
+       return 0;\r
+}\r
+\r
 \r
 // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards),\r
 // plus evtl. 8 sectors with 16 blocks each (4k cards)\r
@@ -525,9 +514,9 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo)
 }\r
 \r
 \r
-// work with emulator memory
-void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
-       uint8_t* emCARD = BigBuf_get_EM_addr();
+// work with emulator memory\r
+void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {\r
+       uint8_t* emCARD = BigBuf_get_EM_addr();\r
        memcpy(emCARD + blockNum * 16, data, blocksCount * 16);\r
 }\r
 \r
@@ -654,8 +643,8 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
        int len;\r
        // load key, keynumber\r
        uint8_t data[2]={0x0a, 0x00};\r
-       uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
-       uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
+       uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
+       uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
        \r
        len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL);\r
        if (len == 1) {\r
@@ -684,8 +673,8 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
        data[0] = 0xAF;\r
        memcpy(data+1,key,16);\r
        \r
-       uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
-       uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
+       uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
+       uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
        \r
        len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL);\r
        \r
@@ -706,4 +695,4 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
                return 0;\r
        }\r
        return 1;\r
-}
+}\r
index 195afa534b45e639e5488163e9068be41385c99d..1e2f8cc83e737c6a7e9729e5583e3ec73e61f4eb 100644 (file)
@@ -62,14 +62,14 @@ int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm
 int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);\r
 int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);
 int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); 
-int mifare_ultra_auth1(uint32_t cuid, uint8_t *blockData);\r
-int mifare_ultra_auth2(uint32_t cuid, uint8_t *key, uint8_t *blockData);\r
-int mifare_ultra_readblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
+int mifare_ultra_auth1(uint8_t *blockData);\r
+int mifare_ultra_auth2(uint8_t *key, uint8_t *blockData);\r
+int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
 int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
-int mifare_ultra_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
-int mifare_ultra_special_writeblock(uint32_t uid, uint8_t blockNo, uint8_t *blockData);
+int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
+int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData);
 int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); 
-int mifare_ultra_halt(uint32_t uid);
+int mifare_ultra_halt();
 \r
 // desfire\r
 int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
index d7332bda5682255bb03e4d306e87763d97218a51..3f5dc67676970783c0ea4e12699d5b2ec3e355ea 100644 (file)
@@ -9,7 +9,7 @@
 // with the linker script.
 //-----------------------------------------------------------------------------
 
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
 #include "apps.h"
 
 extern char __data_start__, __data_src_start__,  __data_end__, __bss_start__, __bss_end__;
index 74fba94b764db748cf6a377ba23b96f5d06bc304..c3d4d2c621d3d3252dd06415de5f6084204af37e 100644 (file)
@@ -8,7 +8,7 @@
 // Utility functions used in many places, not specific to any piece of code.
 //-----------------------------------------------------------------------------
 
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
 #include "util.h"
 #include "string.h"
 #include "apps.h"
index c2c81a9da1594ce4bb1205ac0e89dae9f954b085..7f4aa17811290496b314434b1e54b5bc082b6fb6 100644 (file)
@@ -217,7 +217,7 @@ static void flash_mode(int externally_entered)
 
                if(!externally_entered && !BUTTON_PRESS()) {
                        /* Perform a reset to leave flash mode */
-      usb_disable();
+               usb_disable();
                        LED_B_ON();
                        AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
                        for(;;);
index 81af01499fa75425b4495d557f4666bd4fa05cad..4fd41b46a170e821cec76275ef3b0aa76ae5774c 100644 (file)
@@ -12,9 +12,9 @@ CXX=g++
 VPATH = ../common
 OBJDIR = obj
 
-LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
+LDLIBS =  -L/mingw/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lm -lreadline -lpthread -lgdi32
 LDFLAGS = $(COMMON_FLAGS)
-CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
+CFLAGS = -std=c99 -I. -I../include -I../common -I/mingw/include -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
 LUAPLATFORM = generic
 
 ifneq (,$(findstring MINGW,$(platform)))
@@ -42,6 +42,15 @@ else
     LUAPLATFORM = linux
 endif
 
+# QT version,  4 or 5
+qtplatform = $(shell $(MOC) -v)
+ifneq (, $(findstring moc 5,$(qtplatform)))
+   CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets  -I/mingw/include
+   QTLDLIBS = -L$(QTDIR)/lib  -lQt5Core -lQt5Gui -lQt5Widgets 
+else
+   CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
+   QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
+endif
 
 ifneq ($(QTLDLIBS),)
     QTGUI = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o
@@ -68,6 +77,7 @@ CMDSRCS =     nonce2key/crapto1.c\
                        mifarehost.c\
                        crc.c \
                        crc16.c \
+                       crc64.c \
                        iso14443crc.c \
                        iso15693tools.c \
                        data.c \
@@ -84,6 +94,8 @@ CMDSRCS =     nonce2key/crapto1.c\
                        cmdhficlass.c \
                        cmdhfmf.c \
             cmdhfmfu.c \
+                       cmdhfmfdes.c \
+                       cmdhftopaz.c \
                        cmdhw.c \
                        cmdlf.c \
                        cmdlfio.c \
@@ -144,6 +156,17 @@ clean:
 tarbin: $(BINS)
        $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%)
 
+# must be run as root
+install_kext: Info.plist
+       mkdir -p /System/Library/Extensions/Proxmark3.kext/Contents
+       cp Info.plist /System/Library/Extensions/Proxmark3.kext/Contents
+       chown -R root:wheel /System/Library/Extensions/Proxmark3.kext
+       chmod 755 /System/Library/Extensions/Proxmark3.kext /System/Library/Extensions/Proxmark3.kext/Contents
+       chmod 644 /System/Library/Extensions/Proxmark3.kext/Contents/Info.plist
+       rm -rf /System/Library/Caches/com.apple.kext.caches
+       touch /System/Library/Extensions
+       @echo "*** You may need to reboot for the kext to take effect."
+
 lua_build:
        @echo Compiling liblua, using platform $(LUAPLATFORM)
        cd ../liblua && make $(LUAPLATFORM)
index f6b4b950a53933f44bf97973d4552146b878488c..f1dd9c7b83a6d2a46c7ef94d2c5b7ba41a59a113 100644 (file)
@@ -17,6 +17,7 @@ int CmdData(const char *Cmd);
 void printDemodBuff(void);
 void printBitStream(uint8_t BitStream[], uint32_t bitLen);
 void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
+
 int CmdAmp(const char *Cmd);
 int Cmdaskdemod(const char *Cmd);
 int CmdAskEM410xDemod(const char *Cmd);
@@ -78,6 +79,7 @@ int getSamples(const char *Cmd, bool silent);
 extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
 extern int DemodBufferLen;
 
+extern uint8_t g_debugMode;
 #define BIGBUF_SIZE 40000
 
 #endif
index 22063bbbe566e22e139524ad98ba2cc817c9b641..b4d3e531248724bebb31b99a245ecf1a766111f6 100644 (file)
@@ -23,6 +23,8 @@
 #include "cmdhficlass.h"
 #include "cmdhfmf.h"
 #include "cmdhfmfu.h"
+#include "cmdhfmfdes.h"
+#include "cmdhftopaz.h"
 #include "protocols.h"
 
 static int CmdHelp(const char *Cmd);
@@ -141,6 +143,26 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
        }
 }
 
+
+void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
+{
+       switch(cmd[0]) {
+               case TOPAZ_REQA                                         :snprintf(exp, size, "REQA");break;
+               case TOPAZ_WUPA                                         :snprintf(exp, size, "WUPA");break;
+               case TOPAZ_RID                                          :snprintf(exp, size, "RID");break;
+               case TOPAZ_RALL                                         :snprintf(exp, size, "RALL");break;
+               case TOPAZ_READ                                         :snprintf(exp, size, "READ");break;
+               case TOPAZ_WRITE_E                                      :snprintf(exp, size, "WRITE-E");break;
+               case TOPAZ_WRITE_NE                                     :snprintf(exp, size, "WRITE-NE");break;
+               case TOPAZ_RSEG                                         :snprintf(exp, size, "RSEG");break;
+               case TOPAZ_READ8                                        :snprintf(exp, size, "READ8");break;
+               case TOPAZ_WRITE_E8                                     :snprintf(exp, size, "WRITE-E8");break;
+               case TOPAZ_WRITE_NE8                            :snprintf(exp, size, "WRITE-NE8");break;
+               default:                            snprintf(exp,size,"?"); break;
+       }
+}
+
+
 /**
 06 00 = INITIATE
 0E xx = SELECT ID (xx = Chip-ID)
@@ -172,7 +194,34 @@ void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
 }
 
 /**
- * @brief iso14443B_CRC_Ok Checks CRC in command or response
+ * @brief iso14443A_CRC_check Checks CRC in command or response
+ * @param isResponse
+ * @param data
+ * @param len
+ * @return  0 : CRC-command, CRC not ok
+ *          1 : CRC-command, CRC ok
+ *          2 : Not crc-command
+ */
+
+uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
+{
+       uint8_t b1,b2;
+
+       if(len <= 2) return 2;
+
+       if(isResponse & (len < 6)) return 2;
+       
+       ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2);
+       if (b1 != data[len-2] || b2 != data[len-1]) {
+               return 0;
+       } else {
+               return 1;
+       }
+}
+
+
+/**
+ * @brief iso14443B_CRC_check Checks CRC in command or response
  * @param isResponse
  * @param data
  * @param len
@@ -190,8 +239,9 @@ uint8_t iso14443B_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
        ComputeCrc14443(CRC_14443_B, data, len-2, &b1, &b2);
        if(b1 != data[len-2] || b2 != data[len-1]) {
          return 0;
-       }
+       } else {
        return 1;
+       }
 }
 
 /**
@@ -255,11 +305,66 @@ uint8_t iclass_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
        }
 }
 
-uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
+
+bool is_last_record(uint16_t tracepos, uint8_t *trace, uint16_t traceLen)
 {
-       bool isResponse;
-       uint16_t duration, data_len, parity_len;
+       return(tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) >= traceLen);
+}
+
+
+bool next_record_is_response(uint16_t tracepos, uint8_t *trace)
+{
+       uint16_t next_records_datalen = *((uint16_t *)(trace + tracepos + sizeof(uint32_t) + sizeof(uint16_t)));
+       
+       return(next_records_datalen & 0x8000);
+}
+
+
+bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len)
+{
+
+#define MAX_TOPAZ_READER_CMD_LEN       16
 
+       uint32_t last_timestamp = timestamp + *duration;
+
+       if ((*data_len != 1) || (frame[0] == TOPAZ_WUPA) || (frame[0] == TOPAZ_REQA)) return false;
+
+       memcpy(topaz_reader_command, frame, *data_len);
+
+       while (!is_last_record(*tracepos, trace, traceLen) && !next_record_is_response(*tracepos, trace)) {
+               uint32_t next_timestamp = *((uint32_t *)(trace + *tracepos));
+               *tracepos += sizeof(uint32_t);
+               uint16_t next_duration = *((uint16_t *)(trace + *tracepos));
+               *tracepos += sizeof(uint16_t);
+               uint16_t next_data_len = *((uint16_t *)(trace + *tracepos)) & 0x7FFF;
+               *tracepos += sizeof(uint16_t);
+               uint8_t *next_frame = (trace + *tracepos);
+               *tracepos += next_data_len;
+               if ((next_data_len == 1) && (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN)) {
+                       memcpy(topaz_reader_command + *data_len, next_frame, next_data_len);
+                       *data_len += next_data_len;
+                       last_timestamp = next_timestamp + next_duration;
+               } else {
+                       // rewind and exit
+                       *tracepos = *tracepos - next_data_len - sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t);
+                       break;
+               }
+               uint16_t next_parity_len = (next_data_len-1)/8 + 1;
+               *tracepos += next_parity_len;
+       }
+
+       *duration = last_timestamp - timestamp;
+       
+       return true;
+}
+
+
+uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes)
+{
+       bool isResponse;
+       uint16_t data_len, parity_len;
+       uint32_t duration;
+       uint8_t topaz_reader_command[9];
        uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
        char explanation[30] = {0};
 
@@ -290,29 +395,31 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
        uint8_t *parityBytes = trace + tracepos;
        tracepos += parity_len;
 
+       if (protocol == TOPAZ && !isResponse) {
+               // topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each.
+               // merge them:
+               if (merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) {
+                       frame = topaz_reader_command;
+               }
+       }
+       
        //Check the CRC status
        uint8_t crcStatus = 2;
 
        if (data_len > 2) {
-               uint8_t b1, b2;
-               if(protocol == ICLASS)
-               {
+               switch (protocol) {
+                       case ICLASS:
                        crcStatus = iclass_CRC_check(isResponse, frame, data_len);
-
-               }else if (protocol == ISO_14443B)
-               {
+                               break;
+                       case ISO_14443B:
+                       case TOPAZ:
                        crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
-               }
-               else if (protocol == ISO_14443A){//Iso 14443a
-
-                       ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
-
-                       if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
-                               if(!(isResponse & (data_len < 6)))
-                               {
-                                               crcStatus = 0;
-                               }
-                       }
+                               break;
+                       case ISO_14443A:
+                               crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
+                               break;
+                       default: 
+                               break;
                }
        }
        //0 CRC-command, CRC not ok
@@ -334,19 +441,22 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
                uint8_t parityBits = parityBytes[j>>3];
                if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
                        snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
-
                } else {
                        snprintf(line[j/16]+(( j % 16) * 4),110, "%02x  ", frame[j]);
                }
 
        }
-       if(crcStatus == 1)
+
+       if (markCRCBytes) {
+               if(crcStatus == 0 || crcStatus == 1)
        {//CRC-command
-               char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1;
+                       char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4);
                (*pos1) = '[';
-               char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2;
-               (*pos2) = ']';
+                       char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4);
+                       sprintf(pos2, "%c", ']');
+               }
        }
+
        if(data_len == 0)
        {
                if(data_len == 0){
@@ -361,18 +471,19 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
 
        if(!isResponse)
        {
-               if(protocol == ICLASS)
-                       annotateIclass(explanation,sizeof(explanation),frame,data_len);
-               else if (protocol == ISO_14443A)
-                       annotateIso14443a(explanation,sizeof(explanation),frame,data_len);
-               else if(protocol == ISO_14443B)
-                       annotateIso14443b(explanation,sizeof(explanation),frame,data_len);
+               switch(protocol) {
+                       case ICLASS:            annotateIclass(explanation,sizeof(explanation),frame,data_len); break;
+                       case ISO_14443A:        annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break;
+                       case ISO_14443B:        annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break;
+                       case TOPAZ:                     annotateTopaz(explanation,sizeof(explanation),frame,data_len); break;
+                       default:                        break;
+               }
        }
 
        int num_lines = MIN((data_len - 1)/16 + 1, 16);
        for (int j = 0; j < num_lines ; j++) {
                if (j == 0) {
-                       PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s",
+                       PrintAndLog(" %10d | %10d | %s |%-64s | %s| %s",
                                (timestamp - first_timestamp),
                                (EndOfTransmissionTimestamp - first_timestamp),
                                (isResponse ? "Tag" : "Rdr"),
@@ -387,20 +498,16 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
                }
        }
 
-       if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
+       if (is_last_record(tracepos, trace, traceLen)) return traceLen;
        
-       bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
-
-       if (showWaitCycles && !isResponse && next_isResponse) {
+       if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
                uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
-               if (next_timestamp != 0x44444444) {
                        PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
                                (EndOfTransmissionTimestamp - first_timestamp),
                                (next_timestamp - first_timestamp),
                                "   ",
                                (next_timestamp - EndOfTransmissionTimestamp));
                }
-       }
 
        return tracepos;
 }
@@ -409,34 +516,35 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui
 int CmdHFList(const char *Cmd)
 {
        bool showWaitCycles = false;
+       bool markCRCBytes = false;
        char type[40] = {0};
        int tlen = param_getstr(Cmd,0,type);
-       char param = param_getchar(Cmd, 1);
+       char param1 = param_getchar(Cmd, 1);
+       char param2 = param_getchar(Cmd, 2);
        bool errors = false;
        uint8_t protocol = 0;
        //Validate params
-       if(tlen == 0)
-       {
+
+       if(tlen == 0) {
                errors = true;
        }
-       if(param == 'h' || (param !=0 && param != 'f'))
-       {
+
+       if(param1 == 'h'
+                       || (param1 != 0 && param1 != 'f' && param1 != 'c')
+                       || (param2 != 0 && param2 != 'f' && param2 != 'c')) {
                errors = true;
        }
-       if(!errors)
-       {
-               if(strcmp(type, "iclass") == 0)
-               {
+
+       if(!errors) {
+               if(strcmp(type, "iclass") == 0) {
                        protocol = ICLASS;
-               }else if(strcmp(type, "14a") == 0)
-               {
+               } else if(strcmp(type, "14a") == 0) {
                        protocol = ISO_14443A;
-               }
-               else if(strcmp(type, "14b") == 0)
-               {
+               } else if(strcmp(type, "14b") == 0)     {
                        protocol = ISO_14443B;
-               }else if(strcmp(type,"raw")== 0)
-               {
+               } else if(strcmp(type,"topaz")== 0) {
+                       protocol = TOPAZ;
+               } else if(strcmp(type,"raw")== 0) {
                        protocol = -1;//No crc, no annotations
                }else{
                        errors = true;
@@ -445,13 +553,15 @@ int CmdHFList(const char *Cmd)
 
        if (errors) {
                PrintAndLog("List protocol data in trace buffer.");
-               PrintAndLog("Usage:  hf list <protocol> [f]");
+               PrintAndLog("Usage:  hf list <protocol> [f][c]");
                PrintAndLog("    f      - show frame delay times as well");
+               PrintAndLog("    c      - mark CRC bytes");
                PrintAndLog("Supported <protocol> values:");
                PrintAndLog("    raw    - just show raw data without annotations");
                PrintAndLog("    14a    - interpret data as iso14443a communications");
                PrintAndLog("    14b    - interpret data as iso14443b communications");
                PrintAndLog("    iclass - interpret data as iclass communications");
+               PrintAndLog("    topaz  - interpret data as topaz communications");
                PrintAndLog("");
                PrintAndLog("example: hf list 14a f");
                PrintAndLog("example: hf list iclass");
@@ -459,10 +569,13 @@ int CmdHFList(const char *Cmd)
        }
 
 
-       if (param == 'f') {
+       if (param1 == 'f' || param2 == 'f') {
                showWaitCycles = true;
        }
 
+       if (param1 == 'c' || param2 == 'c') {
+               markCRCBytes = true;
+       }
 
        uint8_t *trace;
        uint16_t tracepos = 0;
@@ -491,12 +604,12 @@ int CmdHFList(const char *Cmd)
        PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
        PrintAndLog("iClass    - Timings are not as accurate");
        PrintAndLog("");
-       PrintAndLog("     Start |       End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |");
-       PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
+    PrintAndLog("      Start |        End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |");
+       PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
 
        while(tracepos < traceLen)
        {
-               tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
+               tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
        }
 
        free(trace);
@@ -514,9 +627,11 @@ static command_t CommandTable[] =
   {"legic",       CmdHFLegic,       0, "{ LEGIC RFIDs... }"},
   {"iclass",      CmdHFiClass,      1, "{ ICLASS RFIDs... }"},
   {"mf",               CmdHFMF,                1, "{ MIFARE RFIDs... }"},
-  {"mfu",                      CmdHFMFUltra,           1, "{ MIFARE Ultralight RFIDs... }"},
-  {"tune",        CmdHFTune,        0, "Continuously measure HF antenna tuning"},
-  {"list",       CmdHFList,         1, "List protocol data in trace buffer"},
+  {"mfu",                      CmdHFMFUltra,   1, "{ MIFARE Ultralight RFIDs... }"},
+  {"mfdes",                    CmdHFMFDes,             1, "{ MIFARE Desfire RFIDs... }"},
+  {"topaz",                    CmdHFTopaz,             1, "{ TOPAZ (NFC Type 1) RFIDs... }"},
+  {"tune",                     CmdHFTune,      0, "Continuously measure HF antenna tuning"},
+  {"list",                     CmdHFList,      1, "List protocol data in trace buffer"},
        {NULL, NULL, 0, NULL}
 };
 
index d36ebb8bee959220547577c0d31495b764630e3b..6fc4d2a06ba13906f35d248bfbe19df66444f87a 100644 (file)
@@ -140,7 +140,7 @@ int CmdHF14AReader(const char *Cmd)
        iso14a_card_select_t card;
        memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
 
-       uint64_t select_status = resp.arg[0];           // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
+       uint64_t select_status = resp.arg[0];           // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
        
        if(select_status == 0) {
                PrintAndLog("iso14443a card select failed");
@@ -152,6 +152,18 @@ int CmdHF14AReader(const char *Cmd)
                return 0;
        }
 
+       if(select_status == 3) {
+               PrintAndLog("Card doesn't support standard iso14443-3 anticollision");
+       PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
+               // disconnect
+               c.arg[0] = 0;
+               c.arg[1] = 0;
+               c.arg[2] = 0;
+               SendCommand(&c);
+               return 0;
+       }
+
+
        PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
        PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
        PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
@@ -497,16 +509,18 @@ int CmdHF14ASnoop(const char *Cmd) {
   return 0;
 }
 
+
 int CmdHF14ACmdRaw(const char *cmd) {
     UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
-    uint8_t reply=1;
-    uint8_t crc=0;
-    uint8_t power=0;
-    uint8_t active=0;
-    uint8_t active_select=0;
+    bool reply=1;
+    bool crc = FALSE;
+    bool power = FALSE;
+    bool active = FALSE;
+    bool active_select = FALSE;
     uint16_t numbits=0;
+       bool bTimeout = FALSE;
        uint32_t timeout=0;
-       uint8_t bTimeout=0;
+       bool topazmode = FALSE;
     char buf[5]="";
     int i=0;
     uint8_t data[USB_CMD_DATA_SIZE];
@@ -514,7 +528,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
        uint32_t temp;
 
     if (strlen(cmd)<2) {
-        PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-f] [-b] [-t] <number of bits> <0A 0B 0C ... hex>");
+        PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-a] [-t] <milliseconds> [-b] <number of bits>  <0A 0B 0C ... hex>");
         PrintAndLog("       -r    do not read response");
         PrintAndLog("       -c    calculate and append CRC");
         PrintAndLog("       -p    leave the signal field ON after receive");
@@ -522,9 +536,11 @@ int CmdHF14ACmdRaw(const char *cmd) {
         PrintAndLog("       -s    active signal field ON with select");
         PrintAndLog("       -b    number of bits to send. Useful for send partial byte");
                PrintAndLog("       -t    timeout in ms");
+               PrintAndLog("       -T    use Topaz protocol to send command");
         return 0;
     }
 
+
     // strip
     while (*cmd==' ' || *cmd=='\t') cmd++;
 
@@ -533,19 +549,19 @@ int CmdHF14ACmdRaw(const char *cmd) {
         if (cmd[i]=='-') {
             switch (cmd[i+1]) {
                 case 'r': 
-                    reply=0;
+                    reply = FALSE;
                     break;
                 case 'c':
-                    crc=1;
+                    crc = TRUE;
                     break;
                 case 'p':
-                    power=1;
+                    power = TRUE;
                     break;
                 case 'a':
-                    active=1;
+                    active = TRUE;
                     break;
                 case 's':
-                    active_select=1;
+                    active_select = TRUE;
                     break;
                 case 'b': 
                     sscanf(cmd+i+2,"%d",&temp);
@@ -555,13 +571,16 @@ int CmdHF14ACmdRaw(const char *cmd) {
                     i-=2;
                     break;
                                case 't':
-                                       bTimeout=1;
+                                       bTimeout = TRUE;
                                        sscanf(cmd+i+2,"%d",&temp);
                                        timeout = temp;
                                        i+=3;
                                        while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
                                        i-=2;
                                        break;
+                case 'T':
+                                       topazmode = TRUE;
+                                       break;
                 default:
                     PrintAndLog("Invalid option");
                     return 0;
@@ -591,10 +610,15 @@ int CmdHF14ACmdRaw(const char *cmd) {
         PrintAndLog("Invalid char on input");
         return 0;
     }
+
     if(crc && datalen>0 && datalen<sizeof(data)-2)
     {
         uint8_t first, second;
+               if (topazmode) {
+                       ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second);
+               } else {
         ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
+               }
         data[datalen++] = first;
         data[datalen++] = second;
     }
@@ -607,7 +631,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
     }
 
        if(bTimeout){
-           #define MAX_TIMEOUT 40542464        // (2^32-1) * (8*16) / 13560000Hz * 1000ms/s = 
+           #define MAX_TIMEOUT 40542464        // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
         c.arg[0] |= ISO14A_SET_TIMEOUT;
         if(timeout > MAX_TIMEOUT) {
             timeout = MAX_TIMEOUT;
@@ -615,11 +639,16 @@ int CmdHF14ACmdRaw(const char *cmd) {
         }
                c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
        }
+
     if(power)
         c.arg[0] |= ISO14A_NO_DISCONNECT;
+
     if(datalen>0)
         c.arg[0] |= ISO14A_RAW;
 
+       if(topazmode)
+               c.arg[0] |= ISO14A_TOPAZMODE;
+               
        // Max buffer is USB_CMD_DATA_SIZE
     c.arg[1] = (datalen & 0xFFFF) | (numbits << 16);
     memcpy(c.d.asBytes,data,datalen);
@@ -635,6 +664,7 @@ int CmdHF14ACmdRaw(const char *cmd) {
     return 0;
 }
 
+
 static void waitCmd(uint8_t iSelect)
 {
     uint8_t *recv;
index c3ff7dd6d3976574b668ab5ec13fa5c0b398f8b3..cff13b5b5cb2b6632e16d420e5ceaef38218a30f 100644 (file)
@@ -175,9 +175,9 @@ const productName uidmapping[] = {
        { 0xE02E000000000000LL, 16, "Broadcom Corporation USA" },
        { 0xE02F000000000000LL, 16, "MStar Semiconductor, Inc Taiwan, ROC" },
        { 0xE030000000000000LL, 16, "BeeDar Technology Inc. USA" },
-       { 0xE031000000000000LL, 16, " RFIDsec Denmark" },
-       { 0xE032000000000000LL, 16, " Schweizer Electronic AG Germany" },
-       { 0xE033000000000000LL, 16, " AMIC Technology Corp Taiwan" }, 
+       { 0xE031000000000000LL, 16, "RFIDsec Denmark" },
+       { 0xE032000000000000LL, 16, "Schweizer Electronic AG Germany" },
+       { 0xE033000000000000LL, 16, "AMIC Technology Corp Taiwan" }, 
        { 0xE034000000000000LL, 16, "Mikron JSC Russia" },
        { 0xE035000000000000LL, 16, "Fraunhofer Institute for Photonic Microsystems Germany" },
        { 0xE036000000000000LL, 16, "IDS Microchip AG Switzerland" },
@@ -668,9 +668,9 @@ int CmdHF15CmdRaw (const char *cmd) {
  */
 int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd[], int iso15cmdlen) {
        int temp;
-       uint8_t *req=c->d.asBytes;
+       uint8_t *req = c->d.asBytes;
        uint8_t uid[8] = {0x00};
-       uint32_t reqlen=0;
+       uint32_t reqlen = 0;
 
        // strip
        while (**cmd==' ' || **cmd=='\t') (*cmd)++;
@@ -763,10 +763,10 @@ int CmdHF15CmdSysinfo(const char *Cmd) {
        UsbCommand resp;
        uint8_t *recv;
        UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv?
-       uint8_t *req=c.d.asBytes;
-       int reqlen=0;
+       uint8_t *req = c.d.asBytes;
+       int reqlen = 0;
        char cmdbuf[100];
-       char *cmd=cmdbuf;
+       char *cmd = cmdbuf;
        char output[2048]="";
        int i;
        
@@ -782,13 +782,11 @@ int CmdHF15CmdSysinfo(const char *Cmd) {
                PrintAndLog("               s         selected tag");
                PrintAndLog("               u         unaddressed mode");
                PrintAndLog("               *         scan for tag");
-               PrintAndLog("           start#:       page number to start 0-255");  
-               PrintAndLog("           count#:       number of pages");  
                return 0;
        }       
        
        prepareHF15Cmd(&cmd, &c,(uint8_t[]){ISO15_CMD_SYSINFO},1);      
-       reqlen=c.arg[0];
+       reqlen = c.arg[0];
        
        reqlen=AddCrc(req,reqlen);
        c.arg[0]=reqlen;
diff --git a/client/cmdhfdes.c b/client/cmdhfdes.c
new file mode 100644 (file)
index 0000000..1876e5c
--- /dev/null
@@ -0,0 +1,69 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2012 nuit
+//
+// 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.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE DESfire commands
+//-----------------------------------------------------------------------------
+
+#include "cmdhfdes.h"
+#include "proxmark3.h"
+#include "cmdmain.h"
+
+static int CmdHelp(const char *Cmd);
+
+int CmdHFDESReader(const char *Cmd)
+{
+    UsbCommand c  ={CMD_MIFARE_DES_READER, {3, 0x60, 0}};
+    SendCommand(&c);
+
+    UsbCommand resp;
+       WaitForResponseTimeout(CMD_ACK,&resp,2000);
+    return 0;
+}  
+
+int CmdHFDESDbg(const char *Cmd)
+{
+    int dbgMode = param_get32ex(Cmd, 0, 0, 10);
+    if (dbgMode > 4) {
+        PrintAndLog("Max debud mode parameter is 4 \n");
+    }
+
+    if (strlen(Cmd) < 1 || !param_getchar(Cmd, 0) || dbgMode > 4) {
+        PrintAndLog("Usage:  hf des dbg  <debug level>");
+        PrintAndLog(" 0 - no debug messages");
+        PrintAndLog(" 1 - error messages");
+        PrintAndLog(" 2 - all messages");
+        PrintAndLog(" 4 - extended debug mode");
+        return 0;
+    }
+
+  UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}};
+  SendCommand(&c);
+
+  return 0;
+}
+
+static command_t CommandTable[] = 
+{
+    {"help",    CmdHelp,    1,  "This help"},
+    {"dbg",     CmdHFDESDbg, 0, "Set default debug mode"},
+    {"reader",  CmdHFDESReader, 0, "Reader"},
+  {NULL, NULL, 0, NULL}
+};
+
+int CmdHFDES(const char *Cmd)
+{
+    //flush
+    WaitForResponseTimeout(CMD_ACK,NULL,100);
+    CmdsParse(CommandTable, Cmd);
+    return 0;
+}
+
+int CmdHelp(const char *Cmd)
+{
+    CmdsHelp(CommandTable);
+    return 0;
+}
diff --git a/client/cmdhfdes.h b/client/cmdhfdes.h
new file mode 100644 (file)
index 0000000..e51797c
--- /dev/null
@@ -0,0 +1,27 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2012 nuit
+//
+// 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.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE DESfire commands
+//-----------------------------------------------------------------------------
+
+#ifndef CMDHFDES_H__
+#define CMDHFDES_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "proxmark3.h"
+#include "data.h"
+#include "ui.h"
+#include "cmdparser.h"
+#include "common.h"
+#include "util.h"
+int CmdHFDES(const char *Cmd);
+int CmdHFDESReader(const char *Cmd);
+int CmdHFDESDbg(const char *Cmd);
+#endif
index 3286ceb9cce45a2f9d9738219347044db63a303a..afcdb0fa040ae9b822376415c2167a0a07326eac 100644 (file)
@@ -13,7 +13,7 @@
 #include "proxmark3.h"
 #include "ui.h"
 #include "cmdparser.h"
-#include "common.h"
+#include "../include/common.h"
 #include "cmdmain.h"
 #include "sleep.h"
 #include "cmdhfepa.h"
index 468243fc594ace7a2d74e3beb334d1956216a18c..db563cadf7de224bf012bfc3c60e836d79ea511d 100644 (file)
@@ -1023,6 +1023,7 @@ int CmdHF14AMf1kSim(const char *Cmd)
                PrintAndLog("           x    (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");\r
                PrintAndLog("");\r
                PrintAndLog("           sample: hf mf sim u 0a0a0a0a ");\r
+               PrintAndLog("                 : hf mf sim u 0a0a0a0a i x");\r
                return 0;\r
        }\r
        uint8_t pnr = 0;\r
@@ -1499,7 +1500,7 @@ int CmdHF14AMfCSetUID(const char *Cmd)
 \r
 int CmdHF14AMfCSetBlk(const char *Cmd)\r
 {\r
-       uint8_t uid[8] = {0x00};\r
+       //uint8_t uid[8] = {0x00};\r
        uint8_t memBlock[16] = {0x00};\r
        uint8_t blockNo = 0;\r
        int res;\r
@@ -1521,7 +1522,8 @@ int CmdHF14AMfCSetBlk(const char *Cmd)
 \r
        PrintAndLog("--block number:%2d data:%s", blockNo, sprint_hex(memBlock, 16));\r
 \r
-       res = mfCSetBlock(blockNo, memBlock, uid, 0, CSETBLOCK_SINGLE_OPER);\r
+       //res = mfCSetBlock(blockNo, memBlock, uid, 0, CSETBLOCK_SINGLE_OPER);\r
+       res = mfCSetBlock(blockNo, memBlock, NULL, 0, CSETBLOCK_SINGLE_OPER);\r
        if (res) {\r
                        PrintAndLog("Can't write block. error=%d", res);\r
                        return 1;\r
index 22dfd4de5071b709d8f10f06ae3c36fd51030a28..45ba7cb1f261cfdf4d668ed20d5b80b64eedd1b6 100644 (file)
 #include <string.h>\r
 #include <ctype.h>\r
 #include "proxmark3.h"\r
-#include "iso14443crc.h"\r
+#include "../common/iso14443crc.h"\r
 #include "data.h"\r
 #include "ui.h"\r
 #include "cmdparser.h"\r
-#include "common.h"\r
+#include "../include/common.h"\r
 #include "util.h"\r
 #include "mifarehost.h"\r
 \r
@@ -53,5 +53,5 @@ int CmdHF14AMfCGetBlk(const char* cmd);
 int CmdHF14AMfCGetSc(const char* cmd);\r
 int CmdHF14AMfCLoad(const char* cmd);\r
 int CmdHF14AMfCSave(const char* cmd);\r
-\r
+int GetCardSize();\r
 #endif\r
diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c
new file mode 100644 (file)
index 0000000..c3cdde2
--- /dev/null
@@ -0,0 +1,686 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2014 Iceman
+//
+// 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.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE Desfire commands
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+//#include <openssl/des.h>
+#include "loclass/des.h"
+#include "cmdmain.h"
+#include "proxmark3.h"
+#include "../include/common.h"
+#include "../include/mifare.h"
+#include "../common/iso14443crc.h"
+#include "data.h"
+#include "ui.h"
+#include "cmdparser.h"
+#include "util.h"
+#include "cmdhfmfdes.h"
+
+uint8_t CMDPOS = 0;
+uint8_t LENPOS = 1;
+
+uint8_t key_zero_data[16] = { 0x00 };
+uint8_t key_ones_data[16] = { 0x01 };
+uint8_t key_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
+uint8_t key_picc_data[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
+
+static int CmdHelp(const char *Cmd);
+static void xor(unsigned char * dst, unsigned char * src, size_t len);
+static int32_t le24toh (uint8_t data[3]);
+
+
+int CmdHF14ADesWb(const char *Cmd)
+{
+/*     uint8_t blockNo = 0;
+       uint8_t keyType = 0;
+       uint8_t key[6] = {0, 0, 0, 0, 0, 0};
+       uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+       
+       char cmdp       = 0x00;
+
+       if (strlen(Cmd)<3) {
+               PrintAndLog("Usage:  hf mf wrbl    <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
+               PrintAndLog("        sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
+               return 0;
+       }       
+
+       blockNo = param_get8(Cmd, 0);
+       cmdp = param_getchar(Cmd, 1);
+       if (cmdp == 0x00) {
+               PrintAndLog("Key type must be A or B");
+               return 1;
+       }
+       if (cmdp != 'A' && cmdp != 'a') keyType = 1;
+       if (param_gethex(Cmd, 2, key, 12)) {
+               PrintAndLog("Key must include 12 HEX symbols");
+               return 1;
+       }
+       if (param_gethex(Cmd, 3, bldata, 32)) {
+               PrintAndLog("Block data must include 32 HEX symbols");
+               return 1;
+       }
+       PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
+       PrintAndLog("--data: %s", sprint_hex(bldata, 16));
+       
+  UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
+       memcpy(c.d.asBytes, key, 6);
+       memcpy(c.d.asBytes + 10, bldata, 16);
+  SendCommand(&c);
+
+       UsbCommand resp;
+       if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+               uint8_t isOK  = resp.arg[0] & 0xff;
+               PrintAndLog("isOk:%02x", isOK);
+       } else {
+               PrintAndLog("Command execute timeout");
+       }
+ */
+       return 0;
+}
+
+int CmdHF14ADesRb(const char *Cmd)
+{
+       // uint8_t blockNo = 0;
+       // uint8_t keyType = 0;
+       // uint8_t key[6] = {0, 0, 0, 0, 0, 0};
+       
+       // char cmdp    = 0x00;
+
+
+       // if (strlen(Cmd)<3) {
+               // PrintAndLog("Usage:  hf mf rdbl    <block number> <key A/B> <key (12 hex symbols)>");
+               // PrintAndLog("        sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
+               // return 0;
+       // }    
+       
+       // blockNo = param_get8(Cmd, 0);
+       // cmdp = param_getchar(Cmd, 1);
+       // if (cmdp == 0x00) {
+               // PrintAndLog("Key type must be A or B");
+               // return 1;
+       // }
+       // if (cmdp != 'A' && cmdp != 'a') keyType = 1;
+       // if (param_gethex(Cmd, 2, key, 12)) {
+               // PrintAndLog("Key must include 12 HEX symbols");
+               // return 1;
+       // }
+       // PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
+       
+  // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
+       // memcpy(c.d.asBytes, key, 6);
+  // SendCommand(&c);
+
+       // UsbCommand resp;
+       // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+               // uint8_t                isOK  = resp.arg[0] & 0xff;
+               // uint8_t              * data  = resp.d.asBytes;
+
+               // if (isOK)
+                       // PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
+               // else
+                       // PrintAndLog("isOk:%02x", isOK);
+       // } else {
+               // PrintAndLog("Command execute timeout");
+       // }
+
+  return 0;
+}
+
+int CmdHF14ADesInfo(const char *Cmd){
+
+       UsbCommand c = {CMD_MIFARE_DESFIRE_INFO};
+    SendCommand(&c);
+       UsbCommand resp;
+       
+       if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+               PrintAndLog("Command execute timeout");
+               return 0;
+       }
+       uint8_t isOK  = resp.arg[0] & 0xff;
+       if ( !isOK ){
+               PrintAndLog("Command unsuccessful");
+               return 0;
+       }  
+       PrintAndLog("");
+       PrintAndLog("-- Desfire Information --------------------------------------");
+       PrintAndLog("-------------------------------------------------------------");
+       PrintAndLog("  UID                : %s",sprint_hex(resp.d.asBytes, 7));
+       PrintAndLog("  Batch number       : %s",sprint_hex(resp.d.asBytes+28,5));
+       PrintAndLog("  Production date    : week %02x, 20%02x",resp.d.asBytes[33], resp.d.asBytes[34]);
+       PrintAndLog("  -----------------------------------------------------------");
+       PrintAndLog("  Hardware Information");
+       PrintAndLog("      Vendor Id      : %s", GetVendorStr(resp.d.asBytes[7]));
+       PrintAndLog("      Type           : 0x%02X",resp.d.asBytes[8]);
+       PrintAndLog("      Subtype        : 0x%02X",resp.d.asBytes[9]);
+       PrintAndLog("      Version        : %d.%d",resp.d.asBytes[10], resp.d.asBytes[11]);
+       PrintAndLog("      Storage size   : %s",GetCardSizeStr(resp.d.asBytes[12]));
+       PrintAndLog("      Protocol       : %s",GetProtocolStr(resp.d.asBytes[13]));
+       PrintAndLog("  -----------------------------------------------------------");
+       PrintAndLog("  Software Information");
+       PrintAndLog("      Vendor Id      : %s",GetVendorStr(resp.d.asBytes[14]));
+       PrintAndLog("      Type           : 0x%02X",resp.d.asBytes[15]);
+       PrintAndLog("      Subtype        : 0x%02X",resp.d.asBytes[16]);
+       PrintAndLog("      Version        : %d.%d",resp.d.asBytes[17], resp.d.asBytes[18]);
+       PrintAndLog("      storage size   : %s", GetCardSizeStr(resp.d.asBytes[19]));
+       PrintAndLog("      Protocol       : %s", GetProtocolStr(resp.d.asBytes[20]));
+       PrintAndLog("-------------------------------------------------------------");
+       
+       // Master Key settings
+       GetKeySettings(NULL);
+       
+       // Free memory on card
+       c.cmd = CMD_MIFARE_DESFIRE;
+       c.arg[0] = (INIT | DISCONNECT);
+       c.arg[1] = 0x01;
+       c.d.asBytes[0] = GET_FREE_MEMORY;
+    SendCommand(&c);
+       if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+               return 0;
+       }  
+       
+       uint8_t tmp[3];
+       memcpy(tmp, resp.d.asBytes+3,3); 
+
+       PrintAndLog("   Available free memory on card       : %d bytes", le24toh( tmp ));
+       PrintAndLog("-------------------------------------------------------------");
+
+       /*
+               Card Master key (CMK)        0x00 AID = 00 00 00 (card level)
+               Application Master Key (AMK) 0x00 AID != 00 00 00
+               Application keys (APK)       0x01-0x0D
+               Application free             0x0E
+               Application never            0x0F
+               
+               ACCESS RIGHTS:
+               keys 0,1,2,3     C
+               keys 4,5,6,7     RW
+               keys 8,9,10,11   W
+               keys 12,13,14,15 R
+       
+       */
+       
+    return 1;
+}
+
+char * GetVendorStr( uint8_t id){
+       static char buf[30];
+       char *retStr = buf;
+       
+       if ( id == 0x04 )
+               sprintf(retStr, "0x%02X (NXP)",id);
+       else 
+               sprintf(retStr,"0x%02X (Unknown)",id);
+       return buf;
+}
+
+/*
+  The 7 MSBits (= n) code the storage size itself based on 2^n, 
+  the LSBit is set to '0' if the size is exactly 2^n
+       and set to '1' if the storage size is between 2^n and 2^(n+1). 
+       For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
+*/
+char * GetCardSizeStr( uint8_t fsize ){
+       static char buf[30];
+       char *retStr = buf;
+
+       uint16_t usize = 1 << ((fsize >>1) + 1);
+       uint16_t lsize = 1 << (fsize >>1);
+       
+       // is  LSB set?
+       if (  fsize & 1 )
+               sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize);
+       else 
+               sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize);             
+       return buf;
+}
+
+char * GetProtocolStr(uint8_t id){
+
+       static char buf[30];
+       char *retStr = buf;
+
+       if ( id == 0x05)
+               sprintf(retStr,"0x%02X (ISO 14443-3, 14443-4)", id);
+       else
+               sprintf(retStr,"0x%02X (Unknown)", id); 
+       return buf;
+}
+
+void GetKeySettings( uint8_t *aid){
+       
+       char messStr[512] = {0x00};
+       char *str = messStr;
+       uint8_t isOK = 0;
+       uint32_t options = NONE;
+       UsbCommand c;
+       UsbCommand resp;
+
+       //memset(messStr, 0x00, 512);
+       
+       c.cmd = CMD_MIFARE_DESFIRE;
+       
+       if ( aid == NULL ){
+               PrintAndLog(" CMK - PICC, Card Master Key settings ");
+               PrintAndLog("");
+               c.arg[CMDPOS] = (INIT | DISCONNECT);
+               c.arg[LENPOS] =  0x01;
+               c.d.asBytes[0] = GET_KEY_SETTINGS;  // 0x45
+               SendCommand(&c);
+               if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}  
+               isOK  = resp.arg[0] & 0xff;
+               if ( !isOK ){
+                       PrintAndLog("   Can't select master application");      
+                       return;
+               }       
+
+               str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";     
+               PrintAndLog("   [0x08] Configuration changeable       : %s", str);
+               str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
+               PrintAndLog("   [0x04] CMK required for create/delete : %s",str);
+               str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
+               PrintAndLog("   [0x02] Directory list access with CMK : %s",str);
+               str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
+               PrintAndLog("   [0x01] CMK is changeable              : %s", str);
+                       
+               c.arg[LENPOS] = 0x02; //LEN
+               c.d.asBytes[0] = GET_KEY_VERSION; //0x64
+               c.d.asBytes[1] = 0x00;
+               SendCommand(&c);
+               if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {
+                       return;
+               }
+               isOK  = resp.arg[0] & 0xff;
+               if ( !isOK ){
+                       PrintAndLog("   Can't read key-version");
+                       return;
+               }
+               PrintAndLog("");
+               PrintAndLog("   Max number of keys       : %d", resp.d.asBytes[4]);
+               PrintAndLog("   Master key Version       : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
+               PrintAndLog("   ----------------------------------------------------------");
+               
+               c.arg[LENPOS] = 0x02; //LEN
+               c.d.asBytes[0] = AUTHENTICATE; //0x0A
+               c.d.asBytes[1] = 0x00; // KEY 0
+               SendCommand(&c);
+               if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
+               isOK  = resp.d.asBytes[2] & 0xff;
+               PrintAndLog("   [0x0A] Authenticate      : %s", ( isOK==0xAE ) ? "NO":"YES");
+
+               c.d.asBytes[0] = AUTHENTICATE_ISO; //0x1A
+               SendCommand(&c);
+               if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
+               isOK  = resp.d.asBytes[2] & 0xff;
+               PrintAndLog("   [0x1A] Authenticate ISO  : %s", ( isOK==0xAE ) ? "NO":"YES");
+               
+               c.d.asBytes[0] = AUTHENTICATE_AES; //0xAA
+               SendCommand(&c);
+               if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
+               isOK  = resp.d.asBytes[2] & 0xff;
+               PrintAndLog("   [0xAA] Authenticate AES  : %s", ( isOK==0xAE ) ? "NO":"YES");
+               PrintAndLog("");
+               PrintAndLog("   ----------------------------------------------------------");
+               
+       } else {
+               PrintAndLog(" AMK - Application Master Key settings");
+               
+               // SELECT AID
+               c.arg[0] = (INIT | CLEARTRACE);
+               c.arg[LENPOS] = 0x04;
+               c.d.asBytes[0] = SELECT_APPLICATION;  // 0x5a
+               memcpy(c.d.asBytes+1, aid, 3);
+               SendCommand(&c);
+               
+               if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+                       PrintAndLog("   Timed-out");
+                       return;
+               } 
+               isOK  = resp.arg[0] & 0xff;
+               if ( !isOK ){
+                       PrintAndLog("   Can't select AID: %s",sprint_hex(aid,3));       
+                       return;
+               }               
+               
+               // KEY SETTINGS
+               options = NONE;
+               c.arg[0] = options;
+               c.arg[LENPOS] = 0x01;
+               c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45              
+               SendCommand(&c);
+               if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+                       return;
+               }
+               isOK  = resp.arg[0] & 0xff;
+               if ( !isOK ){
+                       PrintAndLog("   Can't read Application Master key settings");
+               } else {
+                       // Access rights.
+                       uint8_t rights = (resp.d.asBytes[3] >> 4 && 0xff);
+                       switch (rights){
+                               case 0x00:
+                                       str = "AMK authentication is necessary to change any key (default)";
+                                       break;
+                               case 0x0e:
+                                       str = "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
+                                       break;
+                               case 0x0f:
+                                       str = "All keys (except AMK,see Bit0) within this application are frozen";
+                                       break;
+                               default:
+                                       str = "Authentication with the specified key is necessary to change any ley. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed.";
+                                       break;
+                       }
+                       PrintAndLog("Changekey Access rights");
+                       PrintAndLog("-- %s",str);
+                       PrintAndLog("");        
+                       // same as CMK
+                       str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";     
+                       PrintAndLog("   0x08 Configuration changeable       : %s", str);
+                       str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
+                       PrintAndLog("   0x04 AMK required for create/delete : %s",str);
+                       str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
+                       PrintAndLog("   0x02 Directory list access with AMK : %s",str);
+                       str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
+                       PrintAndLog("   0x01 AMK is changeable              : %s", str);
+               }
+               
+               // KEY VERSION  - AMK 
+               c.arg[0] = NONE;
+               c.arg[LENPOS] = 0x02;
+               c.d.asBytes[0] = GET_KEY_VERSION; //0x64
+               c.d.asBytes[1] = 0x00;
+               SendCommand(&c);
+               if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+                       PrintAndLog("   Timed-out");
+                       return;
+               }
+               
+               int numOfKeys;
+               
+               isOK  = resp.arg[0] & 0xff;
+               if ( !isOK ){
+                       PrintAndLog("   Can't read Application Master key version. Trying all keys");
+                       numOfKeys = MAX_NUM_KEYS;
+               }
+               else{
+                       numOfKeys = resp.d.asBytes[4];
+                       PrintAndLog("");
+                       PrintAndLog("     Max number of keys  : %d", numOfKeys );
+                       PrintAndLog("     Application Master key Version  : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
+                       PrintAndLog("-------------------------------------------------------------");                   
+               }
+               
+               // LOOP over numOfKeys that we got before. 
+               // From 0x01 to numOfKeys.  We already got 0x00. (AMK)
+               for(int i=0x01; i<=0x0f; ++i){
+                                       
+               }
+               
+               
+       }
+}
+
+int CmdHF14ADesEnumApplications(const char *Cmd){
+       
+       uint8_t isOK = 0x00;
+       uint8_t aid[3];
+       uint32_t options = (INIT | DISCONNECT);
+       
+       UsbCommand c = {CMD_MIFARE_DESFIRE, {options , 0x01 }};
+       c.d.asBytes[0] = GET_APPLICATION_IDS;  //0x6a
+       
+    SendCommand(&c);
+       UsbCommand resp;
+               
+       if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+               return 0;
+       }  
+       isOK  = resp.arg[0] & 0xff;
+       if ( !isOK ){
+               PrintAndLog("Command unsuccessful");
+               return 0;
+       } 
+       PrintAndLog("");        
+       PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
+       PrintAndLog("-------------------------------------------------------------");
+
+       UsbCommand respAid;
+       UsbCommand respFiles;
+       
+       uint8_t num = 0;
+       int max = resp.arg[1] -3 -2;
+       
+       for(int i=3; i<=max; i+=3){
+               PrintAndLog(" Aid %d : %02X %02X %02X ",num ,resp.d.asBytes[i],resp.d.asBytes[i+1],resp.d.asBytes[i+2]);
+               num++;
+               
+               aid[0] = resp.d.asBytes[i];
+               aid[1] = resp.d.asBytes[i+1];
+               aid[2] = resp.d.asBytes[i+2];
+               GetKeySettings(aid);
+               
+               // Select Application
+               c.arg[CMDPOS] = INIT;
+               c.arg[LENPOS] = 0x04; 
+               c.d.asBytes[0] = SELECT_APPLICATION;  // 0x5a
+               c.d.asBytes[1] = resp.d.asBytes[i];
+               c.d.asBytes[2] = resp.d.asBytes[i+1];           
+               c.d.asBytes[3] = resp.d.asBytes[i+2];
+               SendCommand(&c);
+               
+               if (!WaitForResponseTimeout(CMD_ACK,&respAid,1500) ) {
+                       PrintAndLog("   Timed-out");
+                       continue;
+               } 
+               isOK  = respAid.d.asBytes[2] & 0xff;
+               if ( isOK != 0x00 ){
+                       PrintAndLog("   Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3));  
+                       continue;
+               }
+       
+               // Get File IDs
+               c.arg[CMDPOS] = NONE;
+               c.arg[LENPOS] = 0x01;
+               c.d.asBytes[0] = GET_FILE_IDS; // 0x6f
+               SendCommand(&c);
+               
+               if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
+                       PrintAndLog("   Timed-out");
+                       continue;
+               } else {
+                       isOK  = respFiles.d.asBytes[2] & 0xff;
+                       if ( !isOK ){
+                               PrintAndLog("   Can't get file ids ");
+                       } else {                        
+                               int respfileLen = resp.arg[1]-3-2;                      
+                               for (int j=0; j< respfileLen; ++j){
+                                       PrintAndLog("   Fileid %d :", resp.d.asBytes[j+3]);
+                               }
+                       }
+               }
+               
+               // Get ISO File IDs
+               c.arg[CMDPOS] = DISCONNECT;
+               c.arg[LENPOS] = 0x01;
+               c.d.asBytes[0] = GET_ISOFILE_IDS; // 0x61
+               SendCommand(&c);
+               
+               if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
+                       PrintAndLog("   Timed-out");
+                       continue;
+               } else {
+                       isOK  = respFiles.d.asBytes[2] & 0xff;
+                       if ( !isOK ){
+                               PrintAndLog("   Can't get ISO file ids ");
+                       } else {                        
+                               int respfileLen = resp.arg[1]-3-2;                      
+                               for (int j=0; j< respfileLen; ++j){
+                                       PrintAndLog(" ISO  Fileid %d :", resp.d.asBytes[j+3]);
+                               }
+                       }
+               }
+               
+               
+       }
+       PrintAndLog("-------------------------------------------------------------");
+       
+       
+       return 1;
+}
+
+// MIAFRE DesFire Authentication
+//
+#define BUFSIZE 256 
+int CmdHF14ADesAuth(const char *Cmd){
+    
+       // NR  DESC             KEYLENGHT
+       // ------------------------
+       // 1 = DES              8
+       // 2 = 3DES             16
+       // 3 = 3K 3DES  24
+       // 4 = AES              16
+
+       uint8_t keylength = 8;
+       unsigned char key[24];  
+       
+    if (strlen(Cmd)<3) {
+        PrintAndLog("Usage:  hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
+               PrintAndLog("               Auth modes");
+               PrintAndLog("                 1 = normal, 2 = iso, 3 = aes");
+               PrintAndLog("               Crypto");
+               PrintAndLog("                 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
+               PrintAndLog("");
+        PrintAndLog("        sample: hf mfdes auth 1 1 0 11223344");
+               PrintAndLog("        sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
+        return 0;
+    } 
+       uint8_t cmdAuthMode     = param_get8(Cmd,0);
+       uint8_t cmdAuthAlgo     = param_get8(Cmd,1);
+       uint8_t cmdKeyNo        = param_get8(Cmd,2);
+       
+       switch (cmdAuthMode)
+       {
+               case 1: 
+                       if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2) {
+                               PrintAndLog("Crypto algo not valid for the auth mode");
+                               return 1;
+                       }
+                       break;
+               case 2:
+                       if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) {
+                               PrintAndLog("Crypto algo not valid for the auth mode");
+                               return 1;
+                       }
+                       break;
+               case 3:
+                       if ( cmdAuthAlgo != 4) {
+                               PrintAndLog("Crypto algo not valid for the auth mode");
+                               return 1;
+                       }
+                       break;
+               default:
+                       PrintAndLog("Wrong Auth mode");
+                       return 1;
+                       break;
+       }
+       
+       switch (cmdAuthAlgo){
+               case 2: 
+                       keylength = 16;
+                       PrintAndLog("3DES selected");
+                       break;
+               case 3: 
+                       keylength = 24;
+                       PrintAndLog("3 key 3DES selected");
+                       break;
+               case 4:
+                       keylength = 16;
+                       PrintAndLog("AES selected");
+                       break;
+               default:
+                       cmdAuthAlgo = 1;
+                       keylength = 8;
+                       PrintAndLog("DES selected");
+                       break;
+       }
+
+       // key
+       if (param_gethex(Cmd, 3, key, keylength*2)) {
+               PrintAndLog("Key must include %d HEX symbols", keylength);
+               return 1;
+       }
+       // algo, nyckellängd, 
+       UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }};
+       
+       c.d.asBytes[0] = keylength;
+       memcpy(c.d.asBytes+1, key, keylength);
+       
+    SendCommand(&c);
+       UsbCommand resp;
+       
+       if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) {
+               PrintAndLog("Client command execute timeout");
+               return 0;
+       }  
+
+       uint8_t isOK  = resp.arg[0] & 0xff;
+       if ( isOK) {
+               uint8_t * data= resp.d.asBytes;
+               
+               PrintAndLog("  Key        :%s",sprint_hex(key, keylength));
+               PrintAndLog("  SESSION    :%s",sprint_hex(data, keylength));
+               PrintAndLog("-------------------------------------------------------------");
+               //PrintAndLog("  Expected   :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
+       } else{
+               PrintAndLog("Client command failed.");
+       }
+       PrintAndLog("-------------------------------------------------------------");   
+    return 1;
+}
+
+
+static void xor(unsigned char * dst, unsigned char * src, size_t len) {
+   for( ; len > 0; len--,dst++,src++)
+       *dst ^= *src;
+}
+
+static int32_t le24toh (uint8_t data[3]) {
+    return (data[2] << 16) | (data[1] << 8) | data[0];
+}
+
+static command_t CommandTable[] =
+{
+  {"help",             CmdHelp,                                        1, "This help"},
+  {"auth",             CmdHF14ADesAuth,                        0, "Tries a MIFARE DesFire Authentication"},
+  {"rb",               CmdHF14ADesRb,                          0, "Read MIFARE DesFire block"},
+  {"wb",               CmdHF14ADesWb,                          0, "write MIFARE DesFire block"},
+  {"info",             CmdHF14ADesInfo,                        0, "Get MIFARE DesFire information"},
+  {"enum",             CmdHF14ADesEnumApplications,0, "Tries enumerate all applications"},
+  {NULL, NULL, 0, NULL}
+};
+
+int CmdHFMFDes(const char *Cmd)
+{
+   // flush
+   WaitForResponseTimeout(CMD_ACK,NULL,100);
+   CmdsParse(CommandTable, Cmd);
+  return 0;
+}
+
+int CmdHelp(const char *Cmd)
+{
+  CmdsHelp(CommandTable);
+  return 0;
+}
+
+
diff --git a/client/cmdhfmfdes.h b/client/cmdhfmfdes.h
new file mode 100644 (file)
index 0000000..6ebc98a
--- /dev/null
@@ -0,0 +1,75 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2014 Iceman
+//
+// 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.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE Desfire commands
+//-----------------------------------------------------------------------------
+
+int CmdHFMFDes(const char *Cmd);
+int CmdHF14ADesAuth(const char* cmd);
+int CmdHF14ADesRb(const char* cmd);
+int CmdHF14ADesWb(const char* cmd);
+int CmdHF14ADesInfo(const char *Cmd);
+int CmdHF14ADesEnumApplications(const char *Cmd);
+
+char * GetCardSizeStr( uint8_t fsize );
+char * GetVendorStr( uint8_t id);
+char * GetProtocolStr(uint8_t id);
+void GetKeySettings( uint8_t * aid);
+
+// Command options for Desfire behavior.
+enum  {
+ NONE          =       0x00,
+ INIT          =       0x01,
+ DISCONNECT =  0x02,
+ CLEARTRACE    =       0x04,
+ BAR           =       0x08,
+} CmdOptions ;
+
+
+#define  CREATE_APPLICATION                     0xca
+#define  DELETE_APPLICATION                     0xda
+#define  GET_APPLICATION_IDS                    0x6a
+#define      SELECT_APPLICATION                 0x5a
+#define      FORMAT_PICC                                0xfc
+#define      GET_VERSION                                0x60
+#define      READ_DATA                                          0xbd
+#define      WRITE_DATA                                         0x3d
+#define      GET_VALUE                                          0x6c
+#define      CREDIT                                     0x0c
+#define      DEBIT                                              0xdc
+#define      LIMITED_CREDIT                     0x1c
+#define      WRITE_RECORD                               0x3b
+#define      READ_RECORDS                               0xbb
+#define     CLEAR_RECORD_FILE                   0xeb
+#define      COMMIT_TRANSACTION                 0xc7
+#define      ABORT_TRANSACTION                          0xa7
+#define      GET_FREE_MEMORY             0x6e
+#define        GET_FILE_IDS                             0x6f
+#define        GET_ISOFILE_IDS                          0x61
+#define     GET_FILE_SETTINGS                   0xf5
+#define     CHANGE_FILE_SETTINGS                0x5f
+#define     CREATE_STD_DATA_FILE                0xcd
+#define     CREATE_BACKUP_DATA_FILE     0xcb
+#define     CREATE_VALUE_FILE                   0xcc
+#define     CREATE_LINEAR_RECORD_FILE   0xc1
+#define     CREATE_CYCLIC_RECORD_FILE   0xc0
+#define     DELETE_FILE                                 0xdf
+#define     AUTHENTICATE                                0x0a  // AUTHENTICATE_NATIVE
+#define        AUTHENTICATE_ISO                         0x1a  // AUTHENTICATE_STANDARD
+#define        AUTHENTICATE_AES                         0xaa
+#define     CHANGE_KEY_SETTINGS                 0x54
+#define     GET_KEY_SETTINGS                    0x45
+#define     CHANGE_KEY                                          0xc4
+#define     GET_KEY_VERSION                     0x64
+#define     AUTHENTICATION_FRAME                0xAF
+
+#define MAX_NUM_KEYS 0x0F
+#define MAX_APPLICATION_COUNT 28
+#define MAX_FILE_COUNT 32
+#define MAX_FRAME_SIZE 60
+#define NOT_YET_AUTHENTICATED 255
+#define FRAME_PAYLOAD_SIZE (MAX_FRAME_SIZE - 5)
\ No newline at end of file
diff --git a/client/cmdhfmfdesfire.c b/client/cmdhfmfdesfire.c
new file mode 100644 (file)
index 0000000..f2c53db
--- /dev/null
@@ -0,0 +1,250 @@
+//-----------------------------------------------------------------------------
+// Copyright (C) 2014 Andy Davies
+//
+// 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.
+//-----------------------------------------------------------------------------
+// High frequency MIFARE commands
+//-----------------------------------------------------------------------------
+
+#include "cmdhfmf.h"
+#include "util.h"
+#include <openssl/des.h>
+#include <openssl/aes.h>
+
+static int CmdHelp(const char *Cmd);
+
+//DESFIRE
+// Reader 2 Card : 020A, key (1 byte), CRC1 CRC2 ; auth (020a00)
+// Card 2 Reader : 02AF, 8 Bytes(b0), CRC1 CRC2
+// Reader 2 Card : 03AF, 8 Bytes(b1),8 bytes(b2), CRC1 CRC2
+// Card 2 Reader : 0300, 8 bytes(b3), CRC1 CRC2 ; success
+
+//send 020A00, receive enc(nc)
+
+//02AE = error
+//receive b3=enc(r4)
+//r5=dec(b3)
+//n'r=rol(r5)
+//verify n'r=nr
+
+int CmdHF14AMfDESAuth(const char *Cmd){
+        
+    uint8_t blockNo = 0;
+    //keyNo=0;
+    uint32_t cuid=0;
+    uint8_t reply[16];
+    //DES_cblock r1_b1;
+    uint8_t b1[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    uint8_t b2[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    DES_cblock nr,  b0, r1, r0;
+    
+    
+    uint8_t key[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    //DES_cblock iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    DES_key_schedule ks1;
+    DES_cblock key1;
+
+    if (strlen(Cmd)<1) {
+        PrintAndLog("Usage:  hf desfire des-auth k <key number>");
+        PrintAndLog("        sample: hf desfire des-auth k 0");
+        return 0;
+    } 
+    
+    //Change key to user defined one
+    
+    memcpy(key1,key,8);
+    //memcpy(key2,key+8,8);
+    DES_set_key((DES_cblock *)key1,&ks1);
+    //DES_set_key((DES_cblock *)key2,&ks2);
+        
+    //Auth1
+    UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}};
+    SendCommand(&c);
+    UsbCommand resp;
+    if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+        uint8_t isOK  = resp.arg[0] & 0xff;
+               cuid  = resp.arg[1];
+        uint8_t * data= resp.d.asBytes;
+
+         if (isOK){
+             PrintAndLog("enc(nc)/b0:%s", sprint_hex(data+2,8));
+             memcpy(b0,data+2,8);
+       }
+    } else {
+        PrintAndLog("Command execute timeout");
+    }
+       
+    //Do crypto magic
+    DES_random_key(&nr);
+    //b1=dec(nr)
+    //r0=dec(b0)
+    DES_ecb_encrypt(&nr,&b1,&ks1,0);
+    DES_ecb_encrypt(&b0,&r0,&ks1,0);
+    //PrintAndLog("b1:%s",sprint_hex(b1, 8));
+    PrintAndLog("r0:%s",sprint_hex(r0, 8));
+    //r1=rol(r0)
+    memcpy(r1,r0,8);
+    rol(r1,8);
+    PrintAndLog("r1:%s",sprint_hex(r1, 8));
+    for(int i=0;i<8;i++){   
+      b2[i]=(r1[i] ^ b1[i]);
+    }
+    DES_ecb_encrypt(&b2,&b2,&ks1,0);
+    //PrintAndLog("b1:%s",sprint_hex(b1, 8));
+    PrintAndLog("b2:%s",sprint_hex(b2, 8));
+
+    //Auth2
+    UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}};
+    memcpy(reply,b1,8);
+    memcpy(reply+8,b2,8);
+    memcpy(d.d.asBytes,reply, 16);
+    SendCommand(&d);
+
+    UsbCommand respb;
+    if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
+        uint8_t  isOK  = respb.arg[0] & 0xff;
+        uint8_t * data2= respb.d.asBytes;
+
+        if (isOK){
+            PrintAndLog("b3:%s", sprint_hex(data2+2, 8));
+       }
+                 
+    } else {
+        PrintAndLog("Command execute timeout");
+    } 
+    return 1;
+}
+
+//EV1
+// Reader 2 Card : 02AA, key (1 byte), CRC1 CRC2 ; auth
+// Card 2 Reader : 02AF, 16 Bytes(b0), CRC1 CRC2
+// Reader 2 Card : 03AF, 16 Bytes(b1),16Bytes(b2) CRC1 CRC2
+// Card 2 Reader : 0300, 16 bytes(b3), CRC1 CRC2 ; success
+int CmdHF14AMfAESAuth(const char *Cmd){
+        
+    uint8_t blockNo = 0;
+    //keyNo=0;
+    uint32_t cuid=0;
+    uint8_t reply[32];
+    //DES_cblock r1_b1;
+    //unsigned char * b1, b2, nr, b0, r0, r1;
+    
+    uint8_t b1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    uint8_t b2[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    uint8_t nr[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    uint8_t b0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    uint8_t r0[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    uint8_t r1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    //
+    uint8_t key[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    uint8_t iv[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+    AES_KEY key_e;
+    AES_KEY key_d;
+
+    if (strlen(Cmd)<1) {
+        PrintAndLog("Usage:  hf desfire aes-auth k <key number>");
+        PrintAndLog("        sample: hf desfire aes-auth k 0");
+        return 0;
+    } 
+    
+    //Change key to user defined one
+    //
+    // int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);
+     //int private_AES_set_decrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key);
+       //
+    //memcpy(key1,key,16);
+    //memcpy(key2,key+8,8);
+    AES_set_encrypt_key(key,128,&key_e);
+    AES_set_decrypt_key(key,128,&key_d);
+        
+    //Auth1
+    UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}};
+    SendCommand(&c);
+    UsbCommand resp;
+    if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+        uint8_t isOK  = resp.arg[0] & 0xff;
+               cuid  = resp.arg[1];
+        uint8_t * data= resp.d.asBytes;
+
+         if (isOK){
+             PrintAndLog("enc(nc)/b0:%s", sprint_hex(data+2,16));
+             memcpy(b0,data+2,16);
+       }
+    } else {
+        PrintAndLog("Command execute timeout");
+    }
+    //
+    // void AES_cbc_encrypt(const unsigned char *in, unsigned char *out,
+       //size_t length, const AES_KEY *key,
+       //unsigned char *ivec, const int enc);
+    
+   //Do crypto magic
+    //DES_random_key(&nr);
+    //b1=dec(nr)
+    //r0=dec(b0)
+    //AES_cbc_encrypt(&nr,&b1,16,&key,0);
+    AES_cbc_encrypt(&b0,&r0,16,&key_d,iv,0);
+    //PrintAndLog("b1:%s",sprint_hex(b1, 8));
+    PrintAndLog("r0:%s",sprint_hex(r0, 16));
+    //r1=rol(r0)
+    memcpy(r1,r0,16);
+    rol(r1,8);
+    PrintAndLog("r1:%s",sprint_hex(r1, 16));
+    for(int i=0;i<16;i++){
+      b1[i]=(nr[i] ^ b0[i]);
+      b2[i]=(r1[i] ^ b1[i]);
+    }
+    PrintAndLog("nr:%s",sprint_hex(nr, 16));
+    AES_cbc_encrypt(&b1,&b1,16,&key_e,iv,1);
+    AES_cbc_encrypt(&b2,&b2,16,&key_e,iv,1);
+    PrintAndLog("b1:%s",sprint_hex(b1, 16));
+    PrintAndLog("b2:%s",sprint_hex(b2, 16));
+
+    //Auth2
+    UsbCommand d = {CMD_MIFARE_DES_AUTH2, {cuid}};
+    memcpy(reply,b1,16);
+    memcpy(reply+16,b2,16);
+    memcpy(d.d.asBytes,reply, 32);
+    SendCommand(&d);
+
+    UsbCommand respb;
+    if (WaitForResponseTimeout(CMD_ACK,&respb,1500)) {
+        uint8_t  isOK  = respb.arg[0] & 0xff;
+        uint8_t * data2= respb.d.asBytes;
+
+        if (isOK){
+            PrintAndLog("b3:%s", sprint_hex(data2+2, 16));
+       }
+                 
+    } else {
+        PrintAndLog("Command execute timeout");
+    } 
+    return 1;
+}
+
+
+//------------------------------------
+// Menu Stuff
+//------------------------------------
+static command_t CommandTable[] =
+{
+    {"help",    CmdHelp,               1,"This help"},
+    {"dbg",     CmdHF14AMfDbg,         0,"Set default debug mode"},
+    {"des-auth",CmdHF14AMfDESAuth,     0,"Desfire Authentication"},
+    {"ev1-auth",CmdHF14AMfAESAuth,     0,"EV1 Authentication"},
+    {NULL, NULL, 0, NULL}
+};
+
+int CmdHFMFDesfire(const char *Cmd){
+    // flush
+    WaitForResponseTimeout(CMD_ACK,NULL,100);
+    CmdsParse(CommandTable, Cmd);
+    return 0;
+}
+
+int CmdHelp(const char *Cmd){
+    CmdsHelp(CommandTable);
+    return 0;
+}
diff --git a/client/cmdhfmfdesfire.h b/client/cmdhfmfdesfire.h
new file mode 100644 (file)
index 0000000..c29fd26
--- /dev/null
@@ -0,0 +1,5 @@
+
+static int CmdHelp(const char *Cmd);
+int CmdHF14AMfDESAuth(const char *Cmd);
+int CmdHFMFDesfire(const char *Cmd);
+int CmdHelp(const char *Cmd);
\ No newline at end of file
index 8dfb9a3b1cceeb075f0facb06e37119a23a6c9e3..9bccc420a28574eaec6397fefb9f40d92e146d65 100644 (file)
@@ -7,18 +7,15 @@
 //-----------------------------------------------------------------------------
 // High frequency MIFARE ULTRALIGHT (C) commands
 //-----------------------------------------------------------------------------
-//#include <openssl/des.h>
 #include "loclass/des.h"
 #include "cmdhfmfu.h"
 #include "cmdhfmf.h"
 #include "cmdhf14a.h"
 
-
 #define MAX_ULTRA_BLOCKS   0x0f
 #define MAX_ULTRAC_BLOCKS  0x2f
 //#define MAX_ULTRAC_BLOCKS  0x2c
 
-
 static int CmdHelp(const char *Cmd);
 
 int CmdHF14AMfUInfo(const char *Cmd){
@@ -77,8 +74,11 @@ int CmdHF14AMfUInfo(const char *Cmd){
 
        int len = CmdHF14AMfucAuth("K 0");
 //     PrintAndLog("CODE: %d",len);
+// Fix reading UL-C 's password higher blocks.
        
        PrintAndLog("Seems to be a Ultralight %s", (len==0) ? "-C" :"");
+       
+       
        return 0;
 }
 
@@ -155,9 +155,9 @@ int CmdHF14AMfUWrBl(const char *Cmd){
 //  Mifare Ultralight Read Single Block
 //
 int CmdHF14AMfURdBl(const char *Cmd){
-  
-       uint8_t blockNo = -1;   
 
+       UsbCommand resp;
+       uint8_t blockNo = -1;   
        char cmdp = param_getchar(Cmd, 0);
        
        if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {    
@@ -169,26 +169,27 @@ int CmdHF14AMfURdBl(const char *Cmd){
        blockNo = param_get8(Cmd, 0);
 
        if (blockNo > MAX_ULTRA_BLOCKS){
-          PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
+          PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight");
           return 1;
        }
-       
-       PrintAndLog("--block no:0x%02X (%d)", (int)blockNo, blockNo);
+
        UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
        SendCommand(&c);
 
-       UsbCommand resp;
+
        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-               uint8_t isOK    = resp.arg[0] & 0xff;
-               uint8_t * data  = resp.d.asBytes;
-               
-               PrintAndLog("isOk: %02x", isOK);
-                       
-               if (isOK)
-                       PrintAndLog("Data: %s", sprint_hex(data, 4));
+               uint8_t isOK = resp.arg[0] & 0xff;
+               if (isOK) {
+                       uint8_t *data = resp.d.asBytes;
+                       PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4));
+               }
+               else {
+                       PrintAndLog("Failed reading block: (%02x)", isOK);
+               }
        } else {
-               PrintAndLog("Command execute timeout");
+               PrintAndLog("Command execute time-out");
        }
+       
        return 0;
 }
 
@@ -224,7 +225,7 @@ int CmdHF14AMfUDump(const char *Cmd){
                PrintAndLog("Reads all pages from Mifare Ultralight or Ultralight-C tag.");
                PrintAndLog("It saves binary dump into the file `filename.bin` or `cardUID.bin`");              
                PrintAndLog("Usage:  hf mfu dump <c> <filename w/o .bin>");
-               PrintAndLog("     <c>  optional cardtype c == Ultralight-C, if not defaults to Ultralight");
+               PrintAndLog("     <c>  optional cardtype c == Ultralight-C, Defaults to Ultralight");
                PrintAndLog("     sample: hf mfu dump");
                PrintAndLog("           : hf mfu dump myfile");
                PrintAndLog("           : hf mfu dump c myfile");
@@ -248,7 +249,7 @@ int CmdHF14AMfUDump(const char *Cmd){
                }
                data  = resp.d.asBytes;
        } else {
-               PrintAndLog("Command execute timeout");
+               PrintAndLog("Command execute time-out");
                return 0;
        }
                
@@ -376,12 +377,14 @@ void rol (uint8_t *data, const size_t len){
 //
 int CmdHF14AMfucAuth(const char *Cmd){
 
-       uint8_t default_keys[5][16] = {
+       uint8_t default_keys[7][16] = {
                { 0x42,0x52,0x45,0x41,0x4b,0x4d,0x45,0x49,0x46,0x59,0x4f,0x55,0x43,0x41,0x4e,0x21 },// 3des std key
                { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },// all zeroes
                { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f },// 0x00-0x0F
                { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 },// NFC-key
-               { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }     // all ones
+               { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },// all ones
+               { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF },// all FF
+               { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF }     // 11 22 33
        };
 
        char cmdp = param_getchar(Cmd, 0);
@@ -391,7 +394,7 @@ int CmdHF14AMfucAuth(const char *Cmd){
        //Change key to user defined one
        if (cmdp == 'k' || cmdp == 'K'){
                keyNo = param_get8(Cmd, 1);
-               if(keyNo >= 4) errors = true;
+               if(keyNo > 6) errors = true;
        }
 
        if (cmdp == 'h' || cmdp == 'H') {
@@ -401,11 +404,13 @@ int CmdHF14AMfucAuth(const char *Cmd){
        if (errors) {
                PrintAndLog("Usage:  hf mfu cauth k <key number>");
                PrintAndLog("      0 (default): 3DES standard key");
-               PrintAndLog("      1 : all zeros key");
+               PrintAndLog("      1 : all 0x00 key");
                PrintAndLog("      2 : 0x00-0x0F key");
                PrintAndLog("      3 : nfc key");
-               PrintAndLog("      4 : all ones key");
-               PrintAndLog("        sample : hf mfu cauth k");
+               PrintAndLog("      4 : all 0x01 key");
+               PrintAndLog("      5 : all 0xff key");
+               PrintAndLog("      6 : 0x00-0xFF key");         
+               PrintAndLog("\n      sample : hf mfu cauth k");
                PrintAndLog("               : hf mfu cauth k 3");
                return 0;
        } 
@@ -430,23 +435,19 @@ int CmdHF14AMfucAuth(const char *Cmd){
                uint8_t * data= resp.d.asBytes;
 
                if (isOK){
-                       PrintAndLog("enc(RndB):%s", sprint_hex(data+1, 8));
                        memcpy(enc_random_b,data+1,8);
                } else {
                        PrintAndLog("Auth failed");
-                       return 2; // auth failed.
+                       return 2;
                }               
        } else {
                PrintAndLog("Command execute timeout");
                return 1;
        }
-
        uint8_t iv[8]           = { 0 };
-       // Do we need random ? Right now we use all ones, is that random enough ?
-//    DES_random_key(&RndA);
 
        PrintAndLog("     RndA  :%s",sprint_hex(random_a, 8));
-       PrintAndLog("     e_RndB:%s",sprint_hex(enc_random_b, 8));
+       PrintAndLog("     enc(RndB):%s",sprint_hex(enc_random_b, 8));
 
        des3_set2key_dec(&ctx, key);
 
@@ -464,7 +465,7 @@ int CmdHF14AMfucAuth(const char *Cmd){
        memcpy(random_a_and_b  ,random_a,8);
        memcpy(random_a_and_b+8,random_b,8);
        
-       PrintAndLog("     RA+B:%s",sprint_hex(random_a_and_b, 16));
+       PrintAndLog("     A+B:%s",sprint_hex(random_a_and_b, 16));
 
        des3_set2key_enc(&ctx, key);
 
@@ -476,7 +477,7 @@ int CmdHF14AMfucAuth(const char *Cmd){
                , random_a_and_b         // unsigned char *output
                );
 
-       PrintAndLog("enc(RA+B):%s",sprint_hex(random_a_and_b, 16));
+       PrintAndLog("enc(A+B):%s",sprint_hex(random_a_and_b, 16));
 
        //Auth2
        UsbCommand d = {CMD_MIFAREUC_AUTH2, {cuid}};
@@ -490,6 +491,23 @@ int CmdHF14AMfucAuth(const char *Cmd){
 
                if (isOK){
                        PrintAndLog("enc(RndA'):%s", sprint_hex(data2+1, 8));
+                       
+                       uint8_t foo[8] = { 0 };
+                       uint8_t bar[8] = { 0 };
+                       memcpy(foo, data2+1, 8);
+                       des3_set2key_dec(&ctx, key);
+
+                       des3_crypt_cbc(&ctx    // des3_context *ctx
+                               , DES_DECRYPT      // int mode
+                               , 8      // size_t length
+                               , enc_random_b     // unsigned char iv[8]
+                               , foo           // const unsigned char *input
+                               , bar   // unsigned char *output
+                       );
+
+                       PrintAndLog("--> : %s  : <-- Should be equal to our RndA",sprint_hex(bar, 8));
+
+                       
                } else {
                        return 2;
                }
@@ -601,12 +619,17 @@ int CmdTestDES(const char * cmd)
 //
 int CmdHF14AMfUCRdBl(const char *Cmd)
 {
+       UsbCommand resp;
+       bool hasPwd = FALSE;
        uint8_t blockNo = -1;
+       unsigned char key[16];
        char cmdp = param_getchar(Cmd, 0);
        
        if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
-               PrintAndLog("Usage:  hf mfu crdbl  <block number>");
-               PrintAndLog("        sample: hf mfu crdbl 0");
+               PrintAndLog("Usage:  hf mfu crdbl  <block number> <password>");
+               PrintAndLog("");
+               PrintAndLog("sample: hf mfu crdbl 0");
+               PrintAndLog("        hf mfu crdbl 0 112233445566778899AABBCCDDEEFF");
                return 0;
        }       
                
@@ -617,26 +640,39 @@ int CmdHF14AMfUCRdBl(const char *Cmd)
        }
        
        if (blockNo > MAX_ULTRAC_BLOCKS ){
-               PrintAndLog("Error: Maximum number of readable blocks is 47 for Ultralight-C Cards!");
+               PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C");
                return 1;
        } 
        
-       PrintAndLog("--block no: 0x%02X (%d)", (int)blockNo, blockNo);
+       // key
+       if ( strlen(Cmd) > 3){
+               if (param_gethex(Cmd, 1, key, 32)) {
+                       PrintAndLog("Key must include %d HEX symbols", 32);
+                       return 1;
+               } else {
+                       hasPwd = TRUE;
+               }       
+       }       
 
        //Read Block
-       UsbCommand e = {CMD_MIFAREU_READBL, {blockNo}};
-       SendCommand(&e);
-       UsbCommand resp_c;
-       if (WaitForResponseTimeout(CMD_ACK,&resp_c,1500)) {
-               uint8_t isOK = resp_c.arg[0] & 0xff;
-               uint8_t *data = resp_c.d.asBytes;
-               
-               PrintAndLog("isOk: %02x", isOK);
-               if (isOK)
-                       PrintAndLog("Data: %s", sprint_hex(data, 4));
-                       
+       UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
+       if ( hasPwd ) {
+               c.arg[1] = 1;
+               memcpy(c.d.asBytes,key,16);
+       }
+       SendCommand(&c);
+
+       if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+               uint8_t isOK = resp.arg[0] & 0xff;
+               if (isOK) {
+                       uint8_t *data = resp.d.asBytes;
+                       PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4));
+               }
+               else {
+                       PrintAndLog("Failed reading block: (%02x)", isOK);
+               }
        } else {
-               PrintAndLog("Command execute timeout");
+               PrintAndLog("Command execute time-out");
        }
        return 0;
 }
@@ -711,6 +747,149 @@ int CmdHF14AMfUCWrBl(const char *Cmd){
        return 0;
 }
 
+// 
+// Mifare Ultralight C - Set password
+//
+int CmdHF14AMfucSetPwd(const char *Cmd){
+
+       uint8_t pwd[16] = {0x00};
+       
+       char cmdp = param_getchar(Cmd, 0);
+       
+       if (strlen(Cmd) == 0  || cmdp == 'h' || cmdp == 'H') {  
+               PrintAndLog("Usage:  hf mfu setpwd <password (32 hex symbols)>");
+               PrintAndLog("       [password] - (32 hex symbols)");
+               PrintAndLog("");
+               PrintAndLog("sample: hf mfu setpwd 000102030405060708090a0b0c0d0e0f");
+               PrintAndLog("");
+               return 0;
+       }
+       
+       if (param_gethex(Cmd, 0, pwd, 32)) {
+               PrintAndLog("Password must include 32 HEX symbols");
+               return 1;
+       }
+       
+       UsbCommand c = {CMD_MIFAREUC_SETPWD};   
+       memcpy( c.d.asBytes, pwd, 16);
+       SendCommand(&c);
+
+       UsbCommand resp;
+       
+       if (WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+               if ( (resp.arg[0] & 0xff) == 1)
+                       PrintAndLog("Ultralight-C new password: %s", sprint_hex(pwd,16));
+               else{
+                       PrintAndLog("Failed writing at block %d", resp.arg[1] & 0xff);
+                       return 1;
+               }
+       }
+       else {
+               PrintAndLog("command execution time out");
+               return 1;
+       }
+       
+       return 0;
+}
+
+//
+// Mifare Ultraligh - Set UID
+//
+int CmdHF14AMfucSetUid(const char *Cmd){
+
+       uint8_t uid[7] = {0x00};
+       char cmdp = param_getchar(Cmd, 0);
+       
+       if (strlen(Cmd) == 0  || cmdp == 'h' || cmdp == 'H') {  
+               PrintAndLog("Usage:  hf mfu setuid <uid (14 hex symbols)>");
+               PrintAndLog("       [uid] - (14 hex symbols)");
+               PrintAndLog("");
+               PrintAndLog("sample: hf mfu setuid 11223344556677");
+               PrintAndLog("");
+               return 0;
+       }
+       
+       if (param_gethex(Cmd, 0, uid, 14)) {
+               PrintAndLog("Password must include 14 HEX symbols");
+               return 1;
+       }
+
+       UsbCommand c = {CMD_MIFAREU_SETUID};    
+       memcpy( c.d.asBytes, uid, 14);
+       SendCommand(&c);
+
+       UsbCommand resp;        
+       if (WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
+               if ( (resp.arg[0] & 0xff) == 1)
+                       PrintAndLog("New UID: %s", sprint_hex(uid,14));
+               else{
+                       PrintAndLog("Failed writing new uid");
+                       return 1;
+               }
+       }
+       else {
+               PrintAndLog("command execution time out");
+               return 1;
+       }
+       return 0;
+}
+
+int CmdHF14AMfuGenDiverseKeys(const char *Cmd){
+       
+       uint8_t iv[8] = { 0x00 };
+       uint8_t block = 0x07;
+       
+       uint8_t uid[] = { 0xF4,0xEA, 0x54, 0x8E };
+       uint8_t mifarekey[] = { 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5 };
+       uint8_t masterkey[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff };
+       
+       uint8_t mix[8] = { 0x00 };
+       uint8_t divkey[8] = { 0x00 };
+       
+       memcpy(mix, mifarekey, 4);
+       
+       mix[4] = mifarekey[4] ^ uid[0];
+       mix[5] = mifarekey[5] ^ uid[1];
+       mix[6] = block ^ uid[2];
+       mix[7] = uid[3];
+       
+       des3_context ctx = { 0x00 };
+       des3_set2key_enc(&ctx, masterkey);
+
+       des3_crypt_cbc(&ctx     // des3_context *ctx
+               , DES_ENCRYPT       // int mode
+               , sizeof(mix)    // size_t length
+               , iv                // unsigned char iv[8]
+               , mix            // const unsigned char *input
+               , divkey           // unsigned char *output
+               );
+
+       PrintAndLog("3DES version");
+       PrintAndLog("Masterkey    :\t %s", sprint_hex(masterkey,sizeof(masterkey)));
+       PrintAndLog("UID          :\t %s", sprint_hex(uid, sizeof(uid)));
+       PrintAndLog("Sector       :\t %0d", block);
+       PrintAndLog("Mifare key   :\t %s", sprint_hex(mifarekey, sizeof(mifarekey)));
+       PrintAndLog("Message      :\t %s", sprint_hex(mix, sizeof(mix)));
+       PrintAndLog("Diversified key: %s", sprint_hex(divkey+1, 6));
+               
+       return 0;
+}
+
+// uint8_t * diversify_key(uint8_t * key){
+ // for(int i=0; i<16; i++){
+   // if(i<=6) key[i]^=cuid[i];
+   // if(i>6) key[i]^=cuid[i%7];
+ // }
+ // return key;
+// }
+
+// static void GenerateUIDe( uint8_t *uid, uint8_t len){
+       // for (int i=0; i<len; ++i){
+                       
+       // }
+       // return;
+// }
+
 //------------------------------------
 // Menu Stuff
 //------------------------------------
@@ -720,12 +899,15 @@ static command_t CommandTable[] =
        {"dbg",         CmdHF14AMfDbg,          0,"Set default debug mode"},
        {"info",        CmdHF14AMfUInfo,        0,"Taginfo"},
        {"dump",        CmdHF14AMfUDump,        0,"Dump MIFARE Ultralight / Ultralight-C tag to binary file"},
-       {"rdbl",        CmdHF14AMfURdBl,        0,"Read block - MIFARE Ultralight"},
+       {"rdbl",        CmdHF14AMfURdBl,        0,"Read block  - MIFARE Ultralight"},
        {"wrbl",        CmdHF14AMfUWrBl,        0,"Write block - MIFARE Ultralight"},    
-       {"crdbl",       CmdHF14AMfUCRdBl,       0,"Read block - MIFARE Ultralight C"},
-       {"cwrbl",       CmdHF14AMfUCWrBl,       0,"Write MIFARE Ultralight C block"},   
-       {"cauth",       CmdHF14AMfucAuth,       0,"try a Ultralight C Authentication"},
+       {"crdbl",       CmdHF14AMfUCRdBl,       0,"Read block  - MIFARE Ultralight C"},
+       {"cwrbl",       CmdHF14AMfUCWrBl,       0,"Write block - MIFARE Ultralight C"},
+       {"cauth",       CmdHF14AMfucAuth,       0,"Ultralight C Authentication"},
        //{"testdes", CmdTestDES ,        1, "Test DES"},
+       {"setpwd", CmdHF14AMfucSetPwd , 1, "Set 3des password [Ultralight-C only]"},
+       {"setuid", CmdHF14AMfucSetUid , 1, "Set UID"},
+       {"gen", CmdHF14AMfuGenDiverseKeys , 1, "Generate 3des mifare diversified keys"},
        {NULL, NULL, 0, NULL}
 };
 
index c4bc03415c7bb8a8a7467a055d58495d32d614f8..ccb53ad0e99f793c92d957883e6eb61067f07e2e 100644 (file)
@@ -1,6 +1,9 @@
 #include "cmdhfmf.h"
 #include "cmdhf14a.h"
 
+#ifndef CMDHFMFU_H__
+#define CMDHFMFU_H__
+
 //standard ultralight
 int CmdHF14AMfUWrBl(const char *Cmd);
 int CmdHF14AMfURdBl(const char *Cmd);
@@ -14,6 +17,6 @@ int CmdHF14AMfucAuth(const char *Cmd);
 int CmdHF14AMfUDump(const char *Cmd);
 void rol (uint8_t *data, const size_t len);
 
-
 int CmdHFMFUltra(const char *Cmd);
 int CmdHF14AMfUInfo(const char *Cmd);
+#endif
index 5ec0aa601eb8024676220ca340a1431930fb861b..4f65fb8c2badddf4fe45cdc6bd6f4e73ad54cdde 100644 (file)
@@ -15,6 +15,7 @@
 #include "ui.h"
 #include "proxmark3.h"
 #include "cmdparser.h"
+#include "cmddata.h"
 #include "cmdhw.h"
 #include "cmdmain.h"
 #include "cmddata.h"
index 54f396fdde630902f6a13ce354853d8b6a0c1840..30c8bb229fa98b6ffe86f73cac00bfcce24b58f3 100644 (file)
@@ -35,326 +35,326 @@ static int CmdHelp(const char *Cmd);
 /* send a command before reading */
 int CmdLFCommandRead(const char *Cmd)
 {
-       static char dummy[3];
+  static char dummy[3];
 
-       dummy[0]= ' ';
+  dummy[0]= ' ';
 
-       UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
-       sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1));
-       // in case they specified 'h'
-       strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
-       SendCommand(&c);
-       return 0;
+  UsbCommand c = {CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K};
+  sscanf(Cmd, "%"lli" %"lli" %"lli" %s %s", &c.arg[0], &c.arg[1], &c.arg[2],(char*)(&c.d.asBytes),(char*)(&dummy+1));
+  // in case they specified 'h'
+  strcpy((char *)&c.d.asBytes + strlen((char *)c.d.asBytes), dummy);
+  SendCommand(&c);
+  return 0;
 }
 
 int CmdFlexdemod(const char *Cmd)
 {
-       int i;
-       for (i = 0; i < GraphTraceLen; ++i) {
-               if (GraphBuffer[i] < 0) {
-                       GraphBuffer[i] = -1;
-               } else {
-                       GraphBuffer[i] = 1;
-               }
-       }
+  int i;
+  for (i = 0; i < GraphTraceLen; ++i) {
+    if (GraphBuffer[i] < 0) {
+      GraphBuffer[i] = -1;
+    } else {
+      GraphBuffer[i] = 1;
+    }
+  }
 
 #define LONG_WAIT 100
-       int start;
-       for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
-               int first = GraphBuffer[start];
-               for (i = start; i < start + LONG_WAIT; i++) {
-                       if (GraphBuffer[i] != first) {
-                               break;
-                       }
-               }
-               if (i == (start + LONG_WAIT)) {
-                       break;
-               }
-       }
-       if (start == GraphTraceLen - LONG_WAIT) {
-               PrintAndLog("nothing to wait for");
-               return 0;
-       }
-
-       GraphBuffer[start] = 2;
-       GraphBuffer[start+1] = -2;
+  int start;
+  for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) {
+    int first = GraphBuffer[start];
+    for (i = start; i < start + LONG_WAIT; i++) {
+      if (GraphBuffer[i] != first) {
+        break;
+      }
+    }
+    if (i == (start + LONG_WAIT)) {
+      break;
+    }
+  }
+  if (start == GraphTraceLen - LONG_WAIT) {
+    PrintAndLog("nothing to wait for");
+    return 0;
+  }
+
+  GraphBuffer[start] = 2;
+  GraphBuffer[start+1] = -2;
        uint8_t bits[64] = {0x00};
 
        int bit, sum;
-       i = start;
-       for (bit = 0; bit < 64; bit++) {
+  i = start;
+  for (bit = 0; bit < 64; bit++) {
                sum = 0;
                for (int j = 0; j < 16; j++) {
-                       sum += GraphBuffer[i++];
-               }
+      sum += GraphBuffer[i++];
+    }
 
                bits[bit] = (sum > 0) ? 1 : 0;
 
-               PrintAndLog("bit %d sum %d", bit, sum);
-       }
-
-       for (bit = 0; bit < 64; bit++) {
-               int j;
-               int sum = 0;
-               for (j = 0; j < 16; j++) {
-                       sum += GraphBuffer[i++];
-               }
-               if (sum > 0 && bits[bit] != 1) {
-                       PrintAndLog("oops1 at %d", bit);
-               }
-               if (sum < 0 && bits[bit] != 0) {
-                       PrintAndLog("oops2 at %d", bit);
-               }
-       }
+    PrintAndLog("bit %d sum %d", bit, sum);
+  }
+
+  for (bit = 0; bit < 64; bit++) {
+    int j;
+    int sum = 0;
+    for (j = 0; j < 16; j++) {
+      sum += GraphBuffer[i++];
+    }
+    if (sum > 0 && bits[bit] != 1) {
+      PrintAndLog("oops1 at %d", bit);
+    }
+    if (sum < 0 && bits[bit] != 0) {
+      PrintAndLog("oops2 at %d", bit);
+    }
+  }
 
        // HACK writing back to graphbuffer.
-       GraphTraceLen = 32*64;
-       i = 0;
-       int phase = 0;
-       for (bit = 0; bit < 64; bit++) {
+  GraphTraceLen = 32*64;
+  i = 0;
+  int phase = 0;
+  for (bit = 0; bit < 64; bit++) {
        
                phase = (bits[bit] == 0) ? 0 : 1;
                
-               int j;
-               for (j = 0; j < 32; j++) {
-                       GraphBuffer[i++] = phase;
-                       phase = !phase;
-               }
-       }
-
-       RepaintGraphWindow();
-       return 0;
+    int j;
+    for (j = 0; j < 32; j++) {
+      GraphBuffer[i++] = phase;
+      phase = !phase;
+    }
+  }
+
+  RepaintGraphWindow();
+  return 0;
 }
-       
+  
 int CmdIndalaDemod(const char *Cmd)
 {
-       // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
+  // Usage: recover 64bit UID by default, specify "224" as arg to recover a 224bit UID
 
-       int state = -1;
-       int count = 0;
-       int i, j;
+  int state = -1;
+  int count = 0;
+  int i, j;
 
-       // worst case with GraphTraceLen=64000 is < 4096
-       // under normal conditions it's < 2048
+  // worst case with GraphTraceLen=64000 is < 4096
+  // under normal conditions it's < 2048
 
-       uint8_t rawbits[4096];
-       int rawbit = 0;
-       int worst = 0, worstPos = 0;
+  uint8_t rawbits[4096];
+  int rawbit = 0;
+  int worst = 0, worstPos = 0;
  // PrintAndLog("Expecting a bit less than %d raw bits", GraphTraceLen / 32);
-       for (i = 0; i < GraphTraceLen-1; i += 2) {
-               count += 1;
-               if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
-                       if (state == 0) {
-                               for (j = 0; j <  count - 8; j += 16) {
-                                       rawbits[rawbit++] = 0;
-                               }
-                               if ((abs(count - j)) > worst) {
-                                       worst = abs(count - j);
-                                       worstPos = i;
-                               }
-                       }
-                       state = 1;
-                       count = 0;
-               } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
-                       if (state == 1) {
-                               for (j = 0; j <  count - 8; j += 16) {
-                                       rawbits[rawbit++] = 1;
-                               }
-                               if ((abs(count - j)) > worst) {
-                                       worst = abs(count - j);
-                                       worstPos = i;
-                               }
-                       }
-                       state = 0;
-                       count = 0;
-               }
-       }
-       
-       if (rawbit>0){
-               PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
-               PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
-       } else {
-               return 0;
-       }
-
-       // Finding the start of a UID
-       int uidlen, long_wait;
-       if (strcmp(Cmd, "224") == 0) {
-               uidlen = 224;
-               long_wait = 30;
+  for (i = 0; i < GraphTraceLen-1; i += 2) {
+    count += 1;
+    if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) {
+      if (state == 0) {
+        for (j = 0; j <  count - 8; j += 16) {
+          rawbits[rawbit++] = 0;
+        }
+        if ((abs(count - j)) > worst) {
+          worst = abs(count - j);
+          worstPos = i;
+        }
+      }
+      state = 1;
+      count = 0;
+    } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) {
+      if (state == 1) {
+        for (j = 0; j <  count - 8; j += 16) {
+          rawbits[rawbit++] = 1;
+        }
+        if ((abs(count - j)) > worst) {
+          worst = abs(count - j);
+          worstPos = i;
+        }
+      }
+      state = 0;
+      count = 0;
+    }
+  }
+  
+  if (rawbit>0){
+    PrintAndLog("Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32);
+    PrintAndLog("worst metric (0=best..7=worst): %d at pos %d", worst, worstPos);
        } else {
-               uidlen = 64;
-               long_wait = 29;
-       }
-
-       int start;
-       int first = 0;
-       for (start = 0; start <= rawbit - uidlen; start++) {
-               first = rawbits[start];
-               for (i = start; i < start + long_wait; i++) {
-                       if (rawbits[i] != first) {
-                               break;
-                       }
-               }
-               if (i == (start + long_wait)) {
-                       break;
-               }
-       }
-       
-       if (start == rawbit - uidlen + 1) {
-               PrintAndLog("nothing to wait for");
                return 0;
        }
 
-       // Inverting signal if needed
-       if (first == 1) {
-               for (i = start; i < rawbit; i++) {
-                       rawbits[i] = !rawbits[i];
-               }
-       }
-
-       // Dumping UID
+  // Finding the start of a UID
+  int uidlen, long_wait;
+  if (strcmp(Cmd, "224") == 0) {
+    uidlen = 224;
+    long_wait = 30;
+  } else {
+    uidlen = 64;
+    long_wait = 29;
+  }
+
+  int start;
+  int first = 0;
+  for (start = 0; start <= rawbit - uidlen; start++) {
+    first = rawbits[start];
+    for (i = start; i < start + long_wait; i++) {
+      if (rawbits[i] != first) {
+        break;
+      }
+    }
+    if (i == (start + long_wait)) {
+      break;
+    }
+  }
+  
+  if (start == rawbit - uidlen + 1) {
+    PrintAndLog("nothing to wait for");
+    return 0;
+  }
+
+  // Inverting signal if needed
+  if (first == 1) {
+    for (i = start; i < rawbit; i++) {
+      rawbits[i] = !rawbits[i];
+    }
+  }
+
+  // Dumping UID
        uint8_t bits[224] = {0x00};
        char showbits[225] = {0x00};
-       int bit;
-       i = start;
-       int times = 0;
-       
-       if (uidlen > rawbit) {
-               PrintAndLog("Warning: not enough raw bits to get a full UID");
-               for (bit = 0; bit < rawbit; bit++) {
-                       bits[bit] = rawbits[i++];
-                       // As we cannot know the parity, let's use "." and "/"
-                       showbits[bit] = '.' + bits[bit];
-               }
-               showbits[bit+1]='\0';
-               PrintAndLog("Partial UID=%s", showbits);
-               return 0;
-       } else {
-               for (bit = 0; bit < uidlen; bit++) {
-                       bits[bit] = rawbits[i++];
-                       showbits[bit] = '0' + bits[bit];
-               }
-               times = 1;
-       }
+  int bit;
+  i = start;
+  int times = 0;
        
-       //convert UID to HEX
-       uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
-       int idx;
+  if (uidlen > rawbit) {
+    PrintAndLog("Warning: not enough raw bits to get a full UID");
+    for (bit = 0; bit < rawbit; bit++) {
+      bits[bit] = rawbits[i++];
+      // As we cannot know the parity, let's use "." and "/"
+      showbits[bit] = '.' + bits[bit];
+    }
+    showbits[bit+1]='\0';
+    PrintAndLog("Partial UID=%s", showbits);
+    return 0;
+  } else {
+    for (bit = 0; bit < uidlen; bit++) {
+      bits[bit] = rawbits[i++];
+      showbits[bit] = '0' + bits[bit];
+    }
+    times = 1;
+  }
+  
+  //convert UID to HEX
+  uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7;
+  int idx;
        uid1 = uid2 = 0;
        
-       if (uidlen==64){
-               for( idx=0; idx<64; idx++) {
-                               if (showbits[idx] == '0') {
-                               uid1=(uid1<<1)|(uid2>>31);
-                               uid2=(uid2<<1)|0;
-                               } else {
-                               uid1=(uid1<<1)|(uid2>>31);
-                               uid2=(uid2<<1)|1;
-                               
-                       }
-               PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
-       }
-       else {
+  if (uidlen==64){
+    for( idx=0; idx<64; idx++) {
+        if (showbits[idx] == '0') {
+        uid1=(uid1<<1)|(uid2>>31);
+        uid2=(uid2<<1)|0;
+        } else {
+        uid1=(uid1<<1)|(uid2>>31);
+        uid2=(uid2<<1)|1;
+        } 
+      }
+    PrintAndLog("UID=%s (%x%08x)", showbits, uid1, uid2);
+  }
+  else {
                uid3 = uid4 = uid5 = uid6 = uid7 = 0;
 
-               for( idx=0; idx<224; idx++) {
-                               uid1=(uid1<<1)|(uid2>>31);
-                               uid2=(uid2<<1)|(uid3>>31);
-                               uid3=(uid3<<1)|(uid4>>31);
-                               uid4=(uid4<<1)|(uid5>>31);
-                               uid5=(uid5<<1)|(uid6>>31);
-                               uid6=(uid6<<1)|(uid7>>31);
+    for( idx=0; idx<224; idx++) {
+        uid1=(uid1<<1)|(uid2>>31);
+        uid2=(uid2<<1)|(uid3>>31);
+        uid3=(uid3<<1)|(uid4>>31);
+        uid4=(uid4<<1)|(uid5>>31);
+        uid5=(uid5<<1)|(uid6>>31);
+        uid6=(uid6<<1)|(uid7>>31);
                        
                        if (showbits[idx] == '0') 
                                uid7 = (uid7<<1) | 0;
                        else 
                                uid7 = (uid7<<1) | 1;
-                       }
-               PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
-       }
+      }
+    PrintAndLog("UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7);
+  }
 
-       // Checking UID against next occurrences
-               int failed = 0;
+  // Checking UID against next occurrences
+    int failed = 0;
        for (; i + uidlen <= rawbit;) {
                failed = 0;
-               for (bit = 0; bit < uidlen; bit++) {
-                       if (bits[bit] != rawbits[i++]) {
-                               failed = 1;
-                               break;
-                       }
-               }
-               if (failed == 1) {
-                       break;
-               }
-               times += 1;
-       }
-
-       PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
-
-       // Remodulating for tag cloning
+    for (bit = 0; bit < uidlen; bit++) {
+      if (bits[bit] != rawbits[i++]) {
+        failed = 1;
+        break;
+      }
+    }
+    if (failed == 1) {
+      break;
+    }
+    times += 1;
+  }
+
+  PrintAndLog("Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen);
+
+  // Remodulating for tag cloning
        // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) 
        // since this changes graphbuffer data.
-       GraphTraceLen = 32*uidlen;
-       i = 0;
-       int phase = 0;
-       for (bit = 0; bit < uidlen; bit++) {
-               if (bits[bit] == 0) {
-                       phase = 0;
-               } else {
-                       phase = 1;
-               }
-               int j;
-               for (j = 0; j < 32; j++) {
-                       GraphBuffer[i++] = phase;
-                       phase = !phase;
-               }
-       }
-
-       RepaintGraphWindow();
-       return 1;
+  GraphTraceLen = 32*uidlen;
+  i = 0;
+  int phase = 0;
+  for (bit = 0; bit < uidlen; bit++) {
+    if (bits[bit] == 0) {
+      phase = 0;
+    } else {
+      phase = 1;
+    }
+    int j;
+    for (j = 0; j < 32; j++) {
+      GraphBuffer[i++] = phase;
+      phase = !phase;
+    }
+  }
+
+  RepaintGraphWindow();
+  return 1;
 }
 
 int CmdIndalaClone(const char *Cmd)
 {
-       UsbCommand c;
+  UsbCommand c;
        unsigned int uid1, uid2, uid3, uid4, uid5, uid6, uid7;
 
        uid1 =  uid2 = uid3 = uid4 = uid5 = uid6 = uid7 = 0;
-       int n = 0, i = 0;
-
-       if (strchr(Cmd,'l') != 0) {
-               while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
-                       uid1 = (uid1 << 4) | (uid2 >> 28);
-                       uid2 = (uid2 << 4) | (uid3 >> 28);
-                       uid3 = (uid3 << 4) | (uid4 >> 28);
-                       uid4 = (uid4 << 4) | (uid5 >> 28);
-                       uid5 = (uid5 << 4) | (uid6 >> 28);
-                       uid6 = (uid6 << 4) | (uid7 >> 28);
-                       uid7 = (uid7 << 4) | (n & 0xf);
-               }
-               PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7);
-               c.cmd = CMD_INDALA_CLONE_TAG_L;
-               c.d.asDwords[0] = uid1;
-               c.d.asDwords[1] = uid2;
-               c.d.asDwords[2] = uid3;
-               c.d.asDwords[3] = uid4;
-               c.d.asDwords[4] = uid5;
-               c.d.asDwords[5] = uid6;
-               c.d.asDwords[6] = uid7;
+  int n = 0, i = 0;
+
+  if (strchr(Cmd,'l') != 0) {
+    while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
+      uid1 = (uid1 << 4) | (uid2 >> 28);
+      uid2 = (uid2 << 4) | (uid3 >> 28);
+      uid3 = (uid3 << 4) | (uid4 >> 28);
+      uid4 = (uid4 << 4) | (uid5 >> 28);
+      uid5 = (uid5 << 4) | (uid6 >> 28);
+      uid6 = (uid6 << 4) | (uid7 >> 28);
+       uid7 = (uid7 << 4) | (n & 0xf);
+    }
+    PrintAndLog("Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7);
+    c.cmd = CMD_INDALA_CLONE_TAG_L;
+    c.d.asDwords[0] = uid1;
+    c.d.asDwords[1] = uid2;
+    c.d.asDwords[2] = uid3;
+    c.d.asDwords[3] = uid4;
+    c.d.asDwords[4] = uid5;
+    c.d.asDwords[5] = uid6;
+    c.d.asDwords[6] = uid7;
        } else {
-               while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
-                       uid1 = (uid1 << 4) | (uid2 >> 28);
-                       uid2 = (uid2 << 4) | (n & 0xf);
-               }
-               PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2);
-               c.cmd = CMD_INDALA_CLONE_TAG;
-               c.arg[0] = uid1;
-               c.arg[1] = uid2;
-       }
-
-       SendCommand(&c);
-       return 0;
+    while (sscanf(&Cmd[i++], "%1x", &n ) == 1) {
+      uid1 = (uid1 << 4) | (uid2 >> 28);
+      uid2 = (uid2 << 4) | (n & 0xf);
+    }
+    PrintAndLog("Cloning 64bit tag with UID %x%08x", uid1, uid2);
+    c.cmd = CMD_INDALA_CLONE_TAG;
+    c.arg[0] = uid1;
+    c.arg[1] = uid2;
+  }
+
+  SendCommand(&c);
+  return 0;
 }
 
 int usage_lf_read()
@@ -492,7 +492,12 @@ int CmdLFRead(const char *Cmd)
        //And ship it to device
        UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {arg1,0,0}};
        SendCommand(&c);
-       WaitForResponse(CMD_ACK,NULL);
+       //WaitForResponse(CMD_ACK,NULL);        
+       if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
+               PrintAndLog("command execution time out");
+               return 1;
+       }
+
        return 0;
 }
 
@@ -512,659 +517,687 @@ int CmdLFSnoop(const char *Cmd)
 
 static void ChkBitstream(const char *str)
 {
-       int i;
+  int i;
  
-       /* convert to bitstream if necessary */
+  /* convert to bitstream if necessary */
        for (i = 0; i < (int)(GraphTraceLen / 2); i++){
                if (GraphBuffer[i] > 1 || GraphBuffer[i] < 0) {
-                       CmdGetBitStream("");
-                       break;
-               }
-       }
+      CmdGetBitStream("");
+      break;
+    }
+  }
 }
 //appears to attempt to simulate manchester
 int CmdLFSim(const char *Cmd)
 {
-       int i,j;
-       static int gap;
+  int i,j;
+  static int gap;
 
-       sscanf(Cmd, "%i", &gap);
+  sscanf(Cmd, "%i", &gap);
 
-       /* convert to bitstream if necessary */
+  /* convert to bitstream if necessary */
 
-       ChkBitstream(Cmd);
+  ChkBitstream(Cmd);
 
-       //can send 512 bits at a time (1 byte sent per bit...)
-       printf("Sending [%d bytes]", GraphTraceLen);
-       for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) {
-               UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
+  //can send 512 bits at a time (1 byte sent per bit...)
+  printf("Sending [%d bytes]", GraphTraceLen);
+  for (i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) {
+    UsbCommand c={CMD_DOWNLOADED_SIM_SAMPLES_125K, {i, 0, 0}};
 
-               for (j = 0; j < USB_CMD_DATA_SIZE; j++) {
-                       c.d.asBytes[j] = GraphBuffer[i+j];
-               }
-               SendCommand(&c);
-               WaitForResponse(CMD_ACK,NULL);
-               printf(".");
-       }
+    for (j = 0; j < USB_CMD_DATA_SIZE; j++) {
+      c.d.asBytes[j] = GraphBuffer[i+j];
+    }
+    SendCommand(&c);
+    WaitForResponse(CMD_ACK,NULL);
+    printf(".");
+  }
 
-       printf("\n");
-       PrintAndLog("Starting to simulate");
-       UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
-       SendCommand(&c);
-       return 0;
+  printf("\n");
+  PrintAndLog("Starting to simulate");
+  UsbCommand c = {CMD_SIMULATE_TAG_125K, {GraphTraceLen, gap, 0}};
+  SendCommand(&c);
+  return 0;
 }
 
 int usage_lf_simfsk(void)
 {
-       //print help
-       PrintAndLog("Usage: lf simfsk [c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>]");
-       PrintAndLog("Options:        ");
-       PrintAndLog("       h              This help");
-       PrintAndLog("       c <clock>      Manually set clock - can autodetect if using DemodBuffer");
-       PrintAndLog("       i              invert data");
-       PrintAndLog("       H <fcHigh>     Manually set the larger Field Clock");
-       PrintAndLog("       L <fcLow>      Manually set the smaller Field Clock");
-       //PrintAndLog("       s              TBD- -to enable a gap between playback repetitions - default: no gap");
-       PrintAndLog("       d <hexdata>    Data to sim as hex - omit to sim from DemodBuffer");
-       PrintAndLog("\n  NOTE: if you set one clock manually set them all manually");
-       return 0;
+  //print help
+  PrintAndLog("Usage: lf simfsk [c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>]");
+  PrintAndLog("Options:        ");
+  PrintAndLog("       h              This help");
+  PrintAndLog("       c <clock>      Manually set clock - can autodetect if using DemodBuffer");
+  PrintAndLog("       i              invert data");
+  PrintAndLog("       H <fcHigh>     Manually set the larger Field Clock");
+  PrintAndLog("       L <fcLow>      Manually set the smaller Field Clock");
+  //PrintAndLog("       s              TBD- -to enable a gap between playback repetitions - default: no gap");
+  PrintAndLog("       d <hexdata>    Data to sim as hex - omit to sim from DemodBuffer");
+  PrintAndLog("\n  NOTE: if you set one clock manually set them all manually");
+  return 0;
 }
 
 int usage_lf_simask(void)
 {
-       //print help
-       PrintAndLog("Usage: lf simask [c <clock>] [i] [b|m|r] [s] [d <raw hex to sim>]");
-       PrintAndLog("Options:        ");
-       PrintAndLog("       h              This help");
-       PrintAndLog("       c <clock>      Manually set clock - can autodetect if using DemodBuffer");
-       PrintAndLog("       i              invert data");
-       PrintAndLog("       b              sim ask/biphase");
-       PrintAndLog("       m              sim ask/manchester - Default");
-       PrintAndLog("       r              sim ask/raw");
-       PrintAndLog("       s              TBD- -to enable a gap between playback repetitions - default: no gap");
-       PrintAndLog("       d <hexdata>    Data to sim as hex - omit to sim from DemodBuffer");
-       return 0;
+  //print help
+  PrintAndLog("Usage: lf simask [c <clock>] [i] [b|m|r] [s] [d <raw hex to sim>]");
+  PrintAndLog("Options:        ");
+  PrintAndLog("       h              This help");
+  PrintAndLog("       c <clock>      Manually set clock - can autodetect if using DemodBuffer");
+  PrintAndLog("       i              invert data");
+  PrintAndLog("       b              sim ask/biphase");
+  PrintAndLog("       m              sim ask/manchester - Default");
+  PrintAndLog("       r              sim ask/raw");
+  PrintAndLog("       s              TBD- -to enable a gap between playback repetitions - default: no gap");
+  PrintAndLog("       d <hexdata>    Data to sim as hex - omit to sim from DemodBuffer");
+  return 0;
 }
 
 int usage_lf_simpsk(void)
 {
-       //print help
-       PrintAndLog("Usage: lf simpsk [1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>]");
-       PrintAndLog("Options:        ");
-       PrintAndLog("       h              This help");
-       PrintAndLog("       c <clock>      Manually set clock - can autodetect if using DemodBuffer");
-       PrintAndLog("       i              invert data");
-       PrintAndLog("       1              set PSK1 (default)");
-       PrintAndLog("       2              set PSK2");
-       PrintAndLog("       3              set PSK3");
-       PrintAndLog("       r <carrier>    2|4|8 are valid carriers: default = 2");
-       PrintAndLog("       d <hexdata>    Data to sim as hex - omit to sim from DemodBuffer");
-       return 0;
+  //print help
+  PrintAndLog("Usage: lf simpsk [1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>]");
+  PrintAndLog("Options:        ");
+  PrintAndLog("       h              This help");
+  PrintAndLog("       c <clock>      Manually set clock - can autodetect if using DemodBuffer");
+  PrintAndLog("       i              invert data");
+  PrintAndLog("       1              set PSK1 (default)");
+  PrintAndLog("       2              set PSK2");
+  PrintAndLog("       3              set PSK3");
+  PrintAndLog("       r <carrier>    2|4|8 are valid carriers: default = 2");
+  PrintAndLog("       d <hexdata>    Data to sim as hex - omit to sim from DemodBuffer");
+  return 0;
 }
 
 // by marshmellow - sim ask data given clock, fcHigh, fcLow, invert 
 // - allow pull data from DemodBuffer
 int CmdLFfskSim(const char *Cmd)
 {
-       //might be able to autodetect FC and clock from Graphbuffer if using demod buffer
-       //will need FChigh, FClow, Clock, and bitstream
-       uint8_t fcHigh=0, fcLow=0, clk=0;
-       uint8_t invert=0;
-       bool errors = FALSE;
-       char hexData[32] = {0x00}; // store entered hex data
-       uint8_t data[255] = {0x00}; 
-       int dataLen = 0;
-       uint8_t cmdp = 0;
-       while(param_getchar(Cmd, cmdp) != 0x00)
-       {
-               switch(param_getchar(Cmd, cmdp))
-               {
-               case 'h':
-                       return usage_lf_simfsk();
-               case 'i':
-                       invert = 1;
-                       cmdp++;
-                       break;
-               case 'c':
-                       errors |= param_getdec(Cmd,cmdp+1,&clk);
-                       cmdp+=2;
-                       break;
-               case 'H':
-                       errors |= param_getdec(Cmd,cmdp+1,&fcHigh);
-                       cmdp+=2;
-                       break;
-               case 'L':
-                       errors |= param_getdec(Cmd,cmdp+1,&fcLow);
-                       cmdp+=2;
-                       break;
-               //case 's':
-               //  separator=1;
-               //  cmdp++;
-               //  break;
-               case 'd':
-                       dataLen = param_getstr(Cmd, cmdp+1, hexData);
-                       if (dataLen==0) {
-                               errors=TRUE; 
-                       } else {
-                               dataLen = hextobinarray((char *)data, hexData);
-                       }   
-                       if (dataLen==0) errors=TRUE; 
-                       if (errors) PrintAndLog ("Error getting hex data");
-                       cmdp+=2;
-                       break;
-               default:
-                       PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
-                       errors = TRUE;
-                       break;
-               }
-               if(errors) break;
-       }
-       if(cmdp == 0 && DemodBufferLen == 0)
-       {
-               errors = TRUE;// No args
-       }
-
-       //Validations
-       if(errors)
-       {
-               return usage_lf_simfsk();
-       }
-
-       if (dataLen == 0){ //using DemodBuffer 
-               if (clk==0 || fcHigh==0 || fcLow==0){ //manual settings must set them all
-                       uint8_t ans = fskClocks(&fcHigh, &fcLow, &clk, 0);
-                       if (ans==0){
-                               if (!fcHigh) fcHigh=10;
-                               if (!fcLow) fcLow=8;
-                               if (!clk) clk=50;
-                       }
-               }
-       } else {
-               setDemodBuf(data, dataLen, 0);
-       }
-       if (clk == 0) clk = 50;
-       if (fcHigh == 0) fcHigh = 10;
-       if (fcLow == 0) fcLow = 8;
-
-       uint16_t arg1, arg2;
-       arg1 = fcHigh << 8 | fcLow;
-       arg2 = invert << 8 | clk;
-       size_t size = DemodBufferLen;
-       if (size > USB_CMD_DATA_SIZE) {
-               PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
-               size = USB_CMD_DATA_SIZE;
-       
-       UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
-
-       memcpy(c.d.asBytes, DemodBuffer, size);
-       SendCommand(&c);
-       return 0;
+  //might be able to autodetect FC and clock from Graphbuffer if using demod buffer
+  //will need FChigh, FClow, Clock, and bitstream
+  uint8_t fcHigh=0, fcLow=0, clk=0;
+  uint8_t invert=0;
+  bool errors = FALSE;
+  char hexData[32] = {0x00}; // store entered hex data
+  uint8_t data[255] = {0x00}; 
+  int dataLen = 0;
+  uint8_t cmdp = 0;
+  while(param_getchar(Cmd, cmdp) != 0x00)
+  {
+    switch(param_getchar(Cmd, cmdp))
+    {
+    case 'h':
+      return usage_lf_simfsk();
+    case 'i':
+      invert = 1;
+      cmdp++;
+      break;
+    case 'c':
+      errors |= param_getdec(Cmd,cmdp+1,&clk);
+      cmdp+=2;
+      break;
+    case 'H':
+      errors |= param_getdec(Cmd,cmdp+1,&fcHigh);
+      cmdp+=2;
+      break;
+    case 'L':
+      errors |= param_getdec(Cmd,cmdp+1,&fcLow);
+      cmdp+=2;
+      break;
+    //case 's':
+    //  separator=1;
+    //  cmdp++;
+    //  break;
+    case 'd':
+      dataLen = param_getstr(Cmd, cmdp+1, hexData);
+      if (dataLen==0) {
+        errors=TRUE; 
+      } else {
+        dataLen = hextobinarray((char *)data, hexData);
+      }   
+      if (dataLen==0) errors=TRUE; 
+      if (errors) PrintAndLog ("Error getting hex data");
+      cmdp+=2;
+      break;
+    default:
+      PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+      errors = TRUE;
+      break;
+    }
+    if(errors) break;
+  }
+  if(cmdp == 0 && DemodBufferLen == 0)
+  {
+    errors = TRUE;// No args
+  }
+
+  //Validations
+  if(errors)
+  {
+    return usage_lf_simfsk();
+  }
+
+  if (dataLen == 0){ //using DemodBuffer 
+    if (clk==0 || fcHigh==0 || fcLow==0){ //manual settings must set them all
+      uint8_t ans = fskClocks(&fcHigh, &fcLow, &clk, 0);
+      if (ans==0){
+        if (!fcHigh) fcHigh=10;
+        if (!fcLow) fcLow=8;
+        if (!clk) clk=50;
+      }
+    }
+  } else {
+    setDemodBuf(data, dataLen, 0);
+  }
+  if (clk == 0) clk = 50;
+  if (fcHigh == 0) fcHigh = 10;
+  if (fcLow == 0) fcLow = 8;
+
+  uint16_t arg1, arg2;
+  arg1 = fcHigh << 8 | fcLow;
+  arg2 = invert << 8 | clk;
+  size_t size = DemodBufferLen;
+  if (size > USB_CMD_DATA_SIZE) {
+    PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
+    size = USB_CMD_DATA_SIZE;
+  } 
+  UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
+
+  memcpy(c.d.asBytes, DemodBuffer, size);
+  SendCommand(&c);
+  return 0;
 }
 
 // by marshmellow - sim ask data given clock, invert, manchester or raw, separator 
 // - allow pull data from DemodBuffer
 int CmdLFaskSim(const char *Cmd)
 {
-       //autodetect clock from Graphbuffer if using demod buffer
-       //will need clock, invert, manchester/raw as m or r, separator as s, and bitstream
-       uint8_t encoding = 1, separator = 0;
-       //char cmdp = Cmd[0], par3='m', par4=0;
-       uint8_t clk=0, invert=0;
-       bool errors = FALSE;
-       char hexData[32] = {0x00}; 
-       uint8_t data[255]= {0x00}; // store entered hex data
-       int dataLen = 0;
-       uint8_t cmdp = 0;
-       while(param_getchar(Cmd, cmdp) != 0x00)
-       {
-               switch(param_getchar(Cmd, cmdp))
-               {
-               case 'h':
-                       return usage_lf_simask();
-               case 'i':
-                       invert = 1;
-                       cmdp++;
-                       break;
-               case 'c':
-                       errors |= param_getdec(Cmd,cmdp+1,&clk);
-                       cmdp+=2;
-                       break;
-               case 'b':
-                       encoding=2; //biphase
-                       cmdp++;
-                       break;
-               case 'm':
-                       encoding=1;
-                       cmdp++;
-                       break;
-               case 'r':
-                       encoding=0;
-                       cmdp++;
-                       break;
-               case 's':
-                       separator=1;
-                       cmdp++;
-                       break;
-               case 'd':
-                       dataLen = param_getstr(Cmd, cmdp+1, hexData);
-                       if (dataLen==0) {
-                               errors=TRUE; 
-                       } else {
-                               dataLen = hextobinarray((char *)data, hexData);
-                       }
-                       if (dataLen==0) errors=TRUE; 
-                       if (errors) PrintAndLog ("Error getting hex data, datalen: %d",dataLen);
-                               cmdp+=2;
-                       break;
-               default:
-                       PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
-                       errors = TRUE;
-                       break;
-               }
-               if(errors) break;
-       }
-       if(cmdp == 0 && DemodBufferLen == 0)
-       {
-               errors = TRUE;// No args
-       }
-
-       //Validations
-       if(errors)
-       {
-               return usage_lf_simask();
-       }
-       if (dataLen == 0){ //using DemodBuffer
-               if (clk == 0) clk = GetAskClock("0", false, false);
-       } else {
-               setDemodBuf(data, dataLen, 0);
-       }
-       if (clk == 0) clk = 64;
-       if (encoding == 0) clk = clk/2; //askraw needs to double the clock speed
-       uint16_t arg1, arg2;
-       size_t size=DemodBufferLen;
-       arg1 = clk << 8 | encoding;
-       arg2 = invert << 8 | separator;
-       if (size > USB_CMD_DATA_SIZE) {
-               PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
-               size = USB_CMD_DATA_SIZE;
-       }
-       UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
-       PrintAndLog("preparing to sim ask data: %d bits", size);
-       memcpy(c.d.asBytes, DemodBuffer, size);
-       SendCommand(&c);
-       return 0;
+  //autodetect clock from Graphbuffer if using demod buffer
+  //will need clock, invert, manchester/raw as m or r, separator as s, and bitstream
+  uint8_t encoding = 1, separator = 0;
+  //char cmdp = Cmd[0], par3='m', par4=0;
+  uint8_t clk=0, invert=0;
+  bool errors = FALSE;
+  char hexData[32] = {0x00}; 
+  uint8_t data[255]= {0x00}; // store entered hex data
+  int dataLen = 0;
+  uint8_t cmdp = 0;
+  while(param_getchar(Cmd, cmdp) != 0x00)
+  {
+    switch(param_getchar(Cmd, cmdp))
+    {
+    case 'h':
+      return usage_lf_simask();
+    case 'i':
+      invert = 1;
+      cmdp++;
+      break;
+    case 'c':
+      errors |= param_getdec(Cmd,cmdp+1,&clk);
+      cmdp+=2;
+      break;
+    case 'b':
+      encoding=2; //biphase
+      cmdp++;
+      break;
+    case 'm':
+      encoding=1;
+      cmdp++;
+      break;
+    case 'r':
+      encoding=0;
+      cmdp++;
+      break;
+    case 's':
+      separator=1;
+      cmdp++;
+      break;
+    case 'd':
+      dataLen = param_getstr(Cmd, cmdp+1, hexData);
+      if (dataLen==0) {
+        errors=TRUE; 
+      } else {
+        dataLen = hextobinarray((char *)data, hexData);
+      }
+      if (dataLen==0) errors=TRUE; 
+      if (errors) PrintAndLog ("Error getting hex data, datalen: %d",dataLen);
+        cmdp+=2;
+      break;
+    default:
+      PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+      errors = TRUE;
+      break;
+    }
+    if(errors) break;
+  }
+  if(cmdp == 0 && DemodBufferLen == 0)
+  {
+    errors = TRUE;// No args
+  }
+
+  //Validations
+  if(errors)
+  {
+    return usage_lf_simask();
+  }
+  if (dataLen == 0){ //using DemodBuffer
+    if (clk == 0) clk = GetAskClock("0", false, false);
+  } else {
+    setDemodBuf(data, dataLen, 0);
+  }
+  if (clk == 0) clk = 64;
+  if (encoding == 0) clk = clk/2; //askraw needs to double the clock speed
+  uint16_t arg1, arg2;
+  size_t size=DemodBufferLen;
+  arg1 = clk << 8 | encoding;
+  arg2 = invert << 8 | separator;
+  if (size > USB_CMD_DATA_SIZE) {
+    PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
+    size = USB_CMD_DATA_SIZE;
+  }
+  UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
+  PrintAndLog("preparing to sim ask data: %d bits", size);
+  memcpy(c.d.asBytes, DemodBuffer, size);
+  SendCommand(&c);
+  return 0;
 }
 
 // by marshmellow - sim psk data given carrier, clock, invert 
 // - allow pull data from DemodBuffer or parameters
 int CmdLFpskSim(const char *Cmd)
 {
-       //might be able to autodetect FC and clock from Graphbuffer if using demod buffer
-       //will need carrier, Clock, and bitstream
-       uint8_t carrier=0, clk=0;
-       uint8_t invert=0;
-       bool errors = FALSE;
-       char hexData[32] = {0x00}; // store entered hex data
-       uint8_t data[255] = {0x00}; 
-       int dataLen = 0;
-       uint8_t cmdp = 0;
-       uint8_t pskType = 1;
-       while(param_getchar(Cmd, cmdp) != 0x00)
-       {
-               switch(param_getchar(Cmd, cmdp))
-               {
-               case 'h':
-                       return usage_lf_simpsk();
-               case 'i':
-                       invert = 1;
-                       cmdp++;
-                       break;
-               case 'c':
-                       errors |= param_getdec(Cmd,cmdp+1,&clk);
-                       cmdp+=2;
-                       break;
-               case 'r':
-                       errors |= param_getdec(Cmd,cmdp+1,&carrier);
-                       cmdp+=2;
-                       break;
-               case '1':
-                       pskType=1;
-                       cmdp++;
-                       break;
-               case '2':
-                       pskType=2;
-                       cmdp++;
-                       break;
-               case '3':
-                       pskType=3;
-                       cmdp++;
-                       break;
-               case 'd':
-                       dataLen = param_getstr(Cmd, cmdp+1, hexData);
-                       if (dataLen==0) {
-                               errors=TRUE; 
-                       } else {
-                               dataLen = hextobinarray((char *)data, hexData);
-                       }    
-                       if (dataLen==0) errors=TRUE; 
-                       if (errors) PrintAndLog ("Error getting hex data");
-                       cmdp+=2;
-                       break;
-               default:
-                       PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
-                       errors = TRUE;
-                       break;
-               }
-               if (errors) break;
-       }
-       if (cmdp == 0 && DemodBufferLen == 0)
-       {
-               errors = TRUE;// No args
-       }
-
-       //Validations
-       if (errors)
-       {
-               return usage_lf_simpsk();
-       }
-       if (dataLen == 0){ //using DemodBuffer
-               PrintAndLog("Getting Clocks");
-               if (clk==0) clk = GetPskClock("", FALSE, FALSE);
-               PrintAndLog("clk: %d",clk);
-               if (!carrier) carrier = GetPskCarrier("", FALSE, FALSE); 
-               PrintAndLog("carrier: %d", carrier);
-       } else {
-               setDemodBuf(data, dataLen, 0);
-       }
-
-       if (clk <= 0) clk = 32;
-       if (carrier == 0) carrier = 2;
-       if (pskType != 1){
-               if (pskType == 2){
-                       //need to convert psk2 to psk1 data before sim
-                       psk2TOpsk1(DemodBuffer, DemodBufferLen);
-               } else {
-                       PrintAndLog("Sorry, PSK3 not yet available");
-               }
-       }
-       uint16_t arg1, arg2;
-       arg1 = clk << 8 | carrier;
-       arg2 = invert;
-       size_t size=DemodBufferLen;
-       if (size > USB_CMD_DATA_SIZE) {
-               PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
-               size=USB_CMD_DATA_SIZE;
-       }
-       UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}};
-       PrintAndLog("DEBUG: Sending DemodBuffer Length: %d", size);
-       memcpy(c.d.asBytes, DemodBuffer, size);
-       SendCommand(&c);
-       
-       return 0;
+  //might be able to autodetect FC and clock from Graphbuffer if using demod buffer
+  //will need carrier, Clock, and bitstream
+  uint8_t carrier=0, clk=0;
+  uint8_t invert=0;
+  bool errors = FALSE;
+  char hexData[32] = {0x00}; // store entered hex data
+  uint8_t data[255] = {0x00}; 
+  int dataLen = 0;
+  uint8_t cmdp = 0;
+  uint8_t pskType = 1;
+  while(param_getchar(Cmd, cmdp) != 0x00)
+  {
+    switch(param_getchar(Cmd, cmdp))
+    {
+    case 'h':
+      return usage_lf_simpsk();
+    case 'i':
+      invert = 1;
+      cmdp++;
+      break;
+    case 'c':
+      errors |= param_getdec(Cmd,cmdp+1,&clk);
+      cmdp+=2;
+      break;
+    case 'r':
+      errors |= param_getdec(Cmd,cmdp+1,&carrier);
+      cmdp+=2;
+      break;
+    case '1':
+      pskType=1;
+      cmdp++;
+      break;
+    case '2':
+      pskType=2;
+      cmdp++;
+      break;
+    case '3':
+      pskType=3;
+      cmdp++;
+      break;
+    case 'd':
+      dataLen = param_getstr(Cmd, cmdp+1, hexData);
+      if (dataLen==0) {
+        errors=TRUE; 
+      } else {
+        dataLen = hextobinarray((char *)data, hexData);
+      }    
+      if (dataLen==0) errors=TRUE; 
+      if (errors) PrintAndLog ("Error getting hex data");
+      cmdp+=2;
+      break;
+    default:
+      PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+      errors = TRUE;
+      break;
+    }
+    if (errors) break;
+  }
+  if (cmdp == 0 && DemodBufferLen == 0)
+  {
+    errors = TRUE;// No args
+  }
+
+  //Validations
+  if (errors)
+  {
+    return usage_lf_simpsk();
+  }
+  if (dataLen == 0){ //using DemodBuffer
+    PrintAndLog("Getting Clocks");
+    if (clk==0) clk = GetPskClock("", FALSE, FALSE);
+    PrintAndLog("clk: %d",clk);
+    if (!carrier) carrier = GetPskCarrier("", FALSE, FALSE); 
+    PrintAndLog("carrier: %d", carrier);
+  } else {
+    setDemodBuf(data, dataLen, 0);
+  }
+
+  if (clk <= 0) clk = 32;
+  if (carrier == 0) carrier = 2;
+  if (pskType != 1){
+    if (pskType == 2){
+      //need to convert psk2 to psk1 data before sim
+      psk2TOpsk1(DemodBuffer, DemodBufferLen);
+    } else {
+      PrintAndLog("Sorry, PSK3 not yet available");
+    }
+  }
+  uint16_t arg1, arg2;
+  arg1 = clk << 8 | carrier;
+  arg2 = invert;
+  size_t size=DemodBufferLen;
+  if (size > USB_CMD_DATA_SIZE) {
+    PrintAndLog("DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE);
+    size=USB_CMD_DATA_SIZE;
+  }
+  UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}};
+  PrintAndLog("DEBUG: Sending DemodBuffer Length: %d", size);
+  memcpy(c.d.asBytes, DemodBuffer, size);
+  SendCommand(&c);
+  
+  return 0;
 }
 
 int CmdLFSimBidir(const char *Cmd)
 {
-       // Set ADC to twice the carrier for a slight supersampling
-       // HACK: not implemented in ARMSRC.
-       PrintAndLog("Not implemented yet.");
-       UsbCommand c = {CMD_LF_SIMULATE_BIDIR, {47, 384, 0}};
-       SendCommand(&c);
-       return 0;
+  // Set ADC to twice the carrier for a slight supersampling
+  // HACK: not implemented in ARMSRC.
+  PrintAndLog("Not implemented yet.");
+  UsbCommand c = {CMD_LF_SIMULATE_BIDIR, {47, 384, 0}};
+  SendCommand(&c);
+  return 0;
 }
 
 /* simulate an LF Manchester encoded tag with specified bitstream, clock rate and inter-id gap */
 /*
 int CmdLFSimManchester(const char *Cmd)
 {
-       static int clock, gap;
-       static char data[1024], gapstring[8];
+  static int clock, gap;
+  static char data[1024], gapstring[8];
 
-       sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap);
+  sscanf(Cmd, "%i %s %i", &clock, &data[0], &gap);
 
-       ClearGraph(0);
+  ClearGraph(0);
 
-       for (int i = 0; i < strlen(data) ; ++i)
-               AppendGraph(0, clock, data[i]- '0');
+  for (int i = 0; i < strlen(data) ; ++i)
+    AppendGraph(0, clock, data[i]- '0');
 
-       CmdManchesterMod("");
+  CmdManchesterMod("");
 
-       RepaintGraphWindow();
+  RepaintGraphWindow();
 
-       sprintf(&gapstring[0], "%i", gap);
-       CmdLFSim(gapstring);
-       return 0;
+  sprintf(&gapstring[0], "%i", gap);
+  CmdLFSim(gapstring);
+  return 0;
 }
 */
 
 int CmdVchDemod(const char *Cmd)
 {
-       // Is this the entire sync pattern, or does this also include some
-       // data bits that happen to be the same everywhere? That would be
-       // lovely to know.
-       static const int SyncPattern[] = {
-               1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-               1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-               1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-               1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-               1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-               1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-               1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-               1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-               1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
-               1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-       };
-
-       // So first, we correlate for the sync pattern, and mark that.
-       int bestCorrel = 0, bestPos = 0;
-       int i;
-       // It does us no good to find the sync pattern, with fewer than
-       // 2048 samples after it...
-       for (i = 0; i < (GraphTraceLen-2048); i++) {
-               int sum = 0;
-               int j;
-               for (j = 0; j < arraylen(SyncPattern); j++) {
-                       sum += GraphBuffer[i+j]*SyncPattern[j];
-               }
-               if (sum > bestCorrel) {
-                       bestCorrel = sum;
-                       bestPos = i;
-               }
-       }
-       PrintAndLog("best sync at %d [metric %d]", bestPos, bestCorrel);
-
-       char bits[257];
-       bits[256] = '\0';
-
-       int worst = INT_MAX;
-       int worstPos = 0;
-
-       for (i = 0; i < 2048; i += 8) {
-               int sum = 0;
-               int j;
-               for (j = 0; j < 8; j++) {
-                       sum += GraphBuffer[bestPos+i+j];
-               }
-               if (sum < 0) {
-                       bits[i/8] = '.';
-               } else {
-                       bits[i/8] = '1';
-               }
-               if(abs(sum) < worst) {
-                       worst = abs(sum);
-                       worstPos = i;
-               }
-       }
-       PrintAndLog("bits:");
-       PrintAndLog("%s", bits);
-       PrintAndLog("worst metric: %d at pos %d", worst, worstPos);
-
-       if (strcmp(Cmd, "clone")==0) {
-               GraphTraceLen = 0;
-               char *s;
-               for(s = bits; *s; s++) {
-                       int j;
-                       for(j = 0; j < 16; j++) {
-                               GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;
-                       }
-               }
-               RepaintGraphWindow();
-       }
-       return 0;
+  // Is this the entire sync pattern, or does this also include some
+  // data bits that happen to be the same everywhere? That would be
+  // lovely to know.
+  static const int SyncPattern[] = {
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+    1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+    1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+    1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+    1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+    1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,
+    1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  };
+
+  // So first, we correlate for the sync pattern, and mark that.
+  int bestCorrel = 0, bestPos = 0;
+  int i;
+  // It does us no good to find the sync pattern, with fewer than
+  // 2048 samples after it...
+  for (i = 0; i < (GraphTraceLen-2048); i++) {
+    int sum = 0;
+    int j;
+    for (j = 0; j < arraylen(SyncPattern); j++) {
+      sum += GraphBuffer[i+j]*SyncPattern[j];
+    }
+    if (sum > bestCorrel) {
+      bestCorrel = sum;
+      bestPos = i;
+    }
+  }
+  PrintAndLog("best sync at %d [metric %d]", bestPos, bestCorrel);
+
+  char bits[257];
+  bits[256] = '\0';
+
+  int worst = INT_MAX;
+  int worstPos = 0;
+
+  for (i = 0; i < 2048; i += 8) {
+    int sum = 0;
+    int j;
+    for (j = 0; j < 8; j++) {
+      sum += GraphBuffer[bestPos+i+j];
+    }
+    if (sum < 0) {
+      bits[i/8] = '.';
+    } else {
+      bits[i/8] = '1';
+    }
+    if(abs(sum) < worst) {
+      worst = abs(sum);
+      worstPos = i;
+    }
+  }
+  PrintAndLog("bits:");
+  PrintAndLog("%s", bits);
+  PrintAndLog("worst metric: %d at pos %d", worst, worstPos);
+
+  if (strcmp(Cmd, "clone")==0) {
+    GraphTraceLen = 0;
+    char *s;
+    for(s = bits; *s; s++) {
+      int j;
+      for(j = 0; j < 16; j++) {
+        GraphBuffer[GraphTraceLen++] = (*s == '1') ? 1 : 0;
+      }
+    }
+    RepaintGraphWindow();
+  }
+  return 0;
 }
 
 //by marshmellow
 int CmdLFfind(const char *Cmd)
 {
-       int ans=0;
-       char cmdp = param_getchar(Cmd, 0);
-       char testRaw = param_getchar(Cmd, 1);
-       if (strlen(Cmd) > 3 || cmdp == 'h' || cmdp == 'H') {
-               PrintAndLog("Usage:  lf search <0|1> [u]");
-               PrintAndLog("     <use data from Graphbuffer> , if not set, try reading data from tag.");
-               PrintAndLog("     [Search for Unknown tags] , if not set, reads only known tags.");
-               PrintAndLog("");
-               PrintAndLog("    sample: lf search     = try reading data from tag & search for known tags");
-               PrintAndLog("          : lf search 1   = use data from GraphBuffer & search for known tags");
-               PrintAndLog("          : lf search u   = try reading data from tag & search for known and unknown tags");
-               PrintAndLog("          : lf search 1 u = use data from GraphBuffer & search for known and unknown tags");
-
-               return 0;
-       }
-
-       if (!offline && (cmdp != '1')){
-               ans=CmdLFRead("");
-               ans=CmdSamples("20000");
-       } else if (GraphTraceLen < 1000) {
-               PrintAndLog("Data in Graphbuffer was too small.");
-               return 0;
-       }
-       if (cmdp == 'u' || cmdp == 'U') testRaw = 'u';
-
-       PrintAndLog("NOTE: some demods output possible binary\n  if it finds something that looks like a tag");
-       PrintAndLog("False Positives ARE possible\n");  
-       PrintAndLog("\nChecking for known tags:\n");
-
-       ans=CmdFSKdemodIO("");
-       if (ans>0) {
-               PrintAndLog("\nValid IO Prox ID Found!");
-               return 1;
-       }
-
-       ans=CmdFSKdemodPyramid("");
-       if (ans>0) {
-               PrintAndLog("\nValid Pyramid ID Found!");
-               return 1;
-       }
-
-       ans=CmdFSKdemodParadox("");
-       if (ans>0) {
-               PrintAndLog("\nValid Paradox ID Found!");
-               return 1;
-       }
-
-       ans=CmdFSKdemodAWID("");
-       if (ans>0) {
-               PrintAndLog("\nValid AWID ID Found!");
-               return 1;
-       }
-
-       ans=CmdFSKdemodHID("");
-       if (ans>0) {
-               PrintAndLog("\nValid HID Prox ID Found!");
-               return 1;
-       }
-
-       //add psk and indala
-       ans=CmdIndalaDecode("");
-       if (ans>0) {
-               PrintAndLog("\nValid Indala ID Found!");
-               return 1;
-       }
-
-       ans=CmdAskEM410xDemod("");
-       if (ans>0) {
-               PrintAndLog("\nValid EM410x ID Found!");
-               return 1;
-       }
+  int ans=0;
+  char cmdp = param_getchar(Cmd, 0);
+  char testRaw = param_getchar(Cmd, 1);
+  if (strlen(Cmd) > 3 || cmdp == 'h' || cmdp == 'H') {
+    PrintAndLog("Usage:  lf search <0|1> [u]");
+    PrintAndLog("     <use data from Graphbuffer> , if not set, try reading data from tag.");
+    PrintAndLog("     [Search for Unknown tags] , if not set, reads only known tags.");
+    PrintAndLog("");
+    PrintAndLog("    sample: lf search     = try reading data from tag & search for known tags");
+    PrintAndLog("          : lf search 1   = use data from GraphBuffer & search for known tags");
+    PrintAndLog("          : lf search u   = try reading data from tag & search for known and unknown tags");
+    PrintAndLog("          : lf search 1 u = use data from GraphBuffer & search for known and unknown tags");
+    return 0;
+  }
+
+  if (!offline && (cmdp != '1')){
+    ans=CmdLFRead("");
+    ans=CmdSamples("20000");
+  } else if (GraphTraceLen < 1000) {
+    PrintAndLog("Data in Graphbuffer was too small.");
+    return 0;
+  }
+  if (cmdp == 'u' || cmdp == 'U') testRaw = 'u';
+
+  PrintAndLog("NOTE: some demods output possible binary\n  if it finds something that looks like a tag");
+  PrintAndLog("False Positives ARE possible\n");  
+  PrintAndLog("\nChecking for known tags:\n");
+
+  ans=CmdFSKdemodIO("");
+  
+  if (ans>0) {
+    PrintAndLog("\nValid IO Prox ID Found!");
+    return 1;
+  }
+
+  ans=CmdFSKdemodPyramid("");
+  if (ans>0) {
+    PrintAndLog("\nValid Pyramid ID Found!");
+    return 1;
+  }
+
+  ans=CmdFSKdemodParadox("");
+  if (ans>0) {
+    PrintAndLog("\nValid Paradox ID Found!");
+    return 1;
+  }
+
+  ans=CmdFSKdemodAWID("");
+  if (ans>0) {
+    PrintAndLog("\nValid AWID ID Found!");
+    return 1;
+  }
+
+  ans=CmdFSKdemodHID("");
+  if (ans>0) {
+    PrintAndLog("\nValid HID Prox ID Found!");
+    return 1;
+  }
+
+  //add psk and indala
+  ans=CmdIndalaDecode("");
+  if (ans>0) {
+    PrintAndLog("\nValid Indala ID Found!");
+    return 1;
+  }
+
+  ans=CmdAskEM410xDemod("");
+  if (ans>0) {
+    PrintAndLog("\nValid EM410x ID Found!");
+    return 1;
+  }
+
+  ans=CmdG_Prox_II_Demod("");
+  if (ans>0) {
+    PrintAndLog("\nValid G Prox II ID Found!");
+    return 1;
+  }
+
+  PrintAndLog("\nNo Known Tags Found!\n");
+  if (testRaw=='u' || testRaw=='U'){
+    //test unknown tag formats (raw mode)
+    PrintAndLog("\nChecking for Unknown tags:\n");
+    ans=AutoCorrelate(4000, FALSE, FALSE);
+       
+    if (ans > 0) {
 
-       ans=CmdG_Prox_II_Demod("");
-       if (ans>0) {
-               PrintAndLog("\nValid G Prox II ID Found!");
-               return 1;
-       }
+               PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
 
-       PrintAndLog("\nNo Known Tags Found!\n");
-       if (testRaw=='u' || testRaw=='U'){
-               //test unknown tag formats (raw mode)
-               PrintAndLog("\nChecking for Unknown tags:\n");
-               ans=AutoCorrelate(4000, FALSE, FALSE);
-               if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
-               ans=GetFskClock("",FALSE,FALSE); //CmdDetectClockRate("F"); //
-               if (ans != 0){ //fsk
-                       ans=FSKrawDemod("",FALSE);
-                       if (ans>0) {
-                               PrintAndLog("\nUnknown FSK Modulated Tag Found!");
-                               printDemodBuff();
-                               return 1;
+               if ( ans % 8 == 0)  {
+                       int bytes = (ans / 8);
+                       PrintAndLog("Possible %d bytes", bytes);
+                       int blocks = 0;
+                       if ( bytes % 2 == 0) {
+                               blocks = (bytes / 2);   
+                               PrintAndLog("Possible  2 blocks, width %d", blocks);
+                       }
+                       if ( bytes % 4 == 0) {
+                               blocks = (bytes / 4);   
+                               PrintAndLog("Possible  4 blocks, width %d", blocks);
+                       }
+                       if ( bytes % 8 == 0) {
+                               blocks = (bytes / 8);   
+                               PrintAndLog("Possible  8 blocks, width %d", blocks);
+                       }
+                       if ( bytes % 16 == 0) {
+                               blocks = (bytes / 16);  
+                               PrintAndLog("Possible 16 blocks, width %d", blocks);
                        }
                }
-               ans=ASKmanDemod("",FALSE,FALSE);
-               if (ans>0) {
-                       PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
-                       PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'");
-                       printDemodBuff();
-                       return 1;
-               }
-               ans=CmdPSK1rawDemod("");
-               if (ans>0) {
-                       PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'");
-                       PrintAndLog("\nCould also be PSK3 - [currently not supported]");
-                       PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod");
-                       printDemodBuff();
-                       return 1;
-               }
-               PrintAndLog("\nNo Data Found!\n");
        }
-       return 0;
+    ans=GetFskClock("",FALSE,FALSE); //CmdDetectClockRate("F"); //
+    if (ans != 0){ //fsk
+      ans=FSKrawDemod("",FALSE);
+      if (ans>0) {
+        PrintAndLog("\nUnknown FSK Modulated Tag Found!");
+        printDemodBuff();
+        return 1;
+      }
+    }
+    ans=ASKmanDemod("",FALSE,FALSE);
+    if (ans>0) {
+      PrintAndLog("\nUnknown ASK Modulated and Manchester encoded Tag Found!");
+      PrintAndLog("\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'");
+      printDemodBuff();
+      return 1;
+    }
+    ans=CmdPSK1rawDemod("");
+    if (ans>0) {
+      PrintAndLog("Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'");
+      PrintAndLog("\nCould also be PSK3 - [currently not supported]");
+      PrintAndLog("\nCould also be NRZ - try 'data nrzrawdemod");
+      printDemodBuff();
+      return 1;
+    }
+    PrintAndLog("\nNo Data Found!\n");
+  }
+  return 0;
 }
 
 static command_t CommandTable[] = 
 {
-       {"help",        CmdHelp,            1, "This help"},
-       {"cmdread",     CmdLFCommandRead,   0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
-       {"em4x",        CmdLFEM4X,          1, "{ EM4X RFIDs... }"},
-       {"config",      CmdLFSetConfig,     0, "Set config for LF sampling, bit/sample, decimation, frequency"},
-       {"flexdemod",   CmdFlexdemod,       1, "Demodulate samples for FlexPass"},
-       {"hid",         CmdLFHID,           1, "{ HID RFIDs... }"},
-       {"io",            CmdLFIO,                1, "{ ioProx tags... }"},
-       {"indalademod", CmdIndalaDemod,     1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
-       {"indalaclone", CmdIndalaClone,     0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
-       {"read",        CmdLFRead,          0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
-       {"search",      CmdLFfind,          1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"},
-       {"sim",         CmdLFSim,           0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
-       {"simask",      CmdLFaskSim,        0, "[clock] [invert <1|0>] [manchester/raw <'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
-       {"simfsk",      CmdLFfskSim,        0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
-       {"simpsk",      CmdLFpskSim,        0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
-       {"simbidir",    CmdLFSimBidir,      0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
-       //{"simman",      CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
-       {"snoop",       CmdLFSnoop,         0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
-       {"ti",          CmdLFTI,            1, "{ TI RFIDs... }"},
-       {"hitag",       CmdLFHitag,         1, "{ Hitag tags and transponders... }"},
-       {"vchdemod",    CmdVchDemod,        1, "['clone'] -- Demodulate samples for VeriChip"},
-       {"t55xx",       CmdLFT55XX,         1, "{ T55xx RFIDs... }"},
-       {"pcf7931",     CmdLFPCF7931,       1, "{PCF7931 RFIDs...}"},
-       {NULL, NULL, 0, NULL}
+  {"help",        CmdHelp,            1, "This help"},
+  {"em4x",        CmdLFEM4X,          1, "{ EM4X RFIDs... }"},
+  {"hid",         CmdLFHID,           1, "{ HID RFIDs... }"},
+  {"hitag",       CmdLFHitag,         1, "{ HITAG RFIDs... }"},
+  {"io",                 CmdLFIO,                1, "{ IOPROX RFIDs... }"},
+  {"pcf7931",     CmdLFPCF7931,       1, "{ PCF7931 RFIDs... }"},
+  {"ti",          CmdLFTI,            1, "{ TI RFIDs... }"},
+  {"t55xx",       CmdLFT55XX,         1, "{ T55X7 RFIDs... }"},
+
+  {"config",      CmdLFSetConfig,     0, "Set config for LF sampling, bit/sample, decimation, frequency"},
+  {"cmdread",     CmdLFCommandRead,   0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
+  {"flexdemod",   CmdFlexdemod,       1, "Demodulate samples for FlexPass"},
+  {"indalademod", CmdIndalaDemod,     1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
+  {"indalaclone", CmdIndalaClone,     0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
+  {"read",        CmdLFRead,          0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
+  {"search",      CmdLFfind,          1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"},
+  {"sim",         CmdLFSim,           0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
+  {"simask",      CmdLFaskSim,        0, "[clock] [invert <1|0>] [manchester/raw <'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
+  {"simfsk",      CmdLFfskSim,        0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
+  {"simpsk",      CmdLFpskSim,        0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
+  {"simbidir",    CmdLFSimBidir,      0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
+  //{"simman",      CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
+  {"snoop",       CmdLFSnoop,         0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
+  {"vchdemod",    CmdVchDemod,        1, "['clone'] -- Demodulate samples for VeriChip"},
+  {NULL, NULL, 0, NULL}
 };
 
 int CmdLF(const char *Cmd)
 {
-       CmdsParse(CommandTable, Cmd);
-       return 0; 
+  CmdsParse(CommandTable, Cmd);
+  return 0; 
 }
 
 int CmdHelp(const char *Cmd)
 {
-       CmdsHelp(CommandTable);
-       return 0;
+  CmdsHelp(CommandTable);
+  return 0;
 }
diff --git a/client/cmdlfawid26.c b/client/cmdlfawid26.c
new file mode 100644 (file)
index 0000000..48e599d
--- /dev/null
@@ -0,0 +1,208 @@
+//-----------------------------------------------------------------------------
+//
+// 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.
+//-----------------------------------------------------------------------------
+// Low frequency AWID26 commands
+//-----------------------------------------------------------------------------
+
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include "proxmark3.h"
+#include "ui.h"
+//#include "graph.h"
+#include "cmdmain.h"
+#include "cmdparser.h"
+//#include "cmddata.h"
+#include "cmdlf.h"
+#include "cmdlfawid26.h"
+#include "util.h"
+//#include "data.h"
+
+
+static int CmdHelp(const char *Cmd);
+
+int CmdClone(const char *Cmd)
+{
+       char cmdp = param_getchar(Cmd, 0);
+
+       if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
+               PrintAndLog("Usage:  lf awid26 clone  <facility> <id>");
+               PrintAndLog("     [], ");
+               PrintAndLog("");
+               PrintAndLog("     sample: lf awid26 clone 15 2233");
+               return 0;
+       }
+
+       //sscanf(Cmd, "%d %d", &facilitycode, &cardno);
+
+       // char block0 = "00107060";  
+       // char block1 = "00107060";  
+       // char block2 = "00107060";  
+       // char block3 = "00107060";  
+
+       unsigned char buf[10] = {0x00};
+       unsigned char *resp = buf;
+       
+       
+       awid26_hex_to_uid(resp, "");
+       // PrintAndLog("Writing block %d with data %08X", Block, Data);
+       return 0;
+}
+
+
+// convert 96 bit AWID FSK data to 8 digit BCD UID
+bool awid26_hex_to_uid(unsigned char *response, char *awid26)
+{
+       //uint8_t i, tmp[96], tmp1[7];
+       //uint8_t tmp[96] = {0x00};
+    //int site;
+    //int id;
+       
+    //if(!hextobinarray(tmp, awid26))
+        return false;
+
+    // // data is in blocks of 4 bits - every 4th bit is parity, except the first
+    // // block which is all zeros
+    // for(i= 0 ; i < 4 ; ++i)
+        // if(tmp[i] != 0x00)
+            // return false;
+
+    // // discard 1st block
+    // memcpy(tmp, tmp + 4, 92);
+
+    // // check and strip parity on the rest
+    // for(i= 1 ; i < 23 ; ++i)
+        // if(tmp[(i * 4) - 1] != GetParity(tmp + (i - 1) * 4, ODD, 3))
+            // return false;
+        // else
+            // memcpy((tmp + (i - 1) * 3), tmp + (i - 1) * 4, 3);
+
+    // // discard the rest of the header - 1 more 3 bit block
+    // memcpy(tmp, tmp + 3, 66);
+
+    // // next 8 bits is data length - should be 26: 0x1A
+    // binarraytohex(tmp1, tmp, 8);
+    // if(strcmp(tmp1, "1A") != 0)
+        // return false;
+    // memcpy(tmp, tmp +8, 58);
+
+    // // standard wiegand parity check - even for 1st 12 bits, odd for 2nd 12
+    // if(tmp[0] != GetParity(tmp + 1, EVEN, 12))
+        // return false;
+    // if(tmp[25] != GetParity(tmp + 13, ODD, 12))
+        // return false;
+
+    // // convert to hex, ignoring parity bits
+    // if(!binarraytohex(tmp1, tmp + 1, 24))
+        // return false;
+
+    // // convert hex to site/id
+    // sscanf(tmp1,"%2X%4X", &site, &id);
+
+    // // final output 8 byte BCD
+    // sprintf(response,"%03d%05d", site, id);
+
+    return true;
+}
+
+// convert null-terminated BCD UID (8 digits) to 96 bit awid26 encoded binary array
+bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd)
+{
+    // char i, p, tmp1[8], tmp2[26];
+    // int tmpint;
+
+    // if(strlen(bcd) != 8)
+        // return false;
+
+    // // convert BCD site code to HEX
+    // sscanf(bcd, "%03d", &tmpint);
+    // sprintf(tmp2, "%02x", tmpint);
+    // memcpy(tmp1, tmp2, 2);
+
+    // // convert BCD ID to HEX
+    // sscanf(bcd + 3, "%05d", &tmpint);;
+    // sprintf(tmp2, "%04x", tmpint);
+       
+    // // copy with trailing NULL
+    // memcpy(tmp1 + 2, tmp2, 5);
+
+    // // convert full HEX to binary, leaving room for parity prefix
+    // hextobinarray(tmp2 + 1, tmp1);
+    
+    // wiegand_add_parity(tmp2, tmp2 + 1, 24);
+
+    // memset(awid26, '\x0', 96);
+
+    // // magic 18 bit awid26 header (we will overwrite the last two bits)
+    // hextobinarray(awid26, "011D8");
+
+    // // copy to target leaving space for parity bits
+    // for(i= 0, p= 18 ; i < 26 ; ++i, ++p)
+    // {
+        // // skip target bit if this is a parity location
+        // if(!((p + 1) % 4))
+            // p += 1;
+        // awid26[p]= tmp2[i];
+    // }
+
+    // // add parity bits
+    // for(i= 1 ; i < 24 ; ++i)
+        // awid26[((i + 1) * 4) - 1]= GetParity(&awid26[i * 4], ODD, 3);
+
+    return false;
+}
+
+// int CmdReadTrace(const char *Cmd)
+// {
+
+       // uint8_t bits[LF_BITSSTREAM_LEN] = {0x00};
+       // uint8_t * bitstream = bits;
+       
+       // uint8_t si = 5;
+       // uint32_t bl0     = PackBits(si, 32, bitstream);
+       // uint32_t bl1     = PackBits(si+32, 32, bitstream);
+       
+       // uint32_t acl     = PackBits(si,  8, bitstream); si += 8;
+       // uint32_t mfc     = PackBits(si, 8, bitstream); si += 8;
+       // uint32_t cid     = PackBits(si, 5, bitstream); si += 5;
+       // uint32_t icr     = PackBits(si, 3, bitstream); si += 3;
+       // uint32_t year    = PackBits(si, 4, bitstream); si += 4;
+       // uint32_t quarter = PackBits(si, 2, bitstream); si += 2;
+       // uint32_t lotid    = PackBits(si, 12, bitstream); si += 12;
+       // uint32_t wafer   = PackBits(si, 5, bitstream); si += 5;
+       // uint32_t dw      = PackBits(si, 15, bitstream); 
+       
+       // PrintAndLog("");
+       // PrintAndLog("-- T55xx Trace Information ----------------------------------");
+       // PrintAndLog("-------------------------------------------------------------");
+       // PrintAndLog(" ACL Allocation class (ISO/IEC 15963-1)  : 0x%02X (%d)", acl, acl);
+       // PrintAndLog(" MFC Manufacturer ID (ISO/IEC 7816-6)    : 0x%02X (%d)", mfc, mfc);
+       // PrintAndLog(" CID                                     : 0x%02X (%d)", cid, cid);
+       // PrintAndLog(" ICR IC Revision                         : %d",icr );
+       
+       
+  // return 0;
+// }
+
+static command_t CommandTable[] =
+{
+  {"help",   CmdHelp,     1, "This help"},
+  {"clone",  CmdClone,    1, "<facility> <id> -- clone AWID26 to t55xx tag"},
+  {NULL, NULL, 0, NULL}
+};
+
+int CmdLFAWID26(const char *Cmd)
+{
+  CmdsParse(CommandTable, Cmd);
+  return 0;
+}
+
+int CmdHelp(const char *Cmd)
+{
+  CmdsHelp(CommandTable);
+  return 0;
+}
diff --git a/client/cmdlfawid26.h b/client/cmdlfawid26.h
new file mode 100644 (file)
index 0000000..7c23d56
--- /dev/null
@@ -0,0 +1,18 @@
+//-----------------------------------------------------------------------------
+//
+// 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.
+//-----------------------------------------------------------------------------
+// Low frequency AWID 26 commands
+//-----------------------------------------------------------------------------
+
+#ifndef CMDLFAWID26_H__
+#define CMDLFAWID26_H__
+
+int CmdLFAWID26(const char *Cmd);
+
+int CmdClone(const char *Cmd);
+bool awid26_hex_to_uid(unsigned char *response, char *awid26);
+bool bcd_to_awid26_bin(unsigned char *awid26, unsigned char *bcd);
+#endif
index b915aa5aac5f62f63e7d35a70f6bd23a61cf78cd..22b12aa48ee7b8aea47f56c965aa1980de8d0c55 100644 (file)
@@ -69,9 +69,9 @@ int CmdEM410xSim(const char *Cmd)
        uint8_t uid[5] = {0x00};
 
        if (cmdp == 'h' || cmdp == 'H') {
-               PrintAndLog("Usage:  lf em4x 410xsim <UID>");
+               PrintAndLog("Usage:  lf em4x em410xsim <UID>");
                PrintAndLog("");
-               PrintAndLog("     sample: lf em4x 410xsim 0F0368568B");
+               PrintAndLog("     sample: lf em4x em410xsim 0F0368568B");
                return 0;
        }
 
index baea50a422eb2ad51f0c331df31b3187ebafe1f3..38f9aab9128a48e1758ba3a79e46a2926c3be90f 100644 (file)
@@ -23,5 +23,6 @@ int CmdReadWord(const char *Cmd);
 int CmdReadWordPWD(const char *Cmd);
 int CmdWriteWord(const char *Cmd);
 int CmdWriteWordPWD(const char *Cmd);
+int MWRem4xReplay(const char* Cmd);
 
 #endif
index da3ee1a9f04b3f4612d69e30946a341665e9f84c..34c8e1efcbe64d41d3e07d320170f16acd389b6f 100644 (file)
@@ -264,35 +264,30 @@ bool DecodeT55xxBlock(){
 \r
        switch( config.modulation ){\r
                case DEMOD_FSK:\r
-                       //CmdLtrim("26");\r
                        sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );\r
                        CmdLtrim(cmdStr);                       \r
                        sprintf(cmdStr,"%d %d", bitRate[config.bitrate], config.inverted );\r
                        ans = FSKrawDemod(cmdStr, FALSE);\r
                        break;\r
                case DEMOD_FSK1:\r
-                       //CmdLtrim("26");\r
                        sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );\r
                        CmdLtrim(cmdStr);                       \r
                        sprintf(cmdStr,"%d 1 8 5", bitRate[config.bitrate] );\r
                        ans = FSKrawDemod(cmdStr, FALSE);\r
                        break;\r
                case DEMOD_FSK1a:\r
-                       //CmdLtrim("26");\r
                        sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );\r
                        CmdLtrim(cmdStr);                       \r
                        sprintf(cmdStr,"%d 0 8 5", bitRate[config.bitrate] );\r
                        ans = FSKrawDemod(cmdStr, FALSE);\r
                        break;\r
                case DEMOD_FSK2:\r
-                       //CmdLtrim("26");\r
                        sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );\r
                        CmdLtrim(cmdStr);                       \r
                        sprintf(cmdStr,"%d 0 10 8", bitRate[config.bitrate] );\r
                        ans = FSKrawDemod(cmdStr, FALSE);\r
                        break;\r
                case DEMOD_FSK2a:\r
-                       //CmdLtrim("26");\r
                        sprintf(cmdStr,"%d", bitRate[config.bitrate]/2 );\r
                        CmdLtrim(cmdStr);                       \r
                        sprintf(cmdStr,"%d 1 10 8", bitRate[config.bitrate] );\r
index 0cf2b35d436e5656d2aaf11c087f4ecc791e5c86..5e4ee73adecf3b6bf5c0c3a48107932a4c331dea 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef CMDMAIN_H__
 #define CMDMAIN_H__
 
-#include "usb_cmd.h"
+#include "../include/usb_cmd.h"
 #include "cmdparser.h"
 void UsbCommandReceived(UsbCommand *UC);
 void CommandReceived(char *Cmd);
index c273c1f383b759c76a008669d91f1300c30134e7..e982ecf19141f474e3f90a858b80848c55d22f74 100644 (file)
@@ -13,7 +13,7 @@
 #include "proxmark3.h"
 #include "flash.h"
 #include "uart.h"
-#include "usb_cmd.h"
+#include "../include/usb_cmd.h"
 
 #ifdef _WIN32
 # define unlink(x)
index 190dfe8f731dc9fbcd1a299261312e02c409b569..f4acc579298317a07dfd8e9b1ed315e05442738d 100644 (file)
@@ -146,7 +146,7 @@ uint8_t GetPskCarrier(const char str[], bool printAns, bool verbose)
        }
        //uint8_t countPSK_FC(uint8_t *BitStream, size_t size)
 
-       carrier = countPSK_FC(grph,size);
+       carrier = countFC(grph,size,0);
        // Only print this message if we're not looping something
        if (printAns){
                PrintAndLog("Auto-detected PSK carrier rate: %d", carrier);
@@ -232,8 +232,7 @@ uint8_t fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, bool verbose)
        uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
        size_t size = getFromGraphBuf(BitStream);
        if (size==0) return 0;
-       uint8_t dummy = 0;
-       uint16_t ans = countFC(BitStream, size, &dummy); 
+       uint16_t ans = countFC(BitStream, size, 1); 
        if (ans==0) {
                if (verbose) PrintAndLog("DEBUG: No data found");
                return 0;
index 7c9cc873a019f1ae67c9c84ba8cabd789d4e88bd..7d3950b1aef2711d03211305ad19573096a1b95d 100644 (file)
@@ -219,7 +219,7 @@ void MAC(uint8_t* k, BitstreamIn input, BitstreamOut out)
        BitstreamIn input_32_zeroes = {zeroes_32,sizeof(zeroes_32)*8,0};
        State initState = suc(k,init(k),&input);
        output(k,initState,&input_32_zeroes,&out);
-}
+}       
 
 void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
 {
@@ -229,15 +229,15 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
 
        memcpy(cc_nr,cc_nr_p,12);
     memcpy(div_key,div_key_p,8);
-
+    
        reverse_arraybytes(cc_nr,12);
        BitstreamIn bitstream = {cc_nr,12 * 8,0};
-    uint8_t dest []= {0,0,0,0,0,0,0,0};
-    BitstreamOut out = { dest, sizeof(dest)*8, 0 };
-    MAC(div_key,bitstream, out);
-    //The output MAC must also be reversed
-    reverse_arraybytes(dest, sizeof(dest));
-    memcpy(mac, dest, 4);
+       uint8_t dest []= {0,0,0,0,0,0,0,0};
+       BitstreamOut out = { dest, sizeof(dest)*8, 0 };
+       MAC(div_key,bitstream, out);
+       //The output MAC must also be reversed
+       reverse_arraybytes(dest, sizeof(dest));
+       memcpy(mac,dest,4);
        //free(cc_nr);
     return;
 }
@@ -264,8 +264,8 @@ int testMAC()
                prnlog("[+] FAILED: MAC calculation failed:");
                printarr("    Calculated_MAC", calculated_mac, 4);
                printarr("    Correct_MAC   ", correct_MAC, 4);
-               return 1;
-       }
+       return 1;
+}
 
        return 0;
 }
index 10720f76d1e50b903d1acc0469a5d3af14f9bb0e..f18472ab4e73b07f026918c21be2ba07000cb87d 100644 (file)
  * @return 0 for ok, 1 for failz
  */
 int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen);
+/**
+ * @brief Utility function to save load binary data from a a file. This method takes a filename,
+ * Should only be used for fixed-size binary files
+ * @param fileName the name of the file
+ * @param data a buffer to place data in
+ * @param datalen the length of the data/data.
+ * @return
+ */
 
 int fileExists(const char *filename);
 #endif //ON_DEVICE
diff --git a/client/loclass/hash1_brute.c b/client/loclass/hash1_brute.c
new file mode 100644 (file)
index 0000000..a9fe0d1
--- /dev/null
@@ -0,0 +1,92 @@
+#include <stdio.h>
+#include "cipherutils.h"
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+#include "elite_crack.h"
+
+void calc_score(uint8_t* csn, uint8_t* k)
+{
+    uint8_t score =0 ;
+    uint8_t i;
+    uint8_t goodvals[16] = {0};
+    uint8_t uniq_vals[8] = {0};
+    memset(goodvals, 0x00, 16);
+    memset(uniq_vals, 0x00, 8);
+    uint8_t badval = 0;
+    int badscore =0;
+    for(i=0; i < 8 ; i++)
+    {
+        if(k[i] == 0x01) continue;
+        if(k[i] == 0x00) continue;
+        if(k[i] == 0x45) continue;
+        if(k[i] < 16){
+            goodvals[k[i]] = 1;
+        }
+//        if(k[i] ==9 || k[i]==2){
+//            goodvals[k[i]] = 1;
+//        }
+
+        else if(k[i]>=16){
+            badscore++;
+            badval = k[i];
+        }
+    }
+    for(i =0; i < 16; i++)
+    {
+        if(goodvals[i])
+        {
+            uniq_vals[score] = i;
+            score +=1;
+        }
+    }
+    if(score >=2 && badscore < 2)
+    {
+        printf("CSN\t%02x%02x%02x%02x%02x%02x%02x%02x\t%02x %02x %02x %02x %02x %02x %02x %02x\t"
+               ,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]
+                ,k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7]
+                );
+        for(i =0 ; i < score; i++)
+        {
+            printf("%d,", uniq_vals[i]);
+        }
+        printf("\tbadscore: %d (%02x)", badscore, badval);
+        printf("\r\n");
+
+    }
+
+}
+
+void brute_hash1(){
+    uint8_t csn[8] = {0,0,0,0,0xf7,0xff,0x12,0xe0};
+    uint8_t k[8]= {0,0,0,0,0,0,0,0};
+    uint16_t a,b,c,d;
+    uint8_t testcsn[8] ={0x00,0x0d,0x0f,0xfd,0xf7,0xff,0x12,0xe0} ;
+    uint8_t testkey[8] ={0x05 ,0x01 ,0x00 ,0x10 ,0x45 ,0x08 ,0x45,0x56} ;
+    calc_score(testcsn,testkey);
+    printf("Brute forcing hashones\n");
+    //exit(1);
+    for(a=0;a < 256;a++)
+    {
+        //if(a > 0)printf("%d/256 done...\n", a);
+        for(b=0;b < 256 ; b++)
+            for(c=0;c < 256;c++)
+               for(d=0;d < 256;d++)
+                {
+                    csn[0] = a;
+                    csn[1] = b;
+                    csn[2] = c;
+                    csn[3] = d;
+                    csn[4] = 0xf7;
+                    csn[5] = 0xff;
+                    csn[6] = 0x12;
+                    csn[7] = 0xe0;
+                    hash1(csn, k);
+                    calc_score(csn,k);
+               }
+    }
+
+}
+
diff --git a/client/loclass/hash1_brute.h b/client/loclass/hash1_brute.h
new file mode 100644 (file)
index 0000000..b26ad96
--- /dev/null
@@ -0,0 +1,5 @@
+#ifndef HASH1_BRUTE_H
+#define HASH1_BRUTE_H
+void brute_hash1();
+
+#endif // HASH1_BRUTE_H
index ad8f6e00c64ac44b1f7f7985051324a369b1bdf6..b0257ef0eb0d27f125b9b0a52b5b2fc994a6fbd9 100644 (file)
@@ -138,6 +138,8 @@ local _commands = {
        CMD_MIFAREUC_AUTH1 =                                                                     0x0724,
        CMD_MIFAREUC_AUTH2 =                                                                     0x0725,
        CMD_MIFAREUC_READCARD =                                                                      0x0726,
+       CMD_MIFAREUC_SETPWD =                                                                                            0x0727,
+       CMD_MIFAREU_SETUID =                                                                         0x0728,
 
        --// mifare desfire
        CMD_MIFARE_DESFIRE_READBL =                                          0x0728,
@@ -153,10 +155,10 @@ local _commands = {
 
 
 local _reverse_lookup,k,v = {}
-for k, v in pairs(_commands) do
-       _reverse_lookup[v] =  k
-end
-_commands.tostring = function(command)
+       for k, v in pairs(_commands) do
+               _reverse_lookup[v] =  k
+       end
+       _commands.tostring = function(command)
        if(type(command) == 'number') then
                return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command) 
        end
@@ -217,7 +219,6 @@ function Command:getBytes()
        local data  = self.data
        local cmd = self.cmd 
        local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
-       
-       return bin.pack("LLLLH",cmd, arg1, arg2, arg3,data);
+       return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data);
 end
 return _commands
index 048a29c9684e63ef5af729ba6a0debaab5347531..749686c75cfeecf06fa37f1315c483230cfd0b76 100644 (file)
@@ -116,42 +116,42 @@ local _names = {
        --[[
        TRAPTEAM
     --]]
-       ["01C2"]="TRAPTEAM GUSTO",
-       ["01C3"]="TRAPTEAM THUNDERBOLT",
-       ["01C4"]="TRAPTEAM FLING KONG",
-       ["01C5"]="TRAPTEAM BLADES",
-       ["01C6"]="TRAPTEAM WALLOP",
-       ["01C7"]="TRAPTEAM HEAD RUSH",
-       ["01C8"]="TRAPTEAM FIST BUMP",
-       ["01C9"]="TRAPTEAM ROCKY ROLL",
-       ["01CA"]="TRAPTEAM WILDFIRE",
-       ["01CB"]="TRAPTEAM KA BOOM",
-       ["01CC"]="TRAPTEAM TRAIL BLAZER",
-       ["01CD"]="TRAPTEAM TORCH",
-       ["01CE"]="TRAPTEAM SNAP SHOT",
-       ["01CF"]="TRAPTEAM LOB STAR",
-       ["01D0"]="TRAPTEAM FLIP WRECK",
-       ["01D1"]="TRAPTEAM ECHO",
-       ["01D2"]="TRAPTEAM BLASTERMIND",
-       ["01D3"]="TRAPTEAM ENIGMA",
-       ["01D4"]="TRAPTEAM DEJA VU",
-       ["01D5"]="TRAPTEAM COBRA CADABRA",
-       ["01D6"]="TRAPTEAM JAWBREAKER", 
-       ["01D7"]="TRAPTEAM GEARSHIFT",
-       ["01D8"]="TRAPTEAM CHOPPER",
-       ["01D9"]="TRAPTEAM TREAD HEAD",
-       ["01DA"]="TRAPTEAM BUSHWHACK",
-       ["01DB"]="TRAPTEAM TUFF LUCK",
-       ["01DC"]="TRAPTEAM FOOD FIGHT",
-       ["01DD"]="TRAPTEAM HIGH FIVE",
-       ["01DE"]="TRAPTEAM NITRO KRYPT KING",
-       ["01DF"]="TRAPTEAM SHORT CUT",
-       ["01E0"]="TRAPTEAM BAT SPIN",
-       ["01E1"]="TRAPTEAM FUNNY BONE",
-       ["01E2"]="TRAPTEAM KNIGHT LIGHT",
-       ["01E3"]="TRAPTEAM SPOTLIGHT",
-       ["01E4"]="TRAPTEAM KNIGHT MARE",
-       ["01E5"]="TRAPTEAM BLACKOUT",
+       ["C201"]="TRAPTEAM GUSTO",
+       ["C301"]="TRAPTEAM THUNDERBOLT",
+       ["C401"]="TRAPTEAM FLING KONG",
+       ["C501"]="TRAPTEAM BLADES",
+       ["C601"]="TRAPTEAM WALLOP",
+       ["C701"]="TRAPTEAM HEAD RUSH",
+       ["C801"]="TRAPTEAM FIST BUMP",
+       ["C901"]="TRAPTEAM ROCKY ROLL",
+       ["CA01"]="TRAPTEAM WILDFIRE",
+       ["CB01"]="TRAPTEAM KA BOOM",
+       ["CC01"]="TRAPTEAM TRAIL BLAZER",
+       ["CD01"]="TRAPTEAM TORCH",
+       ["CE01"]="TRAPTEAM SNAP SHOT",
+       ["CF01"]="TRAPTEAM LOB STAR",
+       ["D001"]="TRAPTEAM FLIP WRECK",
+       ["D101"]="TRAPTEAM ECHO",
+       ["D201"]="TRAPTEAM BLASTERMIND",
+       ["D301"]="TRAPTEAM ENIGMA",
+       ["D401"]="TRAPTEAM DEJA VU",
+       ["D501"]="TRAPTEAM COBRA CADABRA",
+       ["D601"]="TRAPTEAM JAWBREAKER", 
+       ["D701"]="TRAPTEAM GEARSHIFT",
+       ["D801"]="TRAPTEAM CHOPPER",
+       ["D901"]="TRAPTEAM TREAD HEAD",
+       ["DA01"]="TRAPTEAM BUSHWHACK",
+       ["DB01"]="TRAPTEAM TUFF LUCK",
+       ["DC01"]="TRAPTEAM FOOD FIGHT",
+       ["DD01"]="TRAPTEAM HIGH FIVE",
+       ["DE01"]="TRAPTEAM NITRO KRYPT KING",
+       ["DF01"]="TRAPTEAM SHORT CUT",
+       ["E001"]="TRAPTEAM BAT SPIN",
+       ["E101"]="TRAPTEAM FUNNY BONE",
+       ["E201"]="TRAPTEAM KNIGHT LIGHT",
+       ["E301"]="TRAPTEAM SPOTLIGHT",
+       ["E401"]="TRAPTEAM KNIGHT MARE",
+       ["E501"]="TRAPTEAM BLACKOUT",
 
        --[[
        PET
index 3a28d5ae6f988cf5b30c0ffb40094342bca797e6..bd8e6d0cc20ea2942ba2b370c9907e01ea02b570 100644 (file)
@@ -192,7 +192,9 @@ end
 return {
        convert_bin_to_html = convert_bin_to_html,
        convert_eml_to_html = convert_eml_to_html,
-    convert_eml_to_bin = convert_eml_to_bin,   
+    convert_eml_to_bin = convert_eml_to_bin,
+    SaveAsBinary = save_BIN,
+       SaveAsText = save_TEXT,
     SaveAsBinary = save_BIN,
        SaveAsText = save_TEXT,
 }
diff --git a/client/lualibs/md5.lua b/client/lualibs/md5.lua
new file mode 100644 (file)
index 0000000..2390f95
--- /dev/null
@@ -0,0 +1,384 @@
+local md5 = {
+  _VERSION     = "md5.lua 0.5.0",
+  _DESCRIPTION = "MD5 computation in Lua (5.1)",
+  _URL         = "https://github.com/kikito/md5.lua",
+  _LICENSE     = [[
+    MIT LICENSE
+
+    Copyright (c) 2013 Enrique García Cota + Adam Baldwin + hanzao + Equi 4 Software
+
+    Permission is hereby granted, free of charge, to any person obtaining a
+    copy of this software and associated documentation files (the
+    "Software"), to deal in the Software without restriction, including
+    without limitation the rights to use, copy, modify, merge, publish,
+    distribute, sublicense, and/or sell copies of the Software, and to
+    permit persons to whom the Software is furnished to do so, subject to
+    the following conditions:
+
+    The above copyright notice and this permission notice shall be included
+    in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+    OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+  ]]
+}
+
+-- bit lib implementions
+
+local floor, abs, max = math.floor, math.abs, math.max
+local char, byte, format, rep, sub =
+  string.char, string.byte, string.format, string.rep, string.sub
+
+local function check_int(n)
+  -- checking not float
+  if(n - floor(n) > 0) then
+    error("trying to use bitwise operation on non-integer!")
+  end
+end
+
+local function tbl2number(tbl)
+  local n = #tbl
+
+  local rslt = 0
+  local power = 1
+  for i = 1, n do
+    rslt = rslt + tbl[i]*power
+    power = power*2
+  end
+
+  return rslt
+end
+
+local function expand(tbl_m, tbl_n)
+  local big = {}
+  local small = {}
+  if(#tbl_m > #tbl_n) then
+    big = tbl_m
+    small = tbl_n
+  else
+    big = tbl_n
+    small = tbl_m
+  end
+  -- expand small
+  for i = #small + 1, #big do
+    small[i] = 0
+  end
+
+end
+
+local to_bits -- needs to be declared before bit_not
+
+local function bit_not(n)
+  local tbl = to_bits(n)
+  local size = max(#tbl, 32)
+  for i = 1, size do
+    if(tbl[i] == 1) then
+      tbl[i] = 0
+    else
+      tbl[i] = 1
+    end
+  end
+  return tbl2number(tbl)
+end
+
+-- defined as local above
+to_bits = function (n)
+  check_int(n)
+  if(n < 0) then
+    -- negative
+    return to_bits(bit_not(abs(n)) + 1)
+  end
+  -- to bits table
+  local tbl = {}
+  local cnt = 1
+  while (n > 0) do
+    local last = math.fmod(n,2)
+    if(last == 1) then
+      tbl[cnt] = 1
+    else
+      tbl[cnt] = 0
+    end
+    n = (n-last)/2
+    cnt = cnt + 1
+  end
+
+  return tbl
+end
+
+local function bit_or(m, n)
+  local tbl_m = to_bits(m)
+  local tbl_n = to_bits(n)
+  expand(tbl_m, tbl_n)
+
+  local tbl = {}
+  local rslt = max(#tbl_m, #tbl_n)
+  for i = 1, rslt do
+    if(tbl_m[i]== 0 and tbl_n[i] == 0) then
+      tbl[i] = 0
+    else
+      tbl[i] = 1
+    end
+  end
+
+  return tbl2number(tbl)
+end
+
+local function bit_and(m, n)
+  local tbl_m = to_bits(m)
+  local tbl_n = to_bits(n)
+  expand(tbl_m, tbl_n)
+
+  local tbl = {}
+  local rslt = max(#tbl_m, #tbl_n)
+  for i = 1, rslt do
+    if(tbl_m[i]== 0 or tbl_n[i] == 0) then
+      tbl[i] = 0
+    else
+      tbl[i] = 1
+    end
+  end
+
+  return tbl2number(tbl)
+end
+
+local function bit_xor(m, n)
+  local tbl_m = to_bits(m)
+  local tbl_n = to_bits(n)
+  expand(tbl_m, tbl_n)
+
+  local tbl = {}
+  local rslt = max(#tbl_m, #tbl_n)
+  for i = 1, rslt do
+    if(tbl_m[i] ~= tbl_n[i]) then
+      tbl[i] = 1
+    else
+      tbl[i] = 0
+    end
+  end
+
+  return tbl2number(tbl)
+end
+
+local function bit_rshift(n, bits)
+  check_int(n)
+
+  local high_bit = 0
+  if(n < 0) then
+    -- negative
+    n = bit_not(abs(n)) + 1
+    high_bit = 2147483648 -- 0x80000000
+  end
+
+  for i=1, bits do
+    n = n/2
+    n = bit_or(floor(n), high_bit)
+  end
+  return floor(n)
+end
+
+local function bit_lshift(n, bits)
+  check_int(n)
+
+  if(n < 0) then
+    -- negative
+    n = bit_not(abs(n)) + 1
+  end
+
+  for i=1, bits do
+    n = n*2
+  end
+  return bit_and(n, 4294967295) -- 0xFFFFFFFF
+end
+
+-- convert little-endian 32-bit int to a 4-char string
+local function lei2str(i)
+  local f=function (s) return char( bit_and( bit_rshift(i, s), 255)) end
+  return f(0)..f(8)..f(16)..f(24)
+end
+
+-- convert raw string to big-endian int
+local function str2bei(s)
+  local v=0
+  for i=1, #s do
+    v = v * 256 + byte(s, i)
+  end
+  return v
+end
+
+-- convert raw string to little-endian int
+local function str2lei(s)
+  local v=0
+  for i = #s,1,-1 do
+    v = v*256 + byte(s, i)
+  end
+  return v
+end
+
+-- cut up a string in little-endian ints of given size
+local function cut_le_str(s,...)
+  local o, r = 1, {}
+  local args = {...}
+  for i=1, #args do
+    table.insert(r, str2lei(sub(s, o, o + args[i] - 1)))
+    o = o + args[i]
+  end
+  return r
+end
+
+local swap = function (w) return str2bei(lei2str(w)) end
+
+local function hex2binaryaux(hexval)
+  return char(tonumber(hexval, 16))
+end
+
+local function hex2binary(hex)
+  local result, _ = hex:gsub('..', hex2binaryaux)
+  return result
+end
+
+-- An MD5 mplementation in Lua, requires bitlib (hacked to use LuaBit from above, ugh)
+-- 10/02/2001 jcw@equi4.com
+
+local FF     = 0xffffffff
+local CONSTS = {
+  0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
+  0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
+  0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
+  0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
+  0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
+  0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
+  0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
+  0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
+  0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
+  0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
+  0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
+  0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
+  0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
+  0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
+  0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
+  0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391,
+  0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
+}
+
+local f=function (x,y,z) return bit_or(bit_and(x,y),bit_and(-x-1,z)) end
+local g=function (x,y,z) return bit_or(bit_and(x,z),bit_and(y,-z-1)) end
+local h=function (x,y,z) return bit_xor(x,bit_xor(y,z)) end
+local i=function (x,y,z) return bit_xor(y,bit_or(x,-z-1)) end
+local z=function (f,a,b,c,d,x,s,ac)
+  a=bit_and(a+f(b,c,d)+x+ac,FF)
+  -- be *very* careful that left shift does not cause rounding!
+  return bit_or(bit_lshift(bit_and(a,bit_rshift(FF,s)),s),bit_rshift(a,32-s))+b
+end
+
+local function transform(A,B,C,D,X)
+  local a,b,c,d=A,B,C,D
+  local t=CONSTS
+
+  a=z(f,a,b,c,d,X[ 0], 7,t[ 1])
+  d=z(f,d,a,b,c,X[ 1],12,t[ 2])
+  c=z(f,c,d,a,b,X[ 2],17,t[ 3])
+  b=z(f,b,c,d,a,X[ 3],22,t[ 4])
+  a=z(f,a,b,c,d,X[ 4], 7,t[ 5])
+  d=z(f,d,a,b,c,X[ 5],12,t[ 6])
+  c=z(f,c,d,a,b,X[ 6],17,t[ 7])
+  b=z(f,b,c,d,a,X[ 7],22,t[ 8])
+  a=z(f,a,b,c,d,X[ 8], 7,t[ 9])
+  d=z(f,d,a,b,c,X[ 9],12,t[10])
+  c=z(f,c,d,a,b,X[10],17,t[11])
+  b=z(f,b,c,d,a,X[11],22,t[12])
+  a=z(f,a,b,c,d,X[12], 7,t[13])
+  d=z(f,d,a,b,c,X[13],12,t[14])
+  c=z(f,c,d,a,b,X[14],17,t[15])
+  b=z(f,b,c,d,a,X[15],22,t[16])
+
+  a=z(g,a,b,c,d,X[ 1], 5,t[17])
+  d=z(g,d,a,b,c,X[ 6], 9,t[18])
+  c=z(g,c,d,a,b,X[11],14,t[19])
+  b=z(g,b,c,d,a,X[ 0],20,t[20])
+  a=z(g,a,b,c,d,X[ 5], 5,t[21])
+  d=z(g,d,a,b,c,X[10], 9,t[22])
+  c=z(g,c,d,a,b,X[15],14,t[23])
+  b=z(g,b,c,d,a,X[ 4],20,t[24])
+  a=z(g,a,b,c,d,X[ 9], 5,t[25])
+  d=z(g,d,a,b,c,X[14], 9,t[26])
+  c=z(g,c,d,a,b,X[ 3],14,t[27])
+  b=z(g,b,c,d,a,X[ 8],20,t[28])
+  a=z(g,a,b,c,d,X[13], 5,t[29])
+  d=z(g,d,a,b,c,X[ 2], 9,t[30])
+  c=z(g,c,d,a,b,X[ 7],14,t[31])
+  b=z(g,b,c,d,a,X[12],20,t[32])
+
+  a=z(h,a,b,c,d,X[ 5], 4,t[33])
+  d=z(h,d,a,b,c,X[ 8],11,t[34])
+  c=z(h,c,d,a,b,X[11],16,t[35])
+  b=z(h,b,c,d,a,X[14],23,t[36])
+  a=z(h,a,b,c,d,X[ 1], 4,t[37])
+  d=z(h,d,a,b,c,X[ 4],11,t[38])
+  c=z(h,c,d,a,b,X[ 7],16,t[39])
+  b=z(h,b,c,d,a,X[10],23,t[40])
+  a=z(h,a,b,c,d,X[13], 4,t[41])
+  d=z(h,d,a,b,c,X[ 0],11,t[42])
+  c=z(h,c,d,a,b,X[ 3],16,t[43])
+  b=z(h,b,c,d,a,X[ 6],23,t[44])
+  a=z(h,a,b,c,d,X[ 9], 4,t[45])
+  d=z(h,d,a,b,c,X[12],11,t[46])
+  c=z(h,c,d,a,b,X[15],16,t[47])
+  b=z(h,b,c,d,a,X[ 2],23,t[48])
+
+  a=z(i,a,b,c,d,X[ 0], 6,t[49])
+  d=z(i,d,a,b,c,X[ 7],10,t[50])
+  c=z(i,c,d,a,b,X[14],15,t[51])
+  b=z(i,b,c,d,a,X[ 5],21,t[52])
+  a=z(i,a,b,c,d,X[12], 6,t[53])
+  d=z(i,d,a,b,c,X[ 3],10,t[54])
+  c=z(i,c,d,a,b,X[10],15,t[55])
+  b=z(i,b,c,d,a,X[ 1],21,t[56])
+  a=z(i,a,b,c,d,X[ 8], 6,t[57])
+  d=z(i,d,a,b,c,X[15],10,t[58])
+  c=z(i,c,d,a,b,X[ 6],15,t[59])
+  b=z(i,b,c,d,a,X[13],21,t[60])
+  a=z(i,a,b,c,d,X[ 4], 6,t[61])
+  d=z(i,d,a,b,c,X[11],10,t[62])
+  c=z(i,c,d,a,b,X[ 2],15,t[63])
+  b=z(i,b,c,d,a,X[ 9],21,t[64])
+
+  return A+a,B+b,C+c,D+d
+end
+
+----------------------------------------------------------------
+
+function md5.sumhexa(s)
+  local msgLen = #s
+  local padLen = 56 - msgLen % 64
+
+  if msgLen % 64 > 56 then padLen = padLen + 64 end
+
+  if padLen == 0 then padLen = 64 end
+
+  s = s .. char(128) .. rep(char(0),padLen-1) .. lei2str(8*msgLen) .. lei2str(0)
+
+  assert(#s % 64 == 0)
+
+  local t = CONSTS
+  local a,b,c,d = t[65],t[66],t[67],t[68]
+
+  for i=1,#s,64 do
+    local X = cut_le_str(sub(s,i,i+63),4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4)
+    assert(#X == 16)
+    X[0] = table.remove(X,1) -- zero based!
+    a,b,c,d = transform(a,b,c,d,X)
+  end
+
+  return format("%08x%08x%08x%08x",swap(a),swap(b),swap(c),swap(d))
+end
+
+function md5.sum(s)
+  return hex2binary(md5.sumhexa(s))
+end
+
+return md5
index 757112c671f0169fc26ea53f76326bd0db073f77..810f0d6eab466b7fd8a6b40f06d4e9468bbb4249 100644 (file)
@@ -159,7 +159,7 @@ local _keys = {
        '644672bd4afe',
 
        'b5ff67cba951',
-  }
+}
 
 ---
 --    The keys above have just been pasted in, for completeness sake. They contain duplicates. 
diff --git a/client/lualibs/precalc.lua b/client/lualibs/precalc.lua
new file mode 100644 (file)
index 0000000..ce58998
--- /dev/null
@@ -0,0 +1,94 @@
+--[[
+       This is an experimental lib. 
+--]]
+local utils = require('utils')
+
+-- LOOKUP Tables
+local perm = {}
+perm [1]= { 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5, 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA }
+perm [2]= { 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4, 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB }
+perm [3]= { 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7, 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8 }
+perm [4]= { 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6, 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9 }
+perm [5]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE }
+perm [6]= { 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0, 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF }
+perm [7]= { 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3, 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC }
+perm [8]= { 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2, 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD }
+perm [9]= { 0x8, 0x9, 0xB, 0xA, 0xF, 0xE, 0xC, 0xD, 0x7, 0x6, 0x4, 0x5, 0x0, 0x1, 0x3, 0x2 }
+perm [10]= { 0x9, 0x8, 0xA, 0xB, 0xE, 0xF, 0xD, 0xC, 0x6, 0x7, 0x5, 0x4, 0x1, 0x0, 0x2, 0x3 }
+perm [11]= { 0xA, 0xB, 0x9, 0x8, 0xD, 0xC, 0xE, 0xF, 0x5, 0x4, 0x6, 0x7, 0x2, 0x3, 0x1, 0x0 }
+perm [12]= { 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE, 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1 }
+perm [13]= { 0xC, 0xD, 0xF, 0xE, 0xB, 0xA, 0x8, 0x9, 0x3, 0x2, 0x0, 0x1, 0x4, 0x5, 0x7, 0x6 }
+perm [14]= { 0xD, 0xC, 0xE, 0xF, 0xA, 0xB, 0x9, 0x8, 0x2, 0x3, 0x1, 0x0, 0x5, 0x4, 0x6, 0x7 }
+perm [15]= { 0xE, 0xF, 0xD, 0xC, 0x9, 0x8, 0xA, 0xB, 0x1, 0x0, 0x2, 0x3, 0x6, 0x7, 0x5, 0x4 }
+perm [16]= { 0xF, 0xE, 0xC, 0xD, 0x8, 0x9, 0xB, 0xA, 0x0, 0x1, 0x3, 0x2, 0x7, 0x6, 0x4, 0x5 }
+
+local shifts = {}
+shifts[1]= { 0x4, 0x5, 0x7, 0x6, 0x3, 0x2, 0x0, 0x1, 0xB, 0xA, 0x8, 0x9, 0xC, 0xD, 0xF, 0xE }
+shifts[2]= { 0x4, 0xB, 0xB, 0x4, 0xB, 0x4, 0x4, 0xB, 0xA, 0x5, 0x5, 0xA, 0x5, 0xA, 0xA, 0x5 }
+shifts[3]= { 0xB, 0x6, 0x0, 0xD, 0xD, 0x0, 0x6, 0xB, 0x6, 0xB, 0xD, 0x0, 0x0, 0xD, 0xB, 0x6 }
+shifts[4]= { 0xE, 0x5, 0x9, 0x2, 0x0, 0xB, 0x7, 0xC, 0x3, 0x8, 0x4, 0xF, 0xD, 0x6, 0xA, 0x1 }
+shifts[5]= { 0x4, 0xE, 0x1, 0xB, 0xF, 0x5, 0xA, 0x0, 0x3, 0x9, 0x6, 0xC, 0x8, 0x2, 0xD, 0x7 }
+shifts[6]= { 0xA, 0x4, 0x7, 0x9, 0x0, 0xE, 0xD, 0x3, 0xE, 0x0, 0x3, 0xD, 0x4, 0xA, 0x9, 0x7 }
+shifts[7]= { 0xE, 0x6, 0xE, 0x6, 0xF, 0x7, 0xF, 0x7, 0xD, 0x5, 0xD, 0x5, 0xC, 0x4, 0xC, 0x4 }
+shifts[8]= { 0x7, 0x1, 0xB, 0xD, 0xE, 0x8, 0x2, 0x4, 0x4, 0x2, 0x8, 0xE, 0xD, 0xB, 0x1, 0x7 }
+shifts[9]= { 0xD, 0xB, 0x0, 0x6, 0x6, 0x0, 0xB, 0xD, 0xA, 0xC, 0x7, 0x1, 0x1, 0x7, 0xC, 0xA }
+shifts[10]= { 0xe, 0x1, 0x1, 0xe, 0x1, 0xe, 0xe, 0x1, 0x1, 0xe, 0xe, 0x1, 0xe, 0x1, 0x1, 0xe }
+
+local function ApplyPermutationAndShifts( pos, value, nibble)
+       local shiftbytes = shifts[pos]
+       local shiftElem = shiftbytes[nibble+1] --one indexed
+       local shiftOne = shiftbytes[1]
+       local rs = bit32.bxor(value, bit32.bxor(shiftOne, shiftElem))
+       return rs
+end
+
+local function GetOne( uid, block )
+
+       if uid == nil then return nil, 'empty uid string' end
+       if #uid == 0 then return nil, 'empty uid string' end
+       if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end
+       if type(block) ~= 'number' then return nil, 'block is not number' end
+       if  block > 16 or block < 0 then return nil, 'block is out-of-range' end
+       
+       local s = ('%s%02X'):format(uid,block)
+       local nibble1 = tonumber(s:sub(1,1),16) + 1
+
+       local permuted = ''
+       for i = 1, #s do                
+               local el_row = shifts[i]
+               local el_value = el_row[nibble1] 
+               j = 1
+               while j <= i do
+                       if  i-j > 0 then 
+                               local nibble = tonumber(s:sub(j+1,j+1),16) 
+                               el_value = ApplyPermutationAndShifts(i-j, el_value, nibble)
+                       end
+                       j = j+1
+               end 
+               permuted =('%s%X'):format(permuted,el_value)
+       end     
+
+       permuted = 'C2'..permuted
+       local crc64numStr = utils.Crc64(permuted)
+       local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true)
+       local key = utils.ConvertBytesToHex(keybytes) 
+       return key:sub(1,12)
+end
+
+local PreCalc = 
+{
+       GetAll = function(id)
+               if id == nil then return nil, 'empty string' end
+               if #id == 0 then return nil, 'empty string' end
+               if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end
+               
+               local list = '4b0b20107ccb'
+               for i = 1,15 do
+                       local key, err  = GetOne(id,i)
+                       if not key then return oops(err) end
+                       list = list..key
+               end
+               return list
+       end,
+}
+return PreCalc
\ No newline at end of file
index c5baa406955d067012d525e9b57c8bf9cc525a42..a968fde2a90c3b2218b6e67aa005bdeec7486db6 100644 (file)
@@ -71,8 +71,8 @@ local Utils =
                return outResults\r
        end,\r
        \r
-       ------------ CRC-16 ccitt checksums\r
        \r
+       ------------ CRC-16 ccitt checksums\r
        -- Takes a hex string and calculates a crc16\r
        Crc16 = function(s)\r
                if s == nil then return nil end\r
@@ -85,7 +85,22 @@ local Utils =
                end\r
                return nil\r
        end,\r
-\r
+       \r
+       ------------ CRC-64 ecma checksums\r
+       -- Takes a hex string and calculates a crc64 ecma\r
+       Crc64 = function(s)\r
+               if s == nil then return nil end\r
+               if #s == 0 then return nil end\r
+               if  type(s) == 'string' then\r
+                       local utils = require('utils')\r
+                       local asc = utils.ConvertHexToAscii(s)\r
+                       local hash = core.crc64(asc)\r
+                       return hash\r
+               end\r
+               return nil\r
+       end,\r
+       \r
+       \r
        -- input parameter is a string\r
        -- Swaps the endianess and returns a number,  \r
        -- IE:  'cd7a' -> '7acd'  -> 0x7acd\r
@@ -135,7 +150,7 @@ local Utils =
                while IN>0 do\r
                        I=I+1\r
                        IN , D = math.floor(IN/B), math.modf(IN,B)+1\r
-                       OUT=string.sub(K,D,D)..OUT\r
+                       OUT = string.sub(K,D,D)..OUT\r
                end\r
                return OUT\r
        end,\r
@@ -147,7 +162,7 @@ local Utils =
                end\r
                local s={}\r
                for i = 1, #(bytes) do\r
-                       s[i] =   string.format("%02X",bytes[i]) \r
+                       s[i] = string.format("%02X",bytes[i]) \r
                end\r
                return table.concat(s)\r
        end,    \r
@@ -171,16 +186,28 @@ local Utils =
                end\r
                return t\r
        end,\r
-       ConvertAsciiToBytes = function(s)\r
-               local t={}\r
+       ConvertAsciiToBytes = function(s, reverse)\r
+               local t = {}\r
                if s == nil then return t end\r
                if #s == 0 then return t end\r
                \r
                for k in s:gmatch"(.)" do\r
                        table.insert(t, string.byte(k))\r
                end\r
-               return t\r
+               \r
+               if not reverse then\r
+                       return t\r
+               end\r
+       \r
+               local rev = {}\r
+               if reverse then\r
+                       for i = #t, 1,-1 do\r
+                               table.insert(rev, t[i] )\r
+                       end\r
+               end\r
+               return rev\r
        end,\r
+       \r
        ConvertHexToAscii = function(s)\r
                local t={}\r
                if s == nil then return t end\r
@@ -191,6 +218,30 @@ local Utils =
                return  table.concat(t) \r
        end,\r
        \r
+       Chars2num = function(s)\r
+        return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4))\r
+       end,\r
+       \r
+       -- use length of string to determine 8,16,32,64 bits\r
+       bytes_to_int = function(str,endian,signed) \r
+               local t={str:byte(1,-1)}\r
+               if endian=="big" then --reverse bytes\r
+                       local tt={}\r
+                       for k=1,#t do\r
+                               tt[#t-k+1]=t[k]\r
+                       end\r
+                       t=tt\r
+               end\r
+               local n=0\r
+               for k=1,#t do\r
+                       n=n+t[k]*2^((k-1)*8)\r
+               end\r
+               if signed then\r
+                       n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative.\r
+               end\r
+               return n\r
+       end,\r
+       \r
        -- function convertStringToBytes(str)\r
        -- local bytes = {}\r
        -- local strLength = string.len(str)\r
index 35499b83677e18129e2278221ed865edbc52f32a..6716f7eb6077f0488a5a4274fed4954c52e804b6 100644 (file)
@@ -72,7 +72,6 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo
        uint16_t i, len;\r
        uint32_t uid;\r
        UsbCommand resp;\r
-\r
        StateList_t statelists[2];\r
        struct Crypto1State *p1, *p2, *p3, *p4;\r
        \r
@@ -216,7 +215,7 @@ int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) {
        UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}};\r
        SendCommand(&c);\r
 \r
-  UsbCommand resp;\r
+       UsbCommand resp;\r
        if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 1;\r
        memcpy(data, resp.d.asBytes, blocksCount * 16);\r
        return 0;\r
@@ -266,7 +265,7 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, bool wantWipe, uin
        memcpy(c.d.asBytes, data, 16); \r
        SendCommand(&c);\r
 \r
-  UsbCommand resp;\r
+       UsbCommand resp;\r
        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
                isOK  = resp.arg[0] & 0xff;\r
                if (uid != NULL) \r
@@ -365,10 +364,10 @@ int loadTraceCard(uint8_t *tuid) {
        \r
                memset(buf, 0, sizeof(buf));\r
                if (fgets(buf, sizeof(buf), f) == NULL) {\r
-                       PrintAndLog("File reading error.");\r
+      PrintAndLog("File reading error.");\r
                        fclose(f);\r
                        return 2;\r
-       }\r
+    }\r
 \r
                if (strlen(buf) < 32){\r
                        if (feof(f)) break;\r
@@ -474,7 +473,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) {
                }\r
                \r
                // AUTHENTICATION\r
-               if ((len ==4) && ((data[0] == 0x60) || (data[0] == 0x61))) {\r
+               if ((len == 4) && ((data[0] == 0x60) || (data[0] == 0x61))) {\r
                        traceState = TRACE_AUTH1;\r
                        traceCurBlock = data[1];\r
                        traceCurKey = data[0] == 60 ? 1:0;\r
index 1015e27a74b2a866078cb0ca350113081bd95baa..1d7441c7fee996bc34ba9b783b8713b8efacbc54 100644 (file)
@@ -1,21 +1,21 @@
 /*  crapto1.c\r
 \r
-       This program is free software; you can redistribute it and/or\r
-       modify it under the terms of the GNU General Public License\r
-       as published by the Free Software Foundation; either version 2\r
-       of the License, or (at your option) any later version.\r
-\r
-       This program is distributed in the hope that it will be useful,\r
-       but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-       GNU General Public License for more details.\r
-\r
-       You should have received a copy of the GNU General Public License\r
-       along with this program; if not, write to the Free Software\r
-       Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
-       Boston, MA  02110-1301, US$\r
-\r
-       Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
+    This program is free software; you can redistribute it and/or\r
+    modify it under the terms of the GNU General Public License\r
+    as published by the Free Software Foundation; either version 2\r
+    of the License, or (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU General Public License for more details.\r
+\r
+    You should have received a copy of the GNU General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
+    Boston, MA  02110-1301, US$\r
+\r
+    Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
 */\r
 #include "crapto1.h"\r
 #include <stdlib.h>\r
@@ -24,9 +24,9 @@
 static uint8_t filterlut[1 << 20];\r
 static void __attribute__((constructor)) fill_lut()\r
 {\r
-               uint32_t i;\r
-               for(i = 0; i < 1 << 20; ++i)\r
-                               filterlut[i] = filter(i);\r
+        uint32_t i;\r
+        for(i = 0; i < 1 << 20; ++i)\r
+                filterlut[i] = filter(i);\r
 }\r
 #define filter(x) (filterlut[(x) & 0xfffff])\r
 #endif\r
@@ -147,7 +147,7 @@ extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in
                        *p ^= in;\r
                } else {                                                                                // drop\r
                        *p-- = *(*end)--;\r
-               }\r
+       }\r
        }\r
 \r
 }\r
@@ -209,7 +209,7 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
 \r
        for (int i = bucket_info.numbuckets - 1; i >= 0; i--) {\r
                sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks,\r
-                                        bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks,\r
+                                    bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks,\r
                                         rem, sl, in, bucket);\r
        }\r
 \r
@@ -484,7 +484,7 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd)
  */\r
 static struct Crypto1State*\r
 brute_top(uint32_t prefix, uint32_t rresp, unsigned char parities[8][8],\r
-                 uint32_t odd, uint32_t even, struct Crypto1State* sl, uint8_t no_chk)\r
+          uint32_t odd, uint32_t even, struct Crypto1State* sl, uint8_t no_chk)\r
 {\r
        struct Crypto1State s;\r
        uint32_t ks1, nr, ks2, rr, ks3, good, c;\r
index 0e2a698c1b8ca3783f2a1bc16d980539c423ce22..c100bbea0985d05222f580adbf90d05d887540bd 100644 (file)
@@ -35,7 +35,7 @@ volatile static bool txcmd_pending = false;
 
 void SendCommand(UsbCommand *c) {
        #if 0
-               printf("Sending %d bytes\n", sizeof(UsbCommand));
+  printf("Sending %d bytes\n", sizeof(UsbCommand));
        #endif
 
        if (offline) {
@@ -47,110 +47,110 @@ void SendCommand(UsbCommand *c) {
        or disconnected. The main console thread is alive, but comm thread just spins here.
        Not good.../holiman
        **/
-       while(txcmd_pending);
-       txcmd = *c;
-       txcmd_pending = true;
+  while(txcmd_pending);
+  txcmd = *c;
+  txcmd_pending = true;
 }
 
 struct receiver_arg {
-       int run;
+  int run;
 };
 
 struct main_loop_arg {
-       int usb_present;
-       char *script_cmds_file;
+  int usb_present;
+  char *script_cmds_file;
 };
 
 byte_t rx[0x1000000];
 byte_t* prx = rx;
 
 static void *uart_receiver(void *targ) {
-       struct receiver_arg *arg = (struct receiver_arg*)targ;
-       size_t rxlen;
-       size_t cmd_count;
+  struct receiver_arg *arg = (struct receiver_arg*)targ;
+  size_t rxlen;
+  size_t cmd_count;
 
-       while (arg->run) {
-               rxlen = sizeof(UsbCommand);
+  while (arg->run) {
+    rxlen = sizeof(UsbCommand);
                if (uart_receive(sp, prx, &rxlen)) {
-                       prx += rxlen;
-                       if (((prx-rx) % sizeof(UsbCommand)) != 0) {
-                               continue;
-                       }
-                       cmd_count = (prx-rx) / sizeof(UsbCommand);
+      prx += rxlen;
+      if (((prx-rx) % sizeof(UsbCommand)) != 0) {
+        continue;
+      }
+      cmd_count = (prx-rx) / sizeof(UsbCommand);
 
                        for (size_t i = 0; i < cmd_count; i++) {
-                               UsbCommandReceived((UsbCommand*)(rx+(i*sizeof(UsbCommand))));
-                       }
-               }
-               prx = rx;
+        UsbCommandReceived((UsbCommand*)(rx+(i*sizeof(UsbCommand))));
+      }
+    }
+    prx = rx;
 
-               if(txcmd_pending) {
+    if(txcmd_pending) {
                        if (!uart_send(sp, (byte_t*) &txcmd, sizeof(UsbCommand))) {
-                               PrintAndLog("Sending bytes to proxmark failed");
-                       }
-                       txcmd_pending = false;
-               }
-       }
+        PrintAndLog("Sending bytes to proxmark failed");
+      }
+      txcmd_pending = false;
+    }
+  }
 
-       pthread_exit(NULL);
-       return NULL;
+  pthread_exit(NULL);
+  return NULL;
 }
 
 static void *main_loop(void *targ) {
-       struct main_loop_arg *arg = (struct main_loop_arg*)targ;
-       struct receiver_arg rarg;
-       char *cmd = NULL;
-       pthread_t reader_thread;
+  struct main_loop_arg *arg = (struct main_loop_arg*)targ;
+  struct receiver_arg rarg;
+  char *cmd = NULL;
+  pthread_t reader_thread;
   
-       if (arg->usb_present == 1) {
+  if (arg->usb_present == 1) {
                rarg.run = 1;
-               pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
-       }
+    pthread_create(&reader_thread, NULL, &uart_receiver, &rarg);
+  }
 
-       FILE *script_file = NULL;
+  FILE *script_file = NULL;
        char script_cmd_buf[256];  // iceman, needs lua script the same file_path_buffer as the rest
 
        if (arg->script_cmds_file) {
-               script_file = fopen(arg->script_cmds_file, "r");
+    script_file = fopen(arg->script_cmds_file, "r");
                if (script_file) {
-                       printf("using 'scripting' commands file %s\n", arg->script_cmds_file);
-               }
-       }
+      printf("using 'scripting' commands file %s\n", arg->script_cmds_file);
+    }
+  }
 
        read_history(".history");
 
        while(1)  {
 
-               // If there is a script file
-               if (script_file)
-               {
+    // If there is a script file
+    if (script_file)
+    {
                        if (!fgets(script_cmd_buf, sizeof(script_cmd_buf), script_file)) {
-                               fclose(script_file);
-                               script_file = NULL;
+        fclose(script_file);
+        script_file = NULL;
                        } else {
-                               char *nl;
-                               nl = strrchr(script_cmd_buf, '\r');
-                               if (nl) *nl = '\0';
+        char *nl;
+        nl = strrchr(script_cmd_buf, '\r');
+        if (nl) *nl = '\0';
                                
-                               nl = strrchr(script_cmd_buf, '\n');
-                               if (nl) *nl = '\0';
+        nl = strrchr(script_cmd_buf, '\n');
+        if (nl) *nl = '\0';
 
                                if ((cmd = (char*) malloc(strlen(script_cmd_buf) + 1)) != NULL) {
-                                       memset(cmd, 0, strlen(script_cmd_buf));
-                                       strcpy(cmd, script_cmd_buf);
-                                       printf("%s\n", cmd);
-                               }
-                       }
-               }
+          memset(cmd, 0, strlen(script_cmd_buf));
+          strcpy(cmd, script_cmd_buf);
+          printf("%s\n", cmd);
+        }
+      }
+    }
                
                if (!script_file) {
-                       cmd = readline(PROXPROMPT);
+      cmd = readline(PROXPROMPT);
                }
                
                if (cmd) {
 
                        while(cmd[strlen(cmd) - 1] == ' ')
-                               cmd[strlen(cmd) - 1] = 0x00;
+        cmd[strlen(cmd) - 1] = 0x00;
                        
                        if (cmd[0] != 0x00) {
                                if (strncmp(cmd, "quit", 4) == 0) {
@@ -169,19 +169,19 @@ static void *main_loop(void *targ) {
   
        write_history(".history");
   
-       if (arg->usb_present == 1) {
-               rarg.run = 0;
-               pthread_join(reader_thread, NULL);
-       }
+  if (arg->usb_present == 1) {
+    rarg.run = 0;
+    pthread_join(reader_thread, NULL);
+  }
 
        if (script_file) {
-               fclose(script_file);
-               script_file = NULL;
-       }
+    fclose(script_file);
+    script_file = NULL;
+  }
 
-       ExitGraphics();
-       pthread_exit(NULL);
-       return NULL;
+  ExitGraphics();
+  pthread_exit(NULL);
+  return NULL;
 }
 
 static void dumpAllHelp(int markdown)
index 8236bfe71fb345cbd5c3b3066cc40f779cae8277..a634fd68179bf1d29b3bb4a8a29fed6fde3d3080 100644 (file)
@@ -20,7 +20,7 @@
 
 #include "usb_cmd.h"
 
-#define PROXPROMPT "proxmark3> "
+#define PROXPROMPT "pm3 --> "
 
 void SendCommand(UsbCommand *c);
 
index 0ccdeeec7a8d497d5a288fef2fcc0e8998a0e865..50283c8797a6cb50f14fcd4db12fadb155ccf2df 100644 (file)
@@ -19,6 +19,7 @@
 #include "nonce2key/nonce2key.h"
 #include "../common/iso15693tools.h"
 #include "../common/crc16.h"
+#include "../common/crc64.h"
 #include "aes.h"
 /**
  * The following params expected:
@@ -278,6 +279,28 @@ static int l_crc16(lua_State *L)
     return 1;
 }
 
+static int l_crc64(lua_State *L)
+{
+       size_t size;
+       uint64_t crc = 0; 
+       unsigned char outdata[8] = {0x00};
+
+       const char *p_str = luaL_checklstring(L, 1, &size);
+       
+       crc64( (uint8_t*) p_str, size, &crc);
+
+       outdata[0] = (uint8_t)(crc >> 56) & 0xff;
+       outdata[1] = (uint8_t)(crc >> 48) & 0xff;
+       outdata[2] = (uint8_t)(crc >> 40) & 0xff;
+       outdata[3] = (uint8_t)(crc >> 32) & 0xff;
+       outdata[4] = (uint8_t)(crc >> 24) & 0xff;
+       outdata[5] = (uint8_t)(crc >> 16) & 0xff;
+       outdata[6] = (uint8_t)(crc >> 8) & 0xff;
+       outdata[7] = crc & 0xff;
+       lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
+    return 1;
+}
+
 /**
  * @brief Sets the lua path to include "./lualibs/?.lua", in order for a script to be
  * able to do "require('foobar')" if foobar.lua is within lualibs folder.
@@ -313,10 +336,11 @@ int set_pm3_libraries(lua_State *L)
         {"foobar",                      l_foobar},
         {"ukbhit",                      l_ukbhit},
         {"clearCommandBuffer",          l_clearCommandBuffer},
-        {"console",                      l_CmdConsole},
-        {"iso15693_crc",                 l_iso15693_crc},
+        {"console",                     l_CmdConsole},
+        {"iso15693_crc",                l_iso15693_crc},
                {"aes",                         l_aes},
                {"crc16",                       l_crc16},
+               {"crc64",                                               l_crc64},
         {NULL, NULL}
     };
 
index 0d735e98f72a7ce4d3c099fbfe916894cdca92a9..66a61fba9005f29555ae38904470e223bfa5dafb 100644 (file)
@@ -80,14 +80,14 @@ function GetCardInfo()
 \r
        core.clearCommandBuffer()\r
        \r
-       if 0x18 == result.sak then --NXP MIFARE Classic 4k | Plus 4k\r
+       if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k\r
                -- IFARE Classic 4K offers 4096 bytes split into forty sectors, \r
                -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. \r
                numSectors = 40\r
-       elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k\r
+       elseif 0x08 == result.sak then  -- NXP MIFARE CLASSIC 1k | Plus 2k\r
                -- 1K offers 1024 bytes of data storage, split into 16 sector\r
                numSectors = 16\r
-       elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k\r
+       elseif 0x09 == result.sak then  -- NXP MIFARE Mini 0.3k\r
                -- MIFARE Classic mini offers 320 bytes split into five sectors.\r
                numSectors = 5\r
        elseif  0x10 == result.sak then -- NXP MIFARE Plus 2k\r
diff --git a/client/scripts/test.lua b/client/scripts/test.lua
deleted file mode 100644 (file)
index 76adc98..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-local foo = "This shows how to use some standard libraries"
-print(foo)
-local answer
-repeat
-       io.write("Continue with this operation (y/n)? ")
-       io.flush()
-       answer=io.read()
-until answer=="y" or answer=="n"
-local x = "Ok then, %s"
-print (x:format("whatever"))
\ No newline at end of file
index a1793ba602e132745cf9d5bae15b927276d17c56..4f61cf7884866c79ec61df24cd4d869dfb899547 100644 (file)
@@ -98,10 +98,9 @@ function test()
                        elseif _ == 1 then
 
                                local config = pcmd:format(config1, y, config2)
-                               dbg(('lf t55xx wr 0 %s'):format(config))
+                               dbg(('lf t55xx write 0 %s'):format(config))
                                
-                               config = tonumber(config,16) 
-                               local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config}
+                               local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config ,arg2 = 0, arg3 = 0}
                                local err = core.SendCommand(writecmd:getBytes())
                                if err then return oops(err) end
                                local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
diff --git a/client/scripts/tnp3clone.lua b/client/scripts/tnp3clone.lua
new file mode 100644 (file)
index 0000000..aec5483
--- /dev/null
@@ -0,0 +1,113 @@
+local cmds = require('commands')
+local getopt = require('getopt')
+local lib14a = require('read14a')
+local utils = require('utils')
+local pre = require('precalc')
+
+local lsh = bit32.lshift
+local rsh = bit32.rshift
+local bor = bit32.bor
+local band = bit32.band
+
+example =[[
+       script run tnp3dump
+       script run tnp3dump -h
+       script run tnp3dump -t aa00
+
+]]
+author = "Iceman"
+usage = "script run tnp3clone -t <toytype>"
+desc =[[
+This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card.
+
+Arguments:
+       -h             : this help
+       -k <key>       : toytype id,  4 hex symbols.
+]]
+
+
+-- This is only meant to be used when errors occur
+function oops(err)
+       print("ERROR: ",err)
+end
+-- Usage help
+function help()
+       print(desc)
+       print("Example usage")
+       print(example)
+end
+
+local function waitCmd()
+       local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000)
+       if response then
+               local count,cmd,arg0 = bin.unpack('LL',response)
+               if(arg0==1) then
+                       local count,arg1,arg2,data = bin.unpack('LLH511',response,count)
+                       return data:sub(1,32)
+               else
+                       return nil, "Couldn't read block." 
+               end
+       end
+       return nil, "No response from device"
+end
+
+local function readblock( keyA )
+       -- Read block 0
+       cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
+       err = core.SendCommand(cmd:getBytes())
+       if err then return oops(err) end
+       local block0, err = waitCmd()
+       if err then return oops(err) end
+       return block0
+end
+
+local function main(args)
+
+       local numBlocks = 64
+    local cset = 'hf mf csetbl'
+       local empty = '00000000000000000000000000000000'
+       local AccAndKeyB = '7F078869000000000000'
+       -- Defaults to Gusto
+       local toytype = 'C201'
+       
+       -- Arguments for the script
+       for o, a in getopt.getopt(args, 'ht:') do
+               if o == "h" then return help() end              
+               if o == "t" then toytype = a end
+       end
+       
+       if #toytype ~= 4 then return oops('Wrong size in toytype. (4hex symbols)') end  
+       
+       -- find tag
+       result, err = lib14a.read1443a(false)
+       if not result then return oops(err)     end
+
+       -- Show tag info
+       print((' Found tag %s'):format(result.name))
+
+       -- load keys
+       local akeys  = pre.GetAll(result.uid)
+       local  keyA = akeys:sub(1, 12 ) 
+
+       local b0 = readblock(keyA)
+       local b1 = toytype..'000000000000000000000000'
+       
+       local calc = utils.Crc16(b0..b1)
+       local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8))
+       
+       local cmd  = ('hf mf csetbl 1 %s%04x'):format( b1, calcEndian)  
+       core.console( cmd) 
+       
+       local pos, key
+       for blockNo = 2, numBlocks-1, 1 do
+               pos = (math.floor( blockNo / 4 ) * 12)+1
+               key = akeys:sub(pos, pos + 11 )
+               if  blockNo%4 ~= 3 then
+                       cmd =  ('%s %d %s'):format(cset,blockNo,empty) 
+               else
+                       cmd =  ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB) 
+               end
+               core.console(cmd)
+       end 
+end
+main(args)
\ No newline at end of file
index dedd3df1382c4867fcd23128fcc499f6ff956b17..363998fb87ad56e768ce94e03d196f21a9936b2b 100644 (file)
@@ -7,17 +7,20 @@ local md5 = require('md5')
 local dumplib = require('html_dumplib')
 local toyNames = require('default_toys')
 
+
 example =[[
-       1. script run tnp3dump
-       2. script run tnp3dump -n
-       3. script run tnp3dump -k aabbccddeeff
-       4. script run tnp3dump -k aabbccddeeff -n
-       5. script run tnp3dump -o myfile 
-       6. script run tnp3dump -n -o myfile 
-       7. script run tnp3dump -k aabbccddeeff -n -o myfile 
+       script run tnp3dump
+       script run tnp3dump -n
+       script run tnp3dump -p
+       script run tnp3dump -k aabbccddeeff
+       script run tnp3dump -k aabbccddeeff -n
+       script run tnp3dump -o myfile 
+       script run tnp3dump -n -o myfile 
+       script run tnp3dump -p -o myfile 
+       script run tnp3dump -k aabbccddeeff -n -o myfile 
 ]]
 author = "Iceman"
-usage = "script run tnp3dump -k <key> -n -o <filename>"
+usage = "script run tnp3dump -k <key> -n -p -o <filename>"
 desc =[[
 This script will try to dump the contents of a Mifare TNP3xxx card.
 It will need a valid KeyA in order to find the other keys and decode the card.
@@ -25,6 +28,7 @@ Arguments:
        -h             : this help
        -k <key>       : Sector 0 Key A.
        -n             : Use the nested cmd to find all keys
+       -p             : Use the precalc to find all keys
        -o             : filename for the saved dumps
 ]]
 
@@ -112,15 +116,17 @@ local function main(args)
        local cmd
        local err
        local useNested = false
+       local usePreCalc = false
        local cmdReadBlockString = 'hf mf rdbl %d A %s'
        local input = "dumpkeys.bin"
        local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S");
 
        -- Arguments for the script
-       for o, a in getopt.getopt(args, 'hk:no:') do
+       for o, a in getopt.getopt(args, 'hk:npo:') do
                if o == "h" then return help() end              
                if o == "k" then keyA = a end
                if o == "n" then useNested = true end
+               if o == "p" then usePreCalc = true end
                if o == "o" then outputTemplate = a end         
        end
 
@@ -142,29 +148,34 @@ local function main(args)
        core.clearCommandBuffer()
        
        if 0x01 ~= result.sak then -- NXP MIFARE TNP3xxx
-               return oops('This is not a TNP3xxx tag. aborting.')
+       --      return oops('This is not a TNP3xxx tag. aborting.')
        end     
 
        -- Show tag info
-       print((' Found tag : %s'):format(result.name))
-       print(('Using keyA : %s'):format(keyA))
+       print((' Found tag %s'):format(result.name))
+
+       dbg(('Using keyA : %s'):format(keyA))
 
        --Trying to find the other keys
        if useNested then
          core.console( ('hf mf nested 1 0 A %s d'):format(keyA) )
        end
-       
+
        core.clearCommandBuffer()
        
-       -- Loading keyfile
-       print('Loading dumpkeys.bin')
-       local hex, err = utils.ReadDumpFile(input)
-       if not hex then
-               return oops(err)
+       local akeys = ''
+       if usePreCalc then
+               local pre = require('precalc')
+               akeys = pre.GetAll(result.uid)
+       else
+               print('Loading dumpkeys.bin')
+               local hex, err = utils.ReadDumpFile(input)
+               if not hex then
+                       return oops(err)
+               end
+               akeys = hex:sub(0,12*16)
        end
-
-       local akeys = hex:sub(0,12*16)
-
+       
        -- Read block 0
        cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0,arg2 = 0,arg3 = 0, data = keyA}
        err = core.SendCommand(cmd:getBytes())
@@ -188,7 +199,7 @@ local function main(args)
        core.clearCommandBuffer()
                
        -- main loop
-       io.write('Decrypting blocks > ')
+       io.write('Reading blocks > ')
        for blockNo = 0, numBlocks-1, 1 do
 
                if core.ukbhit() then
@@ -204,7 +215,9 @@ local function main(args)
                local blockdata, err = waitCmd()
                if err then return oops(err) end                
 
+
                if  blockNo%4 ~= 3 then
+               
                        if blockNo < 8 then
                                -- Block 0-7 not encrypted
                                blocks[blockNo+1] = ('%02d  :: %s'):format(blockNo,blockdata) 
@@ -249,23 +262,28 @@ local function main(args)
                end
        end 
        
-
        local uid = block0:sub(1,8)
        local itemtype = block1:sub(1,4)
+       local cardidLsw = block1:sub(9,16)
+       local cardidMsw = block1:sub(16,24)
        local cardid = block1:sub(9,24)
        local traptype = block1:sub(25,28)
        
        -- Write dump to files
        if not DEBUG then
                local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'_uid_'..uid..'.bin')
-               print(("Wrote a BIN dump to the file %s"):format(foo))
+               print(("Wrote a BIN dump to %s"):format(foo))
                local bar = dumplib.SaveAsText(emldata, outputTemplate..'_uid_'..uid..'.eml')
-               print(("Wrote a EML dump to the file %s"):format(bar))
+               print(("Wrote a EML dump to %s"):format(bar))
        end
 
+       local itemtypename = toyNames[itemtype]
+       if itemtypename == nil then
+               itemtypename = toyNames[utils.SwapEndiannessStr(itemtype,16)]
+       end
        -- Show info 
        print( string.rep('--',20) )
-       print( ('            ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
+       print( ('            ITEM TYPE : 0x%s - %s'):format(itemtype, itemtypename) )
        print( (' Alter ego / traptype : 0x%s'):format(traptype) )
        print( ('                  UID : 0x%s'):format(uid) )
        print( ('               CARDID : 0x%s'):format(cardid ) )
index adc34cce1ca8e84ef54502e9c2ec5f04d5cfbe73..1d3dbefd176d663d72bd83cca84c42b41f317cde 100644 (file)
@@ -27,6 +27,17 @@ Arguments:
 
 local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds
 local DEBUG = true -- the debug flag
+
+
+local band = bit32.band
+local bor = bit32.bor
+local lshift = bit32.lshift
+local rshift = bit32.rshift
+local byte = string.byte
+local char = string.char
+local sub = string.sub
+local format = string.format
+
 --- 
 -- A debug printout-function
 function dbg(args)
@@ -65,7 +76,6 @@ function ExitMsg(msg)
        print()
 end
 
-
 local function writedumpfile(infile)
         t = infile:read("*all")
         len = string.len(t)
@@ -187,7 +197,6 @@ local function ValidateCheckSums(blocks)
        io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk))
 end
 
-
 local function LoadEmulator(blocks)
        local HASHCONSTANT = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20'
        local cmd
@@ -219,6 +228,102 @@ local function LoadEmulator(blocks)
        io.write('\n')
 end
 
+local function Num2Card(m, l)
+
+       local k = {
+               0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B,
+               0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00
+       }
+       local msw = tonumber(utils.SwapEndiannessStr(m,32),16)
+       local lsw = tonumber(utils.SwapEndiannessStr(l,32),16)
+
+       if msw > 0x17ea1 then
+               return "too big"
+       end
+
+       if msw == 0x17ea1 and lsw > 0x8931fee8 then
+               return "out of range"
+       end
+
+       local s = ""
+       local index
+       for i = 1,10 do
+               index, msw, lsw = DivideByK( msw, lsw)
+               if ( index <= 1 ) then
+                       s = char(k[index]) .. s
+               else
+                       s = char(k[index-1]) .. s
+               end 
+               print (index-1, msw, lsw)
+       end
+    return s
+end
+--33LRT-LM9Q9
+--7, 122, 3474858630
+--20, 4, 1008436634
+--7, 0, 627182959
+--17, 0, 21626998
+--16, 0, 745758
+--23, 0, 25715
+--21, 0, 886
+--16, 0, 30
+--1, 0, 1
+--1, 0, 0
+
+function DivideByK(msw, lsw)
+
+       local lowLSW
+       local highLSW
+       local remainder = 0
+       local RADIX = 29
+
+       --local num = 0 | band( rshift(msw,16), 0xffff)
+       local num = band( rshift(msw, 16), 0xffff)
+       --highLSW = 0 | lshift( (num / RADIX) , 16)
+       highLSW = lshift( (num / RADIX) , 16)
+       remainder = num % RADIX
+
+       num =  bor( lshift(remainder,16), band(msw, 0xffff))
+
+       --highLSW |= num / RADIX
+       highLSW = highLSW or (num / RADIX)
+       remainder = num % RADIX
+
+       num =  bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff)))
+
+       --lowLSW = 0 | (num / RADIX) << 16
+       lowLSW = 0 or (lshift( (num / RADIX), 16))
+       remainder = num % RADIX
+
+       num =  bor( lshift(remainder,16) , band(lsw, 0xffff) )
+
+       lowLSW = bor(lowLSW, (num / RADIX))
+       remainder = num % RADIX
+       return remainder, highLSW, lowLSW
+       
+                   -- uint num = 0 | (msw >> 16) & 0xffff;
+            -- highLSW = 0 | (num / RADIX) << 16;
+            -- remainder = num % RADIX;
+
+            -- num = (remainder << 16) | (msw & 0xffff);
+            -- highLSW |= num / RADIX;
+            -- remainder = num % RADIX;
+
+            -- num = (remainder << 16) | ((lsw >> 16) & 0xffff);
+
+            -- lowLSW = 0 | (num / RADIX) << 16;
+            -- remainder = num % RADIX;
+
+            -- num = (remainder << 16) | (lsw & 0xffff);
+
+            -- lowLSW |= num / RADIX;
+            -- remainder = num % RADIX;
+
+end
+
 local function main(args)
 
        print( string.rep('--',20) )
@@ -278,15 +383,26 @@ local function main(args)
        print(' Gathering info')
        local uid = blocks[0]:sub(1,8)
        local itemtype = blocks[1]:sub(1,4)
-       local cardid = blocks[1]:sub(9,24)
+       local cardidLsw = blocks[1]:sub(9,16)
+       local cardidMsw = blocks[1]:sub(17,24)
 
+       local itemtypename = toyNames[itemtype]
+       if itemtypename == nil then
+               itemtypename = toyNames[utils.SwapEndiannessStr(itemtype,16)]
+       end
+       
        -- Show info 
        print( string.rep('--',20) )
-       print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, toyNames[itemtype]) )
+       print( (' ITEM TYPE : 0x%s - %s'):format(itemtype, itemtypename) )
        print( ('       UID : 0x%s'):format(uid) )
-       print( ('    CARDID : 0x%s'):format(cardid ) )  
+       print( ('    CARDID : 0x%s %s [%s]'):format(
+                                                               cardidMsw,cardidLsw, 
+                                                               --Num2Card(cardidMsw, cardidLsw))
+                                                               '')
+                                                               )
        print( string.rep('--',20) )
 
+
        -- lets do something.
        -- 
        local experience = blocks[8]:sub(1,6)
@@ -351,7 +467,7 @@ local function main(args)
                err = LoadEmulator(blocks)
                if err then return oops(err) end        
                core.clearCommandBuffer()
-               print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..' x\" <--')
+               print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--')
        end
 end
 main(args)
\ No newline at end of file
index c0d01bc32983a2efb313f99640d745ce3af8cde9..6645a99ea5e5f7519380a6d2dc306c1cc9ae879f 100644 (file)
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
+#include <stdbool.h>
 #include <time.h>
 #include <readline/readline.h>
 #include <pthread.h>
-
+#include "loclass/cipherutils.h"
 #include "ui.h"
+#include "cmdmain.h"
+#include "cmddata.h"
+#include "graph.h"
+//#include <liquid/liquid.h>
+#define M_PI 3.14159265358979323846264338327
 
 double CursorScaleFactor;
 int PlotGridX, PlotGridY, PlotGridXdefault= 64, PlotGridYdefault= 64;
 int offline;
-int flushAfterWrite = 0;  //buzzy
+int flushAfterWrite = 0;
 extern pthread_mutex_t print_lock;
 
 static char *logfilename = "proxmark3.log";
@@ -32,13 +38,13 @@ void PrintAndLog(char *fmt, ...)
        int saved_point;
        va_list argptr, argptr2;
        static FILE *logfile = NULL;
-       static int logging=1;
+       static int logging = 1;
 
        // lock this section to avoid interlacing prints from different threats
        pthread_mutex_lock(&print_lock);
   
        if (logging && !logfile) {
-               logfile=fopen(logfilename, "a");
+               logfile = fopen(logfilename, "a");
                if (!logfile) {
                        fprintf(stderr, "Can't open logfile, logging disabled!\n");
                        logging=0;
@@ -77,16 +83,399 @@ void PrintAndLog(char *fmt, ...)
        }
        va_end(argptr2);
 
-       if (flushAfterWrite == 1)  //buzzy
-       {
+       if (flushAfterWrite == 1) {
                fflush(NULL);
        }
        //release lock
        pthread_mutex_unlock(&print_lock);  
 }
 
-
 void SetLogFilename(char *fn)
 {
   logfilename = fn;
 }
+
+int manchester_decode( int * data, const size_t len, uint8_t * dataout,  size_t dataoutlen){
+       
+       int bitlength = 0;
+       int clock, high, low, startindex;
+       low = startindex = 0;
+       high = 1;
+       uint8_t * bitStream =  (uint8_t* ) malloc(sizeof(uint8_t) * dataoutlen);        
+       memset(bitStream, 0x00, dataoutlen);    
+       
+       /* Detect high and lows */
+       DetectHighLowInGraph(&high, &low, TRUE); 
+
+       /* get clock */
+       clock = GetAskClock("",false, false);
+
+       startindex = DetectFirstTransition(data, len, high);
+  
+       if (high != 1)
+               // decode "raw"
+               bitlength = ManchesterConvertFrom255(data, len, bitStream, dataoutlen, high, low, clock, startindex);
+       else
+               // decode manchester
+               bitlength = ManchesterConvertFrom1(data, len, bitStream, dataoutlen, clock, startindex);
+
+       memcpy(dataout, bitStream, bitlength);
+       free(bitStream);
+       return bitlength;
+}
+ int DetectFirstTransition(const int * data, const size_t len, int threshold){
+
+       int i = 0;
+       /* now look for the first threshold */
+       for (; i < len; ++i) {
+               if (data[i] == threshold) {
+                       break;
+               }
+       }
+       return i;
+ }
+
+ int ManchesterConvertFrom255(const int * data, const size_t len, uint8_t * dataout, int dataoutlen, int high, int low, int clock, int startIndex){
+
+       int i, j, z, hithigh, hitlow, bitIndex, startType;
+       i = 0;
+       bitIndex = 0;
+       
+       int isDamp = 0;
+       int damplimit = (int)((high / 2) * 0.3);
+       int dampHi =  (high/2)+damplimit;
+       int dampLow = (high/2)-damplimit;
+       int firstST = 0;
+
+       // i = clock frame of data
+       for (; i < (int)(len/clock); i++)
+       {
+               hithigh = 0;
+               hitlow = 0;
+               startType = -1;
+               z = startIndex + (i*clock);
+               isDamp = 0;
+                       
+               /* Find out if we hit both high and low peaks */
+               for (j = 0; j < clock; j++)
+               {               
+                       if (data[z+j] == high){
+                               hithigh = 1;
+                               if ( startType == -1)
+                                       startType = 1;
+                       }
+                       
+                       if (data[z+j] == low ){
+                               hitlow = 1;
+                               if ( startType == -1)
+                                       startType = 0;
+                       } 
+               
+                       if (hithigh && hitlow)
+                         break;
+               }
+               
+               // No high value found, are we in a dampening field?
+               if ( !hithigh ) {
+                       //PrintAndLog(" # Entering damp test at index : %d (%d)", z+j, j);
+                       for (j = 0; j < clock; j++) {
+                               if ( 
+                                    (data[z+j] <= dampHi && data[z+j] >= dampLow)
+                                  ){
+                                  isDamp++;
+                               }
+                       }
+               }
+
+               /*  Manchester Switching..
+                       0: High -> Low   
+                       1: Low -> High  
+               */
+               if (startType == 0)
+                       dataout[bitIndex++] = 1;
+               else if (startType == 1) 
+                       dataout[bitIndex++] = 0;
+               else
+                       dataout[bitIndex++] = 2;
+                       
+               if ( isDamp > clock/2 ) {
+                       firstST++;
+               }
+               
+               if ( firstST == 4)
+                       break;
+               if ( bitIndex >= dataoutlen-1 )
+                       break;
+       }
+       return bitIndex;
+ }
+ int ManchesterConvertFrom1(const int * data, const size_t len, uint8_t * dataout,int dataoutlen, int clock, int startIndex){
+
+       int i,j, bitindex, lc, tolerance, warnings;
+       warnings = 0;
+       int upperlimit = len*2/clock+8;
+       i = startIndex;
+       j = 0;
+       tolerance = clock/4;
+       uint8_t decodedArr[len];
+       
+       /* Detect duration between 2 successive transitions */
+       for (bitindex = 1; i < len; i++) {
+       
+               if (data[i-1] != data[i]) {
+                       lc = i - startIndex;
+                       startIndex = i;
+
+                       // Error check: if bitindex becomes too large, we do not
+                       // have a Manchester encoded bitstream or the clock is really wrong!
+                       if (bitindex > upperlimit ) {
+                               PrintAndLog("Error: the clock you gave is probably wrong, aborting.");
+                               return 0;
+                       }
+                       // Then switch depending on lc length:
+                       // Tolerance is 1/4 of clock rate (arbitrary)
+                       if (abs((lc-clock)/2) < tolerance) {
+                               // Short pulse : either "1" or "0"
+                               decodedArr[bitindex++] = data[i-1];
+                       } else if (abs(lc-clock) < tolerance) {
+                               // Long pulse: either "11" or "00"
+                               decodedArr[bitindex++] = data[i-1];
+                               decodedArr[bitindex++] = data[i-1];
+                       } else {
+                               ++warnings;
+                               PrintAndLog("Warning: Manchester decode error for pulse width detection.");
+                               if (warnings > 10) {
+                                       PrintAndLog("Error: too many detection errors, aborting.");
+                                       return 0; 
+                               }
+                       }
+               }
+       }
+       
+       /* 
+       * We have a decodedArr of "01" ("1") or "10" ("0")
+       * parse it into final decoded dataout
+    */ 
+    for (i = 0; i < bitindex; i += 2) {
+
+           if ((decodedArr[i] == 0) && (decodedArr[i+1] == 1)) {
+                       dataout[j++] = 1;
+               } else if ((decodedArr[i] == 1) && (decodedArr[i+1] == 0)) {
+                       dataout[j++] = 0;
+               } else {
+                       i++;
+                       warnings++;
+                       PrintAndLog("Unsynchronized, resync...");
+                       PrintAndLog("(too many of those messages mean the stream is not Manchester encoded)");
+
+                       if (warnings > 10) {    
+                               PrintAndLog("Error: too many decode errors, aborting.");
+                               return 0;
+                       }
+               }
+    }
+       
+       PrintAndLog("%s", sprint_hex(dataout, j));
+       return j;
+ }
+ void ManchesterDiffDecodedString(const uint8_t* bitstream, size_t len, uint8_t invert){
+       /* 
+       * We have a bitstream of "01" ("1") or "10" ("0")
+       * parse it into final decoded bitstream
+    */ 
+       int i, j, warnings; 
+       uint8_t decodedArr[(len/2)+1];
+
+       j = warnings = 0;
+       
+       uint8_t lastbit = 0;
+       
+    for (i = 0; i < len; i += 2) {
+       
+               uint8_t first = bitstream[i];
+               uint8_t second = bitstream[i+1];
+
+               if ( first == second ) {
+                       ++i;
+                       ++warnings;
+                       if (warnings > 10) {
+                               PrintAndLog("Error: too many decode errors, aborting.");
+                               return;
+                       }
+               } 
+               else if ( lastbit != first ) {
+                       decodedArr[j++] = 0 ^ invert;
+               }
+               else {
+                       decodedArr[j++] = 1 ^ invert;
+               }
+               lastbit = second;
+    }
+       
+       PrintAndLog("%s", sprint_hex(decodedArr, j));
+}
+void PrintPaddedManchester( uint8_t* bitStream, size_t len, size_t blocksize){
+
+       PrintAndLog(" Manchester decoded  : %d bits", len);
+         
+       uint8_t mod = len % blocksize;
+       uint8_t div = len / blocksize;
+       int i;
+  
+       // Now output the bitstream to the scrollback by line of 16 bits
+       for (i = 0; i < div*blocksize; i+=blocksize) {
+               PrintAndLog(" %s", sprint_bin(bitStream+i,blocksize) );
+       }
+       
+       if ( mod > 0 )
+               PrintAndLog(" %s", sprint_bin(bitStream+i, mod) );      
+}
+
+/* Sliding DFT
+   Smooths out 
+*/ 
+void iceFsk2(int * data, const size_t len){
+
+       int i, j;
+       int * output =  (int* ) malloc(sizeof(int) * len);      
+       memset(output, 0x00, len);
+
+       // for (i=0; i<len-5; ++i){
+               // for ( j=1; j <=5; ++j) {
+                       // output[i] += data[i*j];
+               // }
+               // output[i] /= 5;
+       // }
+       int rest = 127;
+       int tmp =0;
+       for (i=0; i<len; ++i){
+               if ( data[i] < 127)
+                       output[i] = 0;
+               else {
+                       tmp =  (100 * (data[i]-rest)) / rest;
+                       output[i] = (tmp > 60)? 100:0;
+               }
+       }
+       
+       for (j=0; j<len; ++j)
+               data[j] = output[j];
+               
+       free(output);
+}
+
+void iceFsk3(int * data, const size_t len){
+
+       int i,j;
+       
+       int * output =  (int* ) malloc(sizeof(int) * len);      
+       memset(output, 0x00, len);
+       float fc           = 0.1125f;          // center frequency
+       size_t adjustedLen = len;
+       
+    // create very simple low-pass filter to remove images (2nd-order Butterworth)
+    float complex iir_buf[3] = {0,0,0};
+    float b[3] = {0.003621681514929,  0.007243363029857, 0.003621681514929};
+    float a[3] = {1.000000000000000, -1.822694925196308, 0.837181651256023};
+    
+    float sample           = 0;      // input sample read from file
+    float complex x_prime  = 1.0f;   // save sample for estimating frequency
+    float complex x;
+               
+       for (i=0; i<adjustedLen; ++i) {
+
+               sample = data[i]+128;
+               
+        // remove DC offset and mix to complex baseband
+        x = (sample - 127.5f) * cexpf( _Complex_I * 2 * M_PI * fc * i );
+
+        // apply low-pass filter, removing spectral image (IIR using direct-form II)
+        iir_buf[2] = iir_buf[1];
+        iir_buf[1] = iir_buf[0];
+        iir_buf[0] = x - a[1]*iir_buf[1] - a[2]*iir_buf[2];
+        x          = b[0]*iir_buf[0] +
+                     b[1]*iir_buf[1] +
+                     b[2]*iir_buf[2];
+                                        
+        // compute instantaneous frequency by looking at phase difference
+        // between adjacent samples
+        float freq = cargf(x*conjf(x_prime));
+        x_prime = x;    // retain this sample for next iteration
+
+               output[i] =(freq > 0)? 10 : -10;
+    } 
+
+       // show data
+       for (j=0; j<adjustedLen; ++j)
+               data[j] = output[j];
+               
+       CmdLtrim("30");
+       adjustedLen -= 30;
+       
+       // zero crossings.
+       for (j=0; j<adjustedLen; ++j){
+               if ( data[j] == 10) break;
+       }
+       int startOne =j;
+       
+       for (;j<adjustedLen; ++j){
+               if ( data[j] == -10 ) break;
+       }
+       int stopOne = j-1;
+       
+       int fieldlen = stopOne-startOne;
+       
+       fieldlen = (fieldlen == 39 || fieldlen == 41)? 40 : fieldlen;
+       fieldlen = (fieldlen == 59 || fieldlen == 51)? 50 : fieldlen;
+       if ( fieldlen != 40 && fieldlen != 50){
+               printf("Detected field Length: %d \n", fieldlen);
+               printf("Can only handle 40 or 50.  Aborting...\n");
+               return;
+       }
+       
+       // FSK sequence start == 000111
+       int startPos = 0;
+       for (i =0; i<adjustedLen; ++i){
+               int dec = 0;
+               for ( j = 0; j < 6*fieldlen; ++j){
+                       dec += data[i + j];
+               }
+               if (dec == 0) {
+                       startPos = i;
+                       break;
+               }
+       }
+       
+       printf("000111 position: %d \n", startPos);
+
+       startPos += 6*fieldlen+5;
+       
+       int bit =0;
+       printf("BINARY\n");
+       printf("R/40 :  ");
+       for (i =startPos ; i < adjustedLen; i += 40){
+               bit = data[i]>0 ? 1:0;
+               printf("%d", bit );
+       }
+       printf("\n");   
+       
+       printf("R/50 :  ");
+       for (i =startPos ; i < adjustedLen; i += 50){
+               bit = data[i]>0 ? 1:0;
+               printf("%d", bit );     }
+       printf("\n");   
+       
+       free(output);
+}
+
+float complex cexpf (float complex Z)
+{
+  float complex  Res;
+  double rho = exp (__real__ Z);
+  __real__ Res = rho * cosf(__imag__ Z);
+  __imag__ Res = rho * sinf(__imag__ Z);
+  return Res;
+}
index a45799d5c430dcad8094354a702cf81c9a7f47cb..6a45fcfdabb65a545478bcf77d5f9a31a41331b0 100644 (file)
 #ifndef UI_H__
 #define UI_H__
 
+#include <math.h>
+#include <complex.h>
+#include "util.h"
+
 void ShowGui(void);
 void HideGraphWindow(void);
 void ShowGraphWindow(void);
@@ -23,4 +27,13 @@ extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault;
 extern int offline;
 extern int flushAfterWrite;   //buzzy
 
+int manchester_decode( int * data, const size_t len, uint8_t * dataout,  size_t dataoutlen);
+int GetT55x7Clock( const int * data, const size_t len, int high );
+int DetectFirstTransition(const int * data, const size_t len, int low);
+void PrintPaddedManchester( uint8_t * bitStream, size_t len, size_t blocksize);
+void ManchesterDiffDecodedString( const uint8_t *bitStream, size_t len, uint8_t invert );
+int ManchesterConvertFrom255(const int * data, const size_t len, uint8_t * dataout,int dataoutlen, int high, int low, int clock, int startIndex);
+int ManchesterConvertFrom1(const int * data, const size_t len, uint8_t * dataout, int dataoutlen, int clock, int startIndex);
+void iceFsk2(int * data, const size_t len);
+void iceFsk3(int * data, const size_t len);
 #endif
index 2b2bb2fbd7c47fa514d5d2c05dadd890b9a69400..b933361048b6d3756e4c3e843976ce81fb360faf 100644 (file)
@@ -66,7 +66,9 @@ VPATH = . ../common/ ../fpga/
 
 INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/usb_cmd.h $(APP_INCLUDES)
 
-CFLAGS =  -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 $(APP_CFLAGS) -Os
+# compile hint: -flto to minimise size.
+CFLAGS =  -c $(INCLUDE) -Wall -Werror  -fdata-sections -ffunction-sections -pedantic -std=c99 -Os $(APP_CFLAGS)
+#CFLAGS =  -c $(INCLUDE) -Wall -Werror  -pedantic -std=c99 -Os $(APP_CFLAGS)
 LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n
 
 LIBS = -lgcc
diff --git a/common/crc64.c b/common/crc64.c
new file mode 100644 (file)
index 0000000..709c64d
--- /dev/null
@@ -0,0 +1,85 @@
+#include <stdint.h>
+#include <stddef.h>
+#include "crc64.h"
+
+#define CRC64_ISO_PRESET 0xFFFFFFFFFFFFFFFF
+#define CRC64_ECMA_PRESET 0x0000000000000000
+
+const uint64_t crc64_table[] = {
+                0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5,
+         0x493366450E42ECDF, 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A,
+         0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B,
+         0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4,
+         0x663D78FF90E185EF, 0x24CD9914390BB37C, 0xE3DCBB28C335E8C9, 0xA12C5AC36ADFDE5A,
+         0x2F0E1EBA9EA36930, 0x6DFEFF5137495FA3, 0xAAEFDD6DCD770416, 0xE81F3C86649D3285,
+         0xF45BB4758C645C51, 0xB6AB559E258E6AC2, 0x71BA77A2DFB03177, 0x334A9649765A07E4,
+         0xBD68D2308226B08E, 0xFF9833DB2BCC861D, 0x388911E7D1F2DDA8, 0x7A79F00C7818EB3B,
+         0xCC7AF1FF21C30BDE, 0x8E8A101488293D4D, 0x499B3228721766F8, 0x0B6BD3C3DBFD506B,
+         0x854997BA2F81E701, 0xC7B97651866BD192, 0x00A8546D7C558A27, 0x4258B586D5BFBCB4,
+         0x5E1C3D753D46D260, 0x1CECDC9E94ACE4F3, 0xDBFDFEA26E92BF46, 0x990D1F49C77889D5,
+         0x172F5B3033043EBF, 0x55DFBADB9AEE082C, 0x92CE98E760D05399, 0xD03E790CC93A650A,
+         0xAA478900B1228E31, 0xE8B768EB18C8B8A2, 0x2FA64AD7E2F6E317, 0x6D56AB3C4B1CD584,
+         0xE374EF45BF6062EE, 0xA1840EAE168A547D, 0x66952C92ECB40FC8, 0x2465CD79455E395B,
+         0x3821458AADA7578F, 0x7AD1A461044D611C, 0xBDC0865DFE733AA9, 0xFF3067B657990C3A,
+         0x711223CFA3E5BB50, 0x33E2C2240A0F8DC3, 0xF4F3E018F031D676, 0xB60301F359DBE0E5,
+         0xDA050215EA6C212F, 0x98F5E3FE438617BC, 0x5FE4C1C2B9B84C09, 0x1D14202910527A9A,
+         0x93366450E42ECDF0, 0xD1C685BB4DC4FB63, 0x16D7A787B7FAA0D6, 0x5427466C1E109645,
+         0x4863CE9FF6E9F891, 0x0A932F745F03CE02, 0xCD820D48A53D95B7, 0x8F72ECA30CD7A324,
+         0x0150A8DAF8AB144E, 0x43A04931514122DD, 0x84B16B0DAB7F7968, 0xC6418AE602954FFB,
+         0xBC387AEA7A8DA4C0, 0xFEC89B01D3679253, 0x39D9B93D2959C9E6, 0x7B2958D680B3FF75,
+         0xF50B1CAF74CF481F, 0xB7FBFD44DD257E8C, 0x70EADF78271B2539, 0x321A3E938EF113AA,
+         0x2E5EB66066087D7E, 0x6CAE578BCFE24BED, 0xABBF75B735DC1058, 0xE94F945C9C3626CB,
+         0x676DD025684A91A1, 0x259D31CEC1A0A732, 0xE28C13F23B9EFC87, 0xA07CF2199274CA14,
+         0x167FF3EACBAF2AF1, 0x548F120162451C62, 0x939E303D987B47D7, 0xD16ED1D631917144,
+         0x5F4C95AFC5EDC62E, 0x1DBC74446C07F0BD, 0xDAAD56789639AB08, 0x985DB7933FD39D9B,
+         0x84193F60D72AF34F, 0xC6E9DE8B7EC0C5DC, 0x01F8FCB784FE9E69, 0x43081D5C2D14A8FA,
+         0xCD2A5925D9681F90, 0x8FDAB8CE70822903, 0x48CB9AF28ABC72B6, 0x0A3B7B1923564425,
+         0x70428B155B4EAF1E, 0x32B26AFEF2A4998D, 0xF5A348C2089AC238, 0xB753A929A170F4AB,
+         0x3971ED50550C43C1, 0x7B810CBBFCE67552, 0xBC902E8706D82EE7, 0xFE60CF6CAF321874,
+         0xE224479F47CB76A0, 0xA0D4A674EE214033, 0x67C58448141F1B86, 0x253565A3BDF52D15,
+         0xAB1721DA49899A7F, 0xE9E7C031E063ACEC, 0x2EF6E20D1A5DF759, 0x6C0603E6B3B7C1CA,
+         0xF6FAE5C07D3274CD, 0xB40A042BD4D8425E, 0x731B26172EE619EB, 0x31EBC7FC870C2F78,
+         0xBFC9838573709812, 0xFD39626EDA9AAE81, 0x3A28405220A4F534, 0x78D8A1B9894EC3A7,
+         0x649C294A61B7AD73, 0x266CC8A1C85D9BE0, 0xE17DEA9D3263C055, 0xA38D0B769B89F6C6,
+         0x2DAF4F0F6FF541AC, 0x6F5FAEE4C61F773F, 0xA84E8CD83C212C8A, 0xEABE6D3395CB1A19,
+         0x90C79D3FEDD3F122, 0xD2377CD44439C7B1, 0x15265EE8BE079C04, 0x57D6BF0317EDAA97,
+         0xD9F4FB7AE3911DFD, 0x9B041A914A7B2B6E, 0x5C1538ADB04570DB, 0x1EE5D94619AF4648,
+         0x02A151B5F156289C, 0x4051B05E58BC1E0F, 0x87409262A28245BA, 0xC5B073890B687329,
+         0x4B9237F0FF14C443, 0x0962D61B56FEF2D0, 0xCE73F427ACC0A965, 0x8C8315CC052A9FF6,
+         0x3A80143F5CF17F13, 0x7870F5D4F51B4980, 0xBF61D7E80F251235, 0xFD913603A6CF24A6,
+         0x73B3727A52B393CC, 0x31439391FB59A55F, 0xF652B1AD0167FEEA, 0xB4A25046A88DC879,
+         0xA8E6D8B54074A6AD, 0xEA16395EE99E903E, 0x2D071B6213A0CB8B, 0x6FF7FA89BA4AFD18,
+         0xE1D5BEF04E364A72, 0xA3255F1BE7DC7CE1, 0x64347D271DE22754, 0x26C49CCCB40811C7,
+         0x5CBD6CC0CC10FAFC, 0x1E4D8D2B65FACC6F, 0xD95CAF179FC497DA, 0x9BAC4EFC362EA149,
+         0x158E0A85C2521623, 0x577EEB6E6BB820B0, 0x906FC95291867B05, 0xD29F28B9386C4D96,
+         0xCEDBA04AD0952342, 0x8C2B41A1797F15D1, 0x4B3A639D83414E64, 0x09CA82762AAB78F7,
+         0x87E8C60FDED7CF9D, 0xC51827E4773DF90E, 0x020905D88D03A2BB, 0x40F9E43324E99428,
+         0x2CFFE7D5975E55E2, 0x6E0F063E3EB46371, 0xA91E2402C48A38C4, 0xEBEEC5E96D600E57,
+         0x65CC8190991CB93D, 0x273C607B30F68FAE, 0xE02D4247CAC8D41B, 0xA2DDA3AC6322E288,
+         0xBE992B5F8BDB8C5C, 0xFC69CAB42231BACF, 0x3B78E888D80FE17A, 0x7988096371E5D7E9,
+         0xF7AA4D1A85996083, 0xB55AACF12C735610, 0x724B8ECDD64D0DA5, 0x30BB6F267FA73B36,
+         0x4AC29F2A07BFD00D, 0x08327EC1AE55E69E, 0xCF235CFD546BBD2B, 0x8DD3BD16FD818BB8,
+         0x03F1F96F09FD3CD2, 0x41011884A0170A41, 0x86103AB85A2951F4, 0xC4E0DB53F3C36767,
+         0xD8A453A01B3A09B3, 0x9A54B24BB2D03F20, 0x5D45907748EE6495, 0x1FB5719CE1045206,
+         0x919735E51578E56C, 0xD367D40EBC92D3FF, 0x1476F63246AC884A, 0x568617D9EF46BED9,
+         0xE085162AB69D5E3C, 0xA275F7C11F7768AF, 0x6564D5FDE549331A, 0x279434164CA30589,
+         0xA9B6706FB8DFB2E3, 0xEB46918411358470, 0x2C57B3B8EB0BDFC5, 0x6EA7525342E1E956,
+         0x72E3DAA0AA188782, 0x30133B4B03F2B111, 0xF7021977F9CCEAA4, 0xB5F2F89C5026DC37,
+         0x3BD0BCE5A45A6B5D, 0x79205D0E0DB05DCE, 0xBE317F32F78E067B, 0xFCC19ED95E6430E8,
+         0x86B86ED5267CDBD3, 0xC4488F3E8F96ED40, 0x0359AD0275A8B6F5, 0x41A94CE9DC428066,
+         0xCF8B0890283E370C, 0x8D7BE97B81D4019F, 0x4A6ACB477BEA5A2A, 0x089A2AACD2006CB9,
+         0x14DEA25F3AF9026D, 0x562E43B4931334FE, 0x913F6188692D6F4B, 0xD3CF8063C0C759D8,
+         0x5DEDC41A34BBEEB2, 0x1F1D25F19D51D821, 0xD80C07CD676F8394, 0x9AFCE626CE85B507
+};
+
+void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) {
+
+       for (size_t i = 0; i < len; i++)
+       {
+               //uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
+               uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff;
+               *crc = crc64_table[tableIndex] ^ (*crc << 8);
+       }
+}
+
+//suint8_t x =         (c & 0xFF00000000000000 ) >> 56;
\ No newline at end of file
diff --git a/common/crc64.h b/common/crc64.h
new file mode 100644 (file)
index 0000000..e28fba1
--- /dev/null
@@ -0,0 +1,14 @@
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+// CRC64 ECMA
+//-----------------------------------------------------------------------------
+
+#ifndef __CRC64_H
+#define __CRC64_H
+
+void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) ;
+
+#endif
diff --git a/common/desfire.h b/common/desfire.h
new file mode 100644 (file)
index 0000000..c163c5c
--- /dev/null
@@ -0,0 +1,179 @@
+#ifndef __DESFIRE_H
+#define __DESFIRE_H
+
+#include <string.h>
+#include <stdarg.h>
+
+#include "aes.h"
+
+#define MAX_CRYPTO_BLOCK_SIZE 16
+/* Mifare DESFire EV1 Application crypto operations */
+#define APPLICATION_CRYPTO_DES    0x00
+#define APPLICATION_CRYPTO_3K3DES 0x40
+#define APPLICATION_CRYPTO_AES    0x80
+
+#define MAC_LENGTH 4
+#define CMAC_LENGTH 8
+
+typedef enum {
+    MCD_SEND,
+    MCD_RECEIVE
+} MifareCryptoDirection;
+
+typedef enum {
+    MCO_ENCYPHER,
+    MCO_DECYPHER
+} MifareCryptoOperation;
+
+#define MDCM_MASK 0x000F
+
+#define CMAC_NONE 0
+
+// Data send to the PICC is used to update the CMAC
+#define CMAC_COMMAND 0x010
+// Data received from the PICC is used to update the CMAC
+#define CMAC_VERIFY  0x020
+
+// MAC the command (when MDCM_MACED)
+#define MAC_COMMAND 0x100
+// The command returns a MAC to verify (when MDCM_MACED)
+#define MAC_VERIFY  0x200
+
+#define ENC_COMMAND 0x1000
+#define NO_CRC      0x2000
+
+#define MAC_MASK   0x0F0
+#define CMAC_MACK  0xF00
+
+/* Communication mode */
+#define MDCM_PLAIN      0x00
+#define MDCM_MACED      0x01
+#define MDCM_ENCIPHERED 0x03
+
+/* Error code managed by the library */
+#define CRYPTO_ERROR            0x01
+
+
+enum DESFIRE_AUTH_SCHEME {
+       AS_LEGACY,
+       AS_NEW
+};
+
+enum DESFIRE_CRYPTOALGO {
+       T_DES = 0x00,
+       T_3DES = 0x01,
+       T_3K3DES = 0x02,
+       T_AES = 0x03
+};
+
+
+#define DESFIRE_KEY(key) ((struct desfire_key *) key)
+struct desfire_key {
+    enum DESFIRE_CRYPTOALGO type;
+    uint8_t data[24];
+    // DES_key_schedule ks1;
+    // DES_key_schedule ks2;
+    // DES_key_schedule ks3;
+       AesCtx aes_ks;
+    uint8_t cmac_sk1[24];
+    uint8_t cmac_sk2[24];
+    uint8_t aes_version;
+};
+typedef struct desfire_key *desfirekey_t;
+
+#define DESFIRE(tag) ((struct desfire_tag *) tag)
+struct desfire_tag {
+    iso14a_card_select_t info;
+    int active;
+    uint8_t last_picc_error;
+    uint8_t last_internal_error;
+    uint8_t last_pcd_error;
+    desfirekey_t session_key;
+       enum DESFIRE_AUTH_SCHEME authentication_scheme;
+    uint8_t authenticated_key_no;
+    
+       uint8_t ivect[MAX_CRYPTO_BLOCK_SIZE];
+    uint8_t cmac[16];
+    uint8_t *crypto_buffer;
+    size_t crypto_buffer_size;
+    uint32_t selected_application;
+};
+typedef struct desfire_tag *desfiretag_t;
+
+
+/* File types */
+enum DESFIRE_FILE_TYPES {
+    MDFT_STANDARD_DATA_FILE             = 0x00,
+    MDFT_BACKUP_DATA_FILE               = 0x01,
+    MDFT_VALUE_FILE_WITH_BACKUP         = 0x02,
+    MDFT_LINEAR_RECORD_FILE_WITH_BACKUP = 0x03,
+    MDFT_CYCLIC_RECORD_FILE_WITH_BACKUP = 0x04
+};
+
+
+
+enum DESFIRE_STATUS {
+    OPERATION_OK                               = 0x00,
+    NO_CHANGES                                         = 0x0c,
+    OUT_OF_EEPROM_ERROR                = 0x0e,
+    ILLEGAL_COMMAND_CODE               = 0x1c,
+    INTEGRITY_ERROR                    = 0x1e,
+    NO_SUCH_KEY                                = 0x40,
+    LENGTH_ERROR                               = 0x7e,
+    PERMISSION_DENIED                  = 0x9d,
+    PARAMETER_ERROR                    = 0x9e,
+    APPLICATION_NOT_FOUND              = 0xa0,
+    APPL_INTEGRITY_ERROR               = 0xa1,
+    AUTHENTICATION_ERROR               = 0xae,
+    ADDITIONAL_FRAME                   = 0xaf,
+    BOUNDARY_ERROR                             = 0xbe,
+    PICC_INTEGRITY_ERROR               = 0xc1,
+    COMMAND_ABORTED                    = 0xca,
+    PICC_DISABLED_ERROR                = 0xcd,
+    COUNT_ERROR                                = 0xce,
+    DUPLICATE_ERROR                    = 0xde,
+    EEPROM_ERROR                               = 0xee,
+    FILE_NOT_FOUND                             = 0xf0,
+    FILE_INTEGRITY_ERROR               = 0xf1
+};
+
+enum DESFIRE_CMD {
+    CREATE_APPLICATION                         = 0xca,
+    DELETE_APPLICATION                         = 0xda,
+    GET_APPLICATION_IDS                = 0x6a,
+    SELECT_APPLICATION                         = 0x5a,
+    FORMAT_PICC                                = 0xfc,
+    GET_VERSION                                = 0x60,
+    READ_DATA                                  = 0xbd,
+    WRITE_DATA                                 = 0x3d,
+    GET_VALUE                                  = 0x6c,
+    CREDIT                                             = 0x0c,
+    DEBIT                                              = 0xdc,
+    LIMITED_CREDIT                             = 0x1c,
+    WRITE_RECORD                               = 0x3b,
+    READ_RECORDS                               = 0xbb,
+    CLEAR_RECORD_FILE                  = 0xeb,
+    COMMIT_TRANSACTION                         = 0xc7,
+    ABORT_TRANSACTION                  = 0xa7,
+    GET_FREE_MEMORY             = 0x6e,
+       GET_FILE_IDS                            = 0x6f,
+    GET_FILE_SETTINGS                  = 0xf5,
+    CHANGE_FILE_SETTINGS               = 0x5f,
+    CREATE_STD_DATA_FILE               = 0xcd,
+    CREATE_BACKUP_DATA_FILE    = 0xcb,
+    CREATE_VALUE_FILE                  = 0xcc,
+    CREATE_LINEAR_RECORD_FILE  = 0xc1,
+    CREATE_CYCLIC_RECORD_FILE  = 0xc0,
+    DELETE_FILE                                = 0xdf,
+    AUTHENTICATE                               = 0x0a,  // AUTHENTICATE_NATIVE
+       AUTHENTICATE_ISO                        = 0x1a,  // AUTHENTICATE_STANDARD
+       AUTHENTICATE_AES                        = 0xaa,
+    CHANGE_KEY_SETTINGS                = 0x54,
+    GET_KEY_SETTINGS                   = 0x45,
+    CHANGE_KEY                                         = 0xc4,
+    GET_KEY_VERSION                    = 0x64,
+    AUTHENTICATION_FRAME               = 0xAF
+};
+
+#endif
+
index a6def1a91be2df84675660c67ec636ecc3ba4b55..851546ae239df0d728ecd73bf0367fae1c82e0fe 100644 (file)
@@ -6,7 +6,7 @@
 // ISO14443 CRC calculation code.
 //-----------------------------------------------------------------------------
 
-#include "iso14443crc.h"
+#include "../common/iso14443crc.h"
 
 static unsigned short UpdateCrc14443(unsigned char ch, unsigned short *lpwCrc)
 {
index 87347714dbe6be95f1570320efe2512e0f79d05f..80941116332a81430091eadb7c08b5cc39d57a91 100644 (file)
@@ -8,7 +8,7 @@
 
 #ifndef __ISO14443CRC_H
 #define __ISO14443CRC_H
-#include "common.h"
+#include "../include/common.h"
 
 //-----------------------------------------------------------------------------
 // Routines to compute the CRCs (two different flavours, just for confusion)
index 26e636ca7b0c27d90dee14bf3f79d70168fd546c..0ec5492b996d8897513b34e3a85b7f2adf9fd3d8 100644 (file)
@@ -7,7 +7,7 @@
 //-----------------------------------------------------------------------------
 
 
-#include "proxmark3.h"
+#include "../include/proxmark3.h"
 #include <stdint.h>
 #include <stdlib.h>
 //#include "iso15693tools.h"
index f1b63550df86f05f50625a4e0fb2be5891d506c7..c1a48dfc5bc8903e3350349eb603fe45d8c97cf8 100644 (file)
@@ -14,6 +14,7 @@ MEMORY
        bootphase1 : ORIGIN = 0x00100000, LENGTH = 0x200             /* Phase 1 bootloader: Copies real bootloader to RAM */
        bootphase2 : ORIGIN = 0x00100200, LENGTH = 0x2000 - 0x200    /* Main bootloader code, stored in Flash, executed from RAM */
        fpgaimage  : ORIGIN = 0x00102000, LENGTH = 96k - 0x2000      /* Place where the FPGA image will end up */
+       //osimage    : ORIGIN = 0x00118000, LENGTH = 256K - 96k        /* Place where the main OS will end up */
        osimage    : ORIGIN = 0x00118000, LENGTH = 256K - 96k        /* Place where the main OS will end up */
        ram        : ORIGIN = 0x00200000, LENGTH = 64K - 0x20        /* RAM, minus small common area */
        commonarea : ORIGIN = 0x00200000 + 64K - 0x20, LENGTH = 0x20 /* Communication between bootloader and main OS */
index 4f3b1ffee1167ab51a067502451cb4e634c88cef..322429ad716266924d72507ce02c248ac654dd38 100644 (file)
@@ -6,7 +6,7 @@
 // LEFIC's obfuscation function
 //-----------------------------------------------------------------------------
 
-#include "legic_prng.h"
+#include "../include/legic_prng.h"
 
 struct lfsr {
   uint8_t  a;
index 46e2bdd574d040268b2c4950a7d53e108ceca813..15121cbff408ffc7274cb55fcdaa14f35bc4656b 100644 (file)
@@ -19,7 +19,6 @@ int DetectASKClock(uint8_t dest[], size_t size, int *clock, int maxErr);
 uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low);
 int askmandemod(uint8_t *BinStream, size_t *size, int *clk, int *invert, int maxErr);
 uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo);
-//uint64_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx);
 int ManchesterEncode(uint8_t *BitStream, size_t size);
 int manrawdecode(uint8_t *BitStream, size_t *size);
 int BiphaseRawDecode(uint8_t * BitStream, size_t *size, int offset, int invert);
@@ -34,20 +33,16 @@ void psk1TOpsk2(uint8_t *BitStream, size_t size);
 void psk2TOpsk1(uint8_t *BitStream, size_t size);
 int DetectNRZClock(uint8_t dest[], size_t size, int clock);
 int indala26decode(uint8_t *bitStream, size_t *size, uint8_t *invert);
-void pskCleanWave(uint8_t *bitStream, size_t size);
 int PyramiddemodFSK(uint8_t *dest, size_t *size);
 int AWIDdemodFSK(uint8_t *dest, size_t *size);
 size_t removeParity(uint8_t *BitStream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen);
-uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t *mostFC);
+uint16_t countFC(uint8_t *BitStream, size_t size, uint8_t fskAdj);
 uint8_t detectFSKClk(uint8_t *BitStream, size_t size, uint8_t fcHigh, uint8_t fcLow);
 int getHiLo(uint8_t *BitStream, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo);
 int ParadoxdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo);
 uint8_t preambleSearch(uint8_t *BitStream, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx);
 uint8_t parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType);
-uint8_t justNoise(uint8_t *BitStream, size_t size);
-uint8_t countPSK_FC(uint8_t *BitStream, size_t size);
 int pskRawDemod(uint8_t dest[], size_t *size, int *clock, int *invert);
 int DetectPSKClock(uint8_t dest[], size_t size, int clock);
-void askAmp(uint8_t *BitStream, size_t size);
 
 #endif
index 01b738c2b6076ec1fed19d7d47dd2b2033683442..3cdf79f92a87b9616ba991491db8ad303cf03bb2 100644 (file)
@@ -168,9 +168,25 @@ NXP/Philips CUSTOM COMMANDS
 #define ISO15693_READ_MULTI_SECSTATUS 0x2C
 
 
+// Topaz command set:
+#define        TOPAZ_REQA                                              0x26    // Request
+#define        TOPAZ_WUPA                                              0x52    // WakeUp
+#define        TOPAZ_RID                                               0x78    // Read ID
+#define        TOPAZ_RALL                                              0x00    // Read All (all bytes)
+#define        TOPAZ_READ                                              0x01    // Read (a single byte)
+#define        TOPAZ_WRITE_E                                   0x53    // Write-with-erase (a single byte)
+#define        TOPAZ_WRITE_NE                                  0x1a    // Write-no-erase (a single byte)
+// additional commands for Dynamic Memory Model
+#define TOPAZ_RSEG                                             0x10    // Read segment
+#define TOPAZ_READ8                                            0x02    // Read (eight bytes)
+#define TOPAZ_WRITE_E8                                 0x54    // Write-with-erase (eight bytes)
+#define TOPAZ_WRITE_NE8                                        0x1B    // Write-no-erase (eight bytes)
+
+
 #define ISO_14443A 0
 #define ICLASS     1
 #define ISO_14443B 2
+#define TOPAZ          3
 
 //-- Picopass fuses
 #define FUSE_FPERS   0x80
diff --git a/cp2tau b/cp2tau
new file mode 100644 (file)
index 0000000..8b6ee4b
--- /dev/null
+++ b/cp2tau
@@ -0,0 +1,4 @@
+cp armsrc/obj/*.elf /z
+cp armsrc/obj/*.s19 /z
+cp bootrom/obj/*.elf /z
+cp bootrom/obj/*.s19 /z
diff --git a/iceman.txt b/iceman.txt
new file mode 100644 (file)
index 0000000..e69de29
index e2b7a7c5548e2fd37dde3864173cfe08ea95a8b7..89ff758e20727266698385204dc05e2f5b60c0e7 100644 (file)
@@ -11,7 +11,7 @@
 #ifndef _MIFARE_H_
 #define _MIFARE_H_
 
-#include "common.h"
+#include "../include/common.h"
 
 //-----------------------------------------------------------------------------
 // ISO 14443A
@@ -26,14 +26,15 @@ typedef struct {
 } __attribute__((__packed__)) iso14a_card_select_t;
 
 typedef enum ISO14A_COMMAND {
-       ISO14A_CONNECT = 1,
-       ISO14A_NO_DISCONNECT = 2,
-       ISO14A_APDU = 4,
-       ISO14A_RAW = 8,
-       ISO14A_REQUEST_TRIGGER = 0x10,
-       ISO14A_APPEND_CRC = 0x20,
-       ISO14A_SET_TIMEOUT = 0x40,
-       ISO14A_NO_SELECT = 0x80
+       ISO14A_CONNECT =                        (1 << 0),
+       ISO14A_NO_DISCONNECT =          (1 << 1),
+       ISO14A_APDU =                           (1 << 2),
+       ISO14A_RAW =                            (1 << 3),
+       ISO14A_REQUEST_TRIGGER =        (1 << 4),
+       ISO14A_APPEND_CRC =                     (1 << 5),
+       ISO14A_SET_TIMEOUT =            (1 << 6),
+       ISO14A_NO_SELECT =                      (1 << 7),
+       ISO14A_TOPAZMODE =                      (1 << 8)
 } iso14a_command_t;
 
 #endif // _MIFARE_H_
index 62c3d949d2427e934be53fa143c8ad01b45a38de..74d494c276ab41ca1d5ce15890985717d4c148f8 100644 (file)
@@ -128,11 +128,12 @@ typedef struct{
 #define CMD_READER_LEGIC_RF                                               0x0388
 #define CMD_WRITER_LEGIC_RF                                               0x0389
 #define CMD_EPA_PACE_COLLECT_NONCE                                        0x038A
+//#define CMD_EPA_                                                          0x038B
 
 #define CMD_SNOOP_ICLASS                                                  0x0392
 #define CMD_SIMULATE_TAG_ICLASS                                           0x0393
 #define CMD_READER_ICLASS                                                 0x0394
-#define CMD_READER_ICLASS_REPLAY                                                                                 0x0395
+#define CMD_READER_ICLASS_REPLAY                                                                                 0x0395
 #define CMD_ICLASS_ISO14443A_WRITE                                                                               0x0397
 #define CMD_ICLASS_EML_MEMSET                                             0x0398
 
@@ -163,9 +164,11 @@ typedef struct{
 #define CMD_MIFARE_NESTED                                                 0x0612
 
 #define CMD_MIFARE_READBL                                                 0x0620
-#define CMD_MIFAREU_READBL                                               0x0720
+#define CMD_MIFAREU_READBL                                                                       0x0720
+
 #define CMD_MIFARE_READSC                                                 0x0621
-#define CMD_MIFAREU_READCARD                                             0x0721
+#define CMD_MIFAREU_READCARD                                                                 0x0721
+
 #define CMD_MIFARE_WRITEBL                                                0x0622
 #define CMD_MIFAREU_WRITEBL                                                                      0x0722
 #define CMD_MIFAREU_WRITEBL_COMPAT                                                           0x0723
@@ -173,10 +176,13 @@ typedef struct{
 #define CMD_MIFARE_CHKKEYS                                                0x0623
 
 #define CMD_MIFARE_SNIFFER                                                0x0630
+
 //ultralightC
 #define CMD_MIFAREUC_AUTH1                                                                       0x0724
 #define CMD_MIFAREUC_AUTH2                                                                       0x0725
 #define CMD_MIFAREUC_READCARD                                                                0x0726
+#define CMD_MIFAREUC_SETPWD                                                                          0x0727
+#define CMD_MIFAREU_SETUID                                                                           0x0728
 
 // mifare desfire
 #define CMD_MIFARE_DESFIRE_READBL                                         0x0728
@@ -198,7 +204,7 @@ typedef struct{
 
 
 //Iclass reader flags
-#define FLAG_ICLASS_READER_ONLY_ONCE    0x01
+#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
 #define FLAG_ICLASS_READER_CC       0x02
 #define FLAG_ICLASS_READER_CSN         0x04
 #define FLAG_ICLASS_READER_CONF                0x08
index 19616441ad15e0338e688b02c6d8be84bb7f9ace..e12dd4472c4c6df0ff9a21bece88b037a199a59e 100644 (file)
@@ -16,7 +16,7 @@ my $gitbranch = `git rev-parse --abbrev-ref HEAD`;
 my $clean = 2;
 my @compiletime = gmtime();
 
-my $fullgitinfo = $gitbranch . '/' . $gitversion;
+my $fullgitinfo = 'iceman' . $gitbranch . '/' . $gitversion;
 
 $fullgitinfo =~ s/(\s)//g;
 
Impressum, Datenschutz