]> cvs.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge branch 'master' of https://github.com/Proxmark/proxmark3
authoriceman1001 <iceman@iuse.se>
Tue, 24 Mar 2015 10:45:31 +0000 (11:45 +0100)
committericeman1001 <iceman@iuse.se>
Tue, 24 Mar 2015 10:45:31 +0000 (11:45 +0100)
Conflicts:
armsrc/lfops.c
client/cmddata.c
client/cmdlf.c
client/cmdlft55xx.c
client/cmdlft55xx.h
client/scripts/test_t55x7_bi.lua

22 files changed:
1  2 
armsrc/BigBuf.c
armsrc/Makefile
armsrc/appmain.c
armsrc/apps.h
armsrc/iso14443a.c
armsrc/iso14443a.h
armsrc/lfops.c
armsrc/mifarecmd.c
armsrc/mifaredesfire.c
client/Makefile
client/cmddata.h
client/cmdhf.c
client/cmdhf14a.c
client/cmdhfmfdes.c
client/cmdhfmfu.c
client/cmdhfmfu.h
client/cmdlf.c
client/scripts/test_t55x7_bi.lua
common/Makefile.common
common/lfdemod.c
common/protocols.h
include/mifare.h

diff --combined armsrc/BigBuf.c
index 703ade658da348db04f80b2824269a32c738cb55,703ade658da348db04f80b2824269a32c738cb55..2fb50a47ea2e4cee910a84c333f4f90d28153ece
@@@ -171,18 -171,18 +171,19 @@@ bool RAMFUNC LogTrace(const uint8_t *bt
        traceLen += iLen;
  
        // parity bytes
--      if (parity != NULL && iLen != 0) {
++      if (iLen != 0) {
++              if (parity != NULL) {
                memcpy(trace + traceLen, parity, num_paritybytes);
++              } else {
++                      memset(trace + traceLen, 0x00, num_paritybytes);
++              }
        }
        traceLen += num_paritybytes;
  
--      if(traceLen +4 < max_traceLen)
--      {       //If it hadn't been cleared, for whatever reason..
--              memset(trace+traceLen,0x44, 4);
--      }
--
        return TRUE;
  }
++
++
  int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag)
  {
        /**
  
        return TRUE;
  }
++
++
  // Emulator memory
  uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){
        uint8_t* mem = BigBuf_get_EM_addr();
diff --combined armsrc/Makefile
index 14ddbc056b2aad5b7d4499eff5004c11bec96ed6,75ccdece2c3b130d395d83e677ae5c90a7bf4e3e..1c03e5a3b17275124dcb3070e69c5a774d38ba1a
@@@ -10,7 -10,7 +10,7 @@@ APP_INCLUDES = apps.
  
  #remove one of the following defines and comment out the relevant line
  #in the next section to remove that particular feature from compilation  
 -APP_CFLAGS    = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG  -DWITH_CRC -DON_DEVICE -fno-strict-aliasing
 +APP_CFLAGS    = -DWITH_LF -DWITH_ISO15693 -DWITH_ISO14443a -DWITH_ISO14443b -DWITH_ICLASS -DWITH_LEGICRF -DWITH_HITAG  -DWITH_CRC -DON_DEVICE -fno-strict-aliasing -O2
  #-DWITH_LCD 
  
  #SRC_LCD = fonts.c LCD.c
@@@ -18,7 -18,7 +18,7 @@@ SRC_LF = lfops.c hitag2.c lfsampling.
  SRC_ISO15693 = iso15693.c iso15693tools.c
  SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c
  SRC_ISO14443b = iso14443.c
--SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c 
++SRC_CRAPTO1 = crapto1.c crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c
  SRC_CRC = iso14443crc.c crc.c crc16.c crc32.c 
  
  THUMBSRC = start.c \
@@@ -45,7 -45,6 +45,7 @@@ ARMSRC = fpgaloader.c 
        BigBuf.c \
        optimized_cipher.c
  
 +
  # stdint.h provided locally until GCC 4.5 becomes C99 compliant
  APP_CFLAGS += -I.
  
diff --combined armsrc/appmain.c
index f6c979784a28a6b5c7e1df174d45ac6f09ffa740,6e0b58b3da84fa7bc3e2463c47fd10bc285a9eb8..4e12c94df55f3b1e54840a716316127d855e512c
  // executes.
  //-----------------------------------------------------------------------------
  
 -#include "usb_cdc.h"
 -#include "cmd.h"
 +#include "../common/usb_cdc.h"
 +#include "../common/cmd.h"
  
 -#include "proxmark3.h"
 +#include "../include/proxmark3.h"
  #include "apps.h"
  #include "util.h"
  #include "printf.h"
  #include "string.h"
 -
  #include <stdarg.h>
  
  #include "legicrf.h"
 -#include <hitag2.h>
 +#include "../include/hitag2.h"
  #include "lfsampling.h"
  #include "BigBuf.h"
  #ifdef WITH_LCD
@@@ -179,7 -180,7 +179,7 @@@ void MeasureAntennaTuning(void
        int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0 
        int vLf125 = 0, vLf134 = 0, vHf = 0;    // in mV
  
 -      LED_B_ON();
 +  LED_B_ON();
  
  /*
   * Sweeps the useful LF range of the proxmark from
  
        for (i=18; i >= 0; i--) LF_Results[i] = 0;
        
 -      LED_A_ON();
 +  LED_A_ON();
        // Let the FPGA drive the high-frequency antenna around 13.56 MHz.
        FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
  
        cmd_send(CMD_MEASURED_ANTENNA_TUNING, vLf125 | (vLf134<<16), vHf, peakf | (peakv<<16), LF_Results, 256);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 -      LED_A_OFF();
 -      LED_B_OFF();
 -      return;
 +  LED_A_OFF();
 +  LED_B_OFF();
 +  return;
  }
  
  void MeasureAntennaTuningHf(void)
@@@ -369,7 -370,7 +369,7 @@@ void SamyRun(
        for (;;)
        {
                usb_poll();
 -    WDT_HIT();
 +              WDT_HIT();
  
                // Was our button held down or pressed?
                int button_pressed = BUTTON_HELD(1000);
@@@ -639,7 -640,7 +639,7 @@@ void UsbPacketReceived(uint8_t *packet
  {
        UsbCommand *c = (UsbCommand *)packet;
  
 -//  Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]);
 +  //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]);
    
        switch(c->cmd) {
  #ifdef WITH_LF
                        setSamplingConfig((sample_config *) c->d.asBytes);
                        break;
                case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K:
-                       cmd_send(CMD_ACK,SampleLF(),0,0,0,0);
+                       cmd_send(CMD_ACK,SampleLF(c->arg[0]),0,0,0,0);
                        break;
                case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K:
                        ModThenAcquireRawAdcSamples125k(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes);
                        WriteTItag(c->arg[0],c->arg[1],c->arg[2]);
                        break;
                case CMD_SIMULATE_TAG_125K:
 -                      LED_A_ON();
 -                      SimulateTagLowFrequency(c->arg[0], c->arg[1], 1);
 -                      LED_A_OFF();
 +                      SimulateTagLowFrequency(c->arg[0], c->arg[1], 0);
 +                      //SimulateTagLowFrequencyA(c->arg[0], c->arg[1]);
                        break;
                case CMD_LF_SIMULATE_BIDIR:
                        SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]);
                        EPA_PACE_Collect_Nonce(c);
                        break;
                        
 +              // case CMD_EPA_:
 +              //      EpaFoo(c);
 +              // break;
 +                      
                case CMD_READER_MIFARE:
              ReaderMifare(c->arg[0]);
                        break;
                        break;
                case CMD_MIFAREU_READCARD:
                        MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes);
 -                      break;
 +                        break;
                case CMD_MIFAREUC_READCARD:
                        MifareUReadCard(c->arg[0], c->arg[1], c->d.asBytes);
                        break;
                        ReaderIClass(c->arg[0]);
                        break;
                case CMD_READER_ICLASS_REPLAY:
 -                  ReaderIClass_Replay(c->arg[0], c->d.asBytes);
 +                      ReaderIClass_Replay(c->arg[0], c->d.asBytes);
                        break;
        case CMD_ICLASS_EML_MEMSET:
                        emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
@@@ -1042,7 -1040,7 +1042,7 @@@ void  __attribute__((noreturn)) AppMain
        LED_A_OFF();
  
        // Init USB device
 -  usb_enable();
 +      usb_enable();
  
        // The FPGA gets its clock from us from PCK0 output, so set that up.
        AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0;
        size_t rx_len;
    
        for(;;) {
 -    if (usb_poll()) {
 -      rx_len = usb_read(rx,sizeof(UsbCommand));
 -      if (rx_len) {
 -        UsbPacketReceived(rx,rx_len);
 -      }
 -    }
 +              if (usb_poll()) {
 +                      rx_len = usb_read(rx,sizeof(UsbCommand));
 +                      if (rx_len) {
 +                              UsbPacketReceived(rx,rx_len);
 +                      }
 +              }
                WDT_HIT();
  
  #ifdef WITH_LF
diff --combined armsrc/apps.h
index 3fe8acaece373079feaf6286b97bcf65bc7e7ecc,928a3075f44391c80e51f9ffc1f6d511225aa2ce..ea298acb0ccf6dcdd73c46703192484d93c741dc
  
  #include <stdint.h>
  #include <stddef.h>
 -#include "common.h"
 -#include "hitag2.h"
 -#include "mifare.h"
 +#include <stdlib.h>
 +#include <sys/types.h>
 +#include <string.h>
 +#include <strings.h>
  #include "../common/crc32.h"
  #include "BigBuf.h"
 +#include "../include/hitag2.h"
++#include "../include/mifare.h"
++//#include <openssl/des.h>
++//#include <openssl/aes.h>
++//#include "des.h"
++//#include "aes.h"
++#include "desfire.h"
++
  
  extern const uint8_t OddByteParity[256];
  extern int rsamples;   // = 0;
@@@ -118,9 -116,7 +125,9 @@@ void ReadTItag(void)
  void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
  void AcquireTiType(void);
  void AcquireRawBitsTI(void);
 -void SimulateTagLowFrequency(int period, int gap, int ledcontrol);
 +void SimulateTagLowFrequency( uint16_t period, uint32_t gap, uint8_t ledcontrol);
 +//void SimulateTagLowFrequencyA(int period, int gap);
 +
  void CmdHIDsimTAG(int hi, int lo, int ledcontrol);
  void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
  void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
@@@ -137,7 -133,6 +144,7 @@@ void CopyIndala224toT55x7(int uid1, in
  void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode);
  void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode );
  void T55xxReadTrace(void);
 +void TurnReadLFOn();
  int DemodPCF7931(uint8_t **outBlocks);
  int IsBlock0PCF7931(uint8_t *Block);
  int IsBlock1PCF7931(uint8_t *Block);
@@@ -170,7 -165,7 +177,7 @@@ void EPA_PACE_Collect_Nonce(UsbCommand 
  void ReaderMifare(bool first_try);
  int32_t dist_nt(uint32_t nt1, uint32_t nt2);
  void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data);
--void MifareUReadBlock(uint8_t arg0,uint8_t *datain);
++void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
  void MifareUC_Auth1(uint8_t arg0, uint8_t *datain);
  void MifareUC_Auth2(uint32_t arg0, uint8_t *datain);
  void MifareUReadCard(uint8_t arg0, int Pages, uint8_t *datain);
@@@ -207,6 -202,6 +214,17 @@@ void      OnError(uint8_t reason)
  
  
  
++// desfire_crypto.h
++void  *mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, off_t offset, int communication_settings);
++void    *mifare_cryto_postprocess_data (desfiretag_t tag, void *data, ssize_t *nbytes, int communication_settings);
++void    mifare_cypher_single_block (desfirekey_t  key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size);
++void    mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
++size_t  key_block_size (const desfirekey_t  key);
++size_t  padded_data_length (const size_t nbytes, const size_t block_size);
++size_t  maced_data_length (const desfirekey_t  key, const size_t nbytes);
++size_t  enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings);
++void    cmac_generate_subkeys (desfirekey_t key);
++void    cmac (const desfirekey_t  key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
  
  
  /// iso15693.h
diff --combined armsrc/iso14443a.c
index e7477789d287312fbf68ec4a417f4cbbfb7b01ee,ac839cfdc081049ac8ceccaa784c41306158c04e..9cd0cfdc9ceb8158a1cd5e5fe7238db5c58b3096
@@@ -213,6 -213,6 +213,12 @@@ void AppendCrc14443a(uint8_t* data, in
        ComputeCrc14443(CRC_14443_A,data,len,data+len,data+len+1);
  }
  
++void AppendCrc14443b(uint8_t* data, int len)
++{
++      ComputeCrc14443(CRC_14443_B,data,len,data+len,data+len+1);
++}
++
++
  //=============================================================================
  // ISO 14443 Type A - Miller decoder
  //=============================================================================
  static tUart Uart;
  
  // Lookup-Table to decide if 4 raw bits are a modulation.
--// We accept two or three consecutive "0" in any position with the rest "1"
++// We accept the following:
++// 0001  -   a 3 tick wide pause
++// 0011  -   a 2 tick wide pause, or a three tick wide pause shifted left
++// 0111  -   a 2 tick wide pause shifted left
++// 1001  -   a 2 tick wide pause shifted right
  const bool Mod_Miller_LUT[] = {
--      TRUE,  TRUE,  FALSE, TRUE,  FALSE, FALSE, FALSE, FALSE,
--      TRUE,  TRUE,  FALSE, FALSE, TRUE,  FALSE, FALSE, FALSE
++      FALSE,  TRUE, FALSE, TRUE,  FALSE, FALSE, FALSE, TRUE,
++      FALSE,  TRUE, FALSE, FALSE, FALSE, FALSE, FALSE, FALSE
  };
--#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x00F0) >> 4])
--#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x000F)])
++#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
++#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])
  
  void UartReset()
  {
        Uart.parityLen = 0;                                     // number of decoded parity bytes
        Uart.shiftReg = 0;                                      // shiftreg to hold decoded data bits
        Uart.parityBits = 0;                            // holds 8 parity bits
--      Uart.twoBits = 0x0000;                          // buffer for 2 Bits
--      Uart.highCnt = 0;
        Uart.startTime = 0;
        Uart.endTime = 0;
  }
@@@ -258,6 -258,6 +266,7 @@@ void UartInit(uint8_t *data, uint8_t *p
  {
        Uart.output = data;
        Uart.parity = parity;
++      Uart.fourBits = 0x00000000;                     // clear the buffer for 4 Bits
        UartReset();
  }
  
  static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
  {
  
--      Uart.twoBits = (Uart.twoBits << 8) | bit;
++      Uart.fourBits = (Uart.fourBits << 8) | bit;
        
        if (Uart.state == STATE_UNSYNCD) {                                                                                      // not yet synced
        
--              if (Uart.highCnt < 2) {                                                                                                 // wait for a stable unmodulated signal
--                      if (Uart.twoBits == 0xffff) {
--                              Uart.highCnt++;
--                      } else {
--                              Uart.highCnt = 0;
--                      }
--              } else {        
--                      Uart.syncBit = 0xFFFF;                                                                                          // not set
--                                                                                                                                                              // we look for a ...1111111100x11111xxxxxx pattern (the start bit)
--                      if              ((Uart.twoBits & 0xDF00) == 0x1F00) Uart.syncBit = 8;           // mask is   11x11111 xxxxxxxx, 
--                                                                                                                                                              // check for 00x11111 xxxxxxxx
--                      else if ((Uart.twoBits & 0xEF80) == 0x8F80) Uart.syncBit = 7;           // both masks shifted right one bit, left padded with '1'
--                      else if ((Uart.twoBits & 0xF7C0) == 0xC7C0) Uart.syncBit = 6;           // ...
--                      else if ((Uart.twoBits & 0xFBE0) == 0xE3E0) Uart.syncBit = 5;
--                      else if ((Uart.twoBits & 0xFDF0) == 0xF1F0) Uart.syncBit = 4;
--                      else if ((Uart.twoBits & 0xFEF8) == 0xF8F8) Uart.syncBit = 3;
--                      else if ((Uart.twoBits & 0xFF7C) == 0xFC7C) Uart.syncBit = 2;
--                      else if ((Uart.twoBits & 0xFFBE) == 0xFE3E) Uart.syncBit = 1;
--                      if (Uart.syncBit != 0xFFFF) {                                                                           // found a sync bit
++              Uart.syncBit = 9999;                                                                                                    // not set
++              // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
++              // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111)
++              // we therefore look for a ...xx11111111111100x11111xxxxxx... pattern 
++              // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
++#define ISO14443A_STARTBIT_MASK               0x07FFEF80                                                                      // mask is    00000111 11111111 11101111 10000000
++#define ISO14443A_STARTBIT_PATTERN    0x07FF8F80                                                                      // pattern is 00000111 11111111 10001111 10000000
++              if              ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7;
++              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6;
++              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5;
++              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4;
++              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3;
++              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2;
++              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1;
++              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0;
++
++              if (Uart.syncBit != 9999) {                                                                                             // found a sync bit
                                Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
                                Uart.startTime -= Uart.syncBit;
                                Uart.endTime = Uart.startTime;
                                Uart.state = STATE_START_OF_COMMUNICATION;
                        }
--              }
  
        } else {
  
--              if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) {                  
--                      if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) {          // Modulation in both halves - error
++              if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {                 
++                      if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) {         // Modulation in both halves - error
                                UartReset();
                        } else {                                                                                                                        // Modulation in first half = Sequence Z = logic "0"
                                if (Uart.state == STATE_MILLER_X) {                                                             // error - must not follow after X
                                }
                        }
                } else {
--                      if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) {          // Modulation second half = Sequence X = logic "1"
++                      if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) {         // Modulation second half = Sequence X = logic "1"
                                Uart.bitCount++;
                                Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100;                                   // add a 1 to the shiftreg
                                Uart.state = STATE_MILLER_X;
                                                return TRUE;                                                                                    // we are finished with decoding the raw data sequence
                                        } else {
                                                UartReset();                                                                                    // Nothing received - start over
--                                              Uart.highCnt = 1;
                                        }
                                }
                                if (Uart.state == STATE_START_OF_COMMUNICATION) {                               // error - must not follow directly after SOC
                                        UartReset();
--                                      Uart.highCnt = 1;
                                } else {                                                                                                                // a logic "0"
                                        Uart.bitCount++;
                                        Uart.shiftReg = (Uart.shiftReg >> 1);                                           // add a 0 to the shiftreg
@@@ -680,6 -680,6 +684,9 @@@ void RAMFUNC SnoopIso14443a(uint8_t par
  
                                        // And ready to receive another response.
                                        DemodReset();
++                                      // And reset the Miller decoder including itS (now outdated) input buffer
++                                      UartInit(receivedCmd, receivedCmdPar);
++
                                        LED_C_OFF();
                                } 
                                TagIsActive = (Demod.state != DEMOD_UNSYNCD);
@@@ -1337,7 -1337,7 +1344,7 @@@ void CodeIso14443aBitsAsReaderPar(cons
                }
  
                // Only transmit parity bit if we transmitted a complete byte
--              if (j == 8) {
++              if (j == 8 && parity != NULL) {
                        // Get the parity bit
                        if (parity[i>>3] & (0x80 >> (i&0x0007))) {
                                // Sequence X
@@@ -1631,6 -1631,6 +1638,7 @@@ static int GetIso14443aAnswerFromTag(ui
        }
  }
  
++
  void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing)
  {
        CodeIso14443aBitsAsReaderPar(frame, bits, par);
        }
  }
  
++
  void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing)
  {
    ReaderTransmitBitsPar(frame, len*8, par, timing);
  }
  
++
  void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
  {
    // Generate parity and redirect
    ReaderTransmitBitsPar(frame, len, par, timing);
  }
  
++
  void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing)
  {
    // Generate parity and redirect
@@@ -1719,6 -1719,6 +1730,11 @@@ int iso14443a_select_card(byte_t *uid_p
                memset(uid_ptr,0,10);
        }
  
++      // check for proprietary anticollision:
++      if ((resp[0] & 0x1F) == 0) {
++              return 3;
++      }
++      
        // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
        // which case we need to make a cascade 2 request and select - this is a long UID
        // While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
@@@ -1851,7 -1851,7 +1867,7 @@@ void iso14443a_setup(uint8_t fpga_minor
        DemodReset();
        UartReset();
        NextTransferTime = 2*DELAY_ARM2AIR_AS_READER;
--      iso14a_set_timeout(1050); // 10ms default
++      iso14a_set_timeout(50*106); // 10ms default
  }
  
  int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {
@@@ -1927,15 -1927,15 +1943,38 @@@ void ReaderIso14443a(UsbCommand *c
  
        if(param & ISO14A_RAW) {
                if(param & ISO14A_APPEND_CRC) {
++                      if(param & ISO14A_TOPAZMODE) {
++                              AppendCrc14443b(cmd,len);
++                      } else {
                        AppendCrc14443a(cmd,len);
++                      }
                        len += 2;
                        if (lenbits) lenbits += 16;
                }
--              if(lenbits>0) {
++              if(lenbits>0) {                         // want to send a specific number of bits (e.g. short commands)
++                      if(param & ISO14A_TOPAZMODE) {
++                              int bits_to_send = lenbits;
++                              uint16_t i = 0;
++                              ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL);             // first byte is always short (7bits) and no parity
++                              bits_to_send -= 7;
++                              while (bits_to_send > 0) {
++                                      ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL);     // following bytes are 8 bit and no parity
++                                      bits_to_send -= 8;
++                              }
++                      } else {
                        GetParity(cmd, lenbits/8, par);
--                      ReaderTransmitBitsPar(cmd, lenbits, par, NULL);
++                              ReaderTransmitBitsPar(cmd, lenbits, par, NULL);                                                 // bytes are 8 bit with odd parity
++                      }
++              } else {                                        // want to send complete bytes only
++                      if(param & ISO14A_TOPAZMODE) {
++                              uint16_t i = 0;
++                              ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL);                                                // first byte: 7 bits, no paritiy
++                              while (i < len) {
++                                      ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL);                                        // following bytes: 8 bits, no paritiy
++                              }
                } else {
--                      ReaderTransmit(cmd,len, NULL);
++                              ReaderTransmit(cmd,len, NULL);                                                                                  // 8 bits, odd parity
++                      }
                }
                arg0 = ReaderReceive(buf, par);
                cmd_send(CMD_ACK,arg0,0,0,buf,sizeof(buf));
@@@ -2302,6 -2302,8 +2341,8 @@@ void Mifare1ksim(uint8_t flags, uint8_
                } 
                if(cardSTATE == MFEMUL_NOFIELD) continue;
  
+               //Now, get data
                res = EmGetCmd(receivedCmd, &len, receivedCmd_par);
                if (res == 2) { //Field is off!
                        cardSTATE = MFEMUL_NOFIELD;
                                uint32_t nr = bytes_to_num(&receivedCmd[4], 4);
  
                                //Collect AR/NR
 -                              if(ar_nr_collected < 2){
 +                              if(ar_nr_collected < 2 && cardAUTHSC == 2){
                                        if(ar_nr_responses[2] != ar)
                                        {// Avoid duplicates... probably not necessary, ar should vary. 
                                                ar_nr_responses[ar_nr_collected*4] = cuid;
                                                ar_nr_responses[ar_nr_collected*4+2] = ar;
                                                ar_nr_responses[ar_nr_collected*4+3] = nr;
                                                ar_nr_collected++;
 +                                      }                                               
 +                                      // Interactive mode flag, means we need to send ACK
 +                                      if(flags & FLAG_INTERACTIVE && ar_nr_collected == 2)
 +                                      {
 +                                              finished = true;
                                        }
                                }
  
                                        mf_crypto1_encrypt(pcs, response, 18, response_par);
                                        EmSendCmdPar(response, 18, response_par);
                                        numReads++;
 -                                      if(exitAfterNReads > 0 && numReads == exitAfterNReads) {
 +                                      if(exitAfterNReads > 0 && numReads >= exitAfterNReads) {
                                                Dbprintf("%d reads done, exiting", numReads);
                                                finished = true;
                                        }
        if(flags & FLAG_INTERACTIVE)// Interactive mode flag, means we need to send ACK
        {
                //May just aswell send the collected ar_nr in the response aswell
 -              cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,0,0,&ar_nr_responses,ar_nr_collected*4*4);
 +              cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,1,0,&ar_nr_responses,ar_nr_collected*4*4);
        }
  
 -      if(flags & FLAG_NR_AR_ATTACK)
 +      if(flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1 )
        {
 -              if(ar_nr_collected > 1) {
 +              if(ar_nr_collected > 1 ) {
                        Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
                        Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x",
                                        ar_nr_responses[0], // UID
                                        );
                } else {
                        Dbprintf("Failed to obtain two AR/NR pairs!");
 -                      if(ar_nr_collected >0) {
 +                      if(ar_nr_collected > 0 ) {
                                Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x",
                                                ar_nr_responses[0], // UID
                                                ar_nr_responses[1], //NT
@@@ -2805,7 -2802,7 +2846,7 @@@ void RAMFUNC SniffMifare(uint8_t param
                                        if (MfSniffLogic(receivedCmd, Uart.len, Uart.parity, Uart.bitCount, TRUE)) break;
  
                                        /* And ready to receive another command. */
--                                      UartReset();
++                                      UartInit(receivedCmd, receivedCmdPar);
                                        
                                        /* And also reset the demod code */
                                        DemodReset();
  
                                        // And ready to receive another response.
                                        DemodReset();
++                                      // And reset the Miller decoder including its (now outdated) input buffer
++                                      UartInit(receivedCmd, receivedCmdPar);
                                }
                                TagIsActive = (Demod.state != DEMOD_UNSYNCD);
                        }
diff --combined armsrc/iso14443a.h
index be8775cef7d0f66e83f4514e830a3de1a60a1983,1e978e8808fa683f7744211e8bd4060c32eb59c5..3344de4327a5a7d8fba8e2edb595547d54c39e64
@@@ -12,8 -12,7 +12,8 @@@
  
  #ifndef __ISO14443A_H
  #define __ISO14443A_H
 -#include "common.h"
 +#include "../include/common.h"
 +#include "../include/mifare.h"
  #include "mifaresniff.h"
  
  typedef struct {
@@@ -57,15 -56,15 +57,14 @@@ typedef struct 
                // DROP_FIRST_HALF,
                } state;
        uint16_t shiftReg;
--      uint16_t bitCount;
++      int16_t  bitCount;
        uint16_t len;
        uint16_t byteCntMax;
        uint16_t posCnt;
        uint16_t syncBit;
        uint8_t  parityBits;
        uint8_t  parityLen;
--      uint16_t highCnt;
--      uint16_t twoBits;
++      uint32_t fourBits;
        uint32_t startTime, endTime;
      uint8_t *output;
        uint8_t *parity;
diff --combined armsrc/lfops.c
index 7537d63fa60447cea122e02d26371d717ee6fe85,7bbc739d45991e063fd40980112f457c11481a1b..6eb89912606930f46e156075e7b19af5b818dcdf
@@@ -38,15 -38,15 +38,15 @@@ void ModThenAcquireRawAdcSamples125k(in
        sample_config sc = { 0,0,1, divisor_used, 0};
        setSamplingConfig(&sc);
  
 -      /* Make sure the tag is reset */
 -      FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
 -      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 -      SpinDelay(2500);
 +    /* Make sure the tag is reset */
 +    FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
 +    FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 +    SpinDelay(2500);
  
        LFSetupFPGAForADC(sc.divisor, 1);
  
 -      // And a little more time for the tag to fully power up
 -      SpinDelay(2000);
 +    // And a little more time for the tag to fully power up
 +    SpinDelay(2000);
  
      // now modulate the reader field
      while(*command != '\0' && *command != ' ') {
@@@ -73,6 -73,8 +73,6 @@@
        DoAcquisition_config(false);
  }
  
 -
 -
  /* blank r/w tag data stream
  ...0000000000000000 01111111
  1010101010101010101010101010101010101010101010101010101010101010
@@@ -380,7 -382,7 +380,7 @@@ void WriteTItag(uint32_t idhi, uint32_
      DbpString("Now use tiread to check");
  }
  
 -void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
 +void SimulateTagLowFrequency(uint16_t period, uint32_t gap, uint8_t ledcontrol)
  {
      int i;
      uint8_t *tab = BigBuf_get_addr();
@@@ -655,11 -657,11 +655,11 @@@ void CmdASKsimTag(uint16_t arg1, uint16
  
      if (encoding==2){  //biphase
          uint8_t phase=0;
 -        for (i=0; i<size; i++){
 +    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
 -            for (i=0; i<size; i++){
 +        for (i=0; i<size; i++){
                  biphaseSimBit(BitStream[i]^invert, &n, clk, &phase);
              }
          }
          if (encoding==0 && BitStream[0]==BitStream[size-1]){ //run a second set inverted (for biphase phase)
              for (i=0; i<size; i++){
                  askSimBit(BitStream[i]^invert^1, &n, clk, encoding);
 -            }    
 +        }    
          }    
      }
      
@@@ -766,7 -768,7 +766,7 @@@ void CmdHIDdemodFSK(int findone, int *h
          if (ledcontrol) LED_A_ON();
  
                DoAcquisition_default(-1,true);
 -              // FSK demodulator
 +        // FSK demodulator
          size = sizeOfBigBuff;  //variable size will change after demod so re initialize it before use
                idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo);
          
@@@ -843,7 -845,7 +843,7 @@@ void CmdEM410xdemod(int findone, int *h
  {
      uint8_t *dest = BigBuf_get_addr();
  
 -    size_t size=0, idx=0;
 +      size_t size=0, idx=0;
      int clk=0, invert=0, errCnt=0, maxErr=20;
      uint32_t hi=0;
      uint64_t lo=0;
          WDT_HIT();
          if (ledcontrol) LED_A_ON();
  
 -        DoAcquisition_default(-1,true);
 +              DoAcquisition_default(-1,true);
          size  = BigBuf_max_traceLen();
          //Dbprintf("DEBUG: Buffer got");
 -        //askdemod and manchester decode
 -        errCnt = askmandemod(dest, &size, &clk, &invert, maxErr);
 +              //askdemod and manchester decode
 +              errCnt = askmandemod(dest, &size, &clk, &invert, maxErr);
          //Dbprintf("DEBUG: ASK Got");
          WDT_HIT();
  
                          (uint32_t)((lo>>16LL) & 0xFF),
                          (uint32_t)(lo & 0xFFFFFF));
                  } else {
 -                    Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)",
 -                        (uint32_t)(lo>>32),
 -                        (uint32_t)lo,
 -                        (uint32_t)(lo&0xFFFF),
 -                        (uint32_t)((lo>>16LL) & 0xFF),
 -                        (uint32_t)(lo & 0xFFFFFF));
 -                }
 +                              Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)",
 +                                  (uint32_t)(lo>>32),
 +                                  (uint32_t)lo,
 +                                  (uint32_t)(lo&0xFFFF),
 +                                  (uint32_t)((lo>>16LL) & 0xFF),
 +                                  (uint32_t)(lo & 0xFFFFFF));
 +            }
              }
              if (findone){
                  if (ledcontrol)       LED_A_OFF();
@@@ -912,8 -914,6 +912,8 @@@ void CmdIOdemodFSK(int findone, int *hi
      uint8_t version=0;
      uint8_t facilitycode=0;
      uint16_t number=0;
 +      uint8_t crc = 0;
 +      uint16_t calccrc = 0;
      // Configure to go in 125Khz listen mode
      LFSetupFPGAForADC(95, true);
  
          WDT_HIT();
          if (ledcontrol) LED_A_ON();
                DoAcquisition_default(-1,true);
 -              //fskdemod and get start index
 +        //fskdemod and get start index
          WDT_HIT();
          idx = IOdemodFSK(dest, BigBuf_max_traceLen());
          if (idx>0){
              //|           |           |           |           |           |           |
              //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23
              //-----------------------------------------------------------------------------
 -            //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11
 +            //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 checksum 11
              //
 +                      //Checksum:  
 +                      //00000000 0 11110000 1 11100000 1 00000001 1 00000011 1 10110110 1 01110101 11
 +                      //preamble      F0         E0         01         03         B6         75
 +                      // How to calc checksum,
 +                      // http://www.proxmark.org/forum/viewtopic.php?id=364&p=6
 +                      //   F0 + E0 + 01 + 03 + B6 = 28A
 +                      //   28A & FF = 8A
 +                      //   FF - 8A = 75
 +                      // Checksum: 0x75
              //XSF(version)facility:codeone+codetwo
              //Handle the data
              if(findone){ //only print binary if we are doing one
              facilitycode = bytebits_to_byte(dest+idx+18,8) ;
              number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9
  
 -            Dbprintf("XSF(%02d)%02x:%05d (%08x%08x)",version,facilitycode,number,code,code2);
 +                      crc = bytebits_to_byte(dest+idx+54,8);
 +                      for (uint8_t i=1; i<6; ++i)
 +                              calccrc += bytebits_to_byte(dest+idx+9*i,8);
 +                      calccrc &= 0xff;
 +                      calccrc = 0xff - calccrc;
 +                      
 +                      char *crcStr = (crc == calccrc) ? "ok":"!crc";
 +
 +            Dbprintf("IO Prox XSF(%02d)%02x:%05d (%08x%08x)  [%02x %s]",version,facilitycode,number,code,code2, crc, crcStr);
              // if we're only looking for one tag
              if (findone){
                  if (ledcontrol)       LED_A_OFF();
   * and enlarge the gap ones.
   */
  #define START_GAP 50*8 // 10 - 50fc 250
 -#define WRITE_GAP 20*8 //    - 30fc 160
 -#define WRITE_0   24*8 // 16 - 63fc 54fc 144
 -#define WRITE_1   54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550 //400
 +#define WRITE_GAP 20*8 //  8 - 30fc
 +#define WRITE_0   24*8 // 16 - 31fc 24fc 192
 +#define WRITE_1   54*8 // 48 - 63fc 54fc 432 for T55x7; 448 for E5550
 +
 +//  VALUES TAKEN FROM EM4x function: SendForward
 +//  START_GAP = 440;       (55*8) cycles at 125Khz (8us = 1cycle)
 +//  WRITE_GAP = 128;       (16*8)
 +//  WRITE_1   = 256 32*8;  (32*8) 
  
 -#define T55xx_SAMPLES_SIZE      12000 // 32 x 32 x 10  (32 bit times numofblock (7), times clock skip..)
 +//  These timings work for 4469/4269/4305 (with the 55*8 above)
 +//  WRITE_0 = 23*8 , 9*8  SpinDelayUs(23*8); 
 +
 +// 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
 +// 1 Cycle = 8 microseconds(us)
 +
 +#define T55xx_SAMPLES_SIZE            12000 // 32 x 32 x 10  (32 bit times numofblock (7), times clock skip..)
  
  // Write one bit to card
  void T55xxWriteBit(int bit)
      FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
      FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
      FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
 -    if (bit == 0)
 +      if (!bit)
          SpinDelayUs(WRITE_0);
      else
          SpinDelayUs(WRITE_1);
  // Write one card block in page 0, no lock
  void T55xxWriteBlock(uint32_t Data, uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
  {
-       uint32_t i = 0;
+     uint32_t i = 0;
  
-       // Set up FPGA, 125kHz
-       // Wait for config.. (192+8190xPOW)x8 == 67ms
-       LFSetupFPGAForADC(0, true);
+     // Set up FPGA, 125kHz
+     // Wait for config.. (192+8190xPOW)x8 == 67ms
+     LFSetupFPGAForADC(0, true);
  
      // Now start writting
      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
  }
  
+ void TurnReadLFOn(){
+     FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
+     // Give it a bit of time for the resonant antenna to settle.
+     SpinDelayUs(8*150);
+ }
  // Read one card block in page 0
  void T55xxReadBlock(uint32_t Block, uint32_t Pwd, uint8_t PwdMode)
  {
      uint32_t i = 0;
      uint8_t *dest = BigBuf_get_addr();
      uint16_t bufferlength = BigBuf_max_traceLen();
-       if ( bufferlength > T55xx_SAMPLES_SIZE )
-               bufferlength = T55xx_SAMPLES_SIZE;
-       memset(dest, 0x80, bufferlength);
-       
-       // Set up FPGA, 125kHz
-       // Wait for config.. (192+8190xPOW)x8 == 67ms
-       LFSetupFPGAForADC(0, true);
+     if ( bufferlength > T55xx_SAMPLES_SIZE )
+         bufferlength = T55xx_SAMPLES_SIZE;
+     // Clear destination buffer before sending the command
+     memset(dest, 0x80, bufferlength);
+     // Set up FPGA, 125kHz
+     // Wait for config.. (192+8190xPOW)x8 == 67ms
+     LFSetupFPGAForADC(0, true);
      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
      SpinDelayUs(START_GAP);
  
          T55xxWriteBit(Block & i);
  
      // Turn field on to read the response
-       TurnReadLFOn();
+     TurnReadLFOn();
      // Now do the acquisition
      i = 0;
      for(;;) {
          if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
              AT91C_BASE_SSC->SSC_THR = 0x43;
-                       LED_D_ON();
+             LED_D_ON();
          }
          if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
              dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-                       ++i;
-                       LED_D_OFF();
-                       if (i >= bufferlength) break;
+             i++;
+             LED_D_OFF();
+             if (i >= bufferlength) break;
          }
      }
  
-       cmd_send(CMD_ACK,0,0,0,0,0);
+     cmd_send(CMD_ACK,0,0,0,0,0);    
      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
      LED_D_OFF();
  }
  
  // Read card traceability data (page 1)
  void T55xxReadTrace(void){
-       uint32_t i = 0;
+     
+     uint32_t i = 0;
      uint8_t *dest = BigBuf_get_addr();
      uint16_t bufferlength = BigBuf_max_traceLen();
-       if ( bufferlength > T55xx_SAMPLES_SIZE )
-               bufferlength = T55xx_SAMPLES_SIZE;
+     if ( bufferlength > T55xx_SAMPLES_SIZE )
+         bufferlength= T55xx_SAMPLES_SIZE;
  
-       memset(dest, 0x80, bufferlength);  
-   
-       LFSetupFPGAForADC(0, true);
+     // Clear destination buffer before sending the command
+     memset(dest, 0x80, bufferlength);
+     LFSetupFPGAForADC(0, true);
      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
      SpinDelayUs(START_GAP);
  
      T55xxWriteBit(1); //Page 1
  
      // Turn field on to read the response
-       TurnReadLFOn();
+     TurnReadLFOn();
  
      // Now do the acquisition
      for(;;) {
          if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
              AT91C_BASE_SSC->SSC_THR = 0x43;
-                       LED_D_ON();
+             LED_D_ON();
          }
          if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
              dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
-                       ++i;
-                       LED_D_OFF();
-               
-                       if (i >= bufferlength) break;
+             i++;
+             LED_D_OFF();
+             if (i >= bufferlength) break;
 -        }
 -    }
 -
 +              }
 +      }
 +  
 +      cmd_send(CMD_ACK,0,0,0,0,0);
+     cmd_send(CMD_ACK,0,0,0,0,0);
      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
      LED_D_OFF();
  }
  
 +void TurnReadLFOn(){
 +      //FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
 +      FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD);
 +      // Give it a bit of time for the resonant antenna to settle.
 +      //SpinDelay(30);
 +      SpinDelayUs(8*150);
 +}
 +
  /*-------------- Cloning routines -----------*/
  // Copy HID id to card and setup block 0 config
  void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT)
@@@ -1528,16 -1497,10 +1537,16 @@@ void CopyIndala224toT55x7(int uid1, in
  #define max(x,y) ( x<y ? y:x)
  
  int DemodPCF7931(uint8_t **outBlocks) {
 -    uint8_t BitStream[256];
 -    uint8_t Blocks[8][16];
 -    uint8_t *GraphBuffer = BigBuf_get_addr();
 -    int GraphTraceLen = BigBuf_max_traceLen();
 +
 +    uint8_t bits[256] = {0x00};
 +      uint8_t blocks[8][16];
 +    uint8_t *dest = BigBuf_get_addr();
 +    
 +      int GraphTraceLen = BigBuf_max_traceLen();
 +      if (  GraphTraceLen > 18000 )
 +              GraphTraceLen = 18000;
 +      
 +      
      int i, j, lastval, bitidx, half_switch;
      int clock = 64;
      int tolerance = clock / 8;
      uint8_t dir;
  
        LFSetupFPGAForADC(95, true);
 -      DoAcquisition_default(0, 0);
 -
 +      DoAcquisition_default(0, true);
  
      lmin = 64;
      lmax = 192;
      i = 2;
  
      /* Find first local max/min */
 -    if(GraphBuffer[1] > GraphBuffer[0]) {
 +    if(dest[1] > dest[0]) {
          while(i < GraphTraceLen) {
 -            if( !(GraphBuffer[i] > GraphBuffer[i-1]) && GraphBuffer[i] > lmax)
 +            if( !(dest[i] > dest[i-1]) && dest[i] > lmax)
                  break;
              i++;
          }
      }
      else {
          while(i < GraphTraceLen) {
 -            if( !(GraphBuffer[i] < GraphBuffer[i-1]) && GraphBuffer[i] < lmin)
 +            if( !(dest[i] < dest[i-1]) && dest[i] < lmin)
                  break;
              i++;
          }
  
      for (bitidx = 0; i < GraphTraceLen; i++)
      {
 -        if ( (GraphBuffer[i-1] > GraphBuffer[i] && dir == 1 && GraphBuffer[i] > lmax) || (GraphBuffer[i-1] < GraphBuffer[i] && dir == 0 && GraphBuffer[i] < lmin))
 +        if ( (dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin))
          {
              lc = i - lastval;
              lastval = i;
                      block_done = 1;
                  }
                  else if(half_switch == 1) {
 -                    BitStream[bitidx++] = 0;
 +                    bits[bitidx++] = 0;
                      half_switch = 0;
                  }
                  else
                      half_switch++;
              } else if (abs(lc-clock) < tolerance) {
                  // 64TO
 -                BitStream[bitidx++] = 1;
 +                bits[bitidx++] = 1;
              } else {
                  // Error
                  warnings++;
              if(block_done == 1) {
                  if(bitidx == 128) {
                      for(j=0; j<16; j++) {
 -                        Blocks[num_blocks][j] = 128*BitStream[j*8+7]+
 -                                64*BitStream[j*8+6]+
 -                                32*BitStream[j*8+5]+
 -                                16*BitStream[j*8+4]+
 -                                8*BitStream[j*8+3]+
 -                                4*BitStream[j*8+2]+
 -                                2*BitStream[j*8+1]+
 -                                BitStream[j*8];
 +                        blocks[num_blocks][j] = 128*bits[j*8+7]+
 +                                64*bits[j*8+6]+
 +                                32*bits[j*8+5]+
 +                                16*bits[j*8+4]+
 +                                8*bits[j*8+3]+
 +                                4*bits[j*8+2]+
 +                                2*bits[j*8+1]+
 +                                bits[j*8];
 +                                              
                      }
                      num_blocks++;
                  }
                  half_switch = 0;
              }
              if(i < GraphTraceLen)
 -            {
 -                if (GraphBuffer[i-1] > GraphBuffer[i]) dir=0;
 -                else dir = 1;
 -            }
 +                dir =(dest[i-1] > dest[i]) ? 0 : 1;
          }
          if(bitidx==255)
              bitidx=0;
          warnings = 0;
          if(num_blocks == 4) break;
      }
 -    memcpy(outBlocks, Blocks, 16*num_blocks);
 +    memcpy(outBlocks, blocks, 16*num_blocks);
      return num_blocks;
  }
  
@@@ -1952,14 -1918,9 +1961,14 @@@ void EM4xLogin(uint32_t Password) 
  
  void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
  
 +      uint8_t *dest =  BigBuf_get_addr();
 +      uint16_t bufferlength = BigBuf_max_traceLen();
 +      uint32_t i = 0;
 +
 +      // Clear destination buffer before sending the command  0x80 = average.
 +      memset(dest, 0x80, bufferlength);
 +      
      uint8_t fwd_bit_count;
 -    uint8_t *dest = BigBuf_get_addr();
 -    int m=0, i=0;
  
      //If password mode do login
      if (PwdMode == 1) EM4xLogin(Pwd);
      fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
      fwd_bit_count += Prepare_Addr( Address );
  
 -    m = BigBuf_max_traceLen();
 -    // Clear destination buffer before sending the command
 -    memset(dest, 128, m);
      // Connect the A/D to the peak-detected low-frequency path.
      SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
      // Now set up the SSC to get the ADC samples that are now streaming at us.
          }
          if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
              dest[i] = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
 -            i++;
 -            if (i >= m) break;
 -        }
 -    }
 +                      ++i;
 +                      if (i >= bufferlength) break;
 +              }
 +      }
 +  
 +      cmd_send(CMD_ACK,0,0,0,0,0);
      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off
      LED_D_OFF();
  }
diff --combined armsrc/mifarecmd.c
index 94bc1c1c545d7a34d1576721427f9f669e282614,a16cbf16612f9130e29f26ecce116c13669aacfa..69b5b53c76843e41267cdbb3926367b6f694260e
@@@ -16,7 -16,7 +16,8 @@@
  #include "mifarecmd.h"\r
  #include "apps.h"\r
  #include "util.h"\r
--\r
++//#include "../client/loclass/des.h"\r
++#include "des.h"\r
  #include "crc.h"\r
  \r
  //-----------------------------------------------------------------------------\r
@@@ -104,14 -104,14 +105,14 @@@ void MifareUC_Auth1(uint8_t arg0, uint8
        if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
                        Dbprintf("Can't select card");\r
--              //OnError(0);\r
++              OnError(0);\r
                return;\r
        };\r
        \r
        if(mifare_ultra_auth1(cuid, dataoutbuf)){\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)        \r
                        Dbprintf("Authentication part1: Fail.");\r
--              //OnError(1);\r
++              OnError(1);\r
                return;\r
        }\r
  \r
@@@ -138,7 -138,7 +139,7 @@@ void MifareUC_Auth2(uint32_t arg0, uint
        if(mifare_ultra_auth2(cuid, key, dataoutbuf)){\r
            if (MF_DBGLEVEL >= MF_DBG_ERROR) \r
                        Dbprintf("Authentication part2: Fail...");\r
--              //OnError(1);\r
++              OnError(1);\r
                return;                 \r
        }\r
        \r
        LEDsoff();\r
  }\r
  \r
--void MifareUReadBlock(uint8_t arg0,uint8_t *datain)\r
++void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
  {\r
        uint8_t blockNo = arg0;\r
        byte_t dataout[16] = {0x00};\r
        uint8_t uid[10] = {0x00};\r
++      uint8_t key[8] = {0x00};\r
        uint32_t cuid;\r
--    \r
++    bool usePwd = false;\r
++      \r
++      usePwd = (arg1 == 1);\r
++      \r
++      // use password\r
++      if ( usePwd )\r
++              memcpy(key, datain, 8);\r
++      \r
        LED_A_ON();\r
        LED_B_OFF();\r
        LED_C_OFF();\r
      \r
        int len = iso14443a_select_card(uid, NULL, &cuid);\r
        if(!len) {\r
--              if (MF_DBGLEVEL >= MF_DBG_ERROR)        Dbprintf("Can't select card");\r
--              //OnError(1);\r
++              if (MF_DBGLEVEL >= MF_DBG_ERROR)        Dbprintf("Can't select card (RC:%d)",len);\r
++              OnError(1);\r
                return;\r
                };\r
--        \r
++       \r
++       // authenticate here.\r
++      if ( usePwd ) {\r
++\r
++              uint8_t a[8] = { 0x01 };\r
++              uint8_t b[8] = { 0x00 };\r
++              uint8_t enc_b[8] = { 0x00 };\r
++              uint8_t ab[16] = { 0x00 };\r
++              \r
++              uint8_t transKey[8] = { 0x00 };\r
++              \r
++              uint16_t len;\r
++              uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
++              uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
++      \r
++              len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL);\r
++              if (len == 1) {\r
++                      if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
++                              Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
++                              OnError(1);\r
++                              return;\r
++              }\r
++              \r
++//            memcpy(dataout, receivedAnswer, 11);\r
++              \r
++              // tag nonce.\r
++              memcpy(enc_b,receivedAnswer+1,8);\r
++\r
++              // decrypt nonce.\r
++              des_dec(enc_b, b, key );\r
++\r
++              Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", enc_b[0],enc_b[1],enc_b[2],enc_b[3],enc_b[4],enc_b[5],enc_b[6],enc_b[7] );\r
++\r
++              rol(b,8);\r
++              \r
++              memcpy(ab  ,a,8);\r
++              memcpy(ab+8,b,8);\r
++\r
++              Dbprintf("AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[0],ab[1],ab[2],ab[3],ab[4],ab[5],ab[6],ab[7] );\r
++              Dbprintf("AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[8],ab[9],ab[10],ab[11],ab[12],ab[13],ab[14],ab[15] );\r
++\r
++              // encrypt\r
++              des_enc(ab, ab, key);\r
++\r
++              Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[0],ab[1],ab[2],ab[3],ab[4],ab[5],ab[6],ab[7] );\r
++              Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", ab[8],ab[9],ab[10],ab[11],ab[12],ab[13],ab[14],ab[15] );\r
++\r
++              len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, ab, receivedAnswer, receivedAnswerPar, NULL);\r
++              if (len == 1) {\r
++                      if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
++                              Dbprintf("Cmd Error: %02x", receivedAnswer[0]);\r
++                      OnError(1);\r
++                      return;\r
++              }\r
++      \r
++              // \r
++              memcpy(transKey, receivedAnswer+1, 8);\r
++              Dbprintf("TRANSACTIONKEY: %02x %02x %02x %02x %02x %02x %02x %02x", transKey[0],transKey[1],transKey[2],transKey[3],\r
++              transKey[4],transKey[5],transKey[6],transKey[7] );\r
++      }\r
++              \r
        len = mifare_ultra_readblock(cuid, blockNo, dataout);\r
        if(len) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)        Dbprintf("Read block error");\r
--              //OnError(2);\r
++              OnError(2);\r
                return;\r
                };\r
          \r
        len = mifare_ultra_halt(cuid);\r
        if(len) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)        Dbprintf("Halt error");\r
--              //OnError(3);\r
++              OnError(3);\r
                return;\r
                };\r
                \r
@@@ -261,8 -261,8 +330,8 @@@ void MifareReadSector(uint8_t arg0, uin
  \r
  void MifareUReadCard(uint8_t arg0, int arg1, uint8_t *datain)\r
  {\r
--  // params\r
--        uint8_t sectorNo = arg0;\r
++      // params\r
++      uint8_t sectorNo = arg0;\r
        int Pages = arg1;\r
        int count_Pages = 0;\r
        byte_t dataout[176] = {0x00};;\r
        \r
        if (!len) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
--                      Dbprintf("Can't select card");\r
--              //OnError(1);\r
++                      Dbprintf("Can't select card (RC:%d)",len);\r
++              OnError(1);\r
                return;\r
        }\r
        \r
                if (len) {\r
                        if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
                                Dbprintf("Read block %d error",i);\r
--                      //OnError(2);\r
++                      OnError(2);\r
                        return;\r
                } else {\r
                        count_Pages++;\r
        if (len) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
                        Dbprintf("Halt error");\r
--              //OnError(3);\r
++              OnError(3);\r
                return;\r
        }\r
        \r
@@@ -942,12 -942,12 +1011,12 @@@ void MifareCSetBlock(uint32_t arg0, uin
                if (workFlags & 0x01) {\r
                        if(!iso14443a_select_card(uid, NULL, &cuid)) {\r
                                if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");\r
 -                              break;\r
 +                              //break;\r
                        };\r
  \r
                        if(mifare_classic_halt(NULL, cuid)) {\r
                                if (MF_DBGLEVEL >= 1)   Dbprintf("Halt error");\r
 -                              break;\r
 +                              //break;\r
                        };\r
                };\r
        \r
@@@ -1143,14 -1143,14 +1212,14 @@@ void Mifare_DES_Auth1(uint8_t arg0, uin
        if(!len) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)        \r
                        Dbprintf("Can't select card");\r
--              //OnError(1);\r
++              OnError(1);\r
                return;\r
        };\r
  \r
        if(mifare_desfire_des_auth1(cuid, dataout)){\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)        \r
                        Dbprintf("Authentication part1: Fail.");\r
--              //OnError(4);\r
++              OnError(4);\r
                return;\r
        }\r
  \r
@@@ -1173,7 -1173,7 +1242,7 @@@ void Mifare_DES_Auth2(uint32_t arg0, ui
        if( isOK) {\r
            if (MF_DBGLEVEL >= MF_DBG_EXTENDED) \r
                        Dbprintf("Authentication part2: Failed");  \r
--              //OnError(4);\r
++              OnError(4);\r
                return;\r
        }\r
  \r
diff --combined armsrc/mifaredesfire.c
index 5737615106c9a0cddd2d8a92d3763807c97d6b01,0000000000000000000000000000000000000000..979e2f39cd2d04b2184d01a74a6f07938ca918dc
mode 100644,000000..100644
--- /dev/null
@@@ -1,507 -1,0 +1,508 @@@
-       iso14a_set_tracing(TRUE);
 +#include "mifaredesfire.h"
 +#include "des.h"
++#include "BigBuf.h"
 +
 +#define MAX_APPLICATION_COUNT 28
 +#define MAX_FILE_COUNT 16
 +#define MAX_DESFIRE_FRAME_SIZE 60
 +#define NOT_YET_AUTHENTICATED 255
 +#define FRAME_PAYLOAD_SIZE (MAX_DESFIRE_FRAME_SIZE - 5)
 +#define RECEIVE_SIZE 64
 +
 +// the block number for the ISO14443-4 PCB
 +uint8_t pcb_blocknum = 0;
 +// Deselect card by sending a s-block. the crc is precalced for speed
 +static  uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};
 +
 +//static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
 +/*                                       PCB   CID   CMD    PAYLOAD    */
 +//static uint8_t __res[MAX_FRAME_SIZE];
 +
 +bool InitDesfireCard(){
 +      
 +      byte_t cardbuf[USB_CMD_DATA_SIZE] = {0x00};
 +
 +      iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
 +      
-               iso14a_clear_trace();
++      set_tracing(TRUE);
 +      iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
 +      
 +      int len = iso14443a_select_card(NULL,card,NULL);
 +
 +      if (!len) {
 +              if (MF_DBGLEVEL >= MF_DBG_ERROR)
 +                      Dbprintf("Can't select card");
 +              OnError(1);
 +              return false;
 +      }
 +      return true;
 +}
 +
 +// ARG0 flag enums
 +enum  {
 + NONE         =       0x00,
 + INIT                 =       0x01,
 + DISCONNECT = 0x02,
 + CLEARTRACE   =       0x04,
 + BAR          =       0x08,
 +} CmdOptions ;
 +
 +void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
 +      
 +      /* ARG0 contains flags.
 +              0x01 = init card.
 +              0x02 = Disconnect
 +              0x03
 +      */
 +      uint8_t flags = arg0;
 +      size_t datalen = arg1;
 +      uint8_t resp[RECEIVE_SIZE];
 +      memset(resp,0,sizeof(resp));
 +      
 +      if (MF_DBGLEVEL >= 4) {
 +              Dbprintf(" flags : %02X", flags);
 +              Dbprintf(" len   : %02X", datalen);
 +              print_result(" RX    : ", datain, datalen);
 +      }
 +      
 +      if ( flags & CLEARTRACE ){
-       iso14a_clear_trace();
-       iso14a_set_tracing(TRUE);
++              clear_trace();
 +      }
 +      
 +      if ( flags & INIT ){
 +              if ( !InitDesfireCard() )
 +                      return;
 +      }
 +      
 +      int len = DesfireAPDU(datain, datalen, resp);
 +      if (MF_DBGLEVEL >= 4) {
 +              print_result("ERR <--: ", resp, len);
 +      }
 +
 +      if ( !len ) {
 +              OnError(2);
 +              return;
 +      }
 +      
 +      // reset the pcb_blocknum,
 +      pcb_blocknum = 0;
 +      
 +      if ( flags & DISCONNECT ){
 +              OnSuccess();
 +      }
 +      
 +      cmd_send(CMD_ACK,1,len,0,resp,len);
 +}
 +
 +void MifareDesfireGetInformation(){
 +              
 +      int len = 0;
 +      uint8_t resp[USB_CMD_DATA_SIZE] = {0x00};
 +      uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00};
 +      byte_t cardbuf[USB_CMD_DATA_SIZE] = {0x00};
 +      
 +      /*
 +              1 = PCB                                 1
 +              2 = cid                                 2
 +              3 = desfire command             3 
 +              4-5 = crc                               4  key
 +                                                              5-6 crc                                                         
 +              PCB == 0x0A because sending CID byte.
 +              CID == 0x00 first card?         
 +      */
-       uint8_t *resp = ((uint8_t *)BigBuf) + RECV_RESP_OFFSET;
-     uint8_t *resp_par = ((uint8_t *)BigBuf) + RECV_RESP_PAR_OFFSET;
++      clear_trace();
++      set_tracing(TRUE);
 +      iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
 +
 +      // card select - information
 +      iso14a_card_select_t *card = (iso14a_card_select_t*)cardbuf;
 +      byte_t isOK = iso14443a_select_card(NULL, card, NULL);
 +      if ( isOK == 0) {
 +              if (MF_DBGLEVEL >= MF_DBG_ERROR) {
 +                      Dbprintf("Can't select card");
 +              }
 +              OnError(1);
 +              return;
 +      }
 +
 +      memcpy(dataout,card->uid,7);
 +
 +      LED_A_ON();
 +      LED_B_OFF();
 +      LED_C_OFF();
 +      
 +      uint8_t cmd[] = {GET_VERSION};  
 +      size_t cmd_len = sizeof(cmd);
 +      
 +      len =  DesfireAPDU(cmd, cmd_len, resp);
 +      if ( !len ) {
 +              print_result("ERROR <--: ", resp, len); 
 +              OnError(2);
 +              return;
 +      }
 +      
 +      LED_A_OFF();
 +      LED_B_ON();
 +      memcpy(dataout+7,resp+3,7);
 +      
 +      // ADDITION_FRAME 1
 +      cmd[0] = ADDITIONAL_FRAME;
 +      len =  DesfireAPDU(cmd, cmd_len, resp);
 +      if ( !len ) {
 +              print_result("ERROR <--: ", resp, len); 
 +              OnError(2);
 +              return;
 +      }       
 +      
 +      LED_B_OFF();
 +      LED_C_ON();
 +      memcpy(dataout+7+7,resp+3,7);
 +
 +      // ADDITION_FRAME 2
 +      len =  DesfireAPDU(cmd, cmd_len, resp);
 +      if ( !len ) {
 +              print_result("ERROR <--: ", resp, len); 
 +              OnError(2);
 +              return;
 +      }
 +      
 +      memcpy(dataout+7+7+7,resp+3,14);
 +      
 +      cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout));
 +              
 +      // reset the pcb_blocknum,
 +      pcb_blocknum = 0;
 +      OnSuccess();
 +}
 +
 +void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno,  uint8_t *datain){
 +
 +      int len = 0;
 +      //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
 +      uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
 +      uint8_t null_key_data8[8] = {0x00};
 +      //uint8_t null_key_data16[16] = {0x00}; 
 +      //uint8_t new_key_data8[8]  = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
 +      //uint8_t new_key_data16[16]  = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
 +
 +      uint8_t resp[256] = {0x00};
 +      uint8_t IV[16] = {0x00};
 +
 +      size_t datalen = datain[0];
 +      
 +      uint8_t cmd[40] = {0x00};
 +      uint8_t encRndB[16] = {0x00};
 +      uint8_t decRndB[16] = {0x00};
 +      uint8_t nonce[16] = {0x00};
 +      uint8_t both[32] = {0x00};
 +      uint8_t encBoth[32] = {0x00};
 +
 +      InitDesfireCard();
 +      
 +      // 3 olika sätt att authenticera.   AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
 +      // 4 olika crypto algo   DES, 3DES, 3K3DES, AES
 +      // 3 olika kommunikations sätt,   PLAIN,MAC,CRYPTO
 +      
 +      // des, nyckel 0, 
 +      switch (mode){
 +        case 1:{
 +            if (algo == 1) {
 +
 +            uint8_t keybytes[8] = {0x00};
 +            uint8_t RndA[8] = {0x00};
 +            uint8_t RndB[8] = {0x00};
 +            
 +            if (datain[1] == 0xff){
 +                memcpy(keybytes,null_key_data8,8);
 +            } else{
 +                memcpy(keybytes, datain+1, datalen);
 +            }
 +            
 +            struct desfire_key defaultkey = {0};
 +            desfirekey_t key = &defaultkey;
 +            Desfire_des_key_new(keybytes, key);
 +            
 +            cmd[0] = AUTHENTICATE;
 +            cmd[1] = keyno;  //keynumber
 +            len = DesfireAPDU(cmd, 2, resp);
 +            if ( !len ) {
 +                if (MF_DBGLEVEL >= MF_DBG_ERROR) {
 +                    DbpString("Authentication failed. Card timeout.");
 +                }
 +                OnError(3);
 +                return;
 +            }
 +            
 +            if ( resp[2] == 0xaf ){
 +            } else {
 +                DbpString("Authetication failed. Invalid key number.");
 +                OnError(3);
 +                return;
 +            }
 +            
 +            memcpy( encRndB, resp+3, 8);
 +            
 +            des_dec(&decRndB, &encRndB, key->data);
 +            memcpy(RndB, decRndB, 8);
 +            rol(decRndB,8);
 +            
 +            // This should be random
 +            uint8_t decRndA[8] = {0x00};
 +            memcpy(RndA, decRndA, 8);
 +            uint8_t encRndA[8] = {0x00};
 +            
 +            des_dec(&encRndA, &decRndA, key->data);
 +            
 +            memcpy(both, encRndA, 8);
 +            
 +            for (int x = 0; x < 8; x++) {
 +                decRndB[x] = decRndB[x] ^ encRndA[x];
 +            }
 +            
 +            des_dec(&encRndB, &decRndB, key->data);
 +            
 +            memcpy(both + 8, encRndB, 8);
 +            
 +            cmd[0] = ADDITIONAL_FRAME;
 +            memcpy(cmd+1, both, 16 );
 +            
 +            len = DesfireAPDU(cmd, 17, resp);
 +            if ( !len ) {
 +                if (MF_DBGLEVEL >= MF_DBG_ERROR) {
 +                    DbpString("Authentication failed. Card timeout.");
 +                }
 +                OnError(3);
 +                return;
 +            }
 +            
 +            if ( resp[2] == 0x00 ){
 +                
 +                struct desfire_key sessionKey = {0};
 +                desfirekey_t skey = &sessionKey;
 +                Desfire_session_key_new( RndA, RndB , key, skey );
 +                //print_result("SESSION : ", skey->data, 8);
 +                
 +                memcpy(encRndA, resp+3, 8);
 +                des_dec(&encRndA, &encRndA, key->data);
 +                rol(decRndA,8);
 +                for (int x = 0; x < 8; x++) {
 +                    if (decRndA[x] != encRndA[x]) {
 +                        DbpString("Authetication failed. Cannot varify PICC.");
 +                        OnError(4);
 +                        return;
 +                    }
 +                }
 +                
 +                //Change the selected key to a new value.
 +                /*
 +                 
 +                cmd[0] = CHANGE_KEY;
 +                cmd[1] = keyno;
 +                
 +                uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
 +                
 +                uint8_t first, second;
 +                uint8_t buff1[8] = {0x00};
 +                uint8_t buff2[8] = {0x00};
 +                uint8_t buff3[8] = {0x00};
 +                
 +                memcpy(buff1,newKey, 8);
 +                memcpy(buff2,newKey + 8, 8);
 +                
 +                ComputeCrc14443(CRC_14443_A, newKey, 16, &first, &second);
 +                memcpy(buff3, &first, 1);
 +                memcpy(buff3 + 1, &second, 1);
 +                
 +                des_dec(&buff1, &buff1, skey->data);
 +                memcpy(cmd+2,buff1,8);
 +                
 +                for (int x = 0; x < 8; x++) {
 +                    buff2[x] = buff2[x] ^ buff1[x];
 +                }
 +                des_dec(&buff2, &buff2, skey->data);
 +                memcpy(cmd+10,buff2,8);
 +                
 +                for (int x = 0; x < 8; x++) {
 +                    buff3[x] = buff3[x] ^ buff2[x];
 +                }
 +                des_dec(&buff3, &buff3, skey->data);
 +                memcpy(cmd+18,buff3,8);
 +                
 +                // The command always times out on the first attempt, this will retry until a response
 +                // is recieved.
 +                len = 0;
 +                while(!len) {
 +                    len = DesfireAPDU(cmd,26,resp);
 +                }
 +                */
 +                
 +                OnSuccess();
 +                cmd_send(CMD_ACK,1,0,0,skey->data,8);
 +                
 +            } else {
 +                DbpString("Authetication failed.");
 +                OnError(6);
 +                return;
 +            }
 +            
 +            }
 +            }
 +                      break;
 +              case 2:
 +                      //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp);
 +                      break;
 +              case 3:{
 +              
 +                      //defaultkey
 +                      uint8_t keybytes[16] = {0x00};
 +                      if (datain[1] == 0xff){
 +                              memcpy(keybytes,PICC_MASTER_KEY16,16); 
 +                      } else{
 +                              memcpy(keybytes, datain+1, datalen);
 +                      }
 +                      
 +                      struct desfire_key defaultkey = {0x00};
 +                      desfirekey_t key = &defaultkey;
 +                      Desfire_aes_key_new( keybytes, key);
 +              
 +                      AesCtx ctx;
 +                      if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){
 +                              if( MF_DBGLEVEL >= 4) {
 +                                      Dbprintf("AES context failed to init");
 +                              }
 +                              OnError(7);
 +                              return;
 +                      }
 +                      
 +                      cmd[0] = AUTHENTICATE_AES;
 +                      cmd[1] = 0x00;  //keynumber
 +                      len = DesfireAPDU(cmd, 2, resp);
 +                      if ( !len ) {
 +                              if (MF_DBGLEVEL >= MF_DBG_ERROR) {
 +                                      DbpString("Authentication failed. Card timeout.");
 +                              }
 +                              OnError(3);
 +                              return;
 +                      }
 +                      
 +                      memcpy( encRndB, resp+3, 16);
 +              
 +                      // dekryptera tagnonce.
 +                      AesDecrypt(&ctx, encRndB, decRndB, 16);
 +                      rol(decRndB,16);
 +                      memcpy(both, nonce,16);
 +                      memcpy(both+16, decRndB ,16 );
 +                      AesEncrypt(&ctx, both, encBoth, 32 );
 +                      
 +                      cmd[0] = ADDITIONAL_FRAME;
 +                      memcpy(cmd+1, encBoth, 32 );
 +                      
 +                      len = DesfireAPDU(cmd, 33, resp);  // 1 + 32 == 33
 +                      if ( !len ) {
 +                              if (MF_DBGLEVEL >= MF_DBG_ERROR) {
 +                                      DbpString("Authentication failed. Card timeout.");
 +                              }
 +                OnError(3);
 +                              return;
 +                      }
 +                      
 +                      if ( resp[2] == 0x00 ){
 +                              // Create AES Session key               
 +                              struct desfire_key sessionKey = {0};
 +                              desfirekey_t skey = &sessionKey;
 +                              Desfire_session_key_new( nonce, decRndB , key, skey );
 +                              print_result("SESSION : ", skey->data, 16);
 +                      } else {
 +                              DbpString("Authetication failed.");
 +                              OnError(7);
 +                              return;
 +                      }
 +                      break;
 +              }       
 +      }
 +      
 +      OnSuccess();
 +      cmd_send(CMD_ACK,1,len,0,resp,len);
 +}
 +
 +// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO)
 +// cmd  =  cmd bytes to send
 +// cmd_len = length of cmd
 +// dataout = pointer to response data array
 +int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
 +
 +      size_t len = 0;
 +      size_t wrappedLen = 0;
 +      uint8_t wCmd[USB_CMD_DATA_SIZE] = {0};
 +      
-       len = ReaderReceive(resp, resp_par);
++      uint8_t resp[MAX_FRAME_SIZE];
++    uint8_t par[MAX_PARITY_SIZE];
 +      
 +      wrappedLen = CreateAPDU( cmd, cmd_len, wCmd);
 +      
 +      if (MF_DBGLEVEL >= 4) {
 +              print_result("WCMD <--: ", wCmd, wrappedLen);   
 +      }
 +      ReaderTransmit( wCmd, wrappedLen, NULL);
 +
++      len = ReaderReceive(resp, par);
 +      
 +      if( len == 0x00 ){
 +              if (MF_DBGLEVEL >= 4) {
 +                      Dbprintf("fukked");
 +              }
 +              return FALSE; //DATA LINK ERROR
 +      }
 +      // if we received an I- or R(ACK)-Block with a block number equal to the
 +      // current block number, toggle the current block number
 +      else if (len >= 4 // PCB+CID+CRC = 4 bytes
 +               && ((resp[0] & 0xC0) == 0 // I-Block
 +                   || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
 +               && (resp[0] & 0x01) == pcb_blocknum) // equal block numbers
 +      {
 +              pcb_blocknum ^= 1;  //toggle next block 
 +      }
 +
 +      memcpy(dataout, resp, len);
 +      return len;
 +}     
 +
 +// CreateAPDU
 +size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){
 +      
 +      size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1);
 +
 +      uint8_t cmd[cmdlen];
 +      memset(cmd, 0, cmdlen);
 +      
 +      cmd[0] = 0x0A;  //  0x0A = skicka cid,  0x02 = ingen cid. Särskilda bitar //
 +      cmd[0] |= pcb_blocknum; // OR the block number into the PCB     
 +      cmd[1] = 0x00;  //  CID: 0x00 //TODO: allow multiple selected cards
 +      
 +      memcpy(cmd+2, datain, len);
 +      AppendCrc14443a(cmd, len+2);
 +      
 +      memcpy(dataout, cmd, cmdlen);
 +      
 +      return cmdlen;
 +}
 +
 +      // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
 +      // crc_update(&desfire_crc32, addr, addr_sz);
 +      // crc_update(&desfire_crc32, byte, 8);
 +      // uint32_t crc = crc_finish(&desfire_crc32);
 +
 +void OnSuccess(){
 +      pcb_blocknum = 0;
 +      ReaderTransmit(deselect_cmd, 3 , NULL);
 +      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 +      LEDsoff();
 +}
 +
 +void OnError(uint8_t reason){
 +      pcb_blocknum = 0;
 +      ReaderTransmit(deselect_cmd, 3 , NULL);
 +      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 +      cmd_send(CMD_ACK,0,reason,0,0,0);
 +      LEDsoff();
 +}
diff --combined client/Makefile
index ae116dd63da957fb804fa8d7c7af11da871e0c3d,81af01499fa75425b4495d557f4666bd4fa05cad..4fd41b46a170e821cec76275ef3b0aa76ae5774c
@@@ -12,9 -12,9 +12,9 @@@ CXX=g+
  VPATH = ../common
  OBJDIR = obj
  
 -LDLIBS = -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lreadline -lpthread -lm
 +LDLIBS =  -L/mingw/lib -L/opt/local/lib -L/usr/local/lib ../liblua/liblua.a -lm -lreadline -lpthread -lgdi32
  LDFLAGS = $(COMMON_FLAGS)
 -CFLAGS = -std=c99 -I. -I../include -I../common -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
 +CFLAGS = -std=c99 -I. -I../include -I../common -I/mingw/include -I/opt/local/include -I../liblua -Wall $(COMMON_FLAGS) -g -O4
  LUAPLATFORM = generic
  
  ifneq (,$(findstring MINGW,$(platform)))
@@@ -42,15 -42,6 +42,15 @@@ els
      LUAPLATFORM = linux
  endif
  
 +# QT version,  4 or 5
 +qtplatform = $(shell $(MOC) -v)
 +ifneq (, $(findstring moc 5,$(qtplatform)))
 +   CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets  -I/mingw/include
 +   QTLDLIBS = -L$(QTDIR)/lib  -lQt5Core -lQt5Gui -lQt5Widgets 
 +else
 +   CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
 +   QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
 +endif
  
  ifneq ($(QTLDLIBS),)
      QTGUI = $(OBJDIR)/proxgui.o $(OBJDIR)/proxguiqt.o $(OBJDIR)/proxguiqt.moc.o
@@@ -77,7 -68,6 +77,7 @@@ CMDSRCS =     nonce2key/crapto1.c
                        mifarehost.c\
                        crc.c \
                        crc16.c \
 +                      crc64.c \
                        iso14443crc.c \
                        iso15693tools.c \
                        data.c \
@@@ -94,6 -84,6 +94,8 @@@
                        cmdhficlass.c \
                        cmdhfmf.c \
              cmdhfmfu.c \
++                      cmdhfmfdes.c \
++                      cmdhftopaz.c \
                        cmdhw.c \
                        cmdlf.c \
                        cmdlfio.c \
@@@ -154,17 -144,6 +156,17 @@@ clean
  tarbin: $(BINS)
        $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%)
  
 +# must be run as root
 +install_kext: Info.plist
 +      mkdir -p /System/Library/Extensions/Proxmark3.kext/Contents
 +      cp Info.plist /System/Library/Extensions/Proxmark3.kext/Contents
 +      chown -R root:wheel /System/Library/Extensions/Proxmark3.kext
 +      chmod 755 /System/Library/Extensions/Proxmark3.kext /System/Library/Extensions/Proxmark3.kext/Contents
 +      chmod 644 /System/Library/Extensions/Proxmark3.kext/Contents/Info.plist
 +      rm -rf /System/Library/Caches/com.apple.kext.caches
 +      touch /System/Library/Extensions
 +      @echo "*** You may need to reboot for the kext to take effect."
 +
  lua_build:
        @echo Compiling liblua, using platform $(LUAPLATFORM)
        cd ../liblua && make $(LUAPLATFORM)
diff --combined client/cmddata.h
index ea8af9a6bdbf9cc6088bf7139f9834844f9435f4,f6b4b950a53933f44bf97973d4552146b878488c..f1dd9c7b83a6d2a46c7ef94d2c5b7ba41a59a113
@@@ -17,7 -17,6 +17,7 @@@ int CmdData(const char *Cmd)
  void printDemodBuff(void);
  void printBitStream(uint8_t BitStream[], uint32_t bitLen);
  void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx);
 +
  int CmdAmp(const char *Cmd);
  int Cmdaskdemod(const char *Cmd);
  int CmdAskEM410xDemod(const char *Cmd);
@@@ -64,18 -63,21 +64,22 @@@ int CmdThreshold(const char *Cmd)
  int CmdDirectionalThreshold(const char *Cmd);
  int CmdZerocrossings(const char *Cmd);
  int CmdIndalaDecode(const char *Cmd);
+ int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo);
  int ASKbiphaseDemod(const char *Cmd, bool verbose);
  int ASKmanDemod(const char *Cmd, bool verbose, bool emSearch);
  int ASKrawDemod(const char *Cmd, bool verbose);
  int FSKrawDemod(const char *Cmd, bool verbose);
  int PSKDemod(const char *Cmd, bool verbose);
  int NRZrawDemod(const char *Cmd, bool verbose);
+ void printEM410x(uint32_t hi, uint64_t id);
+ int getSamples(const char *Cmd, bool silent);
  
  #define MAX_DEMOD_BUF_LEN (1024*128)
  extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
  extern int DemodBufferLen;
  
 +extern uint8_t g_debugMode;
  #define BIGBUF_SIZE 40000
  
  #endif
diff --combined client/cmdhf.c
index 22063bbbe566e22e139524ad98ba2cc817c9b641,22063bbbe566e22e139524ad98ba2cc817c9b641..eba70a663c4ba82e32fab303f6c207ab81051043
@@@ -23,6 -23,6 +23,8 @@@
  #include "cmdhficlass.h"
  #include "cmdhfmf.h"
  #include "cmdhfmfu.h"
++#include "cmdhfmfdes.h"
++#include "cmdhftopaz.h"
  #include "protocols.h"
  
  static int CmdHelp(const char *Cmd);
@@@ -141,6 -141,6 +143,26 @@@ void annotateIso15693(char *exp, size_
        }
  }
  
++
++void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
++{
++      switch(cmd[0]) {
++              case TOPAZ_REQA                                         :snprintf(exp, size, "REQA");break;
++              case TOPAZ_WUPA                                         :snprintf(exp, size, "WUPA");break;
++              case TOPAZ_RID                                          :snprintf(exp, size, "RID");break;
++              case TOPAZ_RALL                                         :snprintf(exp, size, "RALL");break;
++              case TOPAZ_READ                                         :snprintf(exp, size, "READ");break;
++              case TOPAZ_WRITE_E                                      :snprintf(exp, size, "WRITE-E");break;
++              case TOPAZ_WRITE_NE                                     :snprintf(exp, size, "WRITE-NE");break;
++              case TOPAZ_RSEG                                         :snprintf(exp, size, "RSEG");break;
++              case TOPAZ_READ8                                        :snprintf(exp, size, "READ8");break;
++              case TOPAZ_WRITE_E8                                     :snprintf(exp, size, "WRITE-E8");break;
++              case TOPAZ_WRITE_NE8                            :snprintf(exp, size, "WRITE-NE8");break;
++              default:                            snprintf(exp,size,"?"); break;
++      }
++}
++
++
  /**
  06 00 = INITIATE
  0E xx = SELECT ID (xx = Chip-ID)
@@@ -172,7 -172,7 +194,34 @@@ void annotateIso14443b(char *exp, size_
  }
  
  /**
-- * @brief iso14443B_CRC_Ok Checks CRC in command or response
++ * @brief iso14443A_CRC_check Checks CRC in command or response
++ * @param isResponse
++ * @param data
++ * @param len
++ * @return  0 : CRC-command, CRC not ok
++ *          1 : CRC-command, CRC ok
++ *          2 : Not crc-command
++ */
++
++uint8_t iso14443A_CRC_check(bool isResponse, uint8_t* data, uint8_t len)
++{
++      uint8_t b1,b2;
++
++      if(len <= 2) return 2;
++
++      if(isResponse & (len < 6)) return 2;
++      
++      ComputeCrc14443(CRC_14443_A, data, len-2, &b1, &b2);
++      if (b1 != data[len-2] || b2 != data[len-1]) {
++              return 0;
++      } else {
++              return 1;
++      }
++}
++
++
++/**
++ * @brief iso14443B_CRC_check Checks CRC in command or response
   * @param isResponse
   * @param data
   * @param len
@@@ -190,8 -190,8 +239,9 @@@ uint8_t iso14443B_CRC_check(bool isResp
        ComputeCrc14443(CRC_14443_B, data, len-2, &b1, &b2);
        if(b1 != data[len-2] || b2 != data[len-1]) {
          return 0;
--      }
++      } else {
        return 1;
++      }
  }
  
  /**
@@@ -255,11 -255,11 +305,66 @@@ uint8_t iclass_CRC_check(bool isRespons
        }
  }
  
--uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
++
++bool is_last_record(uint16_t tracepos, uint8_t *trace, uint16_t traceLen)
  {
--      bool isResponse;
--      uint16_t duration, data_len, parity_len;
++      return(tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) >= traceLen);
++}
++
++
++bool next_record_is_response(uint16_t tracepos, uint8_t *trace)
++{
++      uint16_t next_records_datalen = *((uint16_t *)(trace + tracepos + sizeof(uint32_t) + sizeof(uint16_t)));
++      
++      return(next_records_datalen & 0x8000);
++}
++
++
++bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t *tracepos, uint16_t traceLen, uint8_t *trace, uint8_t *frame, uint8_t *topaz_reader_command, uint16_t *data_len)
++{
++
++#define MAX_TOPAZ_READER_CMD_LEN      16
  
++      uint32_t last_timestamp = timestamp + *duration;
++
++      if ((*data_len != 1) || (frame[0] == TOPAZ_WUPA) || (frame[0] == TOPAZ_REQA)) return false;
++
++      memcpy(topaz_reader_command, frame, *data_len);
++
++      while (!is_last_record(*tracepos, trace, traceLen) && !next_record_is_response(*tracepos, trace)) {
++              uint32_t next_timestamp = *((uint32_t *)(trace + *tracepos));
++              *tracepos += sizeof(uint32_t);
++              uint16_t next_duration = *((uint16_t *)(trace + *tracepos));
++              *tracepos += sizeof(uint16_t);
++              uint16_t next_data_len = *((uint16_t *)(trace + *tracepos)) & 0x7FFF;
++              *tracepos += sizeof(uint16_t);
++              uint8_t *next_frame = (trace + *tracepos);
++              *tracepos += next_data_len;
++              if ((next_data_len == 1) && (*data_len + next_data_len <= MAX_TOPAZ_READER_CMD_LEN)) {
++                      memcpy(topaz_reader_command + *data_len, next_frame, next_data_len);
++                      *data_len += next_data_len;
++                      last_timestamp = next_timestamp + next_duration;
++              } else {
++                      // rewind and exit
++                      *tracepos = *tracepos - next_data_len - sizeof(uint16_t) - sizeof(uint16_t) - sizeof(uint32_t);
++                      break;
++              }
++              uint16_t next_parity_len = (next_data_len-1)/8 + 1;
++              *tracepos += next_parity_len;
++      }
++
++      *duration = last_timestamp - timestamp;
++      
++      return true;
++}
++
++
++uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles, bool markCRCBytes)
++{
++      bool isResponse;
++      uint16_t data_len, parity_len;
++      uint32_t duration;
++      uint8_t topaz_reader_command[9];
        uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
        char explanation[30] = {0};
  
        uint8_t *parityBytes = trace + tracepos;
        tracepos += parity_len;
  
++      if (protocol == TOPAZ && !isResponse) {
++              // topaz reader commands come in 1 or 9 separate frames with 7 or 8 Bits each.
++              // merge them:
++              if (merge_topaz_reader_frames(timestamp, &duration, &tracepos, traceLen, trace, frame, topaz_reader_command, &data_len)) {
++                      frame = topaz_reader_command;
++              }
++      }
++      
        //Check the CRC status
        uint8_t crcStatus = 2;
  
        if (data_len > 2) {
--              uint8_t b1, b2;
--              if(protocol == ICLASS)
--              {
++              switch (protocol) {
++                      case ICLASS:
                        crcStatus = iclass_CRC_check(isResponse, frame, data_len);
--
--              }else if (protocol == ISO_14443B)
--              {
++                              break;
++                      case ISO_14443B:
++                      case TOPAZ:
                        crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
--              }
--              else if (protocol == ISO_14443A){//Iso 14443a
--
--                      ComputeCrc14443(CRC_14443_A, frame, data_len-2, &b1, &b2);
--
--                      if (b1 != frame[data_len-2] || b2 != frame[data_len-1]) {
--                              if(!(isResponse & (data_len < 6)))
--                              {
--                                              crcStatus = 0;
--                              }
--                      }
++                              break;
++                      case ISO_14443A:
++                              crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
++                              break;
++                      default: 
++                              break;
                }
        }
        //0 CRC-command, CRC not ok
                uint8_t parityBits = parityBytes[j>>3];
                if (isResponse && (oddparity != ((parityBits >> (7-(j&0x0007))) & 0x01))) {
                        snprintf(line[j/16]+(( j % 16) * 4),110, "%02x! ", frame[j]);
--
                } else {
                        snprintf(line[j/16]+(( j % 16) * 4),110, "%02x  ", frame[j]);
                }
  
        }
--      if(crcStatus == 1)
++
++      if (markCRCBytes) {
++              if(crcStatus == 0 || crcStatus == 1)
        {//CRC-command
--              char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1;
++                      char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4);
                (*pos1) = '[';
--              char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2;
--              (*pos2) = ']';
++                      char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4);
++                      sprintf(pos2, "%c", ']');
++              }
        }
++
        if(data_len == 0)
        {
                if(data_len == 0){
  
        if(!isResponse)
        {
--              if(protocol == ICLASS)
--                      annotateIclass(explanation,sizeof(explanation),frame,data_len);
--              else if (protocol == ISO_14443A)
--                      annotateIso14443a(explanation,sizeof(explanation),frame,data_len);
--              else if(protocol == ISO_14443B)
--                      annotateIso14443b(explanation,sizeof(explanation),frame,data_len);
++              switch(protocol) {
++                      case ICLASS:            annotateIclass(explanation,sizeof(explanation),frame,data_len); break;
++                      case ISO_14443A:        annotateIso14443a(explanation,sizeof(explanation),frame,data_len); break;
++                      case ISO_14443B:        annotateIso14443b(explanation,sizeof(explanation),frame,data_len); break;
++                      case TOPAZ:                     annotateTopaz(explanation,sizeof(explanation),frame,data_len); break;
++                      default:                        break;
++              }
        }
  
        int num_lines = MIN((data_len - 1)/16 + 1, 16);
        for (int j = 0; j < num_lines ; j++) {
                if (j == 0) {
--                      PrintAndLog(" %9d | %9d | %s | %-64s| %s| %s",
++                      PrintAndLog(" %10d | %10d | %s |%-64s | %s| %s",
                                (timestamp - first_timestamp),
                                (EndOfTransmissionTimestamp - first_timestamp),
                                (isResponse ? "Tag" : "Rdr"),
                }
        }
  
--      if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
++      if (is_last_record(tracepos, trace, traceLen)) return traceLen;
        
--      bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
--
--      if (showWaitCycles && !isResponse && next_isResponse) {
++      if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) {
                uint32_t next_timestamp = *((uint32_t *)(trace + tracepos));
--              if (next_timestamp != 0x44444444) {
                        PrintAndLog(" %9d | %9d | %s | fdt (Frame Delay Time): %d",
                                (EndOfTransmissionTimestamp - first_timestamp),
                                (next_timestamp - first_timestamp),
                                "   ",
                                (next_timestamp - EndOfTransmissionTimestamp));
                }
--      }
  
        return tracepos;
  }
  int CmdHFList(const char *Cmd)
  {
        bool showWaitCycles = false;
++      bool markCRCBytes = false;
        char type[40] = {0};
        int tlen = param_getstr(Cmd,0,type);
--      char param = param_getchar(Cmd, 1);
++      char param1 = param_getchar(Cmd, 1);
++      char param2 = param_getchar(Cmd, 2);
        bool errors = false;
        uint8_t protocol = 0;
        //Validate params
--      if(tlen == 0)
--      {
++
++      if(tlen == 0) {
                errors = true;
        }
--      if(param == 'h' || (param !=0 && param != 'f'))
--      {
++
++      if(param1 == 'h'
++                      || (param1 != 0 && param1 != 'f' && param1 != 'c')
++                      || (param2 != 0 && param2 != 'f' && param2 != 'c')) {
                errors = true;
        }
--      if(!errors)
--      {
--              if(strcmp(type, "iclass") == 0)
--              {
++
++      if(!errors) {
++              if(strcmp(type, "iclass") == 0) {
                        protocol = ICLASS;
--              }else if(strcmp(type, "14a") == 0)
--              {
++              } else if(strcmp(type, "14a") == 0) {
                        protocol = ISO_14443A;
--              }
--              else if(strcmp(type, "14b") == 0)
--              {
++              } else if(strcmp(type, "14b") == 0)     {
                        protocol = ISO_14443B;
--              }else if(strcmp(type,"raw")== 0)
--              {
++              } else if(strcmp(type,"topaz")== 0) {
++                      protocol = TOPAZ;
++              } else if(strcmp(type,"raw")== 0) {
                        protocol = -1;//No crc, no annotations
                }else{
                        errors = true;
  
        if (errors) {
                PrintAndLog("List protocol data in trace buffer.");
--              PrintAndLog("Usage:  hf list <protocol> [f]");
++              PrintAndLog("Usage:  hf list <protocol> [f][c]");
                PrintAndLog("    f      - show frame delay times as well");
++              PrintAndLog("    c      - mark CRC bytes");
                PrintAndLog("Supported <protocol> values:");
                PrintAndLog("    raw    - just show raw data without annotations");
                PrintAndLog("    14a    - interpret data as iso14443a communications");
                PrintAndLog("    14b    - interpret data as iso14443b communications");
                PrintAndLog("    iclass - interpret data as iclass communications");
++              PrintAndLog("    topaz  - interpret data as topaz communications");
                PrintAndLog("");
                PrintAndLog("example: hf list 14a f");
                PrintAndLog("example: hf list iclass");
        }
  
  
--      if (param == 'f') {
++      if (param1 == 'f' || param2 == 'f') {
                showWaitCycles = true;
        }
  
++      if (param1 == 'c' || param2 == 'c') {
++              markCRCBytes = true;
++      }
  
        uint8_t *trace;
        uint16_t tracepos = 0;
  
        while(tracepos < traceLen)
        {
--              tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
++              tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
        }
  
        free(trace);
@@@ -514,9 -514,9 +627,11 @@@ static command_t CommandTable[] 
    {"legic",       CmdHFLegic,       0, "{ LEGIC RFIDs... }"},
    {"iclass",      CmdHFiClass,      1, "{ ICLASS RFIDs... }"},
    {"mf",                      CmdHFMF,                1, "{ MIFARE RFIDs... }"},
--  {"mfu",                     CmdHFMFUltra,           1, "{ MIFARE Ultralight RFIDs... }"},
--  {"tune",        CmdHFTune,        0, "Continuously measure HF antenna tuning"},
--  {"list",       CmdHFList,         1, "List protocol data in trace buffer"},
++  {"mfu",                     CmdHFMFUltra,   1, "{ MIFARE Ultralight RFIDs... }"},
++  {"mfdes",                   CmdHFMFDes,             1, "{ MIFARE Desfire RFIDs... }"},
++  {"topaz",                   CmdHFTopaz,             1, "{ TOPAZ (NFC Type 1) RFIDs... }"},
++  {"tune",                    CmdHFTune,      0, "Continuously measure HF antenna tuning"},
++  {"list",                    CmdHFList,      1, "List protocol data in trace buffer"},
        {NULL, NULL, 0, NULL}
  };
  
diff --combined client/cmdhf14a.c
index bce7f4d6cba5f9abfffb613e63ba008e9a2d81ea,d36ebb8bee959220547577c0d31495b764630e3b..6fc4d2a06ba13906f35d248bfbe19df66444f87a
@@@ -140,7 -140,7 +140,7 @@@ int CmdHF14AReader(const char *Cmd
        iso14a_card_select_t card;
        memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t));
  
--      uint64_t select_status = resp.arg[0];           // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS
++      uint64_t select_status = resp.arg[0];           // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision
        
        if(select_status == 0) {
                PrintAndLog("iso14443a card select failed");
                return 0;
        }
  
++      if(select_status == 3) {
++              PrintAndLog("Card doesn't support standard iso14443-3 anticollision");
++      PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
++              // disconnect
++              c.arg[0] = 0;
++              c.arg[1] = 0;
++              c.arg[2] = 0;
++              SendCommand(&c);
++              return 0;
++      }
++
++
        PrintAndLog("ATQA : %02x %02x", card.atqa[1], card.atqa[0]);
        PrintAndLog(" UID : %s", sprint_hex(card.uid, card.uidlen));
        PrintAndLog(" SAK : %02x [%d]", card.sak, resp.arg[0]);
@@@ -497,16 -497,16 +509,18 @@@ int CmdHF14ASnoop(const char *Cmd) 
    return 0;
  }
  
++
  int CmdHF14ACmdRaw(const char *cmd) {
      UsbCommand c = {CMD_READER_ISO_14443a, {0, 0, 0}};
--    uint8_t reply=1;
--    uint8_t crc=0;
--    uint8_t power=0;
--    uint8_t active=0;
--    uint8_t active_select=0;
++    bool reply=1;
++    bool crc = FALSE;
++    bool power = FALSE;
++    bool active = FALSE;
++    bool active_select = FALSE;
      uint16_t numbits=0;
++      bool bTimeout = FALSE;
        uint32_t timeout=0;
--      uint8_t bTimeout=0;
++      bool topazmode = FALSE;
      char buf[5]="";
      int i=0;
      uint8_t data[USB_CMD_DATA_SIZE];
        uint32_t temp;
  
      if (strlen(cmd)<2) {
 -        PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-f] [-b] [-t] <number of bits> <0A 0B 0C ... hex>");
 +        PrintAndLog("Usage: hf 14a raw [-r] [-c] [-p] [-a] [-t] <milliseconds> [-b] <number of bits>  <0A 0B 0C ... hex>");
          PrintAndLog("       -r    do not read response");
          PrintAndLog("       -c    calculate and append CRC");
          PrintAndLog("       -p    leave the signal field ON after receive");
          PrintAndLog("       -s    active signal field ON with select");
          PrintAndLog("       -b    number of bits to send. Useful for send partial byte");
                PrintAndLog("       -t    timeout in ms");
++              PrintAndLog("       -T    use Topaz protocol to send command");
          return 0;
      }
  
++
      // strip
      while (*cmd==' ' || *cmd=='\t') cmd++;
  
          if (cmd[i]=='-') {
              switch (cmd[i+1]) {
                  case 'r': 
--                    reply=0;
++                    reply = FALSE;
                      break;
                  case 'c':
--                    crc=1;
++                    crc = TRUE;
                      break;
                  case 'p':
--                    power=1;
++                    power = TRUE;
                      break;
                  case 'a':
--                    active=1;
++                    active = TRUE;
                      break;
                  case 's':
--                    active_select=1;
++                    active_select = TRUE;
                      break;
                  case 'b': 
                      sscanf(cmd+i+2,"%d",&temp);
                      i-=2;
                      break;
                                case 't':
--                                      bTimeout=1;
++                                      bTimeout = TRUE;
                                        sscanf(cmd+i+2,"%d",&temp);
                                        timeout = temp;
                                        i+=3;
                                        while(cmd[i]!=' ' && cmd[i]!='\0') { i++; }
                                        i-=2;
                                        break;
++                case 'T':
++                                      topazmode = TRUE;
++                                      break;
                  default:
                      PrintAndLog("Invalid option");
                      return 0;
          PrintAndLog("Invalid char on input");
          return 0;
      }
++
      if(crc && datalen>0 && datalen<sizeof(data)-2)
      {
          uint8_t first, second;
++              if (topazmode) {
++                      ComputeCrc14443(CRC_14443_B, data, datalen, &first, &second);
++              } else {
          ComputeCrc14443(CRC_14443_A, data, datalen, &first, &second);
++              }
          data[datalen++] = first;
          data[datalen++] = second;
      }
      }
  
        if(bTimeout){
--          #define MAX_TIMEOUT 40542464        // (2^32-1) * (8*16) / 13560000Hz * 1000ms/s = 
++          #define MAX_TIMEOUT 40542464        // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s
          c.arg[0] |= ISO14A_SET_TIMEOUT;
          if(timeout > MAX_TIMEOUT) {
              timeout = MAX_TIMEOUT;
          }
                c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us)
        }
++
      if(power)
          c.arg[0] |= ISO14A_NO_DISCONNECT;
++
      if(datalen>0)
          c.arg[0] |= ISO14A_RAW;
  
++      if(topazmode)
++              c.arg[0] |= ISO14A_TOPAZMODE;
++              
        // Max buffer is USB_CMD_DATA_SIZE
      c.arg[1] = (datalen & 0xFFFF) | (numbits << 16);
      memcpy(c.d.asBytes,data,datalen);
      return 0;
  }
  
++
  static void waitCmd(uint8_t iSelect)
  {
      uint8_t *recv;
diff --combined client/cmdhfmfdes.c
index 75aaa084685a7ced8ea410a6c69d57d86dcc642c,0000000000000000000000000000000000000000..c3cdde2c944e7b4f2baabc35f01f49765552fac3
mode 100644,000000..100644
--- /dev/null
@@@ -1,685 -1,0 +1,686 @@@
- #include <openssl/des.h>
 +//-----------------------------------------------------------------------------
 +// Copyright (C) 2014 Iceman
 +//
 +// This code is licensed to you under the terms of the GNU GPL, version 2 or,
 +// at your option, any later version. See the LICENSE.txt file for the text of
 +// the license.
 +//-----------------------------------------------------------------------------
 +// High frequency MIFARE Desfire commands
 +//-----------------------------------------------------------------------------
 +
 +#include <stdio.h>
 +#include <stdlib.h>
 +#include <string.h>
 +#include <ctype.h>
-       if (  fsize & (1 << 0 ) )
++//#include <openssl/des.h>
++#include "loclass/des.h"
 +#include "cmdmain.h"
 +#include "proxmark3.h"
 +#include "../include/common.h"
 +#include "../include/mifare.h"
 +#include "../common/iso14443crc.h"
 +#include "data.h"
 +#include "ui.h"
 +#include "cmdparser.h"
 +#include "util.h"
 +#include "cmdhfmfdes.h"
 +
 +uint8_t CMDPOS = 0;
 +uint8_t LENPOS = 1;
 +
 +uint8_t key_zero_data[16] = { 0x00 };
 +uint8_t key_ones_data[16] = { 0x01 };
 +uint8_t key_defa_data[16] = { 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
 +uint8_t key_picc_data[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f };
 +
 +static int CmdHelp(const char *Cmd);
 +static void xor(unsigned char * dst, unsigned char * src, size_t len);
 +static int32_t le24toh (uint8_t data[3]);
 +
 +
 +int CmdHF14ADesWb(const char *Cmd)
 +{
 +/*    uint8_t blockNo = 0;
 +      uint8_t keyType = 0;
 +      uint8_t key[6] = {0, 0, 0, 0, 0, 0};
 +      uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
 +      
 +      char cmdp       = 0x00;
 +
 +      if (strlen(Cmd)<3) {
 +              PrintAndLog("Usage:  hf mf wrbl    <block number> <key A/B> <key (12 hex symbols)> <block data (32 hex symbols)>");
 +              PrintAndLog("        sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F");
 +              return 0;
 +      }       
 +
 +      blockNo = param_get8(Cmd, 0);
 +      cmdp = param_getchar(Cmd, 1);
 +      if (cmdp == 0x00) {
 +              PrintAndLog("Key type must be A or B");
 +              return 1;
 +      }
 +      if (cmdp != 'A' && cmdp != 'a') keyType = 1;
 +      if (param_gethex(Cmd, 2, key, 12)) {
 +              PrintAndLog("Key must include 12 HEX symbols");
 +              return 1;
 +      }
 +      if (param_gethex(Cmd, 3, bldata, 32)) {
 +              PrintAndLog("Block data must include 32 HEX symbols");
 +              return 1;
 +      }
 +      PrintAndLog("--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6));
 +      PrintAndLog("--data: %s", sprint_hex(bldata, 16));
 +      
 +  UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}};
 +      memcpy(c.d.asBytes, key, 6);
 +      memcpy(c.d.asBytes + 10, bldata, 16);
 +  SendCommand(&c);
 +
 +      UsbCommand resp;
 +      if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 +              uint8_t isOK  = resp.arg[0] & 0xff;
 +              PrintAndLog("isOk:%02x", isOK);
 +      } else {
 +              PrintAndLog("Command execute timeout");
 +      }
 + */
 +      return 0;
 +}
 +
 +int CmdHF14ADesRb(const char *Cmd)
 +{
 +      // uint8_t blockNo = 0;
 +      // uint8_t keyType = 0;
 +      // uint8_t key[6] = {0, 0, 0, 0, 0, 0};
 +      
 +      // char cmdp    = 0x00;
 +
 +
 +      // if (strlen(Cmd)<3) {
 +              // PrintAndLog("Usage:  hf mf rdbl    <block number> <key A/B> <key (12 hex symbols)>");
 +              // PrintAndLog("        sample: hf mf rdbl 0 A FFFFFFFFFFFF ");
 +              // return 0;
 +      // }    
 +      
 +      // blockNo = param_get8(Cmd, 0);
 +      // cmdp = param_getchar(Cmd, 1);
 +      // if (cmdp == 0x00) {
 +              // PrintAndLog("Key type must be A or B");
 +              // return 1;
 +      // }
 +      // if (cmdp != 'A' && cmdp != 'a') keyType = 1;
 +      // if (param_gethex(Cmd, 2, key, 12)) {
 +              // PrintAndLog("Key must include 12 HEX symbols");
 +              // return 1;
 +      // }
 +      // PrintAndLog("--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6));
 +      
 +  // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}};
 +      // memcpy(c.d.asBytes, key, 6);
 +  // SendCommand(&c);
 +
 +      // UsbCommand resp;
 +      // if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 +              // uint8_t                isOK  = resp.arg[0] & 0xff;
 +              // uint8_t              * data  = resp.d.asBytes;
 +
 +              // if (isOK)
 +                      // PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 16));
 +              // else
 +                      // PrintAndLog("isOk:%02x", isOK);
 +      // } else {
 +              // PrintAndLog("Command execute timeout");
 +      // }
 +
 +  return 0;
 +}
 +
 +int CmdHF14ADesInfo(const char *Cmd){
 +
 +      UsbCommand c = {CMD_MIFARE_DESFIRE_INFO};
 +    SendCommand(&c);
 +      UsbCommand resp;
 +      
 +      if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
 +              PrintAndLog("Command execute timeout");
 +              return 0;
 +      }
 +      uint8_t isOK  = resp.arg[0] & 0xff;
 +      if ( !isOK ){
 +              PrintAndLog("Command unsuccessful");
 +              return 0;
 +      }  
 +      PrintAndLog("");
 +      PrintAndLog("-- Desfire Information --------------------------------------");
 +      PrintAndLog("-------------------------------------------------------------");
 +      PrintAndLog("  UID                : %s",sprint_hex(resp.d.asBytes, 7));
 +      PrintAndLog("  Batch number       : %s",sprint_hex(resp.d.asBytes+28,5));
 +      PrintAndLog("  Production date    : week %02x, 20%02x",resp.d.asBytes[33], resp.d.asBytes[34]);
 +      PrintAndLog("  -----------------------------------------------------------");
 +      PrintAndLog("  Hardware Information");
 +      PrintAndLog("      Vendor Id      : %s", GetVendorStr(resp.d.asBytes[7]));
 +      PrintAndLog("      Type           : 0x%02X",resp.d.asBytes[8]);
 +      PrintAndLog("      Subtype        : 0x%02X",resp.d.asBytes[9]);
 +      PrintAndLog("      Version        : %d.%d",resp.d.asBytes[10], resp.d.asBytes[11]);
 +      PrintAndLog("      Storage size   : %s",GetCardSizeStr(resp.d.asBytes[12]));
 +      PrintAndLog("      Protocol       : %s",GetProtocolStr(resp.d.asBytes[13]));
 +      PrintAndLog("  -----------------------------------------------------------");
 +      PrintAndLog("  Software Information");
 +      PrintAndLog("      Vendor Id      : %s",GetVendorStr(resp.d.asBytes[14]));
 +      PrintAndLog("      Type           : 0x%02X",resp.d.asBytes[15]);
 +      PrintAndLog("      Subtype        : 0x%02X",resp.d.asBytes[16]);
 +      PrintAndLog("      Version        : %d.%d",resp.d.asBytes[17], resp.d.asBytes[18]);
 +      PrintAndLog("      storage size   : %s", GetCardSizeStr(resp.d.asBytes[19]));
 +      PrintAndLog("      Protocol       : %s", GetProtocolStr(resp.d.asBytes[20]));
 +      PrintAndLog("-------------------------------------------------------------");
 +      
 +      // Master Key settings
 +      GetKeySettings(NULL);
 +      
 +      // Free memory on card
 +      c.cmd = CMD_MIFARE_DESFIRE;
 +      c.arg[0] = (INIT | DISCONNECT);
 +      c.arg[1] = 0x01;
 +      c.d.asBytes[0] = GET_FREE_MEMORY;
 +    SendCommand(&c);
 +      if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 +              return 0;
 +      }  
 +      
 +      uint8_t tmp[3];
 +      memcpy(tmp, resp.d.asBytes+3,3); 
 +
 +      PrintAndLog("   Available free memory on card       : %d bytes", le24toh( tmp ));
 +      PrintAndLog("-------------------------------------------------------------");
 +
 +      /*
 +              Card Master key (CMK)        0x00 AID = 00 00 00 (card level)
 +              Application Master Key (AMK) 0x00 AID != 00 00 00
 +              Application keys (APK)       0x01-0x0D
 +              Application free             0x0E
 +              Application never            0x0F
 +              
 +              ACCESS RIGHTS:
 +              keys 0,1,2,3     C
 +              keys 4,5,6,7     RW
 +              keys 8,9,10,11   W
 +              keys 12,13,14,15 R
 +      
 +      */
 +      
 +    return 1;
 +}
 +
 +char * GetVendorStr( uint8_t id){
 +      static char buf[30];
 +      char *retStr = buf;
 +      
 +      if ( id == 0x04 )
 +              sprintf(retStr, "0x%02X (NXP)",id);
 +      else 
 +              sprintf(retStr,"0x%02X (Unknown)",id);
 +      return buf;
 +}
 +
 +/*
 +  The 7 MSBits (= n) code the storage size itself based on 2^n, 
 +  the LSBit is set to '0' if the size is exactly 2^n
 +      and set to '1' if the storage size is between 2^n and 2^(n+1). 
 +      For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'.
 +*/
 +char * GetCardSizeStr( uint8_t fsize ){
 + 
 +      static char buf[30];
 +      char *retStr = buf;
 +
 +      uint16_t usize = 1 << ((fsize >>1) + 1);
 +      uint16_t lsize = 1 << (fsize >>1);
 +      
 +      // is  LSB set?
-               sprintf(retStr,"0x%02X", id);   
++      if (  fsize & 1 )
 +              sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize);
 +      else 
 +              sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize);             
 +      return buf;
 +}
 +
 +char * GetProtocolStr(uint8_t id){
 +
 +      static char buf[30];
 +      char *retStr = buf;
 +
 +      if ( id == 0x05)
 +              sprintf(retStr,"0x%02X (ISO 14443-3, 14443-4)", id);
 +      else
++              sprintf(retStr,"0x%02X (Unknown)", id); 
 +      return buf;
 +}
 +
 +void GetKeySettings( uint8_t *aid){
 +      
 +      char messStr[512] = {0x00};
 +      char *str = messStr;
 +      uint8_t isOK = 0;
 +      uint32_t options = NONE;
 +      UsbCommand c;
 +      UsbCommand resp;
 +
 +      //memset(messStr, 0x00, 512);
 +      
 +      c.cmd = CMD_MIFARE_DESFIRE;
 +      
 +      if ( aid == NULL ){
 +              PrintAndLog(" CMK - PICC, Card Master Key settings ");
 +              PrintAndLog("");
 +              c.arg[CMDPOS] = (INIT | DISCONNECT);
 +              c.arg[LENPOS] =  0x01;
 +              c.d.asBytes[0] = GET_KEY_SETTINGS;  // 0x45
 +              SendCommand(&c);
 +              if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}  
 +              isOK  = resp.arg[0] & 0xff;
 +              if ( !isOK ){
 +                      PrintAndLog("   Can't select master application");      
 +                      return;
 +              }       
 +
 +              str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";     
 +              PrintAndLog("   [0x08] Configuration changeable       : %s", str);
 +              str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
 +              PrintAndLog("   [0x04] CMK required for create/delete : %s",str);
 +              str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
 +              PrintAndLog("   [0x02] Directory list access with CMK : %s",str);
 +              str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
 +              PrintAndLog("   [0x01] CMK is changeable              : %s", str);
 +                      
 +              c.arg[LENPOS] = 0x02; //LEN
 +              c.d.asBytes[0] = GET_KEY_VERSION; //0x64
 +              c.d.asBytes[1] = 0x00;
 +              SendCommand(&c);
 +              if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {
 +                      return;
 +              }
 +              isOK  = resp.arg[0] & 0xff;
 +              if ( !isOK ){
 +                      PrintAndLog("   Can't read key-version");
 +                      return;
 +              }
 +              PrintAndLog("");
 +              PrintAndLog("   Max number of keys       : %d", resp.d.asBytes[4]);
 +              PrintAndLog("   Master key Version       : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
 +              PrintAndLog("   ----------------------------------------------------------");
 +              
 +              c.arg[LENPOS] = 0x02; //LEN
 +              c.d.asBytes[0] = AUTHENTICATE; //0x0A
 +              c.d.asBytes[1] = 0x00; // KEY 0
 +              SendCommand(&c);
 +              if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
 +              isOK  = resp.d.asBytes[2] & 0xff;
 +              PrintAndLog("   [0x0A] Authenticate      : %s", ( isOK==0xAE ) ? "NO":"YES");
 +
 +              c.d.asBytes[0] = AUTHENTICATE_ISO; //0x1A
 +              SendCommand(&c);
 +              if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
 +              isOK  = resp.d.asBytes[2] & 0xff;
 +              PrintAndLog("   [0x1A] Authenticate ISO  : %s", ( isOK==0xAE ) ? "NO":"YES");
 +              
 +              c.d.asBytes[0] = AUTHENTICATE_AES; //0xAA
 +              SendCommand(&c);
 +              if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;}
 +              isOK  = resp.d.asBytes[2] & 0xff;
 +              PrintAndLog("   [0xAA] Authenticate AES  : %s", ( isOK==0xAE ) ? "NO":"YES");
 +              PrintAndLog("");
 +              PrintAndLog("   ----------------------------------------------------------");
 +              
 +      } else {
 +              PrintAndLog(" AMK - Application Master Key settings");
 +              
 +              // SELECT AID
 +              c.arg[0] = (INIT | CLEARTRACE);
 +              c.arg[LENPOS] = 0x04;
 +              c.d.asBytes[0] = SELECT_APPLICATION;  // 0x5a
 +              memcpy(c.d.asBytes+1, aid, 3);
 +              SendCommand(&c);
 +              
 +              if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
 +                      PrintAndLog("   Timed-out");
 +                      return;
 +              } 
 +              isOK  = resp.arg[0] & 0xff;
 +              if ( !isOK ){
 +                      PrintAndLog("   Can't select AID: %s",sprint_hex(aid,3));       
 +                      return;
 +              }               
 +              
 +              // KEY SETTINGS
 +              options = NONE;
 +              c.arg[0] = options;
 +              c.arg[LENPOS] = 0x01;
 +              c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45              
 +              SendCommand(&c);
 +              if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
 +                      return;
 +              }
 +              isOK  = resp.arg[0] & 0xff;
 +              if ( !isOK ){
 +                      PrintAndLog("   Can't read Application Master key settings");
 +              } else {
 +                      // Access rights.
 +                      uint8_t rights = (resp.d.asBytes[3] >> 4 && 0xff);
 +                      switch (rights){
 +                              case 0x00:
 +                                      str = "AMK authentication is necessary to change any key (default)";
 +                                      break;
 +                              case 0x0e:
 +                                      str = "Authentication with the key to be changed (same KeyNo) is necessary to change a key";
 +                                      break;
 +                              case 0x0f:
 +                                      str = "All keys (except AMK,see Bit0) within this application are frozen";
 +                                      break;
 +                              default:
 +                                      str = "Authentication with the specified key is necessary to change any ley. A change key and a PICC master key (CMK) can only be changed after authentication with the master key. For keys other then the master or change key, an authentication with the same key is needed.";
 +                                      break;
 +                      }
 +                      PrintAndLog("Changekey Access rights");
 +                      PrintAndLog("-- %s",str);
 +                      PrintAndLog("");        
 +                      // same as CMK
 +                      str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO";     
 +                      PrintAndLog("   0x08 Configuration changeable       : %s", str);
 +                      str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES";
 +                      PrintAndLog("   0x04 AMK required for create/delete : %s",str);
 +                      str = (resp.d.asBytes[3] & (1 << 1 )) ? "NO":"YES";
 +                      PrintAndLog("   0x02 Directory list access with AMK : %s",str);
 +                      str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO";
 +                      PrintAndLog("   0x01 AMK is changeable              : %s", str);
 +              }
 +              
 +              // KEY VERSION  - AMK 
 +              c.arg[0] = NONE;
 +              c.arg[LENPOS] = 0x02;
 +              c.d.asBytes[0] = GET_KEY_VERSION; //0x64
 +              c.d.asBytes[1] = 0x00;
 +              SendCommand(&c);
 +              if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
 +                      PrintAndLog("   Timed-out");
 +                      return;
 +              }
 +              
 +              int numOfKeys;
 +              
 +              isOK  = resp.arg[0] & 0xff;
 +              if ( !isOK ){
 +                      PrintAndLog("   Can't read Application Master key version. Trying all keys");
 +                      numOfKeys = MAX_NUM_KEYS;
 +              }
 +              else{
 +                      numOfKeys = resp.d.asBytes[4];
 +                      PrintAndLog("");
 +                      PrintAndLog("     Max number of keys  : %d", numOfKeys );
 +                      PrintAndLog("     Application Master key Version  : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]);
 +                      PrintAndLog("-------------------------------------------------------------");                   
 +              }
 +              
 +              // LOOP over numOfKeys that we got before. 
 +              // From 0x01 to numOfKeys.  We already got 0x00. (AMK)
 +              for(int i=0x01; i<=0x0f; ++i){
 +                                      
 +              }
 +              
 +              
 +      }
 +}
 +
 +int CmdHF14ADesEnumApplications(const char *Cmd){
 +      
 +      uint8_t isOK = 0x00;
 +      uint8_t aid[3];
 +      uint32_t options = (INIT | DISCONNECT);
 +      
 +      UsbCommand c = {CMD_MIFARE_DESFIRE, {options , 0x01 }};
 +      c.d.asBytes[0] = GET_APPLICATION_IDS;  //0x6a
 +      
 +    SendCommand(&c);
 +      UsbCommand resp;
 +              
 +      if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) {
 +              return 0;
 +      }  
 +      isOK  = resp.arg[0] & 0xff;
 +      if ( !isOK ){
 +              PrintAndLog("Command unsuccessful");
 +              return 0;
 +      } 
 +      PrintAndLog("");        
 +      PrintAndLog("-- Desfire Enumerate Applications ---------------------------");
 +      PrintAndLog("-------------------------------------------------------------");
 +
 +      UsbCommand respAid;
 +      UsbCommand respFiles;
 +      
 +      uint8_t num = 0;
 +      int max = resp.arg[1] -3 -2;
 +      
 +      for(int i=3; i<=max; i+=3){
 +              PrintAndLog(" Aid %d : %02X %02X %02X ",num ,resp.d.asBytes[i],resp.d.asBytes[i+1],resp.d.asBytes[i+2]);
 +              num++;
 +              
 +              aid[0] = resp.d.asBytes[i];
 +              aid[1] = resp.d.asBytes[i+1];
 +              aid[2] = resp.d.asBytes[i+2];
 +              GetKeySettings(aid);
 +              
 +              // Select Application
 +              c.arg[CMDPOS] = INIT;
 +              c.arg[LENPOS] = 0x04; 
 +              c.d.asBytes[0] = SELECT_APPLICATION;  // 0x5a
 +              c.d.asBytes[1] = resp.d.asBytes[i];
 +              c.d.asBytes[2] = resp.d.asBytes[i+1];           
 +              c.d.asBytes[3] = resp.d.asBytes[i+2];
 +              SendCommand(&c);
 +              
 +              if (!WaitForResponseTimeout(CMD_ACK,&respAid,1500) ) {
 +                      PrintAndLog("   Timed-out");
 +                      continue;
 +              } 
 +              isOK  = respAid.d.asBytes[2] & 0xff;
 +              if ( isOK != 0x00 ){
 +                      PrintAndLog("   Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3));  
 +                      continue;
 +              }
 +      
 +              // Get File IDs
 +              c.arg[CMDPOS] = NONE;
 +              c.arg[LENPOS] = 0x01;
 +              c.d.asBytes[0] = GET_FILE_IDS; // 0x6f
 +              SendCommand(&c);
 +              
 +              if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
 +                      PrintAndLog("   Timed-out");
 +                      continue;
 +              } else {
 +                      isOK  = respFiles.d.asBytes[2] & 0xff;
 +                      if ( !isOK ){
 +                              PrintAndLog("   Can't get file ids ");
 +                      } else {                        
 +                              int respfileLen = resp.arg[1]-3-2;                      
 +                              for (int j=0; j< respfileLen; ++j){
 +                                      PrintAndLog("   Fileid %d :", resp.d.asBytes[j+3]);
 +                              }
 +                      }
 +              }
 +              
 +              // Get ISO File IDs
 +              c.arg[CMDPOS] = DISCONNECT;
 +              c.arg[LENPOS] = 0x01;
 +              c.d.asBytes[0] = GET_ISOFILE_IDS; // 0x61
 +              SendCommand(&c);
 +              
 +              if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) {
 +                      PrintAndLog("   Timed-out");
 +                      continue;
 +              } else {
 +                      isOK  = respFiles.d.asBytes[2] & 0xff;
 +                      if ( !isOK ){
 +                              PrintAndLog("   Can't get ISO file ids ");
 +                      } else {                        
 +                              int respfileLen = resp.arg[1]-3-2;                      
 +                              for (int j=0; j< respfileLen; ++j){
 +                                      PrintAndLog(" ISO  Fileid %d :", resp.d.asBytes[j+3]);
 +                              }
 +                      }
 +              }
 +              
 +              
 +      }
 +      PrintAndLog("-------------------------------------------------------------");
 +      
 +      
 +      return 1;
 +}
 +
 +// MIAFRE DesFire Authentication
 +//
 +#define BUFSIZE 256 
 +int CmdHF14ADesAuth(const char *Cmd){
 +    
 +      // NR  DESC             KEYLENGHT
 +      // ------------------------
 +      // 1 = DES              8
 +      // 2 = 3DES             16
 +      // 3 = 3K 3DES  24
 +      // 4 = AES              16
 +
 +      uint8_t keylength = 8;
 +      unsigned char key[24];  
 +      
 +    if (strlen(Cmd)<3) {
 +        PrintAndLog("Usage:  hf mfdes auth <1|2|3> <1|2|3|4> <keyno> <key> ");
 +              PrintAndLog("               Auth modes");
 +              PrintAndLog("                 1 = normal, 2 = iso, 3 = aes");
 +              PrintAndLog("               Crypto");
 +              PrintAndLog("                 1 = DES 2 = 3DES 3 = 3K3DES 4 = AES");
 +              PrintAndLog("");
 +        PrintAndLog("        sample: hf mfdes auth 1 1 0 11223344");
 +              PrintAndLog("        sample: hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f");
 +        return 0;
 +    } 
 +      uint8_t cmdAuthMode     = param_get8(Cmd,0);
 +      uint8_t cmdAuthAlgo     = param_get8(Cmd,1);
 +      uint8_t cmdKeyNo        = param_get8(Cmd,2);
 +      
 +      switch (cmdAuthMode)
 +      {
 +              case 1: 
 +                      if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2) {
 +                              PrintAndLog("Crypto algo not valid for the auth mode");
 +                              return 1;
 +                      }
 +                      break;
 +              case 2:
 +                      if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2 && cmdAuthAlgo != 3) {
 +                              PrintAndLog("Crypto algo not valid for the auth mode");
 +                              return 1;
 +                      }
 +                      break;
 +              case 3:
 +                      if ( cmdAuthAlgo != 4) {
 +                              PrintAndLog("Crypto algo not valid for the auth mode");
 +                              return 1;
 +                      }
 +                      break;
 +              default:
 +                      PrintAndLog("Wrong Auth mode");
 +                      return 1;
 +                      break;
 +      }
 +      
 +      switch (cmdAuthAlgo){
 +              case 2: 
 +                      keylength = 16;
 +                      PrintAndLog("3DES selected");
 +                      break;
 +              case 3: 
 +                      keylength = 24;
 +                      PrintAndLog("3 key 3DES selected");
 +                      break;
 +              case 4:
 +                      keylength = 16;
 +                      PrintAndLog("AES selected");
 +                      break;
 +              default:
 +                      cmdAuthAlgo = 1;
 +                      keylength = 8;
 +                      PrintAndLog("DES selected");
 +                      break;
 +      }
 +
 +      // key
 +      if (param_gethex(Cmd, 3, key, keylength*2)) {
 +              PrintAndLog("Key must include %d HEX symbols", keylength);
 +              return 1;
 +      }
 +      // algo, nyckellängd, 
 +      UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }};
 +      
 +      c.d.asBytes[0] = keylength;
 +      memcpy(c.d.asBytes+1, key, keylength);
 +      
 +    SendCommand(&c);
 +      UsbCommand resp;
 +      
 +      if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) {
 +              PrintAndLog("Client command execute timeout");
 +              return 0;
 +      }  
 +
 +      uint8_t isOK  = resp.arg[0] & 0xff;
 +      if ( isOK) {
 +              uint8_t * data= resp.d.asBytes;
 +              
 +              PrintAndLog("  Key        :%s",sprint_hex(key, keylength));
 +              PrintAndLog("  SESSION    :%s",sprint_hex(data, keylength));
 +              PrintAndLog("-------------------------------------------------------------");
 +              //PrintAndLog("  Expected   :B5 21 9E E8 1A A7 49 9D 21 96 68 7E 13 97 38 56");
 +      } else{
 +              PrintAndLog("Client command failed.");
 +      }
 +      PrintAndLog("-------------------------------------------------------------");   
 +    return 1;
 +}
 +
 +
 +static void xor(unsigned char * dst, unsigned char * src, size_t len) {
 +   for( ; len > 0; len--,dst++,src++)
 +       *dst ^= *src;
 +}
 +
 +static int32_t le24toh (uint8_t data[3]) {
 +    return (data[2] << 16) | (data[1] << 8) | data[0];
 +}
 +
 +static command_t CommandTable[] =
 +{
 +  {"help",            CmdHelp,                                        1, "This help"},
 +  {"auth",            CmdHF14ADesAuth,                        0, "Tries a MIFARE DesFire Authentication"},
 +  {"rb",              CmdHF14ADesRb,                          0, "Read MIFARE DesFire block"},
 +  {"wb",              CmdHF14ADesWb,                          0, "write MIFARE DesFire block"},
 +  {"info",            CmdHF14ADesInfo,                        0, "Get MIFARE DesFire information"},
 +  {"enum",            CmdHF14ADesEnumApplications,0, "Tries enumerate all applications"},
 +  {NULL, NULL, 0, NULL}
 +};
 +
 +int CmdHFMFDes(const char *Cmd)
 +{
 +   // flush
 +   WaitForResponseTimeout(CMD_ACK,NULL,100);
 +   CmdsParse(CommandTable, Cmd);
 +  return 0;
 +}
 +
 +int CmdHelp(const char *Cmd)
 +{
 +  CmdsHelp(CommandTable);
 +  return 0;
 +}
 +
 +
diff --combined client/cmdhfmfu.c
index 75080f2513852972d8b55776709644c65d9b6ca6,8dfb9a3b1cceeb075f0facb06e37119a23a6c9e3..f85c160a59c419df9146e1ffb0d6b141352906c3
@@@ -7,7 -7,7 +7,6 @@@
  //-----------------------------------------------------------------------------
  // High frequency MIFARE ULTRALIGHT (C) commands
  //-----------------------------------------------------------------------------
--//#include <openssl/des.h>
  #include "loclass/des.h"
  #include "cmdhfmfu.h"
  #include "cmdhfmf.h"
@@@ -391,7 -391,7 +390,7 @@@ int CmdHF14AMfucAuth(const char *Cmd)
        //Change key to user defined one
        if (cmdp == 'k' || cmdp == 'K'){
                keyNo = param_get8(Cmd, 1);
--              if(keyNo >= 4) errors = true;
++              if(keyNo > 4) errors = true;
        }
  
        if (cmdp == 'h' || cmdp == 'H') {
                uint8_t * data= resp.d.asBytes;
  
                if (isOK){
--                      PrintAndLog("enc(RndB):%s", sprint_hex(data+1, 8));
                        memcpy(enc_random_b,data+1,8);
                } else {
                        PrintAndLog("Auth failed");
                PrintAndLog("Command execute timeout");
                return 1;
        }
--
        uint8_t iv[8]           = { 0 };
--      // Do we need random ? Right now we use all ones, is that random enough ?
--//    DES_random_key(&RndA);
  
        PrintAndLog("     RndA  :%s",sprint_hex(random_a, 8));
        PrintAndLog("     e_RndB:%s",sprint_hex(enc_random_b, 8));
  
                if (isOK){
                        PrintAndLog("enc(RndA'):%s", sprint_hex(data2+1, 8));
++                      
++                      uint8_t foo[8] = { 0 };
++                      uint8_t bar[8] = { 0 };
++                      memcpy(foo, data2+1, 8);
++                      des3_set2key_enc(&ctx, key);
++
++                      des3_crypt_cbc(&ctx    // des3_context *ctx
++                              , DES_DECRYPT      // int mode
++                              , 8      // size_t length
++                              , enc_random_b     // unsigned char iv[8]
++                              , foo           // const unsigned char *input
++                              , bar   // unsigned char *output
++                      );
++
++                      PrintAndLog("BAR:%s",sprint_hex(bar, 8));
++
++                      
                } else {
                        return 2;
                }
@@@ -601,16 -601,12 +613,16 @@@ int CmdTestDES(const char * cmd
  //
  int CmdHF14AMfUCRdBl(const char *Cmd)
  {
 +      bool hasPwd = FALSE;
        uint8_t blockNo = -1;
 +      unsigned char key[16];
        char cmdp = param_getchar(Cmd, 0);
        
        if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
 -              PrintAndLog("Usage:  hf mfu crdbl  <block number>");
 -              PrintAndLog("        sample: hf mfu crdbl 0");
 +              PrintAndLog("Usage:  hf mfu crdbl  <block number> <password>");
 +              PrintAndLog("");
 +              PrintAndLog("sample: hf mfu crdbl 0");
 +              PrintAndLog("        hf mfu crdbl 0 1122334455667788");
                return 0;
        }       
                
                return 1;
        } 
        
 -      PrintAndLog("--block no: 0x%02X (%d)", (int)blockNo, blockNo);
 +      // key
 +      if ( strlen(Cmd) > 3){
 +              if (param_gethex(Cmd, 1, key, 16)) {
 +                      PrintAndLog("Key must include %d HEX symbols", 16);
 +                      return 1;
 +              } else {
 +                      hasPwd = TRUE;
 +              }       
 +      }
 +      
 +      if ( hasPwd ) 
 +              PrintAndLog("--block no: 0x%02X (%d) PWD: %s", (int)blockNo, blockNo, key);
 +      else
 +              PrintAndLog("--block no: 0x%02X (%d)", (int)blockNo, blockNo);
  
        //Read Block
 -      UsbCommand e = {CMD_MIFAREU_READBL, {blockNo}};
 -      SendCommand(&e);
 -      UsbCommand resp_c;
 -      if (WaitForResponseTimeout(CMD_ACK,&resp_c,1500)) {
 -              uint8_t isOK = resp_c.arg[0] & 0xff;
 -              uint8_t *data = resp_c.d.asBytes;
 +      UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
 +      if ( hasPwd ) {
 +              c.arg[1] = 1;
 +              memcpy(c.d.asBytes,key,16);
 +      }
 +      SendCommand(&c);
 +      UsbCommand resp;
 +      if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 +              uint8_t isOK = resp.arg[0] & 0xff;
 +              uint8_t *data = resp.d.asBytes;
                
                PrintAndLog("isOk: %02x", isOK);
                if (isOK)
diff --combined client/cmdhfmfu.h
index c4bc03415c7bb8a8a7467a055d58495d32d614f8,c4bc03415c7bb8a8a7467a055d58495d32d614f8..ccb53ad0e99f793c92d957883e6eb61067f07e2e
@@@ -1,6 -1,6 +1,9 @@@
  #include "cmdhfmf.h"
  #include "cmdhf14a.h"
  
++#ifndef CMDHFMFU_H__
++#define CMDHFMFU_H__
++
  //standard ultralight
  int CmdHF14AMfUWrBl(const char *Cmd);
  int CmdHF14AMfURdBl(const char *Cmd);
@@@ -14,6 -14,6 +17,6 @@@ int CmdHF14AMfucAuth(const char *Cmd)
  int CmdHF14AMfUDump(const char *Cmd);
  void rol (uint8_t *data, const size_t len);
  
--
  int CmdHFMFUltra(const char *Cmd);
  int CmdHF14AMfUInfo(const char *Cmd);
++#endif
diff --combined client/cmdlf.c
index 46927f74a153ccf1dadb9ab86e3e6ece3d33fe88,0fab2adfa562fa75db73d507086f422c066e9510..30c8bb229fa98b6ffe86f73cac00bfcce24b58f3
@@@ -362,6 -362,7 +362,7 @@@ int usage_lf_read(
        PrintAndLog("Usage: lf read");
        PrintAndLog("Options:        ");
        PrintAndLog("       h            This help");
+       PrintAndLog("       s            silent run no printout");
        PrintAndLog("This function takes no arguments. ");
        PrintAndLog("Use 'lf config' to set parameters.");
        return 0;
@@@ -481,20 -482,17 +482,22 @@@ int CmdLFSetConfig(const char *Cmd
  int CmdLFRead(const char *Cmd)
  {
  
-       uint8_t cmdp =0;
-       if(param_getchar(Cmd, cmdp) == 'h')
+       uint8_t cmdp = 0;
+       bool arg1 = false;
+       if (param_getchar(Cmd, cmdp) == 'h')
        {
                return usage_lf_read();
        }
+       if (param_getchar(Cmd, cmdp) == 's') arg1 = true; //suppress print
        //And ship it to device
-       UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K};
+       UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {arg1,0,0}};
        SendCommand(&c);
 -      WaitForResponse(CMD_ACK,NULL);
 +      //WaitForResponse(CMD_ACK,NULL);        
 +      if ( !WaitForResponseTimeout(CMD_ACK,NULL,2500) ) {
 +              PrintAndLog("command execution time out");
 +              return 1;
 +      }
 +
        return 0;
  }
  
@@@ -1030,6 -1028,7 +1033,6 @@@ int CmdLFfind(const char *Cmd
      PrintAndLog("          : lf search 1   = use data from GraphBuffer & search for known tags");
      PrintAndLog("          : lf search u   = try reading data from tag & search for known and unknown tags");
      PrintAndLog("          : lf search 1 u = use data from GraphBuffer & search for known and unknown tags");
 -
      return 0;
    }
  
      return 0;
    }
    if (cmdp == 'u' || cmdp == 'U') testRaw = 'u';
-   
    PrintAndLog("NOTE: some demods output possible binary\n  if it finds something that looks like a tag");
    PrintAndLog("False Positives ARE possible\n");  
    PrintAndLog("\nChecking for known tags:\n");
-   
    ans=CmdFSKdemodIO("");
 +  
    if (ans>0) {
      PrintAndLog("\nValid IO Prox ID Found!");
      return 1;
    }
-   
    ans=CmdFSKdemodPyramid("");
    if (ans>0) {
      PrintAndLog("\nValid Pyramid ID Found!");
      return 1;
    }
-   
    ans=CmdFSKdemodParadox("");
    if (ans>0) {
      PrintAndLog("\nValid Paradox ID Found!");
      return 1;
    }
-   
    ans=CmdFSKdemodAWID("");
    if (ans>0) {
      PrintAndLog("\nValid AWID ID Found!");
      return 1;
    }
-   
    ans=CmdFSKdemodHID("");
    if (ans>0) {
      PrintAndLog("\nValid HID Prox ID Found!");
      return 1;
    }
    //add psk and indala
    ans=CmdIndalaDecode("");
    if (ans>0) {
      PrintAndLog("\nValid Indala ID Found!");
      return 1;
    }
    ans=CmdAskEM410xDemod("");
    if (ans>0) {
      PrintAndLog("\nValid EM410x ID Found!");
      return 1;
    }
    ans=CmdG_Prox_II_Demod("");
    if (ans>0) {
      PrintAndLog("\nValid G Prox II ID Found!");
      return 1;
    }
    PrintAndLog("\nNo Known Tags Found!\n");
    if (testRaw=='u' || testRaw=='U'){
      //test unknown tag formats (raw mode)
      PrintAndLog("\nChecking for Unknown tags:\n");
      ans=AutoCorrelate(4000, FALSE, FALSE);
 -    if (ans > 0) PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
 +      
 +    if (ans > 0) {
 +
 +              PrintAndLog("Possible Auto Correlation of %d repeating samples",ans);
 +
 +              if ( ans % 8 == 0)  {
 +                      int bytes = (ans / 8);
 +                      PrintAndLog("Possible %d bytes", bytes);
 +                      int blocks = 0;
 +                      if ( bytes % 2 == 0) {
 +                              blocks = (bytes / 2);   
 +                              PrintAndLog("Possible  2 blocks, width %d", blocks);
 +                      }
 +                      if ( bytes % 4 == 0) {
 +                              blocks = (bytes / 4);   
 +                              PrintAndLog("Possible  4 blocks, width %d", blocks);
 +                      }
 +                      if ( bytes % 8 == 0) {
 +                              blocks = (bytes / 8);   
 +                              PrintAndLog("Possible  8 blocks, width %d", blocks);
 +                      }
 +                      if ( bytes % 16 == 0) {
 +                              blocks = (bytes / 16);  
 +                              PrintAndLog("Possible 16 blocks, width %d", blocks);
 +                      }
 +              }
 +      }
      ans=GetFskClock("",FALSE,FALSE); //CmdDetectClockRate("F"); //
      if (ans != 0){ //fsk
        ans=FSKrawDemod("",FALSE);
  static command_t CommandTable[] = 
  {
    {"help",        CmdHelp,            1, "This help"},
 -  {"cmdread",     CmdLFCommandRead,   0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
    {"em4x",        CmdLFEM4X,          1, "{ EM4X RFIDs... }"},
 +  {"hid",         CmdLFHID,           1, "{ HID RFIDs... }"},
 +  {"hitag",       CmdLFHitag,         1, "{ HITAG RFIDs... }"},
 +  {"io",                CmdLFIO,                1, "{ IOPROX RFIDs... }"},
 +  {"pcf7931",     CmdLFPCF7931,       1, "{ PCF7931 RFIDs... }"},
 +  {"ti",          CmdLFTI,            1, "{ TI RFIDs... }"},
 +  {"t55xx",       CmdLFT55XX,         1, "{ T55X7 RFIDs... }"},
 +
    {"config",      CmdLFSetConfig,     0, "Set config for LF sampling, bit/sample, decimation, frequency"},
 + 
 +  {"cmdread",     CmdLFCommandRead,   0, "<off period> <'0' period> <'1' period> <command> ['h'] -- Modulate LF reader field to send command before read (all periods in microseconds) (option 'h' for 134)"},
    {"flexdemod",   CmdFlexdemod,       1, "Demodulate samples for FlexPass"},
 -  {"hid",         CmdLFHID,           1, "{ HID RFIDs... }"},
 -  {"io",                CmdLFIO,                1, "{ ioProx tags... }"},
    {"indalademod", CmdIndalaDemod,     1, "['224'] -- Demodulate samples for Indala 64 bit UID (option '224' for 224 bit)"},
    {"indalaclone", CmdIndalaClone,     0, "<UID> ['l']-- Clone Indala to T55x7 (tag must be in antenna)(UID in HEX)(option 'l' for 224 UID"},
-   {"read",        CmdLFRead,          0, "Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
+   {"read",        CmdLFRead,          0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
    {"search",      CmdLFfind,          1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"},
    {"sim",         CmdLFSim,           0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
    {"simask",      CmdLFaskSim,        0, "[clock] [invert <1|0>] [manchester/raw <'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
    {"simbidir",    CmdLFSimBidir,      0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
    //{"simman",      CmdLFSimManchester, 0, "<Clock> <Bitstream> [GAP] Simulate arbitrary Manchester LF tag"},
    {"snoop",       CmdLFSnoop,         0, "['l'|'h'|<divisor>] [trigger threshold]-- Snoop LF (l:125khz, h:134khz)"},
 -  {"ti",          CmdLFTI,            1, "{ TI RFIDs... }"},
 -  {"hitag",       CmdLFHitag,         1, "{ Hitag tags and transponders... }"},
    {"vchdemod",    CmdVchDemod,        1, "['clone'] -- Demodulate samples for VeriChip"},
 -  {"t55xx",       CmdLFT55XX,         1, "{ T55xx RFIDs... }"},
 -  {"pcf7931",     CmdLFPCF7931,       1, "{PCF7931 RFIDs...}"},
    {NULL, NULL, 0, NULL}
  };
  
index 91445d43ecaee998667157ed80d41e36c37ef710,a1793ba602e132745cf9d5bae15b927276d17c56..4f61cf7884866c79ec61df24cd4d869dfb899547
@@@ -98,9 -98,10 +98,9 @@@ function test(
                        elseif _ == 1 then
  
                                local config = pcmd:format(config1, y, config2)
 -                              dbg(('lf t55xx wr 0 %s'):format(config))
 +                              dbg(('lf t55xx write 0 %s'):format(config))
                                
 -                              config = tonumber(config,16) 
 -                              local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config}
 +                              local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK, arg1 = config ,arg2 = 0, arg3 = 0}
                                local err = core.SendCommand(writecmd:getBytes())
                                if err then return oops(err) end
                                local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT)
@@@ -129,4 -130,4 +129,4 @@@ local function main(args
        test()
        print( string.rep('--',20) )
  end
- main(args)
+ main(args)
diff --combined common/Makefile.common
index 445ede1f779b3353dc4a8c1559c46b43ef92375d,2b2bb2fbd7c47fa514d5d2c05dadd890b9a69400..7e264d286a8a5a61186834f75ae0c22fd0f313ca
@@@ -66,13 -66,11 +66,11 @@@ VPATH = . ../common/ ../fpga
  
  INCLUDES = ../include/proxmark3.h ../include/at91sam7s512.h ../include/config_gpio.h ../include/usb_cmd.h $(APP_INCLUDES)
  
 -CFLAGS =  -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 $(APP_CFLAGS) -Os
 +CFLAGS =  -c $(INCLUDE) -Wall -Werror -pedantic -std=c99 -Os $(APP_CFLAGS)
  LDFLAGS = -nostartfiles -nodefaultlibs -Wl,-gc-sections -n
  
  LIBS = -lgcc
  
- LIBS = -lgcc 
  THUMBOBJ = $(patsubst %.c,$(OBJDIR)/%.o,$(THUMBSRC))
  ARMOBJ   = $(ARMSRC:%.c=$(OBJDIR)/%.o)
  ASMOBJ   = $(patsubst %.s,$(OBJDIR)/%.o,$(ASMSRC))
diff --combined common/lfdemod.c
index 5b90f1c4a2eef6d20942c5e685085a9132e7c348,c7acb404bac93319c4176eafb494654200a96cf6..3305c8b0c53e84adb4cdd992c28c3a51fac531b2
@@@ -75,51 -75,6 +75,6 @@@ uint8_t preambleSearch(uint8_t *BitStre
    return 0;
  }
  
- //by marshmellow
- //takes 1s and 0s and searches for EM410x format - output EM ID
- uint64_t Em410xDecodeOld(uint8_t *BitStream, size_t *size, size_t *startIdx)
- {
-   //no arguments needed - built this way in case we want this to be a direct call from "data " cmds in the future
-   //  otherwise could be a void with no arguments
-   //set defaults
-   uint64_t lo=0;
-   uint32_t i = 0;
-   if (BitStream[1]>1){  //allow only 1s and 0s
-     // PrintAndLog("no data found");
-     return 0;
-   }
-   // 111111111 bit pattern represent start of frame
-   uint8_t preamble[] = {1,1,1,1,1,1,1,1,1};
-   uint32_t idx = 0;
-   uint32_t parityBits = 0;
-   uint8_t errChk = 0;
-   *startIdx = 0;
-   for (uint8_t extraBitChk=0; extraBitChk<5; extraBitChk++){
-     errChk = preambleSearch(BitStream+extraBitChk+*startIdx, preamble, sizeof(preamble), size, startIdx);
-     if (errChk == 0) return 0;
-     idx = *startIdx + 9;
-     for (i=0; i<10;i++){ //loop through 10 sets of 5 bits (50-10p = 40 bits)
-       parityBits = bytebits_to_byte(BitStream+(i*5)+idx,5);
-       //check even parity
-       if (parityTest(parityBits, 5, 0) == 0){
-         //parity failed try next bit (in the case of 1111111111) but last 9 = preamble
-         startIdx++;
-         errChk = 0;
-         break;
-       }
-       //set uint64 with ID from BitStream
-       for (uint8_t ii=0; ii<4; ii++){
-         lo = (lo << 1LL) | (BitStream[(i*5)+ii+idx]);
-       }
-     }
-     if (errChk != 0) return lo;
-     //skip last 5 bit parity test for simplicity.
-     // *size = 64;
-   }
-   return 0;
- }
  //by marshmellow
  //takes 1s and 0s and searches for EM410x format - output EM ID
  uint8_t Em410xDecode(uint8_t *BitStream, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo)
    for (uint8_t extraBitChk=0; extraBitChk<5; extraBitChk++){
      errChk = preambleSearch(BitStream+extraBitChk+*startIdx, preamble, sizeof(preamble), size, startIdx);
      if (errChk == 0) return 0;
 +      if (*size<64) return 0;
      if (*size>64) FmtLen = 22;
+     if (*size<64) return 0;
      idx = *startIdx + 9;
      for (i=0; i<FmtLen; i++){ //loop through 10 or 22 sets of 5 bits (50-10p = 40 bits or 88 bits)
        parityBits = bytebits_to_byte(BitStream+(i*5)+idx,5);
@@@ -309,16 -264,12 +265,12 @@@ int ManchesterEncode(uint8_t *BitStream
  //run through 2 times and take least errCnt
  int manrawdecode(uint8_t * BitStream, size_t *size)
  {
-       uint16_t bitnum=0;
-       uint16_t MaxBits = 500;
-       uint16_t errCnt = 0;
-       size_t i=1;
-       uint16_t bestErr = 1000;
-       uint16_t bestRun = 0;
-       size_t ii=1;
+       uint16_t bitnum=0, MaxBits = 512, errCnt = 0;
+       size_t i, ii;
+       uint16_t bestErr = 1000, bestRun = 0;
        if (size == 0) return -1;
-       for (ii=1;ii<3;++ii){
-               i=1;
+       for (ii=0;ii<2;++ii){
+               i=0;
                for (i=i+ii;i<*size-2;i+=2){
                        if(BitStream[i]==1 && (BitStream[i+1]==0)){
                        } else if((BitStream[i]==0)&& BitStream[i+1]==1){
        errCnt=bestErr;
        if (errCnt<20){
                ii=bestRun;
-               i=1;
+               i=0;
                for (i=i+ii; i < *size-2; i+=2){
                        if(BitStream[i] == 1 && (BitStream[i+1] == 0)){
                                BitStream[bitnum++]=0;
  //by marshmellow
  //take 01 or 10 = 1 and 11 or 00 = 0
  //check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010
+ //decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding
  int BiphaseRawDecode(uint8_t *BitStream, size_t *size, int offset, int invert)
  {
        uint16_t bitnum=0;
        if (!offsetA && offsetB) offset++;
        for (i=offset; i<*size-3; i+=2){
                //check for phase error
-               if (i<*size-3 && BitStream[i+1]==BitStream[i+2]) {
+               if (BitStream[i+1]==BitStream[i+2]) {
                        BitStream[bitnum++]=77;
                        errCnt++;
                }
@@@ -413,6 -365,56 +366,56 @@@ void askAmp(uint8_t *BitStream, size_t 
        return;
  }
  
+ int cleanAskRawDemod(uint8_t *BinStream, size_t *size, int clk, int invert, int high, int low)
+ {
+       size_t bitCnt=0, smplCnt=0, errCnt=0;
+       uint8_t waveHigh = 0;
+       //PrintAndLog("clk: %d", clk);
+       for (size_t i=0; i < *size; i++){
+               if (BinStream[i] >= high && waveHigh){
+                       smplCnt++;
+               } else if (BinStream[i] <= low && !waveHigh){
+                       smplCnt++;
+               } else { //transition
+                       if ((BinStream[i] >= high && !waveHigh) || (BinStream[i] <= low && waveHigh)){
+                               if (smplCnt > clk-(clk/4)-1) { //full clock
+                                       if (smplCnt > clk + (clk/4)+1) { //too many samples
+                                               errCnt++;
+                                               BinStream[bitCnt++]=77;
+                                       } else if (waveHigh) {
+                                               BinStream[bitCnt++] = invert;
+                                               BinStream[bitCnt++] = invert;
+                                       } else if (!waveHigh) {
+                                               BinStream[bitCnt++] = invert ^ 1;
+                                               BinStream[bitCnt++] = invert ^ 1;
+                                       }
+                                       waveHigh ^= 1;  
+                                       smplCnt = 0;
+                               } else if (smplCnt > (clk/2) - (clk/4)-1) {
+                                       if (waveHigh) {
+                                               BinStream[bitCnt++] = invert;
+                                       } else if (!waveHigh) {
+                                               BinStream[bitCnt++] = invert ^ 1;
+                                       }
+                                       waveHigh ^= 1;  
+                                       smplCnt = 0;
+                               } else if (!bitCnt) {
+                                       //first bit
+                                       waveHigh = (BinStream[i] >= high);
+                                       smplCnt = 1;
+                               } else {
+                                       smplCnt++;
+                                       //transition bit oops
+                               }
+                       } else { //haven't hit new high or new low yet
+                               smplCnt++;
+                       }
+               }
+       }
+       *size = bitCnt;
+       return errCnt;
+ }
  //by marshmellow
  //takes 3 arguments - clock, invert and maxErr as integers
  //attempts to demodulate ask only
@@@ -424,15 -426,22 +427,22 @@@ int askrawdemod(uint8_t *BinStream, siz
        if (*clk==0) return -1;
        if (start<0) return -1;
        if (*invert != 0 && *invert != 1) *invert =0;
+       if (amp==1) askAmp(BinStream, *size);
        uint32_t initLoopMax = 200;
        if (initLoopMax > *size) initLoopMax=*size;
        // Detect high and lows
-       //25% fuzz in case highs and lows aren't clipped [marshmellow]
+       //25% clip in case highs and lows aren't clipped [marshmellow]
+       uint8_t clip = 75;
        int high, low, ans;
-       if (amp==1) askAmp(BinStream, *size);
-       ans = getHiLo(BinStream, initLoopMax, &high, &low, 75, 75);
+       ans = getHiLo(BinStream, initLoopMax, &high, &low, clip, clip);
        if (ans<1) return -1; //just noise
  
+       if (DetectCleanAskWave(BinStream, *size, high, low)) {
+               //PrintAndLog("Clean");
+               return cleanAskRawDemod(BinStream, size, *clk, *invert, high, low);
+       }
        //PrintAndLog("DEBUG - valid high: %d - valid low: %d",high,low);
        int lastBit = 0;  //set first clock check
        uint32_t bitnum = 0;     //output counter
        uint32_t gLen = *size;
        if (gLen > 500) gLen=500;
        //if 0 errors allowed then only try first 2 clock cycles as we want a low tolerance
-       if (!maxErr) gLen=*clk*2; 
+       if (!maxErr) gLen = *clk * 2; 
        uint8_t errCnt =0;
        uint32_t bestStart = *size;
        uint32_t bestErrCnt = maxErr; //(*size/1000);
        uint8_t midBit=0;
        uint16_t MaxBits=1000;
        //PrintAndLog("DEBUG - lastbit - %d",lastBit);
        //loop to find first wave that works
        for (iii=start; iii < gLen; ++iii){
@@@ -620,7 -630,9 +631,9 @@@ size_t fsk_wave_demod(uint8_t * dest, s
                                //do nothing with extra garbage
                        } else if ((idx-last_transition) < (fchigh-1)) { //6-8 = 8 waves
                                dest[numBits]=1;
-                       } else {                                                        //9+ = 10 waves
+                       } else if ((idx-last_transition) > (fchigh+1) && !numBits) { //12 + and first bit = garbage 
+                               //do nothing with beginning garbage
+                       } else {                                         //9+ = 10 waves
                                dest[numBits]=0;
                        }
                        last_transition = idx;
@@@ -644,18 -656,31 +657,31 @@@ size_t aggregate_bits(uint8_t *dest, si
        uint32_t idx=0;
        size_t numBits=0;
        uint32_t n=1;
+       float lowWaves = (((float)(rfLen))/((float)fclow));
+       float highWaves = (((float)(rfLen))/((float)fchigh));
        for( idx=1; idx < size; idx++) {
  
                if (dest[idx]==lastval) {
                        n++;
                        continue;
                }
+               n++;
                //if lastval was 1, we have a 1->0 crossing
-               if ( dest[idx-1]==1 ) {
-                       n=myround2((float)(n+1)/((float)(rfLen)/(float)fclow));
-               } else {// 0->1 crossing
-                       n=myround2((float)(n+1)/((float)(rfLen-1)/(float)fchigh));  //-1 for fudge factor
+               if (dest[idx-1]==1) {
+                       if (!numBits && n < (uint8_t)lowWaves) {
+                               n=0;
+                               lastval = dest[idx];
+                               continue;
+                       }
+                       n=myround2(((float)n)/lowWaves);
+               } else {// 0->1 crossing 
+                       //test first bitsample too small
+                       if (!numBits && n < (uint8_t)highWaves) {
+                               n=0;
+                               lastval = dest[idx];
+                               continue;
+                       }
+                       n = myround2(((float)n)/highWaves);  //-1 for fudge factor
                }
                if (n == 0) n = 1;
  
                n=0;
                lastval=dest[idx];
        }//end for
+       // if valid extra bits at the end were all the same frequency - add them in
+       if (n > lowWaves && n > highWaves) {
+               if (dest[idx-2]==1) {
+                       n=myround2((float)(n+1)/((float)(rfLen)/(float)fclow));
+               } else {
+                       n=myround2((float)(n+1)/((float)(rfLen-1)/(float)fchigh));  //-1 for fudge factor                       
+               }
+               memset(dest, dest[idx-1]^invert , n);
+               numBits += n;
+       }
        return numBits;
  }
  //by marshmellow  (from holiman's base)
@@@ -857,20 -893,70 +894,70 @@@ int PyramiddemodFSK(uint8_t *dest, size
  
  uint8_t DetectCleanAskWave(uint8_t dest[], size_t size, int high, int low)
  {
-       uint8_t allPeaks=1;
+       uint16_t allPeaks=1;
        uint16_t cntPeaks=0;
-       for (size_t i=20; i<255; i++){
+       size_t loopEnd = 572;
+       if (loopEnd > size) loopEnd = size;
+       for (size_t i=60; i<loopEnd; i++){
                if (dest[i]>low && dest[i]<high) 
                        allPeaks=0;
                else
                        cntPeaks++;
        }
-       if (allPeaks==0){
-               if (cntPeaks>190) return 1;
+       if (allPeaks == 0){
+               if (cntPeaks > 300) return 1;
        }
        return allPeaks;
  }
  
+ int DetectStrongAskClock(uint8_t dest[], size_t size)
+ {
+       int clk[]={0,8,16,32,40,50,64,100,128,256};
+   size_t idx = 40;
+       uint8_t high=0;
+       size_t cnt = 0;
+       size_t highCnt = 0;
+       size_t highCnt2 = 0;
+       for (;idx < size; idx++){
+               if (dest[idx]>128) {
+                       if (!high){
+                               high=1;
+                               if (cnt > highCnt){
+                                       if (highCnt != 0) highCnt2 = highCnt;
+                                       highCnt = cnt;
+                               } else if (cnt > highCnt2) {
+                                       highCnt2 = cnt;
+                               }
+                               cnt=1;
+                       } else {
+                               cnt++;
+                       }
+               } else if (dest[idx] <= 128){
+                       if (high) {
+                               high=0;
+                               if (cnt > highCnt) {
+                                       if (highCnt != 0) highCnt2 = highCnt;
+                                       highCnt = cnt;
+                               } else if (cnt > highCnt2) {
+                                       highCnt2 = cnt;
+                               }
+                               cnt=1;
+                       } else {
+                               cnt++;
+                       }
+               }
+       }
+       uint8_t tol;
+       for (idx=8; idx>0; idx--){
+               tol = clk[idx]/8;
+               if (clk[idx] >= highCnt - tol && clk[idx] <= highCnt + tol)
+                       return clk[idx];
+               if (clk[idx] >= highCnt2 - tol && clk[idx] <= highCnt2 + tol)
+                       return clk[idx];
+       }
+       return -1;
+ }
  // by marshmellow
  // not perfect especially with lower clocks or VERY good antennas (heavy wave clipping)
  // maybe somehow adjust peak trimming value based on samples to fix?
@@@ -893,24 -979,14 +980,14 @@@ int DetectASKClock(uint8_t dest[], size
    
    //test for large clean peaks
    if (DetectCleanAskWave(dest, size, peak, low)==1){
-         uint16_t fcTest=0;
-         uint8_t mostFC=0;
-         fcTest=countFC(dest, size, &mostFC);
-         uint8_t fc1 = fcTest >> 8;
-         uint8_t fc2 = fcTest & 0xFF;
-         for (i=0; i<8; i++){
-               if (clk[i] == fc1) {
-                       *clock=fc1;
-                       return 0;
-               }
-               if (clk[i] == fc2) {
-                       *clock=fc2;
+       int ans = DetectStrongAskClock(dest, size);
+         for (i=7; i>0; i--){
+               if (clk[i] == ans) {
+                       *clock=ans;
                        return 0;
                }
          }
    }
-   
    int ii;
    int clkCnt;
    int tol = 0;
      }else{
        tol=0;
      }
+       if (!maxErr) loopCnt=clk[clkCnt]*2;
      bestErr[clkCnt]=1000;
      //try lining up the peaks by moving starting point (try first 256)
      for (ii=0; ii < loopCnt; ii++){
@@@ -1243,11 -1320,10 +1321,10 @@@ int nrzRawDemod(uint8_t *dest, size_t *
    *clk = DetectNRZClock(dest, *size, *clk);
    if (*clk==0) return -2;
    uint32_t i;
-   int high, low, ans;
-   ans = getHiLo(dest, 1260, &high, &low, 75, 75); //25% fuzz on high 25% fuzz on low
-   if (ans<1) return -2; //just noise
-   uint32_t gLen = 256;
+   uint32_t gLen = 4096;
    if (gLen>*size) gLen = *size;
+   int high, low;
+   if (getHiLo(dest, gLen, &high, &low, 75, 75) < 1) return -3; //25% fuzz on high 25% fuzz on low
    int lastBit = 0;  //set first clock check
    uint32_t bitnum = 0;     //output counter
    uint8_t tol = 1;  //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave
    uint32_t bestErrCnt = maxErr+1;
    uint32_t bestPeakCnt = 0;
    uint32_t bestPeakStart=0;
+   uint8_t bestFirstPeakHigh=0;
+   uint8_t firstPeakHigh=0;
    uint8_t curBit=0;
    uint8_t bitHigh=0;
    uint8_t errBitHigh=0;
    //loop to find first wave that works - align to clock
    for (iii=0; iii < gLen; ++iii){
      if ((dest[iii]>=high) || (dest[iii]<=low)){
+       if (dest[iii]>=high) firstPeakHigh=1;
+       else firstPeakHigh=0;
        lastBit=iii-*clk;
        peakCnt=0;
        errCnt=0;
          //possible good read
          if (errCnt == 0){
            //bestStart = iii;
+           bestFirstPeakHigh=firstPeakHigh;
            bestErrCnt = errCnt;
            bestPeakCnt = peakCnt;
            bestPeakStart = iii;
            //bestStart = iii;
          }
          if (peakCnt > bestPeakCnt){
+           bestFirstPeakHigh=firstPeakHigh;
            bestPeakCnt=peakCnt;
            bestPeakStart=iii;
          } 
      iii=bestPeakStart;
      lastBit=bestPeakStart-*clk;
      bitnum=0;
+     memset(dest, bestFirstPeakHigh^1, bestPeakStart / *clk);
+     bitnum += (bestPeakStart / *clk);
      for (i = iii; i < *size; ++i) {
        //if we found a high bar and we are at a clock bit
        if ((dest[i] >= high ) && (i>=lastBit+*clk-tol && i<=lastBit+*clk+tol)){
      *size=bitnum;
    } else{
      *size=bitnum;
-     return -1;
+     return bestErrCnt;
    }
  
    if (bitnum>16){
      *size=bitnum;
-   } else return -1;
+   } else return -5;
    return errCnt;
  }
  
@@@ -1667,22 -1751,22 +1752,22 @@@ int pskRawDemod(uint8_t dest[], size_t 
    //find first phase shift
    for (i=0; i<loopCnt; i++){
      if (dest[i]+fc < dest[i+1] && dest[i+1] >= dest[i+2]){
 -      waveEnd = i+1;
 -      //PrintAndLog("DEBUG: waveEnd: %d",waveEnd);
 -      waveLenCnt = waveEnd-waveStart;
 +        waveEnd = i+1;
 +        //PrintAndLog("DEBUG: waveEnd: %d",waveEnd);
 +        waveLenCnt = waveEnd-waveStart;
        if (waveLenCnt > fc && waveStart > fc){ //not first peak and is a large wave 
          lastAvgWaveVal = avgWaveVal/(waveLenCnt);
 -        firstFullWave = waveStart;
 -        fullWaveLen=waveLenCnt;
 -        //if average wave value is > graph 0 then it is an up wave or a 1
 +          firstFullWave = waveStart;
 +          fullWaveLen=waveLenCnt;
 +          //if average wave value is > graph 0 then it is an up wave or a 1
          if (lastAvgWaveVal > 123) curPhase^=1;  //fudge graph 0 a little 123 vs 128
 -        break;
 -      } 
 +          break;
 +        
        waveStart = i+1;
        avgWaveVal = 0;
 -    }
 +      }
      avgWaveVal+=dest[i+2];
 -  }
 +    }
    //PrintAndLog("DEBUG: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen);  
    lastClkBit = firstFullWave; //set start of wave as clock align
    //PrintAndLog("DEBUG: clk: %d, lastClkBit: %d", *clock, lastClkBit);
    errCnt=0;
    size_t numBits=0;
    //set skipped bits
-   memset(dest+numBits,curPhase^1,firstFullWave / *clock);
+   memset(dest,curPhase^1,firstFullWave / *clock);
    numBits += (firstFullWave / *clock);
    dest[numBits++] = curPhase; //set first read bit
    for (i = firstFullWave+fullWaveLen-1; i < *size-3; i++){
          waveEnd = i+1;
          waveLenCnt = waveEnd-waveStart;
          lastAvgWaveVal = avgWaveVal/waveLenCnt;
 -        if (waveLenCnt > fc){  
 +        if (waveLenCnt > fc){ 
            //PrintAndLog("DEBUG: avgWaveVal: %d, waveSum: %d",lastAvgWaveVal,avgWaveVal);
            //if this wave is a phase shift
            //PrintAndLog("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+*clock-tol,i+1,fc);
diff --combined common/protocols.h
index 01b738c2b6076ec1fed19d7d47dd2b2033683442,01b738c2b6076ec1fed19d7d47dd2b2033683442..3cdf79f92a87b9616ba991491db8ad303cf03bb2
@@@ -168,9 -168,9 +168,25 @@@ NXP/Philips CUSTOM COMMAND
  #define ISO15693_READ_MULTI_SECSTATUS 0x2C
  
  
++// Topaz command set:
++#define       TOPAZ_REQA                                              0x26    // Request
++#define       TOPAZ_WUPA                                              0x52    // WakeUp
++#define       TOPAZ_RID                                               0x78    // Read ID
++#define       TOPAZ_RALL                                              0x00    // Read All (all bytes)
++#define       TOPAZ_READ                                              0x01    // Read (a single byte)
++#define       TOPAZ_WRITE_E                                   0x53    // Write-with-erase (a single byte)
++#define       TOPAZ_WRITE_NE                                  0x1a    // Write-no-erase (a single byte)
++// additional commands for Dynamic Memory Model
++#define TOPAZ_RSEG                                            0x10    // Read segment
++#define TOPAZ_READ8                                           0x02    // Read (eight bytes)
++#define TOPAZ_WRITE_E8                                        0x54    // Write-with-erase (eight bytes)
++#define TOPAZ_WRITE_NE8                                       0x1B    // Write-no-erase (eight bytes)
++
++
  #define ISO_14443A 0
  #define ICLASS     1
  #define ISO_14443B 2
++#define TOPAZ         3
  
  //-- Picopass fuses
  #define FUSE_FPERS   0x80
diff --combined include/mifare.h
index 403132ac8a8294c75598050632503a2109a93083,e2b7a7c5548e2fd37dde3864173cfe08ea95a8b7..89ff758e20727266698385204dc05e2f5b60c0e7
@@@ -11,7 -11,7 +11,7 @@@
  #ifndef _MIFARE_H_
  #define _MIFARE_H_
  
 -#include "common.h"
 +#include "../include/common.h"
  
  //-----------------------------------------------------------------------------
  // ISO 14443A
@@@ -26,14 -26,14 +26,15 @@@ typedef struct 
  } __attribute__((__packed__)) iso14a_card_select_t;
  
  typedef enum ISO14A_COMMAND {
--      ISO14A_CONNECT = 1,
--      ISO14A_NO_DISCONNECT = 2,
--      ISO14A_APDU = 4,
--      ISO14A_RAW = 8,
--      ISO14A_REQUEST_TRIGGER = 0x10,
--      ISO14A_APPEND_CRC = 0x20,
--      ISO14A_SET_TIMEOUT = 0x40,
--      ISO14A_NO_SELECT = 0x80
++      ISO14A_CONNECT =                        (1 << 0),
++      ISO14A_NO_DISCONNECT =          (1 << 1),
++      ISO14A_APDU =                           (1 << 2),
++      ISO14A_RAW =                            (1 << 3),
++      ISO14A_REQUEST_TRIGGER =        (1 << 4),
++      ISO14A_APPEND_CRC =                     (1 << 5),
++      ISO14A_SET_TIMEOUT =            (1 << 6),
++      ISO14A_NO_SELECT =                      (1 << 7),
++      ISO14A_TOPAZMODE =                      (1 << 8)
  } iso14a_command_t;
  
  #endif // _MIFARE_H_
Impressum, Datenschutz