Merge pull request #119 from marshmellow42/pm3+reveng
authorIceman <iceman@iuse.se>
Sat, 8 Oct 2016 17:18:14 +0000 (19:18 +0200)
committerGitHub <noreply@github.com>
Sat, 8 Oct 2016 17:18:14 +0000 (19:18 +0200)
add reveng 1.30 source to PM3 for CRC calculations & searches

57 files changed:
.gitignore
CHANGELOG.md
COMPILING.txt
README.txt
armsrc/BigBuf.c
armsrc/BigBuf.h
armsrc/Makefile
armsrc/appmain.c
armsrc/apps.h
armsrc/fpgaloader.c
armsrc/fpgaloader.h
armsrc/hitag2.c
armsrc/hitagS.c [new file with mode: 0644]
armsrc/iso14443a.c
armsrc/iso14443b.c
armsrc/iso15693.c
armsrc/legicrf.c
armsrc/lfops.c
armsrc/lfsampling.c
armsrc/mifareutil.h
armsrc/pcf7931.c
bootrom/bootrom.c
client/Makefile
client/cmddata.c
client/cmddata.h
client/cmdhf14a.c
client/cmdhfmf.c
client/cmdhw.c
client/cmdlf.c
client/cmdlfhitag.c
client/cmdlfpresco.c [new file with mode: 0644]
client/cmdlfpresco.h [new file with mode: 0644]
client/cmdlfpyramid.c [new file with mode: 0644]
client/cmdlfpyramid.h [new file with mode: 0644]
client/cmdlft55xx.c
client/cmdlft55xx.h
client/cmdlfviking.c
client/fpga_compress.c
client/graph.c
client/hid-flasher/usb_cmd.h
client/lualibs/mf_default_keys.lua
client/nonce2key/nonce2key.c
client/nonce2key/nonce2key.h
client/proxgui.h
client/util.c
client/util.h
common/default_version.c
common/lfdemod.c
common/lfdemod.h
common/protocols.h
include/common.h
include/hitag2.h
include/hitagS.h [new file with mode: 0644]
include/usb_cmd.h
liblua/Makefile
tools/mfkey/example_trace.txt
tools/mfkey/mfkey64.c

index fa74326ed6f9297683b6124cb138becaa61bc94f..4af73fb12625d454c10459ea96660e5c689cc811 100644 (file)
@@ -21,6 +21,7 @@ flasher
 version.c
 lua
 luac
+fpga_compress
 
 fpga/*
 !fpga/tests
index 795564ae7d495ec4f161ae13ac7ef3083bfe773c..4b09e461cac3358d1f2e474099f10ff15f274f62 100644 (file)
@@ -5,6 +5,12 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
 ## [unreleased][unreleased]
 
 ### Added
+- Added lf pyramid commands (iceman)
+- Added lf presco commands - some bits not fully understood... (iceman)
+- Added experimental HitagS support (Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg)
+  see https://media.ccc.de/v/32c3-7166-sicherheit_von_125khz_transpondern_am_beispiel_hitag_s
+  English video available
+- Added a LF ASK Sequence Terminator detection option to the standard ask demod - and applied it to `lf search u`, `lf t55xx detect`, and `data rawdemod am s` (marshmellow)
 - `lf t55xx bruteforce <start password> <end password> [i <*.dic>]` - Simple bruteforce attack to find password - (iceman and others)
 - `lf viking clone`- clone viking tag to t55x7 or Q5 from 4byte hex ID input 
 - `lf viking sim`  - sim full viking tag from 4byte hex ID input
@@ -12,8 +18,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
 - `lf t55xx wipe`  - sets t55xx back to factory defaults
 - Added viking demod to `lf search` (marshmellow)
 - `data askvikingdemod` demod viking id tag from graphbuffer (marshmellow)
-- `lf t55xx resetread` added reset then read command - should allow determining start
-of stream transmissions (marshmellow)
+- `lf t55xx resetread` added reset then read command - should allow determining start of stream transmissions (marshmellow)
 - `lf t55xx wakeup` added wake with password (AOR) to allow lf search or standard lf read after (iceman, marshmellow)
 - `hf iclass managekeys` to save, load and manage iclass keys.  (adjusted most commands to accept a loaded key in memory) (marshmellow)
 - `hf iclass readblk` to select, authenticate, and read 1 block from an iclass card (marshmellow)
@@ -29,23 +34,32 @@ of stream transmissions (marshmellow)
 - Added 'hf snoop'. This command take digitalized signal from FPGA and put in BigBuffer. (pwpiwi + enio)
 - Added Topaz (NFC type 1) protocol support ('hf topaz reader', 'hf list topaz', 'hf 14a raw -T', 'hf topaz snoop'). (piwi)
 - Added option c to 'hf list' (mark CRC bytes) (piwi)
+- Added option `l` or `h` to `hw tune` to save time and unnecessary fpga writes if you are only interested in lf or hf.
 
 ### Changed
-- Added `[l] <length>` option to data printdemodbuffer
-- Adjusted lf awid clone to optionally clone to Q5 tags
-- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7
-- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal)
-- Adjusted lf pskindalademod to reduce false positive reads.
-- Small adjustments to psk, nrz, and ask clock detect routines - more reliable.
-- Adjusted lf em410x em410xsim to accept a clock argument
+- Fixed bug in lf biphase sim - `lf simask b` (and any tagtype that relies on it - gproxii...) (marshmellow)
+- Fixed bug in lf viking clone/sim (iceman)
+- Fixed broken `data askedgedetect` (marshmellow)
+- Adjusted hf mf sim command (marshmellow)
+    added auto run mfkey32 to extract all keys 
+    also added f parameter to allow attacking with UIDs from a file (implies x and i parameters)
+    also added e parameter to allow adding the extracted keys to emulator memory for the next simulation
+    added 10 byte uid option
+- Added `[l] <length>` option to data printdemodbuffer (marshmellow)
+- Adjusted lf awid clone to optionally clone to Q5 tags (marshmellow)
+- Adjusted lf t55xx detect to find Q5 tags (t5555) instead of just t55x7 (marshmellow)
+- Adjusted all lf NRZ demods - works more accurately and consistently (as long as you have strong signal) (marshmellow)
+- Adjusted lf pskindalademod to reduce false positive reads. (marshmellow)
+- Small adjustments to psk, nrz, and ask clock detect routines - more reliable. (marshmellow)
+- Adjusted lf em410x em410xsim to accept a clock argument (marshmellow)
 - Adjusted lf t55xx dump to allow overriding the safety check and warning text (marshmellow)
 - Adjusted lf t55xx write input variables (marshmellow)
 - Adjusted lf t55xx read with password safety check and warning text and adjusted the input variables (marshmellow & iceman)
-- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate.
+- Adjusted LF FSK demod to account for cross threshold fluctuations (898 count waves will adjust the 9 to 8 now...) more accurate. (marshmellow)
 - Adjusted timings for t55xx commands.  more reliable now. (marshmellow & iceman)
 - `lf cmdread` adjusted input methods and added help text (marshmellow & iceman)
 - changed `lf config t <threshold>` to be 0 - 128 and will trigger on + or - threshold value (marshmellow) 
-- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet)
+- `hf iclass dump` cli options - can now dump AA1 and AA2 with different keys in one run (does not go to multiple pages for the larger tags yet) (marshmellow)
 - Revised workflow for StandAloneMode14a (Craig Young)
 - EPA functions (`hf epa`) now support both ISO 14443-A and 14443-B cards (frederikmoellers)
 - 'hw version' only talks to ARM at startup, after that the info is cached. (pwpiwi)
index 1cc34a0fc008309d1376b1755ceeb09e19c9ae3a..e5abb25fc16dda96fa328dad210308fb7e008325 100644 (file)
@@ -86,19 +86,22 @@ Tested on OSX 10.10 Yosemite
 1 - Install Xcode and Xcode Command Line Tools
 
 2 - Install Homebrew and dependencies
-    brew install readline
-    brew instal libusb
+    brew install readline libusb p7zip libusb-compat wget qt5 pkgconfig
 
-3 - Download DevKitARM for OSX
-    http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/
-    Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory.
+3 - Install DevKitARM for OSX
+    Option 1:
+        http://sourceforge.net/projects/devkitpro/files/devkitARM/devkitARM_r44/
+        Unpack devkitARM_r44-osx.tar.bz2 to proxmark3 directory.
+    Option 2:
+        brew tap nitsky/stm32
+        brew install arm-none-eabi-gcc
 
-4 - Edit proxmark3/client/Makefile adding path to readline
+4 - Edit proxmark3/client/Makefile adding path to readline and qt5
 
-    LDLIBS = -L/usr/local/Cellar/readline/6.3.8/lib/ -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
-    CFLAGS = -std=c99 -I/usr/local/Cellar/readline/6.3.8/include/ -I. -I../include -I../common -I/opt/local/include -I../liblua  -Wall $(COMMON_FLAGS) -g -O4
+    LDLIBS = -L/usr/local/opt/readline/lib -L/usr/local/opt/qt5/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
+    CFLAGS = -std=c99 -I/usr/local/opt/qt5/include -I/usr/local/opt/readline/include -I. -I../include -I../common -I../zlib -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
 
-    Replace path /usr/local/Cellar/readline/6.3.8 with your actuall readline path. See homebrew manuals.
+    If your old brew intallation use /usr/local/Cellar/ path replace /usr/local/opt/readline/lib with your actuall readline and qt5 path. See homebrew manuals.
 
 5 - Set Environment
 
index 1a4ddb6d0e693b3192f7270a5b8326d75b4fd86a..295d57415c75db80592dc01f35bb35af7a809434 100644 (file)
@@ -45,6 +45,9 @@ following locations:
 
    * http://proxmark3.com/
    * http://www.xfpga.com/
+   * http://radiowar.taobao.com/
+   * http://www.elechouse.com/
+   * https://lab401.com/
 
 Most of the ultra-low-volume contract assemblers could put
 something like this together with a reasonable yield. A run of around
index da3b0ce27bcfa99b0f238fc8c330254f8e189c7b..851cf390e795faf4c6d3b3f58411e6d9966a2d5b 100644 (file)
@@ -61,6 +61,10 @@ void BigBuf_Clear_ext(bool verbose)
                Dbprintf("Buffer cleared (%i bytes)",BIGBUF_SIZE);
 }
 
+void BigBuf_Clear_keep_EM(void)
+{
+       memset(BigBuf,0,BigBuf_hi);
+}
 
 // allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
 // at the beginning of BigBuf is always for traces/samples
index 13432e7eabf2953e2ec0bfce9af9645897866b2a..928c50c4d8ca9b3a341fb41186bf9ad7eae7d190 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef __BIGBUF_H
 #define __BIGBUF_H
 
+#include <stdbool.h> // for bool
+#include "common.h"  // for ramfunc
 
 #define BIGBUF_SIZE                            40000
 #define MAX_FRAME_SIZE                 256             // maximum allowed ISO14443 frame
@@ -26,6 +28,7 @@ extern uint8_t *BigBuf_get_EM_addr(void);
 extern uint16_t BigBuf_max_traceLen(void);
 extern void BigBuf_Clear(void);
 extern void BigBuf_Clear_ext(bool verbose);
+extern void BigBuf_Clear_keep_EM(void);
 extern uint8_t *BigBuf_malloc(uint16_t);
 extern void BigBuf_free(void);
 extern void BigBuf_free_keep_EM(void);
index 69ea23006c54c4a8008880179bc8c9d67628a63c..0b540b8483aaa1a9ce7ce6e71d49019bd5337e82 100644 (file)
@@ -15,7 +15,7 @@ APP_CFLAGS    = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO144
 #-DWITH_LCD
 
 #SRC_LCD = fonts.c LCD.c
-SRC_LF = lfops.c hitag2.c lfsampling.c pcf7931.c lfdemod.c protocols.c
+SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c
 SRC_ISO15693 = iso15693.c iso15693tools.c
 SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
 SRC_ISO14443b = iso14443b.c
index 782c57fab10aa4371ce60d3ae64424bf81975874..aaa41f4acd3b6371092f5a86bb151236d7730bc5 100644 (file)
@@ -23,6 +23,7 @@
 
 #include "legicrf.h"
 #include <hitag2.h>
+#include <hitagS.h>
 #include "lfsampling.h"
 #include "BigBuf.h"
 #include "mifareutil.h"
@@ -36,8 +37,6 @@
  #include "iso14443a.h"
 #endif
 
-#define abs(x) ( ((x)<0) ? -(x) : (x) )
-
 //=============================================================================
 // A buffer where we can queue things up to be sent through the FPGA, for
 // any purpose (fake tag, as reader, whatever). We go MSB first, since that
@@ -181,13 +180,9 @@ int AvgAdc(int ch) // was static - merlok
        return (a + 15) >> 5;
 }
 
-void MeasureAntennaTuning(void)
+void MeasureAntennaTuningLfOnly(int *vLf125, int *vLf134, int *peakf, int *peakv, uint8_t LF_Results[])
 {
-       uint8_t LF_Results[256];
-       int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0 
-       int vLf125 = 0, vLf134 = 0, vHf = 0;    // in mV
-
-       LED_B_ON();
+       int i, adcval = 0, peak = 0;
 
 /*
  * Sweeps the useful LF range of the proxmark from
@@ -197,38 +192,67 @@ void MeasureAntennaTuning(void)
  * the resonating frequency of your LF antenna
  * ( hopefully around 95 if it is tuned to 125kHz!)
  */
-  
-       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
        for (i=255; i>=19; i--) {
-    WDT_HIT();
+               WDT_HIT();
                FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i);
                SpinDelay(20);
                adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10);
-               if (i==95)      vLf125 = adcval; // voltage at 125Khz
-               if (i==89)      vLf134 = adcval; // voltage at 134Khz
+               if (i==95) *vLf125 = adcval; // voltage at 125Khz
+               if (i==89) *vLf134 = adcval; // voltage at 134Khz
 
                LF_Results[i] = adcval>>8; // scale int to fit in byte for graphing purposes
                if(LF_Results[i] > peak) {
-                       peakv = adcval;
+                       *peakv = adcval;
                        peak = LF_Results[i];
-                       peakf = i;
+                       *peakf = i;
                        //ptr = i;
                }
        }
 
        for (i=18; i >= 0; i--) LF_Results[i] = 0;
-       
-       LED_A_ON();
+
+       return;
+}
+
+void MeasureAntennaTuningHfOnly(int *vHf)
+{
        // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
-       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+       LED_A_ON();
+       FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
        SpinDelay(20);
-       vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+       *vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
+       LED_A_OFF();
+
+       return;
+}
+
+void MeasureAntennaTuning(int mode)
+{
+       uint8_t LF_Results[256] = {0};
+       int peakv = 0, peakf = 0;
+       int vLf125 = 0, vLf134 = 0, vHf = 0; // in mV
+
+       LED_B_ON();
+
+       if (((mode & FLAG_TUNE_ALL) == FLAG_TUNE_ALL) && (FpgaGetCurrent() == FPGA_BITSTREAM_HF)) {
+               // Reverse "standard" order if HF already loaded, to avoid unnecessary swap.
+               MeasureAntennaTuningHfOnly(&vHf);
+               MeasureAntennaTuningLfOnly(&vLf125, &vLf134, &peakf, &peakv, LF_Results);
+       } else {
+               if (mode & FLAG_TUNE_LF) {
+                       MeasureAntennaTuningLfOnly(&vLf125, &vLf134, &peakf, &peakv, LF_Results);
+               }
+               if (mode & FLAG_TUNE_HF) {
+                       MeasureAntennaTuningHfOnly(&vHf);
+               }
+       }
 
        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;
 }
@@ -841,7 +865,7 @@ void ListenReaderField(int limit)
 
                if (limit != HF_ONLY) {
                        if(mode == 1) {
-                               if (abs(lf_av - lf_baseline) > REPORT_CHANGE) 
+                               if (ABS(lf_av - lf_baseline) > REPORT_CHANGE) 
                                        LED_D_ON();
                                else
                                        LED_D_OFF();
@@ -849,7 +873,7 @@ void ListenReaderField(int limit)
 
                        lf_av_new = AvgAdc(ADC_CHAN_LF);
                        // see if there's a significant change
-                       if(abs(lf_av - lf_av_new) > REPORT_CHANGE) {
+                       if(ABS(lf_av - lf_av_new) > REPORT_CHANGE) {
                                Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10);
                                lf_av = lf_av_new;
                                if (lf_av > lf_max)
@@ -859,7 +883,7 @@ void ListenReaderField(int limit)
 
                if (limit != LF_ONLY) {
                        if (mode == 1){
-                               if (abs(hf_av - hf_baseline) > REPORT_CHANGE)   
+                               if (ABS(hf_av - hf_baseline) > REPORT_CHANGE)   
                                        LED_B_ON();
                                else
                                        LED_B_OFF();
@@ -867,7 +891,7 @@ void ListenReaderField(int limit)
 
                        hf_av_new = AvgAdc(ADC_CHAN_HF);
                        // see if there's a significant change
-                       if(abs(hf_av - hf_av_new) > REPORT_CHANGE) {
+                       if(ABS(hf_av - hf_av_new) > REPORT_CHANGE) {
                                Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10);
                                hf_av = hf_av_new;
                                if (hf_av > hf_max)
@@ -1016,6 +1040,18 @@ void UsbPacketReceived(uint8_t *packet, int len)
                case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function
                        ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
                        break;
+               case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content
+                       SimulateHitagSTag((bool)c->arg[0],(byte_t*)c->d.asBytes);
+                       break;
+               case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file
+                       check_challenges((bool)c->arg[0],(byte_t*)c->d.asBytes);
+                       break;
+               case CMD_READ_HITAG_S://Reader for only Hitag S tags, args = key or challenge
+                       ReadHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
+                       break;
+               case CMD_WR_HITAG_S://writer for Hitag tags args=data to write,page and key or challenge
+                       WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]);
+                       break;
 #endif
 
 #ifdef WITH_ISO15693
@@ -1218,7 +1254,7 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        break;
 
                case CMD_MEASURE_ANTENNA_TUNING:
-                       MeasureAntennaTuning();
+                       MeasureAntennaTuning(c->arg[0]);
                        break;
 
                case CMD_MEASURE_ANTENNA_TUNING_HF:
index c8397c38cdf225cc1d810f8dc75916e653c428c4..4d4c80837ef72747387e699a98536fa4d3d7abaf 100644 (file)
@@ -16,6 +16,7 @@
 #include <stddef.h>
 #include "common.h"
 #include "hitag2.h"
+#include "hitagS.h"
 #include "mifare.h"
 #include "../common/crc32.h"
 #include "BigBuf.h"
@@ -179,6 +180,13 @@ void SnoopHitag(uint32_t type);
 void SimulateHitagTag(bool tag_mem_supplied, byte_t* data);
 void ReaderHitag(hitag_function htf, hitag_data* htd);
 
+//hitagS.h
+void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data);
+void ReadHitagS(hitag_function htf, hitag_data* htd);
+void WritePageHitagS(hitag_function htf, hitag_data* htd,int page);
+void check_challenges(bool file_given, byte_t* data);
+
+
 // cmd.h
 bool cmd_receive(UsbCommand* cmd);
 bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len);
index 308dda8c09e6ebf8fd0a691df91ccb0c0c3189d2..e211c12fbd5a7e5119b86d6196da954e1b0198ef 100644 (file)
@@ -566,3 +566,7 @@ void Fpga_print_status(void)
        else if(downloaded_bitstream == FPGA_BITSTREAM_LF) Dbprintf("  mode.............LF");
        else Dbprintf("  mode.............%d", downloaded_bitstream);
 }
+
+int FpgaGetCurrent() {
+       return downloaded_bitstream;
+}
index 38724cdba3dc996d71b58ccbd671b49b8bbf13ac..7dfc5c1265e539e8e8e419bb9ad68da857e6a061 100644 (file)
@@ -18,6 +18,7 @@ void FpgaSetupSsc(void);
 void SetupSpi(int mode);
 bool FpgaSetupSscDma(uint8_t *buf, int len);
 void Fpga_print_status();
+int FpgaGetCurrent();
 #define FpgaDisableSscDma(void)        AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
 #define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN;
 void SetAdcMuxFor(uint32_t whichGpio);
index 508157de9c9c2eb5e1f1e77cbfb14fa3b2e2ebc2..46432d835b284f06ff785dbe21f1cc5bc924e84e 100644 (file)
@@ -1148,7 +1148,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
       
                case RHT2F_CRYPTO: {
                        DbpString("Authenticating using key:");
-                       memcpy(key,htd->crypto.key,4);    //HACK; 4 or 6??  I read both in the code.
+                       memcpy(key,htd->crypto.key,6);    //HACK; 4 or 6??  I read both in the code.
                        Dbhexdump(6,key,false);
                        blocknr = 0;
                        bQuiet = false;
diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c
new file mode 100644 (file)
index 0000000..58e09a4
--- /dev/null
@@ -0,0 +1,2146 @@
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+// HitagS emulation (preliminary test version)
+//
+// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg
+//     <info@os-s.de>
+//-----------------------------------------------------------------------------
+// Some code was copied from Hitag2.c
+//-----------------------------------------------------------------------------
+
+
+#include <stdlib.h>
+#include "proxmark3.h"
+#include "apps.h"
+#include "util.h"
+#include "hitagS.h"
+#include "hitag2.h"
+#include "string.h"
+#include "BigBuf.h"
+
+#define CRC_PRESET 0xFF
+#define CRC_POLYNOM 0x1D
+
+#define u8                             uint8_t
+#define u32                            uint32_t
+#define u64                            uint64_t
+#define rev8(x)                        ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
+#define rev16(x)               (rev8 (x)+(rev8 (x>> 8)<< 8))
+#define rev32(x)               (rev16(x)+(rev16(x>>16)<<16))
+#define rev64(x)               (rev32(x)+(rev32(x>>32)<<32))
+#define bit(x,n)               (((x)>>(n))&1)
+#define bit32(x,n)             ((((x)[(n)>>5])>>((n)))&1)
+#define inv32(x,i,n)   ((x)[(i)>>5]^=((u32)(n))<<((i)&31))
+#define rotl64(x, n)   ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63)))
+
+static bool bQuiet;
+static bool bSuccessful;
+static struct hitagS_tag tag;
+static byte_t page_to_be_written = 0;
+static int block_data_left = 0;
+typedef enum modulation {
+       AC2K = 0, AC4K, MC4K, MC8K
+} MOD;
+static MOD m = AC2K;                   //used modulation
+static uint32_t temp_uid;
+static int temp2 = 0;
+static int sof_bits;                   //number of start-of-frame bits
+static byte_t pwdh0, pwdl0, pwdl1;     //password bytes
+static uint32_t rnd = 0x74124485;      //randomnumber
+static int test = 0;
+size_t blocknr;
+bool end=false;
+
+// Single bit Hitag2 functions:
+#define i4(x,a,b,c,d)  ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
+static const u32 ht2_f4a = 0x2C79;                     // 0010 1100 0111 1001
+static const u32 ht2_f4b = 0x6671;                     // 0110 0110 0111 0001
+static const u32 ht2_f5c = 0x7907287B;                 // 0111 1001 0000 0111 0010 1000 0111 1011
+#define ht2bs_4a(a,b,c,d)      (~(((a|b)&c)^(a|d)^b))
+#define ht2bs_4b(a,b,c,d)      (~(((d|c)&(a^b))^(d|a|b)))
+#define ht2bs_5c(a,b,c,d,e)    (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c))))
+#define uf20bs                         u32             
+
+static u32 f20(const u64 x) {
+       u32 i5;
+
+       i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
+                       + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2
+                       + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4
+                       + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8
+                       + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16;
+
+       return (ht2_f5c >> i5) & 1;
+}
+static u64 hitag2_round(u64 *state) {
+       u64 x = *state;
+
+       x = (x >> 1)
+                       + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8)
+                                       ^ (x >> 16) ^ (x >> 22) ^ (x >> 23) ^ (x >> 26) ^ (x >> 30)
+                                       ^ (x >> 41) ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47))
+                                       & 1) << 47);
+
+       *state = x;
+       return f20(x);
+}
+static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV) {
+       u32 i;
+       u64 x = ((key & 0xFFFF) << 32) + serial;
+       for (i = 0; i < 32; i++) {
+               x >>= 1;
+               x += (u64) (f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
+       }
+       return x;
+}
+static u32 hitag2_byte(u64 *x) {
+       u32 i, c;
+
+       for (i = 0, c = 0; i < 8; i++)
+               c += (u32) hitag2_round(x) << (i ^ 7);
+       return c;
+}
+
+// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
+// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
+// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
+// T0 = TIMER_CLOCK1 / 125000 = 192
+#define T0                                                     192
+
+#define SHORT_COIL()                                           LOW(GPIO_SSC_DOUT)
+#define OPEN_COIL()                                                    HIGH(GPIO_SSC_DOUT)
+
+#define HITAG_FRAME_LEN                                        20
+#define HITAG_T_STOP                                           36  /* T_EOF should be > 36 */
+#define HITAG_T_LOW                                            8   /* T_LOW should be 4..10 */
+#define HITAG_T_0_MIN                                          15  /* T[0] should be 18..22 */
+#define HITAG_T_1_MIN                                          25  /* T[1] should be 26..30 */
+//#define HITAG_T_EOF   40 /* T_EOF should be > 36 */
+#define HITAG_T_EOF                                            80   /* T_EOF should be > 36 */
+#define HITAG_T_WAIT_1                                                 200  /* T_wresp should be 199..206 */
+#define HITAG_T_WAIT_2                                                 90   /* T_wresp should be 199..206 */
+#define HITAG_T_WAIT_MAX                                       300  /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */
+
+#define HITAG_T_TAG_ONE_HALF_PERIOD                            10
+#define HITAG_T_TAG_TWO_HALF_PERIOD                            25
+#define HITAG_T_TAG_THREE_HALF_PERIOD                          41 
+#define HITAG_T_TAG_FOUR_HALF_PERIOD                           57
+       
+#define HITAG_T_TAG_HALF_PERIOD                                        16
+#define HITAG_T_TAG_FULL_PERIOD                                        32
+       
+#define HITAG_T_TAG_CAPTURE_ONE_HALF                           13
+#define HITAG_T_TAG_CAPTURE_TWO_HALF                           25
+#define HITAG_T_TAG_CAPTURE_THREE_HALF                         41
+#define HITAG_T_TAG_CAPTURE_FOUR_HALF                          57
+
+#define DEBUG 0
+
+/*
+ * Implementation of the crc8 calculation from Hitag S
+ * from http://www.proxmark.org/files/Documents/125%20kHz%20-%20Hitag/HitagS.V11.pdf
+ */
+void calc_crc(unsigned char * crc, unsigned char data, unsigned char Bitcount) {
+       *crc ^= data; // crc = crc (exor) data
+       do {
+               if (*crc & 0x80) // if (MSB-CRC == 1)
+                               {
+                       *crc <<= 1; // CRC = CRC Bit-shift left
+                       *crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM
+               } else {
+                       *crc <<= 1; // CRC = CRC Bit-shift left
+               }
+       } while (--Bitcount);
+}
+
+static void hitag_send_bit(int bit) {
+       LED_A_ON();
+       // Reset clock for the next bit
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+       switch (m) {
+       case AC2K:
+               if (bit == 0) {
+                       // AC Coding --__
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+                               ;
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 64)
+                               ;
+               } else {
+                       // AC coding -_-_
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+                               ;
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+                               ;
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 48)
+                               ;
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 64)
+                               ;;
+               }
+               LED_A_OFF();
+               break;
+       case AC4K:
+               if (bit == 0) {
+                       // AC Coding --__
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD)
+                               ;
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD)
+                               ;
+               } else {
+                       // AC coding -_-_
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 8)
+                               ;
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+                               ;
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 24)
+                               ;
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+                               ;;
+               }
+               LED_A_OFF();
+               break;
+       case MC4K:
+               if (bit == 0) {
+                       // Manchester: Unloaded, then loaded |__--|
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+                               ;
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+                               ;
+               } else {
+                       // Manchester: Loaded, then unloaded |--__|
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+                               ;
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 32)
+                               ;
+               }
+               LED_A_OFF();
+               break;
+       case MC8K:
+               if (bit == 0) {
+                       // Manchester: Unloaded, then loaded |__--|
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 8)
+                               ;
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+                               ;
+               } else {
+                       // Manchester: Loaded, then unloaded |--__|
+                       HIGH(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 8)
+                               ;
+                       LOW(GPIO_SSC_DOUT);
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 16)
+                               ;
+               }
+               LED_A_OFF();
+               break;
+       default:
+               break;
+       }
+}
+
+static void hitag_send_frame(const byte_t* frame, size_t frame_len) {
+// Send start of frame
+
+       for (size_t i = 0; i < sof_bits; i++) {
+               hitag_send_bit(1);
+       }
+
+// Send the content of the frame
+       for (size_t i = 0; i < frame_len; i++) {
+               hitag_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
+       }
+// Drop the modulation
+       LOW(GPIO_SSC_DOUT);
+}
+
+static void hitag_reader_send_bit(int bit) {
+//Dbprintf("BIT: %d",bit);
+       LED_A_ON();
+// Reset clock for the next bit
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+// Binary puls length modulation (BPLM) is used to encode the data stream
+// This means that a transmission of a one takes longer than that of a zero
+
+// Enable modulation, which means, drop the the field
+       HIGH(GPIO_SSC_DOUT);
+       if (test == 1) {
+               // Wait for 4-10 times the carrier period
+               while (AT91C_BASE_TC0->TC_CV < T0 * 6)
+                       ;
+               //      SpinDelayUs(8*8);
+
+               // Disable modulation, just activates the field again
+               LOW(GPIO_SSC_DOUT);
+
+               if (bit == 0) {
+                       // Zero bit: |_-|
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 11)
+                               ;
+                       //              SpinDelayUs(16*8);
+               } else {
+                       // One bit: |_--|
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 14)
+                               ;
+                       //              SpinDelayUs(22*8);
+               }
+       } else {
+               // Wait for 4-10 times the carrier period
+               while (AT91C_BASE_TC0->TC_CV < T0 * 6)
+                       ;
+               //      SpinDelayUs(8*8);
+
+               // Disable modulation, just activates the field again
+               LOW(GPIO_SSC_DOUT);
+
+               if (bit == 0) {
+                       // Zero bit: |_-|
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 22)
+                               ;
+                       //              SpinDelayUs(16*8);
+               } else {
+                       // One bit: |_--|
+                       while (AT91C_BASE_TC0->TC_CV < T0 * 28)
+                               ;
+                       //              SpinDelayUs(22*8);
+               }
+       }
+
+       LED_A_OFF();
+}
+
+static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len) {
+// Send the content of the frame
+       for (size_t i = 0; i < frame_len; i++) {
+               if (frame[0] == 0xf8) {
+                       //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1);
+               }
+               hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
+       }
+// Send EOF
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+// Enable modulation, which means, drop the the field
+       HIGH(GPIO_SSC_DOUT);
+// Wait for 4-10 times the carrier period
+       while (AT91C_BASE_TC0->TC_CV < T0 * 6)
+               ;
+// Disable modulation, just activates the field again
+       LOW(GPIO_SSC_DOUT);
+}
+
+/*
+ * to check if the right uid was selected
+ */
+static int check_select(byte_t* rx, uint32_t uid) {
+       unsigned char resp[48];
+       int i;
+       uint32_t ans = 0x0;
+       for (i = 0; i < 48; i++)
+               resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1;
+       for (i = 0; i < 32; i++)
+               ans += resp[5 + i] << (31 - i);
+       /*if (rx[0] == 0x01 && rx[1] == 0x15 && rx[2] == 0xc1 && rx[3] == 0x14
+        && rx[4] == 0x65 && rx[5] == 0x38)
+        Dbprintf("got uid %X", ans);*/
+       temp_uid = ans;
+       if (ans == tag.uid)
+               return 1;
+       return 0;
+}
+
+/*
+ * handles all commands from a reader
+ */
+static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen,
+               byte_t* tx, size_t* txlen) {
+       byte_t rx_air[HITAG_FRAME_LEN];
+       byte_t page;
+       int i;
+       u64 state;
+       unsigned char crc;
+
+// Copy the (original) received frame how it is send over the air
+       memcpy(rx_air, rx, nbytes(rxlen));
+// Reset the transmission frame length
+       *txlen = 0;
+// Try to find out which command was send by selecting on length (in bits)
+       switch (rxlen) {
+       case 5: {
+               //UID request with a selected response protocol mode
+               tag.pstate = READY;
+               tag.tstate = NO_OP;
+               if ((rx[0] & 0xf0) == 0x30) {
+                       tag.mode = STANDARD;
+                       sof_bits = 1;
+                       m = AC2K;
+               }
+               if ((rx[0] & 0xf0) == 0xc0) {
+                       tag.mode = ADVANCED;
+                       sof_bits = 3;
+                       m = AC2K;
+               }
+
+               if ((rx[0] & 0xf0) == 0xd0) {
+                       tag.mode = FAST_ADVANCED;
+                       sof_bits = 3;
+                       m = AC4K;
+               }
+               //send uid as a response
+               *txlen = 32;
+               for (i = 0; i < 4; i++)
+                       tx[i] = (tag.uid >> (24 - (i * 8))) & 0xff;
+       }
+               break;
+       case 45: {
+               //select command from reader received
+               if (check_select(rx, tag.uid) == 1) {
+                       //if the right tag was selected
+                       *txlen = 32;
+                       switch (tag.mode) {
+                       case STANDARD:
+                               sof_bits = 1;
+                               m = MC4K;
+                               break;
+                       case ADVANCED:
+                               sof_bits = 6;
+                               m = MC4K;
+                               break;
+                       case FAST_ADVANCED:
+                               sof_bits = 6;
+                               m = MC8K;
+                               break;
+                       default:
+                               break;
+                       }
+
+                       //send configuration
+                       for (i = 0; i < 4; i++)
+                               tx[i] = (tag.pages[0][1] >> (i * 8)) & 0xff;
+                       tx[3] = 0xff;
+                       if (tag.mode != STANDARD) {
+                               *txlen = 40;
+                               crc = CRC_PRESET;
+                               for (i = 0; i < 4; i++)
+                                       calc_crc(&crc, tx[i], 8);
+                               tx[4] = crc;
+                       }
+               }
+       }
+               break;
+       case 64: {
+               //challenge message received
+               Dbprintf("Challenge for UID: %X", temp_uid);
+               temp2++;
+               *txlen = 32;
+               state = hitag2_init(rev64(tag.key), rev32(tag.pages[0][0]),
+                               rev32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])));
+               Dbprintf(
+                               ",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}",
+                               rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
+               switch (tag.mode) {
+               case STANDARD:
+                       sof_bits = 1;
+                       m = MC4K;
+                       break;
+               case ADVANCED:
+                       sof_bits = 6;
+                       m = MC4K;
+                       break;
+               case FAST_ADVANCED:
+                       sof_bits = 6;
+                       m = MC8K;
+                       break;
+               default:
+                       break;
+               }
+
+               for (i = 0; i < 4; i++)
+                       hitag2_byte(&state);
+               //send con2,pwdh0,pwdl0,pwdl1 encrypted as a response
+               tx[0] = hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff);
+               tx[1] = hitag2_byte(&state) ^ tag.pwdh0;
+               tx[2] = hitag2_byte(&state) ^ tag.pwdl0;
+               tx[3] = hitag2_byte(&state) ^ tag.pwdl1;
+               if (tag.mode != STANDARD) {
+                       //add crc8
+                       *txlen = 40;
+                       crc = CRC_PRESET;
+                       calc_crc(&crc, ((tag.pages[0][1] >> 16) & 0xff), 8);
+                       calc_crc(&crc, tag.pwdh0, 8);
+                       calc_crc(&crc, tag.pwdl0, 8);
+                       calc_crc(&crc, tag.pwdl1, 8);
+                       tx[4] = (crc ^ hitag2_byte(&state));
+               }
+               /*
+                * some readers do not allow to authenticate multiple times in a row with the same tag.
+                * use this to change the uid between authentications.
+                */
+
+               /*
+                if (temp2 % 2 == 0) {
+                tag.uid = 0x11223344;
+                tag.pages[0][0] = 0x44332211;
+                } else {
+                tag.uid = 0x55667788;
+                tag.pages[0][0] = 0x88776655;
+                }
+                */
+       }
+       case 40:
+               //data received to be written
+               if (tag.tstate == WRITING_PAGE_DATA) {
+                       tag.tstate = NO_OP;
+                       tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0]
+                                       << 0) + (rx[1] << 8) + (rx[2] << 16) + (rx[3] << 24);
+                       //send ack
+                       *txlen = 2;
+                       tx[0] = 0x40;
+                       page_to_be_written = 0;
+                       switch (tag.mode) {
+                       case STANDARD:
+                               sof_bits = 1;
+                               m = MC4K;
+                               break;
+                       case ADVANCED:
+                               sof_bits = 6;
+                               m = MC4K;
+                               break;
+                       case FAST_ADVANCED:
+                               sof_bits = 6;
+                               m = MC8K;
+                               break;
+                       default:
+                               break;
+                       }
+               } else if (tag.tstate == WRITING_BLOCK_DATA) {
+                       tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0]
+                                       << 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3];
+                       //send ack
+                       *txlen = 2;
+                       tx[0] = 0x40;
+                       switch (tag.mode) {
+                       case STANDARD:
+                               sof_bits = 1;
+                               m = MC4K;
+                               break;
+                       case ADVANCED:
+                               sof_bits = 6;
+                               m = MC4K;
+                               break;
+                       case FAST_ADVANCED:
+                               sof_bits = 6;
+                               m = MC8K;
+                               break;
+                       default:
+                               break;
+                       }
+                       page_to_be_written++;
+                       block_data_left--;
+                       if (block_data_left == 0) {
+                               tag.tstate = NO_OP;
+                               page_to_be_written = 0;
+                       }
+               }
+               break;
+       case 20: {
+               //write page, write block, read page or read block command received
+               if ((rx[0] & 0xf0) == 0xc0) //read page
+                               {
+                       //send page data
+                       page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
+                       *txlen = 32;
+                       tx[0] = (tag.pages[page / 4][page % 4]) & 0xff;
+                       tx[1] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
+                       tx[2] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
+                       tx[3] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
+                       if (tag.LKP && page == 1)
+                               tx[3] = 0xff;
+
+                       switch (tag.mode) {
+                       case STANDARD:
+                               sof_bits = 1;
+                               m = MC4K;
+                               break;
+                       case ADVANCED:
+                               sof_bits = 6;
+                               m = MC4K;
+                               break;
+                       case FAST_ADVANCED:
+                               sof_bits = 6;
+                               m = MC8K;
+                               break;
+                       default:
+                               break;
+                       }
+
+                       if (tag.mode != STANDARD) {
+                               //add crc8
+                               *txlen = 40;
+                               crc = CRC_PRESET;
+                               for (i = 0; i < 4; i++)
+                                       calc_crc(&crc, tx[i], 8);
+                               tx[4] = crc;
+                       }
+
+                       if (tag.LKP && (page == 2 || page == 3)) {
+                               //if reader asks for key or password and the LKP-mark is set do not respond
+                               sof_bits = 0;
+                               *txlen = 0;
+                       }
+               } else if ((rx[0] & 0xf0) == 0xd0) //read block
+                               {
+                       page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
+                       *txlen = 32 * 4;
+                       //send page,...,page+3 data
+                       for (i = 0; i < 4; i++) {
+                               tx[0 + i * 4] = (tag.pages[page / 4][page % 4]) & 0xff;
+                               tx[1 + i * 4] = (tag.pages[page / 4][page % 4] >> 8) & 0xff;
+                               tx[2 + i * 4] = (tag.pages[page / 4][page % 4] >> 16) & 0xff;
+                               tx[3 + i * 4] = (tag.pages[page / 4][page % 4] >> 24) & 0xff;
+                               page++;
+                       }
+
+                       switch (tag.mode) {
+                       case STANDARD:
+                               sof_bits = 1;
+                               m = MC4K;
+                               break;
+                       case ADVANCED:
+                               sof_bits = 6;
+                               m = MC4K;
+                               break;
+                       case FAST_ADVANCED:
+                               sof_bits = 6;
+                               m = MC8K;
+                               break;
+                       default:
+                               break;
+                       }
+
+                       if (tag.mode != STANDARD) {
+                               //add crc8
+                               *txlen = 32 * 4 + 8;
+                               crc = CRC_PRESET;
+                               for (i = 0; i < 16; i++)
+                                       calc_crc(&crc, tx[i], 8);
+                               tx[16] = crc;
+                       }
+
+                       if ((page - 4) % 4 != 0 || (tag.LKP && (page - 4) == 0)) {
+                               sof_bits = 0;
+                               *txlen = 0;
+                       }
+               } else if ((rx[0] & 0xf0) == 0x80) //write page
+                               {
+                       page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16);
+
+                       switch (tag.mode) {
+                       case STANDARD:
+                               sof_bits = 1;
+                               m = MC4K;
+                               break;
+                       case ADVANCED:
+                               sof_bits = 6;
+                               m = MC4K;
+                               break;
+                       case FAST_ADVANCED:
+                               sof_bits = 6;
+                               m = MC8K;
+                               break;
+                       default:
+                               break;
+                       }
+                       if ((tag.LCON && page == 1)
+                                       || (tag.LKP && (page == 2 || page == 3))) {
+                               //deny
+                               *txlen = 0;
+                       } else {
+                               //allow
+                               *txlen = 2;
+                               tx[0] = 0x40;
+                               page_to_be_written = page;
+                               tag.tstate = WRITING_PAGE_DATA;
+                       }
+
+               } else if ((rx[0] & 0xf0) == 0x90) //write block
+                               {
+                       page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16);
+                       switch (tag.mode) {
+                       case STANDARD:
+                               sof_bits = 1;
+                               m = MC4K;
+                               break;
+                       case ADVANCED:
+                               sof_bits = 6;
+                               m = MC4K;
+                               break;
+                       case FAST_ADVANCED:
+                               sof_bits = 6;
+                               m = MC8K;
+                               break;
+                       default:
+                               break;
+                       }
+                       if (page % 4 != 0 || page == 0) {
+                               //deny
+                               *txlen = 0;
+                       } else {
+                               //allow
+                               *txlen = 2;
+                               tx[0] = 0x40;
+                               page_to_be_written = page;
+                               block_data_left = 4;
+                               tag.tstate = WRITING_BLOCK_DATA;
+                       }
+               }
+       }
+               break;
+       default:
+
+               break;
+       }
+}
+
+/*
+ * to autenticate to a tag with the given key or challenge
+ */
+static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr, byte_t* rx, const size_t rxlen, byte_t* tx,
+               size_t* txlen) {
+       byte_t rx_air[HITAG_FRAME_LEN];
+       int response_bit[200];
+       int i, j, z, k;
+       unsigned char mask = 1;
+       unsigned char uid[32];
+       byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00;
+       unsigned char crc;
+       u64 state;
+       byte_t auth_ks[4];
+       byte_t conf_pages[3];
+       memcpy(rx_air, rx, nbytes(rxlen));
+       *txlen = 0;
+
+       if (tag.pstate == READY && rxlen >= 67) {
+               //received uid
+               if(end==true) {
+                       Dbprintf("authentication failed!");
+                       return -1;
+               }
+               z = 0;
+               for (i = 0; i < 10; i++) {
+                       for (j = 0; j < 8; j++) {
+                               response_bit[z] = 0;
+                               if ((rx[i] & ((mask << 7) >> j)) != 0)
+                                       response_bit[z] = 1;
+                               z++;
+                       }
+               }
+               k = 0;
+               for (i = 5; i < z; i += 2) {
+                       uid[k] = response_bit[i];
+                       k++;
+                       if (k > 31)
+                               break;
+               }
+               uid1 = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) | (uid[3] << 4)
+                               | (uid[4] << 3) | (uid[5] << 2) | (uid[6] << 1) | uid[7];
+               uid2 = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) | (uid[11] << 4)
+                               | (uid[12] << 3) | (uid[13] << 2) | (uid[14] << 1) | uid[15];
+               uid3 = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) | (uid[19] << 4)
+                               | (uid[20] << 3) | (uid[21] << 2) | (uid[22] << 1) | uid[23];
+               uid4 = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) | (uid[27] << 4)
+                               | (uid[28] << 3) | (uid[29] << 2) | (uid[30] << 1) | uid[31];
+               if (DEBUG)
+                       Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4);
+               tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1);
+
+               //select uid
+               *txlen = 45;
+               crc = CRC_PRESET;
+               calc_crc(&crc, 0x00, 5);
+               calc_crc(&crc, uid1, 8);
+               calc_crc(&crc, uid2, 8);
+               calc_crc(&crc, uid3, 8);
+               calc_crc(&crc, uid4, 8);
+               for (i = 0; i < 100; i++) {
+                       response_bit[i] = 0;
+               }
+               for (i = 0; i < 5; i++) {
+                       response_bit[i] = 0;
+               }
+               for (i = 5; i < 37; i++) {
+                       response_bit[i] = uid[i - 5];
+               }
+               for (j = 0; j < 8; j++) {
+                       response_bit[i] = 0;
+                       if ((crc & ((mask << 7) >> j)) != 0)
+                               response_bit[i] = 1;
+                       i++;
+               }
+               k = 0;
+               for (i = 0; i < 6; i++) {
+                       tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6)
+                                       | (response_bit[k + 2] << 5) | (response_bit[k + 3] << 4)
+                                       | (response_bit[k + 4] << 3) | (response_bit[k + 5] << 2)
+                                       | (response_bit[k + 6] << 1) | response_bit[k + 7];
+                       k += 8;
+               }
+               tag.pstate = INIT;
+       } else if (tag.pstate == INIT && rxlen == 44) {
+               // received configuration after select command
+               z = 0;
+               for (i = 0; i < 6; i++) {
+                       for (j = 0; j < 8; j++) {
+                               response_bit[z] = 0;
+                               if ((rx[i] & ((mask << 7) >> j)) != 0)
+                                       response_bit[z] = 1;
+                               z++;
+                       }
+               }
+               conf_pages[0] = ((response_bit[4] << 7) | (response_bit[5] << 6)
+                               | (response_bit[6] << 5) | (response_bit[7] << 4)
+                               | (response_bit[8] << 3) | (response_bit[9] << 2)
+                               | (response_bit[10] << 1) | response_bit[11]);
+               //check wich memorysize this tag has
+               if (response_bit[10] == 0 && response_bit[11] == 0)
+                       tag.max_page = 32 / 32;
+               if (response_bit[10] == 0 && response_bit[11] == 1)
+                       tag.max_page = 256 / 32;
+               if (response_bit[10] == 1 && response_bit[11] == 0)
+                       tag.max_page = 2048 / 32;
+               conf_pages[1] = ((response_bit[12] << 7) | (response_bit[13] << 6)
+                               | (response_bit[14] << 5) | (response_bit[15] << 4)
+                               | (response_bit[16] << 3) | (response_bit[17] << 2)
+                               | (response_bit[18] << 1) | response_bit[19]);
+               tag.auth = response_bit[12];
+               tag.TTFC = response_bit[13];
+               //tag.TTFDR in response_bit[14] and response_bit[15]
+               //tag.TTFM in response_bit[16] and response_bit[17]
+               tag.LCON = response_bit[18];
+               tag.LKP = response_bit[19];
+               conf_pages[2] = ((response_bit[20] << 7) | (response_bit[21] << 6)
+                               | (response_bit[22] << 5) | (response_bit[23] << 4)
+                               | (response_bit[24] << 3) | (response_bit[25] << 2)
+                               | (response_bit[26] << 1) | response_bit[27]);
+               tag.LCK7 = response_bit[20];
+               tag.LCK6 = response_bit[21];
+               tag.LCK5 = response_bit[22];
+               tag.LCK4 = response_bit[23];
+               tag.LCK3 = response_bit[24];
+               tag.LCK2 = response_bit[25];
+               tag.LCK1 = response_bit[26];
+               tag.LCK0 = response_bit[27];
+
+               if (DEBUG)
+                       Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0],
+                                       conf_pages[1], conf_pages[2]);
+               if (tag.auth == 1) {
+                       //if the tag is in authentication mode try the key or challenge
+                       *txlen = 64;
+                       if(end!=true){
+                               if(htf==02||htf==04){ //RHTS_KEY //WHTS_KEY
+                                       state = hitag2_init(rev64(key), rev32(tag.uid),
+                                                       rev32(rnd));
+
+                                       for (i = 0; i < 4; i++) {
+                                               auth_ks[i] = hitag2_byte(&state) ^ 0xff;
+                                       }
+                                       *txlen = 64;
+                                       tx[0] = rnd & 0xff;
+                                       tx[1] = (rnd >> 8) & 0xff;
+                                       tx[2] = (rnd >> 16) & 0xff;
+                                       tx[3] = (rnd >> 24) & 0xff;
+
+                                       tx[4] = auth_ks[0];
+                                       tx[5] = auth_ks[1];
+                                       tx[6] = auth_ks[2];
+                                       tx[7] = auth_ks[3];
+                                       if (DEBUG)
+                                               Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0],
+                                                               tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]);
+                               } else if(htf==01 || htf==03) { //RHTS_CHALLENGE //WHTS_CHALLENGE
+                                       for (i = 0; i < 8; i++)
+                                               tx[i]=((NrAr>>(56-(i*8)))&0xff);
+                               }
+                               end=true;
+                               tag.pstate = AUTHENTICATE;
+                       } else {
+                               Dbprintf("authentication failed!");
+                               return -1;
+                       }
+               } else if (tag.auth == 0) {
+                       tag.pstate = SELECTED;
+               }
+               
+       } else if (tag.pstate == AUTHENTICATE && rxlen == 44) {
+               //encrypted con2,password received.
+               crc = CRC_PRESET;
+               calc_crc(&crc, 0x80, 1);
+               calc_crc(&crc, ((rx[0] & 0x0f) * 16 + ((rx[1] & 0xf0) / 16)), 8);
+               calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8);
+               calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8);
+               calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8);
+               if (DEBUG) {
+                       Dbprintf("UID:::%X", tag.uid);
+                       Dbprintf("RND:::%X", rnd);
+               }
+
+               //decrypt password
+               pwdh0=0;
+               pwdl0=0;
+               pwdl1=0;
+               if(htf==02 || htf==04){ //RHTS_KEY //WHTS_KEY
+               {
+                       state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd));
+                       for (i = 0; i < 5; i++)
+                               hitag2_byte(&state);
+                       pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16))
+                                       ^ hitag2_byte(&state);
+                       pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16))
+                                       ^ hitag2_byte(&state);
+                       pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16))
+                                       ^ hitag2_byte(&state);
+               }
+
+               if (DEBUG)
+                       Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1);
+               
+
+               //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16));
+               //rnd += 1;
+       }
+               tag.pstate = SELECTED; //tag is now ready for read/write commands
+       }
+       return 0;
+       
+}
+
+/*
+ * Emulates a Hitag S Tag with the given data from the .hts file
+ */
+void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) {
+       int frame_count;
+       int response;
+       int overflow;
+       int i, j;
+       byte_t rx[HITAG_FRAME_LEN];
+       size_t rxlen = 0;
+//bool bQuitTraceFull = false;
+       bQuiet = false;
+       byte_t txbuf[HITAG_FRAME_LEN];
+       byte_t* tx = txbuf;
+       size_t txlen = 0;
+       BigBuf_free();
+
+// Clean up trace and prepare it for storing frames
+       set_tracing(TRUE);
+       clear_trace();
+
+       DbpString("Starting HitagS simulation");
+       LED_D_ON();
+
+       tag.pstate = READY;
+       tag.tstate = NO_OP;
+       for (i = 0; i < 16; i++)
+               for (j = 0; j < 4; j++)
+                       tag.pages[i][j] = 0x0;
+       //read tag data into memory
+       if (tag_mem_supplied) {
+               DbpString("Loading hitagS memory...");
+               memcpy((byte_t*)tag.pages,data,4*64);
+       }
+       tag.uid=(uint32_t)tag.pages[0];
+       Dbprintf("Hitag S simulation started");
+       tag.key=(intptr_t)tag.pages[3];
+       tag.key<<=16;
+       tag.key+=((tag.pages[2][0])<<8)+tag.pages[2][1];
+       tag.pwdl0=tag.pages[2][3];
+       tag.pwdl1=tag.pages[2][2];
+       tag.pwdh0=tag.pages[1][0];
+       //con0
+       tag.max_page=64;
+       if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==1)
+               tag.max_page=8;
+       if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==0)
+               tag.max_page=0;
+       //con1
+       tag.auth=0;
+       if((tag.pages[1][2]&0x80)==1)
+               tag.auth=1;
+       tag.LCON=0;
+       if((tag.pages[1][2]&0x2)==1)
+               tag.LCON=1;
+       tag.LKP=0;
+       if((tag.pages[1][2]&0x1)==1)
+               tag.LKP=1;
+       //con2
+       //0=read write 1=read only
+       tag.LCK7=0;
+       if((tag.pages[1][1]&0x80)==1)
+               tag.LCK7=1;
+       tag.LCK6=0;
+       if((tag.pages[1][1]&0x40)==1)
+               tag.LCK6=1;
+       tag.LCK5=0;
+       if((tag.pages[1][1]&0x20)==1)
+               tag.LCK5=1;
+       tag.LCK4=0;
+       if((tag.pages[1][1]&0x10)==1)
+               tag.LCK4=1;
+       tag.LCK3=0;
+       if((tag.pages[1][1]&0x8)==1)
+               tag.LCK3=1;
+       tag.LCK2=0;
+       if((tag.pages[1][1]&0x4)==1)
+               tag.LCK2=1;
+       tag.LCK1=0;
+       if((tag.pages[1][1]&0x2)==1)
+               tag.LCK1=1;
+       tag.LCK0=0;
+       if((tag.pages[1][1]&0x1)==1)
+               tag.LCK0=1;
+
+// Set up simulator mode, frequency divisor which will drive the FPGA
+// and analog mux selection.
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+       FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+       RELAY_OFF();
+
+// Configure output pin that is connected to the FPGA (for modulating)
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+
+// Disable modulation at default, which means release resistance
+       LOW(GPIO_SSC_DOUT);
+
+// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
+
+// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+       AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
+
+// 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,
+// external trigger rising edge, load RA on rising edge of TIOA.
+       AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
+                       | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
+
+// Reset the received frame, frame count and timing info
+       memset(rx, 0x00, sizeof(rx));
+       frame_count = 0;
+       response = 0;
+       overflow = 0;
+
+// Enable and reset counter
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+       while (!BUTTON_PRESS()) {
+               // Watchdog hit
+               WDT_HIT();
+
+               // Receive frame, watch for at most T0*EOF periods
+               while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_EOF) {
+                       // Check if rising edge in modulation is detected
+                       if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
+                               // Retrieve the new timing values
+                               int ra = (AT91C_BASE_TC1->TC_RA / T0) + overflow;
+                               overflow = 0;
+
+                               // Reset timer every frame, we have to capture the last edge for timing
+                               AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+                               LED_B_ON();
+
+                               // Capture reader frame
+                               if (ra >= HITAG_T_STOP) {
+                                       if (rxlen != 0) {
+                                               //DbpString("wierd0?");
+                                       }
+                                       // Capture the T0 periods that have passed since last communication or field drop (reset)
+                                       response = (ra - HITAG_T_LOW);
+                               } else if (ra >= HITAG_T_1_MIN) {
+                                       // '1' bit
+                                       rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+                                       rxlen++;
+                               } else if (ra >= HITAG_T_0_MIN) {
+                                       // '0' bit
+                                       rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+                                       rxlen++;
+                               } else {
+                                       // Ignore wierd value, is to small to mean anything
+                               }
+                       }
+               }
+
+               // Check if frame was captured
+               if (rxlen > 0) {
+                       frame_count++;
+                       if (!bQuiet) {
+                               if (!LogTraceHitag(rx, rxlen, response, 0, true)) {
+                                       DbpString("Trace full");
+                                       clear_trace();
+                               }
+                       }
+
+                       // Disable timer 1 with external trigger to avoid triggers during our own modulation
+                       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+                       // Process the incoming frame (rx) and prepare the outgoing frame (tx)
+                       hitagS_handle_reader_command(rx, rxlen, tx, &txlen);
+
+                       // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit,
+                       // not that since the clock counts since the rising edge, but T_Wait1 is
+                       // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low)
+                       // periods. The gap time T_Low varies (4..10). All timer values are in
+                       // terms of T0 units
+                       while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW))
+                               ;
+
+                       // Send and store the tag answer (if there is any)
+                       if (txlen > 0) {
+                               // Transmit the tag frame
+                               hitag_send_frame(tx, txlen);
+                               // Store the frame in the trace
+                               if (!bQuiet) {
+                                       if (!LogTraceHitag(tx, txlen, 0, 0, false)) {
+                                               DbpString("Trace full");
+                                               clear_trace();
+                                       }
+                               }
+                       }
+
+                       // Reset the received frame and response timing info
+                       memset(rx, 0x00, sizeof(rx));
+                       response = 0;
+
+                       // Enable and reset external trigger in timer for capturing future frames
+                       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+                       LED_B_OFF();
+               }
+               // Reset the frame length
+               rxlen = 0;
+               // Save the timer overflow, will be 0 when frame was received
+               overflow += (AT91C_BASE_TC1->TC_CV / T0);
+               // Reset the timer to restart while-loop that receives frames
+               AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
+       }
+       LED_B_OFF();
+       LED_D_OFF();
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+}
+
+/*
+ * Authenticates to the Tag with the given key or challenge.
+ * If the key was given the password will be decrypted.
+ * Reads every page of a hitag S transpoder.
+ */
+void ReadHitagS(hitag_function htf, hitag_data* htd) {
+       int i, j, z, k;
+       int frame_count;
+       int response_bit[200];
+       int response;
+       byte_t rx[HITAG_FRAME_LEN];
+       size_t rxlen = 0;
+       byte_t txbuf[HITAG_FRAME_LEN];
+       byte_t* tx = txbuf;
+       size_t txlen = 0;
+       int lastbit;
+       bool bSkip;
+       int reset_sof;
+       int tag_sof;
+       int t_wait = HITAG_T_WAIT_MAX;
+       bool bStop;
+       bool bQuitTraceFull = false;
+       int sendNum = 0;
+       unsigned char mask = 1;
+       unsigned char crc;
+       unsigned char pageData[32];
+       page_to_be_written = 0;
+       
+       //read given key/challenge
+       byte_t NrAr_[8];
+       uint64_t key=0;
+       uint64_t NrAr=0;
+       byte_t key_[6];
+       switch(htf) {
+               case 01: { //RHTS_CHALLENGE
+                       DbpString("Authenticating using nr,ar pair:");
+                       memcpy(NrAr_,htd->auth.NrAr,8);
+                       Dbhexdump(8,NrAr_,false);
+                       NrAr=NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 |
+                                       ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
+               } break;
+               case 02: { //RHTS_KEY
+                       DbpString("Authenticating using key:");
+                       memcpy(key_,htd->crypto.key,6);  
+                       Dbhexdump(6,key_,false);
+                       key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40;
+               } break;
+               default: {
+                       Dbprintf("Error , unknown function: %d",htf);
+                       return;
+               } break;
+       }
+
+
+
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+// Reset the return status
+       bSuccessful = false;
+
+// Clean up trace and prepare it for storing frames
+       set_tracing(TRUE);
+       clear_trace();
+
+       bQuiet = false;
+       bQuitTraceFull = true;
+
+       LED_D_ON();
+
+// Configure output and enable pin that is connected to the FPGA (for modulating)
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+
+// Set fpga in edge detect with reader field, we can modulate as reader now
+       FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
+
+// Set Frequency divisor which will drive the FPGA and analog mux selection
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95);                                      //125Khz
+       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+       RELAY_OFF();
+
+// Disable modulation at default, which means enable the field
+       LOW(GPIO_SSC_DOUT);
+
+// Give it a bit of time for the resonant antenna to settle.
+       SpinDelay(30);
+
+// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
+
+// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+       AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
+
+// Disable timer during configuration
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
+// external trigger rising edge, load RA on falling edge of TIOA.
+       AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
+
+       | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING;
+
+// Enable and reset counters
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+// Reset the received frame, frame count and timing info
+       frame_count = 0;
+       response = 0;
+       lastbit = 1;
+       bStop = false;
+
+       reset_sof = 1;
+       t_wait = 200;
+
+       while (!bStop && !BUTTON_PRESS()) {
+               // Watchdog hit
+               WDT_HIT();
+
+               // Check if frame was captured and store it
+               if (rxlen > 0) {
+                       frame_count++;
+                       if (!bQuiet) {
+                               if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
+                                       DbpString("Trace full");
+                                       if (bQuitTraceFull) {
+                                               break;
+                                       } else {
+                                               bQuiet = true;
+                                       }
+                               }
+                       }
+               }
+
+               // By default reset the transmission buffer
+               tx = txbuf;
+               txlen = 0;
+
+               if (rxlen == 0) {
+                       //start authentication
+                       txlen = 5;
+                       memcpy(tx, "\xc0", nbytes(txlen));
+                       tag.pstate = READY;
+                       tag.tstate = NO_OP;
+               } else if (tag.pstate != SELECTED) {
+                       if (hitagS_handle_tag_auth(htf, key,NrAr,rx, rxlen, tx, &txlen) == -1)
+                               bStop = !false;
+               }
+               if (tag.pstate == SELECTED && tag.tstate == NO_OP && rxlen > 0) {
+                       //send read request
+                       tag.tstate = READING_PAGE;
+                       txlen = 20;
+                       crc = CRC_PRESET;
+                       tx[0] = 0xc0 + (sendNum / 16);
+                       calc_crc(&crc, tx[0], 8);
+                       calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4);
+                       tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16);
+                       tx[2] = 0x00 + (crc % 16) * 16;
+               } else if (tag.pstate == SELECTED && tag.tstate == READING_PAGE
+                               && rxlen > 0) {
+                       //save received data
+                       z = 0;
+                       for (i = 0; i < 5; i++) {
+                               for (j = 0; j < 8; j++) {
+                                       response_bit[z] = 0;
+                                       if ((rx[i] & ((mask << 7) >> j)) != 0)
+                                               response_bit[z] = 1;
+                                       z++;
+                               }
+                       }
+                       k = 0;
+                       for (i = 4; i < 36; i++) {
+                               pageData[k] = response_bit[i];
+                               k++;
+                       }
+                       for (i = 0; i < 4; i++)
+                               tag.pages[sendNum / 4][sendNum % 4] = 0x0;
+                       for (i = 0; i < 4; i++) {
+                               tag.pages[sendNum / 4][sendNum % 4] += ((pageData[i * 8] << 7)
+                                               | (pageData[1 + (i * 8)] << 6)
+                                               | (pageData[2 + (i * 8)] << 5)
+                                               | (pageData[3 + (i * 8)] << 4)
+                                               | (pageData[4 + (i * 8)] << 3)
+                                               | (pageData[5 + (i * 8)] << 2)
+                                               | (pageData[6 + (i * 8)] << 1) | pageData[7 + (i * 8)])
+                                               << (i * 8);
+                       }
+                       if (tag.auth && tag.LKP && sendNum == 1) {
+                               Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, pwdh0,
+                                               (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff,
+                                               (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff,
+                                               tag.pages[sendNum / 4][sendNum % 4] & 0xff);
+                       } else {
+                               Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum,
+                                               (tag.pages[sendNum / 4][sendNum % 4] >> 24) & 0xff,
+                                               (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff,
+                                               (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff,
+                                               tag.pages[sendNum / 4][sendNum % 4] & 0xff);
+                       }
+
+                       sendNum++;
+                       //display key and password if possible
+                       if (sendNum == 2 && tag.auth == 1 && tag.LKP) {
+                               if (htf == 02) { //RHTS_KEY
+                                       Dbprintf("Page[ 2]: %02X %02X %02X %02X",
+                                                       (byte_t)(key >> 8) & 0xff,
+                                                       (byte_t) key & 0xff, pwdl1, pwdl0);
+                                       Dbprintf("Page[ 3]: %02X %02X %02X %02X",
+                                                       (byte_t)(key >> 40) & 0xff,
+                                                       (byte_t)(key >> 32) & 0xff,
+                                                       (byte_t)(key >> 24) & 0xff,
+                                                       (byte_t)(key >> 16) & 0xff);
+                               } else {
+                                       //if the authentication is done with a challenge the key and password are unknown
+                                       Dbprintf("Page[ 2]: __ __ __ __");
+                                       Dbprintf("Page[ 3]: __ __ __ __");
+                               }
+                       }
+
+                       txlen = 20;
+                       crc = CRC_PRESET;
+                       tx[0] = 0xc0 + (sendNum / 16);
+                       calc_crc(&crc, tx[0], 8);
+                       calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4);
+                       tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16);
+                       tx[2] = 0x00 + (crc % 16) * 16;
+                       if (sendNum >= tag.max_page) {
+                               bStop = !false;
+                       }
+               }
+
+               // Send and store the reader command
+               // Disable timer 1 with external trigger to avoid triggers during our own modulation
+               AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+               // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
+               // Since the clock counts since the last falling edge, a 'one' means that the
+               // falling edge occured halfway the period. with respect to this falling edge,
+               // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
+               // All timer values are in terms of T0 units
+
+               while (AT91C_BASE_TC0->TC_CV
+                               < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit)))
+                       ;
+
+               // Transmit the reader frame
+               hitag_reader_send_frame(tx, txlen);
+
+               // Enable and reset external trigger in timer for capturing future frames
+               AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+               // Add transmitted frame to total count
+               if (txlen > 0) {
+                       frame_count++;
+                       if (!bQuiet) {
+                               // Store the frame in the trace
+                               if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
+                                       if (bQuitTraceFull) {
+                                               DbpString("Trace full");
+                                               break;
+                                       } else {
+                                               bQuiet = true;
+                                       }
+                               }
+                       }
+               }
+
+               // Reset values for receiving frames
+               memset(rx, 0x00, sizeof(rx));
+               rxlen = 0;
+               lastbit = 1;
+               bSkip = true;
+               tag_sof = reset_sof;
+               response = 0;
+
+               // Receive frame, watch for at most T0*EOF periods
+               while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
+                       // Check if falling edge in tag modulation is detected
+                       if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
+                               // Retrieve the new timing values
+                               int ra = (AT91C_BASE_TC1->TC_RA / T0);
+
+                               // Reset timer every frame, we have to capture the last edge for timing
+                               AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+                               LED_B_ON();
+
+                               // Capture tag frame (manchester decoding using only falling edges)
+                               if (ra >= HITAG_T_EOF) {
+                                       if (rxlen != 0) {
+                                               //DbpString("wierd1?");
+                                       }
+                                       // Capture the T0 periods that have passed since last communication or field drop (reset)
+                                       // We always recieve a 'one' first, which has the falling edge after a half period |-_|
+                                       response = ra - HITAG_T_TAG_HALF_PERIOD;
+                               } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
+                                       // Manchester coding example |-_|_-|-_| (101)
+                                       rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+                                       rxlen++;
+                                       rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+                                       rxlen++;
+                               } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
+                                       // Manchester coding example |_-|...|_-|-_| (0...01)
+                                       rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+                                       rxlen++;
+                                       // We have to skip this half period at start and add the 'one' the second time
+                                       if (!bSkip) {
+                                               rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+                                               rxlen++;
+                                       }
+                                       lastbit = !lastbit;
+                                       bSkip = !bSkip;
+                               } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
+                                       // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
+                                       if (tag_sof) {
+                                               // Ignore bits that are transmitted during SOF
+                                               tag_sof--;
+                                       } else {
+                                               // bit is same as last bit
+                                               rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
+                                               rxlen++;
+                                       }
+                               } else {
+                                       // Ignore wierd value, is to small to mean anything
+                               }
+                       }
+
+                       // We can break this loop if we received the last bit from a frame
+                       if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
+                               if (rxlen > 0)
+                                       break;
+                       }
+               }
+       }
+       end=false;
+       LED_B_OFF();
+       LED_D_OFF();
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0);
+}
+
+/*
+ * Authenticates to the Tag with the given Key or Challenge.
+ * Writes the given 32Bit data into page_
+ */
+void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) {
+       int frame_count;
+       int response;
+       byte_t rx[HITAG_FRAME_LEN];
+       size_t rxlen = 0;
+       byte_t txbuf[HITAG_FRAME_LEN];
+       byte_t* tx = txbuf;
+       size_t txlen = 0;
+       int lastbit;
+       bool bSkip;
+       int reset_sof;
+       int tag_sof;
+       int t_wait = HITAG_T_WAIT_MAX;
+       bool bStop;
+       bool bQuitTraceFull = false;
+       int page = page_;
+       unsigned char crc;
+       byte_t data[4]= {0,0,0,0};
+       
+       //read given key/challenge, the page and the data
+       byte_t NrAr_[8];
+       uint64_t key=0;
+       uint64_t NrAr=0;
+       byte_t key_[6];
+       switch(htf) {
+               case 03: { //WHTS_CHALLENGE
+                       memcpy(data,htd->auth.data,4);
+                       DbpString("Authenticating using nr,ar pair:");
+                       memcpy(NrAr_,htd->auth.NrAr,8);
+                       Dbhexdump(8,NrAr_,false);
+                       NrAr=NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 |
+                                       ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56;
+               } break;
+               case 04: { //WHTS_KEY
+                       memcpy(data,htd->crypto.data,4);
+                       DbpString("Authenticating using key:");
+                       memcpy(key_,htd->crypto.key,6);  
+                       Dbhexdump(6,key_,false);
+                       key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40;
+               } break;
+               default: {
+                       Dbprintf("Error , unknown function: %d",htf);
+                       return;
+               } break;
+       }
+
+       Dbprintf("Page: %d",page_);
+       Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]);
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+// Reset the return status
+       bSuccessful = false;
+
+       tag.pstate = READY;
+       tag.tstate = NO_OP;
+
+// Clean up trace and prepare it for storing frames
+       set_tracing(TRUE);
+       clear_trace();
+
+       bQuiet = false;
+       bQuitTraceFull = true;
+
+       LED_D_ON();
+
+// Configure output and enable pin that is connected to the FPGA (for modulating)
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+
+// Set fpga in edge detect with reader field, we can modulate as reader now
+       FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
+
+// Set Frequency divisor which will drive the FPGA and analog mux selection
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
+       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+       RELAY_OFF();
+
+// Disable modulation at default, which means enable the field
+       LOW(GPIO_SSC_DOUT);
+
+// Give it a bit of time for the resonant antenna to settle.
+       SpinDelay(30);
+
+// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
+
+// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+       AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
+
+// Disable timer during configuration
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
+// external trigger rising edge, load RA on falling edge of TIOA.
+       AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
+                       | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG
+                       | AT91C_TC_LDRA_FALLING;
+
+// Enable and reset counters
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+// Reset the received frame, frame count and timing info
+       frame_count = 0;
+       response = 0;
+       lastbit = 1;
+       bStop = false;
+
+       reset_sof = 1;
+       t_wait = 200;
+
+       while (!bStop && !BUTTON_PRESS()) {
+               // Watchdog hit
+               WDT_HIT();
+
+               // Check if frame was captured and store it
+               if (rxlen > 0) {
+                       frame_count++;
+                       if (!bQuiet) {
+                               if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
+                                       DbpString("Trace full");
+                                       if (bQuitTraceFull) {
+                                               break;
+                                       } else {
+                                               bQuiet = true;
+                                       }
+                               }
+                       }
+               }
+
+               //check for valid input
+               if (page == 0) {
+                       Dbprintf(
+                                       "usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]");           
+                       bStop = !false;
+               }
+
+               // By default reset the transmission buffer
+               tx = txbuf;
+               txlen = 0;
+
+               if (rxlen == 0 && tag.tstate == WRITING_PAGE_ACK) {
+                       //no write access on this page
+                       Dbprintf("no write access on page %d", page_);
+                       bStop = !false;
+               } else if (rxlen == 0 && tag.tstate != WRITING_PAGE_DATA) {
+                       //start the authetication
+                       txlen = 5;
+                       memcpy(tx, "\xc0", nbytes(txlen));
+                       tag.pstate = READY;
+                       tag.tstate = NO_OP;
+               } else if (tag.pstate != SELECTED) {
+                       //try to authenticate with the given key or challenge
+                       if (hitagS_handle_tag_auth(htf,key,NrAr,rx, rxlen, tx, &txlen) == -1)
+                               bStop = !false;
+               }
+               if (tag.pstate == SELECTED && tag.tstate == NO_OP && rxlen > 0) {
+                       //check if the given page exists
+                       if (page > tag.max_page) {
+                               Dbprintf("page number too big");
+                               bStop = !false;
+                       }
+                       //ask Tag for write permission
+                       tag.tstate = WRITING_PAGE_ACK;
+                       txlen = 20;
+                       crc = CRC_PRESET;
+                       tx[0] = 0x90 + (page / 16);
+                       calc_crc(&crc, tx[0], 8);
+                       calc_crc(&crc, 0x00 + ((page % 16) * 16), 4);
+                       tx[1] = 0x00 + ((page % 16) * 16) + (crc / 16);
+                       tx[2] = 0x00 + (crc % 16) * 16;
+               } else if (tag.pstate == SELECTED && tag.tstate == WRITING_PAGE_ACK
+                               && rxlen == 6 && rx[0] == 0xf4) {
+                       //ACK recieved to write the page. send data
+                       tag.tstate = WRITING_PAGE_DATA;
+                       txlen = 40;
+                       crc = CRC_PRESET;
+                       calc_crc(&crc, data[3], 8);
+                       calc_crc(&crc, data[2], 8);
+                       calc_crc(&crc, data[1], 8);
+                       calc_crc(&crc, data[0], 8);
+                       tx[0] = data[3];
+                       tx[1] = data[2];
+                       tx[2] = data[1];
+                       tx[3] = data[0];
+                       tx[4] = crc;
+               } else if (tag.pstate == SELECTED && tag.tstate == WRITING_PAGE_DATA
+                               && rxlen == 6 && rx[0] == 0xf4) {
+                       //received ACK
+                       Dbprintf("Successful!");
+                       bStop = !false;
+               }
+
+               // Send and store the reader command
+               // Disable timer 1 with external trigger to avoid triggers during our own modulation
+               AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+               // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
+               // Since the clock counts since the last falling edge, a 'one' means that the
+               // falling edge occured halfway the period. with respect to this falling edge,
+               // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
+               // All timer values are in terms of T0 units
+
+               while (AT91C_BASE_TC0->TC_CV
+                               < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit)))
+                       ;
+
+               // Transmit the reader frame
+               hitag_reader_send_frame(tx, txlen);
+
+               // Enable and reset external trigger in timer for capturing future frames
+               AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+               // Add transmitted frame to total count
+               if (txlen > 0) {
+                       frame_count++;
+                       if (!bQuiet) {
+                               // Store the frame in the trace
+                               if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
+                                       if (bQuitTraceFull) {
+                                               DbpString("Trace full");
+                                               break;
+                                       } else {
+                                               bQuiet = true;
+                                       }
+                               }
+                       }
+               }
+
+               // Reset values for receiving frames
+               memset(rx, 0x00, sizeof(rx));
+               rxlen = 0;
+               lastbit = 1;
+               bSkip = true;
+               tag_sof = reset_sof;
+               response = 0;
+
+               // Receive frame, watch for at most T0*EOF periods
+               while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
+                       // Check if falling edge in tag modulation is detected
+                       if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
+                               // Retrieve the new timing values
+                               int ra = (AT91C_BASE_TC1->TC_RA / T0);
+
+                               // Reset timer every frame, we have to capture the last edge for timing
+                               AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+                               LED_B_ON();
+
+                               // Capture tag frame (manchester decoding using only falling edges)
+                               if (ra >= HITAG_T_EOF) {
+                                       if (rxlen != 0) {
+                                               //DbpString("wierd1?");
+                                       }
+                                       // Capture the T0 periods that have passed since last communication or field drop (reset)
+                                       // We always recieve a 'one' first, which has the falling edge after a half period |-_|
+                                       response = ra - HITAG_T_TAG_HALF_PERIOD;
+                               } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
+                                       // Manchester coding example |-_|_-|-_| (101)
+                                       rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+                                       rxlen++;
+                                       rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+                                       rxlen++;
+                               } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
+                                       // Manchester coding example |_-|...|_-|-_| (0...01)
+                                       rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+                                       rxlen++;
+                                       // We have to skip this half period at start and add the 'one' the second time
+                                       if (!bSkip) {
+                                               rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+                                               rxlen++;
+                                       }
+                                       lastbit = !lastbit;
+                                       bSkip = !bSkip;
+                               } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
+                                       // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
+                                       if (tag_sof) {
+                                               // Ignore bits that are transmitted during SOF
+                                               tag_sof--;
+                                       } else {
+                                               // bit is same as last bit
+                                               rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
+                                               rxlen++;
+                                       }
+                               } else {
+                                       // Ignore wierd value, is to small to mean anything
+                               }
+                       }
+
+                       // We can break this loop if we received the last bit from a frame
+                       if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
+                               if (rxlen > 0)
+                                       break;
+                       }
+               }
+       }
+       end=false;
+       LED_B_OFF();
+       LED_D_OFF();
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0);
+}
+
+/*
+ * Tries to authenticate to a Hitag S Transponder with the given challenges from a .cc file.
+ * Displays all Challenges that failed.
+ * When collecting Challenges to break the key it is possible that some data
+ * is not received correctly due to Antenna problems. This function
+ * detects these challenges.
+ */
+void check_challenges(bool file_given, byte_t* data) {
+       int i, j, z, k;
+       byte_t uid_byte[4];
+       int frame_count;
+       int response;
+       byte_t rx[HITAG_FRAME_LEN];
+       byte_t unlocker[60][8];
+       int u1 = 0;
+       size_t rxlen = 0;
+       byte_t txbuf[HITAG_FRAME_LEN];
+       byte_t* tx = txbuf;
+       size_t txlen = 0;
+       int lastbit;
+       bool bSkip;
+       int reset_sof;
+       int tag_sof;
+       int t_wait = HITAG_T_WAIT_MAX;
+       int STATE = 0;
+       bool bStop;
+       bool bQuitTraceFull = false;
+       int response_bit[200];
+       unsigned char mask = 1;
+       unsigned char uid[32];
+       unsigned char crc;
+
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+// Reset the return status
+       bSuccessful = false;
+
+// Clean up trace and prepare it for storing frames
+       set_tracing(TRUE);
+       clear_trace();
+
+       bQuiet = false;
+       bQuitTraceFull = true;
+
+       LED_D_ON();
+
+// Configure output and enable pin that is connected to the FPGA (for modulating)
+       AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
+       AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
+
+// Set fpga in edge detect with reader field, we can modulate as reader now
+       FpgaWriteConfWord(
+       FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
+
+// Set Frequency divisor which will drive the FPGA and analog mux selection
+       FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95);                                      //125Khz
+       SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
+       RELAY_OFF();
+
+// Disable modulation at default, which means enable the field
+       LOW(GPIO_SSC_DOUT);
+
+// Give it a bit of time for the resonant antenna to settle.
+       SpinDelay(30);
+
+// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
+
+// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames
+       AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
+       AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
+
+// Disable timer during configuration
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
+// external trigger rising edge, load RA on falling edge of TIOA.
+       AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK
+
+       | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING;
+
+// Enable and reset counters
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+// Reset the received frame, frame count and timing info
+       frame_count = 0;
+       response = 0;
+       lastbit = 1;
+       bStop = false;
+
+       reset_sof = 1;
+       t_wait = 200;
+
+       if (file_given) {
+               DbpString("Loading challenges...");
+               memcpy((byte_t*)unlocker,data,60*8);
+       }
+
+       while (file_given && !bStop && !BUTTON_PRESS()) {
+               // Watchdog hit
+               WDT_HIT();
+
+               // Check if frame was captured and store it
+               if (rxlen > 0) {
+                       frame_count++;
+                       if (!bQuiet) {
+                               if (!LogTraceHitag(rx, rxlen, response, 0, false)) {
+                                       DbpString("Trace full");
+                                       if (bQuitTraceFull) {
+                                               break;
+                                       } else {
+                                               bQuiet = true;
+                                       }
+                               }
+                       }
+               }
+
+               tx = txbuf;
+               txlen = 0;
+               if (rxlen == 0) {
+                       if (STATE == 2)
+                               // challenge failed
+                               Dbprintf("Challenge failed: %02X %02X %02X %02X %02X %02X %02X %02X",
+                                               unlocker[u1 - 1][0], unlocker[u1 - 1][1],
+                                               unlocker[u1 - 1][2], unlocker[u1 - 1][3],
+                                               unlocker[u1 - 1][4], unlocker[u1 - 1][5],
+                                               unlocker[u1 - 1][6], unlocker[u1 - 1][7]);
+                       STATE = 0;
+                       txlen = 5;
+                       //start new authentication
+                       memcpy(tx, "\xc0", nbytes(txlen));
+               } else if (rxlen >= 67 && STATE == 0) {
+                       //received uid
+                       z = 0;
+                       for (i = 0; i < 10; i++) {
+                               for (j = 0; j < 8; j++) {
+                                       response_bit[z] = 0;
+                                       if ((rx[i] & ((mask << 7) >> j)) != 0)
+                                               response_bit[z] = 1;
+                                       z++;
+                               }
+                       }
+                       k = 0;
+                       for (i = 5; i < z; i += 2) {
+                               uid[k] = response_bit[i];
+                               k++;
+                               if (k > 31)
+                                       break;
+                       }
+                       uid_byte[0] = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5)
+                                       | (uid[3] << 4) | (uid[4] << 3) | (uid[5] << 2)
+                                       | (uid[6] << 1) | uid[7];
+                       uid_byte[1] = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5)
+                                       | (uid[11] << 4) | (uid[12] << 3) | (uid[13] << 2)
+                                       | (uid[14] << 1) | uid[15];
+                       uid_byte[2] = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5)
+                                       | (uid[19] << 4) | (uid[20] << 3) | (uid[21] << 2)
+                                       | (uid[22] << 1) | uid[23];
+                       uid_byte[3] = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5)
+                                       | (uid[27] << 4) | (uid[28] << 3) | (uid[29] << 2)
+                                       | (uid[30] << 1) | uid[31];
+                       //Dbhexdump(10, rx, rxlen);
+                       STATE = 1;
+                       txlen = 45;
+                       crc = CRC_PRESET;
+                       calc_crc(&crc, 0x00, 5);
+                       calc_crc(&crc, uid_byte[0], 8);
+                       calc_crc(&crc, uid_byte[1], 8);
+                       calc_crc(&crc, uid_byte[2], 8);
+                       calc_crc(&crc, uid_byte[3], 8);
+                       for (i = 0; i < 100; i++) {
+                               response_bit[i] = 0;
+                       }
+                       for (i = 0; i < 5; i++) {
+                               response_bit[i] = 0;
+                       }
+                       for (i = 5; i < 37; i++) {
+                               response_bit[i] = uid[i - 5];
+                       }
+                       for (j = 0; j < 8; j++) {
+                               response_bit[i] = 0;
+                               if ((crc & ((mask << 7) >> j)) != 0)
+                                       response_bit[i] = 1;
+                               i++;
+                       }
+                       k = 0;
+                       for (i = 0; i < 6; i++) {
+                               tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6)
+                                               | (response_bit[k + 2] << 5)
+                                               | (response_bit[k + 3] << 4)
+                                               | (response_bit[k + 4] << 3)
+                                               | (response_bit[k + 5] << 2)
+                                               | (response_bit[k + 6] << 1) | response_bit[k + 7];
+                               k += 8;
+                       }
+
+               } else if (STATE == 1 && rxlen == 44) {
+                       //received configuration
+                       STATE = 2;
+                       z = 0;
+                       for (i = 0; i < 6; i++) {
+                               for (j = 0; j < 8; j++) {
+                                       response_bit[z] = 0;
+                                       if ((rx[i] & ((mask << 7) >> j)) != 0)
+                                               response_bit[z] = 1;
+                                       z++;
+                               }
+                       }
+                       txlen = 64;
+
+                       if (u1 >= (sizeof(unlocker) / sizeof(unlocker[0])))
+                               bStop = !false;
+                       for (i = 0; i < 8; i++)
+                               tx[i] = unlocker[u1][i];
+                       u1++;
+
+               } else if (STATE == 2 && rxlen >= 44) {
+                       STATE = 0;
+               }
+
+               // Send and store the reader command
+               // Disable timer 1 with external trigger to avoid triggers during our own modulation
+               AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+
+               // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting,
+               // Since the clock counts since the last falling edge, a 'one' means that the
+               // falling edge occured halfway the period. with respect to this falling edge,
+               // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'.
+               // All timer values are in terms of T0 units
+
+               while (AT91C_BASE_TC0->TC_CV
+                               < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit)))
+                       ;
+
+               // Transmit the reader frame
+               hitag_reader_send_frame(tx, txlen);
+
+               // Enable and reset external trigger in timer for capturing future frames
+               AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
+
+               // Add transmitted frame to total count
+               if (txlen > 0) {
+                       frame_count++;
+                       if (!bQuiet) {
+                               // Store the frame in the trace
+                               if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) {
+                                       if (bQuitTraceFull) {
+                                               DbpString("Trace full");
+                                               break;
+                                       } else {
+                                               bQuiet = true;
+                                       }
+                               }
+                       }
+               }
+
+               // Reset values for receiving frames
+               memset(rx, 0x00, sizeof(rx));
+               rxlen = 0;
+               lastbit = 1;
+               bSkip = true;
+               tag_sof = reset_sof;
+               response = 0;
+
+               // Receive frame, watch for at most T0*EOF periods
+               while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) {
+                       // Check if falling edge in tag modulation is detected
+                       if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
+                               // Retrieve the new timing values
+                               int ra = (AT91C_BASE_TC1->TC_RA / T0);
+
+                               // Reset timer every frame, we have to capture the last edge for timing
+                               AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
+
+                               LED_B_ON();
+
+                               // Capture tag frame (manchester decoding using only falling edges)
+                               if (ra >= HITAG_T_EOF) {
+                                       if (rxlen != 0) {
+                                               //DbpString("wierd1?");
+                                       }
+                                       // Capture the T0 periods that have passed since last communication or field drop (reset)
+                                       // We always recieve a 'one' first, which has the falling edge after a half period |-_|
+                                       response = ra - HITAG_T_TAG_HALF_PERIOD;
+                               } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
+                                       // Manchester coding example |-_|_-|-_| (101)
+                                       rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+                                       rxlen++;
+                                       rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+                                       rxlen++;
+                               } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
+                                       // Manchester coding example |_-|...|_-|-_| (0...01)
+                                       rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
+                                       rxlen++;
+                                       // We have to skip this half period at start and add the 'one' the second time
+                                       if (!bSkip) {
+                                               rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
+                                               rxlen++;
+                                       }
+                                       lastbit = !lastbit;
+                                       bSkip = !bSkip;
+                               } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
+                                       // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
+                                       if (tag_sof) {
+                                               // Ignore bits that are transmitted during SOF
+                                               tag_sof--;
+                                       } else {
+                                               // bit is same as last bit
+                                               rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8));
+                                               rxlen++;
+                                       }
+                               } else {
+                                       // Ignore wierd value, is to small to mean anything
+                               }
+                       }
+
+                       // We can break this loop if we received the last bit from a frame
+                       if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) {
+                               if (rxlen > 0)
+                                       break;
+                       }
+               }
+       }
+       LED_B_OFF();
+       LED_D_OFF();
+       AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
+       AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0);
+}
+
+
+
index 27574dad2601cceda2f59b785445a1915a958892..70dc54f17a39495cb8e374807015c3f2ce53aa63 100644 (file)
 #include "util.h"
 #include "string.h"
 #include "cmd.h"
-
 #include "iso14443crc.h"
 #include "iso14443a.h"
 #include "crapto1.h"
 #include "mifareutil.h"
 #include "BigBuf.h"
+#include "protocols.h"
+
 static uint32_t iso14a_timeout;
 int rsamples = 0;
 uint8_t trigger = 0;
@@ -2307,20 +2308,34 @@ void ReaderMifare(bool first_try)
        set_tracing(FALSE);
 }
 
+typedef struct {
+  uint32_t cuid;
+  uint8_t  sector;
+  uint8_t  keytype;
+  uint32_t nonce;
+  uint32_t ar;
+  uint32_t nr;
+  uint32_t nonce2;
+  uint32_t ar2;
+  uint32_t nr2;
+} nonces_t;
+
 /**
   *MIFARE 1K simulate.
   *
   *@param flags :
   *    FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK
-  * 4B_FLAG_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
-  * 7B_FLAG_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
+  * FLAG_4B_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that
+  * FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that
+  * FLAG_10B_UID_IN_DATA       - use 10-byte UID in the data-section not finished
   *    FLAG_NR_AR_ATTACK  - means we should collect NR_AR responses for bruteforcing later
-  *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is inifite
+  *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ...
+  * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted)
   */
 void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain)
 {
        int cardSTATE = MFEMUL_NOFIELD;
-       int _7BUID = 0;
+       int _UID_LEN = 0; // 4, 7, 10
        int vHf = 0;    // in mV
        int res;
        uint32_t selTimer = 0;
@@ -2344,20 +2359,32 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
        uint8_t response[MAX_MIFARE_FRAME_SIZE];
        uint8_t response_par[MAX_MIFARE_PARITY_SIZE];
        
-       uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
+       uint8_t rATQA[]    = {0x04, 0x00}; // Mifare classic 1k 4BUID
        uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
        uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // !!!
-       uint8_t rSAK[] = {0x08, 0xb6, 0xdd};
-       uint8_t rSAK1[] = {0x04, 0xda, 0x17};
+       uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
+
+       uint8_t rSAKfinal[]= {0x08, 0xb6, 0xdd};      // mifare 1k indicated
+       uint8_t rSAK1[]    = {0x04, 0xda, 0x17};      // indicate UID not finished
 
        uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04};
        uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
                
-       //Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2
-       // This can be used in a reader-only attack.
-       // (it can also be retrieved via 'hf 14a list', but hey...
-       uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0};
-       uint8_t ar_nr_collected = 0;
+       //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2
+       // This will be used in the reader-only attack.
+
+       //allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys
+       #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack()
+       nonces_t ar_nr_resp[ATTACK_KEY_COUNT*2]; //*2 for 2 separate attack types (nml, moebius)
+       memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp));
+
+       uint8_t ar_nr_collected[ATTACK_KEY_COUNT*2]; //*2 for 2nd attack type (moebius)
+       memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected));
+       uint8_t nonce1_count = 0;
+       uint8_t nonce2_count = 0;
+       uint8_t moebius_n_count = 0;
+       bool gettingMoebius = false;
+       uint8_t mM = 0; //moebius_modifier for collection storage
 
        // Authenticate response - nonce
        uint32_t nonce = bytes_to_num(rAUTH_NT, 4);
@@ -2370,45 +2397,96 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                // 4B uid comes from data-portion of packet
                memcpy(rUIDBCC1,datain,4);
                rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
-
+               _UID_LEN = 4;
        } else if (flags & FLAG_7B_UID_IN_DATA) {
                // 7B uid comes from data-portion of packet
                memcpy(&rUIDBCC1[1],datain,3);
                memcpy(rUIDBCC2, datain+3, 4);
-               _7BUID = true;
+               _UID_LEN = 7;
+       } else if (flags & FLAG_10B_UID_IN_DATA) {
+               memcpy(&rUIDBCC1[1], datain,   3);
+               memcpy(&rUIDBCC2[1], datain+3, 3);
+               memcpy( rUIDBCC3,    datain+6, 4);
+               _UID_LEN = 10;
        } else {
-               // get UID from emul memory
+               // get UID from emul memory - guess at length
                emlGetMemBt(receivedCmd, 7, 1);
-               _7BUID = !(receivedCmd[0] == 0x00);
-               if (!_7BUID) {                     // ---------- 4BUID
+               if (receivedCmd[0] == 0x00) {      // ---------- 4BUID
                        emlGetMemBt(rUIDBCC1, 0, 4);
+                       _UID_LEN = 4;
                } else {                           // ---------- 7BUID
                        emlGetMemBt(&rUIDBCC1[1], 0, 3);
                        emlGetMemBt(rUIDBCC2, 3, 4);
+                       _UID_LEN = 7;
                }
        }
 
-       /*
-        * Regardless of what method was used to set the UID, set fifth byte and modify
-        * the ATQA for 4 or 7-byte UID
-        */
-       rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
-       if (_7BUID) {
-               rATQA[0] = 0x44;
-               rUIDBCC1[0] = 0x88;
-               rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
-               rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
-       }
-
-       if (MF_DBGLEVEL >= 1)   {
-               if (!_7BUID) {
-                       Dbprintf("4B UID: %02x%02x%02x%02x", 
-                               rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]);
-               } else {
-                       Dbprintf("7B UID: (%02x)%02x%02x%02x%02x%02x%02x%02x",
-                               rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3],
-                               rUIDBCC2[0], rUIDBCC2[1] ,rUIDBCC2[2], rUIDBCC2[3]);
-               }
+       switch (_UID_LEN) {
+               case 4:
+                       // save CUID
+                       cuid = bytes_to_num(rUIDBCC1, 4);
+                       // BCC
+                       rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
+                       if (MF_DBGLEVEL >= 2)   {
+                               Dbprintf("4B UID: %02x%02x%02x%02x", 
+                                       rUIDBCC1[0],
+                                       rUIDBCC1[1],
+                                       rUIDBCC1[2],
+                                       rUIDBCC1[3]
+                               );
+                       }
+                       break;
+               case 7:
+                       rATQA[0] |= 0x40;
+                       // save CUID
+                       cuid = bytes_to_num(rUIDBCC2, 4);
+                        // CascadeTag, CT
+                       rUIDBCC1[0] = 0x88;
+                       // BCC
+                       rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; 
+                       rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; 
+                       if (MF_DBGLEVEL >= 2)   {
+                               Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x",
+                                       rUIDBCC1[1],
+                                       rUIDBCC1[2],
+                                       rUIDBCC1[3],
+                                       rUIDBCC2[0],
+                                       rUIDBCC2[1],
+                                       rUIDBCC2[2],
+                                       rUIDBCC2[3]
+                               );
+                       }
+                       break;
+               case 10:
+                       rATQA[0] |= 0x80;
+                       //sak_10[0] &= 0xFB;                                    
+                       // save CUID
+                       cuid = bytes_to_num(rUIDBCC3, 4);
+                        // CascadeTag, CT
+                       rUIDBCC1[0] = 0x88;
+                       rUIDBCC2[0] = 0x88;
+                       // BCC
+                       rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
+                       rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
+                       rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3];
+
+                       if (MF_DBGLEVEL >= 2)   {
+                               Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x",
+                                       rUIDBCC1[1],
+                                       rUIDBCC1[2],
+                                       rUIDBCC1[3],
+                                       rUIDBCC2[1],
+                                       rUIDBCC2[2],
+                                       rUIDBCC2[3],
+                                       rUIDBCC3[0],
+                                       rUIDBCC3[1],
+                                       rUIDBCC3[2],
+                                       rUIDBCC3[3]
+                               );
+                       }
+                       break;
+               default: 
+                       break;
        }
 
        // We need to listen to the high-frequency, peak-detected path.
@@ -2421,9 +2499,9 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
        clear_trace();
        set_tracing(TRUE);
 
-
        bool finished = FALSE;
-       while (!BUTTON_PRESS() && !finished) {
+       bool button_pushed = BUTTON_PRESS();
+       while (!button_pushed && !finished && !usb_poll_validate_length()) {
                WDT_HIT();
 
                // find reader field
@@ -2433,11 +2511,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                cardSTATE_TO_IDLE();
                                LED_A_ON();
                        }
-               } 
-               if(cardSTATE == MFEMUL_NOFIELD) continue;
+               }
+               if (cardSTATE == MFEMUL_NOFIELD) continue;
 
                //Now, get data
-
                res = EmGetCmd(receivedCmd, &len, receivedCmd_par);
                if (res == 2) { //Field is off!
                        cardSTATE = MFEMUL_NOFIELD;
@@ -2446,11 +2523,11 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                } else if (res == 1) {
                        break;  //return value 1 means button press
                }
-                       
+
                // REQ or WUP request in ANY state and WUP in HALTED state
-               if (len == 1 && ((receivedCmd[0] == 0x26 && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == 0x52)) {
+               if (len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) {
                        selTimer = GetTickCount();
-                       EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == 0x52));
+                       EmSendCmdEx(rATQA, sizeof(rATQA), (receivedCmd[0] == ISO14443A_CMD_WUPA));
                        cardSTATE = MFEMUL_SELECT1;
 
                        // init crypto block
@@ -2469,59 +2546,137 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                break;
                        }
                        case MFEMUL_SELECT1:{
-                               // select all
-                               if (len == 2 && (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x20)) {
+                               // select all - 0x93 0x20
+                               if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) {
                                        if (MF_DBGLEVEL >= 4)   Dbprintf("SELECT ALL received");
                                        EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
                                        break;
                                }
 
-                               if (MF_DBGLEVEL >= 4 && len == 9 && receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 )
-                               {
-                                       Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
+                               // select card - 0x93 0x70 ...
+                               if (len == 9 &&
+                                               (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
+                                       if (MF_DBGLEVEL >= 4) 
+                                               Dbprintf("SELECT %02x%02x%02x%02x received",receivedCmd[2],receivedCmd[3],receivedCmd[4],receivedCmd[5]);
+                                       
+                                       switch(_UID_LEN) {
+                                               case 4:
+                                                       cardSTATE = MFEMUL_WORK;
+                                                       LED_B_ON();
+                                                       if (MF_DBGLEVEL >= 4)   Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
+                                                       EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
+                                                       break;
+                                               case 7:
+                                                       cardSTATE       = MFEMUL_SELECT2;
+                                                       EmSendCmd(rSAK1, sizeof(rSAK1));
+                                                       break;
+                                               case 10:
+                                                       cardSTATE       = MFEMUL_SELECT2;
+                                                       EmSendCmd(rSAK1, sizeof(rSAK1));
+                                                       break;
+                                               default:break;
+                                       }
+                               } else {
+                                       cardSTATE_TO_IDLE();
+                               }
+                               break;
+                       }
+                       case MFEMUL_SELECT3:{
+                               if (!len) { 
+                                       LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
+                                       break;
                                }
-                               // select card
+                               // select all cl3 - 0x97 0x20
+                               if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) {
+                                       EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3));
+                                       break;
+                               }
+                               // select card cl3 - 0x97 0x70
                                if (len == 9 && 
-                                               (receivedCmd[0] == 0x93 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
-                                       EmSendCmd(_7BUID?rSAK1:rSAK, _7BUID?sizeof(rSAK1):sizeof(rSAK));
-                                       cuid = bytes_to_num(rUIDBCC1, 4);
-                                       if (!_7BUID) {
-                                               cardSTATE = MFEMUL_WORK;
-                                               LED_B_ON();
-                                               if (MF_DBGLEVEL >= 4)   Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
-                                               break;
-                                       } else {
-                                               cardSTATE = MFEMUL_SELECT2;
-                                       }
+                                               (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 &&
+                                                receivedCmd[1] == 0x70 && 
+                                                memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) {
+
+                                       EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
+                                       cardSTATE = MFEMUL_WORK;
+                                       LED_B_ON();
+                                       if (MF_DBGLEVEL >= 4)   Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer);
+                                       break;
                                }
+                               cardSTATE_TO_IDLE();
                                break;
                        }
                        case MFEMUL_AUTH1:{
-                               if( len != 8)
-                               {
+                               if( len != 8) {
                                        cardSTATE_TO_IDLE();
                                        LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
                                        break;
                                }
 
-                               uint32_t ar = bytes_to_num(receivedCmd, 4);
-                               uint32_t nr = bytes_to_num(&receivedCmd[4], 4);
-
-                               //Collect AR/NR
-                               if(ar_nr_collected < 2){
-                                       if(ar_nr_responses[2] != ar)
-                                       {// Avoid duplicates... probably not necessary, ar should vary. 
-                                               ar_nr_responses[ar_nr_collected*4] = cuid;
-                                               ar_nr_responses[ar_nr_collected*4+1] = nonce;
-                                               ar_nr_responses[ar_nr_collected*4+2] = ar;
-                                               ar_nr_responses[ar_nr_collected*4+3] = nr;
-                                               ar_nr_collected++;
+                               uint32_t nr = bytes_to_num(receivedCmd, 4);
+                               uint32_t ar = bytes_to_num(&receivedCmd[4], 4);
+       
+                               // Collect AR/NR per keytype & sector
+                               if(flags & FLAG_NR_AR_ATTACK) {
+                                       for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
+                                               if ( ar_nr_collected[i+mM]==0 || ((cardAUTHSC == ar_nr_resp[i+mM].sector) && (cardAUTHKEY == ar_nr_resp[i+mM].keytype) && (ar_nr_collected[i+mM] > 0)) ) {
+                                                       // if first auth for sector, or matches sector and keytype of previous auth
+                                                       if (ar_nr_collected[i+mM] < 2) {
+                                                               // if we haven't already collected 2 nonces for this sector
+                                                               if (ar_nr_resp[ar_nr_collected[i+mM]].ar != ar) {
+                                                                       // Avoid duplicates... probably not necessary, ar should vary. 
+                                                                       if (ar_nr_collected[i+mM]==0) {
+                                                                               // first nonce collect
+                                                                               ar_nr_resp[i+mM].cuid = cuid;
+                                                                               ar_nr_resp[i+mM].sector = cardAUTHSC;
+                                                                               ar_nr_resp[i+mM].keytype = cardAUTHKEY;
+                                                                               ar_nr_resp[i+mM].nonce = nonce;
+                                                                               ar_nr_resp[i+mM].nr = nr;
+                                                                               ar_nr_resp[i+mM].ar = ar;
+                                                                               nonce1_count++;
+                                                                               // add this nonce to first moebius nonce
+                                                                               ar_nr_resp[i+ATTACK_KEY_COUNT].cuid = cuid;
+                                                                               ar_nr_resp[i+ATTACK_KEY_COUNT].sector = cardAUTHSC;
+                                                                               ar_nr_resp[i+ATTACK_KEY_COUNT].keytype = cardAUTHKEY;
+                                                                               ar_nr_resp[i+ATTACK_KEY_COUNT].nonce = nonce;
+                                                                               ar_nr_resp[i+ATTACK_KEY_COUNT].nr = nr;
+                                                                               ar_nr_resp[i+ATTACK_KEY_COUNT].ar = ar;
+                                                                               ar_nr_collected[i+ATTACK_KEY_COUNT]++;
+                                                                       } else { // second nonce collect (std and moebius)
+                                                                               ar_nr_resp[i+mM].nonce2 = nonce;
+                                                                               ar_nr_resp[i+mM].nr2 = nr;
+                                                                               ar_nr_resp[i+mM].ar2 = ar;
+                                                                               if (!gettingMoebius) {
+                                                                                       nonce2_count++;
+                                                                                       // check if this was the last second nonce we need for std attack
+                                                                                       if ( nonce2_count == nonce1_count ) {
+                                                                                               // done collecting std test switch to moebius
+                                                                                               // first finish incrementing last sample
+                                                                                               ar_nr_collected[i+mM]++; 
+                                                                                               // switch to moebius collection
+                                                                                               gettingMoebius = true;
+                                                                                               mM = ATTACK_KEY_COUNT;
+                                                                                               nonce = nonce*7;
+                                                                                               break;
+                                                                                       }
+                                                                               } else {
+                                                                                       moebius_n_count++;
+                                                                                       // if we've collected all the nonces we need - finish.
+                                                                                       if (nonce1_count == moebius_n_count) finished = true;
+                                                                               }
+                                                                       }
+                                                                       ar_nr_collected[i+mM]++;
+                                                               }
+                                                       }
+                                                       // we found right spot for this nonce stop looking
+                                                       break;
+                                               }
                                        }
                                }
 
                                // --- crypto
-                               crypto1_word(pcs, ar , 1);
-                               cardRr = nr ^ crypto1_word(pcs, 0, 0);
+                               crypto1_word(pcs, nr , 1);
+                               cardRr = ar ^ crypto1_word(pcs, 0, 0);
 
                                // test if auth OK
                                if (cardRr != prng_successor(nonce, 64)){
@@ -2537,6 +2692,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                        break;
                                }
 
+                               //auth successful
                                ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
 
                                num_to_bytes(ans, 4, rAUTH_AT);
@@ -2553,20 +2709,29 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                if (!len) { 
                                        LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
                                        break;
-                               }
-                               if (len == 2 && (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x20)) {
+                               }       
+                               // select all cl2 - 0x95 0x20
+                               if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) {
                                        EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2));
                                        break;
                                }
 
-                               // select 2 card
+                               // select cl2 card - 0x95 0x70 xxxxxxxxxxxx
                                if (len == 9 && 
-                                               (receivedCmd[0] == 0x95 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
-                                       EmSendCmd(rSAK, sizeof(rSAK));
-                                       cuid = bytes_to_num(rUIDBCC2, 4);
-                                       cardSTATE = MFEMUL_WORK;
-                                       LED_B_ON();
-                                       if (MF_DBGLEVEL >= 4)   Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
+                                               (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
+                                       switch(_UID_LEN) {
+                                               case 7:
+                                                       EmSendCmd(rSAKfinal, sizeof(rSAKfinal));
+                                                       cardSTATE = MFEMUL_WORK;
+                                                       LED_B_ON();
+                                                       if (MF_DBGLEVEL >= 4)   Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
+                                                       break;
+                                               case 10:
+                                                       EmSendCmd(rSAK1, sizeof(rSAK1));
+                                                       cardSTATE = MFEMUL_SELECT3;
+                                                       break;
+                                               default:break;
+                                       }
                                        break;
                                }
                                
@@ -2594,11 +2759,22 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                }
                                
                                if (len == 4 && (receivedCmd[0] == 0x60 || receivedCmd[0] == 0x61)) {
+
+                                       // if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack
+                                       if (receivedCmd[1] >= 16 * 4 && !(flags & FLAG_NR_AR_ATTACK)) {
+                                               //is this the correct response to an auth on a out of range block? marshmellow
+                                               EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
+                                               if (MF_DBGLEVEL >= 2) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]);
+                                               break;
+                                       }
+
                                        authTimer = GetTickCount();
                                        cardAUTHSC = receivedCmd[1] / 4;  // received block num
                                        cardAUTHKEY = receivedCmd[0] - 0x60;
                                        crypto1_destroy(pcs);//Added by martin
                                        crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
+                                       //uint64_t key=emlGetKey(cardAUTHSC, cardAUTHKEY);
+                                       //Dbprintf("key: %04x%08x",(uint32_t)(key>>32)&0xFFFF,(uint32_t)(key&0xFFFFFFFF));
 
                                        if (!encrypted_data) { // first authentication
                                                if (MF_DBGLEVEL >= 4) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d",receivedCmd[1] ,receivedCmd[1],cardAUTHKEY  );
@@ -2775,45 +2951,48 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *
                                break;
                        }
                }
+               button_pushed = BUTTON_PRESS();
        }
 
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
        LEDsoff();
 
-       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);
-       }
-
-       if(flags & FLAG_NR_AR_ATTACK)
-       {
-               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
-                                       ar_nr_responses[1], //NT
-                                       ar_nr_responses[2], //AR1
-                                       ar_nr_responses[3], //NR1
-                                       ar_nr_responses[6], //AR2
-                                       ar_nr_responses[7] //NR2
-                                       );
-               } else {
-                       Dbprintf("Failed to obtain two AR/NR pairs!");
-                       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
-                                               ar_nr_responses[2], //AR1
-                                               ar_nr_responses[3] //NR1
+       if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) {
+               for ( uint8_t   i = 0; i < ATTACK_KEY_COUNT; i++) {
+                       if (ar_nr_collected[i] == 2) {
+                               Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
+                               Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
+                                               ar_nr_resp[i].cuid,  //UID
+                                               ar_nr_resp[i].nonce, //NT
+                                               ar_nr_resp[i].nr,    //NR1
+                                               ar_nr_resp[i].ar,    //AR1
+                                               ar_nr_resp[i].nr2,   //NR2
+                                               ar_nr_resp[i].ar2    //AR2
+                                               );
+                       }
+               }       
+               for ( uint8_t   i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT*2; i++) {
+                       if (ar_nr_collected[i] == 2) {
+                               Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i<ATTACK_KEY_COUNT/2) ? "keyA" : "keyB", ar_nr_resp[i].sector);
+                               Dbprintf("../tools/mfkey/mfkey32v2 %08x %08x %08x %08x %08x %08x %08x",
+                                               ar_nr_resp[i].cuid,  //UID
+                                               ar_nr_resp[i].nonce, //NT
+                                               ar_nr_resp[i].nr,    //NR1
+                                               ar_nr_resp[i].ar,    //AR1
+                                               ar_nr_resp[i].nonce2,//NT2
+                                               ar_nr_resp[i].nr2,   //NR2
+                                               ar_nr_resp[i].ar2    //AR2
                                                );
                        }
                }
        }
        if (MF_DBGLEVEL >= 1)   Dbprintf("Emulator stopped. Tracing: %d  trace length: %d ",    tracing, BigBuf_get_traceLen());
-       
-}
 
+       if(flags & FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK
+               //Send the collected ar_nr in the response
+               cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,button_pushed,0,&ar_nr_resp,sizeof(ar_nr_resp));
+       }
+}
 
 
 //-----------------------------------------------------------------------------
index 82e5dd6a1c1bba44a33814b62b06be2d1e047093..22227e74bec96651d5c2620dd37f4bea210f27d2 100644 (file)
@@ -547,15 +547,20 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
        }
  */
 // Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq)))
+
+       //note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
 #define CHECK_FOR_SUBCARRIER() { \
+               v = MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2); \
+       }
+               /*
                if(ci < 0) { \
-                       if(cq < 0) { /* ci < 0, cq < 0 */ \
+                       if(cq < 0) { \ // ci < 0, cq < 0
                                if (cq < ci) { \
                                        v = -cq - (ci >> 1); \
                                } else { \
                                        v = -ci - (cq >> 1); \
                                } \
-                       } else {        /* ci < 0, cq >= 0 */ \
+                       } else {        \ // ci < 0, cq >= 0
                                if (cq < -ci) { \
                                        v = -ci + (cq >> 1); \
                                } else { \
@@ -563,13 +568,13 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
                                } \
                        } \
                } else { \
-                       if(cq < 0) { /* ci >= 0, cq < 0 */ \
+                       if(cq < 0) { \ // ci >= 0, cq < 0
                                if (-cq < ci) { \
                                        v = ci - (cq >> 1); \
                                } else { \
                                        v = -cq + (ci >> 1); \
                                } \
-                       } else {        /* ci >= 0, cq >= 0 */ \
+                       } else {        \ // ci >= 0, cq >= 0
                                if (cq < ci) { \
                                        v = ci + (cq >> 1); \
                                } else { \
@@ -578,6 +583,7 @@ static RAMFUNC int Handle14443bSamplesDemod(int ci, int cq)
                        } \
                } \
        }
+               */
 
        switch(Demod.state) {
                case DEMOD_UNSYNCD:
index e7145c5c9e84b3d6dd5399c145e74123e72be077..9a6ef9f01220a5d52fe441b7e16ae82e70affcb7 100644 (file)
@@ -319,18 +319,7 @@ static int GetIso15693AnswerFromTag(uint8_t *receivedResponse, int maxLen, int *
                        // every other is Q. We just want power, so abs(I) + abs(Q) is
                        // close to what we want.
                        if(getNext) {
-                               int8_t r;
-
-                               if(b < 0) {
-                                       r = -b;
-                               } else {
-                                       r = b;
-                               }
-                               if(prev < 0) {
-                                       r -= prev;
-                               } else {
-                                       r += prev;
-                               }
+                               int8_t r = ABS(b) + ABS(prev);
 
                                dest[c++] = (uint8_t)r;
 
@@ -468,18 +457,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *receivedResponse, int maxLen, int
                        // every other is Q. We just want power, so abs(I) + abs(Q) is
                        // close to what we want.
                        if(getNext) {
-                               int8_t r;
-
-                               if(b < 0) {
-                                       r = -b;
-                               } else {
-                                       r = b;
-                               }
-                               if(prev < 0) {
-                                       r -= prev;
-                               } else {
-                                       r += prev;
-                               }
+                               int8_t r = ABS(b) + ABS(prev);
 
                                dest[c++] = (uint8_t)r;
 
@@ -648,18 +626,7 @@ void AcquireRawAdcSamplesIso15693(void)
                        // every other is Q. We just want power, so abs(I) + abs(Q) is
                        // close to what we want.
                        if(getNext) {
-                               int8_t r;
-
-                               if(b < 0) {
-                                       r = -b;
-                               } else {
-                                       r = b;
-                               }
-                               if(prev < 0) {
-                                       r -= prev;
-                               } else {
-                                       r += prev;
-                               }
+                               int8_t r = ABS(b) + ABS(prev);
 
                                dest[c++] = (uint8_t)r;
 
@@ -713,18 +680,7 @@ void RecordRawAdcSamplesIso15693(void)
                        // every other is Q. We just want power, so abs(I) + abs(Q) is
                        // close to what we want.
                        if(getNext) {
-                               int8_t r;
-
-                               if(b < 0) {
-                                       r = -b;
-                               } else {
-                                       r = b;
-                               }
-                               if(prev < 0) {
-                                       r -= prev;
-                               } else {
-                                       r += prev;
-                               }
+                               int8_t r = ABS(b) + ABS(prev);
 
                                dest[c++] = (uint8_t)r;
 
index 074a0f7896333bc5ece3020bb63aaa989029eecc..27dcc29733ef40d2e30bedbcde01a9dcf97a2abe 100644 (file)
@@ -391,7 +391,7 @@ int legic_write_byte(int byte, int addr, int addr_sz) {
     uint32_t cmd_sz = addr_sz+1+8+4;          //crc+data+cmd
 
     legic_prng_forward(2); /* we wait anyways */
-    while(timer->TC_CV < 387) ; /* ~ 258us */
+    while(timer->TC_CV < 387) {}; /* ~ 258us */
        frame_send_rwd(cmd, cmd_sz);
 
        //== wait for ack ====================================
@@ -418,7 +418,7 @@ int legic_write_byte(int byte, int addr, int addr_sz) {
         }
     }
     timer->TC_CCR = AT91C_TC_SWTRG;
-    while(timer->TC_CV > 1) ; /* Wait till the clock has reset */
+    while(timer->TC_CV > 1) {}; /* Wait till the clock has reset */
        return -1;
 }
 
index 47fec7c2a95d3b6737361b401e56fb0e2297847e..2079f263d5396007d3b4f37b048ff3a15e78ddf5 100644 (file)
@@ -37,6 +37,8 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint
 
        sample_config sc = { 0,0,1, divisor_used, 0};
        setSamplingConfig(&sc);
+       //clear read buffer
+       BigBuf_Clear_keep_EM();
 
        /* Make sure the tag is reset */
        FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
@@ -377,7 +379,7 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc)
        AcquireTiType();
 
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-       DbpString("Now use tiread to check");
+       DbpString("Now use `lf ti read` to check");
 }
 
 void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
@@ -640,6 +642,19 @@ static void biphaseSimBit(uint8_t c, int *n, uint8_t clock, uint8_t *phase)
                memset(dest+(*n), c ^ *phase, clock);
                *phase ^= 1;
        }
+       *n += clock;
+}
+
+static void stAskSimBit(int *n, uint8_t clock) {
+       uint8_t *dest = BigBuf_get_addr();
+       uint8_t halfClk = clock/2;
+       //ST = .5 high .5 low 1.5 high .5 low 1 high    
+       memset(dest+(*n), 1, halfClk);
+       memset(dest+(*n) + halfClk, 0, halfClk);
+       memset(dest+(*n) + clock, 1, clock + halfClk);
+       memset(dest+(*n) + clock*2 + halfClk, 0, halfClk);
+       memset(dest+(*n) + clock*3, 1, clock);
+       *n += clock*4;
 }
 
 // args clock, ask/man or askraw, invert, transmission separator
@@ -657,7 +672,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
                for (i=0; i<size; i++){
                        biphaseSimBit(BitStream[i]^invert, &n, clk, &phase);
                }
-               if (BitStream[0]==BitStream[size-1]){ //run a second set inverted to keep phase in check
+               if (phase==1) { //run a second set inverted to keep phase in check
                        for (i=0; i<size; i++){
                                biphaseSimBit(BitStream[i]^invert, &n, clk, &phase);
                        }
@@ -672,8 +687,10 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
                        }
                }
        }
-       
-       if (separator==1) Dbprintf("sorry but separator option not yet available"); 
+       if (separator==1 && encoding == 1)
+               stAskSimBit(&n, clk);
+       else if (separator==1)
+               Dbprintf("sorry but separator option not yet available");
 
        Dbprintf("Simulating with clk: %d, invert: %d, encoding: %d, separator: %d, n: %d",clk, invert, encoding, separator, n);
        //DEBUG
@@ -683,7 +700,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream)
        //Dbprintf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", dest[i],dest[i+1],dest[i+2],dest[i+3],dest[i+4],dest[i+5],dest[i+6],dest[i+7],dest[i+8],dest[i+9],dest[i+10],dest[i+11],dest[i+12],dest[i+13],dest[i+14],dest[i+15]);
        //i+=16;
        //Dbprintf("%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d%d", dest[i],dest[i+1],dest[i+2],dest[i+3],dest[i+4],dest[i+5],dest[i+6],dest[i+7],dest[i+8],dest[i+9],dest[i+10],dest[i+11],dest[i+12],dest[i+13],dest[i+14],dest[i+15]);
-
+       
        if (ledcontrol) LED_A_ON();
        SimulateTagLowFrequency(n, 0, ledcontrol);
        if (ledcontrol) LED_A_OFF();
@@ -752,6 +769,9 @@ void CmdHIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
        // Configure to go in 125Khz listen mode
        LFSetupFPGAForADC(95, true);
 
+       //clear read buffer
+       BigBuf_Clear_keep_EM();
+
        while(!BUTTON_PRESS() && !usb_poll_validate_length()) {
 
                WDT_HIT();
@@ -837,6 +857,8 @@ void CmdAWIDdemodFSK(int findone, int *high, int *low, int ledcontrol)
        uint8_t *dest = BigBuf_get_addr();
        size_t size; 
        int idx=0;
+       //clear read buffer
+       BigBuf_Clear_keep_EM();
        // Configure to go in 125Khz listen mode
        LFSetupFPGAForADC(95, true);
 
@@ -927,6 +949,8 @@ void CmdEM410xdemod(int findone, int *high, int *low, int ledcontrol)
        int clk=0, invert=0, errCnt=0, maxErr=20;
        uint32_t hi=0;
        uint64_t lo=0;
+       //clear read buffer
+       BigBuf_Clear_keep_EM();
        // Configure to go in 125Khz listen mode
        LFSetupFPGAForADC(95, true);
 
@@ -986,6 +1010,8 @@ void CmdIOdemodFSK(int findone, int *high, int *low, int ledcontrol)
        uint8_t version=0;
        uint8_t facilitycode=0;
        uint16_t number=0;
+       //clear read buffer
+       BigBuf_Clear_keep_EM();
        // Configure to go in 125Khz listen mode
        LFSetupFPGAForADC(95, true);
 
@@ -1079,7 +1105,7 @@ void T55xxWriteBit(int bit) {
 void T55xxResetRead(void) {
        LED_A_ON();
        //clear buffer now so it does not interfere with timing later
-       BigBuf_Clear_ext(false);
+       BigBuf_Clear_keep_EM();
 
        // Set up FPGA, 125kHz
        LFSetupFPGAForADC(95, true);
@@ -1404,7 +1430,7 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) {
        LED_D_ON();
 
        // Write EM410x ID
-       uint32_t data[] = {0, id>>32, id & 0xFFFFFFFF};
+       uint32_t data[] = {0, (uint32_t)(id>>32), (uint32_t)(id & 0xFFFFFFFF)};
 
        clock = (card & 0xFF00) >> 8;
        clock = (clock == 0) ? 64 : clock;
index ab7c79dd3e31ab2b4867c2f1bb080eee0290eb4c..88df543f74022e4657b871e061c662c61c8a610d 100644 (file)
@@ -124,7 +124,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
        uint8_t *dest = BigBuf_get_addr();
     int bufsize = BigBuf_max_traceLen();
 
-       memset(dest, 0, bufsize);
+       //memset(dest, 0, bufsize); //creates issues with cmdread (marshmellow)
 
        if(bits_per_sample < 1) bits_per_sample = 1;
        if(bits_per_sample > 8) bits_per_sample = 8;
index 7a09ce64cdac33707a13abdef1de3294d778cd58..3d4dd40080fdaf74540074a82f49a41a86ecd47c 100644 (file)
@@ -42,14 +42,15 @@ extern int MF_DBGLEVEL;
 #define MFEMUL_IDLE         1\r
 #define MFEMUL_SELECT1      2\r
 #define MFEMUL_SELECT2      3\r
-#define MFEMUL_AUTH1        4\r
-#define MFEMUL_AUTH2        5\r
-#define MFEMUL_WORK            6\r
-#define MFEMUL_WRITEBL2     7\r
-#define MFEMUL_INTREG_INC   8\r
-#define MFEMUL_INTREG_DEC   9\r
-#define MFEMUL_INTREG_REST 10\r
-#define MFEMUL_HALTED      11\r
+#define MFEMUL_SELECT3      4\r
+#define MFEMUL_AUTH1        5\r
+#define MFEMUL_AUTH2        6\r
+#define MFEMUL_WORK            7\r
+#define MFEMUL_WRITEBL2     8\r
+#define MFEMUL_INTREG_INC   9\r
+#define MFEMUL_INTREG_DEC  10\r
+#define MFEMUL_INTREG_REST 11\r
+#define MFEMUL_HALTED      12\r
 \r
 #define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();\r
 \r
index 3093a5e50828a482d9efb1a60c3d85832d72436e..f9f33c5319fc8a01ad5c6da88f38817c9e2e8ade 100644 (file)
@@ -7,9 +7,6 @@
 #define T0_PCF 8 //period for the pcf7931 in us
 #define ALLOC 16
 
-#define abs(x) ( ((x)<0) ? -(x) : (x) )
-#define max(x,y) ( x<y ? y:x)
-
 int DemodPCF7931(uint8_t **outBlocks) {
 
     uint8_t bits[256] = {0x00};
@@ -29,6 +26,8 @@ int DemodPCF7931(uint8_t **outBlocks) {
        int num_blocks = 0;
        int lmin=128, lmax=128;
        uint8_t dir;
+       //clear read buffer
+       BigBuf_Clear_keep_EM();
 
        LFSetupFPGAForADC(95, true);
        DoAcquisition_default(0, true);
@@ -70,7 +69,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
 
                        // Switch depending on lc length:
                        // Tolerance is 1/8 of clock rate (arbitrary)
-                       if (abs(lc-clock/4) < tolerance) {
+                       if (ABS(lc-clock/4) < tolerance) {
                                // 16T0
                                if((i - pmc) == lc) { /* 16T0 was previous one */
                                        /* It's a PMC ! */
@@ -82,7 +81,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
                                else {
                                        pmc = i;
                                }
-                       } else if (abs(lc-clock/2) < tolerance) {
+                       } else if (ABS(lc-clock/2) < tolerance) {
                                // 32TO
                                if((i - pmc) == lc) { /* 16T0 was previous one */
                                        /* It's a PMC ! */
@@ -97,7 +96,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
                                }
                                else
                                        half_switch++;
-                       } else if (abs(lc-clock) < tolerance) {
+                       } else if (ABS(lc-clock) < tolerance) {
                                // 64TO
                 bits[bitidx++] = 1;
                        } else {
@@ -202,7 +201,7 @@ void ReadPCF7931() {
                                                Blocks[0][ALLOC] = 1;
                                                memcpy(Blocks[1], tmpBlocks[i+1], 16);
                                                Blocks[1][ALLOC] = 1;
-                                               max_blocks = max((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
+                                               max_blocks = MAX((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
                                                // Debug print
                                                Dbprintf("(dbg) Max blocks: %d", max_blocks);
                                                num_blocks = 2;
index c2c81a9da1594ce4bb1205ac0e89dae9f954b085..bbea07b53dedf72bd47501ff0639db4bcb80f02b 100644 (file)
@@ -203,7 +203,7 @@ static void flash_mode(int externally_entered)
        size_t rx_len;
 
   usb_enable();
-  for (volatile size_t i=0; i<0x100000; i++);
+  for (volatile size_t i=0; i<0x100000; i++) {};
 
        for(;;) {
                WDT_HIT();
index 5b604b11fd536d5613df2a74804c8b934cf797b3..8dd8ddef513ce3657e57bd228ef9e238139cc594 100644 (file)
@@ -37,6 +37,7 @@ else
     CXXFLAGS = $(shell pkg-config --cflags QtCore QtGui 2>/dev/null) -Wall -O4
     QTLDLIBS = $(shell pkg-config --libs QtCore QtGui 2>/dev/null)
     LUALIB +=  -ldl
+    LDLIBS +=  -ltermcap -lncurses
     MOC = $(shell pkg-config --variable=moc_location QtCore)
     # Below is a variant you can use if you have problems compiling with QT5 on ubuntu. see http://www.proxmark.org/forum/viewtopic.php?id=1661 for more info. 
     #MOC = /usr/lib/x86_64-linux-gnu/qt4/bin/moc
@@ -99,6 +100,8 @@ CMDSRCS =    nonce2key/crapto1.c\
                        cmdlft55xx.c \
                        cmdlfpcf7931.c\
                        cmdlfviking.c\
+                       cmdlfpresco.c\
+                       cmdlfpyramid.c\
                        pm3_binlib.c\
                        scripting.c\
                        cmdscript.c\
index 6dd96ab0289d21099359e1e0b49c63848457044d..86dac4233507089c67abdf43be8fc45e7fd97933 100644 (file)
@@ -8,23 +8,22 @@
 // Data and Graph commands
 //-----------------------------------------------------------------------------
 
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <limits.h>
-#include "proxmark3.h"
-#include "data.h"
-#include "ui.h"
-#include "graph.h"
-#include "cmdparser.h"
+#include <stdio.h>    // also included in util.h
+#include <string.h>   // also included in util.h
+#include <limits.h>   // for CmdNorm INT_MIN && INT_MAX
+#include "data.h"     // also included in util.h
+#include "cmddata.h"
 #include "util.h"
 #include "cmdmain.h"
-#include "cmddata.h"
-#include "lfdemod.h"
-#include "usb_cmd.h"
-#include "crc.h"
-#include "crc16.h"
-#include "loclass/cipherutils.h"
+#include "proxmark3.h"
+#include "ui.h"       // for show graph controls
+#include "graph.h"    // for graph data
+#include "cmdparser.h"// already included in cmdmain.h
+#include "usb_cmd.h"  // already included in cmdmain.h and proxmark3.h
+#include "lfdemod.h"  // for demod code
+#include "crc.h"      // for pyramid checksum maxim
+#include "crc16.h"    // for FDXB demod checksum
+#include "loclass/cipherutils.h" // for decimating samples in getsamples
 
 uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
 uint8_t g_debugMode=0;
@@ -277,7 +276,8 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo )
 
 int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose)
 {
-       if (!ASKDemod(Cmd, FALSE, FALSE, 1)) return 0;
+       bool st = TRUE;
+       if (!ASKDemod_ext(Cmd, FALSE, FALSE, 1, &st)) return 0;
        return AskEm410xDecode(verbose, hi, lo);
 }
 
@@ -312,8 +312,7 @@ int CmdAskEM410xDemod(const char *Cmd)
 //verbose will print results and demoding messages
 //emSearch will auto search for EM410x format in bitstream
 //askType switches decode: ask/raw = 0, ask/manchester = 1 
-int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
-{
+int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) {
        int invert=0;
        int clk=0;
        int maxErr=100;
@@ -334,15 +333,22 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
        if (amp == 'a' || amp == 'A') askAmp=1; 
        size_t BitLen = getFromGraphBuf(BitStream);
        if (g_debugMode) PrintAndLog("DEBUG: Bitlen from grphbuff: %d",BitLen);
-       if (BitLen<255) return 0;
-       if (maxLen<BitLen && maxLen != 0) BitLen = maxLen;
-
+       if (BitLen < 255) return 0;
+       if (maxLen < BitLen && maxLen != 0) BitLen = maxLen;
+       int foundclk = 0;
+       bool st = false;
+       if (*stCheck) st = DetectST(BitStream, &BitLen, &foundclk);
+       if (st) {
+               *stCheck = st;
+               clk = (clk == 0) ? foundclk : clk;
+               if (verbose || g_debugMode) PrintAndLog("\nFound Sequence Terminator");
+       }
        int errCnt = askdemod(BitStream, &BitLen, &clk, &invert, maxErr, askAmp, askType);
        if (errCnt<0 || BitLen<16){  //if fatal error (or -1)
                if (g_debugMode) PrintAndLog("DEBUG: no data found %d, errors:%d, bitlen:%d, clock:%d",errCnt,invert,BitLen,clk);
                return 0;
        }
-       if (errCnt>maxErr){
+       if (errCnt > maxErr){
                if (g_debugMode) PrintAndLog("DEBUG: Too many errors found, errors:%d, bits:%d, clock:%d",errCnt, BitLen, clk);
                return 0;
        }
@@ -365,6 +371,10 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType)
        }
        return 1;
 }
+int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) {
+       bool st = false;
+       return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st);
+}
 
 //by marshmellow
 //takes 5 arguments - clock, invert, maxErr, maxLen as integers and amplify as char == 'a'
@@ -374,7 +384,8 @@ int Cmdaskmandemod(const char *Cmd)
 {
        char cmdp = param_getchar(Cmd, 0);
        if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') {
-               PrintAndLog("Usage:  data rawdemod am [clock] <invert> [maxError] [maxLen] [amplify]");
+               PrintAndLog("Usage:  data rawdemod am <s> [clock] <invert> [maxError] [maxLen] [amplify]");
+               PrintAndLog("     ['s'] optional, check for Sequence Terminator");
                PrintAndLog("     [set clock as integer] optional, if not set, autodetect");
                PrintAndLog("     <invert>, 1 to invert output");
                PrintAndLog("     [set maximum allowed errors], default = 100");
@@ -388,7 +399,13 @@ int Cmdaskmandemod(const char *Cmd)
                PrintAndLog("          : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors");
                return 0;
        }
-       return ASKDemod(Cmd, TRUE, TRUE, 1);
+       bool st = TRUE;
+       if (Cmd[0]=='s') 
+               return ASKDemod_ext(Cmd++, TRUE, TRUE, 1, &st);
+       else if (Cmd[1] == 's')
+               return ASKDemod_ext(Cmd+=2, TRUE, TRUE, 1, &st);
+       else
+               return ASKDemod(Cmd, TRUE, TRUE, 1);
 }
 
 //by marshmellow
@@ -574,7 +591,7 @@ int Cmdaskbiphdemod(const char *Cmd)
 int CmdG_Prox_II_Demod(const char *Cmd)
 {
        if (!ASKbiphaseDemod(Cmd, FALSE)){
-               if (g_debugMode) PrintAndLog("ASKbiphaseDemod failed 1st try");
+               if (g_debugMode) PrintAndLog("Error gProxII: ASKbiphaseDemod failed 1st try");
                return 0;
        }
        size_t size = DemodBufferLen;
@@ -584,46 +601,32 @@ int CmdG_Prox_II_Demod(const char *Cmd)
                if (g_debugMode) PrintAndLog("Error gProxII_Demod");
                return 0;
        }
-       //got a good demod
-       uint32_t ByteStream[65] = {0x00};
+       //got a good demod of 96 bits
+       uint8_t ByteStream[8] = {0x00};
        uint8_t xorKey=0;
-       uint8_t keyCnt=0;
-       uint8_t bitCnt=0;
-       uint8_t ByteCnt=0;
-       size_t startIdx = ans + 6; //start after preamble
-       for (size_t idx = 0; idx<size-6; idx++){
-               if ((idx+1) % 5 == 0){
-                       //spacer bit - should be 0
-                       if (DemodBuffer[startIdx+idx] != 0) {
-                               if (g_debugMode) PrintAndLog("Error spacer not 0: %d, pos: %d",DemodBuffer[startIdx+idx],startIdx+idx);
-                               return 0;
-                       }
-                       continue;
-               } 
-               if (keyCnt<8){ //lsb first
-                       xorKey = xorKey | (DemodBuffer[startIdx+idx]<<keyCnt);
-                       keyCnt++;
-                       if (keyCnt==8 && g_debugMode) PrintAndLog("xorKey Found: %02x", xorKey);
-                       continue;
-               }
-               //lsb first
-               ByteStream[ByteCnt] = ByteStream[ByteCnt] | (DemodBuffer[startIdx+idx]<<bitCnt);
-               bitCnt++;
-               if (bitCnt % 8 == 0){
-                       if (g_debugMode) PrintAndLog("byte %d: %02x",ByteCnt,ByteStream[ByteCnt]);
-                       bitCnt=0;
-                       ByteCnt++;
-               }
+       size_t startIdx = ans + 6; //start after 6 bit preamble
+
+       uint8_t bits_no_spacer[90];
+       //so as to not mess with raw DemodBuffer copy to a new sample array
+       memcpy(bits_no_spacer, DemodBuffer + startIdx, 90);
+       // remove the 18 (90/5=18) parity bits (down to 72 bits (96-6-18=72))
+       size_t bitLen = removeParity(bits_no_spacer, 0, 5, 3, 90); //source, startloc, paritylen, ptype, length_to_run
+       if (bitLen != 72) {
+               if (g_debugMode) PrintAndLog("Error gProxII: spacer removal did not produce 72 bits: %u, start: %u", bitLen, startIdx);
+               return 0;
        }
-       for (uint8_t i = 0; i < ByteCnt; i++){
-               ByteStream[i] ^= xorKey; //xor
-               if (g_debugMode) PrintAndLog("byte %d after xor: %02x", i, ByteStream[i]);
+       // get key and then get all 8 bytes of payload decoded
+       xorKey = (uint8_t)bytebits_to_byteLSBF(bits_no_spacer, 8);
+       for (size_t idx = 0; idx < 8; idx++) {
+               ByteStream[idx] = ((uint8_t)bytebits_to_byteLSBF(bits_no_spacer+8 + (idx*8),8)) ^ xorKey;
+               if (g_debugMode) PrintAndLog("byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]);
        }
-       //now ByteStream contains 64 bytes of decrypted raw tag data
+       //now ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data
        // 
        uint8_t fmtLen = ByteStream[0]>>2;
        uint32_t FC = 0;
        uint32_t Card = 0;
+       //get raw 96 bits to print
        uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans,32);
        uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
        uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
@@ -631,13 +634,14 @@ int CmdG_Prox_II_Demod(const char *Cmd)
        if (fmtLen==36){
                FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1);
                Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5);
-               PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d",fmtLen,FC,Card);
+               PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card);
        } else if(fmtLen==26){
                FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7);
                Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7);
-               PrintAndLog("G-Prox-II Found: FmtLen %d, FC %d, Card %d",fmtLen,FC,Card);    
+               PrintAndLog("G-Prox-II Found: FmtLen %d, FC %u, Card %u", (int)fmtLen, FC, Card);
        } else {
-               PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",fmtLen);
+               PrintAndLog("Unknown G-Prox-II Fmt Found: FmtLen %d",(int)fmtLen);
+               PrintAndLog("Decoded Raw: %s", sprint_hex(ByteStream, 8)); 
        }
        PrintAndLog("Raw: %08x%08x%08x", raw1,raw2,raw3);
        setDemodBuf(DemodBuffer+ans, 96, 0);
@@ -664,7 +668,7 @@ int CmdVikingDemod(const char *Cmd)
        uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
        uint32_t cardid = bytebits_to_byte(DemodBuffer+ans+24, 32);
        uint8_t  checksum = bytebits_to_byte(DemodBuffer+ans+32+24, 8);
-       PrintAndLog("Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, checksum);
+       PrintAndLog("Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, (unsigned int) checksum);
        PrintAndLog("Raw: %08X%08X", raw1,raw2);
        setDemodBuf(DemodBuffer+ans, 64, 0);
        return 1;
@@ -830,16 +834,18 @@ int CmdUndec(const char *Cmd)
        uint8_t factor = param_get8ex(Cmd, 0,2, 10);
        //We have memory, don't we?
        int swap[MAX_GRAPH_TRACE_LEN] = { 0 };
-       uint32_t g_index = 0 ,s_index = 0;
-       while(g_index < GraphTraceLen && s_index < MAX_GRAPH_TRACE_LEN)
+       uint32_t g_index = 0s_index = 0;
+       while(g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN)
        {
                int count = 0;
-               for(count = 0; count < factor && s_index+count < MAX_GRAPH_TRACE_LEN; count ++)
+               for(count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++)
                        swap[s_index+count] = GraphBuffer[g_index];
-               s_index+=count;
+
+               s_index += count;
+               g_index++;
        }
 
-       memcpy(GraphBuffer,swap, s_index * sizeof(int));
+       memcpy(GraphBuffer, swap, s_index * sizeof(int));
        GraphTraceLen = s_index;
        RepaintGraphWindow();
        return 0;
@@ -873,13 +879,15 @@ int CmdGraphShiftZero(const char *Cmd)
 int CmdAskEdgeDetect(const char *Cmd)
 {
        int thresLen = 25;
+       int Last = 0;
        sscanf(Cmd, "%i", &thresLen); 
 
        for(int i = 1; i<GraphTraceLen; i++){
                if (GraphBuffer[i]-GraphBuffer[i-1]>=thresLen) //large jump up
-                       GraphBuffer[i-1] = 127;
+                       Last = 127;
                else if(GraphBuffer[i]-GraphBuffer[i-1]<=-1*thresLen) //large jump down
-                       GraphBuffer[i-1] = -127;
+                       Last = -127;
+               GraphBuffer[i-1] = Last;
        }
        RepaintGraphWindow();
        return 0;
@@ -919,19 +927,21 @@ int CmdDetectClockRate(const char *Cmd)
 
 char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert)
 {
-       char *fskType;
+       static char fType[8];
+       memset(fType, 0x00, 8);
+       char *fskType = fType;
        if (fchigh==10 && fclow==8){
                if (invert) //fsk2a
-                       fskType = "FSK2a";
+                       memcpy(fskType, "FSK2a", 5);
                else //fsk2
-                       fskType = "FSK2";
+                       memcpy(fskType, "FSK2", 4);
        } else if (fchigh == 8 && fclow == 5) {
                if (invert)
-                       fskType = "FSK1";
+                       memcpy(fskType, "FSK1", 4);
                else
-                       fskType = "FSK1a";
+                       memcpy(fskType, "FSK1a", 5);
        } else {
-               fskType = "FSK??";
+               memcpy(fskType, "FSK??", 5);
        }
        return fskType;
 }
@@ -950,39 +960,40 @@ int FSKrawDemod(const char *Cmd, bool verbose)
        invert = param_get8(Cmd, 1);
        fchigh = param_get8(Cmd, 2);
        fclow = param_get8(Cmd, 3);
+
        if (strlen(Cmd)>0 && strlen(Cmd)<=2) {
-                if (rfLen==1){
+               if (rfLen==1) {
                        invert = 1;   //if invert option only is used
                        rfLen = 0;
-                }
+               }
        }
        uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0};
        size_t BitLen = getFromGraphBuf(BitStream);
        if (BitLen==0) return 0;
        //get field clock lengths
-       uint8_t fc1=0, fc2=0, rf1=0;
+       uint16_t fcs=0;
        if (!fchigh || !fclow) {
-               uint8_t ans = fskClocks(&fc1, &fc2, &rf1, false);
-               if (ans == 0) {
-                       if (g_debugMode) PrintAndLog("\nError: cannot detect valid fsk field clocks");                  
-                       return 0; // can't detect field clock
+               fcs = countFC(BitStream, BitLen, 1);
+               if (!fcs) {
+                       fchigh = 10;
+                       fclow = 8;
+               } else {
+                       fchigh = (fcs >> 8) & 0x00FF;
+                       fclow = fcs & 0x00FF;
                }
-               fchigh = fc1;
-               fclow = fc2;
-               if (rfLen == 0) rfLen = rf1;
        }
        //get bit clock length
-       if (!rfLen){
+       if (!rfLen) {
                rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow);
                if (!rfLen) rfLen = 50;
        }
        int size = fskdemod(BitStream, BitLen, rfLen, invert, fchigh, fclow);
-       if (size > 0){
+       if (size > 0) {
                setDemodBuf(BitStream,size,0);
 
                // Now output the bitstream to the scrollback by line of 16 bits
                if (verbose || g_debugMode) {
-                       PrintAndLog("\nUsing Clock:%hu, invert:%hu, fchigh:%hu, fclow:%hu", rfLen, invert, fchigh, fclow);
+                       PrintAndLog("\nUsing Clock:%u, invert:%u, fchigh:%u, fclow:%u", (unsigned int)rfLen, (unsigned int)invert, (unsigned int)fchigh, (unsigned int)fclow);
                        PrintAndLog("%s decoded bitstream:",GetFSKType(fchigh,fclow,invert));
                        printDemodBuff();
                }
@@ -1255,7 +1266,7 @@ int CmdFSKdemodAWID(const char *Cmd)
        //get binary from fsk wave
        int idx = AWIDdemodFSK(BitStream, &size);
        if (idx<=0){
-               if (g_debugMode==1){
+               if (g_debugMode){
                        if (idx == -1)
                                PrintAndLog("DEBUG: Error - not enough samples");
                        else if (idx == -2)
@@ -1293,7 +1304,7 @@ int CmdFSKdemodAWID(const char *Cmd)
 
        size = removeParity(BitStream, idx+8, 4, 1, 88);
        if (size != 66){
-               if (g_debugMode==1) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
+               if (g_debugMode) PrintAndLog("DEBUG: Error - at parity check-tag size does not match AWID format");
                return 0;
        }
        // ok valid card found!
@@ -1353,7 +1364,7 @@ int CmdFSKdemodPyramid(const char *Cmd)
        //get binary from fsk wave
        int idx = PyramiddemodFSK(BitStream, &size);
        if (idx < 0){
-               if (g_debugMode==1){
+               if (g_debugMode){
                        if (idx == -5)
                                PrintAndLog("DEBUG: Error - not enough samples");
                        else if (idx == -1)
@@ -1409,7 +1420,7 @@ int CmdFSKdemodPyramid(const char *Cmd)
 
        size = removeParity(BitStream, idx+8, 8, 1, 120);
        if (size != 105){
-               if (g_debugMode==1
+               if (g_debugMode) 
                        PrintAndLog("DEBUG: Error at parity check - tag size does not match Pyramid format, SIZE: %d, IDX: %d, hi3: %x",size, idx, rawHi3);
                return 0;
        }
@@ -1632,21 +1643,21 @@ int CmdIndalaDecode(const char *Cmd)
        }
 
        if (!ans){
-               if (g_debugMode==1
+               if (g_debugMode) 
                        PrintAndLog("Error1: %d",ans);
                return 0;
        }
        uint8_t invert=0;
        size_t size = DemodBufferLen;
-       size_t startIdx = indala26decode(DemodBuffer, &size, &invert);
-       if (startIdx < 1 || size > 224) {
-               if (g_debugMode==1)
+       int startIdx = indala26decode(DemodBuffer, &size, &invert);
+       if (startIdx < 0 || size > 224) {
+               if (g_debugMode)
                        PrintAndLog("Error2: %d",ans);
                return -1;
        }
-       setDemodBuf(DemodBuffer, size, startIdx);
+       setDemodBuf(DemodBuffer, size, (size_t)startIdx);
        if (invert)
-               if (g_debugMode==1)
+               if (g_debugMode)
                        PrintAndLog("Had to invert bits");
 
        PrintAndLog("BitLen: %d",DemodBufferLen);
@@ -2027,10 +2038,20 @@ int CmdSamples(const char *Cmd)
 
 int CmdTuneSamples(const char *Cmd)
 {
-       int timeout = 0;
+       int timeout = 0, arg = FLAG_TUNE_ALL;
+
+       if(*Cmd == 'l') {
+         arg = FLAG_TUNE_LF;
+       } else if (*Cmd == 'h') {
+         arg = FLAG_TUNE_HF;
+       } else if (*Cmd != '\0') {
+         PrintAndLog("use 'tune' or 'tune l' or 'tune h'");
+         return 0;
+       }
+
        printf("\nMeasuring antenna characteristics, please wait...");
 
-       UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING};
+       UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING, {arg, 0, 0}};
        SendCommand(&c);
 
        UsbCommand resp;
@@ -2313,9 +2334,8 @@ int Cmdbin2hex(const char *Cmd)
        return 0;
 }
 
-int usage_data_hex2bin(){
-
-       PrintAndLog("Usage: data bin2hex <binary_digits>");
+int usage_data_hex2bin() {
+       PrintAndLog("Usage: data hex2bin <hex_digits>");
        PrintAndLog("       This function will ignore all non-hexadecimal characters (but stop reading on whitespace)");
        return 0;
 
index c3303c54c25ce0c269e22523b7953fd5a1308ea2..9b9f2da92d2945879a74e483b5a4790bd8e212f0 100644 (file)
 #ifndef CMDDATA_H__
 #define CMDDATA_H__
 
+#include <stdlib.h>  //size_t
+#include <stdint.h>  //uint_32+
+#include <stdbool.h> //bool
+
+#include "cmdparser.h" // for command_t
+
 command_t * CmdDataCommands();
 
 int CmdData(const char *Cmd);
@@ -63,6 +69,7 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo );
 int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose);
 int ASKbiphaseDemod(const char *Cmd, bool verbose);
 int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType);
+int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck);
 int FSKrawDemod(const char *Cmd, bool verbose);
 int PSKDemod(const char *Cmd, bool verbose);
 int NRZrawDemod(const char *Cmd, bool verbose);
index 81716db32c4e5d3842fe634af7b23c1b1884991f..ecf3ba03e99b3de9ae7ff23fb0a53d3779a34bb1 100644 (file)
@@ -696,14 +696,17 @@ 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)
+    if(power) {
         c.arg[0] |= ISO14A_NO_DISCONNECT;
+    }
 
-       if(datalen > 0)
+       if(datalen > 0) {
         c.arg[0] |= ISO14A_RAW;
+    }
 
-       if(topazmode)
+       if(topazmode) {
                c.arg[0] |= ISO14A_TOPAZMODE;
+    }
                
        // Max buffer is USB_CMD_DATA_SIZE
     c.arg[1] = (datalen & 0xFFFF) | (numbits << 16);
index 48e78b1c2fcad2a74a90de187356d346ed54492c..36c8e6c370eb121fab1ecb8c0b6027b210b640ad 100644 (file)
@@ -9,6 +9,7 @@
 //-----------------------------------------------------------------------------\r
 \r
 #include "cmdhfmf.h"\r
+#include "./nonce2key/nonce2key.h"\r
 \r
 static int CmdHelp(const char *Cmd);\r
 \r
@@ -28,7 +29,7 @@ int CmdHF14AMifare(const char *Cmd)
        printf("-------------------------------------------------------------------------\n");\r
 \r
        \r
-start:\r
+ start:\r
     clearCommandBuffer();\r
     SendCommand(&c);\r
        \r
@@ -1015,72 +1016,273 @@ int CmdHF14AMfChk(const char *Cmd)
        return 0;\r
 }\r
 \r
-int CmdHF14AMf1kSim(const char *Cmd)\r
-{\r
-       uint8_t uid[7] = {0, 0, 0, 0, 0, 0, 0};\r
+void readerAttack(nonces_t ar_resp[], bool setEmulatorMem) {\r
+       #define ATTACK_KEY_COUNT 8 // keep same as define in iso14443a.c -> Mifare1ksim()\r
+       uint64_t key = 0;\r
+       typedef struct {\r
+                       uint64_t keyA;\r
+                       uint64_t keyB;\r
+       } st_t;\r
+       st_t sector_trailer[ATTACK_KEY_COUNT];\r
+       memset(sector_trailer, 0x00, sizeof(sector_trailer));\r
+\r
+       uint8_t stSector[ATTACK_KEY_COUNT];\r
+       memset(stSector, 0x00, sizeof(stSector));\r
+       uint8_t key_cnt[ATTACK_KEY_COUNT];\r
+       memset(key_cnt, 0x00, sizeof(key_cnt));\r
+\r
+       for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {\r
+               if (ar_resp[i].ar2 > 0) {\r
+                       //PrintAndLog("DEBUG: Trying sector %d, cuid %08x, nt %08x, ar %08x, nr %08x, ar2 %08x, nr2 %08x",ar_resp[i].sector, ar_resp[i].cuid,ar_resp[i].nonce,ar_resp[i].ar,ar_resp[i].nr,ar_resp[i].ar2,ar_resp[i].nr2);\r
+                       if (mfkey32(ar_resp[i], &key)) {\r
+                               PrintAndLog("  Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));\r
+\r
+                               for (uint8_t ii = 0; ii<ATTACK_KEY_COUNT; ii++) {\r
+                                       if (key_cnt[ii]==0 || stSector[ii]==ar_resp[i].sector) {\r
+                                               if (ar_resp[i].keytype==0) {\r
+                                                       //keyA\r
+                                                       sector_trailer[ii].keyA = key;\r
+                                                       stSector[ii] = ar_resp[i].sector;\r
+                                                       key_cnt[ii]++;\r
+                                                       break;\r
+                                               } else {\r
+                                                       //keyB\r
+                                                       sector_trailer[ii].keyB = key;\r
+                                                       stSector[ii] = ar_resp[i].sector;\r
+                                                       key_cnt[ii]++;\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       //set emulator memory for keys\r
+       if (setEmulatorMem) {\r
+               for (uint8_t i = 0; i<ATTACK_KEY_COUNT; i++) {\r
+                       if (key_cnt[i]>0) {\r
+                               uint8_t memBlock[16];\r
+                               memset(memBlock, 0x00, sizeof(memBlock));\r
+                               char cmd1[36];\r
+                               memset(cmd1,0x00,sizeof(cmd1));\r
+                               snprintf(cmd1,sizeof(cmd1),"%04x%08xFF078069%04x%08x",(uint32_t) (sector_trailer[i].keyA>>32), (uint32_t) (sector_trailer[i].keyA &0xFFFFFFFF),(uint32_t) (sector_trailer[i].keyB>>32), (uint32_t) (sector_trailer[i].keyB &0xFFFFFFFF));\r
+                               PrintAndLog("Setting Emulator Memory Block %02d: [%s]",stSector[i]*4+3, cmd1);\r
+                               if (param_gethex(cmd1, 0, memBlock, 32)) {\r
+                                       PrintAndLog("block data must include 32 HEX symbols");\r
+                                       return;\r
+                               }\r
+                               \r
+                               UsbCommand c = {CMD_MIFARE_EML_MEMSET, {(stSector[i]*4+3), 1, 0}};\r
+                               memcpy(c.d.asBytes, memBlock, 16);\r
+                               clearCommandBuffer();\r
+                               SendCommand(&c);                        \r
+                       }\r
+               }\r
+       }\r
+       /*\r
+       //un-comment to use as well moebius attack\r
+       for (uint8_t i = ATTACK_KEY_COUNT; i<ATTACK_KEY_COUNT*2; i++) {\r
+               if (ar_resp[i].ar2 > 0) {\r
+                       if (tryMfk32_moebius(ar_resp[i], &key)) {\r
+                               PrintAndLog("M-Found Key%s for sector %02d: [%04x%08x]", (ar_resp[i].keytype) ? "B" : "A", ar_resp[i].sector, (uint32_t) (key>>32), (uint32_t) (key &0xFFFFFFFF));\r
+                       }\r
+               }\r
+       }*/\r
+}\r
+\r
+int usage_hf14_mf1ksim(void) {\r
+       PrintAndLog("Usage:  hf mf sim h u <uid (8, 14, or 20 hex symbols)> n <numreads> i x");\r
+       PrintAndLog("options:");\r
+       PrintAndLog("      h    this help");\r
+       PrintAndLog("      u    (Optional) UID 4,7 or 10 bytes. If not specified, the UID 4B from emulator memory will be used");\r
+       PrintAndLog("      n    (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");\r
+       PrintAndLog("      i    (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");\r
+       PrintAndLog("      x    (Optional) Crack, performs the 'reader attack', nr/ar attack against a legitimate reader, fishes out the key(s)");\r
+       PrintAndLog("      e    (Optional) set keys found from 'reader attack' to emulator memory (implies x and i)");\r
+       PrintAndLog("      f    (Optional) get UIDs to use for 'reader attack' from file 'f <filename.txt>' (implies x and i)");\r
+       PrintAndLog("samples:");\r
+       PrintAndLog("           hf mf sim u 0a0a0a0a");\r
+       PrintAndLog("           hf mf sim u 11223344556677");\r
+       PrintAndLog("           hf mf sim u 112233445566778899AA");\r
+       PrintAndLog("           hf mf sim f uids.txt");\r
+       PrintAndLog("           hf mf sim u 0a0a0a0a e");\r
+               \r
+       return 0;\r
+}\r
+\r
+int CmdHF14AMf1kSim(const char *Cmd) {\r
+       UsbCommand resp;\r
+       uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};\r
        uint8_t exitAfterNReads = 0;\r
        uint8_t flags = 0;\r
-\r
-       uint8_t cmdp = param_getchar(Cmd, 0);\r
-       \r
-       if (cmdp == 'h' || cmdp == 'H') {\r
-               PrintAndLog("Usage:  hf mf sim  u <uid (8 hex symbols)> n <numreads> i x");\r
-               PrintAndLog("           h    this help");\r
-               PrintAndLog("           u    (Optional) UID. If not specified, the UID from emulator memory will be used");\r
-               PrintAndLog("           n    (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");\r
-               PrintAndLog("           i    (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");\r
-               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
-               return 0;\r
-       }\r
+       int uidlen = 0;\r
        uint8_t pnr = 0;\r
-       if (param_getchar(Cmd, pnr) == 'u') {\r
-               if(param_gethex(Cmd, pnr+1, uid, 8) == 0)\r
-               {\r
-                       flags |= FLAG_4B_UID_IN_DATA; // UID from packet\r
-               } else if(param_gethex(Cmd,pnr+1,uid,14) == 0) {\r
-                       flags |= FLAG_7B_UID_IN_DATA;// UID from packet\r
-               } else {\r
-                       PrintAndLog("UID, if specified, must include 8 or 14 HEX symbols");\r
-                       return 1;\r
+       bool setEmulatorMem = false;\r
+       bool attackFromFile = false;\r
+       FILE *f;\r
+       char filename[FILE_PATH_SIZE];\r
+       memset(filename, 0x00, sizeof(filename));\r
+       int len = 0;\r
+       char buf[64];\r
+\r
+       uint8_t cmdp = 0;\r
+       bool errors = false;\r
+\r
+       while(param_getchar(Cmd, cmdp) != 0x00) {\r
+               switch(param_getchar(Cmd, cmdp)) {\r
+               case 'e':\r
+               case 'E':\r
+                       setEmulatorMem = true;\r
+                       //implies x and i\r
+                       flags |= FLAG_INTERACTIVE;\r
+                       flags |= FLAG_NR_AR_ATTACK;\r
+                       cmdp++;\r
+                       break;\r
+               case 'f':\r
+               case 'F':\r
+                       len = param_getstr(Cmd, cmdp+1, filename);\r
+                       if (len < 1) {\r
+                               PrintAndLog("error no filename found");\r
+                               return 0;\r
+                       }\r
+                       attackFromFile = true;\r
+                       //implies x and i\r
+                       flags |= FLAG_INTERACTIVE;\r
+                       flags |= FLAG_NR_AR_ATTACK;\r
+                       cmdp += 2;\r
+                       break;\r
+               case 'h':\r
+               case 'H':\r
+                       return usage_hf14_mf1ksim();\r
+               case 'i':\r
+               case 'I':\r
+                       flags |= FLAG_INTERACTIVE;\r
+                       cmdp++;\r
+                       break;\r
+               case 'n':\r
+               case 'N':\r
+                       exitAfterNReads = param_get8(Cmd, pnr+1);\r
+                       cmdp += 2;\r
+                       break;\r
+               case 'u':\r
+               case 'U':\r
+                       param_gethex_ex(Cmd, cmdp+1, uid, &uidlen);\r
+                       switch(uidlen) {\r
+                               case 20: flags = FLAG_10B_UID_IN_DATA;  break; //not complete\r
+                               case 14: flags = FLAG_7B_UID_IN_DATA; break;\r
+                               case  8: flags = FLAG_4B_UID_IN_DATA; break;\r
+                               default: return usage_hf14_mf1ksim();\r
+                       }\r
+                       cmdp += 2;\r
+                       break;\r
+               case 'x':\r
+               case 'X':\r
+                       flags |= FLAG_NR_AR_ATTACK;\r
+                       cmdp++;\r
+                       break;\r
+               default:\r
+                       PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));\r
+                       errors = true;\r
+                       break;\r
                }\r
-               pnr +=2;\r
-       }\r
-       if (param_getchar(Cmd, pnr) == 'n') {\r
-               exitAfterNReads = param_get8(Cmd,pnr+1);\r
-               pnr += 2;\r
-       }\r
-       if (param_getchar(Cmd, pnr) == 'i' ) {\r
-               //Using a flag to signal interactiveness, least significant bit\r
-               flags |= FLAG_INTERACTIVE;\r
-               pnr++;\r
+               if(errors) break;\r
        }\r
+       //Validations\r
+       if(errors) return usage_hf14_mf1ksim();\r
 \r
-       if (param_getchar(Cmd, pnr) == 'x' ) {\r
-               //Using a flag to signal interactiveness, least significant bit\r
-               flags |= FLAG_NR_AR_ATTACK;\r
-       }\r
-       PrintAndLog(" uid:%s, numreads:%d, flags:%d (0x%02x) ",\r
-                               flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):\r
-                                                                                         flags & FLAG_7B_UID_IN_DATA   ? sprint_hex(uid,7): "N/A"\r
-                               , exitAfterNReads, flags,flags);\r
+       //get uid from file\r
+       if (attackFromFile) {\r
+               int count = 0;\r
+               // open file\r
+               f = fopen(filename, "r");\r
+               if (f == NULL) {\r
+                       PrintAndLog("File %s not found or locked", filename);\r
+                       return 1;\r
+               }\r
+               PrintAndLog("Loading file and simulating. Press keyboard to abort");\r
+               while(!feof(f) && !ukbhit()){\r
+                       memset(buf, 0, sizeof(buf));\r
+                       memset(uid, 0, sizeof(uid));\r
 \r
+                       if (fgets(buf, sizeof(buf), f) == NULL) {                       \r
+                               if (count > 0) break;\r
+                               \r
+                               PrintAndLog("File reading error.");\r
+                               fclose(f);\r
+                               return 2;\r
+                       }\r
+                       if(!strlen(buf) && feof(f)) break;\r
+\r
+                       uidlen = strlen(buf)-1;\r
+                       switch(uidlen) {\r
+                               case 20: flags |= FLAG_10B_UID_IN_DATA; break; //not complete\r
+                               case 14: flags |= FLAG_7B_UID_IN_DATA; break;\r
+                               case  8: flags |= FLAG_4B_UID_IN_DATA; break;\r
+                               default: \r
+                                       PrintAndLog("uid in file wrong length at %d (length: %d) [%s]",count, uidlen, buf);\r
+                                       fclose(f);\r
+                                       return 2;\r
+                       }\r
 \r
-       UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};\r
-       memcpy(c.d.asBytes, uid, sizeof(uid));\r
-       SendCommand(&c);\r
+                       for (uint8_t i = 0; i < uidlen; i += 2) {\r
+                               sscanf(&buf[i], "%02x", (unsigned int *)&uid[i / 2]);\r
+                       }\r
+                       \r
+                       PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) - press button to abort",\r
+                                       flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):\r
+                                               flags & FLAG_7B_UID_IN_DATA     ? sprint_hex(uid,7): \r
+                                                       flags & FLAG_10B_UID_IN_DATA ? sprint_hex(uid,10): "N/A"\r
+                                       , exitAfterNReads, flags, flags);\r
+\r
+                       UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};\r
+                       memcpy(c.d.asBytes, uid, sizeof(uid));\r
+                       clearCommandBuffer();\r
+                       SendCommand(&c);\r
 \r
-       if(flags & FLAG_INTERACTIVE)\r
-       {\r
-               UsbCommand resp;\r
-               PrintAndLog("Press pm3-button to abort simulation");\r
-               while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
-                       //We're waiting only 1.5 s at a time, otherwise we get the\r
-                       // annoying message about "Waiting for a response... "\r
+                       while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+                               //We're waiting only 1.5 s at a time, otherwise we get the\r
+                               // annoying message about "Waiting for a response... "\r
+                       }\r
+                       //got a response\r
+                       nonces_t ar_resp[ATTACK_KEY_COUNT*2];\r
+                       memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));\r
+                       readerAttack(ar_resp, setEmulatorMem);\r
+                       if ((bool)resp.arg[1]) {\r
+                               PrintAndLog("Device button pressed - quitting");\r
+                               fclose(f);\r
+                               return 4;\r
+                       }\r
+                       count++;\r
+               }\r
+               fclose(f);\r
+       } else { //not from file\r
+\r
+               PrintAndLog("mf 1k sim uid: %s, numreads:%d, flags:%d (0x%02x) ",\r
+                               flags & FLAG_4B_UID_IN_DATA ? sprint_hex(uid,4):\r
+                                       flags & FLAG_7B_UID_IN_DATA     ? sprint_hex(uid,7): \r
+                                               flags & FLAG_10B_UID_IN_DATA ? sprint_hex(uid,10): "N/A"\r
+                               , exitAfterNReads, flags, flags);\r
+\r
+               UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads,0}};\r
+               memcpy(c.d.asBytes, uid, sizeof(uid));\r
+               clearCommandBuffer();\r
+               SendCommand(&c);\r
+\r
+               if(flags & FLAG_INTERACTIVE) {\r
+                       PrintAndLog("Press pm3-button to abort simulation");\r
+                       while(! WaitForResponseTimeout(CMD_ACK,&resp,1500)) {\r
+                               //We're waiting only 1.5 s at a time, otherwise we get the\r
+                               // annoying message about "Waiting for a response... "\r
+                       }\r
+                       //got a response\r
+                       if (flags & FLAG_NR_AR_ATTACK) {\r
+                               nonces_t ar_resp[ATTACK_KEY_COUNT*2];\r
+                               memcpy(ar_resp, resp.d.asBytes, sizeof(ar_resp));\r
+                               readerAttack(ar_resp, setEmulatorMem);\r
+                       }\r
                }\r
        }\r
-       \r
+\r
        return 0;\r
 }\r
 \r
index 33dc78aeb523c5731ec297e9432159336d774580..74e476eb55067a3c72eb4c666cb82f32dd1f4086 100644 (file)
@@ -467,7 +467,7 @@ static command_t CommandTable[] =
        {"reset",         CmdReset,       0, "Reset the Proxmark3"},
        {"setlfdivisor",  CmdSetDivisor,  0, "<19 - 255> -- Drive LF antenna at 12Mhz/(divisor+1)"},
        {"setmux",        CmdSetMux,      0, "<loraw|hiraw|lopkd|hipkd> -- Set the ADC mux to a specific value"},
-       {"tune",          CmdTune,        0, "Measure antenna tuning"},
+       {"tune",          CmdTune,        0, "['l'|'h'] -- Measure antenna tuning (option 'l' or 'h' to limit to LF or HF)"},
        {"version",       CmdVersion,     0, "Show version information about the connected Proxmark"},
        {"status",        CmdStatus,      0, "Show runtime status information about the connected Proxmark"},
        {"ping",          CmdPing,        0, "Test if the pm3 is responsive"},
index 41feec20d5b708b98636eaacaa71a5a4b7ce04c5..016f0fe288ba5ca051916d5a775fb009594178d2 100644 (file)
 #include <string.h>
 #include <limits.h>
 #include "proxmark3.h"
-#include "data.h"
-#include "graph.h"
-#include "ui.h"
-#include "cmdparser.h"
-#include "cmdmain.h"
-#include "cmddata.h"
-#include "util.h"
 #include "cmdlf.h"
-#include "cmdlfhid.h"
-#include "cmdlfawid.h"
-#include "cmdlfti.h"
-#include "cmdlfem4x.h"
-#include "cmdlfhitag.h"
-#include "cmdlft55xx.h"
-#include "cmdlfpcf7931.h"
-#include "cmdlfio.h"
-#include "cmdlfviking.h"
-#include "lfdemod.h"
+#include "lfdemod.h"     // for psk2TOpsk1
+#include "util.h"        // for parsing cli command utils
+#include "ui.h"          // for show graph controls
+#include "graph.h"       // for graph data
+#include "cmdparser.h"   // for getting cli commands included in cmdmain.h
+#include "cmdmain.h"     // for sending cmds to device
+#include "data.h"        // for GetFromBigBuf
+#include "cmddata.h"     // for `lf search`
+#include "cmdlfawid.h"   // for awid menu
+#include "cmdlfem4x.h"   // for em4x menu
+#include "cmdlfhid.h"    // for hid menu
+#include "cmdlfhitag.h"  // for hitag menu
+#include "cmdlfio.h"     // for ioprox menu
+#include "cmdlft55xx.h"  // for t55xx menu
+#include "cmdlfti.h"     // for ti menu
+#include "cmdlfpresco.h" // for presco menu
+#include "cmdlfpcf7931.h"// for pcf7931 menu
+#include "cmdlfpyramid.h"// for pyramid menu
+#include "cmdlfviking.h" // for viking menu
 
 static int CmdHelp(const char *Cmd);
 
@@ -62,7 +64,6 @@ int CmdLFCommandRead(const char *Cmd)
        bool errors = FALSE;
        //uint8_t divisor = 95; //125khz
        uint8_t cmdp = 0;
-       int strLength = 0;
        while(param_getchar(Cmd, cmdp) != 0x00)
        {
                switch(param_getchar(Cmd, cmdp))
@@ -78,7 +79,7 @@ int CmdLFCommandRead(const char *Cmd)
                        cmdp++;
                        break;
                case 'c':
-                       strLength = param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes);
+                       param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes);
                        cmdp+=2;
                        break;
                case 'd':
@@ -539,7 +540,7 @@ int CmdLFSetConfig(const char *Cmd)
                return usage_lf_config();
        }
        //Bps is limited to 8, so fits in lower half of arg1
-       if(bps >> 8) bps = 8;
+       if(bps >> 4) bps = 8;
 
        sample_config config = {
                decimation,bps,averaging,divisor,trigger_threshold
@@ -663,7 +664,7 @@ int usage_lf_simask(void)
        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("       s              add t55xx Sequence Terminator gap - default: no gaps (only manchester)");
        PrintAndLog("       d <hexdata>    Data to sim as hex - omit to sim from DemodBuffer");
        return 0;
 }
@@ -1193,7 +1194,8 @@ int CmdLFfind(const char *Cmd)
                                return 1;
                        }
                }
-               ans=ASKDemod("0 0 0",TRUE,FALSE,1);
+               bool st = TRUE;
+               ans=ASKDemod_ext("0 0 0",TRUE,FALSE,1,&st);
                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'");
@@ -1219,7 +1221,9 @@ static command_t CommandTable[] =
        {"hid",         CmdLFHID,           1, "{ HID RFIDs...     }"},
        {"hitag",       CmdLFHitag,         1, "{ Hitag tags and transponders... }"},
        {"io",          CmdLFIO,            1, "{ ioProx tags...   }"},
+       {"presco",      CmdLFPresco,        1, "{ Presco RFIDs... }"},
        {"pcf7931",     CmdLFPCF7931,       1, "{ PCF7931 RFIDs... }"},
+       {"pyramid",     CmdLFPyramid,       1, "{ Farpointe/Pyramid RFIDs... }"},
        {"t55xx",       CmdLFT55XX,         1, "{ T55xx RFIDs...   }"},
        {"ti",          CmdLFTI,            1, "{ TI RFIDs...      }"},
        {"viking",      CmdLFViking,        1, "{ Viking tags...   }"},
index fe5ba587617a502d9b8a0b2ee43dd82619c1e376..07247364c0751a498836871fca7fab1cf193994e 100644 (file)
@@ -18,6 +18,7 @@
 #include "common.h"
 #include "util.h"
 #include "hitag2.h"
+#include "hitagS.h"
 #include "sleep.h"
 #include "cmdmain.h"
 
@@ -190,14 +191,20 @@ int CmdLFHitagSim(const char *Cmd) {
 }
 
 int CmdLFHitagReader(const char *Cmd) {
-//  UsbCommand c = {CMD_READER_HITAG};
-       
-//     param_get32ex(Cmd,1,0,16);
        UsbCommand c = {CMD_READER_HITAG};//, {param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),param_get32ex(Cmd,3,0,16)}};
        hitag_data* htd = (hitag_data*)c.d.asBytes;
        hitag_function htf = param_get32ex(Cmd,0,0,10);
        
        switch (htf) {
+               case 01: { //RHTSF_CHALLENGE
+                       c = (UsbCommand){ CMD_READ_HITAG_S };
+                       num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr);
+                       num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4);
+               } break;
+               case 02: { //RHTSF_KEY
+                       c = (UsbCommand){ CMD_READ_HITAG_S };
+                       num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
+               } break;
                case RHT2F_PASSWORD: {
                        num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->pwd.password);
                } break;
@@ -216,6 +223,8 @@ int CmdLFHitagReader(const char *Cmd) {
                        PrintAndLog("Error: unkown reader function %d",htf);
                        PrintAndLog("Hitag reader functions");
                        PrintAndLog(" HitagS (0*)");
+                       PrintAndLog("  01 <nr> <ar> (Challenge) read all pages from a Hitag S tag");
+                       PrintAndLog("  02 <key> (set to 0 if no authentication is needed) read all pages from a Hitag S tag");
                        PrintAndLog(" Hitag1 (1*)");
                        PrintAndLog(" Hitag2 (2*)");
                        PrintAndLog("  21 <password> (password mode)");
@@ -257,14 +266,126 @@ int CmdLFHitagReader(const char *Cmd) {
   return 0;
 }
 
+
+int CmdLFHitagSimS(const char *Cmd) {
+       UsbCommand c = { CMD_SIMULATE_HITAG_S };
+       char filename[FILE_PATH_SIZE] = { 0x00 };
+       FILE* pf;
+       bool tag_mem_supplied;
+       int len = strlen(Cmd);
+       if (len > FILE_PATH_SIZE)
+               len = FILE_PATH_SIZE;
+       memcpy(filename, Cmd, len);
+
+       if (strlen(filename) > 0) {
+               if ((pf = fopen(filename, "rb+")) == NULL) {
+                       PrintAndLog("Error: Could not open file [%s]", filename);
+                       return 1;
+               }
+               tag_mem_supplied = true;
+               if (fread(c.d.asBytes, 4*64, 1, pf) == 0) {
+                       PrintAndLog("Error: File reading error");
+                       fclose(pf);
+                       return 1;
+               }
+               fclose(pf);
+       } else {
+               tag_mem_supplied = false;
+       }
+
+       // Does the tag comes with memory
+       c.arg[0] = (uint32_t) tag_mem_supplied;
+
+       SendCommand(&c);
+       return 0;
+}
+
+int CmdLFHitagCheckChallenges(const char *Cmd) {
+       UsbCommand c = { CMD_TEST_HITAGS_TRACES };
+       char filename[FILE_PATH_SIZE] = { 0x00 };
+       FILE* pf;
+       bool file_given;
+       int len = strlen(Cmd);
+       if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE;
+       memcpy(filename, Cmd, len);
+       
+       if (strlen(filename) > 0) {
+               if ((pf = fopen(filename,"rb+")) == NULL) {
+                       PrintAndLog("Error: Could not open file [%s]",filename);
+                       return 1;
+               }
+               file_given = true;
+               if (fread(c.d.asBytes,8*60,1,pf) == 0) {
+      PrintAndLog("Error: File reading error");
+      fclose(pf);
+                       return 1;
+        }
+               fclose(pf);
+       } else {
+               file_given = false;
+       }
+       
+       //file with all the challenges to try
+       c.arg[0] = (uint32_t)file_given;
+
+  SendCommand(&c);
+  return 0;
+}
+
+
+int CmdLFHitagWP(const char *Cmd) {
+       UsbCommand c = { CMD_WR_HITAG_S };
+       hitag_data* htd = (hitag_data*)c.d.asBytes;
+       hitag_function htf = param_get32ex(Cmd,0,0,10);
+       switch (htf) {
+               case 03: { //WHTSF_CHALLENGE
+                       num_to_bytes(param_get64ex(Cmd,1,0,16),8,htd->auth.NrAr);
+                       c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
+                       num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->auth.data);
+               } break;
+               case 04: { //WHTSF_KEY
+                       num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key);
+                       c.arg[2]= param_get32ex(Cmd, 2, 0, 10);
+                       num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->crypto.data);
+
+               } break;
+               default: {
+                       PrintAndLog("Error: unkown writer function %d",htf);
+                       PrintAndLog("Hitag writer functions");
+                       PrintAndLog(" HitagS (0*)");
+                       PrintAndLog("  03 <nr,ar> (Challenge) <page> <byte0...byte3> write page on a Hitag S tag");
+                       PrintAndLog("  04 <key> (set to 0 if no authentication is needed) <page> <byte0...byte3> write page on a Hitag S tag");
+                       PrintAndLog(" Hitag1 (1*)");
+                       PrintAndLog(" Hitag2 (2*)");
+                       return 1;
+               } break;
+       }
+       // Copy the hitag function into the first argument
+       c.arg[0] = htf;
+
+  // Send the command to the proxmark
+  SendCommand(&c);
+  
+  UsbCommand resp;
+  WaitForResponse(CMD_ACK,&resp);
+  
+  // Check the return status, stored in the first argument
+  if (resp.arg[0] == false) return 1;
+  return 0;
+}
+
+
 static command_t CommandTable[] = 
 {
-  {"help",    CmdHelp,           1, "This help"},
-  {"list",    CmdLFHitagList,    1, "<outfile> List Hitag trace history"},
-  {"reader",  CmdLFHitagReader,  1, "Act like a Hitag Reader"},
-  {"sim",     CmdLFHitagSim,     1, "<infile> Simulate Hitag transponder"},
-  {"snoop",   CmdLFHitagSnoop,   1, "Eavesdrop Hitag communication"},
-               {NULL, NULL, 0, NULL}
+  {"help",             CmdHelp,           1, "This help"},
+  {"list",             CmdLFHitagList,    1, "<outfile> List Hitag trace history"},
+  {"reader",           CmdLFHitagReader,  1, "Act like a Hitag Reader"},
+  {"sim",              CmdLFHitagSim,     1, "<infile> Simulate Hitag transponder"},
+  {"snoop",            CmdLFHitagSnoop,   1, "Eavesdrop Hitag communication"},
+  {"writer",                   CmdLFHitagWP,      1, "Act like a Hitag Writer" },
+  {"simS",             CmdLFHitagSimS,    1, "<hitagS.hts> Simulate HitagS transponder" }, 
+  {"checkChallenges",  CmdLFHitagCheckChallenges,   1, "<challenges.cc> test all challenges" }, {
+                               NULL,NULL, 0, NULL }
 };
 
 int CmdLFHitag(const char *Cmd)
diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c
new file mode 100644 (file)
index 0000000..abae165
--- /dev/null
@@ -0,0 +1,263 @@
+//-----------------------------------------------------------------------------
+//
+// 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 Presco tag commands
+//-----------------------------------------------------------------------------
+#include <string.h>
+#include <inttypes.h>
+#include "cmdlfpresco.h"
+#include "proxmark3.h"
+#include "ui.h"
+#include "util.h"
+#include "graph.h"
+#include "cmdparser.h"
+#include "cmddata.h"
+#include "cmdmain.h"
+#include "cmdlf.h"
+#include "protocols.h"  // for T55xx config register definitions
+#include "lfdemod.h"    // parityTest
+
+static int CmdHelp(const char *Cmd);
+
+int usage_lf_presco_clone(void){
+       PrintAndLog("clone a Presco tag to a T55x7 tag.");
+       PrintAndLog("Usage: lf presco clone d <Card-ID> H <hex-ID> <Q5>");
+       PrintAndLog("Options :");
+       PrintAndLog("  d <Card-ID>   : 9 digit presco card ID");
+       PrintAndLog("  H <hex-ID>    : 8 digit hex card number");
+       PrintAndLog("  <Q5>          : specify write to Q5 (t5555 instead of t55x7)");
+       PrintAndLog("");
+       PrintAndLog("Sample  : lf presco clone d 123456789");
+       return 0;
+}
+
+int usage_lf_presco_sim(void) {
+       PrintAndLog("Enables simulation of presco card with specified card number.");
+       PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
+       PrintAndLog("Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated.");
+       PrintAndLog("");
+       PrintAndLog("Usage:  lf presco sim d <Card-ID> or H <hex-ID>");
+       PrintAndLog("Options :");
+       PrintAndLog("  d <Card-ID>   : 9 digit presco card number");
+       PrintAndLog("  H <hex-ID>    : 8 digit hex card number");
+       PrintAndLog("");
+       PrintAndLog("Sample  : lf presco sim d 123456789");
+       return 0;
+}
+
+// convert base 12 ID to sitecode & usercode & 8 bit other unknown code
+int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5) {
+
+       uint8_t val = 0;
+       bool hex = false, errors = false;
+       uint8_t cmdp = 0;
+       char id[11];
+       int stringlen = 0;
+       while(param_getchar(Cmd, cmdp) != 0x00) {
+               switch(param_getchar(Cmd, cmdp)) {
+                       case 'h':
+                               return -1;
+                       case 'H':
+                               hex = true;
+                               //get hex
+                               *fullcode = param_get32ex(Cmd, cmdp+1, 0, 10);
+                               cmdp+=2;
+                               break;
+                       case 'P':
+                       case 'p':
+                               //param get string int param_getstr(const char *line, int paramnum, char * str)
+                               stringlen = param_getstr(Cmd, cmdp+1, id);
+                               if (stringlen < 2) return -1;
+                               cmdp+=2;
+                               break;
+                       case 'Q':
+                       case 'q':
+                               *Q5 = true;
+                               cmdp++;
+                               break;
+                       default:
+                               PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
+                               errors = 1;
+                               break;
+               }
+               if(errors) break;
+       }
+       // No args
+       if(cmdp == 0) errors = 1;
+
+       //Validations
+       if(errors) return -1;
+
+       if (!hex) {
+               for (int index =0; index < strlen(id); ++index) {
+                       // Get value from number string.
+                       if ( id[index] == '*' ) val = 10;
+                       if ( id[index] == '#')  val = 11;               
+                       if ( id[index] >= 0x30 && id[index] <= 0x39 )
+                               val = id[index] - 0x30;
+                       
+                       *fullcode += val;
+                       
+                       // last digit is only added, not multipled.
+                       if ( index < strlen(id)-1 ) 
+                               *fullcode *= 12;
+               }
+       }
+
+       *usercode = *fullcode & 0x0000FFFF; //% 65566
+       *sitecode = (*fullcode >> 24) & 0x000000FF;  // /= 16777216;
+       return 0;
+}
+
+// calc not certain - intended to get bitstream for programming / sim
+int GetPrescoBits(uint32_t fullcode, uint8_t *prescoBits) {
+       num_to_bytebits(0x10D00000, 32, prescoBits);
+       num_to_bytebits(0x00000000, 32, prescoBits+32);
+       num_to_bytebits(0x00000000, 32, prescoBits+64);
+       num_to_bytebits(fullcode  , 32, prescoBits+96);
+       return 1;
+}
+
+//see ASKDemod for what args are accepted
+int CmdPrescoDemod(const char *Cmd) {
+       if (!ASKDemod(Cmd, false, false, 1)) {
+               if (g_debugMode) PrintAndLog("ASKDemod failed");
+               return 0;
+       }
+       size_t size = DemodBufferLen;
+       //call lfdemod.c demod for Viking
+       int ans = PrescoDemod(DemodBuffer, &size);
+       if (ans < 0) {
+               if (g_debugMode) PrintAndLog("Error Presco_Demod %d", ans);
+               return 0;
+       }
+       //got a good demod
+       uint32_t raw1 = bytebits_to_byte(DemodBuffer+ans, 32);
+       uint32_t raw2 = bytebits_to_byte(DemodBuffer+ans+32, 32);
+       uint32_t raw3 = bytebits_to_byte(DemodBuffer+ans+64, 32);
+       uint32_t raw4 = bytebits_to_byte(DemodBuffer+ans+96, 32);
+       uint32_t cardid = raw4;
+       PrintAndLog("Presco Tag Found: Card ID %08X", cardid);
+       PrintAndLog("Raw: %08X%08X%08X%08X", raw1,raw2,raw3,raw4);
+       setDemodBuf(DemodBuffer+ans, 128, 0);
+       
+       uint32_t sitecode = 0, usercode = 0, fullcode = 0;
+       bool Q5=false;
+       char cmd[12] = {0};
+       sprintf(cmd, "H %08X", cardid);
+       GetWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5);
+       PrintAndLog("SiteCode %u, UserCode %u, FullCode, %08X", sitecode, usercode, fullcode);
+
+       return 1;
+}
+
+//see ASKDemod for what args are accepted
+int CmdPrescoRead(const char *Cmd) {
+       // Presco Number: 123456789 --> Sitecode 30 | usercode 8665
+
+       // read lf silently
+       CmdLFRead("s");
+       // get samples silently
+       getSamples("30000",false);
+       // demod and output Presco ID   
+       return CmdPrescoDemod(Cmd);
+}
+
+// takes base 12 ID converts to hex
+// Or takes 8 digit hex ID
+int CmdPrescoClone(const char *Cmd) {
+
+       bool Q5 = false;
+       uint32_t sitecode=0, usercode=0, fullcode=0;
+       uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4<<T55x7_MAXBLOCK_SHIFT | T55x7_ST_TERMINATOR, 0, 0, 0, 5};
+       
+       // get wiegand from printed number.
+       if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone();
+
+       if (Q5)
+               blocks[0] = T5555_MODULATION_MANCHESTER | 32<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT | T5555_ST_TERMINATOR;
+
+       if ((sitecode & 0xFF) != sitecode) {
+               sitecode &= 0xFF;
+               PrintAndLog("Facility-Code Truncated to 8-bits (Presco): %u", sitecode);
+       }
+
+       if ((usercode & 0xFFFF) != usercode) {
+               usercode &= 0xFFFF;
+               PrintAndLog("Card Number Truncated to 16-bits (Presco): %u", usercode);
+       }
+       
+       blocks[1] = 0x10D00000; //preamble
+       blocks[2] = 0x00000000;
+       blocks[3] = 0x00000000;
+       blocks[4] = fullcode;
+
+       PrintAndLog("Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode);
+       PrintAndLog("Blk | Data ");
+       PrintAndLog("----+------------");
+       PrintAndLog(" 00 | 0x%08x", blocks[0]);
+       PrintAndLog(" 01 | 0x%08x", blocks[1]);
+       PrintAndLog(" 02 | 0x%08x", blocks[2]);
+       PrintAndLog(" 03 | 0x%08x", blocks[3]); 
+       PrintAndLog(" 04 | 0x%08x", blocks[4]); 
+
+       UsbCommand resp;
+       UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
+
+       for (int i=4; i>=0; i--) {
+               c.arg[0] = blocks[i];
+               c.arg[1] = i;
+               clearCommandBuffer();
+               SendCommand(&c);
+               if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
+                       PrintAndLog("Error occurred, device did not respond during write operation.");
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+// takes base 12 ID converts to hex
+// Or takes 8 digit hex ID
+int CmdPrescoSim(const char *Cmd) {
+       uint32_t sitecode=0, usercode=0, fullcode=0;
+       bool Q5=false;
+       // get wiegand from printed number.
+       if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_sim();
+
+       uint8_t clk = 32, encoding = 1, separator = 1, invert = 0;
+       uint16_t arg1, arg2;
+       size_t size = 128;
+       arg1 = clk << 8 | encoding;
+       arg2 = invert << 8 | separator;
+
+       PrintAndLog("Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X",sitecode, usercode, fullcode);
+
+       UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}};
+       GetPrescoBits(fullcode, c.d.asBytes);
+       clearCommandBuffer();
+       SendCommand(&c);
+       return 0;
+}
+
+static command_t CommandTable[] = {
+       {"help",  CmdHelp,        1, "This help"},
+       {"read",  CmdPrescoRead,  0, "Attempt to read and Extract tag data"},
+       {"clone", CmdPrescoClone, 0, "d <9 digit ID> or h <hex> [Q5] clone presco tag"},
+       {"sim",   CmdPrescoSim,   0, "d <9 digit ID> or h <hex> simulate presco tag"},
+       {NULL, NULL, 0, NULL}
+};
+
+int CmdLFPresco(const char *Cmd) {
+       clearCommandBuffer();
+    CmdsParse(CommandTable, Cmd);
+    return 0;
+}
+
+int CmdHelp(const char *Cmd) {
+    CmdsHelp(CommandTable);
+    return 0;
+}
diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h
new file mode 100644 (file)
index 0000000..801df8a
--- /dev/null
@@ -0,0 +1,24 @@
+//-----------------------------------------------------------------------------
+//
+// 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 T55xx commands
+//-----------------------------------------------------------------------------
+#ifndef CMDLFPRESCO_H__
+#define CMDLFPRESCO_H__
+
+#include <stdint.h>  //uint_32+
+#include <stdbool.h> //bool
+
+int CmdLFPresco(const char *Cmd);
+int CmdPrescoClone(const char *Cmd);
+int CmdPrescoSim(const char *Cmd);
+
+int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5);
+
+int usage_lf_presco_clone(void);
+int usage_lf_presco_sim(void);
+#endif
+
diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c
new file mode 100644 (file)
index 0000000..7c19fbd
--- /dev/null
@@ -0,0 +1,199 @@
+//-----------------------------------------------------------------------------
+//
+// 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 Farpoint / Pyramid tag commands
+//-----------------------------------------------------------------------------
+#include <string.h>
+#include <inttypes.h>
+#include "cmdlfpyramid.h"
+#include "proxmark3.h"
+#include "ui.h"
+#include "util.h"
+#include "graph.h"
+#include "cmdparser.h"
+#include "cmddata.h"
+#include "cmdmain.h"
+#include "cmdlf.h"
+#include "protocols.h"  // for T55xx config register definitions
+#include "lfdemod.h"    // parityTest
+#include "crc.h"
+
+static int CmdHelp(const char *Cmd);
+
+int usage_lf_pyramid_clone(void){
+       PrintAndLog("clone a Farpointe/Pyramid tag to a T55x7 tag.");
+       PrintAndLog("The facility-code is 8-bit and the card number is 16-bit.  Larger values are truncated. ");
+       PrintAndLog("Currently work only on 26bit");
+       PrintAndLog("");
+       PrintAndLog("Usage: lf pyramid clone <Facility-Code> <Card-Number>");
+       PrintAndLog("Options :");
+       PrintAndLog("  <Facility-Code> :  8-bit value facility code");
+       PrintAndLog("  <Card Number>   : 16-bit value card number");
+       PrintAndLog("  Q5              : optional - clone to Q5 (T5555) instead of T55x7 chip");
+       PrintAndLog("");
+       PrintAndLog("Sample  : lf pyramid clone 123 11223");
+       return 0;
+}
+
+int usage_lf_pyramid_sim(void) {
+       PrintAndLog("Enables simulation of Farpointe/Pyramid card with specified card number.");
+       PrintAndLog("Simulation runs until the button is pressed or another USB command is issued.");
+       PrintAndLog("The facility-code is 8-bit and the card number is 16-bit.  Larger values are truncated.");
+       PrintAndLog("Currently work only on 26bit");
+       PrintAndLog("");
+       PrintAndLog("Usage:  lf pyramid sim <Card-Number>");
+       PrintAndLog("Options :");
+       PrintAndLog("  <Facility-Code> :  8-bit value facility code");
+       PrintAndLog("  <Card Number>   : 16-bit value card number");
+       PrintAndLog("");
+       PrintAndLog("Sample  : lf pyramid sim 123 11223");
+       return 0;
+}
+
+// Works for 26bits.
+int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) {
+
+       uint8_t pre[128];
+       memset(pre, 0x00, sizeof(pre));
+
+       // format start bit
+       pre[79] = 1;
+       
+       // Get 26 wiegand from FacilityCode, CardNumber 
+       uint8_t wiegand[24];
+       memset(wiegand, 0x00, sizeof(wiegand));
+       num_to_bytebits(fc, 8, wiegand);
+       num_to_bytebits(cn, 16, wiegand+8);
+
+       // add wiegand parity bits (dest, source, len)
+       wiegand_add_parity(pre+80, wiegand, 24);
+       
+       // add paritybits       (bitsource, dest, sourcelen, paritylen, parityType (odd, even,)
+       addParity(pre+8, pyramidBits+8, 102, 8, 1);
+
+       // add checksum         
+       uint8_t csBuff[13];
+       for (uint8_t i = 0; i < 13; i++)
+               csBuff[i] = bytebits_to_byte(pyramidBits + 16 + (i*8), 8);
+
+       uint32_t crc = CRC8Maxim(csBuff, 13);
+       num_to_bytebits(crc, 8, pyramidBits+120);
+       return 1;
+}
+
+int CmdPyramidRead(const char *Cmd) {
+       CmdLFRead("s");
+       getSamples("30000",false);
+       return CmdFSKdemodPyramid("");
+}
+
+int CmdPyramidClone(const char *Cmd) {
+
+       char cmdp = param_getchar(Cmd, 0);
+       if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_clone();
+
+       uint32_t facilitycode=0, cardnumber=0, fc = 0, cn = 0;
+       uint32_t blocks[5];
+       uint8_t i;
+       uint8_t bs[128];
+       memset(bs, 0x00, sizeof(bs));
+
+       if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_clone();
+
+       facilitycode = (fc & 0x000000FF);
+       cardnumber = (cn & 0x0000FFFF);
+       
+       if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
+               PrintAndLog("Error with tag bitstream generation.");
+               return 1;
+       }
+
+       //Pyramid - compat mode, FSK2a, data rate 50, 4 data blocks
+       blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 4<<T55x7_MAXBLOCK_SHIFT;
+
+       if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q')
+               blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 50<<T5555_BITRATE_SHIFT | 4<<T5555_MAXBLOCK_SHIFT;
+
+       blocks[1] = bytebits_to_byte(bs,32);
+       blocks[2] = bytebits_to_byte(bs+32,32);
+       blocks[3] = bytebits_to_byte(bs+64,32);
+       blocks[4] = bytebits_to_byte(bs+96,32);
+
+       PrintAndLog("Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber);
+       PrintAndLog("Blk | Data ");
+       PrintAndLog("----+------------");
+       for ( i = 0; i<5; ++i )
+               PrintAndLog(" %02d | %08" PRIx32, i, blocks[i]);
+
+       UsbCommand resp;
+       UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}};
+
+       for ( i = 0; i<5; ++i ) {
+               c.arg[0] = blocks[i];
+               c.arg[1] = i;
+               clearCommandBuffer();
+               SendCommand(&c);
+               if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)){
+                       PrintAndLog("Error occurred, device did not respond during write operation.");
+                       return -1;
+               }
+       }
+       return 0;
+}
+
+int CmdPyramidSim(const char *Cmd) {
+
+       char cmdp = param_getchar(Cmd, 0);
+       if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_sim();
+
+       uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0;
+
+       uint8_t bs[128];
+       size_t size = sizeof(bs);
+       memset(bs, 0x00, size);
+
+       // Pyramid uses:  fcHigh: 10, fcLow: 8, clk: 50, invert: 0
+       uint64_t arg1, arg2;
+       arg1 = (10 << 8) + 8;
+       arg2 = 50 | 0;
+
+       if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_sim();
+
+       facilitycode = (fc & 0x000000FF);
+       cardnumber = (cn & 0x0000FFFF);
+
+       if ( !GetPyramidBits(facilitycode, cardnumber, bs)) {
+               PrintAndLog("Error with tag bitstream generation.");
+               return 1;
+       }
+
+       PrintAndLog("Simulating Farpointe/Pyramid - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber );
+
+       UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}};
+       memcpy(c.d.asBytes, bs, size);
+       clearCommandBuffer();
+       SendCommand(&c);
+       return 0;
+}
+
+static command_t CommandTable[] = {
+       {"help",  CmdHelp,         1, "This help"},
+       {"read",  CmdPyramidRead,  0, "Attempt to read and extract tag data"},
+       {"clone", CmdPyramidClone, 0, "<Facility-Code> <Card Number>  clone pyramid tag"},
+       {"sim",   CmdPyramidSim,   0, "<Facility-Code> <Card Number>  simulate pyramid tag"},
+       {NULL, NULL, 0, NULL}
+};
+
+int CmdLFPyramid(const char *Cmd) {
+       clearCommandBuffer();
+       CmdsParse(CommandTable, Cmd);
+       return 0;
+}
+
+int CmdHelp(const char *Cmd) {
+       CmdsHelp(CommandTable);
+       return 0;
+}
diff --git a/client/cmdlfpyramid.h b/client/cmdlfpyramid.h
new file mode 100644 (file)
index 0000000..73e8338
--- /dev/null
@@ -0,0 +1,19 @@
+//-----------------------------------------------------------------------------
+//
+// 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 T55xx commands
+//-----------------------------------------------------------------------------
+#ifndef CMDLFPYRAMID_H__
+#define CMDLFPYRAMID_H__
+
+int CmdLFPyramid(const char *Cmd);
+int CmdPyramidClone(const char *Cmd);
+int CmdPyramidSim(const char *Cmd);
+
+int usage_lf_pyramid_clone(void);
+int usage_lf_pyramid_sim(void);
+#endif
+
index dfee9aa6dc46abc80889193c0e334143b5b224db..9e4883c759b55240b8ce052baf6f150271dbecf4 100644 (file)
@@ -48,6 +48,7 @@ int usage_t55xx_config(){
        PrintAndLog("       i [1]                         Invert data signal, defaults to normal");\r
        PrintAndLog("       o [offset]                    Set offset, where data should start decode in bitstream");\r
        PrintAndLog("       Q5                            Set as Q5(T5555) chip instead of T55x7");\r
+       PrintAndLog("       ST                            Set Sequence Terminator on");\r
        PrintAndLog("");\r
        PrintAndLog("Examples:");\r
        PrintAndLog("      lf t55xx config d FSK          - FSK demodulation");\r
@@ -75,7 +76,7 @@ int usage_t55xx_read(){
        return 0;\r
 }\r
 int usage_t55xx_write(){\r
-       PrintAndLog("Usage:  lf t55xx wr [b <block>] [d <data>] [p <password>] [1]");\r
+       PrintAndLog("Usage:  lf t55xx write [b <block>] [d <data>] [p <password>] [1]");\r
        PrintAndLog("Options:");\r
        PrintAndLog("     b <block>    - block number to write. Between 0-7");\r
        PrintAndLog("     d <data>     - 4 bytes of data to write (8 hex characters)");\r
@@ -83,8 +84,8 @@ int usage_t55xx_write(){
        PrintAndLog("     1            - OPTIONAL write Page 1 instead of Page 0");\r
        PrintAndLog("");\r
        PrintAndLog("Examples:");\r
-       PrintAndLog("      lf t55xx wr b 3 d 11223344            - write 11223344 to block 3");\r
-       PrintAndLog("      lf t55xx wr b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef");\r
+       PrintAndLog("      lf t55xx write b 3 d 11223344            - write 11223344 to block 3");\r
+       PrintAndLog("      lf t55xx write b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef");\r
        PrintAndLog("");\r
        return 0;\r
 }\r
@@ -270,6 +271,11 @@ int CmdT55xxSetConfig(const char *Cmd) {
                        config.Q5 = TRUE;\r
                        cmdp++;\r
                        break;\r
+               case 'S':\r
+               case 's':               \r
+                       config.ST = TRUE;\r
+                       cmdp++;\r
+                       break;\r
                default:\r
                        PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));\r
                        errors = TRUE;\r
@@ -370,6 +376,7 @@ bool DecodeT55xxBlock(){
        char buf[30] = {0x00};\r
        char *cmdStr = buf;\r
        int ans = 0;\r
+       bool ST = config.ST;\r
        uint8_t bitRate[8] = {8,16,32,40,50,64,100,128};\r
        DemodBufferLen = 0x00;\r
 \r
@@ -390,7 +397,7 @@ bool DecodeT55xxBlock(){
                        break;\r
                case DEMOD_ASK:\r
                        snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted );\r
-                       ans = ASKDemod(cmdStr, FALSE, FALSE, 1);\r
+                       ans = ASKDemod_ext(cmdStr, FALSE, FALSE, 1, &ST);\r
                        break;\r
                case DEMOD_PSK1:\r
                        // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise)\r
@@ -482,7 +489,6 @@ bool tryDetectModulation(){
        t55xx_conf_block_t tests[15];\r
        int bitRate=0;\r
        uint8_t fc1 = 0, fc2 = 0, clk=0;\r
-\r
        if (GetFskClock("", FALSE, FALSE)){ \r
                fskClocks(&fc1, &fc2, &clk, FALSE);\r
                if ( FSKrawDemod("0 0", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
@@ -494,6 +500,7 @@ bool tryDetectModulation(){
                        tests[hits].bitrate = bitRate;\r
                        tests[hits].inverted = FALSE;\r
                        tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                       tests[hits].ST = FALSE;\r
                        ++hits;\r
                }\r
                if ( FSKrawDemod("0 1", FALSE) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
@@ -505,19 +512,22 @@ bool tryDetectModulation(){
                        tests[hits].bitrate = bitRate;\r
                        tests[hits].inverted = TRUE;\r
                        tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                       tests[hits].ST = FALSE;\r
                        ++hits;\r
                }\r
        } else {\r
                clk = GetAskClock("", FALSE, FALSE);\r
                if (clk>0) {\r
-                       if ( ASKDemod("0 0 1", FALSE, FALSE, 1) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
+                       tests[hits].ST = TRUE;\r
+                       if ( ASKDemod_ext("0 0 1", FALSE, FALSE, 1, &tests[hits].ST) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
                                tests[hits].modulation = DEMOD_ASK;\r
                                tests[hits].bitrate = bitRate;\r
                                tests[hits].inverted = FALSE;\r
                                tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
                                ++hits;\r
                        }\r
-                       if ( ASKDemod("0 1 1", FALSE, FALSE, 1)  && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
+                       tests[hits].ST = TRUE;\r
+                       if ( ASKDemod_ext("0 1 1", FALSE, FALSE, 1, &tests[hits].ST)  && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
                                tests[hits].modulation = DEMOD_ASK;\r
                                tests[hits].bitrate = bitRate;\r
                                tests[hits].inverted = TRUE;\r
@@ -529,6 +539,7 @@ bool tryDetectModulation(){
                                tests[hits].bitrate = bitRate;\r
                                tests[hits].inverted = FALSE;\r
                                tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                               tests[hits].ST = FALSE;\r
                                ++hits;\r
                        }\r
                        if ( ASKbiphaseDemod("0 0 1 2", FALSE) && test(DEMOD_BIa, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5) ) {\r
@@ -536,6 +547,7 @@ bool tryDetectModulation(){
                                tests[hits].bitrate = bitRate;\r
                                tests[hits].inverted = TRUE;\r
                                tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                               tests[hits].ST = FALSE;\r
                                ++hits;\r
                        }\r
                }\r
@@ -548,6 +560,7 @@ bool tryDetectModulation(){
                                tests[hits].bitrate = bitRate;\r
                                tests[hits].inverted = FALSE;\r
                                tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                               tests[hits].ST = FALSE;\r
                                ++hits;\r
                        }\r
 \r
@@ -556,6 +569,7 @@ bool tryDetectModulation(){
                                tests[hits].bitrate = bitRate;\r
                                tests[hits].inverted = TRUE;\r
                                tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                               tests[hits].ST = FALSE;\r
                                ++hits;\r
                        }\r
                }\r
@@ -571,6 +585,7 @@ bool tryDetectModulation(){
                                tests[hits].bitrate = bitRate;\r
                                tests[hits].inverted = FALSE;\r
                                tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                               tests[hits].ST = FALSE;\r
                                ++hits;\r
                        }\r
                        if ( PSKDemod("0 1 6", FALSE) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) {\r
@@ -578,6 +593,7 @@ bool tryDetectModulation(){
                                tests[hits].bitrate = bitRate;\r
                                tests[hits].inverted = TRUE;\r
                                tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                               tests[hits].ST = FALSE;\r
                                ++hits;\r
                        }\r
                        // PSK2 - needs a call to psk1TOpsk2.\r
@@ -588,6 +604,7 @@ bool tryDetectModulation(){
                                        tests[hits].bitrate = bitRate;\r
                                        tests[hits].inverted = FALSE;\r
                                        tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                                       tests[hits].ST = FALSE;\r
                                        ++hits;\r
                                }\r
                        } // inverse waves does not affect this demod\r
@@ -599,6 +616,7 @@ bool tryDetectModulation(){
                                        tests[hits].bitrate = bitRate;\r
                                        tests[hits].inverted = FALSE;\r
                                        tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer);\r
+                                       tests[hits].ST = FALSE;\r
                                        ++hits;\r