]> git.zerfleddert.de Git - proxmark3-svn/commitdiff
Merge branch 'master' of https://github.com/Proxmark/proxmark3
authoriceman1001 <iceman@iuse.se>
Sat, 23 May 2015 06:16:40 +0000 (08:16 +0200)
committericeman1001 <iceman@iuse.se>
Sat, 23 May 2015 06:16:40 +0000 (08:16 +0200)
Conflicts:
README.txt
armsrc/appmain.c
armsrc/apps.h
armsrc/des.c
armsrc/iclass.c
armsrc/mifarecmd.c
armsrc/mifareutil.c
armsrc/mifareutil.h
client/cmddata.c
client/cmdhf.c
client/cmdhf14a.c
client/cmdhficlass.c
client/cmdhfmfu.c
client/cmdhfmfu.h
client/cmdscript.c
client/lualibs/commands.lua
client/lualibs/html_dumplib.lua
client/scripting.c
client/util.c
common/protocols.h
include/usb_cmd.h

19 files changed:
1  2 
README.txt
armsrc/appmain.c
armsrc/des.h
armsrc/iso14443a.c
armsrc/lfops.c
armsrc/mifarecmd.c
armsrc/mifareutil.c
armsrc/mifareutil.h
client/cmdhf.c
client/cmdhficlass.c
client/cmdhfmf.c
client/cmdhfmfu.c
client/cmdhfmfu.h
client/lualibs/html_dumplib.lua
client/nonce2key/crapto1.c
client/scripting.c
client/util.c
common/protocols.h
include/usb_cmd.h

diff --combined README.txt
index 05829dac22cd2123610b2982daa3d4b4b6181e03,1a4ddb6d0e693b3192f7270a5b8326d75b4fd86a..e510e792059a09ba4d15325e23f1aa6f86f6a6ab
@@@ -1,68 -1,87 +1,70 @@@
 +The iceman fork.
 +
  NOTICE:
 -(2014-03-26)
 -This is now the official Proxmark repository!
  
 -INTRODUCTION:
 +The official Proxmark repository is found here: https://github.com/Proxmark/proxmark3
  
 -The proxmark3 is a powerful general purpose RFID tool, the size of a deck
 -of cards, designed to snoop, listen and emulate everything from
 -Low Frequency (125kHz) to High Frequency (13.56MHz) tags.
  
 -This repository contains enough software, logic (for the FPGA), and design
 -documentation for the hardware that you could, at least in theory,
 -do something useful with a proxmark3.
 +NEWS:      
  
 -RESOURCES:
 +Whats in this fork?  I have scraped the web for different enhancements to the PM3 source code and not all of them ever found their way to the master branch. 
 +Among the stuff is
  
 -   * This repository!
 -      https://github.com/Proxmark/proxmark3
 -      
 -   * The Wiki
 -      https://github.com/Proxmark/proxmark3/wiki
 -      
 -   * The GitHub page
 -      http://proxmark.github.io/proxmark3/
 -      
 -   * The Forum
 -      http://www.proxmark.org/forum
 -      
 -   * The IRC chanel
 -       irc.freenode.org #proxmark3
 -       -or-
 -       http://webchat.freenode.net/?channels=#proxmark3
 -   
 -DEVELOPMENT:
 +      * Jonor's hf 14a raw timing patch
 +      * Piwi's updates. (usually gets into the master)
 +      * Holiman's iclass, (usually gets into the master)
 +      * Marshmellow's LF fixes
 +      * Midnitesnake's Ultralight,  Ultralight-c enhancements
 +      * Izsh's lf peak modification / iir-filtering
 +      * Aspers's tips and tricks from inside the PM3-gui-tool, settings.xml and other stuff.
 +      * My own desfire, Ultralight extras, LF T55xx enhancements, bugs fixes (filelength, hf mf commands ), TNP3xxx lua scripts,  Awid26,  skidata scripts (will come)
 +      * other obscure patches like for the sammy-mode,  (offline you know), tagidentifications, defaultkeys. 
 +      
 +Give me a hint, and I'll see if I can't merge in the stuff you have. 
  
 -The tools required to build  or run the project will vary depending on
 -your operating system. Please refer to the Wiki for details.
 +I don't actually know how to make small pull-request to github :( and that is the number one reason for me not pushing a lot of things back to the PM3 master.
 +      
 +PM3 GUI:
  
 -   * https://github.com/Proxmark/proxmark3/wiki
 +I do tend to rename and move stuff around, the official PM3-GUI from Gaucho will not work so well. *sorry*    
 +
 +        
 +DEVELOPMENT:
  
 -OBTAINING HARDWARE:
 +This fork is adjusted to compile on windows/mingw environment with Qt5.3.1 & GCC 4.8
 +For people with linux you will need to patch some source code and some small change to one makefile.  If you are lazy, you google the forum and find asper's or holimans makefile or you find your solution below.
 +
 +Common errors linux/macOS finds
 +Error:
-       * loclass/fileutils.c:15:2: warning: implicit declaration of function ‘_stat’ [-Wimplicit-function-declaration]
++      * loclass/fileutils.c:15:2: warning: implicit declaration of function \91_stat\92 [-Wimplicit-function-declaration]
 +Solution:
 +      * Remove the "unscore" sign.   In linux you use without underscore, in windows you need a underscore. 
 +      
 +Error:  
 +      * \client\makefile  the parameter -lgdi32 
 +Solution:
 +      * Remove parameter.
 +      
 +Error:  
 +      * Using older Qt4.6 gives compilation errors.  
 +Solution
 +      * Upgrade to Qt5.3.1 
 +      OR 
 +      * Change these two line in  \client\makefile
 +              CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui -I$(QTDIR)/include/QtWidgets  -I/mingw/include
 +              QTLDLIBS = -L$(QTDIR)/lib  -lQt5Core -lQt5Gui -lQt5Widgets 
 +              
 +              TO
 +              
 +              CXXFLAGS = -I$(QTDIR)/include -I$(QTDIR)/include/QtCore -I$(QTDIR)/include/QtGui
 +              QTLDLIBS = -L$(QTDIR)/lib -lQtCore4 -lQtGui4
 +      
 +
 +An old Qt4 version makefile is found here: http://www.icesql.se/proxmark3/code/linuxmakefile.txt  but this one doesn't have all new files in it. So I don't recommend it.
  
+ The Proxmark 3 is available for purchase (assembled and tested) from the
+ following locations:
  
 -   * http://proxmark3.com/
 -   * http://www.xfpga.com/
 -
 -Most of the ultra-low-volume contract assemblers could put
 -something like this together with a reasonable yield. A run of around
 -a dozen units is probably cost-effective. The BOM includes (possibly-
 -outdated) component pricing, and everything is available from Digikey
 -and the usual distributors.
 -
 -If you've never assembled a modern circuit board by hand, then this is
 -not a good place to start. Some of the components (e.g. the crystals)
 -must not be assembled with a soldering iron, and require hot air.
 -
 -The schematics are included; the component values given are not
 -necessarily correct for all situations, but it should be possible to do
 -nearly anything you would want with appropriate population options.
 -
 -The printed circuit board artwork is also available, as Gerbers and an
 -Excellon drill file.
 -
 -
 -LICENSING:
 -
 -This program is free software; you can redistribute it and/or modify
 -it under the terms of the GNU General Public License as published by
 -the Free Software Foundation; either version 2 of the License, or
 -(at your option) any later version.
 -
 -This program is distributed in the hope that it will be useful,
 -but WITHOUT ANY WARRANTY; without even the implied warranty of
 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 -GNU General Public License for more details.
 -
 -You should have received a copy of the GNU General Public License
 -along with this program; if not, write to the Free Software
 -Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 -
 -
 -Jonathan Westhues
 -user jwesthues, at host cq.cx
  
 -May 2007, Cambridge MA
 +January 2015, Sweden
 +iceman at host iuse.se
diff --combined armsrc/appmain.c
index b19e079b15876adcb1a76c19f7aad6633fe12118,96644b9a09e039062130d5fae52c34952c3032d1..04503a4fa58da584f36518d7d226dbfc25309602
  // executes.
  //-----------------------------------------------------------------------------
  
 -#include "usb_cdc.h"
 -#include "cmd.h"
 -
 -#include "proxmark3.h"
 +#include "../common/usb_cdc.h"
 +#include "../common/cmd.h"
 +#include "../include/proxmark3.h"
 +#include "../include/hitag2.h"
  #include "apps.h"
  #include "util.h"
  #include "printf.h"
  #include "string.h"
 -
  #include <stdarg.h>
 -
  #include "legicrf.h"
 -#include <hitag2.h>
  #include "lfsampling.h"
  #include "BigBuf.h"
 +
  #ifdef WITH_LCD
   #include "LCD.h"
  #endif
@@@ -178,7 -180,7 +178,7 @@@ void MeasureAntennaTuning(void
        int i, adcval = 0, peak = 0, peakv = 0, peakf = 0; //ptr = 0 
        int vLf125 = 0, vLf134 = 0, vHf = 0;    // in mV
  
 -      LED_B_ON();
 +  LED_B_ON();
  
  /*
   * Sweeps the useful LF range of the proxmark from
  
        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)
@@@ -368,7 -370,7 +368,7 @@@ void SamyRun(
        for (;;)
        {
                usb_poll();
 -    WDT_HIT();
 +              WDT_HIT();
  
                // Was our button held down or pressed?
                int button_pressed = BUTTON_HELD(1000);
@@@ -638,7 -640,7 +638,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
                        ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes);
                        break;
  #endif
-             
  #ifdef WITH_ISO15693
                case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693:
                        AcquireRawAdcSamplesIso15693();
  
  #ifdef WITH_ISO14443a
                case CMD_SNOOP_ISO_14443a:
 -                      SnoopIso14443a(c->arg[0]);
 +                      SniffIso14443a(c->arg[0]);
                        break;
                case CMD_READER_ISO_14443a:
                        ReaderIso14443a(c);
                        EPA_PACE_Collect_Nonce(c);
                        break;
                        
 +              // case CMD_EPA_:
 +              //      EpaFoo(c);
 +              // break;
 +                      
                case CMD_READER_MIFARE:
 -                      ReaderMifare(c->arg[0]);
 +            ReaderMifare(c->arg[0]);
                        break;
                case CMD_MIFARE_READBL:
                        MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        break;
                case CMD_MIFAREU_READCARD:
                        MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
-                       break;          
+                       break;
                case CMD_MIFAREUC_SETPWD: 
                        MifareUSetPwd(c->arg[0], c->d.asBytes);
                        break;
                        break;
                case CMD_MIFAREU_WRITEBL_COMPAT:
                        MifareUWriteBlock(c->arg[0], c->d.asBytes);
-             break;
+                       break;
                case CMD_MIFAREU_WRITEBL:
+                       MifareUWriteBlock_Special(c->arg[0], c->d.asBytes);
 +                      MifareUWriteBlock_Special(c->arg[0], c->arg[1], c->d.asBytes);
                        break;
                case CMD_MIFARE_NESTED:
                        MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
                        SniffMifare(c->arg[0]);
                        break;
  
 +              //mifare desfire
 +              case CMD_MIFARE_DESFIRE_READBL: break;
 +              case CMD_MIFARE_DESFIRE_WRITEBL: break;
 +              case CMD_MIFARE_DESFIRE_AUTH1:
 +                      MifareDES_Auth1(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
 +                      break;
 +              case CMD_MIFARE_DESFIRE_AUTH2:
 +                      //MifareDES_Auth2(c->arg[0],c->d.asBytes);
 +                      break;
 +              case CMD_MIFARE_DES_READER:
 +                      //readermifaredes(c->arg[0], c->arg[1], c->d.asBytes);
 +                      break;
 +              case CMD_MIFARE_DESFIRE_INFO:
 +                      MifareDesfireGetInformation();
 +                      break;
 +              case CMD_MIFARE_DESFIRE:
 +                      MifareSendCommand(c->arg[0], c->arg[1], c->d.asBytes);
 +                      break;
 +
 +              case CMD_MIFARE_COLLECT_NONCES:
 +                      MifareCollectNonces(c->arg[0], c->arg[1]);
 +                      break;
  #endif
  
  #ifdef WITH_ICLASS
                        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]);
@@@ -1061,7 -1037,7 +1062,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/des.h
index 880413e93a215e88026486cca07f0c613ee419ad,90f742464ba6d4ed41988c81f2cf33b8c4dc77ec..3379463a612ce5fd3062a941fdced0d3df16a6ac
@@@ -96,10 -96,10 +96,13 @@@ void tdes_enc(void* out, const void* in
   * \param key pointer to the key (192 bit = 24 byte)
   */
   void tdes_dec(void* out, const void* in, const void* key);
 + 
 + void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
 + void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
  
+  void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
+  void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]);
  #endif /*DES_H_*/
  
  // Copied from des.h in desfire imp.
diff --combined armsrc/iso14443a.c
index c6628c07470aecfe862620fc9239fd13b6b94838,64bbcbf50eaaa456123163bc16bd115a13e77ef2..e1943b2654eea613892db908e836991b8c381c5a
@@@ -15,6 -15,7 +15,6 @@@
  #include "util.h"
  #include "string.h"
  #include "cmd.h"
 -
  #include "iso14443crc.h"
  #include "iso14443a.h"
  #include "crapto1.h"
@@@ -212,12 -213,6 +212,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;
 +      
 +      Uart.byteCntMax = 0;
 +      Uart.posCnt = 0;
 +      Uart.syncBit = 9999;
  }
  
  void UartInit(uint8_t *data, uint8_t *parity)
  {
        Uart.output = data;
        Uart.parity = parity;
 +      Uart.fourBits = 0x00000000;                     // clear the buffer for 4 Bits
        UartReset();
  }
  
  static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
  {
  
 -      Uart.twoBits = (Uart.twoBits << 8) | bit;
 +      Uart.fourBits = (Uart.fourBits << 8) | bit;
        
        if (Uart.state == STATE_UNSYNCD) {                                                                                      // not yet synced
        
 -              if (Uart.highCnt < 2) {                                                                                                 // wait for a stable unmodulated signal
 -                      if (Uart.twoBits == 0xffff) {
 -                              Uart.highCnt++;
 -                      } else {
 -                              Uart.highCnt = 0;
 -                      }
 -              } else {        
 -                      Uart.syncBit = 0xFFFF;                                                                                          // not set
 -                                                                                                                                                              // we look for a ...1111111100x11111xxxxxx pattern (the start bit)
 -                      if              ((Uart.twoBits & 0xDF00) == 0x1F00) Uart.syncBit = 8;           // mask is   11x11111 xxxxxxxx, 
 -                                                                                                                                                              // check for 00x11111 xxxxxxxx
 -                      else if ((Uart.twoBits & 0xEF80) == 0x8F80) Uart.syncBit = 7;           // both masks shifted right one bit, left padded with '1'
 -                      else if ((Uart.twoBits & 0xF7C0) == 0xC7C0) Uart.syncBit = 6;           // ...
 -                      else if ((Uart.twoBits & 0xFBE0) == 0xE3E0) Uart.syncBit = 5;
 -                      else if ((Uart.twoBits & 0xFDF0) == 0xF1F0) Uart.syncBit = 4;
 -                      else if ((Uart.twoBits & 0xFEF8) == 0xF8F8) Uart.syncBit = 3;
 -                      else if ((Uart.twoBits & 0xFF7C) == 0xFC7C) Uart.syncBit = 2;
 -                      else if ((Uart.twoBits & 0xFFBE) == 0xFE3E) Uart.syncBit = 1;
 -                      if (Uart.syncBit != 0xFFFF) {                                                                           // found a sync bit
 +              Uart.syncBit = 9999;                                                                                                    // not set
 +              
 +              // 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated           Sequence Z (a "0" or "start of communication")
 +              // 11111111 8 ticks unmodulation                                                                        Sequence Y (a "0" or "end of communication" or "no information")
 +              // 111100x1 4 ticks unmodulated followed by 2|3 ticks pause                     Sequence X (a "1")
 +
 +              // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from
 +              // Sequence X followed by Sequence Y followed by Sequence Z     (111100x1 11111111 00x11111)
 +              // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern 
 +              // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's)
 +              //
 +#define ISO14443A_STARTBIT_MASK               0x07FFEF80              // mask is    00001111 11111111 1110 1111 10000000
 +#define ISO14443A_STARTBIT_PATTERN    0x07FF8F80              // pattern is 00001111 11111111 1000 1111 10000000
 +
 +              if              ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1;
 +              else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0;
 +
 +              if (Uart.syncBit != 9999) {                                                                                             // found a sync bit
                                Uart.startTime = non_real_time?non_real_time:(GetCountSspClk() & 0xfffffff8);
                                Uart.startTime -= Uart.syncBit;
                                Uart.endTime = Uart.startTime;
                                Uart.state = STATE_START_OF_COMMUNICATION;
                        }
 -              }
  
        } else {
  
 -              if (IsMillerModulationNibble1(Uart.twoBits >> Uart.syncBit)) {                  
 -                      if (IsMillerModulationNibble2(Uart.twoBits >> Uart.syncBit)) {          // Modulation in both halves - error
 +              if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) {                 
 +                      if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) {         // Modulation in both halves - error
                                UartReset();
                        } else {                                                                                                                        // Modulation in first half = Sequence Z = logic "0"
                                if (Uart.state == STATE_MILLER_X) {                                                             // error - must not follow after X
                                }
                        }
                } 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
@@@ -444,11 -430,6 +444,11 @@@ void DemodReset(
        Demod.highCnt = 0;
        Demod.startTime = 0;
        Demod.endTime = 0;
 +      
 +      //
 +      Demod.bitCount = 0;
 +      Demod.syncBit = 0xFFFF;
 +      Demod.samples = 0;
  }
  
  void DemodInit(uint8_t *data, uint8_t *parity)
@@@ -547,7 -528,9 +547,7 @@@ static RAMFUNC int ManchesterDecoding(u
                                }
                        }
                }
 -                      
        } 
 -
      return FALSE;     // not finished yet, need more data
  }
  
  // triggering so that we start recording at the point that the tag is moved
  // near the reader.
  //-----------------------------------------------------------------------------
 -void RAMFUNC SnoopIso14443a(uint8_t param) {
 +void RAMFUNC SniffIso14443a(uint8_t param) {
        // param:
        // bit 0 - trigger from first card answer
        // bit 1 - trigger from first reader 7-bit request
  
                                        // 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);
@@@ -935,15 -915,8 +935,15 @@@ bool prepare_allocated_tag_modulation(t
  // Main loop of simulated tag: receive commands from reader, decide what
  // response to send, and send it.
  //-----------------------------------------------------------------------------
 -void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
 +void SimulateIso14443aTag(int tagType, int flags, int uid_2nd, byte_t* data)
  {
 +
 +      //Here, we collect UID,NT,AR,NR,UID2,NT2,AR2,NR2
 +      // This can be used in a reader-only attack.
 +      // (it can also be retrieved via 'hf 14a list', but hey...
 +      uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0,0,0};
 +      uint8_t ar_nr_collected = 0;
 +      
        uint8_t sak;
  
        // The first response contains the ATQA (note: bytes are transmitted in reverse order).
                        response1[0] = 0x01;
                        response1[1] = 0x0f;
                        sak = 0x01;
 -              } break;                
 +              } break;
 +              case 6: { // MIFARE Mini
 +                      // Says: I am a Mifare Mini, 320b
 +                      response1[0] = 0x44;
 +                      response1[1] = 0x00;
 +                      sak = 0x09;
 +              } break;
                default: {
                        Dbprintf("Error: unkown tagtype (%d)",tagType);
                        return;
        // Check if the uid uses the (optional) part
        uint8_t response2a[5] = {0x00};
        
 -      if (uid_2nd) {
 +      if (flags & FLAG_7B_UID_IN_DATA) {
                response2[0] = 0x88;
 -              num_to_bytes(uid_1st,3,response2+1);
 -              num_to_bytes(uid_2nd,4,response2a);
 +              response2[1] = data[0];
 +              response2[2] = data[1];
 +              response2[3] = data[2];
 +
 +              response2a[0] = data[3];
 +              response2a[1] = data[4];
 +              response2a[2] = data[5];
 +              response2a[3] = data[7];
                response2a[4] = response2a[0] ^ response2a[1] ^ response2a[2] ^ response2a[3];
  
                // Configure the ATQA and SAK accordingly
                response1[0] |= 0x40;
                sak |= 0x04;
        } else {
 -              num_to_bytes(uid_1st,4,response2);
 +              memcpy(response2, data, 4);
 +              //num_to_bytes(uid_1st,4,response2);
                // Configure the ATQA and SAK accordingly
                response1[0] &= 0xBF;
                sak &= 0xFB;
                        if (tracing) {
                                LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, TRUE);
                        }
 +                      uint32_t nonce = bytes_to_num(response5,4);
                        uint32_t nr = bytes_to_num(receivedCmd,4);
                        uint32_t ar = bytes_to_num(receivedCmd+4,4);
 -                      Dbprintf("Auth attempt {nr}{ar}: %08x %08x",nr,ar);
 +                      //Dbprintf("Auth attempt {nonce}{nr}{ar}: %08x %08x %08x", nonce, nr, ar);
 +
 +                      if(flags & FLAG_NR_AR_ATTACK )
 +                      {
 +                              if(ar_nr_collected < 2){
 +                                      // Avoid duplicates... probably not necessary, nr should vary. 
 +                                      //if(ar_nr_responses[3] != nr){                                         
 +                                              ar_nr_responses[ar_nr_collected*5]   = 0;
 +                                              ar_nr_responses[ar_nr_collected*5+1] = 0;
 +                                              ar_nr_responses[ar_nr_collected*5+2] = nonce;
 +                                              ar_nr_responses[ar_nr_collected*5+3] = nr;
 +                                              ar_nr_responses[ar_nr_collected*5+4] = ar;
 +                                              ar_nr_collected++;
 +                                      //}
 +                              }                       
 +
 +                              if(ar_nr_collected > 1 ) {
 +                              
 +                                      if (MF_DBGLEVEL >= 2) {
 +                                                      Dbprintf("Collected two pairs of AR/NR which can be used to extract keys from reader:");
 +                                                      Dbprintf("../tools/mfkey/mfkey32 %07x%08x %08x %08x %08x %08x %08x",
 +                                                              ar_nr_responses[0], // UID1
 +                                                              ar_nr_responses[1], // UID2
 +                                                              ar_nr_responses[2], // NT
 +                                                              ar_nr_responses[3], // AR1
 +                                                              ar_nr_responses[4], // NR1
 +                                                              ar_nr_responses[8], // AR2
 +                                                              ar_nr_responses[9]  // NR2
 +                                                      );
 +                                      }
 +                                      uint8_t len = ar_nr_collected*5*4;
 +                                      cmd_send(CMD_ACK,CMD_SIMULATE_MIFARE_CARD,len,0,&ar_nr_responses,len);
 +                                      ar_nr_collected = 0;
 +                                      memset(ar_nr_responses, 0x00, len);
 +                                      Dbprintf("ICE");
 +                              }
 +                      }
                } else {
                        // Check for ISO 14443A-4 compliant commands, look at left nibble
                        switch (receivedCmd[0]) {
                }
        }
  
 +      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 +      
        Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
        LED_A_OFF();
        BigBuf_free_keep_EM();
@@@ -1416,7 -1337,7 +1416,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
@@@ -1680,7 -1601,7 +1680,7 @@@ bool EmLogTrace(uint8_t *reader_data, u
  //-----------------------------------------------------------------------------
  static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset)
  {
 -      uint32_t c;
 +      uint32_t c = 0x00;
        
        // Set FPGA mode to "reader listen mode", no modulation (listen
        // only, since we are receiving, not transmitting).
        // clear RXRDY:
      uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
  
 -      c = 0;
        for(;;) {
                WDT_HIT();
  
        }
  }
  
 +
  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
@@@ -1801,11 -1719,6 +1801,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.
@@@ -1938,7 -1851,7 +1938,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(10*106); // 10ms default
  }
  
  int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) {
@@@ -2014,38 -1927,15 +2014,38 @@@ void ReaderIso14443a(UsbCommand *c
  
        if(param & ISO14A_RAW) {
                if(param & ISO14A_APPEND_CRC) {
 -                      AppendCrc14443a(cmd,len);
 +                      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));
  // Therefore try in alternating directions.
  int32_t dist_nt(uint32_t nt1, uint32_t nt2) {
  
 -      uint16_t i;
 -      uint32_t nttmp1, nttmp2;
 -
        if (nt1 == nt2) return 0;
  
 -      nttmp1 = nt1;
 -      nttmp2 = nt2;
 +      uint16_t i;
 +      uint32_t nttmp1 = nt1;
 +      uint32_t nttmp2 = nt2;
        
        for (i = 1; i < 32768; i++) {
                nttmp1 = prng_successor(nttmp1, 1);
  // Cloning MiFare Classic Rail and Building Passes, Anywhere, Anytime"
  // (article by Nicolas T. Courtois, 2009)
  //-----------------------------------------------------------------------------
 -void ReaderMifare(bool first_try)
 -{
 -      // Mifare AUTH
 -      uint8_t mf_auth[]    = { 0x60,0x00,0xf5,0x7b };
 -      uint8_t mf_nr_ar[]   = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
 -      static uint8_t mf_nr_ar3;
 -
 -      uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
 -      uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
 -
 +void ReaderMifare(bool first_try) {
        // free eventually allocated BigBuf memory. We want all for tracing.
        BigBuf_free();
        
        clear_trace();
        set_tracing(TRUE);
  
 +      // Mifare AUTH
 +      uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b };
 +      uint8_t mf_nr_ar[8] = { 0x00 }; //{ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 };
 +      static uint8_t mf_nr_ar3 = 0;
 +
 +      uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = { 0x00 };
 +      uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = { 0x00 };
 +
        byte_t nt_diff = 0;
        uint8_t par[1] = {0};   // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough
        static byte_t par_low = 0;
        bool led_on = TRUE;
 -      uint8_t uid[10]  ={0};
 -      uint32_t cuid;
 +      uint8_t uid[10] = {0x00};
 +      //uint32_t cuid = 0x00;
  
        uint32_t nt = 0;
        uint32_t previous_nt = 0;
        byte_t par_list[8] = {0x00};
        byte_t ks_list[8] = {0x00};
  
 -      static uint32_t sync_time;
 -      static uint32_t sync_cycles;
 +      static uint32_t sync_time = 0;
 +      static uint32_t sync_cycles = 0;
        int catch_up_cycles = 0;
        int last_catch_up = 0;
        uint16_t consecutive_resyncs = 0;
        int isOK = 0;
  
 +      int numWrongDistance = 0;
 +      
        if (first_try) { 
                mf_nr_ar3 = 0;
                iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
        LED_A_ON();
        LED_B_OFF();
        LED_C_OFF();
 -      
 +      LED_C_ON();     
    
        for(uint16_t i = 0; TRUE; i++) {
                
                WDT_HIT();
  
                // Test if the action was cancelled
 -              if(BUTTON_PRESS()) {
 +              if(BUTTON_PRESS()) break;
 +              
 +              if (numWrongDistance > 1000) {
 +                      isOK = 0;
                        break;
                }
                
 -              LED_C_ON();
 -
 -              if(!iso14443a_select_card(uid, NULL, &cuid)) {
 +              //if(!iso14443a_select_card(uid, NULL, &cuid)) {
 +              if(!iso14443a_select_card(uid, NULL, NULL)) {
                        if (MF_DBGLEVEL >= 1)   Dbprintf("Mifare: Can't select card");
                        continue;
                }
                                nt_attacked = nt;
                        }
                        else {
 -                              if (nt_distance == -99999) { // invalid nonce received, try again
 +                              
 +                              // invalid nonce received, try again
 +                              if (nt_distance == -99999) { 
 +                                      numWrongDistance++;
 +                                      if (MF_DBGLEVEL >= 3) Dbprintf("The two nonces has invalid distance, tag could have good PRNG\n");
                                        continue;
                                }
 +                              
                                sync_cycles = (sync_cycles - nt_distance);
                                if (MF_DBGLEVEL >= 3) Dbprintf("calibrating in cycle %d. nt_distance=%d, Sync_cycles: %d\n", i, nt_distance, sync_cycles);
                                continue;
  
                if ((nt != nt_attacked) && nt_attacked) {       // we somehow lost sync. Try to catch up again...
                        catch_up_cycles = -dist_nt(nt_attacked, nt);
 -                      if (catch_up_cycles == 99999) {                 // invalid nonce received. Don't resync on that one.
 +                      if (catch_up_cycles >= 99999) {                 // invalid nonce received. Don't resync on that one.
                                catch_up_cycles = 0;
                                continue;
                        }
                }
        }
  
 -
        mf_nr_ar[3] &= 0x1F;
        
 -      byte_t buf[28];
 +      byte_t buf[28] = {0x00};
 +      
        memcpy(buf + 0,  uid, 4);
        num_to_bytes(nt, 4, buf + 4);
        memcpy(buf + 8,  par_list, 8);
                
        cmd_send(CMD_ACK,isOK,0,0,buf,28);
  
 -      // Thats it...
 +      set_tracing(FALSE);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
        LEDsoff();
 -
 -      set_tracing(FALSE);
  }
  
 -/**
 +
 + /*
    *MIFARE 1K simulate.
    *
    *@param flags :
@@@ -2490,7 -2375,7 +2490,7 @@@ void Mifare1ksim(uint8_t flags, uint8_
                                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;
 +                              }
                                }
  
                                // --- crypto
                                        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
 -                                      ar_nr_responses[1], //NT
 -                                      ar_nr_responses[2], //AR1
 -                                      ar_nr_responses[3], //NR1
 -                                      ar_nr_responses[6], //AR2
 -                                      ar_nr_responses[7] //NR2
 +                                      ar_nr_responses[1], // NT
 +                                      ar_nr_responses[2], // AR1
 +                                      ar_nr_responses[3], // NR1
 +                                      ar_nr_responses[6], // AR2
 +                                      ar_nr_responses[7]  // NR2
                                        );
                } else {
                        Dbprintf("Failed to obtain two AR/NR pairs!");
 -                      if(ar_nr_collected >0) {
 +                      if(ar_nr_collected > 0 ) {
                                Dbprintf("Only got these: UID=%08x, nonce=%08x, AR1=%08x, NR1=%08x",
                                                ar_nr_responses[0], // UID
 -                                              ar_nr_responses[1], //NT
 -                                              ar_nr_responses[2], //AR1
 -                                              ar_nr_responses[3] //NR1
 +                                              ar_nr_responses[1], // NT
 +                                              ar_nr_responses[2], // AR1
 +                                              ar_nr_responses[3]  // NR1
                                                );
                        }
                }
  }
  
  
 -
  //-----------------------------------------------------------------------------
  // MIFARE sniffer. 
  // 
@@@ -2811,9 -2692,6 +2811,9 @@@ void RAMFUNC SniffMifare(uint8_t param
        // bit 0 - trigger from first card answer
        // bit 1 - trigger from first reader 7-bit request
  
 +      // free eventually allocated BigBuf memory
 +      BigBuf_free();
 +      
        // C(red) A(yellow) B(green)
        LEDsoff();
        // init trace buffer
        uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE];
        uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE];
  
 -      // As we receive stuff, we copy it from receivedCmd or receivedResponse
 -      // into trace, along with its length and other annotations.
 -      //uint8_t *trace = (uint8_t *)BigBuf;
 -      
 -      // free eventually allocated BigBuf memory
 -      BigBuf_free();
        // allocate the DMA buffer, used to stream samples from the FPGA
        uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
        uint8_t *data = dmaBuf;
                                        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);
                        }
        
        Dbprintf("maxDataLen=%x, Uart.state=%x, Uart.len=%x", maxDataLen, Uart.state, Uart.len);
        LEDsoff();
- }
+ }
diff --combined armsrc/lfops.c
index 5b0b4904e33ad5e01ed72ca3d353b187d28adb18,c3fa8a0e630f2f743aaedd247b2d711c89610385..b9890cebba15610b931e6691d90277a80334214d
@@@ -379,7 -379,7 +379,7 @@@ void WriteTItag(uint32_t idhi, uint32_
        AcquireTiType();
  
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
 -      DbpString("Now use tiread to check");
 +      DbpString("Now use 'lf ti read' to check");
  }
  
  void SimulateTagLowFrequency(int period, int gap, int ledcontrol)
@@@ -651,7 -651,7 +651,7 @@@ void CmdASKsimTag(uint16_t arg1, uint16
        int ledcontrol = 1;
        int n=0, i=0;
        uint8_t clk = (arg1 >> 8) & 0xFF;
-       uint8_t encoding = arg1 & 1;
+       uint8_t encoding = arg1 & 0xFF;
        uint8_t separator = arg2 & 1;
        uint8_t invert = (arg2 >> 8) & 1;
  
@@@ -756,7 -756,7 +756,7 @@@ void CmdHIDdemodFSK(int findone, int *h
  {
        uint8_t *dest = BigBuf_get_addr();
        //const size_t sizeOfBigBuff = BigBuf_max_traceLen();
 -      size_t size; 
 +      size_t size = 0
        uint32_t hi2=0, hi=0, lo=0;
        int idx=0;
        // Configure to go in 125Khz listen mode
@@@ -866,24 -866,24 +866,24 @@@ void CmdEM410xdemod(int findone, int *h
  
                if (errCnt<0) continue;
        
 -              errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
 -              if (errCnt){
 -                      if (size>64){
 -                              Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)",
 -                                hi,
 -                                (uint32_t)(lo>>32),
 -                                (uint32_t)lo,
 -                                (uint32_t)(lo&0xFFFF),
 -                                (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));
 -                      }
 +                      errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo);
 +                      if (errCnt){
 +                              if (size>64){
 +                                      Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)",
 +                                        hi,
 +                                        (uint32_t)(lo>>32),
 +                                        (uint32_t)lo,
 +                                        (uint32_t)(lo&0xFFFF),
 +                                        (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));
 +                              }
  
                        if (findone){
                                if (ledcontrol) LED_A_OFF();
@@@ -908,8 -908,6 +908,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();
                idx = IOdemodFSK(dest, BigBuf_max_traceLen());
                if (idx<0) continue;
 -              //valid tag found
 -
 -              //Index map
 -              //0           10          20          30          40          50          60
 -              //|           |           |           |           |           |           |
 -              //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
 -              //
 -              //XSF(version)facility:codeone+codetwo
 -              //Handle the data
 -              if(findone){ //only print binary if we are doing one
 -                      Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx],   dest[idx+1],   dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]);
 -                      Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]);
 -                      Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]);
 -                      Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]);
 -                      Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]);
 -                      Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]);
 -                      Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
 -              }
 -              code = bytebits_to_byte(dest+idx,32);
 -              code2 = bytebits_to_byte(dest+idx+32,32);
 -              version = bytebits_to_byte(dest+idx+27,8); //14,4
 +                      //valid tag found
 +
 +                      //Index map
 +                      //0           10          20          30          40          50          60
 +                      //|           |           |           |           |           |           |
 +                      //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 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
 +                              Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx],   dest[idx+1],   dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]);
 +                              Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]);
 +                              Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]);
 +                              Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]);
 +                              Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]);
 +                              Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]);
 +                              Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]);
 +                      }
 +                      code = bytebits_to_byte(dest+idx,32);
 +                      code2 = bytebits_to_byte(dest+idx+32,32);
 +                      version = bytebits_to_byte(dest+idx+27,8); //14,4
                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);
 -              // if we're only looking for one tag
 -              if (findone){
 -                      if (ledcontrol) LED_A_OFF();
 -                      //LED_A_OFF();
 -                      *high=code;
 -                      *low=code2;
 -                      return;
 -              }
 -              code=code2=0;
 -              version=facilitycode=0;
 -              number=0;
 -              idx=0;
 +                      number = (bytebits_to_byte(dest+idx+36,8)<<8)|(bytebits_to_byte(dest+idx+45,8)); //36,9
 +
 +                      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();
 +                              //LED_A_OFF();
 +                              *high=code;
 +                              *low=code2;
 +                              return;
 +                      }
 +                      code=code2=0;
 +                      version=facilitycode=0;
 +                      number=0;
 +                      idx=0;
  
                WDT_HIT();
        }
   * 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) 
 +
 +//  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..)
  
@@@ -1070,7 -1037,7 +1070,7 @@@ 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);
@@@ -1524,16 -1491,10 +1524,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();
 +
 +    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;
  }
  
@@@ -1948,14 -1912,9 +1948,14 @@@ void EM4xLogin(uint32_t Password) 
  
  void EM4xReadWord(uint8_t Address, uint32_t Pwd, uint8_t PwdMode) {
  
 -      uint8_t fwd_bit_count;
        uint8_t *dest = BigBuf_get_addr();
 -      int m=0, i=0;
 +      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;
  
        //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 03e15b3b52e9ce8d29bd38bb33c87ad598b9d011,0586a25db1b8882678ca3bd3080bcb37437d9293..c56f2337e68b0cdb8c12c2543b4e1c4a8c52f4ce
  \r
  #include "crc.h"\r
  \r
+ // the block number for the ISO14443-4 PCB\r
+ uint8_t pcb_blocknum = 0;\r
+ // Deselect card by sending a s-block. the crc is precalced for speed\r
+ static  uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4};\r
\r
\r
  //-----------------------------------------------------------------------------\r
  // Select, Authenticate, Read a MIFARE tag. \r
  // read block\r
@@@ -86,7 -92,6 +92,6 @@@ void MifareReadBlock(uint8_t arg0, uint
        LEDsoff();\r
  }\r
  \r
\r
  void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){\r
  \r
        bool turnOffField = (arg0 == 1);\r
                OnError(1);\r
                return;\r
        }\r
-     \r
\r
        if (turnOffField) {\r
                FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
                LEDsoff();\r
+       }\r
+       cmd_send(CMD_ACK,1,0,0,0,0);\r
 +      }       \r
 +      cmd_send(CMD_ACK,1,0,0,0,0);\r
  }\r
  \r
  // Arg0 = BlockNo,\r
  // Arg1 = UsePwd bool\r
- // datain = PWD bytes,  \r
+ // datain = PWD bytes,\r
  void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
  {\r
        uint8_t blockNo = arg0;\r
        bool useKey = (arg1 == 1); //UL_C\r
        bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
  \r
-       LEDsoff();      \r
-       LED_A_ON();    \r
+       LEDsoff();\r
+       LED_A_ON();\r
        clear_trace();\r
        iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
-     \r
\r
        int len = iso14443a_select_card(NULL, NULL, NULL);\r
        if(!len) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len);\r
                OnError(1);\r
                return;\r
        }\r
-        \r
\r
        // UL-C authentication\r
        if ( useKey ) {\r
-               uint8_t key[16] = {0x00};       \r
+               uint8_t key[16] = {0x00};\r
                memcpy(key, datain, sizeof(key) );\r
  \r
                if ( !mifare_ultra_auth(key) ) {\r
                        OnError(1);\r
-                       return;                 \r
+                       return;\r
                }\r
        }\r
-       \r
\r
        // UL-EV1 / NTAG authentication\r
-       if (usePwd) { \r
+       if ( usePwd ) {\r
                uint8_t pwd[4] = {0x00};\r
                memcpy(pwd, datain, 4);\r
                uint8_t pack[4] = {0,0,0,0};\r
                if (!mifare_ul_ev1_auth(pwd, pack)) {\r
                        OnError(1);\r
-                       return;                 \r
+                       return;\r
                }\r
-       }\r
-               \r
+       }       \r
\r
        if( mifare_ultra_readblock(blockNo, dataout) ) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error");\r
                OnError(2);\r
                return;\r
        }\r
-         \r
\r
        if( mifare_ultra_halt() ) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
                OnError(3);\r
                return;\r
        }\r
-               \r
\r
 -      cmd_send(CMD_ACK,1,0,0,dataout,16);\r
 +    cmd_send(CMD_ACK,1,0,0,dataout,16);\r
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
        LEDsoff();\r
  }\r
@@@ -210,7 -215,7 +217,7 @@@ void MifareReadSector(uint8_t arg0, uin
                isOK = 0;\r
                if (MF_DBGLEVEL >= 1)   Dbprintf("Can't select card");\r
        }\r
 -\r
 +      \r
        \r
        if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) {\r
                isOK = 0;\r
        LEDsoff();\r
  }\r
  \r
 +// arg0 = blockNo (start)\r
 +// arg1 = Pages (number of blocks)\r
 +// arg2 = useKey\r
 +// datain = KEY bytes\r
  void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain)\r
  {\r
        // free eventually allocated BigBuf memory\r
        }\r
  \r
        LEDsoff();\r
-       LED_A_ON(); \r
+       LED_A_ON();\r
        iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
  \r
        int len = iso14443a_select_card(NULL, NULL, NULL);\r
                OnError(1);\r
                return;\r
        }\r
\r
+       // UL-C authentication\r
+       if ( useKey ) {\r
+               uint8_t key[16] = {0x00};\r
+               memcpy(key, datain, sizeof(key) );\r
\r
+               if ( !mifare_ultra_auth(key) ) {\r
+                       OnError(1);\r
+                       return;\r
+               }\r
+       }\r
\r
+       // UL-EV1 / NTAG authentication\r
+       if (usePwd) {\r
+               uint8_t pwd[4] = {0x00};\r
+               memcpy(pwd, datain, sizeof(pwd));\r
+               uint8_t pack[4] = {0,0,0,0};\r
\r
+               if (!mifare_ul_ev1_auth(pwd, pack)){\r
+                       OnError(1);\r
+                       return;                 \r
+               }\r
+       }\r
\r
+       for (int i = 0; i < blocks; i++){\r
+               if ((i*4) + 4 > CARD_MEMORY_SIZE) {\r
+                       Dbprintf("Data exceeds buffer!!");\r
+                       break;\r
+               }\r
        \r
 -              len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);\r
 +       // UL-C authentication\r
 +      if ( useKey ) {\r
 +              uint8_t key[16] = {0x00};       \r
 +              memcpy(key, datain, sizeof(key) );\r
 +\r
 +              if ( !mifare_ultra_auth(key) ) {\r
 +                      OnError(1);\r
 +                      return;                 \r
 +              }\r
 +      }\r
 +\r
 +      // UL-EV1 / NTAG authentication\r
 +      if (usePwd) { \r
 +              uint8_t pwd[4] = {0x00};\r
 +              memcpy(pwd, datain, sizeof(pwd));\r
 +              uint8_t pack[4] = {0,0,0,0};\r
  \r
 +              if (!mifare_ul_ev1_auth(pwd, pack)){\r
 +                      OnError(1);\r
 +                      return;                 \r
 +              }\r
 +      }\r
 +      \r
 +      for (int i = 0; i < blocks; i++){\r
 +              if ((i*4) + 4 > CARD_MEMORY_SIZE) {\r
 +                      Dbprintf("Data exceeds buffer!!");\r
 +                      break;\r
 +              }\r
 +      \r
 +              len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i);\r
 +              \r
                if (len) {\r
                        if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i);\r
                        // if no blocks read - error out\r
                        if (i==0){\r
-                       OnError(2);\r
+                               OnError(2);\r
 -                              return;\r
 +                      return;\r
                        } else {\r
                                //stop at last successful read block and return what we got\r
                                break;\r
                        countblocks++;\r
                }\r
        }\r
-               \r
\r
        len = mifare_ultra_halt();\r
        if (len) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error");\r
                OnError(3);\r
                return;\r
        }\r
-       \r
\r
        if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks);\r
  \r
        countblocks *= 4;\r
@@@ -413,15 -414,15 +449,15 @@@ void MifareWriteBlock(uint8_t arg0, uin
  \r
  void MifareUWriteBlock(uint8_t arg0, uint8_t *datain)\r
  {\r
-     uint8_t blockNo = arg0;\r
+       uint8_t blockNo = arg0;\r
        byte_t blockdata[16] = {0x00};\r
  \r
-     memcpy(blockdata, datain, 16);\r
-         \r
+       memcpy(blockdata, datain, 16);\r
\r
        uint8_t uid[10] = {0x00};\r
  \r
        LED_A_ON(); LED_B_OFF(); LED_C_OFF();\r
-               \r
\r
        clear_trace();\r
        iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
  \r
                OnError(0);\r
                return;\r
        };\r
-               \r
\r
        if (MF_DBGLEVEL >= 2)   DbpString("WRITE BLOCK FINISHED");\r
  \r
        cmd_send(CMD_ACK,1,0,0,0,0);\r
        LEDsoff();\r
  }\r
  \r
 -void MifareUWriteBlock_Special(uint8_t arg0, uint8_t *datain)\r
 +// Arg0   : Block to write to.\r
 +// Arg1   : 0 = use no authentication.\r
 +//          1 = use 0x1A authentication.\r
 +//          2 = use 0x1B authentication.\r
 +// datain : 4 first bytes is data to be written.\r
 +//        : 4/16 next bytes is authentication key.\r
 +void MifareUWriteBlock_Special(uint8_t arg0, uint8_t arg1, uint8_t *datain)\r
  {\r
        uint8_t blockNo = arg0;\r
 +      bool useKey = (arg1 == 1); //UL_C\r
 +      bool usePwd = (arg1 == 2); //UL_EV1/NTAG\r
        byte_t blockdata[4] = {0x00};\r
-       \r
-       memcpy(blockdata, datain, 4);\r
\r
+       memcpy(blockdata, datain,4);\r
        \r
        LEDsoff();\r
        LED_A_ON();\r
                return;\r
        };\r
  \r
 +      // UL-C authentication\r
 +      if ( useKey ) {\r
 +              uint8_t key[16] = {0x00};       \r
 +              memcpy(key, datain+4, sizeof(key) );\r
 +\r
 +              if ( !mifare_ultra_auth(key) ) {\r
 +                      OnError(1);\r
 +                      return;                 \r
 +              }\r
 +      }\r
 +      \r
 +      // UL-EV1 / NTAG authentication\r
 +      if (usePwd) { \r
 +              uint8_t pwd[4] = {0x00};\r
 +              memcpy(pwd, datain+4, 4);\r
 +              uint8_t pack[4] = {0,0,0,0};\r
 +              if (!mifare_ul_ev1_auth(pwd, pack)) {\r
 +                      OnError(1);\r
 +                      return;                 \r
 +              }\r
 +      }\r
 +      \r
        if(mifare_ultra_special_writeblock(blockNo, blockdata)) {\r
                if (MF_DBGLEVEL >= 1) Dbprintf("Write block error");\r
                OnError(0);\r
@@@ -1034,12 -1005,12 +1070,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
@@@ -1218,74 -1189,7 +1254,74 @@@ void MifareCIdent()
        cmd_send(CMD_ACK,isOK,0,0,0,0);\r
  }\r
  \r
 -                      //\r
 +void MifareCollectNonces(uint32_t arg0, uint32_t arg1){\r
 +\r
 +      BigBuf_free();\r
 +\r
 +      uint32_t iterations = arg0;\r
 +      uint8_t uid[10] = {0x00};\r
 +\r
 +      uint8_t *response = BigBuf_malloc(MAX_MIFARE_FRAME_SIZE);\r
 +      uint8_t *responsePar = BigBuf_malloc(MAX_MIFARE_PARITY_SIZE);\r
 +\r
 +      uint8_t mf_auth[] = { 0x60,0x00,0xf5,0x7b };\r
 +      \r
 +      // get memory from BigBuf.\r
 +      uint8_t *nonces = BigBuf_malloc(iterations * 4);\r
 +\r
 +      LED_A_ON();\r
 +      LED_B_OFF();\r
 +      LED_C_OFF();\r
 +\r
 +      clear_trace();\r
 +      set_tracing(TRUE);\r
 +      iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
 +      \r
 +      for (int i = 0; i < iterations; i++) {\r
 +                                              \r
 +              WDT_HIT();\r
 +\r
 +              // Test if the action was cancelled\r
 +              if(BUTTON_PRESS()) break;\r
 +              \r
 +              //              if(mifare_classic_halt(pcs, cuid)) {\r
 +              //                      if (MF_DBGLEVEL >= 1) Dbprintf("Halt error");\r
 +              //}\r
 +\r
 +              if(!iso14443a_select_card(uid, NULL, NULL)) {\r
 +                      if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card");\r
 +                      continue;\r
 +              };\r
 +\r
 +              // Transmit MIFARE_CLASSIC_AUTH.\r
 +              ReaderTransmit(mf_auth, sizeof(mf_auth), NULL);\r
 +\r
 +              // Receive the (4 Byte) "random" nonce\r
 +              if (!ReaderReceive(response, responsePar)) {\r
 +                      if (MF_DBGLEVEL >= 1)   Dbprintf("Couldn't receive tag nonce");\r
 +                      continue;\r
 +              }       \r
 +              \r
 +              nonces[i*4] = bytes_to_num(response, 4);\r
 +      }\r
 +              \r
 +      int packLen =  iterations * 4;\r
 +      int packSize = 0;\r
 +      int packNum = 0;\r
 +      while (packLen > 0) {\r
 +              packSize = MIN(USB_CMD_DATA_SIZE, packLen);\r
 +              LED_B_ON();\r
 +              cmd_send(CMD_ACK, 77, 0, packSize, nonces - packLen, packSize);\r
 +              LED_B_OFF();\r
 +\r
 +              packLen -= packSize;\r
 +              packNum++;\r
 +      }\r
 +      FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
 +      LEDsoff();\r
 +}\r
 +\r
 +//\r
  // DESFIRE\r
  //\r
  \r
@@@ -1293,7 -1197,7 +1329,7 @@@ void Mifare_DES_Auth1(uint8_t arg0, uin
  \r
        byte_t dataout[11] = {0x00};\r
        uint8_t uid[10] = {0x00};\r
 -      uint32_t cuid;\r
 +      uint32_t cuid = 0x00;\r
      \r
        clear_trace();\r
        iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);\r
@@@ -1319,22 -1223,39 +1355,37 @@@ void Mifare_DES_Auth2(uint32_t arg0, ui
  \r
        uint32_t cuid = arg0;\r
        uint8_t key[16] = {0x00};\r
 -      byte_t isOK = 0;\r
        byte_t dataout[12] = {0x00};\r
 +      byte_t isOK = 0;\r
      \r
        memcpy(key, datain, 16);\r
        \r
        isOK = mifare_desfire_des_auth2(cuid, key, dataout);\r
        \r
        if( isOK) {\r
 -          if (MF_DBGLEVEL >= MF_DBG_EXTENDED) \r
 -                      Dbprintf("Authentication part2: Failed");  \r
 -              //OnError(4);\r
 +          if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed");  \r
 +              OnError(4);\r
                return;\r
        }\r
  \r
 -      if (MF_DBGLEVEL >= MF_DBG_EXTENDED) \r
 -              DbpString("AUTH 2 FINISHED");\r
 +      if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED");\r
  \r
        cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));\r
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
        LEDsoff();\r
  }\r
\r
+ void OnSuccess(){\r
+       pcb_blocknum = 0;\r
+       ReaderTransmit(deselect_cmd, 3 , NULL);\r
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+       LEDsoff();\r
+ }\r
\r
+ void OnError(uint8_t reason){\r
+       pcb_blocknum = 0;\r
+       ReaderTransmit(deselect_cmd, 3 , NULL);\r
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
+       cmd_send(CMD_ACK,0,reason,0,0,0);\r
+       LEDsoff();\r
+ }\r
diff --combined armsrc/mifareutil.c
index 8c44445f5c01a614cc41a0b88de01617c03d0123,2f84797b92e015384d8b2755410bd4c553431efd..109b91b0efb1bdc961b5693af83ffcbc5f05015d
@@@ -315,34 -315,35 +315,35 @@@ int mifare_ul_ev1_auth(uint8_t *keybyte
        uint16_t len;\r
        uint8_t resp[4];\r
        uint8_t respPar[1];\r
-       uint8_t key[4] = {0x00};        \r
+       uint8_t key[4] = {0x00};\r
        memcpy(key, keybytes, 4);\r
-       \r
\r
        Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);\r
        len = mifare_sendcmd_short_mfuev1auth(NULL, 0, 0x1B, key, resp, respPar, NULL);\r
        if (len != 4) {\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);\r
                return 0;\r
        }\r
-       \r
\r
        if (MF_DBGLEVEL >= MF_DBG_EXTENDED)\r
-               Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]);\r
-       \r
+               Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]);\r
\r
        memcpy(pack, resp, 4);\r
        return 1;\r
  }\r
  \r
  int mifare_ultra_auth(uint8_t *keybytes){\r
  \r
-       // 3des2k\r
+       /// 3des2k\r
\r
        uint8_t random_a[8] = {1,1,1,1,1,1,1,1};\r
        uint8_t random_b[8] = {0x00};\r
        uint8_t enc_random_b[8] = {0x00};\r
        uint8_t rnd_ab[16] = {0x00};\r
        uint8_t IV[8] = {0x00};\r
-       uint8_t key[16] = {0x00};       \r
+       uint8_t key[16] = {0x00};\r
        memcpy(key, keybytes, 16);\r
-       \r
\r
        uint16_t len;\r
        uint8_t resp[19] = {0x00};\r
        uint8_t respPar[3] = {0,0,0};\r
        rol(random_b,8);\r
        memcpy(rnd_ab  ,random_a,8);\r
        memcpy(rnd_ab+8,random_b,8);\r
-       \r
\r
        if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {\r
                Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x",\r
                        enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3],enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]);\r
-                       \r
\r
                Dbprintf("    B: %02x %02x %02x %02x %02x %02x %02x %02x",\r
                        random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]);\r
  \r
                Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",\r
                                rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]);\r
-                               \r
\r
                Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",\r
                                rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] );\r
        }\r
-       \r
\r
+       // encrypt    out, in, length, key, iv\r
+       tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b);\r
\r
+       len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);\r
+       if (len != 11) {\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);\r
+               return 0;\r
+       }\r
\r
+       uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 };\r
+       uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 };\r
+       memcpy(enc_resp, resp+1, 8);\r
\r
+       // decrypt    out, in, length, key, iv \r
+       tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b);\r
+       if ( memcmp(resp_random_a, random_a, 8) != 0 ) {\r
+               if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication");\r
+               return 0;\r
+       }\r
\r
 +      // encrypt    out, in, length, key, iv\r
 +      tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b);\r
 +\r
 +      len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, rnd_ab, resp, respPar, NULL);\r
 +      if (len != 11) {\r
 +              if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);\r
 +              return 0;\r
 +      }\r
 +\r
 +      uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 };\r
 +      uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 };\r
 +      memcpy(enc_resp, resp+1, 8);\r
 +      \r
 +      // decrypt    out, in, length, key, iv \r
 +      tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b);\r
 +      if ( memcmp(resp_random_a, random_a, 8) != 0 ) {\r
 +              if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication");\r
 +              return 0;\r
 +      }       \r
 +\r
        if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {\r
                Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", \r
                                rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],\r
                Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x",\r
                                random_a[0],random_a[1],random_a[2],random_a[3],\r
                                random_a[4],random_a[5],random_a[6],random_a[7]);\r
-                               \r
\r
                Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x",\r
                                resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3],\r
                                resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]);\r
@@@ -449,9 -450,9 +470,9 @@@ int mifare_classic_writeblock(struct Cr
  {\r
        // variables\r
        uint16_t len, i;        \r
 -      uint32_t pos;\r
 -      uint8_t par[3] = {0};           // enough for 18 Bytes to send\r
 -      byte_t res;\r
 +      uint32_t pos = 0;\r
 +      uint8_t par[3] = {0x00};                // enough for 18 Bytes to send\r
 +      byte_t res = 0;\r
        \r
        uint8_t d_block[18], d_block_enc[18];\r
        uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
  \r
  int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) \r
  {\r
-     uint16_t len;     \r
+       uint16_t len;\r
 -      uint8_t par[3] = {0};  // enough for 18 parity bits\r
 +    uint8_t par[3] = {0};  // enough for 18 parity bits\r
        uint8_t d_block[18] = {0x00};\r
        uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
        uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
-         \r
\r
 -      // command MIFARE_CLASSIC_WRITEBLOCK\r
 -      len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
 +    // command MIFARE_CLASSIC_WRITEBLOCK\r
 +    len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
  \r
 -      if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK\r
 +    if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
-                       Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);  \r
+                       Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);\r
 -              return 1;\r
 -      }\r
 +        return 1;\r
 +    }\r
  \r
        memcpy(d_block, blockData, 16);\r
 -      AppendCrc14443a(d_block, 16);\r
 +    AppendCrc14443a(d_block, 16);\r
  \r
        ReaderTransmitPar(d_block, sizeof(d_block), par, NULL);\r
  \r
-     len = ReaderReceive(receivedAnswer, receivedAnswerPar);    \r
+       len = ReaderReceive(receivedAnswer, receivedAnswerPar);\r
  \r
        if ((len != 1) || (receivedAnswer[0] != 0x0A)) {   //  0x0a - ACK\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
                        Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);\r
 -              return 2;\r
 +        return 2;\r
-     }        \r
+       }\r
 -      return 0;\r
 +    return 0;\r
- } \r
+ }\r
  \r
  int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData)\r
  {\r
 -      uint16_t len;\r
 +    uint16_t len;\r
        uint8_t d_block[8] = {0x00};\r
        uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
        uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
  \r
 -      // command MIFARE_CLASSIC_WRITEBLOCK\r
 +    // command MIFARE_CLASSIC_WRITEBLOCK\r
        d_block[0]= blockNo;\r
        memcpy(d_block+1,blockData,4);\r
        AppendCrc14443a(d_block, 6);\r
  \r
 -      len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);\r
 +    len = mifare_sendcmd_short_special(NULL, 1, 0xA2, d_block, receivedAnswer, receivedAnswerPar, NULL);\r
  \r
 -      if (receivedAnswer[0] != 0x0A) {   //  0x0a - ACK\r
 +    if (receivedAnswer[0] != 0x0A) {   //  0x0a - ACK\r
                if (MF_DBGLEVEL >= MF_DBG_ERROR)\r
                        Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len);\r
 -              return 1;\r
 -      }\r
 -      return 0;\r
 +        return 1;\r
 +    }\r
 +    return 0;\r
  }\r
  \r
  int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) \r
@@@ -757,8 -758,8 +778,8 @@@ int mifare_desfire_des_auth2(uint32_t u
        data[0] = 0xAF;\r
        memcpy(data+1,key,16);\r
        \r
 -      uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
 -      uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
 +      uint8_t receivedAnswer[MAX_FRAME_SIZE];\r
 +      uint8_t receivedAnswerPar[MAX_PARITY_SIZE];\r
        \r
        len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL);\r
        \r
diff --combined armsrc/mifareutil.h
index f73814be51458bdafaeadc83a7b9a06c44b5524d,d4fcd818932e4cf66299edd53044e00f9432fb2f..9575b9fc6bac103ba62da142698f173943cf32d0
@@@ -52,34 -52,34 +52,34 @@@ extern int MF_DBGLEVEL
  \r
  #define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();\r
  \r
 -//functions\r
 -int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
 -int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
 +//functions
 +int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
 +int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
  \r
  int mifare_sendcmd_short_mfucauth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);\r
  int mifare_sendcmd_short_mfuev1auth(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);\r
 -int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
 -\r
 +int mifare_sendcmd_shortex(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
 +
  int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);\r
 -int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);\r
 +int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing);
- int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); 
+ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);\r
  int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack);\r
  int mifare_ultra_auth(uint8_t *key);\r
- int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
+ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);\r
 -int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);\r
 -int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);\r
 -int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData);\r
 -int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); \r
 -int mifare_ultra_halt();\r
 +int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
 +int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
 +int mifare_ultra_special_writeblock(uint8_t blockNo, uint8_t *blockData);
 +int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); 
 +int mifare_ultra_halt();
  \r
  // desfire\r
  int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);\r
  int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing);\r
  int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData);\r
  int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);\r
 -\r
 -// crypto functions\r
 -void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);\r
 +
 +// crypto functions
 +void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len);
  void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);\r
  uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);\r
  \r
@@@ -94,7 -94,7 +94,7 @@@ void emlGetMem(uint8_t *data, int block
  void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount);\r
  uint64_t emlGetKey(int sectorNum, int keyType);\r
  int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);\r
 -int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);\r
 -int emlCheckValBl(int blockNum);\r
 -\r
 -#endif\r
 +int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);
 +int emlCheckValBl(int blockNum);
 +
 +#endif
diff --combined client/cmdhf.c
index 1a0886769ae3517c4c89cae3860e7f9669ad6b6b,16f7bb0f39f661c180723bd0c52bd1306407f8bd..614dcdc4460e98bf7ed5b90de015970cfe6c10ea
@@@ -23,8 -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);
@@@ -36,6 -34,7 +36,6 @@@ int CmdHFTune(const char *Cmd
    return 0;
  }
  
 -
  void annotateIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize)
  {
        switch(cmd[0])
        case MIFARE_MAGICWUPC1:                 snprintf(exp,size,"MAGIC WUPC1"); break;
        case MIFARE_MAGICWUPC2:                 snprintf(exp,size,"MAGIC WUPC2"); break;
        case MIFARE_MAGICWIPEC:                 snprintf(exp,size,"MAGIC WIPEC"); break;
 -      case MIFARE_ULC_AUTH_1:         snprintf(exp,size,"AUTH "); break;
 -      case MIFARE_ULC_AUTH_2:         snprintf(exp,size,"AUTH_ANSW"); break;
 -      case MIFARE_ULEV1_AUTH:
 +      case MIFARE_ULC_AUTH_1 :                snprintf(exp,size,"AUTH "); break;
 +      case MIFARE_ULC_AUTH_2 :                snprintf(exp,size,"AUTH_ANSW"); break;
 +      case MIFARE_ULEV1_AUTH :        
                if ( cmdsize == 7 )
                        snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] );
                else
                        snprintf(exp,size,"PWD-AUTH");
                break;
 -      case MIFARE_ULEV1_FASTREAD:{
 +
 +      case MIFARE_ULEV1_FASTREAD : {
                if ( cmdsize >=3 && cmd[2] <= 0xE6)
                        snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); 
                else
                        snprintf(exp,size,"?");
                break;
        }
 -      case MIFARE_ULC_WRITE:{
 +      case MIFARE_ULC_WRITE : {
                if ( cmd[1] < 0x21 )
                        snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); 
                else
                        snprintf(exp,size,"?");
                break;
        }
 -      case MIFARE_ULEV1_READ_CNT:{
 +      case MIFARE_ULEV1_READ_CNT :{
                if ( cmd[1] < 5 )
                        snprintf(exp,size,"READ CNT(%d)",cmd[1]);
                else
                        snprintf(exp,size,"?");
                break;
        }
 -      case MIFARE_ULEV1_INCR_CNT:{
 +      case MIFARE_ULEV1_INCR_CNT : {
                if ( cmd[1] < 5 )
                        snprintf(exp,size,"INCR(%d)",cmd[1]);
                else
                        snprintf(exp,size,"?");
                break;
        }
 -      case MIFARE_ULEV1_READSIG             snprintf(exp,size,"READ_SIG"); break;
 -      case MIFARE_ULEV1_CHECKTEAR   snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break;
 -      case MIFARE_ULEV1_VCSL:         snprintf(exp,size,"VCSL"); break;
 +      case MIFARE_ULEV1_READSIG :             snprintf(exp,size,"READ_SIG"); break;
 +      case MIFARE_ULEV1_CHECKTEAR :   snprintf(exp,size,"CHK_TEARING(%d)",cmd[1]); break;
 +      case MIFARE_ULEV1_VCSL :                snprintf(exp,size,"VCSL"); break;
        default:                                                snprintf(exp,size,"?"); break;
        }
        return;
@@@ -189,26 -187,6 +189,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)
@@@ -240,34 -218,7 +240,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
@@@ -350,66 -301,11 +350,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)
 -              {
 -                      crcStatus = iclass_CRC_check(isResponse, frame, data_len);
 -
 -              }else if (protocol == ISO_14443B)
 -              {
 -                      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;
 -                              }
 -                      }
 +              switch (protocol) {
 +                      case ICLASS:
 +                              crcStatus = iclass_CRC_check(isResponse, frame, data_len);
 +                              break;
 +                      case ISO_14443B:
 +                      case TOPAZ:
 +                              crcStatus = iso14443B_CRC_check(isResponse, frame, data_len);
 +                              break;
 +                      case ISO_14443A:
 +                              crcStatus = iso14443A_CRC_check(isResponse, frame, data_len);
 +                              break;
 +                      default: 
 +                              break;
                }
        }
        //0 CRC-command, CRC not ok
        //2 Not crc-command
  
        //--- Draw the data column
 -      //char line[16][110];
        char line[16][110];
  
        for (int j = 0; j < data_len && j/16 < 16; j++) {
                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)
 -      {//CRC-command
 -              char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4)-1;
 -              (*pos1) = '[';
 -              char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4)-2;
 -              (*pos2) = ']';
        }
 -      if(data_len == 0)
 -      {
 -              if(data_len == 0){
 -                      sprintf(line[0],"<empty trace - possible error>");
 +
 +      if (markCRCBytes) {
 +              //CRC-command
 +              if(crcStatus == 0 || crcStatus == 1) {
 +                      char *pos1 = line[(data_len-2)/16]+(((data_len-2) % 16) * 4);
 +                      (*pos1) = '[';
 +                      char *pos2 = line[(data_len)/16]+(((data_len) % 16) * 4);
 +                      sprintf(pos2, "%c", ']');
                }
        }
 -      //--- Draw the CRC column
  
 +      if(data_len == 0){
 +              sprintf(line[0],"<empty trace - possible error>");
 +      }
 +      //--- Draw the CRC column
        char *crc = (crcStatus == 0 ? "!crc" : (crcStatus == 1 ? " ok " : "    "));
  
        EndOfTransmissionTimestamp = timestamp + duration;
  
        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"),
                                (j == num_lines-1) ? crc : "    ",
                                (j == num_lines-1) ? explanation : "");
                } else {
 -                      PrintAndLog("           |           |     | %-64s| %s| %s",
 +                      PrintAndLog("            |            |     |%-64s | %s| %s",
                                line[j],
 -                              (j == num_lines-1)?crc:"    ",
 +                              (j == num_lines-1) ? crc : "    ",
                                (j == num_lines-1) ? explanation : "");
                }
        }
  
 -      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",
 +                      PrintAndLog(" %10d | %10d | %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;
        PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
        PrintAndLog("iClass    - Timings are not as accurate");
        PrintAndLog("");
 -      PrintAndLog("     Start |       End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |");
 -      PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
 +    PrintAndLog("      Start |        End | Src | Data (! denotes parity error)                                   | CRC | Annotation         |");
 +      PrintAndLog("------------|------------|-----|-----------------------------------------------------------------|-----|--------------------|");
  
        while(tracepos < traceLen)
        {
 -              tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
 +              tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles, markCRCBytes);
        }
  
        free(trace);
@@@ -677,7 -571,7 +677,7 @@@ int CmdHFSearch(const char *Cmd)
  
        //14b has issues currently...
        //ans = CmdHF14BRead(Cmd);
-       //if (ans > 0) return ans;      
+       //if (ans > 0) return ans;
  
        return 0;
  }
@@@ -691,12 -585,10 +691,12 @@@ static command_t CommandTable[] 
    {"epa",         CmdHFEPA,         1, "{ German Identification Card... }"},
    {"legic",       CmdHFLegic,       0, "{ LEGIC RFIDs... }"},
    {"iclass",      CmdHFiClass,      1, "{ ICLASS RFIDs... }"},
 -  {"mf",          CmdHFMF,          1, "{ MIFARE RFIDs... }"},
 +  {"mf",                      CmdHFMF,                1, "{ MIFARE RFIDs... }"},
-   {"mfu",                     CmdHFMFUltra,   1, "{ MIFARE Ultralight RFIDs... }"},
+   {"mfu",         CmdHFMFUltra,     1, "{ MIFARE Ultralight RFIDs... }"},
 -  {"tune",        CmdHFTune,        0, "Continuously measure HF antenna tuning"},
 +  {"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"},
+   {"list",        CmdHFList,        1, "List protocol data in trace buffer"},
    {"search",      CmdHFSearch,      1, "Search for known HF tags [preliminary]"},
        {NULL, NULL, 0, NULL}
  };
diff --combined client/cmdhficlass.c
index d6c791656806f2540797b0facc30478bc658738d,824aaa3674cc1bd5cf84d38174968d0e3fbd468e..e8ba68f18467c2c221bd40cb24a63fc9b57a1a8c
@@@ -174,12 -174,12 +174,12 @@@ int HFiClassReader(const char *Cmd, boo
        SendCommand(&c);
        UsbCommand resp;
        while(!ukbhit()){
-               if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
+               if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
 -                      uint8_t readStatus = resp.arg[0] & 0xff;
 +                      uint8_t readStatus    = resp.arg[0] & 0xff;
-                       uint8_t * data  = resp.d.asBytes;
+                       uint8_t *data = resp.d.asBytes;
  
                        if (verbose)
 -                              PrintAndLog("Readstatus:%02x", readStatus);
 +                      PrintAndLog("Readstatus:%02x", readStatus);
                        if( readStatus == 0){
                                //Aborted
                                if (verbose) PrintAndLog("Quitting...");
diff --combined client/cmdhfmf.c
index 1b815326e13e26f611a169a059702193455f9b83,aa3b66dc64b960f2bf855b62257f904b26196a4e..676a8884c863f30ffbcae7d1a63adead2d1036f8
@@@ -781,8 -781,8 +781,8 @@@ int CmdHF14AMfChk(const char *Cmd
                PrintAndLog("Usage:  hf mf chk <block number>|<*card memory> <key type (A/B/?)> [t|d] [<key (12 hex symbols)>] [<dic (*.dic)>]");\r
                PrintAndLog("          * - all sectors");\r
                PrintAndLog("card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, <other> - 1K");\r
 -              PrintAndLog("d - write keys to binary file\n");\r
 -              PrintAndLog("t - write keys to emulator memory");\r
 +              PrintAndLog("d - write keys to binary file");\r
 +              PrintAndLog("t - write keys to emulator memory\n");\r
                PrintAndLog("      sample: hf mf chk 0 A 1234567890ab keys.dic");\r
                PrintAndLog("              hf mf chk *1 ? t");\r
                PrintAndLog("              hf mf chk *1 ? d");\r
@@@ -1592,8 -1592,8 +1592,9 @@@ int CmdHF14AMfCLoad(const char *Cmd
                        memset(buf, 0, sizeof(buf));\r
                        \r
                        if (fgets(buf, sizeof(buf), f) == NULL) {\r
+                               fclose(f);\r
                                PrintAndLog("File reading error.");\r
 +                              fclose(f);\r
                                return 2;\r
                        }\r
  \r
diff --combined client/cmdhfmfu.c
index ea381736d249c65ea76698d34afe431eebf5f0fd,07c379bc0d63c5ffc77540384ea4246199b231a3..6ab24a43edeac6f61a05d4387664fd48aa7b4529
  #include "cmdhf14a.h"
  #include "mifare.h"
  #include "util.h"
 -#include "protocols.h"
 +#include "../common/protocols.h"
  #include "data.h"
  
- #define MAX_UL_BLOCKS         0x0f
- #define MAX_ULC_BLOCKS                0x2b
- #define MAX_ULEV1a_BLOCKS     0x13
- #define MAX_ULEV1b_BLOCKS     0x28
- #define MAX_NTAG_203          0x29
- #define MAX_NTAG_210          0x13
- #define MAX_NTAG_212          0x28
- #define MAX_NTAG_213          0x2c
- #define MAX_NTAG_215          0x86
- #define MAX_NTAG_216        0xe6
+ #define MAX_UL_BLOCKS     0x0f
+ #define MAX_ULC_BLOCKS    0x2b
+ #define MAX_ULEV1a_BLOCKS 0x13
+ #define MAX_ULEV1b_BLOCKS 0x28
+ #define MAX_NTAG_203      0x29
+ #define MAX_NTAG_210      0x13
+ #define MAX_NTAG_212      0x28
+ #define MAX_NTAG_213      0x2c
+ #define MAX_NTAG_215      0x86
+ #define MAX_NTAG_216      0xe6
  
  #define KEYS_3DES_COUNT 7
  uint8_t default_3des_keys[KEYS_3DES_COUNT][16] = {
                { 0x49,0x45,0x4D,0x4B,0x41,0x45,0x52,0x42,0x21,0x4E,0x41,0x43,0x55,0x4F,0x59,0x46 },// NFC-key
                { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 },// all ones
                { 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF },// all FF
-               { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF },// 11 22 33
      };
+               { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF }     // 11 22 33
+ };
  
  #define KEYS_PWD_COUNT 10
  uint8_t default_pwd_pack[KEYS_PWD_COUNT][4] = {
        {0xFF,0xFF,0xFF,0xFF}, // PACK 0x00,0x00 -- factory default
-       
        {0x4A,0xF8,0x4B,0x19}, // PACK 0xE5,0xBE -- italian bus (sniffed)
        {0x33,0x6B,0xA1,0x19}, // PACK 0x9c,0x2d -- italian bus (sniffed)
        {0xFF,0x90,0x6C,0xB2}, // PACK 0x12,0x9e -- italian bus (sniffed)       
        {0x46,0x1c,0xA3,0x19}, // PACK 0xE9,0x5A -- italian bus (sniffed)
        {0x35,0x1C,0xD0,0x19}, // PACK 0x9A,0x5a -- italian bus (sniffed)
-       
        {0x05,0x22,0xE6,0xB4}, // PACK 0x80,0x80 -- Amiiboo (sniffed) pikachu-b UID:
        {0x7E,0x22,0xE6,0xB4}, // PACK 0x80,0x80 -- AMiiboo (sniffed) 
        {0x02,0xE1,0xEE,0x36}, // PACK 0x80,0x80 -- AMiiboo (sniffed) sonic UID:  04d257 7ae33e8027
        {0x32,0x0C,0x16,0x17}, // PACK 0x80,0x80 -- AMiiboo (sniffed) 
- };    
-       
+ };
  #define MAX_UL_TYPES 16
  uint16_t UL_TYPES_ARRAY[MAX_UL_TYPES] = {UNKNOWN, UL, UL_C, UL_EV1_48, UL_EV1_128, NTAG, NTAG_203,
            NTAG_210, NTAG_212, NTAG_213, NTAG_215, NTAG_216, MY_D, MY_D_NFC, MY_D_MOVE, MY_D_MOVE_NFC};
@@@ -65,9 -65,9 +65,9 @@@ uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] 
  
  static int CmdHelp(const char *Cmd);
  
- chargetProductTypeStr( uint8_t id){
+ char *getProductTypeStr( uint8_t id){
  
-       static char buf[20];
+       static char buf[20];
        char *retStr = buf;
  
        switch(id) {
    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). 
  */
- chargetUlev1CardSizeStr( uint8_t fsize ){
-  
-       static char buf[40];
+ char *getUlev1CardSizeStr( uint8_t fsize ){
+       static char buf[40];
        char *retStr = buf;
-       memset(buf, 0, sizeof(buf));    
-       
+       memset(buf, 0, sizeof(buf));
        uint16_t usize = 1 << ((fsize >>1) + 1);
        uint16_t lsize = 1 << (fsize >>1);
  
        // is  LSB set?
-       if ( fsize & 1 )
-               sprintf(retStr, "%02X, (%u <-> %u bytes)", fsize, usize, lsize);
+       if (  fsize & 1 )
+               sprintf(retStr, "%02X, (%u <-> %u bytes)",fsize, usize, lsize);
        else 
                sprintf(retStr, "%02X, (%u bytes)", fsize, lsize);              
        return buf;
@@@ -115,9 -115,9 +115,9 @@@ static int ul_send_cmd_raw( uint8_t *cm
        memcpy(c.d.asBytes, cmd, cmdlen);
        SendCommand(&c);
        UsbCommand resp;
-       if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return -1;
-       if ( !resp.arg[0] && responseLength) return -1;
-       
+       if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1;
+       if (!resp.arg[0] && responseLength) return -1;
        uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength;
        memcpy(response, resp.d.asBytes, resplen);
        return resplen;
@@@ -127,7 -127,7 +127,7 @@@ static int ul_send_cmd_raw_crc( uint8_
        UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT , cmdlen, 0}};
        if (append_crc)
                c.arg[0] |= ISO14A_APPEND_CRC;
-       
        memcpy(c.d.asBytes, cmd, cmdlen);       
        SendCommand(&c);
        UsbCommand resp;
        if (!resp.arg[0] && responseLength) return -1;
  
        uint16_t resplen = (resp.arg[0] < responseLength) ? resp.arg[0] : responseLength;
-               memcpy(response, resp.d.asBytes, resplen );
+       memcpy(response, resp.d.asBytes, resplen);
        return resplen;
  }
  */
  static int ul_select( iso14a_card_select_t *card ){
-       
        ul_switch_on_field();
  
        UsbCommand resp;
                ul_switch_off_field();
                return 0;
        }
+       memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t));
+       return 1;
+ }
+ // This read command will at least return 16bytes.
+ static int ul_read( uint8_t page, uint8_t *response, uint16_t responseLength ){
+       uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, page};
+       int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
+       return len;
+ }
+ static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){
+       uint8_t cmd[18];
+       memset(cmd, 0x00, sizeof(cmd));
+       datalen = ( datalen > 16) ? 16 : datalen;
+       cmd[0] = ISO14443A_CMD_WRITEBLOCK;
+       cmd[1] = page;
+       memcpy(cmd+2, data, datalen);
+       uint8_t response[1] = {0xff};
+       ul_send_cmd_raw(cmd, 2+datalen, response, sizeof(response));
+       // ACK
+       if ( response[0] == 0x0a ) return 0;
+       // NACK
+       return -1;
+ }
+ static int ulc_requestAuthentication( uint8_t *nonce, uint16_t nonceLength ){
+       uint8_t cmd[] = {MIFARE_ULC_AUTH_1, 0x00};
+       int len = ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength);
+       return len;
+ }
+ static int ulc_authentication( uint8_t *key, bool switch_off_field ){
+       UsbCommand c = {CMD_MIFAREUC_AUTH, {switch_off_field}};
+       memcpy(c.d.asBytes, key, 16);
+       SendCommand(&c);
+       UsbCommand resp;
+       if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return 0;
+       if ( resp.arg[0] == 1 ) return 1;
+       return 0;
+ }
+ static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){
+       uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]};
+       int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength);
+       return len;
+ }
++static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool hasAuthKey, uint8_t *authenticationkey, uint8_t *pack, uint8_t packSize){
++      if ( hasAuthKey && (tagtype & UL_C)) {
++              //will select card automatically and close connection on error
++              if (!ulc_authentication(authenticationkey, false)) {
++                      PrintAndLog("Error: Authentication Failed UL-C");
++                      return 0;
++      }
 +      
 +      memcpy(card, resp.d.asBytes, sizeof(iso14a_card_select_t));
 +      return 1;
 +}
 +
 +// This read command will at least return 16bytes.
 +static int ul_read( uint8_t page, uint8_t *response, uint16_t responseLength ){
 +      
 +      uint8_t cmd[] = {ISO14443A_CMD_READBLOCK, page};
 +      int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
 +      return len;
 +}
 +
 +static int ul_comp_write( uint8_t page, uint8_t *data, uint8_t datalen ){
 +
 +      uint8_t cmd[18];
 +      memset(cmd, 0x00, sizeof(cmd));
 +      datalen = ( datalen > 16) ? 16 : datalen;
 +
 +      cmd[0] = ISO14443A_CMD_WRITEBLOCK;
 +      cmd[1] = page;
 +      memcpy(cmd+2, data, datalen);
 +
 +      uint8_t response[1] = {0xff};
 +      ul_send_cmd_raw(cmd, 2+datalen, response, sizeof(response));
 +      // ACK
 +      if ( response[0] == 0x0a ) return 0;
 +      // NACK
 +      return -1;      
 +}
 +
 +static int ulc_requestAuthentication( uint8_t *nonce, uint16_t nonceLength ){
 +      
 +      uint8_t cmd[] = {MIFARE_ULC_AUTH_1, 0x00};
 +      int len = ul_send_cmd_raw(cmd, sizeof(cmd), nonce, nonceLength);
 +      return len;
 +}
 +
 +static int ulc_authentication( uint8_t *key, bool switch_off_field ){
 +      
 +      UsbCommand c = {CMD_MIFAREUC_AUTH, {switch_off_field}};
 +      memcpy(c.d.asBytes, key, 16);   
 +      SendCommand(&c);
 +      UsbCommand resp;
 +      if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) return 0;
 +      if ( resp.arg[0] == 1 ) return 1;
 +      
 +      return 0;
 +}
 +
 +static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t packLength ){
 +      
 +      uint8_t cmd[] = {MIFARE_ULEV1_AUTH, pwd[0], pwd[1], pwd[2], pwd[3]};
 +      int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength);
 +      return len;
 +}
 +
  static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool hasAuthKey, uint8_t *authenticationkey, uint8_t *pack, uint8_t packSize){
        if ( hasAuthKey && (tagtype & UL_C)) {
                //will select card automatically and close connection on error
  }
  
  static int ulev1_getVersion( uint8_t *response, uint16_t responseLength ){
-       
        uint8_t cmd[] = {MIFARE_ULEV1_VERSION}; 
        int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength);
        return len;
@@@ -268,7 -268,7 +332,7 @@@ static int ulev1_readSignature( uint8_
  }
  
  static int ul_print_default( uint8_t *data){
-       
        uint8_t uid[7];
        uid[0] = data[0];
        uid[1] = data[1];
        uid[6] = data[7];
  
        PrintAndLog("       UID : %s ", sprint_hex(uid, 7));
-       PrintAndLog("    UID[0] : %02X, %s",  uid[0], getTagInfo(uid[0]) );
+       PrintAndLog("    UID[0] : %02X, Manufacturer: %s",  uid[0], getTagInfo(uid[0]) );
        if ( uid[0] == 0x05 ) {
                uint8_t chip = (data[8] & 0xC7); // 11000111  mask, bit 3,4,5 RFU
                switch (chip){
                PrintAndLog("      BCC0 : %02X, Ok", data[3]);
        else
                PrintAndLog("      BCC0 : %02X, crc should be %02X", data[3], crc0);
-       
        int crc1 = data[4] ^ data[5] ^ data[6] ^data[7];
        if ( data[8] == crc1 )
                PrintAndLog("      BCC1 : %02X, Ok", data[8]);
        else
                PrintAndLog("      BCC1 : %02X, crc should be %02X", data[8], crc1 );
-       
        PrintAndLog("  Internal : %02X, %sdefault", data[9], (data[9]==0x48)?"":"not " );
  
        PrintAndLog("      Lock : %s - %s",
                                printBits(2, data+10)
                );
  
-       PrintAndLog("OneTimePad : %s - %s\n",
-                               sprint_hex(data + 12, 4),
-                               printBits(4, data+12)
-               );
+       PrintAndLog("OneTimePad : %s - %s\n",
+                               sprint_hex(data + 12, 4),
+                               printBits(4, data+12)
+               );
+       return 0;
+ }
+ static int ndef_print_CC(uint8_t *data) {
+       // no NDEF message
+       if(data[0] != 0xe1)
+               return -1;
+       PrintAndLog("--- NDEF Message");
+       PrintAndLog("Capability Container: %s", sprint_hex(data,4) );
+       PrintAndLog("  %02X : NDEF Magic Number", data[0]); 
+       PrintAndLog("  %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f);
+       PrintAndLog("  %02X : Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8);
+       if ( data[2] == 0x12 )
+               PrintAndLog("  %02X : NDEF Memory Size: %d bytes", data[2], 144);
+       else if ( data[2] == 0x3e )
+               PrintAndLog("  %02X : NDEF Memory Size: %d bytes", data[2], 496);
+       else if ( data[2] == 0x6d )
+               PrintAndLog("  %02X : NDEF Memory Size: %d bytes", data[2], 872);
+       PrintAndLog("  %02X : %s / %s", data[3], 
+                               (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", 
+                               (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)");
+       return 0;
+ }
+ int ul_print_type(uint32_t tagtype, uint8_t spaces){
+       char spc[11] = "          ";
+       spc[10]=0x00;
+       char *spacer = spc + (10-spaces);
+       if ( tagtype & UL )     
+               PrintAndLog("%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "<magic>" : "" );
+       else if ( tagtype & UL_C)
+               PrintAndLog("%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "<magic>" : "" );
+       else if ( tagtype & UL_EV1_48)
+               PrintAndLog("%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); 
+       else if ( tagtype & UL_EV1_128) 
+               PrintAndLog("%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer);
+       else if ( tagtype & NTAG )
+               PrintAndLog("%sTYPE : NTAG UNKNOWN", spacer);
+       else if ( tagtype & NTAG_203 )
+               PrintAndLog("%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer);
+       else if ( tagtype & NTAG_210 )
+               PrintAndLog("%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer);
+       else if ( tagtype & NTAG_212 )
+               PrintAndLog("%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer);
+       else if ( tagtype & NTAG_213 )
+               PrintAndLog("%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer);
+       else if ( tagtype & NTAG_215 )
+               PrintAndLog("%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer);
+       else if ( tagtype & NTAG_216 )
+               PrintAndLog("%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer);
+       else if ( tagtype & NTAG_I2C_1K )
+               PrintAndLog("%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD");
+       else if ( tagtype & NTAG_I2C_2K )       
+               PrintAndLog("%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD");
+       else if ( tagtype & MY_D )
+               PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer);
+       else if ( tagtype & MY_D_NFC )
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC", spacer);
+       else if ( tagtype & MY_D_MOVE )
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 move", spacer);
+       else if ( tagtype & MY_D_MOVE_NFC )
+               PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC", spacer);
+       else
+               PrintAndLog("%sTYPE : Unknown %06x", spacer, tagtype);
+       return 0;
+ }
+ static int ulc_print_3deskey( uint8_t *data){
+       PrintAndLog("         deskey1 [44/0x2C] : %s [%.4s]", sprint_hex(data   ,4),data);
+       PrintAndLog("         deskey1 [45/0x2D] : %s [%.4s]", sprint_hex(data+4 ,4),data+4);
+       PrintAndLog("         deskey2 [46/0x2E] : %s [%.4s]", sprint_hex(data+8 ,4),data+8);
+       PrintAndLog("         deskey2 [47/0x2F] : %s [%.4s]", sprint_hex(data+12,4),data+12);
+       PrintAndLog("\n 3des key : %s", sprint_hex(SwapEndian64(data, 16, 8), 16));
+       return 0;
+ }
+ static int ulc_print_configuration( uint8_t *data){
+       PrintAndLog("--- UL-C Configuration");
+       PrintAndLog(" Higher Lockbits [40/0x28] : %s - %s", sprint_hex(data, 4), printBits(2, data));
+       PrintAndLog("         Counter [41/0x29] : %s - %s", sprint_hex(data+4, 4), printBits(2, data+4));
+       bool validAuth = (data[8] >= 0x03 && data[8] <= 0x30);
+       if ( validAuth )
+               PrintAndLog("           Auth0 [42/0x2A] : %s page %d/0x%02X and above need authentication", sprint_hex(data+8, 4), data[8],data[8] );
+       else{
+               if ( data[8] == 0){
+                       PrintAndLog("           Auth0 [42/0x2A] : %s default", sprint_hex(data+8, 4) );
+               } else {
+                       PrintAndLog("           Auth0 [42/0x2A] : %s auth byte is out-of-range", sprint_hex(data+8, 4) );
+               }
+       }
+       PrintAndLog("           Auth1 [43/0x2B] : %s %s",
+                       sprint_hex(data+12, 4),
+                       (data[12] & 1) ? "write access restricted": "read and write access restricted"
+                       );
+       return 0;
+ }
+ static int ulev1_print_configuration( uint8_t *data, uint8_t startPage){
+       PrintAndLog("\n--- Tag Configuration");
+       bool strg_mod_en = (data[0] & 2);
+       uint8_t authlim = (data[4] & 0x07);
+       bool cfglck = (data[4] & 0x40);
+       bool prot = (data[4] & 0x80);
+       uint8_t vctid = data[5];
+       PrintAndLog("  cfg0 [%u/0x%02X] : %s", startPage, startPage, sprint_hex(data, 4));
+       if ( data[3] < 0xff )
+               PrintAndLog("                    - page %d and above need authentication",data[3]);
+       else 
+               PrintAndLog("                    - pages don't need authentication");
+       PrintAndLog("                    - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled");
+       PrintAndLog("  cfg1 [%u/0x%02X] : %s", startPage + 1, startPage + 1,  sprint_hex(data+4, 4) );
+       if ( authlim == 0)
+               PrintAndLog("                    - Unlimited password attempts");
+       else
+               PrintAndLog("                    - Max number of password attempts is %d", authlim);
+       PrintAndLog("                    - user configuration %s", cfglck ? "permanently locked":"writeable");
+       PrintAndLog("                    - %s access is protected with password", prot ? "read and write":"write");
+       PrintAndLog("                    - %02X, Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not");
+       PrintAndLog("  PWD  [%u/0x%02X] : %s- (cannot be read)", startPage + 2, startPage + 2,  sprint_hex(data+8, 4));
+       PrintAndLog("  PACK [%u/0x%02X] : %s      - (cannot be read)", startPage + 3, startPage + 3,  sprint_hex(data+12, 2));
+       PrintAndLog("  RFU  [%u/0x%02X] :       %s- (cannot be read)", startPage + 3, startPage + 3,  sprint_hex(data+12, 2));
+       return 0;
+ }
+ static int ulev1_print_counters(){
+       PrintAndLog("--- Tag Counters");
+       uint8_t tear[1] = {0};
+       uint8_t counter[3] = {0,0,0};
+       uint16_t len = 0;
+       for ( uint8_t i = 0; i<3; ++i) {
+               ulev1_readTearing(i,tear,sizeof(tear));
+               len = ulev1_readCounter(i,counter, sizeof(counter) );
+               if (len == 3) {
+                       PrintAndLog("       [%0d] : %s", i, sprint_hex(counter,3));
+                       PrintAndLog("                    - %02X tearing %s", tear[0], ( tear[0]==0xBD)?"Ok":"failure");
+               }
+       }
+       return len;
+ }
+ static int ulev1_print_signature( uint8_t *data, uint8_t len){
+       PrintAndLog("\n--- Tag Signature");     
+       //PrintAndLog("IC signature public key name  : NXP NTAG21x 2013"); // don't know if there is other NXP public keys.. :(
+       PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61");
+       PrintAndLog("    Elliptic curve parameters : secp128r1");
+       PrintAndLog("            Tag ECC Signature : %s", sprint_hex(data, len));
+       //to do:  verify if signature is valid
+       //PrintAndLog("IC signature status: %s valid", (iseccvalid() )?"":"not");
+       return 0;
+ }
+ static int ulev1_print_version(uint8_t *data){
+       PrintAndLog("\n--- Tag Version");
+       PrintAndLog("       Raw bytes : %s",sprint_hex(data, 8) );
+       PrintAndLog("       Vendor ID : %02X, %s", data[1], getTagInfo(data[1]));
+       PrintAndLog("    Product type : %s", getProductTypeStr(data[2]));
+       PrintAndLog(" Product subtype : %02X, %s", data[3], (data[3]==1) ?"17 pF":"50pF");
+       PrintAndLog("   Major version : %02X", data[4]);
+       PrintAndLog("   Minor version : %02X", data[5]);
+       PrintAndLog("            Size : %s", getUlev1CardSizeStr(data[6]));
+       PrintAndLog("   Protocol type : %02X", data[7]);
+       return 0;
+ }
+ /*
+ static int ulc_magic_test(){
+       // Magic Ultralight test
+               // Magic UL-C, by observation,
+       // 1) it seems to have a static nonce response to 0x1A command.
+       // 2) the deskey bytes is not-zero:d out on as datasheet states.
+       // 3) UID - changeable, not only, but pages 0-1-2-3.
+       // 4) use the ul_magic_test !  magic tags answers specially!
+       int returnValue = UL_ERROR;
+       iso14a_card_select_t card;
+       uint8_t nonce1[11] = {0x00};
+       uint8_t nonce2[11] = {0x00};
+       int status = ul_select(&card);
+       if ( !status ){
+               return UL_ERROR;
+       }
+       status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
+       if ( status > 0 ) {
+               status = ulc_requestAuthentication(nonce2, sizeof(nonce2));
+               returnValue =  ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C;
+       } else {
+               returnValue = UL;
+       }       
+       ul_switch_off_field();
+       return returnValue;
+ }
+ */
+ static int ul_magic_test(){
+       // Magic Ultralight tests
+       // 1) take present UID, and try to write it back. OBSOLETE 
+       // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK:
+       iso14a_card_select_t card;
+       if ( !ul_select(&card) ) 
+               return UL_ERROR;
+       int status = ul_comp_write(0, NULL, 0);
+       ul_switch_off_field();
+       if ( status == 0 ) 
+               return MAGIC;
+       return 0;
+ }
+ uint32_t GetHF14AMfU_Type(void){
+       TagTypeUL_t tagtype = UNKNOWN;
+       iso14a_card_select_t card;
+       uint8_t version[10] = {0x00};
+       int status = 0;
+       int len;
+       if (!ul_select(&card)) return UL_ERROR;
+       // Ultralight - ATQA / SAK 
+       if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) {
+               PrintAndLog("Tag is not Ultralight | NTAG | MY-D  [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak);
+               ul_switch_off_field();
+               return UL_ERROR;
+       }
+       if ( card.uid[0] != 0x05) {
+               len  = ulev1_getVersion(version, sizeof(version));
+               ul_switch_off_field();
+               switch (len) {
+                       case 0x0A: {
+                               if ( version[2] == 0x03 && version[6] == 0x0B )
+                                       tagtype = UL_EV1_48;
+                               else if ( version[2] == 0x03 && version[6] != 0x0B )
+                                       tagtype = UL_EV1_128;
+                               else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0B )
+                                       tagtype = NTAG_210;
+                               else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0E )
+                                       tagtype = NTAG_212;
+                               else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x0F )
+                                       tagtype = NTAG_213;
+                               else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x11 )
+                                       tagtype = NTAG_215;
+                               else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x13 )
+                                       tagtype = NTAG_216;
+                               else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x13 )
+                                       tagtype = NTAG_I2C_1K;
+                               else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x15 )
+                                       tagtype = NTAG_I2C_2K;
+                               else if ( version[2] == 0x04 )
+                                       tagtype = NTAG;
+                               break;
+                       }
+                       case 0x01: tagtype = UL_C; break;
+                       case 0x00: tagtype = UL; break;
+                       case -1  : tagtype = (UL | UL_C | NTAG_203); break;  // could be UL | UL_C magic tags
+                       default  : tagtype = UNKNOWN; break;
+               }
+               // UL vs UL-C vs ntag203 test
+               if (tagtype & (UL | UL_C | NTAG_203)) {
+                       if ( !ul_select(&card) ) return UL_ERROR;
+                       // do UL_C check first...
+                       uint8_t nonce[11] = {0x00};
+                       status = ulc_requestAuthentication(nonce, sizeof(nonce));
+                       ul_switch_off_field();
+                       if (status > 1) {
+                               tagtype = UL_C;
+                       } else { 
+                               // need to re-select after authentication error
+                               if ( !ul_select(&card) ) return UL_ERROR;
+                               uint8_t data[16] = {0x00};
+                               // read page 0x26-0x29 (last valid ntag203 page)
+                               status = ul_read(0x26, data, sizeof(data));
+                               if ( status <= 1 ) {
+                                       tagtype = UL;
+                               } else {
+                                       // read page 0x30 (should error if it is a ntag203)
+                                       status = ul_read(0x30, data, sizeof(data));
+                                       if ( status <= 1 ){
+                                               tagtype = NTAG_203;
+                                       } else {
+                                               tagtype = UNKNOWN;
+                                       }
+                               }
+                               ul_switch_off_field();
+                       }
+               }
+       } else {
+               // Infinition MY-D tests   Exam high nibble 
+               uint8_t nib = (card.uid[1] & 0xf0) >> 4;
+               switch ( nib ){
+                       case 1: tagtype =  MY_D; break;
+                       case 2: tagtype = (MY_D | MY_D_NFC); break; //notice: we can not currently distinguish between these two
+                       case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //notice: we can not currently distinguish between these two
+               }
+       }
+       tagtype |= ul_magic_test();
+       if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC);
+       return tagtype;
+ }
+ int CmdHF14AMfUInfo(const char *Cmd){
+       uint8_t authlim = 0xff;
+       uint8_t data[16] = {0x00};
+       iso14a_card_select_t card;
+       int status;
+       bool errors = false;
+       bool hasAuthKey = false;
+       bool locked = false;
+       bool swapEndian = false;
+       uint8_t cmdp = 0;
+       uint8_t dataLen = 0;
+       uint8_t authenticationkey[16] = {0x00};
+       uint8_t *authkeyptr = authenticationkey;
+       uint8_t *key;
+       uint8_t pack[4] = {0,0,0,0};
+       int len = 0;
+       char tempStr[50];
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+               case 'h':
+               case 'H':
+                       return usage_hf_mfu_info();
+               case 'k':
+               case 'K':
+                       dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+                       if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length
+                               errors = param_gethex(tempStr, 0, authenticationkey, dataLen);
+                               dataLen /= 2; // handled as bytes from now on
+                       } else {
+                               PrintAndLog("\nERROR: Key is incorrect length\n");
 -                              errors = true;
++                              errors = true;
++                      }
++                      cmdp += 2;
++                      hasAuthKey = true;
++                      break;
++              case 'l':
++              case 'L':
++                      swapEndian = true;
++                      cmdp++;
++                      break;
++              default:
++                      PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
++                      errors = true;
++                      break;
++              }
++              if(errors) break;
++      }
++
++      //Validations
++      if(errors) return usage_hf_mfu_info();
++
++      TagTypeUL_t tagtype = GetHF14AMfU_Type();
++      if (tagtype == UL_ERROR) return -1;
++
++      PrintAndLog("\n--- Tag Information ---------");
++      PrintAndLog("-------------------------------------------------------------");
++      ul_print_type(tagtype, 6);
++
++      // Swap endianness 
++      if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4 );
++
++      if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
++
++      // read pages 0,1,2,3 (should read 4pages)
++      status = ul_read(0, data, sizeof(data));
++      if ( status == -1 ) {
++              ul_switch_off_field();
++              PrintAndLog("Error: tag didn't answer to READ");
++              return status;
++      } else if (status == 16) {
++              ul_print_default(data);
++              ndef_print_CC(data+12);
++      } else {
++              locked = true;
++      }
++
++      // UL_C Specific
++      if ((tagtype & UL_C)) {
 +
-       return 0;
- }
++              // read pages 0x28, 0x29, 0x2A, 0x2B
++              uint8_t ulc_conf[16] = {0x00};
++              status = ul_read(0x28, ulc_conf, sizeof(ulc_conf));
++              if ( status == -1 ){
++                      PrintAndLog("Error: tag didn't answer to READ UL-C");
++                      ul_switch_off_field();
++                      return status;
++              } 
++              if (status == 16) ulc_print_configuration(ulc_conf);
++              else locked = true;
 +
- static int ndef_print_CC(uint8_t *data) {
-       // no NDEF message
-       if(data[0] != 0xe1)
-               return -1;
++              if ((tagtype & MAGIC)) {
++                      //just read key
++                      uint8_t ulc_deskey[16] = {0x00};
++                      status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
++                      if ( status == -1 ) {
++                              ul_switch_off_field();
++                              PrintAndLog("Error: tag didn't answer to READ magic");
++                              return status;
++                      }
++                      if (status == 16) ulc_print_3deskey(ulc_deskey);
 +
-       PrintAndLog("--- NDEF Message");
-       PrintAndLog("Capability Container: %s", sprint_hex(data,4) );
-       PrintAndLog("  %02X : NDEF Magic Number", data[0]); 
-       PrintAndLog("  %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f);
-       PrintAndLog("  %02X : Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8);
-       if ( data[2] == 0x12 )
-               PrintAndLog("  %02X : NDEF Memory Size: %d bytes", data[2], 144);
-       else if ( data[2] == 0x3e )
-               PrintAndLog("  %02X : NDEF Memory Size: %d bytes", data[2], 496);
-       else if ( data[2] == 0x6d )
-               PrintAndLog("  %02X : NDEF Memory Size: %d bytes", data[2], 872);
-       
-       PrintAndLog("  %02X : %s / %s", data[3], 
-                               (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", 
-                               (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)");
-       return 0;                               
- }
++              } else {
++                      ul_switch_off_field();
++                      // if we called info with key, just return 
++                      if ( hasAuthKey ) return 1;
 +
- int ul_print_type(uint32_t tagtype, uint8_t spaces){
-       char spc[11] = "          ";
-       spc[10]=0x00;
-       char *spacer = spc + (10-spaces);
++                      // also try to diversify default keys..  look into CmdHF14AMfuGenDiverseKeys
++                      PrintAndLog("Trying some default 3des keys");
++                      for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) {
++                              key = default_3des_keys[i];
++                              if (ulc_authentication(key, true)) {
++                                      PrintAndLog("Found default 3des key: ");
++                                      uint8_t keySwap[16];
++                                      memcpy(keySwap, SwapEndian64(key,16,8), 16);
++                                      ulc_print_3deskey(keySwap);
++                                      return 1;
++                              } 
++                      }
++                      return 1;
++              }
++      }
 +
-       if ( tagtype & UL )     
-               PrintAndLog("%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "<magic>" : "" );
-       else if ( tagtype & UL_C)
-               PrintAndLog("%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "<magic>" : "" );
-       else if ( tagtype & UL_EV1_48)
-               PrintAndLog("%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); 
-       else if ( tagtype & UL_EV1_128) 
-               PrintAndLog("%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer);
-       else if ( tagtype & NTAG )
-               PrintAndLog("%sTYPE : NTAG UNKNOWN", spacer);
-       else if ( tagtype & NTAG_203 )
-               PrintAndLog("%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer);
-       else if ( tagtype & NTAG_210 )
-               PrintAndLog("%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer);
-       else if ( tagtype & NTAG_212 )
-               PrintAndLog("%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer);
-       else if ( tagtype & NTAG_213 )
-               PrintAndLog("%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer);
-       else if ( tagtype & NTAG_215 )
-               PrintAndLog("%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer);
-       else if ( tagtype & NTAG_216 )
-               PrintAndLog("%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer);
-       else if ( tagtype & NTAG_I2C_1K )
-               PrintAndLog("%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD");
-       else if ( tagtype & NTAG_I2C_2K )       
-               PrintAndLog("%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD");
-       else if ( tagtype & MY_D )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99", spacer);
-       else if ( tagtype & MY_D_NFC )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99 NFC", spacer);
-       else if ( tagtype & MY_D_MOVE )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99 move", spacer);
-       else if ( tagtype & MY_D_MOVE_NFC )
-               PrintAndLog("%sTYPE : INFINEON my-d\x99 move NFC", spacer);
-       else
-               PrintAndLog("%sTYPE : Unknown %06x", spacer, tagtype);
-       return 0;
- }
++      // do counters and signature first (don't neet auth) 
 +
- static int ulc_print_3deskey( uint8_t *data){                 
-       PrintAndLog("         deskey1 [44/0x2C] : %s [%.4s]", sprint_hex(data   ,4),data);
-       PrintAndLog("         deskey1 [45/0x2D] : %s [%.4s]", sprint_hex(data+4 ,4),data+4);
-       PrintAndLog("         deskey2 [46/0x2E] : %s [%.4s]", sprint_hex(data+8 ,4),data+8);
-       PrintAndLog("         deskey2 [47/0x2F] : %s [%.4s]", sprint_hex(data+12,4),data+12);
-       PrintAndLog("\n 3des key : %s", sprint_hex(SwapEndian64(data, 16, 8), 16));
-       return 0;
- }
++      // ul counters are different than ntag counters
++      if ((tagtype & (UL_EV1_48 | UL_EV1_128))) {
++              if (ulev1_print_counters() != 3) {
++                      // failed - re-select
++                      if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
++              }
++      }
 +
- static int ulc_print_configuration( uint8_t *data){
-               
-       PrintAndLog("--- UL-C Configuration");
-       PrintAndLog(" Higher Lockbits [40/0x28] : %s - %s", sprint_hex(data, 4), printBits(2, data));
-       PrintAndLog("         Counter [41/0x29] : %s - %s", sprint_hex(data+4, 4), printBits(2, data+4));
++      if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K     ))) {
++              uint8_t ulev1_signature[32] = {0x00};
++              status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature));
++              if ( status == -1 ) {
++                      PrintAndLog("Error: tag didn't answer to READ SIGNATURE");
++                      ul_switch_off_field();
++                      return status;
++              }
++              if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature));
++              else {
++                      // re-select
++                      if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
++              }
++      }
 +
-       bool validAuth = (data[8] >= 0x03 && data[8] <= 0x30);
-       if ( validAuth )
-               PrintAndLog("           Auth0 [42/0x2A] : %s page %d/0x%02X and above need authentication", sprint_hex(data+8, 4), data[8],data[8] );
-       else{
-               if ( data[8] == 0){
-                       PrintAndLog("           Auth0 [42/0x2A] : %s default", sprint_hex(data+8, 4) );
++      if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) {
++              uint8_t version[10] = {0x00};
++              status  = ulev1_getVersion(version, sizeof(version));
++              if ( status == -1 ) {
++                      PrintAndLog("Error: tag didn't answer to GETVERSION");
++                      ul_switch_off_field();
++                      return status;
++              } else if (status == 10) {
++                      ulev1_print_version(version);
 +              } else {
-                       PrintAndLog("           Auth0 [42/0x2A] : %s auth byte is out-of-range", sprint_hex(data+8, 4) );
++                      locked = true;
++                      if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
++              }
++
++              uint8_t startconfigblock = 0;
++              uint8_t ulev1_conf[16] = {0x00};
++              // config blocks always are last 4 pages
++              for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++)
++                      if (tagtype & UL_TYPES_ARRAY[idx])
++                              startconfigblock = UL_MEMORY_ARRAY[idx]-3;
++
++              if (startconfigblock){ // if we know where the config block is...
++                      status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
++                      if ( status == -1 ) {
++                              PrintAndLog("Error: tag didn't answer to READ EV1");
++                              ul_switch_off_field();
++                              return status;
++                      } else if (status == 16) {
++                              // save AUTHENTICATION LIMITS for later:
++                              authlim = (ulev1_conf[4] & 0x07);
++                              ulev1_print_configuration(ulev1_conf, startconfigblock);
++                      }
++              }
++
++              // AUTHLIMIT, (number of failed authentications)
++              // 0 = limitless.
++              // 1-7 = limit. No automatic tries then.
++              // hasAuthKey,  if we was called with key, skip test.
++              if ( !authlim && !hasAuthKey ) {
++                      PrintAndLog("\n--- Known EV1/NTAG passwords.");
++                      len = 0;
++                      for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ) {
++                              key = default_pwd_pack[i];
++                              len = ulev1_requestAuthentication(key, pack, sizeof(pack));
++                              if (len >= 1) {
++                                      PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
++                                      break;
++                              } else {
++                                      if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
++                              }
++                      }
++                      if (len < 1) PrintAndLog("password not known");
 +              }
 +      }
-       PrintAndLog("           Auth1 [43/0x2B] : %s %s",
-                       sprint_hex(data+12, 4),
-                       (data[12] & 1) ? "write access restricted": "read and write access restricted"
-                       );
-       return 0;
++
++      ul_switch_off_field();
++      if (locked) PrintAndLog("\nTag appears to be locked, try using the key to get more info");
++      PrintAndLog("");
++      return 1;
 +}
 +
- static int ulev1_print_configuration( uint8_t *data){
++//
++//  Mifare Ultralight Write Single Block
++//
++int CmdHF14AMfUWrBl(const char *Cmd){
++      uint8_t blockNo    = -1;
++      bool chinese_card  = FALSE;
++      uint8_t bldata[16] = {0x00};
++      UsbCommand resp;
 +
 +      PrintAndLog("\n--- Tag Configuration");
 +
 +      bool strg_mod_en = (data[0] & 2);
 +      uint8_t authlim = (data[4] & 0x07);
 +      bool cfglck = (data[4] & 0x40);
 +      bool prot = (data[4] & 0x80);
 +      uint8_t vctid = data[5];
 +       
 +      PrintAndLog(" cfg0 [16/0x10]: %s", sprint_hex(data, 4));
 +      if ( data[3] < 0xff )
 +              PrintAndLog("                    - page %d and above need authentication",data[3]);
 +      else 
 +              PrintAndLog("                    - pages don't need authentication");
 +      PrintAndLog("                    - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled");
 +      PrintAndLog(" cfg1 [17/0x11]: %s", sprint_hex(data+4, 4) );
 +      if ( authlim == 0)
 +              PrintAndLog("                    - Unlimited password attempts");
 +      else
 +              PrintAndLog("                    - Max number of password attempts is %d", authlim);
 +      PrintAndLog("                    - user configuration %s", cfglck ? "permanently locked":"writeable");
 +      PrintAndLog("                    - %s access is protected with password", prot ? "read and write":"write");
 +      PrintAndLog("                 %02X - Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not");
 +      PrintAndLog(" PWD  [18/0x12]: %s", sprint_hex(data+8, 4));
 +      PrintAndLog(" PACK [19/0x13]: %s", sprint_hex(data+12, 4));
 +      return 0;
 +}
 +
 +static int ulev1_print_counters(){
 +      PrintAndLog("--- Tag Counters");
 +      uint8_t tear[1] = {0};
 +      uint8_t counter[3] = {0,0,0};
 +      uint16_t len = 0;
 +      for ( uint8_t i = 0; i<3; ++i) {
 +              ulev1_readTearing(i,tear,sizeof(tear));
 +              len = ulev1_readCounter(i,counter, sizeof(counter) );
 +              if (len == 3) {
 +              PrintAndLog("       [%0d] : %s", i, sprint_hex(counter,3));
 +              PrintAndLog("                    - %02X tearing %s", tear[0], ( tear[0]==0xBD)?"Ok":"failure");
 +      }
 +      }
 +      return len;
 +}
 +
 +static int ulev1_print_signature( uint8_t *data, uint8_t len){
 +      PrintAndLog("\n--- Tag Signature");     
 +      //PrintAndLog("IC signature public key name  : NXP NTAG21x 2013");  // don't know if there is other NXP public keys.. :(
 +      PrintAndLog("IC signature public key value : 04494e1a386d3d3cfe3dc10e5de68a499b1c202db5b132393e89ed19fe5be8bc61");
 +      PrintAndLog("    Elliptic curve parameters : secp128r1");
 +      PrintAndLog("            Tag ECC Signature : %s", sprint_hex(data, len));
 +      //to do:  verify if signature is valid
 +      //PrintAndLog("IC signature status: %s valid", (iseccvalid() )?"":"not");
 +      return 0;
 +}
 +
 +static int ulev1_print_version(uint8_t *data){                
 +      PrintAndLog("\n--- Tag Version");
 +      PrintAndLog("       Raw bytes : %s", sprint_hex(data, 8) );
 +      PrintAndLog("       Vendor ID : %02X, %s", data[1], getTagInfo(data[1]));
 +      PrintAndLog("    Product type : %s"             , getProductTypeStr(data[2]));
 +      PrintAndLog(" Product subtype : %02X, %s"       , data[3], (data[3]==1) ?"17 pF":"50pF");
 +      PrintAndLog("   Major version : %02X"   , data[4]);
 +      PrintAndLog("   Minor version : %02X"   , data[5]);
 +      PrintAndLog("            Size : %s", getUlev1CardSizeStr(data[6]));
 +      PrintAndLog("   Protocol type : %02X"   , data[7]);
 +      return 0;
 +}
 +
 +/*
 +static int ulc_magic_test(){
 +      // Magic Ultralight test
 +              // Magic UL-C, by observation,
 +      // 1) it seems to have a static nonce response to 0x1A command.
 +      // 2) the deskey bytes is not-zero:d out on as datasheet states.
 +      // 3) UID - changeable, not only, but pages 0-1-2-3.
 +      // 4) use the ul_magic_test !  magic tags answers specially!
 +      int returnValue = UL_ERROR;
 +      iso14a_card_select_t card;
 +      uint8_t nonce1[11] = {0x00};
 +      uint8_t nonce2[11] = {0x00};
 +      int status = ul_select(&card);
 +      if ( !status ){
 +              return UL_ERROR;
 +      }
 +      status = ulc_requestAuthentication(nonce1, sizeof(nonce1));
 +      if ( status > 0 ) {
 +              status = ulc_requestAuthentication(nonce2, sizeof(nonce2));
 +              returnValue =  ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C;
 +      } else {
 +              returnValue = UL;
 +      }       
 +      ul_switch_off_field();
 +      return returnValue;
 +}
 +*/
 +static int ul_magic_test(){
 +      
 +      // Magic Ultralight tests
 +      // 1) take present UID, and try to write it back. OBSOLETE 
 +      // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK:
 +      iso14a_card_select_t card;
 +      if ( !ul_select(&card) ) 
 +              return UL_ERROR;
 +      int status = ul_comp_write(0, NULL, 0);
 +      ul_switch_off_field();
 +      if ( status == 0 ) 
 +              return MAGIC;
 +      return 0;
 +}
 +
- uint32_t GetHF14AMfU_Type(void){
-       TagTypeUL_t tagtype = UNKNOWN;
-       iso14a_card_select_t card;
-       uint8_t version[10] = {0x00};
-       int status = 0;
-       int len;
-       if (!ul_select(&card)) return UL_ERROR;
-       // Ultralight - ATQA / SAK 
-       if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) {
-               PrintAndLog("Tag is not Ultralight | NTAG | MY-D  [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak);
-               ul_switch_off_field();
-               return UL_ERROR;
++      if (blockNo > MAX_UL_BLOCKS){
++              PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
++              return 1;
 +      }
 +      
 +      if ( card.uid[0] != 0x05) {
 +
 +              len  = ulev1_getVersion(version, sizeof(version));
 +              ul_switch_off_field();
 +      
 +              switch (len) {
 +                      case 0x0A: {
 +                      
 +                              if ( version[2] == 0x03 && version[6] == 0x0B ) 
 +                                      tagtype = UL_EV1_48;
 +                              else if ( version[2] == 0x03 && version[6] != 0x0B ) 
 +                                      tagtype = UL_EV1_128;                                   
 +                              else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0B )
 +                                      tagtype = NTAG_210;
 +                              else if ( version[2] == 0x04 && version[3] == 0x01 && version[6] == 0x0E )
 +                                      tagtype = NTAG_212;
 +                              else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x0F )
 +                                      tagtype = NTAG_213;
 +                              else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x11 )
 +                                      tagtype = NTAG_215;     
 +                              else if ( version[2] == 0x04 && version[3] == 0x02 && version[6] == 0x13 )                              
 +                                      tagtype = NTAG_216;                             
 +                              else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x13 )
 +                                      tagtype = NTAG_I2C_1K;
 +                              else if ( version[2] == 0x04 && version[3] == 0x05 && version[6] == 0x15 )
 +                                      tagtype = NTAG_I2C_2K;
 +                              else if ( version[2] == 0x04 ) 
 +                                      tagtype = NTAG;
 +                              
 +                              break;
 +                              }
 +                      case 0x01: tagtype = UL_C; break;
 +                      case 0x00: tagtype = UL; break;
 +                      case -1  : tagtype = (UL | UL_C | NTAG_203); break;  // could be UL | UL_C magic tags
 +                      default  : tagtype = UNKNOWN; break;
 +              }
 +              // UL vs UL-C vs ntag203 test
 +              if (tagtype & (UL | UL_C | NTAG_203)) {
 +                      if ( !ul_select(&card) ) return UL_ERROR;
 +
 +                      // do UL_C check first...
 +                      uint8_t nonce[11] = {0x00};
 +                      status = ulc_requestAuthentication(nonce, sizeof(nonce));
 +                      ul_switch_off_field();
 +                      if (status > 1) {
 +                              tagtype = UL_C;
 +                      } else { 
 +                              // need to re-select after authentication error
 +                              if ( !ul_select(&card) ) return UL_ERROR;
 +
 +                              uint8_t data[16] = {0x00};
 +                              // read page 0x26-0x29 (last valid ntag203 page)
 +                              status = ul_read(0x26, data, sizeof(data));
 +                              if ( status <= 1 ) {
 +                                      tagtype = UL;
 +                              } else {
 +                                      // read page 0x30 (should error if it is a ntag203)
 +                                      status = ul_read(0x30, data, sizeof(data));
 +                                      if ( status <= 1 ){
 +                                              tagtype = NTAG_203;
 +                                      } else {
 +                                              tagtype = UNKNOWN;
 +                                      }
 +                              }
 +                              ul_switch_off_field();
 +                      }
 +              }
 +      } else {
 +              // Infinition MY-D tests   Exam high nibble 
 +              uint8_t nib = (card.uid[1] & 0xf0) >> 4;
 +              switch ( nib ){
 +                      case 1: tagtype =  MY_D; break;
 +                      case 2: tagtype = (MY_D | MY_D_NFC); break; //notice: we can not currently distinguish between these two
 +                      case 3: tagtype = (MY_D_MOVE | MY_D_MOVE_NFC); break; //notice: we can not currently distinguish between these two
 +              }
 +      }
 +      
 +
 +      tagtype |= ul_magic_test();
 +      if (tagtype == (UNKNOWN | MAGIC)) tagtype = (UL_MAGIC);
 +      return tagtype;
 +}     
 +
 +int CmdHF14AMfUInfo(const char *Cmd){
 +
 +      uint8_t authlim = 0xff;
 +      uint8_t data[16] = {0x00};
 +      iso14a_card_select_t card;
 +      int status;     
 +      bool errors = false;
 +      bool hasAuthKey = false;
 +      bool locked = false;
 +      bool swapEndian = false;
 +      uint8_t cmdp = 0;
 +      uint8_t dataLen = 0;
 +      uint8_t authenticationkey[16] = {0x00}; 
 +      uint8_t *authkeyptr = authenticationkey;
 +      uint8_t *key;
 +      uint8_t pack[4] = {0,0,0,0};
 +      int len = 0;
 +      char tempStr[50];
 +                              
 +      while(param_getchar(Cmd, cmdp) != 0x00)
 +      {
 +              switch(param_getchar(Cmd, cmdp))
 +              {
 +              case 'h':
 +              case 'H':
 +                      return usage_hf_mfu_info();
 +              case 'k':
 +              case 'K':
 +                      dataLen = param_getstr(Cmd, cmdp+1, tempStr);
 +                      if (dataLen == 32 || dataLen == 8) { //ul-c or ev1/ntag key length
 +                              errors = param_gethex(tempStr, 0, authenticationkey, dataLen);
 +                              dataLen /= 2; // handled as bytes from now on
 +                      } else {
 +                              PrintAndLog("\nERROR: Key is incorrect length\n");
 +                      errors = true; 
                        }
                        cmdp += 2;
                        hasAuthKey = true;
  
        //Validations
        if(errors) return usage_hf_mfu_info();
 -
 +      
        TagTypeUL_t tagtype = GetHF14AMfU_Type();
        if (tagtype == UL_ERROR) return -1;
  
        PrintAndLog("\n--- Tag Information ---------");
        PrintAndLog("-------------------------------------------------------------");
        ul_print_type(tagtype, 6);
 -
 +      
        // Swap endianness 
        if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4 );
 -
 +      
        if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
  
        // read pages 0,1,2,3 (should read 4pages)
        status = ul_read(0, data, sizeof(data));
 -      if ( status == -1 ) {
 +      if ( status == -1 ){
                ul_switch_off_field();
                PrintAndLog("Error: tag didn't answer to READ");
                return status;
        } else if (status == 16) {
                ul_print_default(data);
                ndef_print_CC(data+12);
 -      } else {
 +      }       else {
                locked = true;
        }
  
        // UL_C Specific
 -      if ((tagtype & UL_C)) {
 -
 +      if ((tagtype & UL_C)){
 +      
                // read pages 0x28, 0x29, 0x2A, 0x2B
                uint8_t ulc_conf[16] = {0x00};
                status = ul_read(0x28, ulc_conf, sizeof(ulc_conf));
                if (status == 16) ulc_print_configuration(ulc_conf);
                else locked = true;
  
 -              if ((tagtype & MAGIC)) {
 +              if ((tagtype & MAGIC)){
                        //just read key
                        uint8_t ulc_deskey[16] = {0x00};
                        status = ul_read(0x2C, ulc_deskey, sizeof(ulc_deskey));
 -                      if ( status == -1 ) {
 +                      if ( status == -1 ){
                                ul_switch_off_field();
                                PrintAndLog("Error: tag didn't answer to READ magic");
                                return status;
                        ul_switch_off_field();
                        // if we called info with key, just return 
                        if ( hasAuthKey ) return 1;
 -
 +                      
                        // also try to diversify default keys..  look into CmdHF14AMfuGenDiverseKeys
                        PrintAndLog("Trying some default 3des keys");
 -                      for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) {
 +                      for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ){
                                key = default_3des_keys[i];
 -                              if (ulc_authentication(key, true)) {
 +                              if (ulc_authentication(key, true)){
                                        PrintAndLog("Found default 3des key: ");
                                        uint8_t keySwap[16];
                                        memcpy(keySwap, SwapEndian64(key,16,8), 16);
        if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K     ))) {
                uint8_t ulev1_signature[32] = {0x00};
                status = ulev1_readSignature( ulev1_signature, sizeof(ulev1_signature));
 -              if ( status == -1 ) {
 +              if ( status == -1 ){
                        PrintAndLog("Error: tag didn't answer to READ SIGNATURE");
                        ul_switch_off_field();
                        return status;
 -              }
 +              }               
                if (status == 32) ulev1_print_signature( ulev1_signature, sizeof(ulev1_signature));
                else {
                        // re-select
                        if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
                }
        }
 -
 +      
        if ((tagtype & (UL_EV1_48 | UL_EV1_128 | NTAG_210 | NTAG_212 | NTAG_213 | NTAG_215 | NTAG_216 | NTAG_I2C_1K | NTAG_I2C_2K))) {
                uint8_t version[10] = {0x00};
                status  = ulev1_getVersion(version, sizeof(version));
 -              if ( status == -1 ) {
 +              if ( status == -1 ){
                        PrintAndLog("Error: tag didn't answer to GETVERSION");
                        ul_switch_off_field();
                        return status;
                                startconfigblock = UL_MEMORY_ARRAY[idx]-3;
  
                if (startconfigblock){ // if we know where the config block is...
 -                      status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
 -                      if ( status == -1 ) {
 -                              PrintAndLog("Error: tag didn't answer to READ EV1");
 -                              ul_switch_off_field();
 -                              return status;
 -                      } else if (status == 16) {
 -                              // save AUTHENTICATION LIMITS for later:
 -                              authlim = (ulev1_conf[4] & 0x07);
 -                              ulev1_print_configuration(ulev1_conf, startconfigblock);
 +              status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf));
 +              if ( status == -1 ) {
 +                      PrintAndLog("Error: tag didn't answer to READ EV1");
 +                      ul_switch_off_field();
 +                      return status;
 +              } else if (status == 16) {
 +                      // save AUTHENTICATION LIMITS for later:
 +                      authlim = (ulev1_conf[4] & 0x07);
 +                      ulev1_print_configuration(ulev1_conf);
                        }
                }
 -
 +      
                // AUTHLIMIT, (number of failed authentications)
                // 0 = limitless.
                // 1-7 = limit. No automatic tries then.
                if ( !authlim && !hasAuthKey ) {
                        PrintAndLog("\n--- Known EV1/NTAG passwords.");
                        len = 0;
 -                      for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ) {
 +                      for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ){
                                key = default_pwd_pack[i];
 -                              len = ulev1_requestAuthentication(key, pack, sizeof(pack));
 +                                      len = ulev1_requestAuthentication(key, pack, sizeof(pack));
                                if (len >= 1) {
                                        PrintAndLog("Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]);
                                        break;
                                } else {
                                        if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1;
 -                              }
 +                      }
                        }
                        if (len < 1) PrintAndLog("password not known");
                }
  }
  
  //
 -//  Mifare Ultralight Write Single Block
 +//  Write Single Block
  //
  int CmdHF14AMfUWrBl(const char *Cmd){
 -      uint8_t blockNo    = -1;
 -      bool chinese_card  = FALSE;
 -      uint8_t bldata[16] = {0x00};
 -      UsbCommand resp;
  
 -      char cmdp = param_getchar(Cmd, 0);
 -      if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {
 -              PrintAndLog("Usage:  hf mfu wrbl <block number> <block data (8 hex symbols)> [w]");
 -              PrintAndLog("       [block number]");
 -              PrintAndLog("       [block data] - (8 hex symbols)");
 -              PrintAndLog("       [w] - Chinese magic ultralight tag");
 -              PrintAndLog("");
 -              PrintAndLog("        sample: hf mfu wrbl 0 01020304");
 -              PrintAndLog("");                
 -              return 0;
 -      }       
 -      
 -      blockNo = param_get8(Cmd, 0);
 +      int blockNo = -1;       
 +      bool errors = false;
 +      bool hasAuthKey = false;
 +      bool hasPwdKey = false;
 +      bool swapEndian = false;
  
 -      if (blockNo > MAX_UL_BLOCKS){
 -              PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight Cards!");
 -              return 1;
 -      }
 +      uint8_t cmdp = 0;
 +      uint8_t keylen = 0;
 +      uint8_t blockdata[20] = {0x00};
 +      uint8_t data[16] = {0x00};
 +      uint8_t authenticationkey[16] = {0x00};
 +      uint8_t *authkeyptr = authenticationkey;
        
 -      if (param_gethex(Cmd, 1, bldata, 8)) {
 -              PrintAndLog("Block data must include 8 HEX symbols");
 -              return 1;
 +      // starting with getting tagtype
 +      TagTypeUL_t tagtype = GetHF14AMfU_Type();
 +      if (tagtype == UL_ERROR) return -1;
 +      
 +      while(param_getchar(Cmd, cmdp) != 0x00)
 +      {
 +              switch(param_getchar(Cmd, cmdp))
 +              {
 +                      case 'h':
 +                      case 'H':
 +                              return usage_hf_mfu_wrbl();
 +                      case 'k':
 +                      case 'K':
 +                              // EV1/NTAG size key
 +                              keylen = param_gethex(Cmd, cmdp+1, data, 8);
 +                              if ( !keylen ) {
 +                                      memcpy(authenticationkey, data, 4);
 +                                      cmdp += 2;
 +                                      hasPwdKey = true;
 +                                      break;
 +                              }
 +                              // UL-C size key        
 +                              keylen = param_gethex(Cmd, cmdp+1, data, 32);
 +                              if (!keylen){
 +                                      memcpy(authenticationkey, data, 16);
 +                                      cmdp += 2;
 +                                      hasAuthKey = true;
 +                                      break;
 +                              }
 +                              PrintAndLog("\nERROR: Key is incorrect length\n");
 +                              errors = true; 
 +                              break;
 +                      case 'b':
 +                      case 'B':
 +                              blockNo = param_get8(Cmd, cmdp+1);
 +                              
 +                              uint8_t maxblockno = 0;
 +                              for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){
 +                                      if (tagtype & UL_TYPES_ARRAY[idx])
 +                                              maxblockno = UL_MEMORY_ARRAY[idx]+1;
 +                              }
 +              
 +                              if (blockNo < 0) {
 +                                      PrintAndLog("Wrong block number");
 +                                      errors = true;                                  
 +                              }
 +                              if (blockNo > maxblockno){
 +                                      PrintAndLog("block number to large. Max block is %u/0x%02X \n", maxblockno,maxblockno);
 +                                      errors = true;                                                                  
 +                              }
 +                              cmdp += 2;
 +                              break;
 +                      case 'l':
 +                      case 'L':
 +                              swapEndian = true;
 +                              cmdp++; 
 +                              break;
 +                      case 'd':
 +                      case 'D':
 +                              if ( param_gethex(Cmd, cmdp+1, blockdata, 8) ) {
 +                                      PrintAndLog("Block data must include 8 HEX symbols");
 +                                      errors = true;
 +                                      break;
 +                              }
 +                              cmdp += 2;
 +                              break;
 +                      default:
 +                              PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
 +                              errors = true;
 +                              break;
 +              }
 +              //Validations
 +              if(errors) return usage_hf_mfu_wrbl();
        }
 +
 +      if ( blockNo == -1 ) return usage_hf_mfu_wrbl();
 +      
 +      // Swap endianness 
 +      if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, 16, 8);
 +      if (swapEndian && hasPwdKey)  authkeyptr = SwapEndian64(authenticationkey, 4, 4);
 +
 +
 +      if ( blockNo <= 3)              
 +              PrintAndLog("Special Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
 +      else
 +              PrintAndLog("Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4));
 +      
        
 -      if (strchr(Cmd,'w') != 0  || strchr(Cmd,'W') != 0 ) {
 -              chinese_card = TRUE; 
 +
 +      //Send write Block
 +      UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}};
 +      memcpy(c.d.asBytes,blockdata,4);
 +
 +      if ( hasAuthKey ){
 +              c.arg[1] = 1;
 +              memcpy(c.d.asBytes+4,authkeyptr,16);
 +      }
 +      else if ( hasPwdKey ) {
 +              c.arg[1] = 2;
 +              memcpy(c.d.asBytes+4,authkeyptr,4);
        }
        
 -      if ( blockNo <= 3) {
 -              if (!chinese_card){
 -                      PrintAndLog("Access Denied");
 -              } else {
 -                      PrintAndLog("--specialblock no:%02x", blockNo);
 -                      PrintAndLog("--data: %s", sprint_hex(bldata, 4));
 -                      UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
 -                      memcpy(d.d.asBytes,bldata, 4);
 -                      SendCommand(&d);
 -                      if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 -                              uint8_t isOK  = resp.arg[0] & 0xff;
 -                              PrintAndLog("isOk:%02x", isOK);
 -                      } else {
 -                              PrintAndLog("Command execute timeout");
 -                      }  
 -              }
 +      SendCommand(&c);
 +      UsbCommand resp;
 +      if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 +              uint8_t isOK  = resp.arg[0] & 0xff;
 +              PrintAndLog("isOk:%02x", isOK);
        } else {
 -              PrintAndLog("--block no:%02x", blockNo);
 -              PrintAndLog("--data: %s", sprint_hex(bldata, 4));               
 -              UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
 -              memcpy(e.d.asBytes,bldata, 4);
 -              SendCommand(&e);
 -              if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 -                      uint8_t isOK  = resp.arg[0] & 0xff;
 -                      PrintAndLog("isOk:%02x", isOK);
 -              } else {
 -                      PrintAndLog("Command execute timeout");
 -              }
 +              PrintAndLog("Command execute timeout");
        }
 +      
        return 0;
  }
 -
  //
 -//  Mifare Ultralight Read Single Block
 +//  Read Single Block
  //
  int CmdHF14AMfURdBl(const char *Cmd){
  
 -      UsbCommand resp;
 -      uint8_t blockNo = -1;   
 -      char cmdp = param_getchar(Cmd, 0);
 +      int blockNo = -1;       
 +      bool errors = false;
 +      bool hasAuthKey = false;
 +      bool hasPwdKey = false;
 +      bool swapEndian = false;
 +      uint8_t cmdp = 0;
 +      uint8_t keylen = 0;
 +      uint8_t data[16] = {0x00};
 +      uint8_t authenticationkey[16] = {0x00};
 +      uint8_t *authkeyptr = authenticationkey;
 +              
 +      // starting with getting tagtype
 +      TagTypeUL_t tagtype = GetHF14AMfU_Type();
 +      if (tagtype == UL_ERROR) return -1;
        
 -      if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {    
 -              PrintAndLog("Usage:  hf mfu rdbl <block number>");
 -              PrintAndLog("        sample: hfu mfu rdbl 0");
 -              return 0;
 -      }
 -
 -      blockNo = param_get8(Cmd, 0);
 -
 -      if (blockNo > MAX_UL_BLOCKS){
 -              PrintAndLog("Error: Maximum number of blocks is 15 for Ultralight");
 -              return 1;
 +      while(param_getchar(Cmd, cmdp) != 0x00)
 +      {
 +              switch(param_getchar(Cmd, cmdp))
 +              {
 +                      case 'h':
 +                      case 'H':
 +                              return usage_hf_mfu_rdbl();
 +                      case 'k':
 +                      case 'K':
 +                              // EV1/NTAG size key
 +                              keylen = param_gethex(Cmd, cmdp+1, data, 8);
 +                              if ( !keylen ) {
 +                                      memcpy(authenticationkey, data, 4);
 +                                      cmdp += 2;
 +                                      hasPwdKey = true;
 +                                      break;
 +                              }
 +                              // UL-C size key        
 +                              keylen = param_gethex(Cmd, cmdp+1, data, 32);
 +                              if (!keylen){
 +                                      memcpy(authenticationkey, data, 16);
 +                                      cmdp += 2;
 +                                      hasAuthKey = true;
 +                                      break;
 +                              }
 +                              PrintAndLog("\nERROR: Key is incorrect length\n");
 +                              errors = true; 
 +                              break;
 +                      case 'b':
 +                      case 'B':
 +                              blockNo = param_get8(Cmd, cmdp+1);
 +                              
 +                              uint8_t maxblockno = 0;
 +                              for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++){
 +                                      if (tagtype & UL_TYPES_ARRAY[idx])
 +                                              maxblockno = UL_MEMORY_ARRAY[idx]+1;
 +                              }
 +              
 +                              if (blockNo < 0) {
 +                                      PrintAndLog("Wrong block number");
 +                                      errors = true;                                  
 +                              }
 +                              if (blockNo > maxblockno){
 +                                      PrintAndLog("block number to large. Max block is %u/0x%02X \n", maxblockno,maxblockno);
 +                                      errors = true;                                                                  
 +                              }
 +                              cmdp += 2;
 +                              break;
 +                      case 'l':
 +                      case 'L':
 +                              swapEndian = true;
 +                              cmdp++; 
 +                              break;                          
 +                      default:
 +                              PrintAndLog("Unknown parameter '%c'", param_getchar(Cmd, cmdp));
 +                              errors = true;
 +                              break;
 +              }
 +              //Validations
 +              if(errors) return usage_hf_mfu_rdbl();
        }
--
 +      if ( blockNo == -1 ) return usage_hf_mfu_rdbl();
 +      
 +      // Swap endianness 
 +      if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, 16, 8);
 +      if (swapEndian && hasPwdKey)  authkeyptr = SwapEndian64(authenticationkey, 4, 4);
 +      
 +      //Read Block
        UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
 +      if ( hasAuthKey ){
 +              c.arg[1] = 1;
 +              memcpy(c.d.asBytes,authkeyptr,16);
 +      }
 +      else if ( hasPwdKey ) {
 +              c.arg[1] = 2;
 +              memcpy(c.d.asBytes,authkeyptr,4);
 +      }
 +      
        SendCommand(&c);
-       UsbCommand resp;
 -
        if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
                uint8_t isOK = resp.arg[0] & 0xff;
                if (isOK) {
                        uint8_t *data = resp.d.asBytes;
 -                      PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4));
 +                      PrintAndLog("Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(data, 4));
                }
                else {
                        PrintAndLog("Failed reading block: (%02x)", isOK);
        } else {
                PrintAndLog("Command execute time-out");
        }
        return 0;
  }
  
@@@ -1124,44 -988,14 +1606,44 @@@ int usage_hf_mfu_dump(void) 
        return 0;
  }
  
 +int usage_hf_mfu_rdbl(void) {
 +      PrintAndLog("Read a block and print. It autodetects card type.\n");     
 +      PrintAndLog("Usage:  hf mfu rdbl b <block number> k <key> l\n");
 +      PrintAndLog("  Options:");
 +      PrintAndLog("  b <no>  : block to read");
 +      PrintAndLog("  k <key> : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
 +      PrintAndLog("  l       : (optional) swap entered key's endianness");    
 +      PrintAndLog("");
 +      PrintAndLog("   sample : hf mfu rdbl b 0");
 +      PrintAndLog("          : hf mfu rdbl b 0 k 00112233445566778899AABBCCDDEEFF");
 +      PrintAndLog("          : hf mfu rdbl b 0 k AABBCCDDD\n");
 +      return 0;
 +}
 +
 +int usage_hf_mfu_wrbl(void) {
 +      PrintAndLog("Write a block. It autodetects card type.\n");              
 +      PrintAndLog("Usage:  hf mfu wrbl b <block number> d <data> k <key> l\n");
 +      PrintAndLog("  Options:");      
 +      PrintAndLog("  b <no>   : block to write");
 +      PrintAndLog("  d <data> : block data - (8 hex symbols)");
 +      PrintAndLog("  k <key>  : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]");
 +      PrintAndLog("  l        : (optional) swap entered key's endianness");   
 +      PrintAndLog("");
 +      PrintAndLog("    sample : hf mfu wrbl b 0 d 01234567");
 +      PrintAndLog("           : hf mfu wrbl b 0 d 01234567 k AABBCCDDD\n");
 +      return 0;
 +}
 +
  //
  //  Mifare Ultralight / Ultralight-C / Ultralight-EV1
  //  Read and Dump Card Contents,  using auto detection of tag size.
 +//
 +//  TODO: take a password to read UL-C / UL-EV1 tags.
  int CmdHF14AMfUDump(const char *Cmd){
  
        FILE *fout;
        char filename[FILE_PATH_SIZE] = {0x00};
-       char * fnameptr = filename;
+       char *fnameptr = filename;
        uint8_t *lockbytes_t = NULL;
        uint8_t lockbytes[2] = {0x00};
        uint8_t *lockbytes_t2 = NULL;
        int i = 0;
        int Pages = 16;
        bool tmplockbit = false;
-       uint8_t dataLen=0;
-       uint8_t cmdp =0;
+       uint8_t dataLen = 0;
+       uint8_t cmdp = 0;
        uint8_t authenticationkey[16] = {0x00};
-       uint8_t *authKeyPtr = authenticationkey;
+       uint8_t *authKeyPtr = authenticationkey;
        size_t fileNlen = 0;
        bool errors = false;
        bool swapEndian = false;
  
        //Validations
        if(errors) return usage_hf_mfu_dump();
-       
        if (swapEndian && hasAuthKey) 
                authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4);
  
        TagTypeUL_t tagtype = GetHF14AMfU_Type();
        if (tagtype == UL_ERROR) return -1;
-       
        if (!manualPages)
                for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++)
                        if (tagtype & UL_TYPES_ARRAY[idx])
        ul_print_type(tagtype, 0);
        PrintAndLog("Reading tag memory...");
        UsbCommand c = {CMD_MIFAREU_READCARD, {startPage,Pages}};
-       if ( hasAuthKey ) { 
+       if ( hasAuthKey ) {
                if (tagtype & UL_C)
                        c.arg[2] = 1; //UL_C auth
                else
        }
        SendCommand(&c);
        UsbCommand resp;
-       if (!WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
+       if (!WaitForResponseTimeout(CMD_ACK, &resp,1500)) {
                PrintAndLog("Command execute time-out");
                return 1;
        }
        Pages = bufferSize/4;
        // Load lock bytes.
        int j = 0;
-       
        lockbytes_t = data + 8;
        lockbytes[0] = lockbytes_t[2];
        lockbytes[1] = lockbytes_t[3];
        for(j = 0; j < 16; j++){
                bit[j] = lockbytes[j/8] & ( 1 <<(7-j%8));
-       }               
-       
+       }
        // Load bottom lockbytes if available
        // TODO -- FIGURE OUT LOCK BYTES FOR TO EV1 and/or NTAG
        if ( Pages == 44 ) {
  
        // add keys to block dump
        if (hasAuthKey) {
-               if (!swapEndian) {
+               if (!swapEndian){
                        authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4);
-                       memcpy(data + Pages*4, authKeyPtr, dataLen);
                } else {
-                       memcpy(data + Pages*4, authenticationkey, dataLen);
+                       authKeyPtr = authenticationkey;
+               }
+               if (tagtype & UL_C){ //add 4 pages
+                       memcpy(data + Pages*4, authKeyPtr, dataLen);
+                       Pages += dataLen/4;  
+               } else { // 2nd page from end
+                       memcpy(data + (Pages*4) - 8, authenticationkey, dataLen);
                }
-               Pages += dataLen/4;  //not sure output is in correct location for all tag types.
        }
-       
        for (i = 0; i < Pages; ++i) {
                if ( i < 3 ) {
                        PrintAndLog("Block %02x:%s ", i,sprint_hex(data + i * 4, 4));
                }
                switch(i){
                        case 3: tmplockbit = bit[4]; break;
 -                      case 4: tmplockbit = bit[3]; break;
 -                      case 5: tmplockbit = bit[2]; break;
 -                      case 6: tmplockbit = bit[1]; break;
 -                      case 7: tmplockbit = bit[0]; break;
 -                      case 8: tmplockbit = bit[15]; break;
 +                      case 4: tmplockbit = bit[3]; break;
 +                      case 5: tmplockbit = bit[2]; break;
 +                      case 6: tmplockbit = bit[1]; break;
 +                      case 7: tmplockbit = bit[0]; break;
 +                      case 8: tmplockbit = bit[15]; break;
                        case 9: tmplockbit = bit[14]; break;
                        case 10: tmplockbit = bit[13]; break;
                        case 11: tmplockbit = bit[12]; break;
                        case 24:
                        case 25:
                        case 26:
-                       case 27: tmplockbit = bit2[4]; break;               
+                       case 27: tmplockbit = bit2[4]; break;
                        case 28:
                        case 29:
                        case 30:
                        case 43: tmplockbit = bit2[9]; break;  //auth1
                        default: break;
                }
-               PrintAndLog("Block %02x:%s [%d] {%.4s}", i, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4);
-       }  
-       
+               PrintAndLog("Block %02X:%s [%d] {%.4s}", i, sprint_hex(data + i * 4, 4), tmplockbit, data+i*4);
+       }
        // user supplied filename?
        if (fileNlen < 1) {
                // UID = data 0-1-2 4-5-6-7  (skips a beat)
                sprintf(fnameptr,"%02X%02X%02X%02X%02X%02X%02X.bin",
-                       data[0], data[1], data[2], data[4], data[5], data[6], data[7]);
+                       data[0],data[1], data[2], data[4],data[5],data[6], data[7]);
        } else {
                sprintf(fnameptr + fileNlen,".bin");
        }
  
        if ((fout = fopen(filename,"wb")) == NULL) { 
                PrintAndLog("Could not create file name %s", filename);
-               return 1;       
+               return 1;
        }
        fwrite( data, 1, Pages*4, fout );
        fclose(fout);
  //
  int CmdHF14AMfucAuth(const char *Cmd){
  
-       uint8_t keyNo = 0;
+       uint8_t keyNo = 3;
        bool errors = false;
  
        char cmdp = param_getchar(Cmd, 0);
                PrintAndLog("Authentication successful. 3des key: %s",sprint_hex(key, 16));
        else
                PrintAndLog("Authentication failed");
-                       
+               
        return 0;
  }
  
@@@ -1529,15 -1368,151 +2016,16 @@@ int CmdTestDES(const char * cmd
  }
  **/
  
 -//
 -// Ultralight C Read Single Block
 -//
 -int CmdHF14AMfUCRdBl(const char *Cmd)
 -{
 -      UsbCommand resp;
 -      bool hasPwd = FALSE;
 -      uint8_t blockNo = -1;
 -      uint8_t key[16];
 -      char cmdp = param_getchar(Cmd, 0);
 -
 -      if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') {
 -              PrintAndLog("Usage:  hf mfu crdbl  <block number> <key>");
 -              PrintAndLog("");
 -              PrintAndLog("sample: hf mfu crdbl 0");
 -              PrintAndLog("        hf mfu crdbl 0 00112233445566778899AABBCCDDEEFF");
 -              return 0;
 -      }
 -
 -      blockNo = param_get8(Cmd, 0);
 -      if (blockNo < 0) {
 -              PrintAndLog("Wrong block number");
 -              return 1;
 -      }
 -
 -      if (blockNo > MAX_ULC_BLOCKS ){
 -              PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C");
 -              return 1;
 -      } 
 -      
 -      // key
 -      if ( strlen(Cmd) > 3){
 -              if (param_gethex(Cmd, 1, key, 32)) {
 -                      PrintAndLog("Key must include %d HEX symbols", 32);
 -                      return 1;
 -              } else {
 -                      hasPwd = TRUE;
 -              }       
 -      }       
 -
 -      //Read Block
 -      UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}};
 -      if ( hasPwd ) {
 -              c.arg[1] = 1;
 -              memcpy(c.d.asBytes,key,16);
 -      }
 -      SendCommand(&c);
 -
 -      if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 -              uint8_t isOK = resp.arg[0] & 0xff;
 -              if (isOK) {
 -                      uint8_t *data = resp.d.asBytes;
 -                      PrintAndLog("Block: %0d (0x%02X) [ %s]", (int)blockNo, blockNo, sprint_hex(data, 4));
 -              }
 -              else {
 -                      PrintAndLog("Failed reading block: (%02x)", isOK);
 -              }
 -      } else {
 -              PrintAndLog("Command execute time-out");
 -      }
 -      return 0;
 -}
 -
 -//
 -//  Mifare Ultralight C Write Single Block
 -//
 -int CmdHF14AMfUCWrBl(const char *Cmd){
 -      
 -      uint8_t blockNo = -1;
 -      bool chinese_card = FALSE;
 -      uint8_t bldata[16] = {0x00};
 -      UsbCommand resp;
 -
 -      char cmdp = param_getchar(Cmd, 0);
 -      
 -      if (strlen(Cmd) < 3 || cmdp == 'h' || cmdp == 'H') {    
 -              PrintAndLog("Usage:  hf mfu cwrbl <block number> <block data (8 hex symbols)> [w]");
 -              PrintAndLog("       [block number]");
 -              PrintAndLog("       [block data] - (8 hex symbols)");
 -              PrintAndLog("       [w] - Chinese magic ultralight tag");
 -              PrintAndLog("");
 -              PrintAndLog("        sample: hf mfu cwrbl 0 01020304");
 -              PrintAndLog("");
 -              return 0;
 -      }
 -      
 -      blockNo = param_get8(Cmd, 0);
 -      if (blockNo > MAX_ULC_BLOCKS ){
 -              PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C Cards!");
 -              return 1;
 -      }
 -      
 -      if (param_gethex(Cmd, 1, bldata, 8)) {
 -              PrintAndLog("Block data must include 8 HEX symbols");
 -              return 1;
 -      }
 -
 -      if (strchr(Cmd,'w') != 0  || strchr(Cmd,'W') != 0 ) {
 -              chinese_card = TRUE; 
 -      }
 -
 -      if ( blockNo <= 3 ) {
 -              if (!chinese_card){
 -                      PrintAndLog("Access Denied");  
 -                      return 1;
 -              } else {
 -                      PrintAndLog("--Special block no: 0x%02x", blockNo);
 -                      PrintAndLog("--Data: %s", sprint_hex(bldata, 4));
 -                      UsbCommand d = {CMD_MIFAREU_WRITEBL, {blockNo}};
 -                      memcpy(d.d.asBytes,bldata, 4);
 -                      SendCommand(&d);
 -                      if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 -                              uint8_t isOK  = resp.arg[0] & 0xff;
 -                              PrintAndLog("isOk:%02x", isOK);
 -                      } else {
 -                              PrintAndLog("Command execute timeout");
 -                              return 1;
 -                      }
 -              }
 -      } else {
 -                      PrintAndLog("--Block no : 0x%02x", blockNo);
 -                      PrintAndLog("--Data: %s", sprint_hex(bldata, 4));               
 -                      UsbCommand e = {CMD_MIFAREU_WRITEBL, {blockNo}};
 -                      memcpy(e.d.asBytes,bldata, 4);
 -                      SendCommand(&e);
 -                      if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
 -                              uint8_t isOK  = resp.arg[0] & 0xff;
 -                              PrintAndLog("isOk : %02x", isOK);
 -                      } else {
 -                              PrintAndLog("Command execute timeout");
 -                              return 1;
 -                      }
 -      }
 -      return 0;
 -}
 -
  // 
  // Mifare Ultralight C - Set password
  //
  int CmdHF14AMfucSetPwd(const char *Cmd){
  
 -      uint8_t pwd[16] = {0x00};
 +      uint8_t pwd[16] = {0x00};       
        
++      uint8_t key[16];
        char cmdp = param_getchar(Cmd, 0);
--      
++
        if (strlen(Cmd) == 0  || cmdp == 'h' || cmdp == 'H') {  
                PrintAndLog("Usage:  hf mfu setpwd <password (32 hex symbols)>");
                PrintAndLog("       [password] - (32 hex symbols)");
                PrintAndLog("Password must include 32 HEX symbols");
                return 1;
        }
++
++      if (blockNo > MAX_ULC_BLOCKS ){
++              PrintAndLog("Error: Maximum number of blocks is 47 for Ultralight-C");
++              return 1;
++      } 
        
        UsbCommand c = {CMD_MIFAREUC_SETPWD};   
        memcpy( c.d.asBytes, pwd, 16);
@@@ -1607,7 -1582,7 +2100,7 @@@ int CmdHF14AMfucSetUid(const char *Cmd)
                PrintAndLog("Command execute timeout");
                return 2;
        }
--      
++
        // save old block2.
        uint8_t oldblock2[4] = {0x00};
        memcpy(resp.d.asBytes, oldblock2, 4);
                PrintAndLog("Command execute timeout");
                return 3;
        }
--      
++
        // block 1.
        c.arg[0] = 1;
        c.d.asBytes[0] = uid[3];
@@@ -1760,8 -1735,10 +2253,8 @@@ static command_t CommandTable[] 
        {"dbg",         CmdHF14AMfDbg,          0, "Set default debug mode"},
        {"info",        CmdHF14AMfUInfo,        0, "Tag information"},
        {"dump",        CmdHF14AMfUDump,        0, "Dump Ultralight / Ultralight-C tag to binary file"},
 -      {"rdbl",        CmdHF14AMfURdBl,        0, "Read block  - Ultralight"},
 -      {"wrbl",        CmdHF14AMfUWrBl,        0, "Write block - Ultralight"},    
 -      {"crdbl",       CmdHF14AMfUCRdBl,       0, "Read block        - Ultralight C"},
 -      {"cwrbl",       CmdHF14AMfUCWrBl,       0, "Write block       - Ultralight C"},
 +      {"rdbl",        CmdHF14AMfURdBl,        0, "Read block"},
 +      {"wrbl",        CmdHF14AMfUWrBl,        0, "Write block"},    
        {"cauth",       CmdHF14AMfucAuth,       0, "Authentication    - Ultralight C"},
        {"setpwd",      CmdHF14AMfucSetPwd, 1, "Set 3des password - Ultralight-C"},
        {"setuid",      CmdHF14AMfucSetUid, 1, "Set UID - MAGIC tags only"},
diff --combined client/cmdhfmfu.h
index d4d3070a472c76d29dd1d9722b4befd9b306ac86,83f2840316c06d111597a80ce09a632fe1b7a21c..4ec48ff9dfbcb07c9d7768c3a589c20f2a8b7163
@@@ -4,24 -4,25 +4,24 @@@
  #ifndef CMDHFMFU_H__
  #define CMDHFMFU_H__
  
 -//standard ultralight
  int CmdHF14AMfUWrBl(const char *Cmd);
  int CmdHF14AMfURdBl(const char *Cmd);
  
  //Crypto Cards
 -int CmdHF14AMfUCRdBl(const char *Cmd);
 -int CmdHF14AMfUCRdCard(const char *Cmd);
  int CmdHF14AMfucAuth(const char *Cmd);
  
  //general stuff
  int CmdHF14AMfUDump(const char *Cmd);
  int CmdHF14AMfUInfo(const char *Cmd);
 -uint32_t GetHF14AMfU_Type(void);
  
 +uint32_t GetHF14AMfU_Type(void);
  int ul_print_type(uint32_t tagtype, uint8_t spacer);
  void ul_switch_off_field(void);
  
  int usage_hf_mfu_dump(void);
  int usage_hf_mfu_info(void);
 +int usage_hf_mfu_rdbl(void);
 +int usage_hf_mfu_wrbl(void);
  
  int CmdHFMFUltra(const char *Cmd);
  
@@@ -32,9 -33,9 +32,9 @@@ typedef enum TAGTYPE_UL 
        UL_EV1_48     = 0x000004,
        UL_EV1_128    = 0x000008,
        NTAG          = 0x000010,
-       NTAG_203          = 0x000020,
-       NTAG_210          = 0x000040,
-       NTAG_212          = 0x000080,
+       NTAG_203      = 0x000020,
+       NTAG_210      = 0x000040,
+       NTAG_212      = 0x000080,
        NTAG_213      = 0x000100,
        NTAG_215      = 0x000200,
        NTAG_216      = 0x000400,
@@@ -42,8 -43,8 +42,8 @@@
        MY_D_NFC      = 0x001000,
        MY_D_MOVE     = 0x002000,
        MY_D_MOVE_NFC = 0x004000,
-       NTAG_I2C_1K       = 0x008000,
-       NTAG_I2C_2K       = 0x010000,
+       NTAG_I2C_1K   = 0x008000,
+       NTAG_I2C_2K   = 0x010000,
        MAGIC         = 0x020000,
        UL_MAGIC      = UL | MAGIC,
        UL_C_MAGIC    = UL_C | MAGIC,
index bd8e6d0cc20ea2942ba2b370c9907e01ea02b570,566128f7dde5324f5db084fc8d008517cb958365..1709606385ccfbb4c92c30e4be84ffaa0be42d26
@@@ -192,9 -192,7 +192,9 @@@ en
  return {
        convert_bin_to_html = convert_bin_to_html,
        convert_eml_to_html = convert_eml_to_html,
-     convert_eml_to_bin = convert_eml_to_bin,
+       convert_eml_to_bin = convert_eml_to_bin,
 -      SaveAsBinary = save_BIN,
 +    SaveAsBinary = save_BIN,
 +      SaveAsText = save_TEXT,
 +    SaveAsBinary = save_BIN,
        SaveAsText = save_TEXT,
  }
index 1d7441c7fee996bc34ba9b783b8713b8efacbc54,1015e27a74b2a866078cb0ca350113081bd95baa..13c4c063af078fb4d155b7f227d26eda6b8fa9c9
@@@ -1,21 -1,21 +1,21 @@@
  /*  crapto1.c\r
  \r
 -      This program is free software; you can redistribute it and/or\r
 -      modify it under the terms of the GNU General Public License\r
 -      as published by the Free Software Foundation; either version 2\r
 -      of the License, or (at your option) any later version.\r
 -\r
 -      This program is distributed in the hope that it will be useful,\r
 -      but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 -      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 -      GNU General Public License for more details.\r
 -\r
 -      You should have received a copy of the GNU General Public License\r
 -      along with this program; if not, write to the Free Software\r
 -      Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
 -      Boston, MA  02110-1301, US$\r
 -\r
 -      Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
 +    This program is free software; you can redistribute it and/or\r
 +    modify it under the terms of the GNU General Public License\r
 +    as published by the Free Software Foundation; either version 2\r
 +    of the License, or (at your option) any later version.\r
 +\r
 +    This program is distributed in the hope that it will be useful,\r
 +    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
 +    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
 +    GNU General Public License for more details.\r
 +\r
 +    You should have received a copy of the GNU General Public License\r
 +    along with this program; if not, write to the Free Software\r
 +    Foundation, Inc., 51 Franklin Street, Fifth Floor,\r
 +    Boston, MA  02110-1301, US$\r
 +\r
 +    Copyright (C) 2008-2008 bla <blapost@gmail.com>\r
  */\r
  #include "crapto1.h"\r
  #include <stdlib.h>\r
@@@ -24,9 -24,9 +24,9 @@@
  static uint8_t filterlut[1 << 20];\r
  static void __attribute__((constructor)) fill_lut()\r
  {\r
 -              uint32_t i;\r
 -              for(i = 0; i < 1 << 20; ++i)\r
 -                              filterlut[i] = filter(i);\r
 +        uint32_t i;\r
 +        for(i = 0; i < 1 << 20; ++i)\r
 +                filterlut[i] = filter(i);\r
  }\r
  #define filter(x) (filterlut[(x) & 0xfffff])\r
  #endif\r
@@@ -147,7 -147,7 +147,7 @@@ extend_table(uint32_t *tbl, uint32_t **
                        *p ^= in;\r
                } else {                                                                                // drop\r
                        *p-- = *(*end)--;\r
 -              }\r
 +      }\r
        }\r
  \r
  }\r
@@@ -209,7 -209,7 +209,7 @@@ recover(uint32_t *o_head, uint32_t *o_t
  \r
        for (int i = bucket_info.numbuckets - 1; i >= 0; i--) {\r
                sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks,\r
 -                                       bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks,\r
 +                                   bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks,\r
                                         rem, sl, in, bucket);\r
        }\r
  \r
@@@ -251,7 -251,7 +251,6 @@@ struct Crypto1State* lfsr_recovery32(ui
                        }\r
                }\r
  \r
--\r
        // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream\r
        for(i = 1 << 20; i >= 0; --i) {\r
                if(filter(i) == (oks & 1))\r
  \r
        in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00);            // Byte swapping\r
  \r
--      recover(odd_head, odd_tail, oks,\r
--              even_head, even_tail, eks, 11, statelist, in << 1, bucket);\r
--\r
++      recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket);\r
  \r
  out:\r
        free(odd_head);\r
@@@ -484,7 -484,7 +481,7 @@@ uint32_t *lfsr_prefix_ks(uint8_t ks[8]
   */\r
  static struct Crypto1State*\r
  brute_top(uint32_t prefix, uint32_t rresp, unsigned char parities[8][8],\r
 -                uint32_t odd, uint32_t even, struct Crypto1State* sl, uint8_t no_chk)\r
 +          uint32_t odd, uint32_t even, struct Crypto1State* sl, uint8_t no_chk)\r
  {\r
        struct Crypto1State s;\r
        uint32_t ks1, nr, ks2, rr, ks3, good, c;\r
   * It returns a zero terminated list of possible cipher states after the\r
   * tag nonce was fed in\r
   */\r
--struct Crypto1State*\r
--lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint8_t no_par)\r
++struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint8_t no_par)\r
  {\r
        struct Crypto1State *statelist, *s;\r
        uint32_t *odd, *even, *o, *e, top;\r
        statelist = malloc((sizeof *statelist) << 21);  //how large should be?\r
        if(!statelist || !odd || !even)\r
        {\r
--                              free(statelist);\r
--                              free(odd);\r
--                              free(even);\r
--                              return 0;\r
++              free(statelist);\r
++              free(odd);\r
++              free(even);\r
++              return 0;\r
        }\r
  \r
        s = statelist;\r
  \r
        return statelist;\r
  }\r
++\r
++/*\r
++struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint8_t no_par, uint32_t nt, uint32_t uid)\r
++{\r
++    long long int amount = 0;\r
++    struct Crypto1State *statelist, *s;\r
++    uint32_t *odd, *even, *o, *e, top;\r
++\r
++    odd = lfsr_prefix_ks(ks, 1);\r
++    even = lfsr_prefix_ks(ks, 0);\r
++\r
++    s = statelist = malloc((sizeof *statelist) << 20);\r
++    if(!s || !odd || !even) {\r
++              free(odd);\r
++              free(even);\r
++              free(statelist);\r
++              return 0;\r
++    }\r
++\r
++    char filename[50] = "archivo.txt";\r
++    sprintf(filename, "logs/%x.txt", nt);\r
++    PrintAndLog("Name: %s\n", filename);\r
++    FILE *file = fopen(filename,"w+");\r
++      if ( !file ) {\r
++              s->odd = s->even = 0;\r
++              free(odd);\r
++              free(even);\r
++              PrintAndLog("Failed to create file");\r
++              return 0;\r
++      }\r
++    PrintAndLog("Creating file... ");\r
++      uint32_t xored = uid^nt;\r
++      \r
++    int lastOdd = 0;\r
++    for(o = odd; *o + 1; ++o)\r
++        for(e = even; *e + 1; ++e)\r
++            for(top = 0; top < 64; ++top) {\r
++                *o += 1 << 21;\r
++                *e += (!(top & 7) + 1) << 21;\r
++\r
++                //added by MG\r
++                if(lastOdd != statelist->odd){\r
++                                      // Here I create a temporal crypto1 state, \r
++                                      // where I load the odd and even state and work with it,\r
++                                      // in order not to interfere with regular mechanism, This is what I save to file\r
++                                      struct Crypto1State *state;\r
++                    lastOdd = state->odd = statelist->odd; state->even = statelist->even;\r
++                    lfsr_rollback_word(state,xored,0);\r
++                    fprintf(file,"%x %x \n",state->odd,state->even);\r
++                    amount++;\r
++                }\r
++                //s = check_pfx_parity(pfx, rr, par, *o, *e, s); //This is not useful at all when attacking chineese cards\r
++                              s = brute_top(pfx, rr, par, *o, *e, s, no_par); \r
++            }\r
++\r
++      PrintAndLog("File created, amount %u\n",amount);\r
++      fclose(file);\r
++      s->odd = s->even = 0;\r
++      free(odd);\r
++      free(even);\r
++    return statelist;\r
++}\r
++ */\r
diff --combined client/scripting.c
index 880b7cb2ffecea9741fad613a3f64d3cae380496,152fd9d44335236ffe3def9237d3bb38eccb68b3..9e643932c1b59e148dfeaf882a0a18d2b2f8202e
   */
  static int l_SendCommand(lua_State *L){
  
 -      /*
 -       *
 -       The SendCommand (native) expects the following structure:
 -
 -       typedef struct {
 -        uint64_t cmd; //8 bytes
 -        uint64_t arg[3]; // 8*3 bytes = 24 bytes
 -        union {
 -              uint8_t  asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR)
 -              uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes
 -        } d;
 -      } PACKED UsbCommand;
 -
 -      ==> A 544 byte buffer will do.
 -      **/
 -      //Pop cmd
 -      size_t size;
 -      const char *data = luaL_checklstring(L, 1, &size);
 -      if(size != sizeof(UsbCommand))
 -      {
 -              printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand));
 -              lua_pushstring(L,"Wrong data size");
 -              return 1;
 -      }
 +    /*
 +     *
 +     The SendCommand (native) expects the following structure:
 +
 +     typedef struct {
 +      uint64_t cmd; //8 bytes
 +      uint64_t arg[3]; // 8*3 bytes = 24 bytes
 +      union {
 +        uint8_t  asBytes[USB_CMD_DATA_SIZE]; // 1 byte * 512 = 512 bytes (OR)
 +        uint32_t asDwords[USB_CMD_DATA_SIZE/4]; // 4 byte * 128 = 512 bytes
 +      } d;
 +    } PACKED UsbCommand;
 +
 +    ==> A 544 byte buffer will do.
 +    **/
 +    //Pop cmd
 +    size_t size;
 +    const char *data = luaL_checklstring(L, 1, &size);
 +    if(size != sizeof(UsbCommand))
 +    {
 +        printf("Got data size %d, expected %d" , (int) size,(int) sizeof(UsbCommand));
 +        lua_pushstring(L,"Wrong data size");
 +        return 1;
 +    }
  
  //    UsbCommand c = (*data);
 -      SendCommand((UsbCommand* )data);
 -      return 0; // no return values
 +    SendCommand((UsbCommand* )data);
 +    return 0; // no return values
  }
  /**
   * @brief The following params expected:
   */
  static int l_WaitForResponseTimeout(lua_State *L){
  
 -      uint32_t cmd = 0;
 -      size_t ms_timeout = -1;
 -
 -      //Check number of arguments
 -      int n = lua_gettop(L);
 -      if(n == 0)
 -      {
 -              //signal error by returning Nil, errorstring
 -              lua_pushnil(L);
 -              lua_pushstring(L,"You need to supply at least command to wait for");
 -              return 2; // two return values
 -      }
 -      if(n >= 1)
 -      {
 -              //pop cmd
 -              cmd = luaL_checkunsigned(L,1);
 -      }
 -      if(n >= 2)
 -      {
 -              //Did the user send a timeout ?
 -              //Check if the current top of stack is an integer
 -              ms_timeout = luaL_checkunsigned(L,2);
 -              //printf("Timeout set to %dms\n" , (int) ms_timeout);
 -      }
 -
 -      UsbCommand response;
 -
 -      if(WaitForResponseTimeout(cmd, &response, ms_timeout))
 -      {
 -              //Push it as a string
 -              lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand));
 -
 -              return 1;// return 1 to signal one return value
 -      }else{
 -              //Push a Nil instead
 -              lua_pushnil(L);
 -              return 1;// one return value
 -      }
 +    uint32_t cmd = 0;
 +    size_t ms_timeout = -1;
 +
 +    //Check number of arguments
 +    int n = lua_gettop(L);
 +    if(n == 0)
 +    {
 +        //signal error by returning Nil, errorstring
 +        lua_pushnil(L);
 +        lua_pushstring(L,"You need to supply at least command to wait for");
 +        return 2; // two return values
 +    }
 +    if(n >= 1)
 +    {
 +        //pop cmd
 +        cmd = luaL_checkunsigned(L,1);
 +    }
 +    if(n >= 2)
 +    {
 +        //Did the user send a timeout ?
 +        //Check if the current top of stack is an integer
 +        ms_timeout = luaL_checkunsigned(L,2);
 +        //printf("Timeout set to %dms\n" , (int) ms_timeout);
 +    }
 +
 +    UsbCommand response;
 +
 +    if(WaitForResponseTimeout(cmd, &response, ms_timeout))
 +    {
 +        //Push it as a string
 +         lua_pushlstring(L,(const char *)&response,sizeof(UsbCommand));
 +
 +        return 1;// return 1 to signal one return value
 +    }else{
 +        //Push a Nil instead
 +        lua_pushnil(L);
 +        return 1;// one return value
 +    }
  }
  
  static int returnToLuaWithError(lua_State *L, const char* fmt, ...)
  {
 -      char buffer[200];
 -      va_list args;
 -      va_start(args,fmt);
 -      vsnprintf(buffer, sizeof(buffer), fmt,args);
 -      va_end(args);
 -
 -      lua_pushnil(L);
 -      lua_pushstring(L,buffer);
 -      return 2;
 +    char buffer[200];
 +    va_list args;
 +    va_start(args,fmt);
 +    vsnprintf(buffer, sizeof(buffer), fmt,args);
 +    va_end(args);
 +
 +    lua_pushnil(L);
 +    lua_pushstring(L,buffer);
 +    return 2;
  }
  
  static int l_nonce2key(lua_State *L){
  
 -      size_t size;
 -      const char *p_uid = luaL_checklstring(L, 1, &size);
 -      if(size != 4)  return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size);
 +    size_t size;
 +    const char *p_uid = luaL_checklstring(L, 1, &size);
 +    if(size != 4)  return returnToLuaWithError(L,"Wrong size of uid, got %d bytes, expected 4", (int) size);
  
 -      const char *p_nt = luaL_checklstring(L, 2, &size);
 -      if(size != 4)  return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size);
 +    const char *p_nt = luaL_checklstring(L, 2, &size);
 +    if(size != 4)  return returnToLuaWithError(L,"Wrong size of nt, got %d bytes, expected 4", (int) size);
  
 -      const char *p_nr = luaL_checklstring(L, 3, &size);
 -      if(size != 4)  return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size);
 +    const char *p_nr = luaL_checklstring(L, 3, &size);
 +    if(size != 4)  return returnToLuaWithError(L,"Wrong size of nr, got %d bytes, expected 4", (int) size);
  
 -      const char *p_par_info = luaL_checklstring(L, 4, &size);
 -      if(size != 8)  return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size);
 +    const char *p_par_info = luaL_checklstring(L, 4, &size);
 +    if(size != 8)  return returnToLuaWithError(L,"Wrong size of par_info, got %d bytes, expected 8", (int) size);
  
 -      const char *p_pks_info = luaL_checklstring(L, 5, &size);
 -      if(size != 8)  return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size);
 +    const char *p_pks_info = luaL_checklstring(L, 5, &size);
 +    if(size != 8)  return returnToLuaWithError(L,"Wrong size of ks_info, got %d bytes, expected 8", (int) size);
  
  
 -      uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4);
 -      uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4);
 +    uint32_t uid = bytes_to_num(( uint8_t *)p_uid,4);
 +    uint32_t nt = bytes_to_num(( uint8_t *)p_nt,4);
  
 -      uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4);
 -      uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8);
 -      uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8);
 +    uint32_t nr = bytes_to_num(( uint8_t*)p_nr,4);
 +    uint64_t par_info = bytes_to_num(( uint8_t *)p_par_info,8);
 +    uint64_t ks_info = bytes_to_num(( uint8_t *)p_pks_info,8);
  
 -      uint64_t key = 0;
 +    uint64_t key = 0;
  
 -      int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key);
 +    int retval = nonce2key(uid,nt, nr, par_info,ks_info, &key);
  
 -      //Push the retval on the stack
 -      lua_pushinteger(L,retval);
 +    //Push the retval on the stack
 +    lua_pushinteger(L,retval);
-   
 -      //Push the key onto the stack
 -      uint8_t dest_key[8];
 -      num_to_bytes(key,sizeof(dest_key),dest_key);
 +    //Push the key onto the stack
 +    uint8_t dest_key[8];
 +    num_to_bytes(key,sizeof(dest_key),dest_key);
  
 -      //printf("Pushing to lua stack: %012"llx"\n",key);
 -      lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key));
 +    //printf("Pushing to lua stack: %012"llx"\n",key);
 +    lua_pushlstring(L,(const char *) dest_key,sizeof(dest_key));
  
 -      return 2; //Two return values
 +    return 2; //Two return values
  }
  //static int l_PrintAndLog(lua_State *L){ return CmdHF14AMfDump(luaL_checkstring(L, 1));}
  static int l_clearCommandBuffer(lua_State *L){
 -      clearCommandBuffer();
 -      return 0;
 +    clearCommandBuffer();
 +    return 0;
  }
  /**
   * @brief l_foobar is a dummy function to test lua-integration with
   */
  static int l_foobar(lua_State *L)
  {
 -      //Check number of arguments
 -      int n = lua_gettop(L);
 -      printf("foobar called with %d arguments" , n);
 -      lua_settop(L, 0);
 -      printf("Arguments discarded, stack now contains %d elements", lua_gettop(L));
 -
 -      // todo: this is not used, where was it intended for?
 -      // UsbCommand response =  {CMD_MIFARE_READBL, {1337, 1338, 1339}};
 -
 -      printf("Now returning a uint64_t as a string");
 -      uint64_t x = 0xDEADBEEF;
 -      uint8_t destination[8];
 -      num_to_bytes(x,sizeof(x),destination);
 -      lua_pushlstring(L,(const char *)&x,sizeof(x));
 -      lua_pushlstring(L,(const char *)destination,sizeof(destination));
 -
 -      return 2;
 +    //Check number of arguments
 +    int n = lua_gettop(L);
 +    printf("foobar called with %d arguments" , n);
 +    lua_settop(L, 0);
 +    printf("Arguments discarded, stack now contains %d elements", lua_gettop(L));
-   
++
 +    // todo: this is not used, where was it intended for?
 +    // UsbCommand response =  {CMD_MIFARE_READBL, {1337, 1338, 1339}};
-   
++
 +    printf("Now returning a uint64_t as a string");
 +    uint64_t x = 0xDEADBEEF;
 +    uint8_t destination[8];
 +    num_to_bytes(x,sizeof(x),destination);
 +    lua_pushlstring(L,(const char *)&x,sizeof(x));
 +    lua_pushlstring(L,(const char *)destination,sizeof(destination));
 +
 +    return 2;
  }
  
  
   */
  static int l_ukbhit(lua_State *L)
  {
 -      lua_pushboolean(L,ukbhit() ? true : false);
 -      return 1;
 +    lua_pushboolean(L,ukbhit() ? true : false);
 +    return 1;
  }
  /**
   * @brief Calls the command line parser to deal with the command. This enables
   */
  static int l_CmdConsole(lua_State *L)
  {
 -      CommandReceived((char *)luaL_checkstring(L, 1));
 -      return 0;
 +    CommandReceived((char *)luaL_checkstring(L, 1));
 +    return 0;
  }
  
  static int l_iso15693_crc(lua_State *L)
  {
 -      //    uint16_t Iso15693Crc(uint8_t *v, int n);
 -      size_t size;
 -      const char *v = luaL_checklstring(L, 1, &size);
 -      uint16_t retval = Iso15693Crc((uint8_t *) v, size);
 -      lua_pushinteger(L, (int) retval);
 -      return 1;
 +    //    uint16_t Iso15693Crc(uint8_t *v, int n);
 +    size_t size;
 +    const char *v = luaL_checklstring(L, 1, &size);
 +    uint16_t retval = Iso15693Crc((uint8_t *) v, size);
 +    lua_pushinteger(L, (int) retval);
 +    return 1;
  }
  
  /*
@@@ -235,28 -235,28 +235,29 @@@ static int l_aes128decrypt(lua_State *L
  {
        //Check number of arguments
        int i;
 -      size_t size;
 -      const char *p_key = luaL_checklstring(L, 1, &size);
 -      if(size != 32)  return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
 +    size_t size;
 +    const char *p_key = luaL_checklstring(L, 1, &size);
 +    if(size != 32)  return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
  
 -      const char *p_encTxt = luaL_checklstring(L, 2, &size);
 +    const char *p_encTxt = luaL_checklstring(L, 2, &size);
-     
        unsigned char indata[16] = {0x00};
        unsigned char outdata[16] = {0x00};
 -      unsigned char aes_key[16] = {0x00};
 +    unsigned char aes_key[16] = {0x00};
        unsigned char iv[16] = {0x00};
  
+       // convert key to bytearray and convert input to bytearray
        for (i = 0; i < 32; i += 2) {
                sscanf(&p_encTxt[i], "%02x", (unsigned int *)&indata[i / 2]);
                sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
        }
  
 -      aes_context ctx;
 -      aes_init(&ctx);
 +    aes_context ctx;
 +    aes_init(&ctx);
 +    //aes_setkey_enc(&ctx, (const unsigned char *)aes_key, 128);
        aes_setkey_dec(&ctx, aes_key, 128);
 -      aes_crypt_cbc(&ctx,AES_DECRYPT,sizeof(indata), iv, indata,outdata );
 -      //Push decrypted array as a string
 +      aes_crypt_cbc(&ctx, AES_DECRYPT, sizeof(indata), iv, indata, outdata );
 +    //Push decrypted array as a string
        lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
        return 1;// return 1 to signal one return value
  }
@@@ -264,15 -264,15 +265,15 @@@ static int l_aes128encrypt(lua_State *L
  {
        //Check number of arguments
        int i;
 -      size_t size;
 -      const char *p_key = luaL_checklstring(L, 1, &size);
 -      if(size != 32)  return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
 -
 -      const char *p_txt = luaL_checklstring(L, 2, &size);
 +    size_t size;
 +    const char *p_key = luaL_checklstring(L, 1, &size);
 +    if(size != 32)  return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size);
  
 +    const char *p_txt = luaL_checklstring(L, 2, &size);
 +    
        unsigned char indata[16] = {0x00};
        unsigned char outdata[16] = {0x00};
 -      unsigned char aes_key[16] = {0x00};
 +    unsigned char aes_key[16] = {0x00};
        unsigned char iv[16] = {0x00};
        
        for (i = 0; i < 32; i += 2) {
                sscanf(&p_key[i], "%02x", (unsigned int *)&aes_key[i / 2]);
        }
  
 -      aes_context ctx;
 -      aes_init(&ctx);
 +    aes_context ctx;
 +    aes_init(&ctx);
-     aes_setkey_enc(&ctx, aes_key, 128);
+       aes_setkey_enc(&ctx, aes_key, 128);
        aes_crypt_cbc(&ctx, AES_ENCRYPT, sizeof(indata), iv, indata, outdata );
-     //Push encrypted array as a string
+       //Push encrypted array as a string
        lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
        return 1;// return 1 to signal one return value
  }
@@@ -293,10 -293,10 +294,10 @@@ static int l_crc16(lua_State *L
  {
        size_t size;
        const char *p_str = luaL_checklstring(L, 1, &size);
-               
        uint16_t retval = crc16_ccitt( (uint8_t*) p_str, size);
 -      lua_pushinteger(L, (int) retval);
 -      return 1;
 +    lua_pushinteger(L, (int) retval);
 +    return 1;
  }
  
  static int l_crc64(lua_State *L)
        unsigned char outdata[8] = {0x00};
  
        const char *p_str = luaL_checklstring(L, 1, &size);
-       
        crc64( (uint8_t*) p_str, size, &crc);
  
        outdata[0] = (uint8_t)(crc >> 56) & 0xff;
        outdata[6] = (uint8_t)(crc >> 8) & 0xff;
        outdata[7] = crc & 0xff;
        lua_pushlstring(L,(const char *)&outdata, sizeof(outdata));
-     return 1;
+       return 1;
  }
  
  /**
   */
  int setLuaPath( lua_State* L, const char* path )
  {
 -      lua_getglobal( L, "package" );
 -      lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1)
 -      const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack
 -      int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it
 -      char * buf = malloc(requiredLength);
 -      snprintf(buf, requiredLength, "%s;%s", cur_path, path);
 -      lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5
 -      lua_pushstring( L, buf ); // push the new one
 -      lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack
 -      lua_pop( L, 1 ); // get rid of package table from top of stack
 +    lua_getglobal( L, "package" );
 +    lua_getfield( L, -1, "path" ); // get field "path" from table at top of stack (-1)
 +    const char* cur_path = lua_tostring( L, -1 ); // grab path string from top of stack
 +    int requiredLength = strlen(cur_path)+ strlen(path)+10; //A few bytes too many, whatever we can afford it
 +    char * buf = malloc(requiredLength);
 +    snprintf(buf, requiredLength, "%s;%s", cur_path, path);
 +    lua_pop( L, 1 ); // get rid of the string on the stack we just pushed on line 5
 +    lua_pushstring( L, buf ); // push the new one
 +    lua_setfield( L, -2, "path" ); // set the field "path" in table at -2 with value at top of stack
 +    lua_pop( L, 1 ); // get rid of package table from top of stack
-     free(buf);
+       free(buf);
        return 0; // all done!
  }
  
  int set_pm3_libraries(lua_State *L)
  {
  
 -      static const luaL_Reg libs[] = {
 -              {"SendCommand",                 l_SendCommand},
 -              {"WaitForResponseTimeout",      l_WaitForResponseTimeout},
 -              {"nonce2key",                   l_nonce2key},
 -              //{"PrintAndLog",                 l_PrintAndLog},
 -              {"foobar",                      l_foobar},
 -              {"ukbhit",                      l_ukbhit},
 -              {"clearCommandBuffer",          l_clearCommandBuffer},
 +    static const luaL_Reg libs[] = {
 +        {"SendCommand",                 l_SendCommand},
 +        {"WaitForResponseTimeout",      l_WaitForResponseTimeout},
 +        {"nonce2key",                   l_nonce2key},
 +        //{"PrintAndLog",                 l_PrintAndLog},
 +        {"foobar",                      l_foobar},
 +        {"ukbhit",                      l_ukbhit},
 +        {"clearCommandBuffer",          l_clearCommandBuffer},
-         {"console",                     l_CmdConsole},
-         {"iso15693_crc",                l_iso15693_crc},
+               {"console",                     l_CmdConsole},
+               {"iso15693_crc",                l_iso15693_crc},
                {"aes128_decrypt",              l_aes128decrypt},
                {"aes128_encrypt",              l_aes128encrypt},
                {"crc16",                       l_crc16},
-               {"crc64",                                               l_crc64},
+               {"crc64",                       l_crc64},
 -              {NULL, NULL}
 -      };
 -
 -      lua_pushglobaltable(L);
 -      // Core library is in this table. Contains '
 -      //this is 'pm3' table
 -      lua_newtable(L);
 -
 -      //Put the function into the hash table.
 -      for (int i = 0; libs[i].name; i++) {
 -              lua_pushcfunction(L, libs[i].func);
 -              lua_setfield(L, -2, libs[i].name);//set the name, pop stack
 -      }
 -      //Name of 'core'
 -      lua_setfield(L, -2, "core");
 -
 -      //-- remove the global environment table from the stack
 -      lua_pop(L, 1);
 -
 -      //-- Last but not least, add to the LUA_PATH (package.path in lua)
 -      // so we can load libraries from the ./lualib/ - directory
 -      setLuaPath(L,"./lualibs/?.lua");
 -
 -      return 1;
 +        {NULL, NULL}
 +    };
 +
 +    lua_pushglobaltable(L);
 +    // Core library is in this table. Contains '
 +    //this is 'pm3' table
 +    lua_newtable(L);
 +
 +    //Put the function into the hash table.
 +    for (int i = 0; libs[i].name; i++) {
 +        lua_pushcfunction(L, libs[i].func);
 +        lua_setfield(L, -2, libs[i].name);//set the name, pop stack
 +    }
 +    //Name of 'core'
 +    lua_setfield(L, -2, "core");
 +
 +    //-- remove the global environment table from the stack
 +    lua_pop(L, 1);
 +
 +    //-- Last but not least, add to the LUA_PATH (package.path in lua)
 +    // so we can load libraries from the ./lualib/ - directory
 +    setLuaPath(L,"./lualibs/?.lua");
 +
 +    return 1;
  }
diff --combined client/util.c
index 391b9b00c7629e6e4239873ee7d8bbdfc9f9d441,cea9f7d734a81150d1f5536118364552dcbfa807..a64f46b98e815461c1eaf6aa18fb4fff0b81c973
@@@ -108,16 -108,16 +108,16 @@@ void print_hex(const uint8_t * data, co
        printf("\n");
  }
  
 -char * sprint_hex(const uint8_t * data, const size_t len) {
 +char *sprint_hex(const uint8_t *data, const size_t len) {
        
        int maxLen = ( len > 1024/3) ? 1024/3 : len;
        static char buf[1024];
        memset(buf, 0x00, 1024);
-       char *tmp = buf;
+       char * tmp = buf;
        size_t i;
  
        for (i=0; i < maxLen; ++i, tmp += 3)
 -              sprintf(tmp, "%02x ", data[i]);
 +              sprintf(tmp, "%02X ", data[i]);
  
        return buf;
  }
diff --combined common/protocols.h
index 62cfb7ff9cb42fe5932b1ea5f5178f97b119da3b,580342728b866ee7f76d3f09537580da1c43c72d..466e84f1b169e83d5aebb11a34a89702ccedaab6
@@@ -109,7 -109,7 +109,7 @@@ NXP/Philips CUSTOM COMMAND
  #define ISO14443A_CMD_WUPA       0x52
  #define ISO14443A_CMD_ANTICOLL_OR_SELECT     0x93
  #define ISO14443A_CMD_ANTICOLL_OR_SELECT_2   0x95
 -#define ISO14443A_CMD_WRITEBLOCK 0xA0 // or 0xA2 ?
 +#define ISO14443A_CMD_WRITEBLOCK 0xA0
  #define ISO14443A_CMD_HALT       0x50
  #define ISO14443A_CMD_RATS       0xE0
  
  #define MIFARE_CMD_RESTORE      0xC2
  #define MIFARE_CMD_TRANSFER     0xB0
  
- #define MIFARE_ULC_WRITE              0xA2
- //#define MIFARE_ULC_COMP_WRITE 0xA0
+ #define MIFARE_ULC_WRITE        0xA2
+ //#define MIFARE_ULC__COMP_WRITE  0xA0
  #define MIFARE_ULC_AUTH_1       0x1A
  #define MIFARE_ULC_AUTH_2       0xAF
  
 -#define MIFARE_ULEV1_AUTH       0x1B
 -#define MIFARE_ULEV1_VERSION    0x60
 -#define MIFARE_ULEV1_FASTREAD   0x3A
 -//#define MIFARE_ULEV1_WRITE      0xA2
 -//#define MIFARE_ULEV1_COMP_WRITE 0xA0
 -#define MIFARE_ULEV1_READ_CNT   0x39
 -#define MIFARE_ULEV1_INCR_CNT   0xA5
 -#define MIFARE_ULEV1_READSIG    0x3C
 -#define MIFARE_ULEV1_CHECKTEAR  0x3E
 -#define MIFARE_ULEV1_VCSL       0x4B
 +#define MIFARE_ULEV1_AUTH             0x1B
 +#define MIFARE_ULEV1_VERSION  0x60
 +#define MIFARE_ULEV1_FASTREAD 0x3A
 +#define MIFARE_ULEV1_READ_CNT 0x39
 +#define MIFARE_ULEV1_INCR_CNT 0xA5
 +#define MIFARE_ULEV1_READSIG  0x3C
 +#define MIFARE_ULEV1_CHECKTEAR        0x3E
 +#define MIFARE_ULEV1_VCSL             0x4B
  
  /**
  06 00 = INITIATE
  #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/usb_cmd.h
index 2a6e94842e904fb106d5ea11b3c3a8948398e065,357395d43f3103eb01a66144648dbd2e97d001e9..345793eca48f8cd5cdd80e634a1f536a6af85a14
@@@ -128,13 -128,12 +128,13 @@@ typedef struct
  #define CMD_READER_LEGIC_RF                                               0x0388
  #define CMD_WRITER_LEGIC_RF                                               0x0389
  #define CMD_EPA_PACE_COLLECT_NONCE                                        0x038A
 +//#define CMD_EPA_                                                          0x038B
  
  #define CMD_SNOOP_ICLASS                                                  0x0392
  #define CMD_SIMULATE_TAG_ICLASS                                           0x0393
  #define CMD_READER_ICLASS                                                 0x0394
- #define CMD_READER_ICLASS_REPLAY                                                                                0x0395
+ #define CMD_READER_ICLASS_REPLAY                                          0x0395
 -#define CMD_ICLASS_ISO14443A_WRITE                                        0x0397
 +#define CMD_ICLASS_ISO14443A_WRITE                                                                              0x0397
  #define CMD_ICLASS_EML_MEMSET                                             0x0398
  
  // For measurements of the antenna tuning
  #define CMD_MIFARE_NESTED                                                 0x0612
  
  #define CMD_MIFARE_READBL                                                 0x0620
- #define CMD_MIFAREU_READBL                                                                      0x0720
+ #define CMD_MIFAREU_READBL                                                0x0720
  #define CMD_MIFARE_READSC                                                 0x0621
- #define CMD_MIFAREU_READCARD                                                                0x0721
+ #define CMD_MIFAREU_READCARD                                              0x0721
  #define CMD_MIFARE_WRITEBL                                                0x0622
 -#define CMD_MIFAREU_WRITEBL                                               0x0722
 -#define CMD_MIFAREU_WRITEBL_COMPAT                                        0x0723
 +#define CMD_MIFAREU_WRITEBL                                                                     0x0722
 +#define CMD_MIFAREU_WRITEBL_COMPAT                                                          0x0723
  
  #define CMD_MIFARE_CHKKEYS                                                0x0623
  
  #define CMD_MIFARE_SNIFFER                                                0x0630
  //ultralightC
- #define CMD_MIFAREUC_AUTH                                                                       0x0724
+ #define CMD_MIFAREUC_AUTH                                                 0x0724
  //0x0725 and 0x0726 no longer used 
- #define CMD_MIFAREUC_SETPWD                                                                         0x0727
+ #define CMD_MIFAREUC_SETPWD                                               0x0727
  
  
  // mifare desfire
  #define CMD_MIFARE_DESFIRE_INFO                                           0x072d
  #define CMD_MIFARE_DESFIRE                                                0x072e
  
 +#define CMD_MIFARE_COLLECT_NONCES                                                                               0x072f
 +
  #define CMD_UNKNOWN                                                       0xFFFF
  
  
  
  
  //Iclass reader flags
 -#define FLAG_ICLASS_READER_ONLY_ONCE    0x01
 -#define FLAG_ICLASS_READER_CC           0x02
 -#define FLAG_ICLASS_READER_CSN          0x04
 -#define FLAG_ICLASS_READER_CONF         0x08
 -#define FLAG_ICLASS_READER_AA           0x10
 +#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
 +#define FLAG_ICLASS_READER_CC       0x02
 +#define FLAG_ICLASS_READER_CSN                0x04
 +#define FLAG_ICLASS_READER_CONF               0x08
 +#define FLAG_ICLASS_READER_AA         0x10
  #define FLAG_ICLASS_READER_ONE_TRY      0x20
  
  
Impressum, Datenschutz