]> 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 --cc 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
index b19e079b15876adcb1a76c19f7aad6633fe12118,96644b9a09e039062130d5fae52c34952c3032d1..04503a4fa58da584f36518d7d226dbfc25309602
@@@ -845,9 -843,9 +845,10 @@@ void UsbPacketReceived(uint8_t *packet
                        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);
diff --cc 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.
Simple merge
diff --cc armsrc/lfops.c
Simple merge
index 03e15b3b52e9ce8d29bd38bb33c87ad598b9d011,0586a25db1b8882678ca3bd3080bcb37437d9293..c56f2337e68b0cdb8c12c2543b4e1c4a8c52f4ce
@@@ -110,8 -115,8 +115,10 @@@ void MifareUC_Auth(uint8_t arg0, uint8_
        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
@@@ -169,8 -174,8 +176,8 @@@ void MifareUReadBlock(uint8_t arg0, uin
                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
@@@ -277,44 -278,44 +284,73 @@@ void MifareUReadCard(uint8_t arg0, uint
                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
@@@ -449,20 -450,12 +485,20 @@@ void MifareUWriteBlock(uint8_t arg0, ui
        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
index 8c44445f5c01a614cc41a0b88de01617c03d0123,2f84797b92e015384d8b2755410bd4c553431efd..109b91b0efb1bdc961b5693af83ffcbc5f05015d
@@@ -376,27 -377,27 +377,47 @@@ int mifare_ultra_auth(uint8_t *keybytes
                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
@@@ -494,23 -495,23 +515,23 @@@ int mifare_classic_writeblock(struct Cr
  \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
        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
index f73814be51458bdafaeadc83a7b9a06c44b5524d,d4fcd818932e4cf66299edd53044e00f9432fb2f..9575b9fc6bac103ba62da142698f173943cf32d0
@@@ -58,19 -58,19 +58,19 @@@ int mifare_sendcmd_short_special(struc
  \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
diff --cc client/cmdhf.c
index 1a0886769ae3517c4c89cae3860e7f9669ad6b6b,16f7bb0f39f661c180723bd0c52bd1306407f8bd..614dcdc4460e98bf7ed5b90de015970cfe6c10ea
@@@ -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}
  };
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...");
index 1b815326e13e26f611a169a059702193455f9b83,aa3b66dc64b960f2bf855b62257f904b26196a4e..676a8884c863f30ffbcae7d1a63adead2d1036f8
@@@ -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
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] = {
@@@ -151,63 -151,63 +151,127 @@@ static int ul_select( iso14a_card_selec
                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
@@@ -308,359 -308,359 +372,777 @@@ static int ul_print_default( uint8_t *d
                                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;
@@@ -974,102 -912,27 +1456,101 @@@ int CmdHF14AMfUWrBl(const char *Cmd)
  //
  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) {
@@@ -1534,10 -1509,10 +2021,11 @@@ int CmdTestDES(const char * cmd
  //
  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];
Simple merge
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
@@@ -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
@@@ -536,8 -536,8 +533,7 @@@ brute_top(uint32_t prefix, uint32_t rre
   * 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
index 880b7cb2ffecea9741fad613a3f64d3cae380496,152fd9d44335236ffe3def9237d3bb38eccb68b3..9e643932c1b59e148dfeaf882a0a18d2b2f8202e
@@@ -123,45 -123,45 +123,45 @@@ static int returnToLuaWithError(lua_Sta
  
  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){
   */
  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;
  }
  
  
@@@ -235,17 -235,18 +235,18 @@@ 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]);
@@@ -280,11 -280,11 +281,11 @@@ static int l_aes128encrypt(lua_State *L
                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)
   */
  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 --cc client/util.c
Simple merge
Simple merge
index 2a6e94842e904fb106d5ea11b3c3a8948398e065,357395d43f3103eb01a66144648dbd2e97d001e9..345793eca48f8cd5cdd80e634a1f536a6af85a14
@@@ -133,8 -132,8 +133,8 @@@ typedef struct
  #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
  
Impressum, Datenschutz