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 
   5 // Copyright (C) 2019 piwi 
   7 // This code is licensed to you under the terms of the GNU GPL, version 2 or, 
   8 // at your option, any later version. See the LICENSE.txt file for the text of 
  10 //----------------------------------------------------------------------------- 
  11 // High frequency iClass commands 
  12 //----------------------------------------------------------------------------- 
  19 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type 
  22 #include "cliparser/cliparser.h" 
  23 #include "cmdparser.h" 
  24 #include "cmdhficlass.h" 
  28 #include "mbedtls/des.h" 
  29 #include "loclass/cipherutils.h" 
  30 #include "loclass/cipher.h" 
  31 #include "loclass/ikeys.h" 
  32 #include "loclass/elite_crack.h" 
  33 #include "loclass/fileutils.h" 
  34 #include "protocols.h" 
  37 #include "util_posix.h" 
  38 #include "cmdhf14a.h" // DropField() 
  41 #define ICLASS_KEYS_MAX 8 
  42 static uint8_t iClass_Key_Table
[ICLASS_KEYS_MAX
][8] = { 
  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 }, 
  48                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  49                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  50                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } 
  54 typedef struct iclass_block 
{ 
  59 // iclass / picopass chip config structures and shared routines 
  61         uint8_t app_limit
;      //[8] 
  62         uint8_t otp
[2];         //[9-10] 
  63         uint8_t block_writelock
;//[11] 
  64         uint8_t chip_config
;    //[12] 
  65         uint8_t mem_config
;     //[13] 
  68 } picopass_conf_block
; 
  72         picopass_conf_block conf
; 
  76         uint8_t app_issuer_area
[8]; 
  80 static void fuse_config(const picopass_hdr 
*hdr
) { 
  81         uint8_t fuses 
= hdr
->conf
.fuses
; 
  83         if (fuses 
& FUSE_FPERS
) 
  84                 PrintAndLog("  Mode: Personalization [Programmable]"); 
  86                 PrintAndLog("  Mode: Application [Locked]"); 
  88         if (fuses 
& FUSE_CODING1
) 
  89                 PrintAndLog("Coding: RFU"); 
  91                 if (fuses 
& FUSE_CODING0
) 
  92                         PrintAndLog("Coding: ISO 14443-2 B/ISO 15693"); 
  94                         PrintAndLog("Coding: ISO 14443B only"); 
  96         if ((fuses 
& FUSE_CRYPT1
) && (fuses 
& FUSE_CRYPT0
)) PrintAndLog(" Crypt: Secured page, keys not locked"); 
  97         if ((fuses 
& FUSE_CRYPT1
) && !(fuses 
& FUSE_CRYPT0
)) PrintAndLog(" Crypt: Secured page, keys locked"); 
  98         if (!(fuses 
& FUSE_CRYPT1
) && (fuses 
& FUSE_CRYPT0
)) PrintAndLog(" Crypt: Non secured page"); 
  99         if (!(fuses 
& FUSE_CRYPT1
) && !(fuses 
& FUSE_CRYPT0
)) PrintAndLog(" Crypt: No auth possible. Read only if RA is enabled"); 
 102                 PrintAndLog("    RA: Read access enabled"); 
 104                 PrintAndLog("    RA: Read access not enabled"); 
 108 static void getMemConfig(uint8_t mem_cfg
, uint8_t chip_cfg
, uint8_t *max_blk
, uint8_t *app_areas
, uint8_t *kb
) { 
 109         // mem-bit 5, mem-bit 7, chip-bit 4: defines chip type 
 110         if((chip_cfg 
& 0x10) && !(mem_cfg 
& 0x80) && !(mem_cfg 
& 0x20)) { 
 114         } else if((chip_cfg 
& 0x10) && (mem_cfg 
& 0x80) && !(mem_cfg 
& 0x20)) { 
 117                 *max_blk 
= 255; //16kb 
 118         } else if(!(chip_cfg 
& 0x10) && !(mem_cfg 
& 0x80) && !(mem_cfg 
& 0x20)) { 
 121                 *max_blk 
= 255; //16kb 
 122         } else if((chip_cfg 
& 0x10) && (mem_cfg 
& 0x80) && (mem_cfg 
& 0x20)) { 
 125                 *max_blk 
= 255; //16kb 
 126         } else if(!(chip_cfg 
& 0x10) && !(mem_cfg 
& 0x80) && (mem_cfg 
& 0x20)) { 
 129                 *max_blk 
= 255; //16kb 
 138 static void mem_app_config(const picopass_hdr 
*hdr
) { 
 139         uint8_t mem 
= hdr
->conf
.mem_config
; 
 140         uint8_t chip 
= hdr
->conf
.chip_config
; 
 141         uint8_t applimit 
= hdr
->conf
.app_limit
; 
 142         if (applimit 
< 6) applimit 
= 26; 
 144         uint8_t app_areas 
= 2; 
 145         uint8_t max_blk 
= 31; 
 146         getMemConfig(mem
, chip
, &max_blk
, &app_areas
, &kb
); 
 147         PrintAndLog("   Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb
, app_areas
, max_blk
+1, mem
); 
 148         PrintAndLog("   AA1: blocks 06-%02X", applimit
); 
 149         PrintAndLog("   AA2: blocks %02X-%02X", applimit
+1, max_blk
); 
 153 static void printIclassDumpInfo(uint8_t* iclass_dump
) { 
 154         fuse_config((picopass_hdr
*)iclass_dump
); 
 155         mem_app_config((picopass_hdr
*)iclass_dump
); 
 159 static void usage_hf_iclass_chk(void) { 
 160         PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag"); 
 161         PrintAndLog("Usage: hf iclass chk [h|e|r] <f  (*.dic)>"); 
 162         PrintAndLog("Options:"); 
 163         PrintAndLog("h             Show this help"); 
 164         PrintAndLog("f <filename>  Dictionary file with default iclass keys"); 
 165         PrintAndLog("      e             target Elite / High security key scheme"); 
 166         PrintAndLog("      r             interpret dictionary file as raw (diversified keys)"); 
 167         PrintAndLog("Samples:"); 
 168         PrintAndLog("        hf iclass chk f default_iclass_keys.dic"); 
 169         PrintAndLog("        hf iclass chk f default_iclass_keys.dic e"); 
 173 static int CmdHFiClassList(const char *Cmd
) { 
 174         PrintAndLog("Deprecated command, use 'hf list iclass' instead"); 
 179 static int CmdHFiClassSnoop(const char *Cmd
) { 
 181         CLIParserInit("hf iclass snoop", "\nSnoop a communication between an iClass Reader and an iClass Tag.", NULL
); 
 184                 arg_lit0("j",  "jam",    "Jam (prevent) e-purse Updates"), 
 187         if (CLIParserParseString(Cmd
, argtable
, arg_getsize(argtable
), true)){ 
 192         bool jam_epurse_update 
= arg_get_lit(1); 
 194         const uint8_t update_epurse_sequence
[2] = {0x87, 0x02}; 
 196         UsbCommand c 
= {CMD_SNOOP_ICLASS
, {0}}; 
 197         if (jam_epurse_update
) { 
 198                 c
.arg
[0] = sizeof(update_epurse_sequence
); 
 199                 memcpy(c
.d
.asBytes
, update_epurse_sequence
, sizeof(update_epurse_sequence
)); 
 207 static void usage_hf_iclass_sim(void) { 
 208         PrintAndLog("Usage:  hf iclass sim <option> [CSN]"); 
 209         PrintAndLog("        options"); 
 210         PrintAndLog("                0 <CSN> simulate the given CSN"); 
 211         PrintAndLog("                1       simulate default CSN"); 
 212         PrintAndLog("                2       Reader-attack, gather reader responses to extract elite key"); 
 213         PrintAndLog("                3       Full simulation using emulator memory (see 'hf iclass eload')"); 
 214         PrintAndLog("        example: hf iclass sim 0 031FEC8AF7FF12E0"); 
 215         PrintAndLog("        example: hf iclass sim 2"); 
 216         PrintAndLog("        example: hf iclass eload 'tagdump.bin'"); 
 217         PrintAndLog("                 hf iclass sim 3"); 
 221 // the original malicious IDs from Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult, 
 222 // and Milosch Meriac. Dismantling iClass and iClass Elite. 
 224 static uint8_t csns
[8 * NUM_CSNS
] = { 
 225         0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, 
 226         0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0, 
 227         0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0, 
 228         0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0, 
 229         0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0, 
 230         0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0, 
 231         0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0, 
 232         0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0, 
 233         0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0, 
 234         0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0, 
 235         0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0, 
 236         0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0, 
 237         0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0, 
 238         0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0, 
 239         0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 }; 
 242 // pre-defined 9 CSNs by iceman. 
 243 // only one csn depend on several others. 
 244 // six depends only on the first csn,  (0,1, 0x45) 
 246 // #define NUM_CSNS 9 
 247 // static uint8_t csns[8 * NUM_CSNS] = { 
 248         // 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, 
 249         // 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0, 
 250         // 0x10, 0x97, 0x83, 0x7B, 0xF7, 0xFF, 0x12, 0xE0, 
 251         // 0x13, 0x97, 0x82, 0x7A, 0xF7, 0xFF, 0x12, 0xE0, 
 252         // 0x07, 0x0E, 0x0D, 0xF9, 0xF7, 0xFF, 0x12, 0xE0, 
 253         // 0x14, 0x96, 0x84, 0x76, 0xF7, 0xFF, 0x12, 0xE0, 
 254         // 0x17, 0x96, 0x85, 0x71, 0xF7, 0xFF, 0x12, 0xE0, 
 255         // 0xCE, 0xC5, 0x0F, 0x77, 0xF7, 0xFF, 0x12, 0xE0, 
 256         // 0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0 
 257         // //0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0 
 261 static int CmdHFiClassSim(const char *Cmd
) { 
 263         uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 
 265         if (strlen(Cmd
) < 1) { 
 266                 usage_hf_iclass_sim(); 
 269         simType 
= param_get8ex(Cmd
, 0, 0, 10); 
 271         if (simType 
== ICLASS_SIM_MODE_CSN
) { 
 272                 if (param_gethex(Cmd
, 1, CSN
, 16)) { 
 273                         PrintAndLog("A CSN should consist of 16 HEX symbols"); 
 274                         usage_hf_iclass_sim(); 
 277                 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8)); 
 280         if (simType 
== ICLASS_SIM_MODE_READER_ATTACK
) { 
 281                 UsbCommand c 
= {CMD_SIMULATE_TAG_ICLASS
, {simType
, NUM_CSNS
}}; 
 282                 UsbCommand resp 
= {0}; 
 284                 memcpy(c
.d
.asBytes
, csns
, 8 * NUM_CSNS
); 
 287                 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) { 
 288                         PrintAndLog("Command timed out"); 
 292                 uint8_t num_mac_responses  
= resp
.arg
[1]; 
 293                 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
, NUM_CSNS
); 
 295                 size_t datalen 
= NUM_CSNS 
* 24; 
 297                  * Now, time to dump to file. We'll use this format: 
 298                  * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>.... 
 299                  * So, it should wind up as 
 302                  * The returndata from the pm3 is on the following format 
 303                  * <8 byte CC><4 byte NR><4 byte MAC> 
 304                  * CSN is the same as was sent in 
 306                 void* dump 
= malloc(datalen
); 
 307                 for(int i 
= 0; i 
< NUM_CSNS
; i
++) { 
 308                         memcpy(dump 
+ i
*24, csns
+i
*8, 8); //CSN 
 309                         //copy CC from response 
 310                         memcpy(dump 
+ i
*24 + 8, resp
.d
.asBytes 
+ i
*16, 8); 
 311                         //Then comes NR_MAC (eight bytes from the response) 
 312                         memcpy(dump 
+ i
*24 + 16, resp
.d
.asBytes 
+ i
*16 + 8, 8); 
 314                 /** Now, save to dumpfile **/ 
 315                 saveFile("iclass_mac_attack", "bin", dump
,datalen
); 
 318         } else if (simType 
== ICLASS_SIM_MODE_CSN 
|| simType 
== ICLASS_SIM_MODE_CSN_DEFAULT 
|| simType 
== ICLASS_SIM_MODE_FULL
) { 
 319                 UsbCommand c 
= {CMD_SIMULATE_TAG_ICLASS
, {simType
, 0}}; 
 320                 memcpy(c
.d
.asBytes
, CSN
, 8); 
 324                 PrintAndLog("Undefined simtype %d", simType
); 
 325                 usage_hf_iclass_sim(); 
 333 int HFiClassReader(bool loop
, bool verbose
) { 
 335         bool tagFound 
= false; 
 336         UsbCommand c 
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_INIT 
| FLAG_ICLASS_READER_CLEARTRACE 
| FLAG_ICLASS_READER_CSN 
| FLAG_ICLASS_READER_CONF 
| FLAG_ICLASS_READER_CC 
| FLAG_ICLASS_READER_AA
} }; 
 341                 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) { 
 342                         uint8_t readStatus 
= resp
.arg
[0] & 0xff; 
 343                         uint8_t *data 
= resp
.d
.asBytes
; 
 346                         if (readStatus 
== 0 && !loop
) { 
 348                                 if (verbose
) PrintAndLog("Quitting..."); 
 353                         if (readStatus 
& FLAG_ICLASS_READER_CSN
) { 
 354                                 PrintAndLog("   CSN: %s",sprint_hex(data
,8)); 
 357                         if (readStatus 
& FLAG_ICLASS_READER_CC
) { 
 358                                 PrintAndLog("    CC: %s",sprint_hex(data
+16,8)); 
 360                         if (readStatus 
& FLAG_ICLASS_READER_CONF
) { 
 361                                 printIclassDumpInfo(data
); 
 363                         if (readStatus 
& FLAG_ICLASS_READER_AA
) { 
 365                                 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*5,8)); 
 366                                 for (int i 
= 0; i
<8; i
++) { 
 367                                         if (data
[8*5+i
] != 0xFF) { 
 371                                 PrintAndLog("      : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)"); 
 374                         if (tagFound 
&& !loop
) return 1; 
 376                         if (verbose
) PrintAndLog("Command execute timeout"); 
 386 static void usage_hf_iclass_reader(void) { 
 387         PrintAndLogEx(NORMAL
, "Act as a Iclass reader.  Look for iClass tags until Enter or the pm3 button is pressed\n"); 
 388         PrintAndLogEx(NORMAL
, "Usage:  hf iclass reader [h] [1]\n"); 
 389         PrintAndLogEx(NORMAL
, "Options:"); 
 390         PrintAndLogEx(NORMAL
, "    h   This help text"); 
 391         PrintAndLogEx(NORMAL
, "    1   read only 1 tag"); 
 392         PrintAndLogEx(NORMAL
, "Examples:"); 
 393         PrintAndLogEx(NORMAL
, "        hf iclass reader 1"); 
 397 static int CmdHFiClassReader(const char *Cmd
) { 
 398         char cmdp 
= tolower(param_getchar(Cmd
, 0)); 
 400                 usage_hf_iclass_reader(); 
 403         bool findone 
= (cmdp 
== '1') ? false : true; 
 404         return HFiClassReader(findone
, true); 
 408 static void usage_hf_iclass_eload(void) { 
 409         PrintAndLog("Loads iclass tag-dump into emulator memory on device"); 
 410         PrintAndLog("Usage:  hf iclass eload f <filename>"); 
 412         PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin"); 
 416 static int CmdHFiClassELoad(const char *Cmd
) { 
 418         char opt 
= param_getchar(Cmd
, 0); 
 419         if (strlen(Cmd
)<1 || opt 
== 'h') { 
 420                 usage_hf_iclass_eload(); 
 424         //File handling and reading 
 426         char filename
[FILE_PATH_SIZE
]; 
 427         if (opt 
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) { 
 428                 f 
= fopen(filename
, "rb"); 
 430                 usage_hf_iclass_eload(); 
 435                 PrintAndLog("Failed to read from file '%s'", filename
); 
 439         fseek(f
, 0, SEEK_END
); 
 440         long fsize 
= ftell(f
); 
 441         fseek(f
, 0, SEEK_SET
); 
 444                 PrintAndLog("Error, when getting filesize"); 
 449         uint8_t *dump 
= malloc(fsize
); 
 451         size_t bytes_read 
= fread(dump
, 1, fsize
, f
); 
 454         printIclassDumpInfo(dump
); 
 457         if (bytes_read 
< fsize
) { 
 458                 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize 
); 
 463         uint32_t bytes_sent 
= 0; 
 464         uint32_t bytes_remaining  
= bytes_read
; 
 466         while (bytes_remaining 
> 0) { 
 467                 uint32_t bytes_in_packet 
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
); 
 468                 UsbCommand c 
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}}; 
 469                 memcpy(c
.d
.asBytes
, dump
+bytes_sent
, bytes_in_packet
); 
 471                 bytes_remaining 
-= bytes_in_packet
; 
 472                 bytes_sent 
+= bytes_in_packet
; 
 475         PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
); 
 480 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) { 
 481         FILE *f 
= fopen(filename
, "rb"); 
 483                 PrintAndLog("Failed to read from file '%s'", filename
); 
 486         fseek(f
, 0, SEEK_END
); 
 487         long fsize 
= ftell(f
); 
 488         fseek(f
, 0, SEEK_SET
); 
 489         size_t bytes_read 
= fread(buffer
, 1, len
, f
); 
 493                 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
); 
 496         if(bytes_read 
!= len
) 
 498                 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
); 
 505 static void usage_hf_iclass_decrypt(void) { 
 506         PrintAndLog("Usage: hf iclass decrypt f <tagdump>"); 
 508         PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); 
 509         PrintAndLog("in the working directory. The file should be 16 bytes binary data"); 
 511         PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin"); 
 513         PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. "); 
 514         PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,"); 
 515         PrintAndLog("which is defined by the configuration block."); 
 519 static int CmdHFiClassDecrypt(const char *Cmd
) { 
 520         uint8_t key
[16] = { 0 }; 
 521         if(readKeyfile("iclass_decryptionkey.bin", 16, key
)) 
 523                 usage_hf_iclass_decrypt(); 
 526         PrintAndLog("Decryption file found... "); 
 527         char opt 
= param_getchar(Cmd
, 0); 
 528         if (strlen(Cmd
)<1 || opt 
== 'h') { 
 529                 usage_hf_iclass_decrypt(); 
 533         //Open the tagdump-file 
 535         char filename
[FILE_PATH_SIZE
]; 
 536         if(opt 
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) { 
 537                 f 
= fopen(filename
, "rb"); 
 539                         PrintAndLog("Could not find file %s", filename
); 
 543                 usage_hf_iclass_decrypt(); 
 547         fseek(f
, 0, SEEK_END
); 
 548         long fsize 
= ftell(f
); 
 549         fseek(f
, 0, SEEK_SET
); 
 550         uint8_t enc_dump
[8] = {0}; 
 551         uint8_t *decrypted 
= malloc(fsize
); 
 552         mbedtls_des3_context ctx 
= { {0} }; 
 553         mbedtls_des3_set2key_dec( &ctx
, key
); 
 554         size_t bytes_read 
= fread(enc_dump
, 1, 8, f
); 
 556         //Use the first block (CSN) for filename 
 557         char outfilename
[FILE_PATH_SIZE
] = { 0 }; 
 558         snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted", 
 559                          enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3], 
 560                          enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]); 
 563         while(bytes_read 
== 8) 
 567                         memcpy(decrypted
+(blocknum
*8), enc_dump
, 8); 
 569                         mbedtls_des3_crypt_ecb(&ctx
, enc_dump
,decrypted 
+(blocknum
*8) ); 
 571                 printvar("decrypted block", decrypted 
+(blocknum
*8), 8); 
 572                 bytes_read 
= fread(enc_dump
, 1, 8, f
); 
 577         saveFile(outfilename
,"bin", decrypted
, blocknum
*8); 
 583 static void usage_hf_iclass_encrypt(void) { 
 584         PrintAndLog("Usage: hf iclass encrypt <BlockData>"); 
 586         PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); 
 587         PrintAndLog("in the working directory. The file should be 16 bytes binary data"); 
 589         PrintAndLog("example: hf iclass encrypt 0102030405060708"); 
 594 static int iClassEncryptBlkData(uint8_t *blkData
) { 
 595         uint8_t key
[16] = { 0 }; 
 596         if(readKeyfile("iclass_decryptionkey.bin", 16, key
)) 
 598                 usage_hf_iclass_encrypt(); 
 601         PrintAndLog("Decryption file found... "); 
 603         uint8_t encryptedData
[16]; 
 604         uint8_t *encrypted 
= encryptedData
; 
 605         mbedtls_des3_context ctx 
= { {0} }; 
 606         mbedtls_des3_set2key_enc( &ctx
, key
); 
 608         mbedtls_des3_crypt_ecb(&ctx
, blkData
,encrypted
); 
 609         //printvar("decrypted block", decrypted, 8); 
 610         memcpy(blkData
,encrypted
,8); 
 616 static int CmdHFiClassEncryptBlk(const char *Cmd
) { 
 617         uint8_t blkData
[8] = {0}; 
 618         char opt 
= param_getchar(Cmd
, 0); 
 619         if (strlen(Cmd
)<1 || opt 
== 'h') { 
 620                 usage_hf_iclass_encrypt(); 
 623         //get the bytes to encrypt 
 624         if (param_gethex(Cmd
, 0, blkData
, 16)) { 
 625                 PrintAndLog("BlockData must include 16 HEX symbols"); 
 628         if (!iClassEncryptBlkData(blkData
)) return 0; 
 629         printvar("encrypted block", blkData
, 8); 
 634 static void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) { 
 637         memcpy(WB
+1, data
, 8); 
 638         doMAC_N(WB
, sizeof(WB
), div_key
, MAC
); 
 639         //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]); 
 643 static bool iClass_select(uint8_t *CSN
, bool verbose
, bool cleartrace
, bool init
) { 
 645         UsbCommand c 
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
}}; 
 646         if (init
) c
.arg
[0] |= FLAG_ICLASS_READER_INIT
; 
 647         if (cleartrace
) c
.arg
[0] |= FLAG_ICLASS_READER_CLEARTRACE
; 
 650         clearCommandBuffer(); 
 652         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 653                 PrintAndLog("Command execute timeout"); 
 657         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 658         uint8_t *data 
= resp
.d
.asBytes
; 
 660         if (isOK 
& FLAG_ICLASS_READER_CSN
) { 
 661                 memcpy(CSN
, data
, 8); 
 662                 if (verbose
) PrintAndLog("CSN: %s", sprint_hex(CSN
, 8)); 
 664                 PrintAndLog("Failed to select card! Aborting"); 
 671 static void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){ 
 672         uint8_t keytable
[128] = {0}; 
 673         uint8_t key_index
[8] = {0}; 
 675                 uint8_t key_sel
[8] = { 0 }; 
 676                 uint8_t key_sel_p
[8] = { 0 }; 
 677                 hash2(KEY
, keytable
); 
 678                 hash1(CSN
, key_index
); 
 679                 for(uint8_t i 
= 0; i 
< 8 ; i
++) 
 680                         key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF; 
 682                 //Permute from iclass format to standard format 
 683                 permutekey_rev(key_sel
, key_sel_p
); 
 684                 diversifyKey(CSN
, key_sel_p
, div_key
); 
 686                 diversifyKey(CSN
, KEY
, div_key
); 
 691 static bool iClass_authenticate(uint8_t *CSN
, uint8_t *KEY
, uint8_t *MAC
, uint8_t *div_key
, bool use_credit_key
, bool elite
, bool rawkey
, bool replay
, bool verbose
) { 
 694         if (rawkey 
|| replay
) 
 695                 memcpy(div_key
, KEY
, 8); 
 697                 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
); 
 699         char keytypetext
[23] = "legacy diversified key"; 
 701                 strcpy(keytypetext
, "raw key"); 
 703                 strcpy(keytypetext
, "replayed NR/MAC"); 
 705                 strcpy(keytypetext
, "Elite diversified key"); 
 708         if (verbose
) PrintAndLog("Authenticating with %s: %s", keytypetext
, sprint_hex(div_key
, 8)); 
 711         UsbCommand d 
= {CMD_ICLASS_READCHECK
, {2, use_credit_key
, 0}}; 
 713         clearCommandBuffer(); 
 716         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 717                 if (verbose
) PrintAndLog("Auth Command (READCHECK[2]) execute timeout"); 
 720         bool isOK 
= resp
.arg
[0]; 
 722                 if (verbose
) PrintAndLog("Couldn't get Card Challenge"); 
 727                 memcpy(MAC
, KEY
+4, 4); 
 730                 memcpy(CCNR
, resp
.d
.asBytes
, 8); 
 731                 memset(CCNR
+8, 0x00, 4); // default NR = {0, 0, 0, 0} 
 732                 doMAC(CCNR
, div_key
, MAC
); 
 735         d
.cmd 
= CMD_ICLASS_CHECK
; 
 737                 memcpy(d
.d
.asBytes
, KEY
, 8); 
 739                 memset(d
.d
.asBytes
, 0x00, 4); // default NR = {0, 0, 0, 0} 
 740                 memcpy(d
.d
.asBytes
+4, MAC
, 4); 
 742         clearCommandBuffer(); 
 744         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 745                 if (verbose
) PrintAndLog("Auth Command (CHECK) execute timeout"); 
 750                 if (verbose
) PrintAndLog("Authentication error"); 
 757 static void usage_hf_iclass_dump(void) { 
 758         PrintAndLog("Usage:  hf iclass dump f <fileName> k <Key> c <CreditKey> e|r|n\n"); 
 759         PrintAndLog("Options:"); 
 760         PrintAndLog("  f <filename> : specify a filename to save dump to"); 
 761         PrintAndLog("  k <Key>      : *Debit Key (AA1) as 16 hex symbols (8 bytes) or 1 hex to select key from memory"); 
 762         PrintAndLog("  c <CreditKey>: Credit Key (AA2) as 16 hex symbols (8 bytes) or 1 hex to select key from memory"); 
 763         PrintAndLog("  e            : If 'e' is specified, the keys are interpreted as Elite"); 
 764         PrintAndLog("                 Custom Keys (KCus), which can be obtained via reader-attack"); 
 765         PrintAndLog("                 See 'hf iclass sim 2'. This key should be on iclass-format"); 
 766         PrintAndLog("  r            : If 'r' is specified, keys are interpreted as raw blocks 3/4"); 
 767         PrintAndLog("  n            : If 'n' is specified, keys are interpreted as NR/MAC pairs which can be obtained by 'hf iclass snoop'"); 
 768         PrintAndLog("  NOTE: * = required"); 
 769         PrintAndLog("Samples:"); 
 770         PrintAndLog("  hf iclass dump k 001122334455667B"); 
 771         PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B"); 
 772         PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA e"); 
 776 static void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) { 
 778         memcpy(&mem_config
, iclass_dump 
+ 13,1); 
 780         uint8_t filemaxblock 
= filesize 
/ 8; 
 781         if (mem_config 
& 0x80) 
 785         //PrintAndLog   ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock); 
 789         if ((endblock 
> maxmemcount
) || (endblock 
== 0)) 
 790                 endblock 
= maxmemcount
; 
 792         // remember endblock need to relate to zero-index arrays. 
 793         if (endblock 
> filemaxblock
-1) 
 794                 endblock 
= filemaxblock
; 
 797         printf("------+--+-------------------------+\n"); 
 798         while (i 
<= endblock
) { 
 799                 uint8_t *blk 
= iclass_dump 
+ (i 
* 8); 
 800                 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) ); 
 803         printf("------+--+-------------------------+\n"); 
 807 static int CmdHFiClassReader_Dump(const char *Cmd
) { 
 809         uint8_t MAC
[4] = {0x00,0x00,0x00,0x00}; 
 810         uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 811         uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 813         uint8_t AA1_maxBlk 
= 0; 
 815         uint8_t app_areas 
= 1; 
 817         uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 818         uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 821         uint8_t fileNameLen 
= 0; 
 822         char filename
[FILE_PATH_SIZE
]={0}; 
 823         char tempStr
[50] = {0}; 
 824         bool have_debit_key 
= false; 
 825         bool have_credit_key 
= false; 
 826         bool use_credit_key 
= false; 
 829         bool NRMAC_replay 
= false; 
 831         bool verbose 
= false; 
 834         while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) { 
 835                 switch(param_getchar(Cmd
, cmdp
)) { 
 838                                 usage_hf_iclass_dump(); 
 842                                 have_credit_key 
= true; 
 843                                 dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
)); 
 845                                         errors 
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
); 
 846                                 } else if (dataLen 
== 1) { 
 847                                         keyNbr 
= param_get8(Cmd
, cmdp
+1); 
 848                                         if (keyNbr 
< ICLASS_KEYS_MAX
) { 
 849                                                 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8); 
 851                                                 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
 855                                         PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
 867                                 fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
)); 
 868                                 if (fileNameLen 
< 1) { 
 869                                         PrintAndLog("No filename found after f"); 
 876                                 have_debit_key 
= true; 
 877                                 dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
)); 
 879                                         errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
 880                                 } else if (dataLen 
== 1) { 
 881                                         keyNbr 
= param_get8(Cmd
, cmdp
+1); 
 882                                         if (keyNbr 
< ICLASS_KEYS_MAX
) { 
 883                                                 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
 885                                                 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
 889                                         PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
 910                                 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
 916         if (elite 
+ rawkey 
+ NRMAC_replay 
> 1) { 
 917                 PrintAndLog("You cannot combine the 'e', 'r', and 'n' options\n"); 
 921         if (errors 
|| cmdp 
< 2) { 
 922                 usage_hf_iclass_dump(); 
 926         // if only credit key is given: try for AA1 as well (not for iclass but for some picopass this will work) 
 927         if (!have_debit_key 
&& have_credit_key
) { 
 928                 use_credit_key 
= true; 
 929                 memcpy(KEY
, CreditKEY
, 8); 
 932         // clear trace and get first 3 blocks 
 933         UsbCommand c 
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_INIT 
| FLAG_ICLASS_READER_CLEARTRACE 
| FLAG_ICLASS_READER_CSN 
| FLAG_ICLASS_READER_CONF 
| FLAG_ICLASS_READER_CC
}}; 
 935         uint8_t tag_data
[256*8]; 
 937         clearCommandBuffer(); 
 939         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 940                 PrintAndLog("Command execute timeout"); 
 945         uint8_t readStatus 
= resp
.arg
[0] & 0xff; 
 946         uint8_t *data 
= resp
.d
.asBytes
; 
 947         uint8_t status_mask 
= FLAG_ICLASS_READER_CSN 
| FLAG_ICLASS_READER_CONF 
| FLAG_ICLASS_READER_CC
; 
 949         if (readStatus 
!= status_mask
) { 
 950                 PrintAndLog("No tag found ..."); 
 953                 memcpy(tag_data
, data
, 8*3); 
 954                 if (verbose
) PrintAndLog("CSN: %s", sprint_hex(tag_data
, 8)); 
 955                 AA1_maxBlk 
= data
[8]; 
 956                 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
); 
 957                 // large memory - not able to dump pages currently 
 958                 if (AA1_maxBlk 
> maxBlk
) AA1_maxBlk 
= maxBlk
; 
 961         // authenticate with debit key (or credit key if we have no debit key) and get div_key - later store in dump block 3 
 962         if (!iClass_authenticate(tag_data
, KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, NRMAC_replay
, verbose
)){ 
 968         UsbCommand w 
= {CMD_ICLASS_DUMP
}; 
 969         uint32_t blocksRead 
= 0; 
 970         for (blockno 
= 3; blockno 
<= AA1_maxBlk
; blockno 
+= blocksRead
) { 
 972                 w
.arg
[1] = AA1_maxBlk 
- blockno 
+ 1; 
 973                 clearCommandBuffer(); 
 975                 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 976                         PrintAndLog("Command execute time-out 1"); 
 980                 blocksRead 
= resp
.arg
[1]; 
 981                 bool isOK 
= resp
.arg
[0]; 
 983                         PrintAndLog("Reading AA1 block failed"); 
 987                 memcpy(tag_data 
+ blockno
*8, resp
.d
.asBytes
, blocksRead
*8); 
 990         // do we still need to read more blocks (AA2 enabled)? 
 991         if (have_credit_key 
&& maxBlk 
> AA1_maxBlk
) { 
 992                 if (!use_credit_key
) { 
 993                         //turn off hf field before authenticating with different key 
 995                         // AA2 authenticate credit key and git c_div_key - later store in dump block 4 
 997                         if (!iClass_select(CSN
, verbose
, false, true) || !iClass_authenticate(CSN
, CreditKEY
, MAC
, c_div_key
, true, false, false, NRMAC_replay
, verbose
)){ 
1002                 for ( ; blockno 
<= maxBlk
; blockno 
+= blocksRead
) { 
1004                         w
.arg
[1] = maxBlk 
- blockno 
+ 1; 
1005                         clearCommandBuffer(); 
1007                         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
1008                                 PrintAndLog("Command execute time-out 1"); 
1012                         blocksRead 
= resp
.arg
[1]; 
1013                         bool isOK 
= resp
.arg
[0]; 
1015                                 PrintAndLog("Reading AA2 block failed"); 
1019                         memcpy(tag_data 
+ blockno
*8, resp
.d
.asBytes
, blocksRead
*8); 
1025         // add diversified keys to dump 
1026         if (have_debit_key
) { 
1027                 memcpy(tag_data 
+ 3*8, div_key
, 8); 
1029                 memset(tag_data 
+ 3*8, 0xff, 8); 
1031         if (have_credit_key
) { 
1032                 memcpy(tag_data 
+ 4*8, c_div_key
, 8); 
1034                 memset(tag_data 
+ 4*8, 0xff, 8); 
1038         printf("------+--+-------------------------+\n"); 
1039         printf("CSN   |00| %s|\n",sprint_hex(tag_data
, 8)); 
1040         printIclassDumpContents(tag_data
, 1, blockno
-1, blockno
*8); 
1042         if (filename
[0] == 0) { 
1043                 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x", 
1044                         tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3], 
1045                         tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]); 
1048         // save the dump to .bin file 
1049         PrintAndLog("Saving dump file - %d blocks read", blockno
); 
1050         saveFile(filename
, "bin", tag_data
, blockno
*8); 
1055 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool NRMAC_replay
, bool verbose
) { 
1057         uint8_t MAC
[4] = {0x00,0x00,0x00,0x00}; 
1058         uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1061         if (!iClass_select(CSN
, verbose
, true, true) || !iClass_authenticate(CSN
, KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, NRMAC_replay
, verbose
)) { 
1068         Calc_wb_mac(blockno
, bldata
, div_key
, MAC
); 
1070         UsbCommand w 
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}}; 
1071         memcpy(w
.d
.asBytes
, bldata
, 8); 
1072         memcpy(w
.d
.asBytes 
+ 8, MAC
, 4); 
1074         clearCommandBuffer(); 
1076         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
1077                 PrintAndLog("Write Command execute timeout"); 
1081         bool isOK 
= resp
.arg
[0]; 
1083                 PrintAndLog("Write Block Failed"); 
1088         PrintAndLog("Write Block Successful"); 
1093 static void usage_hf_iclass_writeblock(void) { 
1094         PrintAndLog("Options:"); 
1095         PrintAndLog("  b <Block> : The block number as 2 hex symbols"); 
1096         PrintAndLog("  d <data>  : Set the Data to write as 16 hex symbols"); 
1097         PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory"); 
1098         PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n"); 
1099         PrintAndLog("  e         : If 'e' is specified, elite computations applied to key"); 
1100         PrintAndLog("  r         : If 'r' is specified, no computations applied to key"); 
1101         PrintAndLog("Samples:"); 
1102         PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B"); 
1103         PrintAndLog("  hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c"); 
1104         PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0"); 
1108 static int CmdHFiClass_WriteBlock(const char *Cmd
) { 
1110         uint8_t bldata
[8]={0,0,0,0,0,0,0,0}; 
1111         uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1113         uint8_t dataLen 
= 0; 
1114         char tempStr
[50] = {0}; 
1115         bool use_credit_key 
= false; 
1117         bool rawkey 
= false; 
1118         bool errors 
= false; 
1121         while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
)     { 
1122                 switch(param_getchar(Cmd
, cmdp
)) { 
1125                         usage_hf_iclass_writeblock(); 
1129                         if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) { 
1130                                 PrintAndLog("Block No must include 2 HEX symbols\n"); 
1137                         use_credit_key 
= true; 
1142                         if (param_gethex(Cmd
, cmdp
+1, bldata
, 16)) { 
1143                                 PrintAndLog("Data must include 16 HEX symbols\n"); 
1155                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
)); 
1156                         if (dataLen 
== 16) { 
1157                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1158                         } else if (dataLen 
== 1) { 
1159                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1160                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1161                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
1163                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
1167                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
1178                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1183                         usage_hf_iclass_writeblock(); 
1188         if (elite 
&& rawkey
) { 
1189                 PrintAndLog("You cannot combine the 'e' and 'r' options\n"); 
1194                 usage_hf_iclass_writeblock(); 
1197         int ans 
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, false, true); 
1203 static void usage_hf_iclass_clone(void) { 
1204         PrintAndLog("Usage:  hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r"); 
1205         PrintAndLog("Options:"); 
1206         PrintAndLog("  f <filename>: specify a filename to clone from"); 
1207         PrintAndLog("  b <Block>   : The first block to clone as 2 hex symbols"); 
1208         PrintAndLog("  l <Last Blk>: Set the Data to write as 16 hex symbols"); 
1209         PrintAndLog("  k <Key>     : Access Key as 16 hex symbols or 1 hex to select key from memory"); 
1210         PrintAndLog("  c           : If 'c' is specified, the key set is assumed to be the credit key\n"); 
1211         PrintAndLog("  e           : If 'e' is specified, elite computations applied to key"); 
1212         PrintAndLog("  r           : If 'r' is specified, no computations applied to key"); 
1213         PrintAndLog("Samples:"); 
1214         PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e"); 
1215         PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0"); 
1216         PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e"); 
1220 static int CmdHFiClassCloneTag(const char *Cmd
) { 
1221         char filename
[FILE_PATH_SIZE
] = {0}; 
1222         char tempStr
[50]={0}; 
1223         uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1225         uint8_t fileNameLen 
= 0; 
1226         uint8_t startblock 
= 0; 
1227         uint8_t endblock 
= 0; 
1228         uint8_t dataLen 
= 0; 
1229         bool use_credit_key 
= false; 
1231         bool rawkey 
= false; 
1232         bool errors 
= false; 
1235         while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) { 
1236                 switch(param_getchar(Cmd
, cmdp
)) { 
1239                         usage_hf_iclass_clone(); 
1243                         if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) { 
1244                                 PrintAndLog("Start Block No must include 2 HEX symbols\n"); 
1251                         use_credit_key 
= true; 
1261                         fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
)); 
1262                         if (fileNameLen 
< 1) { 
1263                                 PrintAndLog("No filename found after f"); 
1270                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
)); 
1271                         if (dataLen 
== 16) { 
1272                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1273                         } else if (dataLen 
== 1) { 
1274                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1275                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1276                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
1278                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
1282                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
1289                         if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) { 
1290                                 PrintAndLog("Start Block No must include 2 HEX symbols\n"); 
1301                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1306                         usage_hf_iclass_clone(); 
1312                 usage_hf_iclass_clone(); 
1318         iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12]; 
1320         if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) { 
1321                 PrintAndLog("Trying to write too many blocks at once.  Max: %d", USB_CMD_DATA_SIZE
/8); 
1323         // file handling and reading 
1324         f 
= fopen(filename
,"rb"); 
1326                 PrintAndLog("Failed to read from file '%s'", filename
); 
1331                 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4"); 
1335         // now read data from the file from block 6 --- 19 
1336         // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data 
1337         // 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, 
1338         // else we have to create a share memory 
1340         fseek(f
, startblock
*8, SEEK_SET
); 
1341         if (fread(tag_data
, sizeof(iclass_block_t
), endblock 
- startblock 
+ 1, f
) == 0 ) { 
1342                 PrintAndLog("File reading error."); 
1347         uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
1348         uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1351         if (!iClass_select(CSN
, true, false, false) || !iClass_authenticate(CSN
, KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false, true)) { 
1356         UsbCommand w 
= {CMD_ICLASS_CLONE
, {startblock
, endblock
}}; 
1358         // calculate all mac for every the block we will write 
1359         for (i 
= startblock
; i 
<= endblock
; i
++){ 
1360                 Calc_wb_mac(i
, tag_data
[i 
- startblock
].d
, div_key
, MAC
); 
1361                 // usb command d start pointer = d + (i - 6) * 12 
1362                 // memcpy(pointer,tag_data[i - 6],8) 8 bytes 
1363                 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes; 
1365                 ptr 
= w
.d
.asBytes 
+ (i 
- startblock
) * 12; 
1366                 memcpy(ptr
, &(tag_data
[i 
- startblock
].d
[0]), 8); 
1367                 memcpy(ptr 
+ 8,MAC
, 4); 
1370         for (i 
= 0; i 
<= endblock 
- startblock
;i
++){ 
1371                 memcpy(p
,w
.d
.asBytes 
+ (i 
* 12),12); 
1372                 printf("Block |%02x|",i 
+ startblock
); 
1373                 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]); 
1374                 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]); 
1379         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) 
1381                 PrintAndLog("Command execute timeout"); 
1389 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool NRMAC_replay
, bool verbose
, bool auth
) { 
1391         uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
1392         uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1395         if (!iClass_select(CSN
, verbose
, true, true)) { 
1401                 if (!iClass_authenticate(CSN
, KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, NRMAC_replay
, verbose
)) { 
1408         UsbCommand w 
= {CMD_ICLASS_READBLOCK
, {blockno
}}; 
1409         clearCommandBuffer(); 
1411         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
1412                 PrintAndLog("Command execute timeout"); 
1416         bool isOK 
= resp
.arg
[0]; 
1418                 PrintAndLog("Read Block Failed"); 
1422         //data read is stored in: resp.d.asBytes[0-15] 
1424                 PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8)); 
1430 static void usage_hf_iclass_readblock(void) { 
1431         PrintAndLog("Usage:  hf iclass readblk b <Block> k <Key> [c] [e|r|n]\n"); 
1432         PrintAndLog("Options:"); 
1433         PrintAndLog("  b <Block> : The block number as 2 hex symbols"); 
1434         PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory"); 
1435         PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n"); 
1436         PrintAndLog("  e         : If 'e' is specified, elite computations applied to key"); 
1437         PrintAndLog("  r         : If 'r' is specified, no computations applied to key"); 
1438         PrintAndLog("  n         : If 'n' is specified, <Key> specifies a NR/MAC pair which can be obtained by 'hf iclass snoop'"); 
1439         PrintAndLog("Samples:"); 
1440         PrintAndLog("  hf iclass readblk b 06 k 0011223344556677"); 
1441         PrintAndLog("  hf iclass readblk b 1B k 0011223344556677 c"); 
1442         PrintAndLog("  hf iclass readblk b 0A k 0"); 
1446 static int CmdHFiClass_ReadBlock(const char *Cmd
) { 
1448         uint8_t keyType 
= 0x88; //debit key 
1449         uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1451         uint8_t dataLen 
= 0; 
1452         char tempStr
[50] = {0}; 
1454         bool rawkey 
= false; 
1455         bool NRMAC_replay 
= false; 
1456         bool errors 
= false; 
1460         while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) { 
1461                 switch (param_getchar(Cmd
, cmdp
)) { 
1464                                 usage_hf_iclass_readblock(); 
1468                                 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) { 
1469                                         PrintAndLog("Block No must include 2 HEX symbols\n"); 
1487                                 dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
)); 
1488                                 if (dataLen 
== 16) { 
1489                                         errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1490                                 } else if (dataLen 
== 1) { 
1491                                         keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1492                                         if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1493                                                 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
1495                                                 PrintAndLog("\nERROR: KeyNbr is invalid\n"); 
1499                                         PrintAndLog("\nERROR: Key is incorrect length\n"); 
1511                                 NRMAC_replay 
= true; 
1515                                 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1521         if (elite 
+ rawkey 
+ NRMAC_replay 
> 1) { 
1522                 PrintAndLog("You cannot combine the 'e', 'r', and 'n' options\n"); 
1527                 usage_hf_iclass_readblock(); 
1532                 usage_hf_iclass_readblock(); 
1536                 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication."); 
1538         return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, NRMAC_replay
, true, auth
); 
1542 static int CmdHFiClass_loclass(const char *Cmd
) { 
1543         char opt 
= param_getchar(Cmd
, 0); 
1545         if (strlen(Cmd
)<1 || opt 
== 'h') { 
1546                 PrintAndLog("Usage: hf iclass loclass [options]"); 
1547                 PrintAndLog("Options:"); 
1548                 PrintAndLog("h             Show this help"); 
1549                 PrintAndLog("t             Perform self-test"); 
1550                 PrintAndLog("f <filename>  Bruteforce iclass dumpfile"); 
1551                 PrintAndLog("                   An iclass dumpfile is assumed to consist of an arbitrary number of"); 
1552                 PrintAndLog("                   malicious CSNs, and their protocol responses"); 
1553                 PrintAndLog("                   The binary format of the file is expected to be as follows: "); 
1554                 PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); 
1555                 PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); 
1556                 PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); 
1557                 PrintAndLog("                  ... totalling N*24 bytes"); 
1560         char fileName
[255] = {0}; 
1562                 if(param_getstr(Cmd
, 1, fileName
, sizeof(fileName
)) > 0) { 
1563                         return bruteforceFileNoKeys(fileName
); 
1565                         PrintAndLog("You must specify a filename"); 
1567         } else if(opt 
== 't') { 
1568                 int errors 
= testCipherUtils(); 
1569                 errors 
+= testMAC(); 
1570                 errors 
+= doKeyTests(0); 
1571                 errors 
+= testElite(); 
1573                         prnlog("OBS! There were errors!!!"); 
1582 static void usage_hf_iclass_readtagfile() { 
1583         PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]"); 
1587 static int CmdHFiClassReadTagFile(const char *Cmd
) { 
1592         char filename
[FILE_PATH_SIZE
]; 
1593         if (param_getstr(Cmd
, 0, filename
, sizeof(filename
)) < 1) { 
1594                 usage_hf_iclass_readtagfile(); 
1597         if (param_getstr(Cmd
, 1, tempnum
, sizeof(tempnum
)) < 1) 
1600                 sscanf(tempnum
,"%d",&startblock
); 
1602         if (param_getstr(Cmd
,2, tempnum
, sizeof(tempnum
)) < 1) 
1605                 sscanf(tempnum
,"%d",&endblock
); 
1606         // file handling and reading 
1607         f 
= fopen(filename
,"rb"); 
1609                 PrintAndLog("Failed to read from file '%s'", filename
); 
1612         fseek(f
, 0, SEEK_END
); 
1613         long fsize 
= ftell(f
); 
1614         fseek(f
, 0, SEEK_SET
); 
1617                 PrintAndLog("Error, when getting filesize"); 
1622         uint8_t *dump 
= malloc(fsize
); 
1624         size_t bytes_read 
= fread(dump
, 1, fsize
, f
); 
1626         uint8_t *csn 
= dump
; 
1627         printf("------+--+-------------------------+\n"); 
1628         printf("CSN   |00| %s|\n", sprint_hex(csn
, 8) ); 
1629         //    printIclassDumpInfo(dump); 
1630         printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
); 
1636 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) { 
1637         uint64_t new_div = 0x00; 
1643 uint64_t hexarray_to_uint64(uint8_t *key) { 
1646         for (int i = 0;i < 8;i++) 
1647                 sprintf(&temp[(i *2)],"%02X",key[i]); 
1649         if (sscanf(temp,"%016" SCNx64,&uint_key) < 1) 
1656 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite) 
1657 //calculate and return xor_div_key (ready for a key write command) 
1658 //print all div_keys if verbose 
1659 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){ 
1660         uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1661         uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1663         HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
); 
1665         HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
); 
1667         for (uint8_t i 
= 0; i 
< sizeof(old_div_key
); i
++){ 
1668                 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
]; 
1671                 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8)); 
1672                 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8)); 
1673                 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8)); 
1678 static void usage_hf_iclass_calc_newkey(void) { 
1679         PrintAndLog("HELP :  Manage iClass Keys in client memory:\n"); 
1680         PrintAndLog("Usage:  hf iclass calc_newkey o <Old key> n <New key> s [csn] e"); 
1681         PrintAndLog("  Options:"); 
1682         PrintAndLog("  o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol"); 
1683         PrintAndLog("  n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol"); 
1684         PrintAndLog("  s <csn>    : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)"); 
1685         PrintAndLog("  e          : specify new key as elite calc"); 
1686         PrintAndLog("  ee         : specify old and new key as elite calc"); 
1687         PrintAndLog("Samples:"); 
1688         PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee"); 
1689         PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e"); 
1690         PrintAndLog(" std to std read csn      : hf iclass calcnewkey o 1122334455667788 n 2233445566778899"); 
1691         PrintAndLog("NOTE: * = required\n"); 
1695 static int CmdHFiClassCalcNewKey(const char *Cmd
) { 
1696         uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1697         uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1698         uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1699         uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1701         uint8_t dataLen 
= 0; 
1702         char tempStr
[50] = {0}; 
1703         bool givenCSN 
= false; 
1704         bool oldElite 
= false; 
1706         bool errors 
= false; 
1709         while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) { 
1710                 switch(param_getchar(Cmd
, cmdp
)) { 
1713                         usage_hf_iclass_calc_newkey(); 
1717                         dataLen 
= param_getstr(Cmd
, cmdp
, tempStr
, sizeof(tempStr
)); 
1725                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
)); 
1726                         if (dataLen 
== 16) { 
1727                                 errors 
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
); 
1728                         } else if (dataLen 
== 1) { 
1729                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1730                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1731                                         memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8); 
1733                                         PrintAndLog("\nERROR: NewKey Nbr is invalid\n"); 
1737                                 PrintAndLog("\nERROR: NewKey is incorrect length\n"); 
1744                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
)); 
1745                         if (dataLen 
== 16) { 
1746                                 errors 
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
); 
1747                         } else if (dataLen 
== 1) { 
1748                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1749                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1750                                         memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8); 
1752                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
1756                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
1764                         if (param_gethex(Cmd
, cmdp
+1, CSN
, 16)) { 
1765                                 usage_hf_iclass_calc_newkey(); 
1771                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1776                         usage_hf_iclass_calc_newkey(); 
1782                 usage_hf_iclass_calc_newkey(); 
1787                 if (!iClass_select(CSN
, true, true, true)) { 
1793         HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true); 
1798 static int loadKeys(char *filename
) { 
1800         f 
= fopen(filename
,"rb"); 
1802                 PrintAndLog("Failed to read from file '%s'", filename
); 
1805         fseek(f
, 0, SEEK_END
); 
1806         long fsize 
= ftell(f
); 
1807         fseek(f
, 0, SEEK_SET
); 
1810                 PrintAndLog("Error, when getting filesize"); 
1815         uint8_t *dump 
= malloc(fsize
); 
1817         size_t bytes_read 
= fread(dump
, 1, fsize
, f
); 
1819         if (bytes_read 
> ICLASS_KEYS_MAX 
* 8){ 
1820                 PrintAndLog("File is too long to load - bytes: %u", bytes_read
); 
1825         for (; i 
< bytes_read
/8; i
++){ 
1826                 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8); 
1829         PrintAndLog("%u keys loaded", i
); 
1834 static int saveKeys(char *filename
) { 
1836         f 
= fopen(filename
,"wb"); 
1838                 printf("error opening file %s\n",filename
); 
1841         for (uint8_t i 
= 0; i 
< ICLASS_KEYS_MAX
; i
++){ 
1842                 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){ 
1843                         PrintAndLog("save key failed to write to file: %s", filename
); 
1852 static int printKeys(void) { 
1854         for (uint8_t i 
= 0; i 
< ICLASS_KEYS_MAX
; i
++){ 
1855                 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8)); 
1862 static void usage_hf_iclass_managekeys(void) { 
1863         PrintAndLog("HELP :  Manage iClass Keys in client memory:\n"); 
1864         PrintAndLog("Usage:  hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n"); 
1865         PrintAndLog("  Options:"); 
1866         PrintAndLog("  n <keynbr>  : specify the keyNbr to set in memory"); 
1867         PrintAndLog("  k <key>     : set a key in memory"); 
1868         PrintAndLog("  f <filename>: specify a filename to use with load or save operations"); 
1869         PrintAndLog("  s           : save keys in memory to file specified by filename"); 
1870         PrintAndLog("  l           : load keys to memory from file specified by filename"); 
1871         PrintAndLog("  p           : print keys loaded into memory\n"); 
1872         PrintAndLog("Samples:"); 
1873         PrintAndLog(" set key      : hf iclass managekeys n 0 k 1122334455667788"); 
1874         PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s"); 
1875         PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l"); 
1876         PrintAndLog(" print keys   : hf iclass managekeys p\n"); 
1880 static int CmdHFiClassManageKeys(const char *Cmd
) { 
1882         uint8_t dataLen 
= 0; 
1883         uint8_t KEY
[8] = {0}; 
1884         char filename
[FILE_PATH_SIZE
]; 
1885         uint8_t fileNameLen 
= 0; 
1886         bool errors 
= false; 
1887         uint8_t operation 
= 0; 
1891         while(param_getchar(Cmd
, cmdp
) != 0x00) { 
1892                 switch(param_getchar(Cmd
, cmdp
)) { 
1895                         usage_hf_iclass_managekeys(); 
1899                         fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
)); 
1900                         if (fileNameLen 
< 1) { 
1901                                 PrintAndLog("No filename found after f"); 
1908                         keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1909                         if (keyNbr 
>= ICLASS_KEYS_MAX
) { 
1910                                 PrintAndLog("Invalid block number"); 
1917                         operation 
+= 3; //set key 
1918                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
)); 
1919                         if (dataLen 
== 16) { //ul-c or ev1/ntag key length 
1920                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1922                                 PrintAndLog("\nERROR: Key is incorrect length\n"); 
1929                         operation 
+= 4; //print keys in memory 
1934                         operation 
+= 5; //load keys from file 
1939                         operation 
+= 6; //save keys to file 
1943                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1948                         usage_hf_iclass_managekeys(); 
1953         if (operation 
== 0){ 
1954                 PrintAndLog("no operation specified (load, save, or print)\n"); 
1955                 usage_hf_iclass_managekeys(); 
1960                 PrintAndLog("Too many operations specified\n"); 
1961                 usage_hf_iclass_managekeys(); 
1964         if (operation 
> 4 && fileNameLen 
== 0){ 
1965                 PrintAndLog("You must enter a filename when loading or saving\n"); 
1966                 usage_hf_iclass_managekeys(); 
1971                 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1; 
1972                 case 4: return printKeys(); 
1973                 case 5: return loadKeys(filename
); 
1974                 case 6: return saveKeys(filename
); 
1981 static int CmdHFiClassCheckKeys(const char *Cmd
) { 
1983         uint8_t mac
[4] = {0x00,0x00,0x00,0x00}; 
1984         uint8_t key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1985         uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1987         // elite key,  raw key, standard key 
1988         bool use_elite 
= false; 
1989         bool use_raw 
= false; 
1990         bool found_debit 
= false; 
1991         bool found_credit 
= false; 
1992         bool errors 
= false; 
1993         uint8_t cmdp 
= 0x00; 
1995         char filename
[FILE_PATH_SIZE
] = {0}; 
1996         uint8_t fileNameLen 
= 0; 
1998         uint8_t *keyBlock 
= NULL
, *p
; 
1999         int keyitems 
= 0, keycnt 
= 0; 
2001         while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) { 
2002                 switch (param_getchar(Cmd
, cmdp
)) { 
2005                         usage_hf_iclass_chk(); 
2009                         fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
)); 
2010                         if (fileNameLen 
< 1) { 
2011                                 PrintAndLog("No filename found after f"); 
2027                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
2034                 usage_hf_iclass_chk(); 
2038         if ( !(f 
= fopen( filename 
, "r")) ) { 
2039                 PrintAndLog("File: %s: not found or locked.", filename
); 
2043         while( fgets(buf
, sizeof(buf
), f
) ){ 
2044                 if (strlen(buf
) < 16 || buf
[15] == '\n') 
2047                 while (fgetc(f
) != '\n' && !feof(f
)) ;  //goto next line 
2049                 if( buf
[0]=='#' ) continue; //The line start with # is comment, skip 
2051                 if (!isxdigit(buf
[0])){ 
2052                         PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf
); 
2058                 p 
= realloc(keyBlock
, 8 * (keyitems 
+= 64)); 
2060                         PrintAndLog("Cannot allocate memory for default keys"); 
2067                 memset(keyBlock 
+ 8 * keycnt
, 0, 8); 
2068                 num_to_bytes(strtoull(buf
, NULL
, 16), 8, keyBlock 
+ 8 * keycnt
); 
2070                 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8)); 
2072                 memset(buf
, 0, sizeof(buf
)); 
2075         PrintAndLog("Loaded %2d keys from %s", keycnt
, filename
); 
2078         uint64_t t1 
= msclock(); 
2081         if (!iClass_select(CSN
, false, true, true)) { 
2082                 PrintAndLog("Couldn't select card"); 
2087         for (uint32_t c 
= 0; c 
< keycnt
; c
++) { 
2088                 printf("."); fflush(stdout
); 
2090                         int gc 
= getchar(); (void)gc
; 
2091                         printf("\naborted via keyboard!\n"); 
2095                 memcpy(key
, keyBlock 
+ 8 * c 
, 8); 
2098                 if (!iClass_authenticate(CSN
, key
, mac
, div_key
, false, use_elite
, use_raw
, false, false)) 
2102                 PrintAndLog("\n--------------------------------------------------------"); 
2103                 PrintAndLog("   Found AA1 debit key\t\t[%s]", sprint_hex(key
, 8)); 
2107                 if (!iClass_authenticate(CSN
, key
, mac
, div_key
, true, use_elite
, use_raw
, false, false)) 
2111                 PrintAndLog("\n--------------------------------------------------------"); 
2112                 PrintAndLog("   Found AA2 credit key\t\t[%s]", sprint_hex(key
, 8)); 
2113                 found_credit 
= true; 
2116                 if (found_debit 
&& found_credit
) 
2120         t1 
= msclock() - t1
; 
2122         PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1
/1000.0); 
2131 static void usage_hf_iclass_permutekey(void) { 
2132         PrintAndLogEx(NORMAL
, "Convert keys from standard NIST to iClass format (and vice versa)"); 
2133         PrintAndLogEx(NORMAL
, ""); 
2134         PrintAndLogEx(NORMAL
, "Usage:  hf iclass permute [h] [r] <key>"); 
2135         PrintAndLogEx(NORMAL
, "Options:"); 
2136         PrintAndLogEx(NORMAL
, "           h          This help"); 
2137         PrintAndLogEx(NORMAL
, "           r          reverse convert key from iClass to NIST format"); 
2138         PrintAndLogEx(NORMAL
, ""); 
2139         PrintAndLogEx(NORMAL
, "Examples:"); 
2140         PrintAndLogEx(NORMAL
, "      hf iclass permute r 0123456789abcdef"); 
2144 static int CmdHFiClassPermuteKey(const char *Cmd
) { 
2146         uint8_t key
[8] = {0}; 
2147         uint8_t data
[16] = {0}; 
2148         bool isReverse 
= false; 
2149         int len 
= sizeof(data
); 
2150         char cmdp 
= tolower(param_getchar(Cmd
, 0)); 
2151         if (strlen(Cmd
) == 0 || cmdp 
== 'h') { 
2152                 usage_hf_iclass_permutekey(); 
2158                 param_gethex_ex(Cmd
, 1, data
, &len
); 
2159         } else if (cmdp 
== 'f') { 
2160                 param_gethex_ex(Cmd
, 1, data
, &len
); 
2162                 param_gethex_ex(Cmd
, 0, data
, &len
); 
2167                 usage_hf_iclass_permutekey(); 
2173         memcpy(key
, data
, 8); 
2176                 // generate_rev(data, len); 
2177                 uint8_t key_std_format
[8] = {0}; 
2178                 permutekey_rev(key
, key_std_format
); 
2179                 PrintAndLogEx(SUCCESS
, "key in standard NIST format:     %s \n", sprint_hex(key_std_format
, 8)); 
2180                 // if (mbedtls_des_key_check_key_parity(key_std_format 
2182                 // generate(data, len); 
2183                 uint8_t key_iclass_format
[8] = {0}; 
2184                 permutekey(key
, key_iclass_format
); 
2185                 PrintAndLogEx(SUCCESS
, "key in iClass (permuted) format: %s \n", sprint_hex(key_iclass_format
, 8)); 
2191 static int CmdHelp(const char *Cmd
); 
2193 static command_t CommandTable
[] = { 
2194         {"help",        CmdHelp
,                        1,  "This help"}, 
2195         {"calcnewkey",  CmdHFiClassCalcNewKey
,          1,  "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"}, 
2196         {"chk",         CmdHFiClassCheckKeys
,           0,  "            Check keys"}, 
2197         {"clone",       CmdHFiClassCloneTag
,            0,  "[options..] Authenticate and Clone from iClass bin file"}, 
2198         {"decrypt",     CmdHFiClassDecrypt
,             1,  "[f <fname>] Decrypt tagdump" }, 
2199         {"dump",        CmdHFiClassReader_Dump
,         0,  "[options..] Authenticate and Dump iClass tag's AA1 and/or AA2"}, 
2200         {"eload",       CmdHFiClassELoad
,               0,  "[f <fname>] (experimental) Load data into iClass emulator memory"}, 
2201         {"encryptblk",  CmdHFiClassEncryptBlk
,          1,  "<BlockData> Encrypt given block data"}, 
2202         {"list",        CmdHFiClassList
,                0,  "            (Deprecated) List iClass history"}, 
2203         {"loclass",     CmdHFiClass_loclass
,            1,  "[options..] Use loclass to perform bruteforce of reader attack dump"}, 
2204         {"managekeys",  CmdHFiClassManageKeys
,          1,  "[options..] Manage the keys to use with iClass"}, 
2205         {"permutekey",  CmdHFiClassPermuteKey
,          1,  "            iClass key permutation"}, 
2206         {"readblk",     CmdHFiClass_ReadBlock
,          0,  "[options..] Authenticate and Read iClass block"}, 
2207         {"reader",      CmdHFiClassReader
,              0,  "            Look for iClass tags until a key or the pm3 button is pressed"}, 
2208         {"readtagfile", CmdHFiClassReadTagFile
,         1,  "[options..] Display Content from tagfile"}, 
2209         {"sim",         CmdHFiClassSim
,                 0,  "[options..] Simulate iClass tag"}, 
2210         {"snoop",       CmdHFiClassSnoop
,               0,  "            Eavesdrop iClass communication"}, 
2211         {"writeblk",    CmdHFiClass_WriteBlock
,         0,  "[options..] Authenticate and Write iClass block"}, 
2212         {NULL
, NULL
, 0, NULL
} 
2216 int CmdHFiClass(const char *Cmd
) { 
2217         clearCommandBuffer(); 
2218         CmdsParse(CommandTable
, Cmd
); 
2223 int CmdHelp(const char *Cmd
) { 
2224         CmdsHelp(CommandTable
);