1 //----------------------------------------------------------------------------- 
   2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch 
   3 // Copyright (C) 2011 Gerhard de Koning Gans 
   4 // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende 
   6 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   7 // at your option, any later version. See the LICENSE.txt file for the text of 
   9 //----------------------------------------------------------------------------- 
  10 // High frequency iClass commands 
  11 //----------------------------------------------------------------------------- 
  17 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type 
  19 #include "proxmark3.h" 
  21 #include "cmdparser.h" 
  22 #include "cmdhficlass.h" 
  26 #include "loclass/des.h" 
  27 #include "loclass/cipherutils.h" 
  28 #include "loclass/cipher.h" 
  29 #include "loclass/ikeys.h" 
  30 #include "loclass/elite_crack.h" 
  31 #include "loclass/fileutils.h" 
  32 #include "protocols.h" 
  36 static int CmdHelp(const char *Cmd
); 
  38 #define ICLASS_KEYS_MAX 8 
  39 static uint8_t iClass_Key_Table
[ICLASS_KEYS_MAX
][8] = { 
  40                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  41                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  42                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  43                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  44                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  45                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  46                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  47                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } 
  50 typedef struct iclass_block 
{ 
  54 int xorbits_8(uint8_t val
) { 
  55         uint8_t res 
= val 
^ (val 
>> 1); //1st pass 
  56         res 
= res 
^ (res 
>> 1);                 // 2nd pass 
  57         res 
= res 
^ (res 
>> 2);                 // 3rd pass 
  58         res 
= res 
^ (res 
>> 4);                         // 4th pass 
  62 int CmdHFiClassList(const char *Cmd
) { 
  63         PrintAndLog("Deprecated command, use 'hf list iclass' instead"); 
  67 int CmdHFiClassSnoop(const char *Cmd
) { 
  68         UsbCommand c 
= {CMD_SNOOP_ICLASS
}; 
  73 int usage_hf_iclass_sim(void) { 
  74         PrintAndLog("Usage:  hf iclass sim <option> [CSN]"); 
  75         PrintAndLog("        options"); 
  76         PrintAndLog("                0 <CSN> simulate the given CSN"); 
  77         PrintAndLog("                1       simulate default CSN"); 
  78         PrintAndLog("                2       Reader-attack, gather reader responses to extract elite key"); 
  79         PrintAndLog("                3       Full simulation using emulator memory (see 'hf iclass eload')"); 
  80         PrintAndLog("        example: hf iclass sim 0 031FEC8AF7FF12E0"); 
  81         PrintAndLog("        example: hf iclass sim 2"); 
  82         PrintAndLog("        example: hf iclass eload 'tagdump.bin'"); 
  83         PrintAndLog("                 hf iclass sim 3"); 
  88 int CmdHFiClassSim(const char *Cmd
) { 
  90         uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 
  93                 return usage_hf_iclass_sim(); 
  95         simType 
= param_get8ex(Cmd
, 0, 0, 10); 
  99                 if (param_gethex(Cmd
, 1, CSN
, 16)) { 
 100                         PrintAndLog("A CSN should consist of 16 HEX symbols"); 
 101                         return usage_hf_iclass_sim(); 
 104                 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8)); 
 108                 PrintAndLog("Undefined simptype %d", simType
); 
 109                 return usage_hf_iclass_sim(); 
 112         uint8_t numberOfCSNs
=0; 
 115                 UsbCommand c 
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}}; 
 116                 UsbCommand resp 
= {0}; 
 118                 uint8_t csns
[8*NUM_CSNS
] = { 
 119                         0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, 
 120                         0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0, 
 121                         0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0, 
 122                         0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0, 
 123                         0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0, 
 124                         0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0, 
 125                         0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0, 
 126                         0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0, 
 127                         0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0, 
 128                         0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0, 
 129                         0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0, 
 130                         0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0, 
 131                         0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0, 
 132                         0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0, 
 133                         0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 }; 
 135                 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
); 
 138                 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) { 
 139                         PrintAndLog("Command timed out"); 
 143                 uint8_t num_mac_responses  
= resp
.arg
[1]; 
 144                 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
); 
 146                 size_t datalen 
= NUM_CSNS
*24; 
 148                  * Now, time to dump to file. We'll use this format: 
 149                  * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>.... 
 150                  * So, it should wind up as 
 153                  * The returndata from the pm3 is on the following format 
 154                  * <4 byte NR><4 byte MAC> 
 155                  * CC are all zeroes, CSN is the same as was sent in 
 157                 void* dump 
= malloc(datalen
); 
 158                 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field 
 160                 for(i 
= 0 ; i 
< NUM_CSNS 
; i
++) 
 162                         memcpy(dump
+i
*24, csns
+i
*8,8); //CSN 
 163                         //8 zero bytes here... 
 164                         //Then comes NR_MAC (eight bytes from the response) 
 165                         memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8); 
 168                 /** Now, save to dumpfile **/ 
 169                 saveFile("iclass_mac_attack", "bin", dump
,datalen
); 
 173                 UsbCommand c 
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}}; 
 174                 memcpy(c
.d
.asBytes
, CSN
, 8); 
 181 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) { 
 182         bool tagFound 
= false; 
 183         UsbCommand c 
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN 
| 
 184                     FLAG_ICLASS_READER_CC 
| FLAG_ICLASS_READER_CONF 
| FLAG_ICLASS_READER_AA 
| 
 185                     FLAG_ICLASS_READER_ONLY_ONCE 
| FLAG_ICLASS_READER_ONE_TRY 
} }; 
 186         // loop in client not device - else on windows have a communication error 
 190                 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) { 
 191                         uint8_t readStatus 
= resp
.arg
[0] & 0xff; 
 192                         uint8_t *data 
= resp
.d
.asBytes
; 
 195                         if( readStatus 
== 0) continue; 
 197                         if( readStatus 
& FLAG_ICLASS_READER_CSN
) { 
 198                                 PrintAndLog("   CSN: %s",sprint_hex(data
,8)); 
 201                         if( readStatus 
& FLAG_ICLASS_READER_CC
) {  
 202                                 PrintAndLog("    CC: %s",sprint_hex(data
+16,8)); 
 204                         if( readStatus 
& FLAG_ICLASS_READER_CONF
) { 
 205                                 printIclassDumpInfo(data
); 
 207                         if (readStatus 
& FLAG_ICLASS_READER_AA
) { 
 209                                 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*5,8)); 
 210                                 for (int i 
= 0; i
<8; i
++) { 
 211                                         if (data
[8*5+i
] != 0xFF) { 
 215                                 PrintAndLog("      : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)"); 
 218                         if (tagFound 
&& !loop
) return 1; 
 220                         if (verbose
) PrintAndLog("Command execute timeout"); 
 227 int CmdHFiClassReader(const char *Cmd
) { 
 228         return HFiClassReader(Cmd
, true, true); 
 231 int CmdHFiClassReader_Replay(const char *Cmd
) { 
 232         uint8_t readerType 
= 0; 
 233         uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00}; 
 236                 PrintAndLog("Usage:  hf iclass replay <MAC>"); 
 237                 PrintAndLog("        sample: hf iclass replay 00112233"); 
 241         if (param_gethex(Cmd
, 0, MAC
, 8)) { 
 242                 PrintAndLog("MAC must include 8 HEX symbols"); 
 246         UsbCommand c 
= {CMD_READER_ICLASS_REPLAY
, {readerType
}}; 
 247         memcpy(c
.d
.asBytes
, MAC
, 4); 
 253 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) { 
 254         UsbCommand c 
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}}; 
 255         memcpy(c
.d
.asBytes
, data
, blocksCount 
* 16); 
 260 int hf_iclass_eload_usage(void) { 
 261         PrintAndLog("Loads iclass tag-dump into emulator memory on device"); 
 262         PrintAndLog("Usage:  hf iclass eload f <filename>"); 
 264         PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin"); 
 268 int CmdHFiClassELoad(const char *Cmd
) { 
 270         char opt 
= param_getchar(Cmd
, 0); 
 271         if (strlen(Cmd
)<1 || opt 
== 'h') 
 272                 return hf_iclass_eload_usage(); 
 274         //File handling and reading 
 276         char filename
[FILE_PATH_SIZE
]; 
 277         if(opt 
== 'f' && param_getstr(Cmd
, 1, filename
) > 0) 
 279                 f 
= fopen(filename
, "rb"); 
 281                 return hf_iclass_eload_usage(); 
 285                 PrintAndLog("Failed to read from file '%s'", filename
); 
 289         fseek(f
, 0, SEEK_END
); 
 290         long fsize 
= ftell(f
); 
 291         fseek(f
, 0, SEEK_SET
); 
 294                 PrintAndLog("Error, when getting filesize"); 
 299         uint8_t *dump 
= malloc(fsize
); 
 301         size_t bytes_read 
= fread(dump
, 1, fsize
, f
); 
 304         printIclassDumpInfo(dump
); 
 307         if (bytes_read 
< fsize
) 
 309                 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize 
); 
 314         uint32_t bytes_sent 
= 0; 
 315         uint32_t bytes_remaining  
= bytes_read
; 
 317         while(bytes_remaining 
> 0){ 
 318                 uint32_t bytes_in_packet 
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
); 
 319                 UsbCommand c 
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}}; 
 320                 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
); 
 322                 bytes_remaining 
-= bytes_in_packet
; 
 323                 bytes_sent 
+= bytes_in_packet
; 
 326         PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
); 
 330 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) { 
 331         FILE *f 
= fopen(filename
, "rb"); 
 333                 PrintAndLog("Failed to read from file '%s'", filename
); 
 336         fseek(f
, 0, SEEK_END
); 
 337         long fsize 
= ftell(f
); 
 338         fseek(f
, 0, SEEK_SET
); 
 339         size_t bytes_read 
= fread(buffer
, 1, len
, f
); 
 343                 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
); 
 346         if(bytes_read 
!= len
) 
 348                 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
); 
 354 int usage_hf_iclass_decrypt(void) { 
 355         PrintAndLog("Usage: hf iclass decrypt f <tagdump>"); 
 357         PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); 
 358         PrintAndLog("in the working directory. The file should be 16 bytes binary data"); 
 360         PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin"); 
 362         PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. "); 
 363         PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,"); 
 364         PrintAndLog("which is defined by the configuration block."); 
 368 int CmdHFiClassDecrypt(const char *Cmd
) { 
 369         uint8_t key
[16] = { 0 }; 
 370         if(readKeyfile("iclass_decryptionkey.bin", 16, key
)) 
 372                 usage_hf_iclass_decrypt(); 
 375         PrintAndLog("Decryption file found... "); 
 376         char opt 
= param_getchar(Cmd
, 0); 
 377         if (strlen(Cmd
)<1 || opt 
== 'h') 
 378                 return usage_hf_iclass_decrypt(); 
 380         //Open the tagdump-file 
 382         char filename
[FILE_PATH_SIZE
]; 
 383         if(opt 
== 'f' && param_getstr(Cmd
, 1, filename
) > 0) { 
 384                 f 
= fopen(filename
, "rb"); 
 386                         PrintAndLog("Could not find file %s", filename
); 
 390                 return usage_hf_iclass_decrypt(); 
 393         fseek(f
, 0, SEEK_END
); 
 394         long fsize 
= ftell(f
); 
 395         fseek(f
, 0, SEEK_SET
); 
 396         uint8_t enc_dump
[8] = {0}; 
 397         uint8_t *decrypted 
= malloc(fsize
); 
 398         des3_context ctx 
= { DES_DECRYPT 
,{ 0 } }; 
 399         des3_set2key_dec( &ctx
, key
); 
 400         size_t bytes_read 
= fread(enc_dump
, 1, 8, f
); 
 402         //Use the first block (CSN) for filename 
 403         char outfilename
[FILE_PATH_SIZE
] = { 0 }; 
 404         snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted", 
 405                          enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3], 
 406                          enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]); 
 409         while(bytes_read 
== 8) 
 413                         memcpy(decrypted
+(blocknum
*8), enc_dump
, 8); 
 415                         des3_crypt_ecb(&ctx
, enc_dump
,decrypted 
+(blocknum
*8) ); 
 417                 printvar("decrypted block", decrypted 
+(blocknum
*8), 8); 
 418                 bytes_read 
= fread(enc_dump
, 1, 8, f
); 
 423         saveFile(outfilename
,"bin", decrypted
, blocknum
*8); 
 428 int usage_hf_iclass_encrypt(void) { 
 429         PrintAndLog("Usage: hf iclass encrypt <BlockData>"); 
 431         PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); 
 432         PrintAndLog("in the working directory. The file should be 16 bytes binary data"); 
 434         PrintAndLog("example: hf iclass encrypt 0102030405060708"); 
 439 static int iClassEncryptBlkData(uint8_t *blkData
) { 
 440         uint8_t key
[16] = { 0 }; 
 441         if(readKeyfile("iclass_decryptionkey.bin", 16, key
)) 
 443                 usage_hf_iclass_encrypt(); 
 446         PrintAndLog("Decryption file found... "); 
 448         uint8_t encryptedData
[16]; 
 449         uint8_t *encrypted 
= encryptedData
; 
 450         des3_context ctx 
= { DES_DECRYPT 
,{ 0 } }; 
 451         des3_set2key_enc( &ctx
, key
); 
 453         des3_crypt_ecb(&ctx
, blkData
,encrypted
); 
 454         //printvar("decrypted block", decrypted, 8); 
 455         memcpy(blkData
,encrypted
,8); 
 460 int CmdHFiClassEncryptBlk(const char *Cmd
) { 
 461         uint8_t blkData
[8] = {0}; 
 462         char opt 
= param_getchar(Cmd
, 0); 
 463         if (strlen(Cmd
)<1 || opt 
== 'h') 
 464                 return usage_hf_iclass_encrypt(); 
 466         //get the bytes to encrypt 
 467         if (param_gethex(Cmd
, 0, blkData
, 16)) 
 469                 PrintAndLog("BlockData must include 16 HEX symbols"); 
 472         if (!iClassEncryptBlkData(blkData
)) return 0; 
 474         printvar("encrypted block", blkData
, 8); 
 478 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) { 
 481         memcpy(WB 
+ 1,data
,8); 
 482         doMAC_N(WB
,sizeof(WB
),div_key
,MAC
); 
 483         //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]); 
 486 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) { 
 489         UsbCommand c 
= {CMD_READER_ICLASS
, {0}}; 
 490         c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE 
| FLAG_ICLASS_READER_CC 
| FLAG_ICLASS_READER_ONE_TRY
; 
 492                 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
; 
 494         clearCommandBuffer(); 
 496         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) 
 498                 PrintAndLog("Command execute timeout"); 
 502         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 503         uint8_t *data 
= resp
.d
.asBytes
; 
 506         if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8); 
 509                 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8)); 
 512                 PrintAndLog("Failed to obtain CC! Aborting"); 
 518 static bool select_and_auth(uint8_t *KEY
, uint8_t *MAC
, uint8_t *div_key
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) { 
 519         uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 520         uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 522         if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
)) 
 527                 memcpy(div_key
, KEY
, 8); 
 529                 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
); 
 530         PrintAndLog("Authing with %s: %02x%02x%02x%02x%02x%02x%02x%02x", rawkey 
? "raw key" : "diversified key", div_key
[0],div_key
[1],div_key
[2],div_key
[3],div_key
[4],div_key
[5],div_key
[6],div_key
[7]); 
 532         doMAC(CCNR
, div_key
, MAC
); 
 534         UsbCommand d 
= {CMD_ICLASS_AUTHENTICATION
, {0}}; 
 535         memcpy(d
.d
.asBytes
, MAC
, 4); 
 536         clearCommandBuffer(); 
 538         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) 
 540                 PrintAndLog("Auth Command execute timeout"); 
 543         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 545                 PrintAndLog("Authentication error"); 
 551 int usage_hf_iclass_dump(void) { 
 552         PrintAndLog("Usage:  hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n"); 
 553         PrintAndLog("Options:"); 
 554         PrintAndLog("  f <filename> : specify a filename to save dump to"); 
 555         PrintAndLog("  k <Key>      : *Access Key as 16 hex symbols or 1 hex to select key from memory"); 
 556         PrintAndLog("  c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory"); 
 557         PrintAndLog("  e            : If 'e' is specified, the key is interpreted as the 16 byte"); 
 558         PrintAndLog("                 Custom Key (KCus), which can be obtained via reader-attack"); 
 559         PrintAndLog("                 See 'hf iclass sim 2'. This key should be on iclass-format"); 
 560         PrintAndLog("  r            : If 'r' is specified, the key is interpreted as raw block 3/4"); 
 561         PrintAndLog("  NOTE: * = required"); 
 562   PrintAndLog("Samples:"); 
 563         PrintAndLog("  hf iclass dump k 001122334455667B"); 
 564         PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B"); 
 565         PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA e"); 
 569 int CmdHFiClassReader_Dump(const char *Cmd
) { 
 571         uint8_t MAC
[4] = {0x00,0x00,0x00,0x00}; 
 572         uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 573         uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 577         uint8_t app_areas 
= 1; 
 579         uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 580         uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 583         uint8_t fileNameLen 
= 0; 
 584         char filename
[FILE_PATH_SIZE
]={0}; 
 585         char tempStr
[50] = {0}; 
 586         bool have_debit_key 
= false; 
 587         bool have_credit_key 
= false; 
 588         bool use_credit_key 
= false; 
 594         while(param_getchar(Cmd
, cmdp
) != 0x00) 
 596                 switch(param_getchar(Cmd
, cmdp
)) 
 600                         return usage_hf_iclass_dump(); 
 603                         have_credit_key 
= true; 
 604                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
 606                                 errors 
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
); 
 607                         } else if (dataLen 
== 1) { 
 608                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
 609                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
 610                                         memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8); 
 612                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
 616                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
 628                         fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
);  
 629                         if (fileNameLen 
< 1) { 
 630                                 PrintAndLog("No filename found after f"); 
 637                         have_debit_key 
= true; 
 638                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
 640                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
 641                         } else if (dataLen 
== 1) { 
 642                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
 643                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
 644                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
 646                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
 650                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
 661                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
 665                 if(errors
) return usage_hf_iclass_dump(); 
 668         if (cmdp 
< 2) return usage_hf_iclass_dump(); 
 669         // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work) 
 670         if (!have_debit_key 
&& have_credit_key
) use_credit_key 
= true; 
 672         //get config and first 3 blocks 
 673         UsbCommand c 
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN 
| 
 674                                         FLAG_ICLASS_READER_CONF 
| FLAG_ICLASS_READER_ONLY_ONCE 
| FLAG_ICLASS_READER_ONE_TRY
}}; 
 676         uint8_t tag_data
[255*8]; 
 678         clearCommandBuffer(); 
 680         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 681                 PrintAndLog("Command execute timeout"); 
 682                 ul_switch_off_field(); 
 685         uint8_t readStatus 
= resp
.arg
[0] & 0xff; 
 686         uint8_t *data 
= resp
.d
.asBytes
; 
 689                 PrintAndLog("No tag found..."); 
 690                 ul_switch_off_field(); 
 693         if( readStatus 
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){ 
 694                 memcpy(tag_data
, data
, 8*3); 
 695                 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..) 
 697                 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
); 
 698                 // large memory - not able to dump pages currently 
 699                 if (numblks 
> maxBlk
) numblks 
= maxBlk
; 
 701         ul_switch_off_field(); 
 702         // authenticate debit key and get div_key - later store in dump block 3 
 703         if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){ 
 704                 //try twice - for some reason it sometimes fails the first time... 
 705                 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){ 
 706                         ul_switch_off_field(); 
 712         UsbCommand w 
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}}; 
 713         clearCommandBuffer(); 
 715         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 716                 PrintAndLog("Command execute time-out 1"); 
 717                 ul_switch_off_field(); 
 720         uint32_t blocksRead 
= resp
.arg
[1]; 
 721         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 722         if (!isOK 
&& !blocksRead
) { 
 723                 PrintAndLog("Read Block Failed"); 
 724                 ul_switch_off_field(); 
 727         uint32_t startindex 
= resp
.arg
[2]; 
 728         if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) { 
 729                 PrintAndLog("Data exceeded Buffer size!"); 
 730                 blocksRead 
= (sizeof(tag_data
)/8) - blockno
; 
 732         // response ok - now get bigbuf content of the dump 
 733         GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
); 
 734         WaitForResponse(CMD_ACK
,NULL
); 
 735         size_t gotBytes 
= blocksRead
*8 + blockno
*8; 
 738         if (have_credit_key
) { 
 739                 //turn off hf field before authenticating with different key 
 740                 ul_switch_off_field(); 
 742                 // AA2 authenticate credit key and git c_div_key - later store in dump block 4 
 743                 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){ 
 744                         //try twice - for some reason it sometimes fails the first time... 
 745                         if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){ 
 746                                 ul_switch_off_field(); 
 750                 // do we still need to read more block?  (aa2 enabled?) 
 751                 if (maxBlk 
> blockno
+numblks
+1) { 
 752                         // setup dump and start 
 753                         w
.arg
[0] = blockno 
+ blocksRead
; 
 754                         w
.arg
[1] = maxBlk 
- (blockno 
+ blocksRead
); 
 755                         clearCommandBuffer(); 
 757                         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 758                                 PrintAndLog("Command execute timeout 2"); 
 759                                 ul_switch_off_field(); 
 762                         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 763                         blocksRead 
= resp
.arg
[1]; 
 764                         if (!isOK 
&& !blocksRead
) { 
 765                                 PrintAndLog("Read Block Failed 2"); 
 766                                 ul_switch_off_field(); 
 770                         startindex 
= resp
.arg
[2]; 
 771                         if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) { 
 772                                 PrintAndLog("Data exceeded Buffer size!"); 
 773                                 blocksRead 
= (sizeof(tag_data
) - gotBytes
)/8; 
 775                         // get dumped data from bigbuf 
 776                         GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
); 
 777                         WaitForResponse(CMD_ACK
,NULL
); 
 779                         gotBytes 
+= blocksRead
*8;                        
 780                 } else { //field is still on - turn it off... 
 781                         ul_switch_off_field(); 
 785         // add diversified keys to dump 
 786         if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8); 
 787         if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8); 
 789         printf("------+--+-------------------------+\n"); 
 790         printf("CSN   |00| %s|\n",sprint_hex(tag_data
, 8)); 
 791         printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
); 
 793         if (filename
[0] == 0){ 
 794                 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x", 
 795                     tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3], 
 796                     tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]); 
 799         // save the dump to .bin file 
 800         PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8); 
 801         saveFile(filename
, "bin", tag_data
, gotBytes
); 
 805 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) { 
 806         uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
 807         uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 808         if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
)) 
 813         Calc_wb_mac(blockno
,bldata
,div_key
,MAC
); 
 814         UsbCommand w 
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}}; 
 815         memcpy(w
.d
.asBytes
, bldata
, 8); 
 816         memcpy(w
.d
.asBytes 
+ 8, MAC
, 4); 
 818         clearCommandBuffer(); 
 820         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) 
 822                 PrintAndLog("Write Command execute timeout"); 
 825         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 827                 PrintAndLog("Write Block Failed"); 
 830         PrintAndLog("Write Block Successful"); 
 834 int usage_hf_iclass_writeblock(void) { 
 835         PrintAndLog("Options:"); 
 836   PrintAndLog("  b <Block> : The block number as 2 hex symbols"); 
 837   PrintAndLog("  d <data>  : Set the Data to write as 16 hex symbols"); 
 838         PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory"); 
 839   PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n"); 
 840   PrintAndLog("  e         : If 'e' is specified, elite computations applied to key"); 
 841   PrintAndLog("  r         : If 'r' is specified, no computations applied to key"); 
 842   PrintAndLog("Samples:"); 
 843         PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B"); 
 844         PrintAndLog("  hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c"); 
 845         PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0"); 
 849 int CmdHFiClass_WriteBlock(const char *Cmd
) { 
 851         uint8_t bldata
[8]={0,0,0,0,0,0,0,0}; 
 852         uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 855         char tempStr
[50] = {0}; 
 856         bool use_credit_key 
= false; 
 861         while(param_getchar(Cmd
, cmdp
) != 0x00) 
 863                 switch(param_getchar(Cmd
, cmdp
)) 
 867                         return usage_hf_iclass_writeblock(); 
 870                         if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) { 
 871                                 PrintAndLog("Block No must include 2 HEX symbols\n"); 
 878                         use_credit_key 
= true; 
 883                         if (param_gethex(Cmd
, cmdp
+1, bldata
, 16)) 
 885                                 PrintAndLog("KEY must include 16 HEX symbols\n"); 
 897                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
 899                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
 900                         } else if (dataLen 
== 1) { 
 901                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
 902                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
 903                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
 905                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
 909                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
 920                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
 924                 if(errors
) return usage_hf_iclass_writeblock(); 
 927         if (cmdp 
< 6) return usage_hf_iclass_writeblock(); 
 928         int ans 
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true); 
 929         ul_switch_off_field(); 
 933 int usage_hf_iclass_clone(void) { 
 934         PrintAndLog("Usage:  hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r"); 
 935         PrintAndLog("Options:"); 
 936         PrintAndLog("  f <filename>: specify a filename to clone from"); 
 937         PrintAndLog("  b <Block>   : The first block to clone as 2 hex symbols"); 
 938         PrintAndLog("  l <Last Blk>: Set the Data to write as 16 hex symbols"); 
 939         PrintAndLog("  k <Key>     : Access Key as 16 hex symbols or 1 hex to select key from memory"); 
 940         PrintAndLog("  c           : If 'c' is specified, the key set is assumed to be the credit key\n"); 
 941         PrintAndLog("  e           : If 'e' is specified, elite computations applied to key"); 
 942         PrintAndLog("  r           : If 'r' is specified, no computations applied to key"); 
 943         PrintAndLog("Samples:"); 
 944         PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e"); 
 945         PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0"); 
 946         PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e"); 
 950 int CmdHFiClassCloneTag(const char *Cmd
) { 
 951         char filename
[FILE_PATH_SIZE
] = {0}; 
 952         char tempStr
[50]={0}; 
 953         uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 955         uint8_t fileNameLen 
= 0; 
 956         uint8_t startblock 
= 0; 
 957         uint8_t endblock 
= 0; 
 959         bool use_credit_key 
= false; 
 964         while(param_getchar(Cmd
, cmdp
) != 0x00) 
 966                 switch(param_getchar(Cmd
, cmdp
)) 
 970                         return usage_hf_iclass_clone(); 
 973                         if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) { 
 974                                 PrintAndLog("Start Block No must include 2 HEX symbols\n"); 
 981                         use_credit_key 
= true; 
 991                         fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
);  
 992                         if (fileNameLen 
< 1) { 
 993                                 PrintAndLog("No filename found after f"); 
1000                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1001                         if (dataLen 
== 16) {  
1002                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1003                         } else if (dataLen 
== 1) { 
1004                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1005                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1006                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
1008                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
1012                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
1019                         if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) { 
1020                                 PrintAndLog("Start Block No must include 2 HEX symbols\n"); 
1031                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1035                 if(errors
) return usage_hf_iclass_clone(); 
1038         if (cmdp 
< 8) return usage_hf_iclass_clone(); 
1042         iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12]; 
1044         if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) { 
1045                 PrintAndLog("Trying to write too many blocks at once.  Max: %d", USB_CMD_DATA_SIZE
/8); 
1047         // file handling and reading 
1048         f 
= fopen(filename
,"rb"); 
1050                 PrintAndLog("Failed to read from file '%s'", filename
); 
1055                 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4"); 
1059         // now read data from the file from block 6 --- 19 
1060         // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data 
1061         // 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, 
1062         // else we have to create a share memory 
1064         fseek(f
,startblock
*8,SEEK_SET
); 
1065         if ( fread(tag_data
,sizeof(iclass_block_t
),endblock 
- startblock 
+ 1,f
) == 0 ) { 
1066                 PrintAndLog("File reading error."); 
1071         uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
1072         uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1074         if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true)) 
1077         UsbCommand w 
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}}; 
1079         // calculate all mac for every the block we will write 
1080         for (i 
= startblock
; i 
<= endblock
; i
++){ 
1081             Calc_wb_mac(i
,tag_data
[i 
- startblock
].d
,div_key
,MAC
); 
1082             // usb command d start pointer = d + (i - 6) * 12 
1083             // memcpy(pointer,tag_data[i - 6],8) 8 bytes 
1084             // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes; 
1086             ptr 
= w
.d
.asBytes 
+ (i 
- startblock
) * 12; 
1087             memcpy(ptr
, &(tag_data
[i 
- startblock
].d
[0]), 8); 
1088             memcpy(ptr 
+ 8,MAC
, 4); 
1091         for (i 
= 0; i 
<= endblock 
- startblock
;i
++){ 
1092             memcpy(p
,w
.d
.asBytes 
+ (i 
* 12),12); 
1093             printf("Block |%02x|",i 
+ startblock
); 
1094             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]); 
1095             printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]); 
1099         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) 
1101                 PrintAndLog("Command execute timeout"); 
1107 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) { 
1108         uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
1109         uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1112                 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
)) 
1115                 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1116                 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1117                 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
)) 
1122         UsbCommand w 
= {CMD_ICLASS_READBLOCK
, {blockno
}}; 
1123         clearCommandBuffer(); 
1125         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) 
1127                 PrintAndLog("Command execute timeout"); 
1130         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
1132                 PrintAndLog("Read Block Failed"); 
1135         //data read is stored in: resp.d.asBytes[0-15] 
1136         if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8)); 
1140 int usage_hf_iclass_readblock(void) { 
1141         PrintAndLog("Usage:  hf iclass readblk b <Block> k <Key> c e|r\n"); 
1142         PrintAndLog("Options:"); 
1143   PrintAndLog("  b <Block> : The block number as 2 hex symbols"); 
1144         PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory"); 
1145   PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n"); 
1146   PrintAndLog("  e         : If 'e' is specified, elite computations applied to key"); 
1147   PrintAndLog("  r         : If 'r' is specified, no computations applied to key"); 
1148   PrintAndLog("Samples:"); 
1149         PrintAndLog("  hf iclass readblk b 06 k 0011223344556677"); 
1150         PrintAndLog("  hf iclass readblk b 1B k 0011223344556677 c"); 
1151         PrintAndLog("  hf iclass readblk b 0A k 0"); 
1155 int CmdHFiClass_ReadBlock(const char *Cmd
) { 
1157         uint8_t keyType 
= 0x88; //debit key 
1158         uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1160         uint8_t dataLen 
= 0; 
1161         char tempStr
[50] = {0}; 
1163         bool rawkey 
= false; 
1164         bool errors 
= false; 
1167         while(param_getchar(Cmd
, cmdp
) != 0x00) 
1169                 switch(param_getchar(Cmd
, cmdp
)) 
1173                         return usage_hf_iclass_readblock(); 
1176                         if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) { 
1177                                 PrintAndLog("Block No must include 2 HEX symbols\n"); 
1195                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1196                         if (dataLen 
== 16) {  
1197                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1198                         } else if (dataLen 
== 1) { 
1199                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1200                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1201                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
1203                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
1207                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
1218                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1222                 if(errors
) return usage_hf_iclass_readblock(); 
1225         if (cmdp 
< 2) return usage_hf_iclass_readblock(); 
1227                 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication."); 
1228         return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
); 
1231 int CmdHFiClass_loclass(const char *Cmd
) { 
1232         char opt 
= param_getchar(Cmd
, 0); 
1234         if (strlen(Cmd
)<1 || opt 
== 'h') { 
1235                 PrintAndLog("Usage: hf iclass loclass [options]"); 
1236                 PrintAndLog("Options:"); 
1237                 PrintAndLog("h             Show this help"); 
1238                 PrintAndLog("t             Perform self-test"); 
1239                 PrintAndLog("f <filename>  Bruteforce iclass dumpfile"); 
1240                 PrintAndLog("                   An iclass dumpfile is assumed to consist of an arbitrary number of"); 
1241                 PrintAndLog("                   malicious CSNs, and their protocol responses"); 
1242                 PrintAndLog("                   The binary format of the file is expected to be as follows: "); 
1243                 PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); 
1244                 PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); 
1245                 PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); 
1246                 PrintAndLog("                  ... totalling N*24 bytes"); 
1249         char fileName
[255] = {0}; 
1252                 if(param_getstr(Cmd
, 1, fileName
) > 0) 
1254                         return bruteforceFileNoKeys(fileName
); 
1257                         PrintAndLog("You must specify a filename"); 
1262                 int errors 
= testCipherUtils(); 
1263                 errors 
+= testMAC(); 
1264                 errors 
+= doKeyTests(0); 
1265                 errors 
+= testElite(); 
1268                         prnlog("OBS! There were errors!!!"); 
1276 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) { 
1278         memcpy(&mem_config
, iclass_dump 
+ 13,1); 
1279         uint8_t maxmemcount
; 
1280         uint8_t filemaxblock 
= filesize 
/ 8; 
1281         if (mem_config 
& 0x80) 
1285         //PrintAndLog   ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock); 
1287         if (startblock 
== 0) 
1289         if ((endblock 
> maxmemcount
) || (endblock 
== 0)) 
1290                 endblock 
= maxmemcount
; 
1292         // remember endblock need to relate to zero-index arrays. 
1293         if (endblock 
> filemaxblock
-1) 
1294                 endblock 
= filemaxblock
; 
1297         printf("------+--+-------------------------+\n"); 
1298         while (i 
<= endblock
) { 
1299                 uint8_t *blk 
= iclass_dump 
+ (i 
* 8); 
1300                 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );    
1303         printf("------+--+-------------------------+\n"); 
1306 int usage_hf_iclass_readtagfile() { 
1307         PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]"); 
1311 int CmdHFiClassReadTagFile(const char *Cmd
) { 
1316         char filename
[FILE_PATH_SIZE
]; 
1317         if (param_getstr(Cmd
, 0, filename
) < 1) 
1318                 return usage_hf_iclass_readtagfile(); 
1319         if (param_getstr(Cmd
,1,(char *)&tempnum
) < 1) 
1322                 sscanf(tempnum
,"%d",&startblock
); 
1324         if (param_getstr(Cmd
,2,(char *)&tempnum
) < 1) 
1327                 sscanf(tempnum
,"%d",&endblock
); 
1328         // file handling and reading 
1329         f 
= fopen(filename
,"rb"); 
1331                 PrintAndLog("Failed to read from file '%s'", filename
); 
1334         fseek(f
, 0, SEEK_END
); 
1335         long fsize 
= ftell(f
); 
1336         fseek(f
, 0, SEEK_SET
); 
1339                 PrintAndLog("Error, when getting filesize"); 
1344         uint8_t *dump 
= malloc(fsize
); 
1346         size_t bytes_read 
= fread(dump
, 1, fsize
, f
); 
1348         uint8_t *csn 
= dump
; 
1349         printf("------+--+-------------------------+\n"); 
1350         printf("CSN   |00| %s|\n", sprint_hex(csn
, 8) ); 
1351         //    printIclassDumpInfo(dump); 
1352         printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
); 
1358 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) { 
1359         uint64_t new_div = 0x00; 
1365 uint64_t hexarray_to_uint64(uint8_t *key) { 
1368         for (int i = 0;i < 8;i++) 
1369                 sprintf(&temp[(i *2)],"%02X",key[i]); 
1371         if (sscanf(temp,"%016" SCNx64,&uint_key) < 1) 
1376 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t   *KEY
, uint8_t *div_key
, bool elite
){ 
1377         uint8_t keytable
[128] = {0}; 
1378         uint8_t key_index
[8] = {0}; 
1380                 uint8_t key_sel
[8] = { 0 }; 
1381                 uint8_t key_sel_p
[8] = { 0 }; 
1382                 hash2(KEY
, keytable
); 
1383                 hash1(CSN
, key_index
); 
1384                 for(uint8_t i 
= 0; i 
< 8 ; i
++) 
1385                         key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF; 
1387                 //Permute from iclass format to standard format 
1388                 permutekey_rev(key_sel
, key_sel_p
); 
1389                 diversifyKey(CSN
, key_sel_p
, div_key
);   
1391                 diversifyKey(CSN
, KEY
, div_key
); 
1395 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite) 
1396 //calculate and return xor_div_key (ready for a key write command) 
1397 //print all div_keys if verbose 
1398 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){ 
1399         uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1400         uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1402         HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
); 
1404         HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
); 
1406         for (uint8_t i 
= 0; i 
< sizeof(old_div_key
); i
++){ 
1407                 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
]; 
1410                 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8)); 
1411                 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8)); 
1412                 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));          
1416 int usage_hf_iclass_calc_newkey(void) { 
1417         PrintAndLog("HELP :  Manage iClass Keys in client memory:\n"); 
1418         PrintAndLog("Usage:  hf iclass calc_newkey o <Old key> n <New key> s [csn] e"); 
1419         PrintAndLog("  Options:"); 
1420         PrintAndLog("  o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol"); 
1421         PrintAndLog("  n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol"); 
1422         PrintAndLog("  s <csn>    : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)"); 
1423         PrintAndLog("  e          : specify new key as elite calc"); 
1424         PrintAndLog("  ee         : specify old and new key as elite calc"); 
1425         PrintAndLog("Samples:"); 
1426         PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee"); 
1427         PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e"); 
1428         PrintAndLog(" std to std read csn      : hf iclass calcnewkey o 1122334455667788 n 2233445566778899"); 
1429         PrintAndLog("NOTE: * = required\n"); 
1434 int CmdHFiClassCalcNewKey(const char *Cmd
) { 
1435         uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1436         uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1437         uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1438         uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1439         uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1441         uint8_t dataLen 
= 0; 
1442         char tempStr
[50] = {0}; 
1443         bool givenCSN 
= false; 
1444         bool oldElite 
= false; 
1446         bool errors 
= false; 
1448         while(param_getchar(Cmd
, cmdp
) != 0x00) 
1450                 switch(param_getchar(Cmd
, cmdp
)) 
1454                         return usage_hf_iclass_calc_newkey(); 
1457                         dataLen 
= param_getstr(Cmd
, cmdp
, tempStr
); 
1465                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1466                         if (dataLen 
== 16) {  
1467                                 errors 
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
); 
1468                         } else if (dataLen 
== 1) { 
1469                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1470                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1471                                         memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8); 
1473                                         PrintAndLog("\nERROR: NewKey Nbr is invalid\n"); 
1477                                 PrintAndLog("\nERROR: NewKey is incorrect length\n"); 
1484                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1485                         if (dataLen 
== 16) {  
1486                                 errors 
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
); 
1487                         } else if (dataLen 
== 1) { 
1488                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1489                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1490                                         memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8); 
1492                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
1496                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
1504                         if (param_gethex(Cmd
, cmdp
+1, CSN
, 16)) 
1505                                 return usage_hf_iclass_calc_newkey(); 
1509                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1513                 if(errors
) return usage_hf_iclass_calc_newkey(); 
1516         if (cmdp 
< 4) return usage_hf_iclass_calc_newkey(); 
1519                 if (!select_only(CSN
, CCNR
, false, true)) 
1522         HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true); 
1526 static int loadKeys(char *filename
) { 
1528         f 
= fopen(filename
,"rb"); 
1530                 PrintAndLog("Failed to read from file '%s'", filename
); 
1533         fseek(f
, 0, SEEK_END
); 
1534         long fsize 
= ftell(f
); 
1535         fseek(f
, 0, SEEK_SET
); 
1538                 PrintAndLog("Error, when getting filesize"); 
1543         uint8_t *dump 
= malloc(fsize
); 
1545         size_t bytes_read 
= fread(dump
, 1, fsize
, f
); 
1547         if (bytes_read 
> ICLASS_KEYS_MAX 
* 8){ 
1548                 PrintAndLog("File is too long to load - bytes: %u", bytes_read
); 
1553         for (; i 
< bytes_read
/8; i
++){ 
1554                 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8); 
1557         PrintAndLog("%u keys loaded", i
); 
1561 static int saveKeys(char *filename
) { 
1563         f 
= fopen(filename
,"wb"); 
1565                 printf("error opening file %s\n",filename
); 
1568         for (uint8_t i 
= 0; i 
< ICLASS_KEYS_MAX
; i
++){ 
1569                 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){ 
1570                         PrintAndLog("save key failed to write to file: %s", filename
); 
1578 static int printKeys(void) { 
1580         for (uint8_t i 
= 0; i 
< ICLASS_KEYS_MAX
; i
++){ 
1581                 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8)); 
1587 int usage_hf_iclass_managekeys(void) { 
1588         PrintAndLog("HELP :  Manage iClass Keys in client memory:\n"); 
1589         PrintAndLog("Usage:  hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n"); 
1590         PrintAndLog("  Options:"); 
1591         PrintAndLog("  n <keynbr>  : specify the keyNbr to set in memory"); 
1592         PrintAndLog("  k <key>     : set a key in memory"); 
1593         PrintAndLog("  f <filename>: specify a filename to use with load or save operations"); 
1594         PrintAndLog("  s           : save keys in memory to file specified by filename"); 
1595         PrintAndLog("  l           : load keys to memory from file specified by filename"); 
1596         PrintAndLog("  p           : print keys loaded into memory\n"); 
1597         PrintAndLog("Samples:"); 
1598         PrintAndLog(" set key      : hf iclass managekeys n 0 k 1122334455667788"); 
1599         PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s"); 
1600         PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l"); 
1601         PrintAndLog(" print keys   : hf iclass managekeys p\n"); 
1605 int CmdHFiClassManageKeys(const char *Cmd
) { 
1607         uint8_t dataLen 
= 0; 
1608         uint8_t KEY
[8] = {0}; 
1609         char filename
[FILE_PATH_SIZE
]; 
1610         uint8_t fileNameLen 
= 0; 
1611         bool errors 
= false; 
1612         uint8_t operation 
= 0; 
1616         while(param_getchar(Cmd
, cmdp
) != 0x00) 
1618                 switch(param_getchar(Cmd
, cmdp
)) 
1622                         return usage_hf_iclass_managekeys(); 
1625                         fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
);  
1626                         if (fileNameLen 
< 1) { 
1627                                 PrintAndLog("No filename found after f"); 
1634                         keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1635                         if (keyNbr 
>= ICLASS_KEYS_MAX
) { 
1636                                 PrintAndLog("Invalid block number"); 
1643                         operation 
+= 3; //set key  
1644                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1645                         if (dataLen 
== 16) { //ul-c or ev1/ntag key length 
1646                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1648                                 PrintAndLog("\nERROR: Key is incorrect length\n"); 
1655                         operation 
+= 4; //print keys in memory 
1660                         operation 
+= 5; //load keys from file 
1665                         operation 
+= 6; //save keys to file 
1669                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1673                 if(errors
) return usage_hf_iclass_managekeys(); 
1675         if (operation 
== 0){ 
1676                 PrintAndLog("no operation specified (load, save, or print)\n"); 
1677                 return usage_hf_iclass_managekeys(); 
1680                 PrintAndLog("Too many operations specified\n"); 
1681                 return usage_hf_iclass_managekeys(); 
1683         if (operation 
> 4 && fileNameLen 
== 0){ 
1684                 PrintAndLog("You must enter a filename when loading or saving\n"); 
1685                 return usage_hf_iclass_managekeys(); 
1689                 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1; 
1690                 case 4: return printKeys(); 
1691                 case 5: return loadKeys(filename
); 
1692                 case 6: return saveKeys(filename
); 
1698 static command_t CommandTable
[] =  
1700         {"help",        CmdHelp
,                        1,      "This help"}, 
1701         {"calcnewkey",  CmdHFiClassCalcNewKey
,          1,      "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"}, 
1702         {"clone",       CmdHFiClassCloneTag
,            0,      "[options..] Authenticate and Clone from iClass bin file"}, 
1703         {"decrypt",     CmdHFiClassDecrypt
,             1,      "[f <fname>] Decrypt tagdump" }, 
1704         {"dump",        CmdHFiClassReader_Dump
,         0,      "[options..] Authenticate and Dump iClass tag's AA1"}, 
1705         {"eload",       CmdHFiClassELoad
,               0,      "[f <fname>] (experimental) Load data into iClass emulator memory"}, 
1706         {"encryptblk",  CmdHFiClassEncryptBlk
,          1,      "<BlockData> Encrypt given block data"}, 
1707         {"list",        CmdHFiClassList
,                0,      "            (Deprecated) List iClass history"}, 
1708         {"loclass",     CmdHFiClass_loclass
,            1,      "[options..] Use loclass to perform bruteforce of reader attack dump"}, 
1709         {"managekeys",  CmdHFiClassManageKeys
,          1,      "[options..] Manage the keys to use with iClass"}, 
1710         {"readblk",     CmdHFiClass_ReadBlock
,          0,      "[options..] Authenticate and Read iClass block"}, 
1711         {"reader",      CmdHFiClassReader
,              0,      "            Read an iClass tag"}, 
1712         {"readtagfile", CmdHFiClassReadTagFile
,         1,      "[options..] Display Content from tagfile"}, 
1713         {"replay",      CmdHFiClassReader_Replay
,       0,      "<mac>       Read an iClass tag via Reply Attack"}, 
1714         {"sim",         CmdHFiClassSim
,                 0,      "[options..] Simulate iClass tag"}, 
1715         {"snoop",       CmdHFiClassSnoop
,               0,      "            Eavesdrop iClass communication"}, 
1716         {"writeblk",    CmdHFiClass_WriteBlock
,         0,      "[options..] Authenticate and Write iClass block"}, 
1717         {NULL
, NULL
, 0, NULL
} 
1720 int CmdHFiClass(const char *Cmd
) 
1722         CmdsParse(CommandTable
, Cmd
); 
1726 int CmdHelp(const char *Cmd
) 
1728         CmdsHelp(CommandTable
);