]> cvs.zerfleddert.de Git - proxmark3-svn/commitdiff
iclass additions
authormarshmellow42 <marshmellowrf@gmail.com>
Mon, 20 Jul 2015 17:41:40 +0000 (13:41 -0400)
committermarshmellow42 <marshmellowrf@gmail.com>
Mon, 20 Jul 2015 17:41:40 +0000 (13:41 -0400)
multiple contributors - thanks!

13 files changed:
armsrc/appmain.c
armsrc/apps.h
armsrc/iclass.c
client/cmdhf.c
client/cmdhficlass.c
client/cmdhficlass.h
client/cmdlf.c
client/hid-flasher/usb_cmd.h
client/loclass/cipher.c
client/loclass/cipher.h
client/lualibs/commands.lua
common/protocols.c
include/usb_cmd.h

index 0cbfa2498e6ca7349f23766af663cd57ab70ac47..906379a7f45d211bd9225f541e5fdd82c03dda60 100644 (file)
@@ -860,11 +860,26 @@ void UsbPacketReceived(uint8_t *packet, int len)
                        ReaderIClass(c->arg[0]);
                        break;
                case CMD_READER_ICLASS_REPLAY:
                        ReaderIClass(c->arg[0]);
                        break;
                case CMD_READER_ICLASS_REPLAY:
-                   ReaderIClass_Replay(c->arg[0], c->d.asBytes);
+                       ReaderIClass_Replay(c->arg[0], c->d.asBytes);
                        break;
                        break;
-       case CMD_ICLASS_EML_MEMSET:
+               case CMD_ICLASS_EML_MEMSET:
                        emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
                        break;
                        emlSet(c->d.asBytes,c->arg[0], c->arg[1]);
                        break;
+               case CMD_ICLASS_WRITEBLOCK:
+                       iClass_WriteBlock(c->arg[0], c->arg[1], c->d.asBytes);
+                       break;
+               case CMD_ICLASS_READBLOCK:
+                       iClass_ReadBlk(c->arg[0], c->arg[1]);
+                       break;
+               case CMD_ICLASS_AUTHENTICATION:
+                       iClass_Authentication(c->d.asBytes);
+                       break;
+               case CMD_ICLASS_DUMP:
+                       iClass_Dump(c->arg[0], c->arg[1], c->arg[2]);
+                       break;
+               case CMD_ICLASS_CLONE:
+                       iClass_Clone(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes);
+                       break;
 #endif
 
                case CMD_BUFF_CLEAR:
 #endif
 
                case CMD_BUFF_CLEAR:
index 42efd11837fddc81e21c078af02227025ef43239..e8b43e9bb2b5af8628044cecf541e6960027f9ee 100644 (file)
@@ -149,9 +149,6 @@ void        OnSuccess();
 void   OnError(uint8_t reason);
 
 
 void   OnError(uint8_t reason);
 
 
-
-
-
 /// iso15693.h
 void RecordRawAdcSamplesIso15693(void);
 void AcquireRawAdcSamplesIso15693(void);
 /// iso15693.h
 void RecordRawAdcSamplesIso15693(void);
 void AcquireRawAdcSamplesIso15693(void);
@@ -167,6 +164,12 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
 void ReaderIClass(uint8_t arg0);
 void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC);
 void IClass_iso14443A_GetPublic(uint8_t arg0);
 void ReaderIClass(uint8_t arg0);
 void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC);
 void IClass_iso14443A_GetPublic(uint8_t arg0);
+void iClass_Authentication(uint8_t *MAC);
+void iClass_WriteBlock(uint8_t blockNo, uint8_t keyType, uint8_t *data);
+void iClass_ReadBlk(uint8_t blockNo, uint8_t keyType);
+bool iClass_ReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *readdata);
+void iClass_Dump(uint8_t blockno, uint8_t numblks, uint8_t keyType);
+void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t keyType, uint8_t *data);
 
 // hitag2.h
 void SnoopHitag(uint32_t type);
 
 // hitag2.h
 void SnoopHitag(uint32_t type);
index 97c62bb60daf7c4d3367f1a49a5bdd9f7c001468..a27fb970069965c919fbd53a96066f0ebc4b474e 100644 (file)
@@ -1601,16 +1601,16 @@ void setupIclassReader()
 
 }
 
 
 }
 
-size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries)
+bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries)
 {
        while(retries-- > 0)
        {
                ReaderTransmitIClass(command, cmdsize);
                if(expected_size == ReaderReceiveIClass(resp)){
 {
        while(retries-- > 0)
        {
                ReaderTransmitIClass(command, cmdsize);
                if(expected_size == ReaderReceiveIClass(resp)){
-                       return 0;
+                       return true;
                }
        }
                }
        }
-       return 1;//Error
+       return false;//Error
 }
 
 /**
 }
 
 /**
@@ -1620,14 +1620,17 @@ size_t sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t*
  *         1 = Got CSN
  *         2 = Got CSN and CC
  */
  *         1 = Got CSN
  *         2 = Got CSN and CC
  */
-uint8_t handshakeIclassTag(uint8_t *card_data)
+uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key)
 {
        static uint8_t act_all[]     = { 0x0a };
 {
        static uint8_t act_all[]     = { 0x0a };
-       static uint8_t identify[]    = { 0x0c };
+       //static uint8_t identify[]    = { 0x0c };
+       static uint8_t identify[]    = { 0x0c, 0x00, 0x73, 0x33 };
        static uint8_t select[]      = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
        static uint8_t select[]      = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-
-
-       static uint8_t readcheck_cc[]= { 0x88, 0x02,};
+       static uint8_t readcheck_cc[]= { 0x88, 0x02 };
+       if (use_credit_key)
+               readcheck_cc[0] = 0x18;
+       else
+               readcheck_cc[0] = 0x88;
 
        uint8_t resp[ICLASS_BUFFER_SIZE];
 
 
        uint8_t resp[ICLASS_BUFFER_SIZE];
 
@@ -1668,6 +1671,9 @@ uint8_t handshakeIclassTag(uint8_t *card_data)
 
        return read_status;
 }
 
        return read_status;
 }
+uint8_t handshakeIclassTag(uint8_t *card_data){
+       return handshakeIclassTag_ext(card_data, false);
+}
 
 
 // Reader iClass Anticollission
 
 
 // Reader iClass Anticollission
@@ -1687,6 +1693,9 @@ void ReaderIClass(uint8_t arg0) {
        uint8_t result_status = 0;
        bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
        bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY;
        uint8_t result_status = 0;
        bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE;
        bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY;
+       bool use_credit_key = false;
+       if (arg0 & FLAG_ICLASS_READER_CEDITKEY)
+               use_credit_key = true;
        set_tracing(TRUE);
        setupIclassReader();
 
        set_tracing(TRUE);
        setupIclassReader();
 
@@ -1701,7 +1710,7 @@ void ReaderIClass(uint8_t arg0) {
                }
                WDT_HIT();
 
                }
                WDT_HIT();
 
-               read_status = handshakeIclassTag(card_data);
+               read_status = handshakeIclassTag_ext(card_data, use_credit_key);
 
                if(read_status == 0) continue;
                if(read_status == 1) result_status = FLAG_ICLASS_READER_CSN;
 
                if(read_status == 0) continue;
                if(read_status == 1) result_status = FLAG_ICLASS_READER_CSN;
@@ -1715,11 +1724,10 @@ void ReaderIClass(uint8_t arg0) {
                if(arg0 & FLAG_ICLASS_READER_CONF)
                {
                        if(sendCmdGetResponseWithRetries(readConf, sizeof(readConf),card_data+8, 10, 10))
                if(arg0 & FLAG_ICLASS_READER_CONF)
                {
                        if(sendCmdGetResponseWithRetries(readConf, sizeof(readConf),card_data+8, 10, 10))
-                       {
-                               Dbprintf("Failed to dump config block");
-                       }else
                        {
                                result_status |= FLAG_ICLASS_READER_CONF;
                        {
                                result_status |= FLAG_ICLASS_READER_CONF;
+                       } else {
+                               Dbprintf("Failed to dump config block");
                        }
                }
 
                        }
                }
 
@@ -1727,10 +1735,9 @@ void ReaderIClass(uint8_t arg0) {
                if(arg0 & FLAG_ICLASS_READER_AA){
                        if(sendCmdGetResponseWithRetries(readAA, sizeof(readAA),card_data+(8*4), 10, 10))
                        {
                if(arg0 & FLAG_ICLASS_READER_AA){
                        if(sendCmdGetResponseWithRetries(readAA, sizeof(readAA),card_data+(8*4), 10, 10))
                        {
-//                             Dbprintf("Failed to dump AA block");
-                       }else
-                       {
                                result_status |= FLAG_ICLASS_READER_AA;
                                result_status |= FLAG_ICLASS_READER_AA;
+                       } else {
+                               //Dbprintf("Failed to dump AA block");
                        }
                }
 
                        }
                }
 
@@ -1814,7 +1821,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
                //for now replay captured auth (as cc not updated)
                memcpy(check+5,MAC,4);
 
                //for now replay captured auth (as cc not updated)
                memcpy(check+5,MAC,4);
 
-               if(sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
+               if(!sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5))
                {
                        Dbprintf("Error: Authentication Fail!");
                        continue;
                {
                        Dbprintf("Error: Authentication Fail!");
                        continue;
@@ -1826,7 +1833,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
                read[2] = crc >> 8;
                read[3] = crc & 0xff;
 
                read[2] = crc >> 8;
                read[3] = crc & 0xff;
 
-               if(sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
+               if(!sendCmdGetResponseWithRetries(read, sizeof(read),resp, 10, 10))
                {
                        Dbprintf("Dump config (block 1) failed");
                        continue;
                {
                        Dbprintf("Dump config (block 1) failed");
                        continue;
@@ -1853,7 +1860,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
                        read[2] = crc >> 8;
                        read[3] = crc & 0xff;
 
                        read[2] = crc >> 8;
                        read[3] = crc & 0xff;
 
-                       if(!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
+                       if(sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 10))
                        {
                                Dbprintf("     %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
                                                 block, resp[0], resp[1], resp[2],
                        {
                                Dbprintf("     %02x: %02x %02x %02x %02x %02x %02x %02x %02x",
                                                 block, resp[0], resp[1], resp[2],
@@ -1904,130 +1911,130 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
        LED_A_OFF();
 }
 
        LED_A_OFF();
 }
 
-//2. Create Read method (cut-down from above) based off responses from 1. 
-//   Since we have the MAC could continue to use replay function.
-//3. Create Write method
-/*
-void IClass_iso14443A_write(uint8_t arg0, uint8_t blockNo, uint8_t *data, uint8_t *MAC) {
-       uint8_t act_all[]     = { 0x0a };
-       uint8_t identify[]    = { 0x0c };
-       uint8_t select[]      = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-       uint8_t readcheck_cc[]= { 0x88, 0x02 };
-       uint8_t check[]       = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-       uint8_t read[]        = { 0x0c, 0x00, 0x00, 0x00 };
-       uint8_t write[]       = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
-       
-    uint16_t crc = 0;
-       
-       uint8_t* resp = (((uint8_t *)BigBuf) + 3560);
+void iClass_Authentication(uint8_t *MAC) {
+       uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       uint8_t resp[ICLASS_BUFFER_SIZE];
+       memcpy(check+5,MAC,4);
+       bool isOK;
+       isOK = sendCmdGetResponseWithRetries(check, sizeof(check),resp, 4, 5);
+       cmd_send(CMD_ACK,isOK,0,0,0,0);
+       //Dbprintf("isOK %d, Tag response : %02x%02x%02x%02x",isOK,resp[0],resp[1],resp[2],resp[3]);
+}
+bool iClass_ReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *readdata) {
+       uint8_t readcmd[] = {keyType, blockNo}; //0x88, 0x00
+       uint8_t resp[8];
+       size_t isOK = 1;
 
 
-       // Reset trace buffer
-    memset(trace, 0x44, RECV_CMD_OFFSET);
-       traceLen = 0;
+       readcmd[1] = blockNo;
+       isOK = sendCmdGetResponseWithRetries(readcmd, sizeof(readcmd),resp, 8, 5);
+       memcpy(readdata,resp,sizeof(resp));
 
 
-       // Setup SSC
-       FpgaSetupSsc();
-       // Start from off (no field generated)
-       // Signal field is off with the appropriate LED
-       LED_D_OFF();
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-       SpinDelay(200);
+       return isOK;
+}
 
 
-       SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
+void iClass_ReadBlk(uint8_t blockno, uint8_t keyType) {
+       uint8_t readblockdata[8];
+       bool isOK = false;
+       isOK = iClass_ReadBlock(blockno, keyType, readblockdata);
+       //Dbprintf("read block [%02x] [%02x%02x%02x%02x%02x%02x%02x%02x]",blockNo,readblockdata[0],readblockdata[1],readblockdata[2],readblockdata[3],readblockdata[4],readblockdata[5],readblockdata[6],readblockdata[7]);
+       cmd_send(CMD_ACK,isOK,0,0,readblockdata,8);
+}
 
 
-       // Now give it time to spin up.
-       // Signal field is on with the appropriate LED
-       FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
-       SpinDelay(200);
+void iClass_Dump(uint8_t blockno, uint8_t numblks, uint8_t keyType) {
+       uint8_t readblockdata[8];
+       bool isOK = false;
+       uint8_t blkCnt = 0;
 
 
-       LED_A_ON();
+       BigBuf_free();
+       uint8_t *dataout = BigBuf_malloc(255*8);
+       memset(dataout,0xFF,255*8);
+       if (dataout == NULL){
+               Dbprintf("out of memory");
+               OnError(1);
+               return;
+       }
 
 
-       for(int i=0;i<1;i++) {
-       
-               if(traceLen > TRACE_SIZE) {
-                       DbpString("Trace full");
-                       break;
+       for (;blkCnt < numblks; blkCnt++) {
+               isOK = iClass_ReadBlock(blockno+blkCnt, keyType, readblockdata);
+               if (!isOK || (readblockdata[0] == 0xBB || readblockdata[7] == 0x33 || readblockdata[2] == 0xBB)) { //try again
+                       isOK = iClass_ReadBlock(blockno+blkCnt, keyType, readblockdata);
+                       if (!isOK) {
+                               Dbprintf("Block %02X failed to read", blkCnt+blockno);
+                               break;
+                       }
                }
                }
-               
-               if (BUTTON_PRESS()) break;
-
-               // Send act_all
-               ReaderTransmitIClass(act_all, 1);
-               // Card present?
-               if(ReaderReceiveIClass(resp)) {
-                       ReaderTransmitIClass(identify, 1);
-                       if(ReaderReceiveIClass(resp) == 10) {
-                               // Select card          
-                               memcpy(&select[1],resp,8);
-                               ReaderTransmitIClass(select, sizeof(select));
-
-                               if(ReaderReceiveIClass(resp) == 10) {
-                                       Dbprintf("     Selected CSN: %02x %02x %02x %02x %02x %02x %02x %02x",
-                                       resp[0], resp[1], resp[2],
-                                       resp[3], resp[4], resp[5],
-                                       resp[6], resp[7]);
-                               }
-                               // Card selected
-                               Dbprintf("Readcheck on Sector 2");
-                               ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc));
-                               if(ReaderReceiveIClass(resp) == 8) {
-                                  Dbprintf("     CC: %02x %02x %02x %02x %02x %02x %02x %02x",
-                                       resp[0], resp[1], resp[2],
-                                       resp[3], resp[4], resp[5],
-                                       resp[6], resp[7]);
-                               }else return;
-                               Dbprintf("Authenticate");
-                               //for now replay captured auth (as cc not updated)
-                               memcpy(check+5,MAC,4);
-                               Dbprintf("     AA: %02x %02x %02x %02x",
-                                       check[5], check[6], check[7],check[8]);
-                               ReaderTransmitIClass(check, sizeof(check));
-                               if(ReaderReceiveIClass(resp) == 4) {
-                                  Dbprintf("     AR: %02x %02x %02x %02x",
-                                       resp[0], resp[1], resp[2],resp[3]);
-                               }else {
-                                 Dbprintf("Error: Authentication Fail!");
-                                 return;
-                               }
-                               Dbprintf("Write Block");
-                               
-                               //read configuration for max block number
-                               read_success=false;
-                               read[1]=1;
-                               uint8_t *blockno=&read[1];
-                               crc = iclass_crc16((char *)blockno,1);
-                               read[2] = crc >> 8;
-                               read[3] = crc & 0xff;
-                               while(!read_success){
-                                     ReaderTransmitIClass(read, sizeof(read));
-                                     if(ReaderReceiveIClass(resp) == 10) {
-                                        read_success=true;
-                                        mem=resp[5];
-                                        memory.k16= (mem & 0x80);
-                                        memory.book= (mem & 0x20);
-                                        memory.k2= (mem & 0x8);
-                                        memory.lockauth= (mem & 0x2);
-                                        memory.keyaccess= (mem & 0x1);
-
-                                     }
-                               }
-                               if (memory.k16){
-                                 cardsize=255;
-                               }else cardsize=32;
-                               //check card_size
-                               
-                               memcpy(write+1,blockNo,1);
-                               memcpy(write+2,data,8);
-                               memcpy(write+10,mac,4);
-                               while(!send_success){
-                                 ReaderTransmitIClass(write, sizeof(write));
-                                 if(ReaderReceiveIClass(resp) == 10) {
-                                   write_success=true;
-                               }
-                       }//
+               memcpy(dataout+(blkCnt*8),readblockdata,8);
+               /*Dbprintf("| %02x | %02x%02x%02x%02x%02x%02x%02x%02x |",
+                       blockno+blkCnt, readblockdata[0], readblockdata[1], readblockdata[2],
+                       readblockdata[3], readblockdata[4], readblockdata[5],
+                       readblockdata[6], readblockdata[7]);
+               */
+       }
+       //return pointer to dump memory in arg3
+       cmd_send(CMD_ACK,isOK,blkCnt,BigBuf_max_traceLen(),0,0);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       LEDsoff();
+       BigBuf_free();
+}
+
+bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t keyType, uint8_t *data) {
+       uint8_t write[] = { 0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+       uint8_t readblockdata[8];
+       write[1] = blockNo;
+       memcpy(write+2, data, 12); // data + mac
+       uint8_t resp[10];
+       bool isOK;
+       isOK = sendCmdGetResponseWithRetries(write,sizeof(write),resp,sizeof(resp),5);
+       //Dbprintf("reply       [%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x]",resp[0],resp[1],resp[2],resp[3],resp[4],resp[5],resp[6],resp[7],resp[8],resp[9]);
+       if (isOK) {
+               isOK = iClass_ReadBlock(blockNo, keyType, readblockdata);
+               //try again
+               if (!isOK || (readblockdata[0] == 0xBB || readblockdata[7] == 0xBB || readblockdata[2] == 0xBB)) 
+                       isOK = iClass_ReadBlock(blockNo, keyType, readblockdata);
+       }
+       if (isOK) {
+               //Dbprintf("read block  [%02x] [%02x%02x%02x%02x%02x%02x%02x%02x]",blockNo,readblockdata[0],readblockdata[1],readblockdata[2],readblockdata[3],readblockdata[4],readblockdata[5],readblockdata[6],readblockdata[7]);
+               if (memcmp(write+2,readblockdata,sizeof(readblockdata)) != 0){
+                       isOK=false;
                }
                }
-               WDT_HIT();
        }
        }
-       
-       LED_A_OFF();
-}*/
+       return isOK;
+}
+
+void iClass_WriteBlock(uint8_t blockNo, uint8_t keyType, uint8_t *data) {
+       bool isOK = iClass_WriteBlock_ext(blockNo, keyType, data);
+       if (isOK){
+               Dbprintf("Write block [%02x] successful",blockNo);
+       } else {
+               Dbprintf("Write block [%02x] failed",blockNo);          
+       }
+       cmd_send(CMD_ACK,isOK,0,0,0,0); 
+}
+
+void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t keyType, uint8_t *data) {
+       int i;
+       int written = 0;
+       int total_block = (endblock - startblock) + 1;
+       for (i = 0; i < total_block;i++){
+               // block number
+               if (iClass_WriteBlock_ext(i+startblock, keyType, data+(i*12))){
+                       Dbprintf("Write block [%02x] successful",i + startblock);
+                       written++;
+               } else {
+                       if (iClass_WriteBlock_ext(i+startblock, keyType, data+(i*12))){
+                               Dbprintf("Write block [%02x] successful",i + startblock);
+                               written++;
+                       } else {
+                               Dbprintf("Write block [%02x] failed",i + startblock);
+                       }
+               }
+       }
+       if (written == total_block)
+               Dbprintf("Clone complete");
+       else
+               Dbprintf("Clone incomplete");   
+
+       cmd_send(CMD_ACK,1,0,0,0,0);
+       FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
+       LEDsoff();
+}
index f8daff7e5ef106f20721ef1dfd53a706648da8f2..8406fe7601b69937833772303579662754cee3c5 100644 (file)
@@ -557,14 +557,14 @@ int CmdHFSearch(const char *Cmd){
                PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n");
                return ans;
        }
                PrintAndLog("\nValid ISO14443A Tag Found - Quiting Search\n");
                return ans;
        }
-       ans = HF14BInfo(false);
+       ans = HFiClassReader("", false, false);
        if (ans) {
        if (ans) {
-               PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
+               PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n");
                return ans;
        }
                return ans;
        }
-       ans = HFiClassReader("", false, false);
+       ans = HF14BInfo(false);
        if (ans) {
        if (ans) {
-               PrintAndLog("\nValid iClass Tag (or PicoPass Tag) Found - Quiting Search\n");
+               PrintAndLog("\nValid ISO14443B Tag Found - Quiting Search\n");
                return ans;
        }
        ans = HF15Reader("", false);
                return ans;
        }
        ans = HF15Reader("", false);
index 824aaa3674cc1bd5cf84d38174968d0e3fbd468e..db3de20577a718a78999eba5158a5c15d96b8387 100644 (file)
 #include "loclass/fileutils.h"
 #include "protocols.h"
 #include "usb_cmd.h"
 #include "loclass/fileutils.h"
 #include "protocols.h"
 #include "usb_cmd.h"
+#include "cmdhfmfu.h"
+
+#define llX PRIx64
 
 static int CmdHelp(const char *Cmd);
 
 
 static int CmdHelp(const char *Cmd);
 
+#define ICLASS_KEYS_MAX 8
+static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = {
+               { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+               { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+               { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+               { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+               { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+               { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+               { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
+               { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
+};
+
+typedef struct iclass_block {
+    uint8_t d[8];
+} iclass_block_t;
+
 int xorbits_8(uint8_t val)
 {
        uint8_t res = val ^ (val >> 1); //1st pass
 int xorbits_8(uint8_t val)
 {
        uint8_t res = val ^ (val >> 1); //1st pass
@@ -170,10 +189,11 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose)
        bool tagFound = false;
        UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN|
                                        FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_AA}};
        bool tagFound = false;
        UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN|
                                        FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_AA}};
-       if (!loop) c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY;
-       SendCommand(&c);
+       // loop in client not device - else on windows have a communication error
+       c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY;
        UsbCommand resp;
        while(!ukbhit()){
        UsbCommand resp;
        while(!ukbhit()){
+               SendCommand(&c);
                if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
                        uint8_t readStatus = resp.arg[0] & 0xff;
                        uint8_t *data = resp.d.asBytes;
                if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
                        uint8_t readStatus = resp.arg[0] & 0xff;
                        uint8_t *data = resp.d.asBytes;
@@ -200,7 +220,6 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose)
                if (!loop) break;
        }
        return 0;
                if (!loop) break;
        }
        return 0;
-
 }
 
 int CmdHFiClassReader(const char *Cmd)
 }
 
 int CmdHFiClassReader(const char *Cmd)
@@ -231,163 +250,6 @@ int CmdHFiClassReader_Replay(const char *Cmd)
        return 0;
 }
 
        return 0;
 }
 
-int CmdHFiClassReader_Dump(const char *Cmd)
-{
-       uint8_t readerType = 0;
-       uint8_t MAC[4]={0x00,0x00,0x00,0x00};
-       uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-       uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-       uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-       //uint8_t CC_temp[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-       uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-       uint8_t keytable[128] = {0};
-       int elite = 0;
-       uint8_t *used_key;
-       int i;
-       if (strlen(Cmd)<1)
-       {
-               PrintAndLog("Usage:  hf iclass dump <Key> [e]");
-               PrintAndLog("        Key    - A 16 byte master key");
-               PrintAndLog("        e      - If 'e' is specified, the key is interpreted as the 16 byte");
-               PrintAndLog("                 Custom Key (KCus), which can be obtained via reader-attack");
-               PrintAndLog("                 See 'hf iclass sim 2'. This key should be on iclass-format");
-               PrintAndLog("        sample: hf iclass dump 0011223344556677");
-
-
-               return 0;
-       }
-
-       if (param_gethex(Cmd, 0, KEY, 16))
-       {
-               PrintAndLog("KEY must include 16 HEX symbols");
-               return 1;
-       }
-
-       if (param_getchar(Cmd, 1) == 'e')
-       {
-               PrintAndLog("Elite switch on");
-               elite = 1;
-
-               //calc h2
-               hash2(KEY, keytable);
-               printarr_human_readable("keytable", keytable, 128);
-
-       }
-
-       UsbCommand resp;
-       uint8_t key_sel[8] = {0};
-       uint8_t key_sel_p[8] = { 0 };
-
-       UsbCommand c = {CMD_READER_ICLASS, {0}};
-       c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
-       SendCommand(&c);
-
-
-
-       if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
-       {
-               PrintAndLog("Command execute timeout");
-               return 0;
-       }
-
-       uint8_t isOK    = resp.arg[0] & 0xff;
-       uint8_t * data  = resp.d.asBytes;
-
-       memcpy(CSN,data,8);
-       memcpy(CCNR,data+16,8);
-
-       PrintAndLog("isOk:%02x", isOK);
-
-       if(isOK > 0)
-       {
-               PrintAndLog("CSN: %s",sprint_hex(CSN,8));
-       }
-       if(isOK <= 1){
-               PrintAndLog("Failed to obtain CC! Aborting");
-               return 0;
-       }
-       //Status 2 or higher
-
-       if(elite)
-       {
-               //Get the key index (hash1)
-               uint8_t key_index[8] = {0};
-
-               hash1(CSN, key_index);
-               printvar("hash1", key_index,8);
-               for(i = 0; i < 8 ; i++)
-                       key_sel[i] = keytable[key_index[i]] & 0xFF;
-               PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
-               printvar("k_sel", key_sel,8);
-               //Permute from iclass format to standard format
-               permutekey_rev(key_sel,key_sel_p);
-               used_key = key_sel_p;
-       }else{
-               used_key = KEY;
-       }
-
-       PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
-       printvar("Used key",used_key,8);
-       diversifyKey(CSN,used_key, div_key);
-       PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
-       printvar("Div key", div_key, 8);
-       printvar("CC_NR:",CCNR,12);
-       doMAC(CCNR,div_key, MAC);
-       printvar("MAC", MAC, 4);
-
-       uint8_t iclass_data[32000] = {0};
-       uint32_t iclass_datalen = 0;
-       uint32_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete
-
-       UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
-       memcpy(d.d.asBytes, MAC, 4);
-       clearCommandBuffer();
-       SendCommand(&d);
-       PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
-       while (true) {
-               printf(".");
-               if (ukbhit()) {
-                       getchar();
-                       printf("\naborted via keyboard!\n");
-                       break;
-               }
-               if(WaitForResponseTimeout(CMD_ACK,&resp,4500))
-               {
-                       uint32_t dataLength = resp.arg[0];
-                       iclass_blocksFailed |= resp.arg[1];
-                       if(dataLength > 0)
-                       {
-                               PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
-                               memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength);
-                               iclass_datalen += dataLength;
-                       }else
-                       {//Last transfer, datalength 0 means the dump is finished
-                               PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen);
-                               if(iclass_blocksFailed)
-                               {
-                                       PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
-                               }
-                               if(iclass_datalen > 0)
-                               {
-                                       char filename[100] = {0};
-                                       //create a preferred filename
-                                       snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
-                                                        CSN[0],CSN[1],CSN[2],CSN[3],
-                                                       CSN[4],CSN[5],CSN[6],CSN[7]);
-                                       //Place the div_key in block 3
-                                       memcpy(iclass_data+(3*8), div_key, 8);
-                                       saveFile(filename,"bin",iclass_data, iclass_datalen );
-                               }
-                               //Aaaand we're finished
-                               return 0;
-                       }
-               }
-       }
-
-
-       return 0;
-}
-
 int hf_iclass_eload_usage()
 {
        PrintAndLog("Loads iclass tag-dump into emulator memory on device");
 int hf_iclass_eload_usage()
 {
        PrintAndLog("Loads iclass tag-dump into emulator memory on device");
@@ -395,7 +257,6 @@ int hf_iclass_eload_usage()
        PrintAndLog("");
        PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
        return 0;
        PrintAndLog("");
        PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
        return 0;
-
 }
 
 int iclassEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
 }
 
 int iclassEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
@@ -462,21 +323,6 @@ int CmdHFiClassELoad(const char *Cmd)
        return 0;
 }
 
        return 0;
 }
 
-int usage_hf_iclass_decrypt()
-{
-       PrintAndLog("Usage: hf iclass decrypt f <tagdump> o ");
-       PrintAndLog("");
-       PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
-       PrintAndLog("in the working directory. The file should be 16 bytes binary data");
-       PrintAndLog("");
-       PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
-       PrintAndLog("");
-       PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
-       PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
-       PrintAndLog("which is defined by the configuration block.");
-       return 1;
-}
-
 int readKeyfile(const char *filename, size_t len, uint8_t* buffer)
 {
        FILE *f = fopen(filename, "rb");
 int readKeyfile(const char *filename, size_t len, uint8_t* buffer)
 {
        FILE *f = fopen(filename, "rb");
@@ -502,6 +348,21 @@ int readKeyfile(const char *filename, size_t len, uint8_t* buffer)
        return 0;
 }
 
        return 0;
 }
 
+int usage_hf_iclass_decrypt()
+{
+       PrintAndLog("Usage: hf iclass decrypt f <tagdump> o ");
+       PrintAndLog("");
+       PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
+       PrintAndLog("in the working directory. The file should be 16 bytes binary data");
+       PrintAndLog("");
+       PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
+       PrintAndLog("");
+       PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
+       PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
+       PrintAndLog("which is defined by the configuration block.");
+       return 1;
+}
+
 int CmdHFiClassDecrypt(const char *Cmd)
 {
        uint8_t key[16] = { 0 };
 int CmdHFiClassDecrypt(const char *Cmd)
 {
        uint8_t key[16] = { 0 };
@@ -560,91 +421,987 @@ int CmdHFiClassDecrypt(const char *Cmd)
        return 0;
 }
 
        return 0;
 }
 
-int CmdHFiClass_iso14443A_write(const char *Cmd)
+int usage_hf_iclass_encrypt(){
+       PrintAndLog("Usage: hf iclass encrypt <BlockData>");
+       PrintAndLog("");
+       PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
+       PrintAndLog("in the working directory. The file should be 16 bytes binary data");
+       PrintAndLog("");
+       PrintAndLog("example: hf iclass encrypt 0102030405060708");
+       PrintAndLog("");
+       return 0;
+}
+
+int iClassEncryptBlkData(uint8_t *blkData)
 {
 {
-       uint8_t readerType = 0;
-       uint8_t MAC[4]={0x00,0x00,0x00,0x00};
-       uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-       uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-       uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
-       uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t key[16] = { 0 };
+       if(readKeyfile("iclass_decryptionkey.bin", 16, key))
+       {
+               usage_hf_iclass_encrypt();
+               return 1;
+       }
+       PrintAndLog("Decryption file found... ");
 
 
-       uint8_t blockNo=0;
-       uint8_t bldata[8]={0};
+       uint8_t decryptedData[16];
+       uint8_t *decrypted = decryptedData;
+       des3_context ctx = { DES_DECRYPT ,{ 0 } };
+       des3_set2key_enc( &ctx, key);
+       
+       des3_crypt_ecb(&ctx, blkData,decrypted);
+       //printvar("decrypted block", decrypted, 8);
+       memcpy(blkData,decrypted,8);
+
+       return 1;
+}
+
+int CmdHFiClassEncryptBlk(const char *Cmd)
+{
+       uint8_t blkData[8] = {0};
+       char opt = param_getchar(Cmd, 0);
+       if (strlen(Cmd)<1 || opt == 'h')
+               return usage_hf_iclass_encrypt();
 
 
-       if (strlen(Cmd)<3)
+       //get the bytes to encrypt
+       if (param_gethex(Cmd, 0, blkData, 16))
        {
        {
-               PrintAndLog("Usage:  hf iclass write <Key> <Block> <Data>");
-               PrintAndLog("        sample: hf iclass write 0011223344556677 10 AAAAAAAAAAAAAAAA");
+               PrintAndLog("BlockData must include 16 HEX symbols");
                return 0;
        }
                return 0;
        }
+       if (!iClassEncryptBlkData(blkData)) return 0;
 
 
-       if (param_gethex(Cmd, 0, KEY, 16))
-       {
-               PrintAndLog("KEY must include 16 HEX symbols");
-               return 1;
-       }
+       printvar("encrypted block", blkData, 8);
+       return 1;
+}
 
 
-       blockNo = param_get8(Cmd, 1);
-       if (blockNo>32)
-       {
-               PrintAndLog("Error: Maximum number of blocks is 32 for iClass 2K Cards!");
-               return 1;
-       }
-       if (param_gethex(Cmd, 2, bldata, 8))
-       {
-               PrintAndLog("Block data must include 8 HEX symbols");
-               return 1;
-       }
+void Calc_wb_mac(uint8_t blockno,uint8_t *data,uint8_t *div_key,uint8_t MAC[4]){
+       uint8_t WB[9];
+       WB[0] = blockno;
+       memcpy(WB + 1,data,8);
+       doMAC_N(WB,sizeof(WB),div_key,MAC);
+       //printf("Cal wb mac block [%02x][%02x%02x%02x%02x%02x%02x%02x%02x] : MAC [%02x%02x%02x%02x]",WB[0],WB[1],WB[2],WB[3],WB[4],WB[5],WB[6],WB[7],WB[8],MAC[0],MAC[1],MAC[2],MAC[3]);
+}
 
 
-       UsbCommand c = {CMD_ICLASS_ISO14443A_WRITE, {0}};
-       SendCommand(&c);
+static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose){
        UsbCommand resp;
 
        UsbCommand resp;
 
-       if (WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
-               uint8_t isOK    = resp.arg[0] & 0xff;
-               uint8_t * data  = resp.d.asBytes;
+       UsbCommand c = {CMD_READER_ICLASS, {0}};
+       c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
+       if (use_credit_key)
+               c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY;
 
 
-               memcpy(CSN,data,8);
-               memcpy(CCNR,data+8,8);
-               PrintAndLog("DEBUG: %s",sprint_hex(CSN,8));
-               PrintAndLog("DEBUG: %s",sprint_hex(CCNR,8));
-               PrintAndLog("isOk:%02x", isOK);
-       } else {
+       clearCommandBuffer();
+       SendCommand(&c);
+       if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
+       {
                PrintAndLog("Command execute timeout");
                PrintAndLog("Command execute timeout");
+               return false;
        }
 
        }
 
-       diversifyKey(CSN,KEY, div_key);
-
-       PrintAndLog("Div Key: %s",sprint_hex(div_key,8));
-       doMAC(CCNR, div_key, MAC);
-
-       UsbCommand c2 = {CMD_ICLASS_ISO14443A_WRITE, {readerType,blockNo}};
-       memcpy(c2.d.asBytes, bldata, 8);
-       memcpy(c2.d.asBytes+8, MAC, 4);
-       SendCommand(&c2);
-
-       if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) {
-               uint8_t isOK    = resp.arg[0] & 0xff;
-               uint8_t * data  = resp.d.asBytes;
+       uint8_t isOK = resp.arg[0] & 0xff;
+       uint8_t *data = resp.d.asBytes;
 
 
-               if (isOK)
-                       PrintAndLog("isOk:%02x data:%s", isOK, sprint_hex(data, 4));
-               else
-                       PrintAndLog("isOk:%02x", isOK);
-       } else {
-               PrintAndLog("Command execute timeout");
+       memcpy(CSN,data,8);
+       if (CCNR!=NULL)memcpy(CCNR,data+16,8);
+       //PrintAndLog("isOk:%02x", isOK);
+       if(isOK > 0)
+       {
+               if (verbose) PrintAndLog("CSN: %s",sprint_hex(CSN,8));
        }
        }
-       return 0;
+       if(isOK <= 1){
+               PrintAndLog("Failed to obtain CC! Aborting");
+               return false;
+       }
+       return true;    
 }
 }
-int CmdHFiClass_loclass(const char *Cmd)
-{
-       char opt = param_getchar(Cmd, 0);
 
 
-       if (strlen(Cmd)<1 || opt == 'h') {
-               PrintAndLog("Usage: hf iclass loclass [options]");
-               PrintAndLog("Options:");
-               PrintAndLog("h             Show this help");
+static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool use_credit_key, bool elite, bool verbose) {
+       uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t keytable[128] = {0};
+       uint8_t *used_key;
+       uint8_t key_sel[8] = {0};
+       uint8_t key_sel_p[8] = { 0 };
+
+       if (!select_only(CSN, CCNR, use_credit_key, verbose))
+               return false;
+
+       if(elite) {
+               hash2(KEY, keytable);
+               //Get the key index (hash1)
+               uint8_t key_index[8] = {0};
+               hash1(CSN, key_index);
+               //printvar("hash1", key_index,8);
+               for(uint8_t i = 0; i < 8 ; i++)
+                       key_sel[i] = keytable[key_index[i]] & 0xFF;
+               //PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
+               //printvar("k_sel", key_sel,8);
+               //Permute from iclass format to standard format
+               permutekey_rev(key_sel, key_sel_p);
+               used_key = key_sel_p;
+       } else {
+               used_key = KEY;
+       }
+       //PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
+       //printvar("Used key",KEY,8);
+       diversifyKey(CSN, used_key, div_key);
+       //PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
+       //printvar("Div key", div_key, 8);
+       //printvar("CC_NR:",CCNR,8);
+       doMAC(CCNR, div_key, MAC);
+       //printvar("MAC", MAC, 4);
+       UsbCommand resp;
+       UsbCommand d = {CMD_ICLASS_AUTHENTICATION, {0}};
+       memcpy(d.d.asBytes, MAC, 4);
+       clearCommandBuffer();
+       SendCommand(&d);
+       if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
+       {
+               PrintAndLog("Auth Command execute timeout");
+               return false;
+       }
+       uint8_t isOK = resp.arg[0] & 0xff;
+       if (!isOK) {
+               PrintAndLog("Authentication error");
+               return false;
+       }
+       return true;
+}
+
+int usage_hf_iclass_dump(){
+       PrintAndLog("Usage:  hf iclass dump f <fileName> k <Key> c <CreditKey> e\n");
+       PrintAndLog("Options:");
+       PrintAndLog("  f <filename> : specify a filename to save dump to");
+       PrintAndLog("  k <Key>      : *Access Key as 16 hex symbols or 1 hex to select key from memory");
+       PrintAndLog("  c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
+       PrintAndLog("  e            : If 'e' is specified, the key is interpreted as the 16 byte");
+       PrintAndLog("                 Custom Key (KCus), which can be obtained via reader-attack");
+       PrintAndLog("                 See 'hf iclass sim 2'. This key should be on iclass-format");
+       PrintAndLog("  NOTE: * = required");
+  PrintAndLog("Samples:");
+       PrintAndLog("  hf iclass dump k 001122334455667B");
+       PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
+       PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA e");
+       return 0;
+}
+
+int CmdHFiClassReader_Dump(const char *Cmd){
+
+       uint8_t MAC[4] = {0x00,0x00,0x00,0x00};
+       uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t c_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t blockno = 0;
+       uint8_t numblks = 0;
+       uint8_t maxBlk = 32;
+       uint8_t KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t CreditKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t keyNbr = 0;
+       uint8_t dataLen = 0;
+       uint8_t fileNameLen = 0;
+       char filename[FILE_PATH_SIZE]={0};
+       char tempStr[50] = {0};
+       bool have_credit_key = false;
+       bool elite = false;
+       bool errors = false;
+       uint8_t cmdp = 0;
+
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+               case 'h':
+               case 'H':
+                       return usage_hf_iclass_dump();
+               case 'c':
+               case 'C':
+                       have_credit_key = true;
+                       dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+                       if (dataLen == 16) {
+                               errors = param_gethex(tempStr, 0, CreditKEY, dataLen);
+                       } else if (dataLen == 1) {
+                               keyNbr = param_get8(Cmd, cmdp+1);
+                               if (keyNbr <= ICLASS_KEYS_MAX) {
+                                       memcpy(CreditKEY, iClass_Key_Table[keyNbr], 8);
+                               } else {
+                                       PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
+                                       errors = true;
+                               }
+                       } else {
+                               PrintAndLog("\nERROR: Credit Key is incorrect length\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'e':
+               case 'E':
+                       elite = true;
+                       cmdp++;
+                       break;
+               case 'f':
+               case 'F':
+                       fileNameLen = param_getstr(Cmd, cmdp+1, filename); 
+                       if (fileNameLen < 1) {
+                               PrintAndLog("No filename found after f");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'k':
+               case 'K':
+                       dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+                       if (dataLen == 16) { 
+                               errors = param_gethex(tempStr, 0, KEY, dataLen);
+                       } else if (dataLen == 1) {
+                               keyNbr = param_get8(Cmd, cmdp+1);
+                               if (keyNbr <= ICLASS_KEYS_MAX) {
+                                       memcpy(KEY, iClass_Key_Table[keyNbr], 8);
+                               } else {
+                                       PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
+                                       errors = true;
+                               }
+                       } else {
+                               PrintAndLog("\nERROR: Credit Key is incorrect length\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
+                       errors = true;
+                       break;
+               }
+               if(errors) return usage_hf_iclass_dump();
+       }
+
+       if (cmdp < 2) return usage_hf_iclass_dump();
+
+       //get config and first 3 blocks
+       UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN |
+                                       FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY}};
+       UsbCommand resp;
+       uint8_t tag_data[255*8];
+       clearCommandBuffer();
+       SendCommand(&c);
+       if (WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
+               uint8_t readStatus = resp.arg[0] & 0xff;
+               uint8_t *data = resp.d.asBytes;
+
+               if( readStatus == 0){
+                       //Aborted
+                       PrintAndLog("No tag found...");
+                       return 0;
+               }
+               if( readStatus & (FLAG_ICLASS_READER_CSN|FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_CC)){
+                       memcpy(tag_data, data, 8*3);
+                       /*for (; blockno < 3; blockno++) {
+                               PrintAndLog("     | %02X | %02X%02X%02X%02X%02X%02X%02X%02X |", blockno,
+                                       data[(blockno*8)+0],data[(blockno*8)+1],data[(blockno*8)+2],data[(blockno*8)+3],
+                                       data[(blockno*8)+4],data[(blockno*8)+5],data[(blockno*8)+6],data[(blockno*8)+7]);
+                       }*/
+                       blockno+=2;
+                       numblks = data[8];
+
+                       if (data[13] & 0x80) {
+                               // large memory - not able to dump pages currently
+                               maxBlk = 255;
+                       }       else {
+                               maxBlk = 32;
+                       }
+                       //PrintAndLog("maxBlk: %02X",maxBlk);
+               }
+       } else {
+               PrintAndLog("Command execute timeout");
+               return 0;
+       }
+
+       if (!select_and_auth(KEY, MAC, div_key, false, elite, false)){
+               //try twice - for some reason it sometimes fails the first time...
+               if (!select_and_auth(KEY, MAC, div_key, false, elite, false)){
+                       ul_switch_off_field();
+                       return 0;
+               }
+       }
+       //print debit div_key
+       //PrintAndLog("     | 03 | %02X%02X%02X%02X%02X%02X%02X%02X |",
+       //      div_key[0],div_key[1],div_key[2],div_key[3],
+       //      div_key[4],div_key[5],div_key[6],div_key[7]);
+       
+       if (have_credit_key){
+               //turn off hf field
+               //PrintAndLog("attempt 1 to auth with credit key");
+               ul_switch_off_field();
+               memset(c_div_key,0,8);
+               memset(MAC,0,4);
+               if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false)){
+                       //try twice - for some reason it sometimes fails the first time...
+                       memset(c_div_key,0,8);
+                       memset(MAC,0,4);
+                       if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false)){
+                               ul_switch_off_field();
+                               return 0;
+                       }
+               }
+               //print credit div_key
+               //PrintAndLog("     | 04 | %02X%02X%02X%02X%02X%02X%02X%02X |",
+               //      div_key[0],div_key[1],div_key[2],div_key[3],
+               //      div_key[4],div_key[5],div_key[6],div_key[7]);
+       
+               //turn off hf field
+               //PrintAndLog("attempt 2 to auth with debit key");
+               ul_switch_off_field();
+               memset(div_key,0,8);
+               memset(MAC,0,4);
+               if (!select_and_auth(KEY, MAC, div_key, false, elite, false)){
+                       //try twice - for some reason it sometimes fails the first time...
+                       if (!select_and_auth(KEY, MAC, div_key, false, elite, false)){
+                               ul_switch_off_field();
+                               return 0;
+                       }
+               }
+       }
+       //PrintAndLog("have %d blocks",blockno);
+
+       UsbCommand w = {CMD_ICLASS_DUMP, {blockno, numblks-blockno+1, 0x88}};
+       clearCommandBuffer();
+       SendCommand(&w);
+       if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
+               PrintAndLog("Command execute time-out 1");
+               return 1;
+       }
+       uint32_t blocksRead = resp.arg[1];
+       uint8_t isOK = resp.arg[0] & 0xff;
+       if (!isOK && !blocksRead) {
+               PrintAndLog("Read Block Failed");
+               return 0;
+       }
+       uint32_t startindex = resp.arg[2];
+       if (blocksRead*8 > sizeof(tag_data)-(blockno*8)) {
+               PrintAndLog("Data exceeded Buffer size!");
+               blocksRead = (sizeof(tag_data)/8) - blockno;
+       }
+       //PrintAndLog("blocksread: %d, blockno: %d, startindex: %x",blocksRead,blockno,startindex);
+       GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex);
+       WaitForResponse(CMD_ACK,NULL);
+       uint32_t gotBytes = blocksRead*8 + blockno*8;
+
+       //PrintAndLog("have %d blocks",gotBytes/8);
+       
+       if (have_credit_key && maxBlk > blockno+numblks+1) {
+               //turn off hf field
+               ul_switch_off_field();
+               //PrintAndLog("attempt 2 to auth with credit key");
+               memset(c_div_key,0,8);
+               memset(MAC,0,4);
+               if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false)){
+                       //try twice - for some reason it sometimes fails the first time...
+                       if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false)){
+                               ul_switch_off_field();
+                               return 0;
+                       }
+               }
+               w.arg[0] = blockno + blocksRead;
+               w.arg[1] = maxBlk - (blockno + blocksRead);
+               w.arg[2] = 0x18;
+               clearCommandBuffer();
+               SendCommand(&w);
+               if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
+                       PrintAndLog("Command execute timeout 2");
+                       return 0;
+               }
+               uint8_t isOK = resp.arg[0] & 0xff;
+               blocksRead = resp.arg[1];
+               if (!isOK && !blocksRead) {
+                       PrintAndLog("Read Block Failed 2");
+                       return 0;
+               }               
+
+               startindex = resp.arg[2];
+               if (blocksRead*8 > sizeof(tag_data)-gotBytes) {
+                       PrintAndLog("Data exceeded Buffer size!");
+                       blocksRead = (sizeof(tag_data) - gotBytes)/8;
+               }
+               GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex);
+               WaitForResponse(CMD_ACK,NULL);
+
+               gotBytes += blocksRead*8;
+               //PrintAndLog("have %d blocks",gotBytes/8);
+       }
+
+       memcpy(tag_data+(3*8),div_key,8);
+       memcpy(tag_data+(4*8),c_div_key,8);
+
+       for (blockno = 0; blockno < gotBytes/8; blockno++){
+               PrintAndLog("     | %02X | %02X%02X%02X%02X%02X%02X%02X%02X |", blockno,
+                       tag_data[(blockno*8)+0],tag_data[(blockno*8)+1],tag_data[(blockno*8)+2],tag_data[(blockno*8)+3],
+                       tag_data[(blockno*8)+4],tag_data[(blockno*8)+5],tag_data[(blockno*8)+6],tag_data[(blockno*8)+7]);
+       }
+       if (filename[0] == 0){
+               snprintf(filename, FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
+                   tag_data[0],tag_data[1],tag_data[2],tag_data[3],
+                   tag_data[4],tag_data[5],tag_data[6],tag_data[7]);
+       }
+       saveFile(filename,"bin",tag_data, gotBytes );
+       PrintAndLog("Saving dump file - %d blocks read", gotBytes/8);
+       return 1;
+}
+
+/*
+int CmdHFiClassReader_Dump(const char *Cmd)
+{
+       uint8_t readerType = 0;
+       uint8_t MAC[4]={0x00,0x00,0x00,0x00};
+       uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t keytable[128] = {0};
+       bool elite = false;
+       bool use_credit_key = false;
+       uint8_t *used_key;
+       int i;
+       if (strlen(Cmd) < 1)
+       {
+               return usage_hf_iclass_dump();
+       }
+
+       if (param_gethex(Cmd, 0, KEY, 16))
+       {
+               PrintAndLog("KEY must include 16 HEX symbols");
+               return 1;
+       }
+
+       if (param_getchar(Cmd, 1) == 'e')
+       {
+               PrintAndLog("Elite switch on");
+               elite = true;
+
+               //calc h2
+               hash2(KEY, keytable);
+               printarr_human_readable("keytable", keytable, 128);
+
+               if (param_getchar(Cmd, 2) == 'c')
+                       use_credit_key = true;
+       } else if (param_getchar(Cmd, 1) == 'c'){
+               use_credit_key = true;          
+       }
+
+       UsbCommand resp;
+       uint8_t key_sel[8] = {0};
+       uint8_t key_sel_p[8] = { 0 };
+
+       UsbCommand c = {CMD_READER_ICLASS, {0}};
+       c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
+       if (use_credit_key)
+               c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY;
+       clearCommandBuffer();
+       SendCommand(&c);
+
+       if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
+       {
+               PrintAndLog("Command execute timeout");
+               return 0;
+       }
+
+       uint8_t isOK    = resp.arg[0] & 0xff;
+       uint8_t * data  = resp.d.asBytes;
+
+       memcpy(CSN,data,8);
+       memcpy(CCNR,data+16,8);
+
+       PrintAndLog("isOk:%02x", isOK);
+
+       if(isOK > 0)
+       {
+               PrintAndLog("CSN: %s",sprint_hex(CSN,8));
+       }
+       if(isOK <= 1){
+               PrintAndLog("Failed to obtain CC! Aborting");
+               return 0;
+       }
+       //Status 2 or higher
+
+       if(elite)
+       {
+               //Get the key index (hash1)
+               uint8_t key_index[8] = {0};
+
+               hash1(CSN, key_index);
+               printvar("hash1", key_index,8);
+               for(i = 0; i < 8 ; i++)
+                       key_sel[i] = keytable[key_index[i]] & 0xFF;
+               PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
+               printvar("k_sel", key_sel,8);
+               //Permute from iclass format to standard format
+               permutekey_rev(key_sel,key_sel_p);
+               used_key = key_sel_p;
+       }else{
+               used_key = KEY;
+       }
+
+       PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
+       printvar("Used key",used_key,8);
+       diversifyKey(CSN,used_key, div_key);
+       PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
+       printvar("Div key", div_key, 8);
+       printvar("CC_NR:",CCNR,12);
+       doMAC(CCNR,div_key, MAC);
+       printvar("MAC", MAC, 4);
+
+       uint8_t iclass_data[32000] = {0};
+       uint32_t iclass_datalen = 0;
+       uint32_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete
+
+       UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
+       memcpy(d.d.asBytes, MAC, 4);
+       clearCommandBuffer();
+       SendCommand(&d);
+       PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
+       while (true) {
+               printf(".");
+               if (ukbhit()) {
+                       getchar();
+                       printf("\naborted via keyboard!\n");
+                       break;
+               }
+               if(WaitForResponseTimeout(CMD_ACK,&resp,4500))
+               {
+                       uint32_t dataLength = resp.arg[0];
+                       iclass_blocksFailed |= resp.arg[1];
+                       if(dataLength > 0)
+                       {
+                               PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
+                               memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength);
+                               iclass_datalen += dataLength;
+                       }else
+                       {//Last transfer, datalength 0 means the dump is finished
+                               PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen);
+                               if(iclass_blocksFailed)
+                               {
+                                       PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
+                               }
+                               if(iclass_datalen > 0)
+                               {
+                                       char filename[100] = {0};
+                                       //create a preferred filename
+                                       snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
+                                                        CSN[0],CSN[1],CSN[2],CSN[3],
+                                                       CSN[4],CSN[5],CSN[6],CSN[7]);
+                                       //Place the div_key in block 3
+                                       memcpy(iclass_data+(3*8), div_key, 8);
+                                       saveFile(filename,"bin",iclass_data, iclass_datalen );
+                               }
+                               //Aaaand we're finished
+                               return 0;
+                       }
+               }
+       }
+       return 0;
+}
+*/
+
+int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool verbose){
+       uint8_t MAC[4]={0x00,0x00,0x00,0x00};
+       uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t keyType = (use_credit_key) ? 0x18 : 0x88;
+       if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, verbose))
+               return 0;
+
+       UsbCommand resp;
+
+       Calc_wb_mac(blockno,bldata,div_key,MAC);
+       UsbCommand w = {CMD_ICLASS_WRITEBLOCK, {blockno, keyType}};
+       memcpy(w.d.asBytes, bldata, 8);
+       memcpy(w.d.asBytes + 8,MAC, 4);
+       
+       clearCommandBuffer();
+       SendCommand(&w);
+       if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
+       {
+               PrintAndLog("Write Command execute timeout");
+               return 0;
+       }
+       uint8_t isOK = resp.arg[0] & 0xff;
+       if (!isOK) {
+               PrintAndLog("Write Block Failed");
+               return 0;
+       }
+       PrintAndLog("Write Block Successful");
+
+       return 1;
+}
+
+int usage_hf_iclass_writeblock() {
+       PrintAndLog("Options:");
+  PrintAndLog("  b <Block> : The block number as 2 hex symbols");
+  PrintAndLog("  d <data>  : Set the Data to write as 16 hex symbols");
+       PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory");
+  PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n");
+  PrintAndLog("  e         : If 'e' is specified, elite computations applied to key");
+  PrintAndLog("Samples:");
+       PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
+       PrintAndLog("  hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
+       PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
+       return 0;
+}
+
+int CmdHFiClass_WriteBlock(const char *Cmd) {
+       uint8_t blockno=0;
+       uint8_t bldata[8]={0};
+       uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t keyNbr = 0;
+       uint8_t dataLen = 0;
+       char tempStr[50] = {0};
+       bool use_credit_key = false;
+       bool elite = false;
+       bool errors = false;
+       uint8_t cmdp = 0;
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+               case 'h':
+               case 'H':
+                       return usage_hf_iclass_writeblock();
+               case 'b':
+               case 'B':
+                       if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
+                               PrintAndLog("Block No must include 2 HEX symbols\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'c':
+               case 'C':
+                       use_credit_key = true;
+                       cmdp++;
+                       break;
+               case 'd':
+               case 'D':
+                       if (param_gethex(Cmd, cmdp+1, bldata, 16))
+                       {
+                               PrintAndLog("KEY must include 16 HEX symbols\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'e':
+               case 'E':
+                       elite = true;
+                       cmdp++;
+                       break;
+               case 'k':
+               case 'K':
+                       dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+                       if (dataLen == 16) { 
+                               errors = param_gethex(tempStr, 0, KEY, dataLen);
+                       } else if (dataLen == 1) {
+                               keyNbr = param_get8(Cmd, cmdp+1);
+                               if (keyNbr <= ICLASS_KEYS_MAX) {
+                                       memcpy(KEY, iClass_Key_Table[keyNbr], 8);
+                               } else {
+                                       PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
+                                       errors = true;
+                               }
+                       } else {
+                               PrintAndLog("\nERROR: Credit Key is incorrect length\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
+                       errors = true;
+                       break;
+               }
+               if(errors) return usage_hf_iclass_writeblock();
+       }
+
+       if (cmdp < 6) return usage_hf_iclass_writeblock();
+
+       return WriteBlock(blockno, bldata, KEY, use_credit_key, elite, true);
+}
+
+int usage_hf_iclass_clone() {
+       PrintAndLog("Usage:  hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> e c");
+       PrintAndLog("Options:");
+       PrintAndLog("  f <filename>: specify a filename to clone from");
+       PrintAndLog("  b <Block>   : The first block to clone as 2 hex symbols");
+       PrintAndLog("  l <Last Blk>: Set the Data to write as 16 hex symbols");
+       PrintAndLog("  k <Key>     : Access Key as 16 hex symbols or 1 hex to select key from memory");
+       PrintAndLog("  c           : If 'c' is specified, the key set is assumed to be the credit key\n");
+       PrintAndLog("  e           : If 'e' is specified, elite computations applied to key");
+       PrintAndLog("Samples:");
+       PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
+       PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
+       PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
+       return -1;
+}
+
+int CmdHFiClassCloneTag(const char *Cmd) {
+       char filename[FILE_PATH_SIZE];
+       char tempStr[50]={0};
+       uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t keyNbr = 0;
+       uint8_t fileNameLen = 0;
+       uint8_t startblock = 0;
+       uint8_t endblock = 0;
+       uint8_t dataLen = 0;
+       bool use_credit_key = false;
+       bool elite = false;
+       bool errors = false;
+       uint8_t cmdp = 0;
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+               case 'h':
+               case 'H':
+                       return usage_hf_iclass_clone();
+               case 'b':
+               case 'B':
+                       if (param_gethex(Cmd, cmdp+1, &startblock, 2)) {
+                               PrintAndLog("Start Block No must include 2 HEX symbols\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'c':
+               case 'C':
+                       use_credit_key = true;
+                       cmdp++;
+                       break;
+               case 'e':
+               case 'E':
+                       elite = true;
+                       cmdp++;
+                       break;
+               case 'f':
+               case 'F':
+                       fileNameLen = param_getstr(Cmd, cmdp+1, filename); 
+                       if (fileNameLen < 1) {
+                               PrintAndLog("No filename found after f");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'k':
+               case 'K':
+                       dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+                       if (dataLen == 16) { 
+                               errors = param_gethex(tempStr, 0, KEY, dataLen);
+                       } else if (dataLen == 1) {
+                               keyNbr = param_get8(Cmd, cmdp+1);
+                               if (keyNbr <= ICLASS_KEYS_MAX) {
+                                       memcpy(KEY, iClass_Key_Table[keyNbr], 8);
+                               } else {
+                                       PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
+                                       errors = true;
+                               }
+                       } else {
+                               PrintAndLog("\nERROR: Credit Key is incorrect length\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'l':
+               case 'L':
+                       if (param_gethex(Cmd, cmdp+1, &endblock, 2)) {
+                               PrintAndLog("Start Block No must include 2 HEX symbols\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
+                       errors = true;
+                       break;
+               }
+               if(errors) return usage_hf_iclass_clone();
+       }
+
+       if (cmdp < 8) return usage_hf_iclass_clone();
+
+       FILE *f;
+
+       iclass_block_t tag_data[USB_CMD_DATA_SIZE/12];
+
+       if ((endblock-startblock+1)*12 > USB_CMD_DATA_SIZE) {
+               PrintAndLog("Trying to write too many blocks at once.  Max: %d", USB_CMD_DATA_SIZE/8);
+       }
+       // file handling and reading
+       f = fopen(filename,"rb");
+       if(!f) {
+               PrintAndLog("Failed to read from file '%s'", filename);
+               return 1;
+       }
+
+       if (startblock<5) {
+               PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
+               return 0;
+       }
+       // now read data from the file from block 6 --- 19
+       // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
+       // then copy to usbcommand->asbytes; the max is 32 - 6 = 24 block 12 bytes each block 288 bytes then we can only accept to clone 21 blocks at the time,
+       // else we have to create a share memory
+       int i;
+       fseek(f,startblock*8,SEEK_SET);
+       fread(tag_data,sizeof(iclass_block_t),endblock - startblock + 1,f);
+       /*
+       for (i = 0; i < endblock - startblock+1; i++){
+               printf("block [%02x] [%02x%02x%02x%02x%02x%02x%02x%02x]\n",i + startblock,tag_data[i].d[0],tag_data[i].d[1],tag_data[i].d[2],tag_data[i].d[3],tag_data[i].d[4],tag_data[i].d[5],tag_data[i].d[6],tag_data[i].d[7]);
+       }*/
+
+       uint8_t MAC[4]={0x00,0x00,0x00,0x00};
+       uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+       if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, true))
+               return 0;
+
+       UsbCommand w = {CMD_ICLASS_CLONE,{startblock,endblock,((use_credit_key) ? 0x18 : 0x88)}};
+       uint8_t *ptr;
+       // calculate all mac for every the block we will write
+       for (i = startblock; i <= endblock; i++){
+           Calc_wb_mac(i,tag_data[i - startblock].d,div_key,MAC);
+           // usb command d start pointer = d + (i - 6) * 12
+           // memcpy(pointer,tag_data[i - 6],8) 8 bytes
+           // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
+           // next one
+           ptr = w.d.asBytes + (i - startblock) * 12;
+           memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
+           memcpy(ptr + 8,MAC, 4);
+       }
+       uint8_t p[12];
+       for (i = 0; i <= endblock - startblock;i++){
+           memcpy(p,w.d.asBytes + (i * 12),12);
+           printf("block [%02x]",i + startblock);
+           printf(" [%02x%02x%02x%02x%02x%02x%02x%02x]",p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7]);
+           printf(" MAC [%02x%02x%02x%02x]\n",p[8],p[9],p[10],p[11]);
+       }
+       UsbCommand resp;
+       SendCommand(&w);
+       if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
+       {
+               PrintAndLog("Command execute timeout");
+               return 0;
+       }
+       return 1;
+}
+
+int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool verbose){
+       uint8_t MAC[4]={0x00,0x00,0x00,0x00};
+       uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+       if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, verbose))
+               return 0;
+
+       UsbCommand resp;
+       UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno, keyType}};
+       clearCommandBuffer();
+       SendCommand(&w);
+       if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
+       {
+               PrintAndLog("Command execute timeout");
+               return 0;
+       }
+       uint8_t isOK = resp.arg[0] & 0xff;
+       if (!isOK) {
+               PrintAndLog("Read Block Failed");
+               return 0;
+       }
+       //data read is stored in: resp.d.asBytes[0-15]
+       if (verbose) PrintAndLog("Block %02X: %s\n",blockno, sprint_hex(resp.d.asBytes,8));
+       return 1;
+}
+
+int usage_hf_iclass_readblock(){
+       PrintAndLog("Usage:  hf iclass readblk b <Block> k <Key> c e\n");
+       PrintAndLog("Options:");
+  PrintAndLog("  b <Block> : The block number as 2 hex symbols");
+       PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory");
+  PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n");
+  PrintAndLog("  e         : If 'e' is specified, elite computations applied to key");
+  PrintAndLog("Samples:");
+       PrintAndLog("  hf iclass readblk b 06 k 0011223344556677");
+       PrintAndLog("  hf iclass readblk b 1B k 0011223344556677 c");
+       PrintAndLog("  hf iclass readblk b 0A k 0");
+       return 0;
+}
+
+int CmdHFiClass_ReadBlock(const char *Cmd)
+{
+       uint8_t blockno=0;
+       uint8_t keyType = 0x88; //debit key
+       uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t keyNbr = 0;
+       uint8_t dataLen = 0;
+       char tempStr[50] = {0};
+       bool elite = false;
+       bool errors = false;
+       uint8_t cmdp = 0;
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+               case 'h':
+               case 'H':
+                       return usage_hf_iclass_readblock();
+               case 'b':
+               case 'B':
+                       if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
+                               PrintAndLog("Block No must include 2 HEX symbols\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'c':
+               case 'C':
+                       keyType = 0x18;
+                       cmdp++;
+                       break;
+               case 'e':
+               case 'E':
+                       elite = true;
+                       cmdp++;
+                       break;
+               case 'k':
+               case 'K':
+                       dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+                       if (dataLen == 16) { 
+                               errors = param_gethex(tempStr, 0, KEY, dataLen);
+                       } else if (dataLen == 1) {
+                               keyNbr = param_get8(Cmd, cmdp+1);
+                               if (keyNbr <= ICLASS_KEYS_MAX) {
+                                       memcpy(KEY, iClass_Key_Table[keyNbr], 8);
+                               } else {
+                                       PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
+                                       errors = true;
+                               }
+                       } else {
+                               PrintAndLog("\nERROR: Credit Key is incorrect length\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
+                       errors = true;
+                       break;
+               }
+               if(errors) return usage_hf_iclass_readblock();
+       }
+
+       if (cmdp < 4) return usage_hf_iclass_readblock();
+       
+       return ReadBlock(KEY, blockno, keyType, elite, true);
+}
+
+int CmdHFiClass_loclass(const char *Cmd)
+{
+       char opt = param_getchar(Cmd, 0);
+
+       if (strlen(Cmd)<1 || opt == 'h') {
+               PrintAndLog("Usage: hf iclass loclass [options]");
+               PrintAndLog("Options:");
+               PrintAndLog("h             Show this help");
                PrintAndLog("t             Perform self-test");
                PrintAndLog("f <filename>  Bruteforce iclass dumpfile");
                PrintAndLog("                   An iclass dumpfile is assumed to consist of an arbitrary number of");
                PrintAndLog("t             Perform self-test");
                PrintAndLog("f <filename>  Bruteforce iclass dumpfile");
                PrintAndLog("                   An iclass dumpfile is assumed to consist of an arbitrary number of");
@@ -683,19 +1440,350 @@ int CmdHFiClass_loclass(const char *Cmd)
        return 0;
 }
 
        return 0;
 }
 
+int usage_hf_iclass_readtagfile(){
+       PrintAndLog("Usage: hf iclass readtagfile <filename>");
+       return 1;
+}
+
+void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize){
+       uint8_t blockdata[8];
+       uint8_t mem_config;
+       memcpy(&mem_config, iclass_dump + 13,1);
+       uint8_t maxmemcount;
+       uint8_t filemaxblock = filesize / 8;
+       if (mem_config == 0x80)
+               maxmemcount = 255;
+       else
+               maxmemcount = 32;
+
+       if (startblock == 0)
+               startblock = 6;
+       if ((endblock > maxmemcount) || (endblock == 0))
+               endblock = maxmemcount;
+       if (endblock > filemaxblock)
+               endblock = filemaxblock;
+       int i = startblock;
+       int j;
+       while (i < endblock){
+               printf("block[%02X]: ",i);
+               memcpy(blockdata,iclass_dump + (i * 8),8);
+               for (j = 0;j < 8;j++)
+                       printf("%02X ",blockdata[j]);
+               printf("\n");
+               i++;
+       }
+       if ((i < filemaxblock) && (i < maxmemcount)){
+               printf("block[%02X]: ",i);
+               memcpy(blockdata,iclass_dump + (i * 8),8);
+               for (j = 0;j < 8;j++)
+                       printf("%02X",blockdata[j]);
+               printf("\n");
+       }
+}
+
+int CmdHFiClassReadTagFile(const char *Cmd)
+{
+       int startblock = 0;
+       int endblock = 0;
+       char tempnum[5];
+       FILE *f;
+       char filename[FILE_PATH_SIZE];
+       if (param_getstr(Cmd, 0, filename) < 1)
+               return usage_hf_iclass_readtagfile();
+       if (param_getstr(Cmd,1,(char *)&tempnum) < 1)
+               startblock = 0;
+       else
+               sscanf(tempnum,"%d",&startblock);
+
+       if (param_getstr(Cmd,2,(char *)&tempnum) < 1)
+               endblock = 0;
+       else
+               sscanf(tempnum,"%d",&endblock);
+       // file handling and reading
+       f = fopen(filename,"rb");
+       if(!f) {
+               PrintAndLog("Failed to read from file '%s'", filename);
+               return 1;
+       }
+       fseek(f, 0, SEEK_END);
+       long fsize = ftell(f);
+       fseek(f, 0, SEEK_SET);
+
+       uint8_t *dump = malloc(fsize);
+
+
+       size_t bytes_read = fread(dump, 1, fsize, f);
+       fclose(f);
+       uint8_t *csn = dump;
+       printf("CSN :     %02X %02X %02X %02X %02X %02X %02X %02X\n",csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7]);
+       //    printIclassDumpInfo(dump);
+       printIclassDumpContents(dump,startblock,endblock,bytes_read);
+       free(dump);
+       return 0;
+}
+
+uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv){
+       uint64_t new_div = 0x00;
+       new_div ^= sdiv;
+       new_div ^= hdiv;
+       return new_div;
+}
+
+uint64_t hexarray_to_uint64(uint8_t *key){
+       char temp[17];
+       uint64_t uint_key;
+       for (int i = 0;i < 8;i++)
+               sprintf(&temp[(i *2)],"%02X",key[i]);
+       temp[16] = '\0';
+       if (sscanf(temp,"%016"llX,&uint_key) < 1)
+               return 0;
+       return uint_key;
+}
+
+int usage_hf_iclass_calc_ekey(){
+       PrintAndLog("Usage: hf iclass calc_ekey <STDKEY> <ELITE key> [c]");
+       return 1;
+}
+
+int CmdHFiClassCalcEKey(const char *Cmd){
+       uint8_t STDKEY[8];
+       uint8_t ELITEKEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t std_div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t elite_div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+       uint8_t keytable[128] = {0};
+       uint8_t key_index[8] = {0};
+       uint64_t new_div_key;
+       uint64_t i_elite_div_key;
+       uint64_t i_std_div_key;
+       bool use_credit_key = false;
+       //memcpy(STDKEY,GLOBAL_KEY,sizeof(STDKEY));
+       int i;
+       if (strlen(Cmd) < 2)
+               return usage_hf_iclass_calc_ekey();
+
+       if (param_gethex(Cmd, 0, STDKEY, 16))
+               return usage_hf_iclass_calc_ekey();
+
+       if (param_gethex(Cmd, 1, ELITEKEY, 16) != 0)
+               return usage_hf_iclass_calc_ekey();
+
+       if (param_getchar(Cmd, 2)=='c')
+               use_credit_key = true;
+
+       hash2(ELITEKEY, keytable);
+
+       uint8_t key_sel[8] = { 0 };
+       uint8_t key_sel_p[8] = { 0 };
+
+       if (!select_only(CSN, CCNR, use_credit_key, true))
+               return 0;
+
+       diversifyKey(CSN, STDKEY, std_div_key);
+
+       //    printvar("(S)Div key", std_div_key, 8);
+       hash1(CSN, key_index);
+       for(i = 0; i < 8 ; i++)
+               key_sel[i] = keytable[key_index[i]] & 0xFF;
+
+       //Permute from iclass format to standard format
+       permutekey_rev(key_sel, key_sel_p);
+       diversifyKey(CSN, key_sel_p, elite_div_key);
+       //    printvar("(E)Div key", elite_div_key, 8);
+       i_elite_div_key = hexarray_to_uint64(elite_div_key);
+       i_std_div_key = hexarray_to_uint64(std_div_key);
+       new_div_key = xorcheck(i_std_div_key, i_elite_div_key);
+       printf("New Div Key : %016"llX"\n",new_div_key);
+       return 0;
+}
+
+int loadKeys(char *filename){
+       FILE *f;
+       f = fopen(filename,"rb");
+       if(!f) {
+               PrintAndLog("Failed to read from file '%s'", filename);
+               return 0;
+       }
+       fseek(f, 0, SEEK_END);
+       long fsize = ftell(f);
+       fseek(f, 0, SEEK_SET);
+
+       uint8_t *dump = malloc(fsize);
+
+       size_t bytes_read = fread(dump, 1, fsize, f);
+       fclose(f);
+       if (bytes_read > ICLASS_KEYS_MAX * 8){
+               PrintAndLog("File is too long to load - bytes: %u", bytes_read);
+               free(dump);
+               return 0;
+       }
+       uint8_t i = 0;
+       for (; i < bytes_read/8; i++){
+               memcpy(iClass_Key_Table[i],dump+(i*8),8);
+       }
+       free(dump);
+       PrintAndLog("%u keys loaded", i);
+       return 1;
+}
+
+int saveKeys(char *filename){
+       FILE *f;
+       f = fopen(filename,"wb");
+       if (f == NULL) {
+               printf("error opening file %s\n",filename);
+               return 0;
+       }
+       for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
+               if (fwrite(iClass_Key_Table[i],8,1,f) != 1){
+                       PrintAndLog("save key failed to write to file: %s", filename);
+                       break;
+               }
+       }
+       fclose(f);
+       return 0;
+}
+
+int printKeys(){
+       PrintAndLog("");
+       for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
+               PrintAndLog("%u: %s",i,sprint_hex(iClass_Key_Table[i],8));
+       }
+       PrintAndLog("");        
+       return 0;
+}
+
+int usage_hf_iclass_managekeys(){
+       PrintAndLog("HELP :  Manage iClass Keys in client memory:\n");
+       PrintAndLog("Usage:  hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
+       PrintAndLog("  Options:");
+       PrintAndLog("  n <keynbr>  : specify the keyNbr to set in memory");
+       PrintAndLog("  k <key>     : set a key in memory");
+       PrintAndLog("  f <filename>: specify a filename to use with load or save operations");
+       PrintAndLog("  s           : save keys in memory to file specified by filename");
+       PrintAndLog("  l           : load keys to memory from file specified by filename");
+       PrintAndLog("  p           : print keys loaded into memory\n");
+       PrintAndLog("Samples:");
+       PrintAndLog(" set key      : hf iclass managekeys n 0 k 1122334455667788");
+       PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
+       PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
+       PrintAndLog(" print keys   : hf iclass managekeys p\n");
+       return 0;
+}
+
+int CmdManageKeys(const char *Cmd){
+       uint8_t keyNbr = 0;
+       uint8_t dataLen = 0;
+       uint8_t KEY[8] = {0};
+       char filename[FILE_PATH_SIZE];
+       uint8_t fileNameLen = 0;
+       bool errors = false;
+       uint8_t operation = 0;
+       char tempStr[20];
+       uint8_t cmdp = 0;
+
+       while(param_getchar(Cmd, cmdp) != 0x00)
+       {
+               switch(param_getchar(Cmd, cmdp))
+               {
+               case 'h':
+               case 'H':
+                       return usage_hf_iclass_managekeys();
+               case 'f':
+               case 'F':
+                       fileNameLen = param_getstr(Cmd, cmdp+1, filename); 
+                       if (fileNameLen < 1) {
+                               PrintAndLog("No filename found after f");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'n':
+               case 'N':
+                       keyNbr = param_get8(Cmd, cmdp+1);
+                       if (keyNbr < 0) {
+                               PrintAndLog("Wrong block number");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'k':
+               case 'K':
+                       operation += 3; //set key 
+                       dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+                       if (dataLen == 16) { //ul-c or ev1/ntag key length
+                               errors = param_gethex(tempStr, 0, KEY, dataLen);
+                       } else {
+                               PrintAndLog("\nERROR: Key is incorrect length\n");
+                               errors = true;
+                       }
+                       cmdp += 2;
+                       break;
+               case 'p':
+               case 'P':
+                       operation += 4; //print keys in memory
+                       cmdp++;
+                       break;
+               case 'l':
+               case 'L':
+                       operation += 5; //load keys from file
+                       cmdp++;
+                       break;
+               case 's':
+               case 'S':
+                       operation += 6; //save keys to file
+                       cmdp++;
+                       break;
+               default:
+                       PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
+                       errors = true;
+                       break;
+               }
+               if(errors) return usage_hf_iclass_managekeys();
+       }
+       if (operation == 0){
+               PrintAndLog("no operation specified (load, save, or print)\n");
+               return usage_hf_iclass_managekeys();
+       }
+       if (operation > 6){
+               PrintAndLog("Too many operations specified\n");
+               return usage_hf_iclass_managekeys();
+       }
+       if (operation > 4 && fileNameLen == 0){
+               PrintAndLog("You must enter a filename when loading or saving\n");
+               return usage_hf_iclass_managekeys();
+       }
+
+       switch (operation){
+               case 3: memcpy(iClass_Key_Table[keyNbr], KEY, 8); return 1;
+               case 4: return printKeys();
+               case 5: return loadKeys(filename);
+               case 6: return saveKeys(filename);
+               break;
+       }
+       return 0;
+}
+
 static command_t CommandTable[] = 
 {
 static command_t CommandTable[] = 
 {
-       {"help",        CmdHelp,                        1,      "This help"},
-       {"list",        CmdHFiClassList,        0,      "[Deprecated] List iClass history"},
-       {"snoop",       CmdHFiClassSnoop,       0,      "Eavesdrop iClass communication"},
-       {"sim", CmdHFiClassSim,         0,      "Simulate iClass tag"},
-       {"reader",CmdHFiClassReader,    0,      "Read an iClass tag"},
-       {"replay",CmdHFiClassReader_Replay,     0,      "Read an iClass tag via Reply Attack"},
-       {"dump",        CmdHFiClassReader_Dump, 0,              "Authenticate and Dump iClass tag"},
-//     {"write",       CmdHFiClass_iso14443A_write,    0,      "Authenticate and Write iClass block"},
-       {"loclass",     CmdHFiClass_loclass,    1,      "Use loclass to perform bruteforce of reader attack dump"},
-       {"eload",   CmdHFiClassELoad,    0,     "[experimental] Load data into iclass emulator memory"},
-       {"decrypt", CmdHFiClassDecrypt,  1,     "Decrypt tagdump" },
+       {"help",        CmdHelp,                        1,      "This help"},
+       {"calc_ekey",   CmdHFiClassCalcEKey,            0,      "Get Elite Diversified key (block 3) to write to convert std to elite"},
+       {"clone",       CmdHFiClassCloneTag,            0,      "Authenticate and Clone from iClass bin file"},
+       {"decrypt",     CmdHFiClassDecrypt,             1,      "Decrypt tagdump" },
+       {"dump",        CmdHFiClassReader_Dump,         0,      "Authenticate and Dump iClass tag's AA1"},
+       {"eload",       CmdHFiClassELoad,               0,      "[experimental] Load data into iClass emulator memory"},
+       {"encryptblk",  CmdHFiClassEncryptBlk,          1,      "[blockData] Encrypt given block data"},
+       {"list",        CmdHFiClassList,                0,      "[Deprecated] List iClass history"},
+       //{"load",        CmdHFiClass_load,             0,      "Load from tagfile to iClass card"},
+       {"loclass",     CmdHFiClass_loclass,            1,      "Use loclass to perform bruteforce of reader attack dump"},
+       {"managekeys",  CmdManageKeys,                  1,      "Manage the keys to use with iClass"},
+       {"readblk",     CmdHFiClass_ReadBlock,          0,      "Authenticate and Read iClass block"},
+       {"reader",      CmdHFiClassReader,              0,      "Read an iClass tag"},
+       {"readtagfile", CmdHFiClassReadTagFile,         1,      "Display Content from tagfile"},
+       {"replay",      CmdHFiClassReader_Replay,       0,      "Read an iClass tag via Reply Attack"},
+       {"sim",         CmdHFiClassSim,                 0,      "Simulate iClass tag"},
+       {"snoop",       CmdHFiClassSnoop,               0,      "Eavesdrop iClass communication"},
+       {"writeblk",    CmdHFiClass_WriteBlock,         0,      "Authenticate and Write iClass block"},
        {NULL, NULL, 0, NULL}
 };
 
        {NULL, NULL, 0, NULL}
 };
 
index 30c6a8a7b1907f2bedf6f121b79ffad46293c9a1..88e61434e9fb5b2c725a2dc53af7366084adc7c9 100644 (file)
@@ -20,5 +20,11 @@ int CmdHFiClassList(const char *Cmd);
 int HFiClassReader(const char *Cmd, bool loop, bool verbose);
 int CmdHFiClassReader(const char *Cmd);
 int CmdHFiClassReader_Replay(const char *Cmd);
 int HFiClassReader(const char *Cmd, bool loop, bool verbose);
 int CmdHFiClassReader(const char *Cmd);
 int CmdHFiClassReader_Replay(const char *Cmd);
+int CmdHFiClassReadKeyFile(const char *filename);
+int CmdHFiClassWriteKeyFile(const char *Cmd);
+int CmdHFiClass_ReadBlock(const char *Cmd);
+int CmdHFiClass_WriteBlock(const char *Cmd);
+int CmdHFiClassCalcEKey(const char *Cmd);
+int CmdHFiClass_TestMac(const char *Cmd);
 
 #endif
 
 #endif
index 1acee39b3fdd5327bf0fdd927398cc583434bf25..21b19b092609f80cf3786ffda0b374696e8119b5 100644 (file)
@@ -1136,7 +1136,7 @@ static command_t CommandTable[] =
        {"read",        CmdLFRead,          0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
        {"search",      CmdLFfind,          1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"},
        {"sim",         CmdLFSim,           0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
        {"read",        CmdLFRead,          0, "['s' silent] Read 125/134 kHz LF ID-only tag. Do 'lf read h' for help"},
        {"search",      CmdLFfind,          1, "[offline] ['u'] Read and Search for valid known tag (in offline mode it you can load first then search) - 'u' to search for unknown tags"},
        {"sim",         CmdLFSim,           0, "[GAP] -- Simulate LF tag from buffer with optional GAP (in microseconds)"},
-       {"simask",      CmdLFaskSim,        0, "[clock] [invert <1|0>] [manchester/raw <'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
+       {"simask",      CmdLFaskSim,        0, "[clock] [invert <1|0>] [biphase/manchester/raw <'b'|'m'|'r'>] [msg separator 's'] [d <hexdata>] -- Simulate LF ASK tag from demodbuffer or input"},
        {"simfsk",      CmdLFfskSim,        0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
        {"simpsk",      CmdLFpskSim,        0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
        {"simbidir",    CmdLFSimBidir,      0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
        {"simfsk",      CmdLFfskSim,        0, "[c <clock>] [i] [H <fcHigh>] [L <fcLow>] [d <hexdata>] -- Simulate LF FSK tag from demodbuffer or input"},
        {"simpsk",      CmdLFpskSim,        0, "[1|2|3] [c <clock>] [i] [r <carrier>] [d <raw hex to sim>] -- Simulate LF PSK tag from demodbuffer or input"},
        {"simbidir",    CmdLFSimBidir,      0, "Simulate LF tag (with bidirectional data transmission between reader and tag)"},
index b3a7f4ec94c3e3663fc3db40fb9de301dbb1d065..cc41535287146d2f12aa5a7d18a50466cecc14a0 100644 (file)
@@ -114,9 +114,16 @@ typedef struct {
 #define CMD_WRITER_LEGIC_RF                                               0x0389
 #define CMD_EPA_PACE_COLLECT_NONCE                                        0x038A
 
 #define CMD_WRITER_LEGIC_RF                                               0x0389
 #define CMD_EPA_PACE_COLLECT_NONCE                                        0x038A
 
+#define CMD_ICLASS_CLONE                                                  0x0390
+#define CMD_ICLASS_DUMP                                                   0x0391
 #define CMD_SNOOP_ICLASS                                                  0x0392
 #define CMD_SIMULATE_TAG_ICLASS                                           0x0393
 #define CMD_READER_ICLASS                                                 0x0394
 #define CMD_SNOOP_ICLASS                                                  0x0392
 #define CMD_SIMULATE_TAG_ICLASS                                           0x0393
 #define CMD_READER_ICLASS                                                 0x0394
+#define CMD_READER_ICLASS_REPLAY                                          0x0395
+#define CMD_ICLASS_READBLOCK                                              0x0396
+#define CMD_ICLASS_WRITEBLOCK                                             0x0397
+#define CMD_ICLASS_EML_MEMSET                                             0x0398
+#define CMD_ICLASS_AUTHENTICATION                                         0x0399
 
 // For measurements of the antenna tuning
 #define CMD_MEASURE_ANTENNA_TUNING                                        0x0400
 
 // For measurements of the antenna tuning
 #define CMD_MEASURE_ANTENNA_TUNING                                        0x0400
index 7c9cc873a019f1ae67c9c84ba8cabd789d4e88bd..2aae093debc9150d99ab0a5c8fe2c7c36864b080 100644 (file)
@@ -241,6 +241,27 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4])
        //free(cc_nr);
     return;
 }
        //free(cc_nr);
     return;
 }
+void doMAC_N(uint8_t *cc_nr_p,uint8_t cc_nr_size, uint8_t *div_key_p, uint8_t mac[4])
+{
+    uint8_t *cc_nr;
+    uint8_t div_key[8];
+    cc_nr = (uint8_t*) malloc(cc_nr_size);
+    
+    memcpy(cc_nr,cc_nr_p,cc_nr_size);
+    memcpy(div_key,div_key_p,8);
+    
+    reverse_arraybytes(cc_nr,cc_nr_size);
+    BitstreamIn bitstream = {cc_nr,cc_nr_size * 8,0};
+    uint8_t dest []= {0,0,0,0,0,0,0,0};
+    BitstreamOut out = { dest, sizeof(dest)*8, 0 };
+    MAC(div_key,bitstream, out);
+    //The output MAC must also be reversed
+    reverse_arraybytes(dest, sizeof(dest));
+    memcpy(mac, dest, 4);
+    free(cc_nr);
+    return;
+}
+
 #ifndef ON_DEVICE
 int testMAC()
 {
 #ifndef ON_DEVICE
 int testMAC()
 {
index bdea94322a82aba0e06c95933a6b08e3e6123dd9..24e868513bb778efc5cf7392902d1f00dfb2dbe5 100644 (file)
@@ -42,6 +42,8 @@
 #include <stdint.h>
 
 void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
 #include <stdint.h>
 
 void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]);
+void doMAC_N(uint8_t *cc_nr_p,uint8_t cc_nr_size, uint8_t *div_key_p, uint8_t mac[4]);
+
 #ifndef ON_DEVICE
 int testMAC();
 #endif
 #ifndef ON_DEVICE
 int testMAC();
 #endif
index 4c7bc638319d39066227f769c4ee662720a58707..97f0b70a9c5d331702ead02b7ff3eb98e6308bc5 100644 (file)
@@ -86,11 +86,16 @@ local _commands = {
        CMD_EPA_PACE_COLLECT_NONCE =                                         0x038A,
        --//CMD_EPA_ =                                                         0x038B,
 
        CMD_EPA_PACE_COLLECT_NONCE =                                         0x038A,
        --//CMD_EPA_ =                                                         0x038B,
 
+       CMD_ICLASS_CLONE =                                                   0x0390,
+       CMD_ICLASS_DUMP =                                                    0x0391,
        CMD_SNOOP_ICLASS =                                                   0x0392,
        CMD_SIMULATE_TAG_ICLASS =                                            0x0393,
        CMD_READER_ICLASS =                                                  0x0394,
        CMD_SNOOP_ICLASS =                                                   0x0392,
        CMD_SIMULATE_TAG_ICLASS =                                            0x0393,
        CMD_READER_ICLASS =                                                  0x0394,
-       CMD_READER_ICLASS_REPLAY =                                                                                       0x0395,
-       CMD_ICLASS_ISO14443A_WRITE =                                                                             0x0397,
+       CMD_READER_ICLASS_REPLAY =                                           0x0395,
+       CMD_ICLASS_READBLOCK =                                               0x0396,
+       CMD_ICLASS_WRITEBLOCK =                                              0x0397,
+       CMD_ICLASS_EML_MEMSET =                                              0x0398,
+       CMD_ICLASS_AUTHENTICATION =                                          0x0399,
 
        --// For measurements of the antenna tuning
        CMD_MEASURE_ANTENNA_TUNING =                                         0x0400,
 
        --// For measurements of the antenna tuning
        CMD_MEASURE_ANTENNA_TUNING =                                         0x0400,
index aa80491b58f2b94d61313e01e1b4b4a2f64ac6a5..56a6924f78cafa9aa1c9d31ba9a70f96754afdb9 100644 (file)
@@ -74,24 +74,30 @@ void fuse_config(const picopass_hdr *hdr)
        if( isset( fuses, FUSE_RA)) prnt("      RA: Read access enabled");
        else prnt("     RA: Read access not enabled");
 }
        if( isset( fuses, FUSE_RA)) prnt("      RA: Read access enabled");
        else prnt("     RA: Read access not enabled");
 }
-void mem_config(const picopass_hdr *hdr)
+void mem_app_config(const picopass_hdr *hdr)
 {
        uint8_t mem = hdr->conf.mem_config;
 {
        uint8_t mem = hdr->conf.mem_config;
-       if( isset (mem, 0x80)) prnt("   Mem: 16KBits (255 * 8 bytes)");
-       else prnt("     Mem: 2 KBits ( 32 * 8 bytes)");
-
-}
-void applimit_config(const picopass_hdr *hdr)
-{
        uint8_t applimit = hdr->conf.app_limit;
        uint8_t applimit = hdr->conf.app_limit;
-       prnt("  AA1: blocks 6-%d", applimit);
-       prnt("  AA2: blocks %d-", (applimit+1));
+       if (applimit < 6) applimit = 26;
+       uint8_t kb=2;
+       uint8_t maxBlk = 32;
+       if( isset(mem, 0x10) && notset(mem, 0x80)){
+               // 2kb default
+       } else if( isset(mem, 0x80) && notset(mem, 0x10)){
+               kb = 16;
+               maxBlk = 255; //16kb
+       } else {
+               kb = 32;
+               maxBlk = 255;
+       }
+       prnt("  Mem: %u KBits ( %u * 8 bytes) [%02X]", kb, maxBlk, mem);
+       prnt("  AA1: blocks 06-%02X", applimit);
+       prnt("  AA2: blocks %02X-%02X", (applimit+1), (hdr->conf.mem_config));
 }
 void print_picopass_info(const picopass_hdr *hdr)
 {
        fuse_config(hdr);
 }
 void print_picopass_info(const picopass_hdr *hdr)
 {
        fuse_config(hdr);
-       mem_config(hdr);
-       applimit_config(hdr);
+       mem_app_config(hdr);
 }
 void printIclassDumpInfo(uint8_t* iclass_dump)
 {
 }
 void printIclassDumpInfo(uint8_t* iclass_dump)
 {
index 524554e9384b1db9c715a182df6bddf08431c3b2..2618476a25873ec2c906c91dc68c050ab9fbd82b 100644 (file)
@@ -128,12 +128,16 @@ typedef struct{
 #define CMD_EPA_PACE_COLLECT_NONCE                                        0x038A
 #define CMD_EPA_PACE_REPLAY                                               0x038B
 
 #define CMD_EPA_PACE_COLLECT_NONCE                                        0x038A
 #define CMD_EPA_PACE_REPLAY                                               0x038B
 
+#define CMD_ICLASS_CLONE                                                  0x0390
+#define CMD_ICLASS_DUMP                                                   0x0391
 #define CMD_SNOOP_ICLASS                                                  0x0392
 #define CMD_SIMULATE_TAG_ICLASS                                           0x0393
 #define CMD_READER_ICLASS                                                 0x0394
 #define CMD_READER_ICLASS_REPLAY                                          0x0395
 #define CMD_SNOOP_ICLASS                                                  0x0392
 #define CMD_SIMULATE_TAG_ICLASS                                           0x0393
 #define CMD_READER_ICLASS                                                 0x0394
 #define CMD_READER_ICLASS_REPLAY                                          0x0395
-#define CMD_ICLASS_ISO14443A_WRITE                                        0x0397
+#define CMD_ICLASS_READBLOCK                                              0x0396
+#define CMD_ICLASS_WRITEBLOCK                                             0x0397
 #define CMD_ICLASS_EML_MEMSET                                             0x0398
 #define CMD_ICLASS_EML_MEMSET                                             0x0398
+#define CMD_ICLASS_AUTHENTICATION                                         0x0399
 
 // For measurements of the antenna tuning
 #define CMD_MEASURE_ANTENNA_TUNING                                        0x0400
 
 // For measurements of the antenna tuning
 #define CMD_MEASURE_ANTENNA_TUNING                                        0x0400
@@ -204,6 +208,7 @@ typedef struct{
 #define FLAG_ICLASS_READER_CONF         0x08
 #define FLAG_ICLASS_READER_AA           0x10
 #define FLAG_ICLASS_READER_ONE_TRY      0x20
 #define FLAG_ICLASS_READER_CONF         0x08
 #define FLAG_ICLASS_READER_AA           0x10
 #define FLAG_ICLASS_READER_ONE_TRY      0x20
+#define FLAG_ICLASS_READER_CEDITKEY     0x40
 
 
 
 
 
 
Impressum, Datenschutz