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 //----------------------------------------------------------------------------- 
  13 #include "cmdhficlass.h" 
  15 static int CmdHelp(const char *Cmd
); 
  18 #define ICLASS_KEYS_MAX 8 
  19 static uint8_t iClass_Key_Table
[ICLASS_KEYS_MAX
][8] = { 
  20                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  21                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  22                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  23                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  24                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  25                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  26                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, 
  27                 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } 
  30 typedef struct iclass_block 
{ 
  34 int usage_hf_iclass_sim(void) { 
  35         PrintAndLog("Usage:  hf iclass sim <option> [CSN]"); 
  36         PrintAndLog("        options"); 
  37         PrintAndLog("                0 <CSN> simulate the given CSN"); 
  38         PrintAndLog("                1       simulate default CSN"); 
  39         PrintAndLog("                2       Reader-attack, gather reader responses to extract elite key"); 
  40         PrintAndLog("                3       Full simulation using emulator memory (see 'hf iclass eload')"); 
  41         PrintAndLog("        example: hf iclass sim 0 031FEC8AF7FF12E0"); 
  42         PrintAndLog("        example: hf iclass sim 2"); 
  43         PrintAndLog("        example: hf iclass eload 'tagdump.bin'"); 
  44         PrintAndLog("                 hf iclass sim 3"); 
  47 int usage_hf_iclass_eload(void) { 
  48         PrintAndLog("Loads iclass tag-dump into emulator memory on device"); 
  49         PrintAndLog("Usage:  hf iclass eload f <filename>"); 
  51         PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin"); 
  54 int usage_hf_iclass_decrypt(void) { 
  55         PrintAndLog("Usage: hf iclass decrypt f <tagdump>"); 
  57         PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); 
  58         PrintAndLog("in the working directory. The file should be 16 bytes binary data"); 
  60         PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin"); 
  62         PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. "); 
  63         PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,"); 
  64         PrintAndLog("which is defined by the configuration block."); 
  67 int usage_hf_iclass_encrypt(void) { 
  68         PrintAndLog("Usage: hf iclass encrypt <BlockData>"); 
  70         PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); 
  71         PrintAndLog("in the working directory. The file should be 16 bytes binary data"); 
  73         PrintAndLog("example: hf iclass encrypt 0102030405060708"); 
  77 int usage_hf_iclass_dump(void) { 
  78         PrintAndLog("Usage:  hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n"); 
  79         PrintAndLog("Options:"); 
  80         PrintAndLog("  f <filename> : specify a filename to save dump to"); 
  81         PrintAndLog("  k <Key>      : *Access Key as 16 hex symbols or 1 hex to select key from memory"); 
  82         PrintAndLog("  c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory"); 
  83         PrintAndLog("  e            : If 'e' is specified, the key is interpreted as the 16 byte"); 
  84         PrintAndLog("                 Custom Key (KCus), which can be obtained via reader-attack"); 
  85         PrintAndLog("                 See 'hf iclass sim 2'. This key should be on iclass-format"); 
  86         PrintAndLog("  r            : If 'r' is specified, the key is interpreted as raw block 3/4"); 
  87         PrintAndLog("  NOTE: * = required"); 
  88         PrintAndLog("Samples:"); 
  89         PrintAndLog("  hf iclass dump k 001122334455667B"); 
  90         PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B"); 
  91         PrintAndLog("  hf iclass dump k AAAAAAAAAAAAAAAA e"); 
  94 int usage_hf_iclass_clone(void) { 
  95         PrintAndLog("Usage:  hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r"); 
  96         PrintAndLog("Options:"); 
  97         PrintAndLog("  f <filename>: specify a filename to clone from"); 
  98         PrintAndLog("  b <Block>   : The first block to clone as 2 hex symbols"); 
  99         PrintAndLog("  l <Last Blk>: Set the Data to write as 16 hex symbols"); 
 100         PrintAndLog("  k <Key>     : Access Key as 16 hex symbols or 1 hex to select key from memory"); 
 101         PrintAndLog("  c           : If 'c' is specified, the key set is assumed to be the credit key\n"); 
 102         PrintAndLog("  e           : If 'e' is specified, elite computations applied to key"); 
 103         PrintAndLog("  r           : If 'r' is specified, no computations applied to key"); 
 104         PrintAndLog("Samples:"); 
 105         PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e"); 
 106         PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0"); 
 107         PrintAndLog("  hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e"); 
 110 int usage_hf_iclass_writeblock(void) { 
 111         PrintAndLog("Options:"); 
 112         PrintAndLog("  b <Block> : The block number as 2 hex symbols"); 
 113         PrintAndLog("  d <data>  : Set the Data to write as 16 hex symbols"); 
 114         PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory"); 
 115         PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n"); 
 116         PrintAndLog("  e         : If 'e' is specified, elite computations applied to key"); 
 117         PrintAndLog("  r         : If 'r' is specified, no computations applied to key"); 
 118         PrintAndLog("Samples:"); 
 119         PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B"); 
 120         PrintAndLog("  hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c"); 
 121         PrintAndLog("  hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0"); 
 124 int usage_hf_iclass_readblock(void) { 
 125         PrintAndLog("Usage:  hf iclass readblk b <Block> k <Key> c e|r\n"); 
 126         PrintAndLog("Options:"); 
 127         PrintAndLog("  b <Block> : The block number as 2 hex symbols"); 
 128         PrintAndLog("  k <Key>   : Access Key as 16 hex symbols or 1 hex to select key from memory"); 
 129         PrintAndLog("  c         : If 'c' is specified, the key set is assumed to be the credit key\n"); 
 130         PrintAndLog("  e         : If 'e' is specified, elite computations applied to key"); 
 131         PrintAndLog("  r         : If 'r' is specified, no computations applied to key"); 
 132         PrintAndLog("Samples:"); 
 133         PrintAndLog("  hf iclass readblk b 06 k 0011223344556677"); 
 134         PrintAndLog("  hf iclass readblk b 1B k 0011223344556677 c"); 
 135         PrintAndLog("  hf iclass readblk b 0A k 0"); 
 138 int usage_hf_iclass_readtagfile() { 
 139         PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]"); 
 142 int usage_hf_iclass_calc_newkey(void) { 
 143         PrintAndLog("HELP :  Manage iClass Keys in client memory:\n"); 
 144         PrintAndLog("Usage:  hf iclass calc_newkey o <Old key> n <New key> s [csn] e"); 
 145         PrintAndLog("  Options:"); 
 146         PrintAndLog("  o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol"); 
 147         PrintAndLog("  n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol"); 
 148         PrintAndLog("  s <csn>    : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)"); 
 149         PrintAndLog("  e          : specify new key as elite calc"); 
 150         PrintAndLog("  ee         : specify old and new key as elite calc"); 
 151         PrintAndLog("Samples:"); 
 152         PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee"); 
 153         PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e"); 
 154         PrintAndLog(" std to std read csn      : hf iclass calcnewkey o 1122334455667788 n 2233445566778899"); 
 155         PrintAndLog("NOTE: * = required\n"); 
 158 int usage_hf_iclass_managekeys(void) { 
 159         PrintAndLog("HELP :  Manage iClass Keys in client memory:\n"); 
 160         PrintAndLog("Usage:  hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n"); 
 161         PrintAndLog("  Options:"); 
 162         PrintAndLog("  n <keynbr>  : specify the keyNbr to set in memory"); 
 163         PrintAndLog("  k <key>     : set a key in memory"); 
 164         PrintAndLog("  f <filename>: specify a filename to use with load or save operations"); 
 165         PrintAndLog("  s           : save keys in memory to file specified by filename"); 
 166         PrintAndLog("  l           : load keys to memory from file specified by filename"); 
 167         PrintAndLog("  p           : print keys loaded into memory\n"); 
 168         PrintAndLog("Samples:"); 
 169         PrintAndLog(" set key      : hf iclass managekeys n 0 k 1122334455667788"); 
 170         PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s"); 
 171         PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l"); 
 172         PrintAndLog(" print keys   : hf iclass managekeys p\n"); 
 176 int xorbits_8(uint8_t val
) { 
 177         uint8_t res 
= val 
^ (val 
>> 1); //1st pass 
 178         res 
= res 
^ (res 
>> 1);                 // 2nd pass 
 179         res 
= res 
^ (res 
>> 2);                 // 3rd pass 
 180         res 
= res 
^ (res 
>> 4);                         // 4th pass 
 184 int CmdHFiClassList(const char *Cmd
) { 
 185         //PrintAndLog("Deprecated command, use 'hf list iclass' instead"); 
 190 int CmdHFiClassSnoop(const char *Cmd
) { 
 191         UsbCommand c 
= {CMD_SNOOP_ICLASS
}; 
 196 int CmdHFiClassSim(const char *Cmd
) { 
 198         uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 
 200         if (strlen(Cmd
)<1) return usage_hf_iclass_sim(); 
 202         simType 
= param_get8ex(Cmd
, 0, 0, 10); 
 206                 if (param_gethex(Cmd
, 1, CSN
, 16)) { 
 207                         PrintAndLog("A CSN should consist of 16 HEX symbols"); 
 208                         return usage_hf_iclass_sim(); 
 211                 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8)); 
 216                 PrintAndLog("Undefined simptype %d", simType
); 
 217                 return usage_hf_iclass_sim(); 
 220         uint8_t numberOfCSNs
=0; 
 223                 UsbCommand c 
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}}; 
 224                 UsbCommand resp 
= {0}; 
 226                 uint8_t csns
[8*NUM_CSNS
] = { 
 227                         0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, 
 228                         0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0, 
 229                         0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0, 
 230                         0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0, 
 231                         0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0, 
 232                         0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0, 
 233                         0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0, 
 234                         0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0, 
 235                         0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0, 
 236                         0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0, 
 237                         0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0, 
 238                         0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0, 
 239                         0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0, 
 240                         0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0, 
 241                         0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 }; 
 243                 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
); 
 244                 clearCommandBuffer(); 
 246                 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) { 
 247                         PrintAndLog("Command timed out"); 
 251                 uint8_t num_mac_responses  
= resp
.arg
[1]; 
 252                 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
); 
 254                 size_t datalen 
= NUM_CSNS
*24; 
 256                  * Now, time to dump to file. We'll use this format: 
 257                  * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>.... 
 258                  * So, it should wind up as 
 261                  * The returndata from the pm3 is on the following format 
 262                  * <4 byte NR><4 byte MAC> 
 263                  * CC are all zeroes, CSN is the same as was sent in 
 265                 void* dump 
= malloc(datalen
); 
 266                 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field 
 268                 for(i 
= 0 ; i 
< NUM_CSNS 
; i
++) { 
 269                         memcpy(dump
+i
*24, csns
+i
*8, 8); //CSN 
 270                         //8 zero bytes here... 
 271                         //Then comes NR_MAC (eight bytes from the response) 
 272                         memcpy(dump
+i
*24+16, resp
.d
.asBytes
+i
*8, 8); 
 274                 /** Now, save to dumpfile **/ 
 275                 saveFile("iclass_mac_attack", "bin", dump
, datalen
); 
 278                 UsbCommand c 
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}}; 
 279                 memcpy(c
.d
.asBytes
, CSN
, 8); 
 280                 clearCommandBuffer(); 
 286 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) { 
 287         bool tagFound 
= false; 
 288         UsbCommand c 
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN 
| 
 289                                         FLAG_ICLASS_READER_CONF 
| FLAG_ICLASS_READER_AA
}}; 
 290         // loop in client not device - else on windows have a communication error 
 291         c
.arg
[0] |= FLAG_ICLASS_READER_ONLY_ONCE 
| FLAG_ICLASS_READER_ONE_TRY
; 
 294                 clearCommandBuffer(); 
 296                 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) { 
 297                         uint8_t readStatus 
= resp
.arg
[0] & 0xff; 
 298                         uint8_t *data 
= resp
.d
.asBytes
; 
 300                         if (verbose
) PrintAndLog("Readstatus:%02x", readStatus
); 
 301                         if( readStatus 
== 0){ 
 303                                 if (verbose
) PrintAndLog("Quitting..."); 
 306                         if( readStatus 
& FLAG_ICLASS_READER_CSN
){ 
 307                                 PrintAndLog("CSN: %s",sprint_hex(data
,8)); 
 310                         if( readStatus 
& FLAG_ICLASS_READER_CC
)   PrintAndLog("CC: %s", sprint_hex(data
+16, 8)); 
 311                         if( readStatus 
& FLAG_ICLASS_READER_CONF
) printIclassDumpInfo(data
);                     
 312                         if (tagFound 
&& !loop
) return 1; 
 314                         if (verbose
) PrintAndLog("Command execute timeout"); 
 321 int CmdHFiClassReader(const char *Cmd
) { 
 322         return HFiClassReader(Cmd
, true, true); 
 325 int CmdHFiClassReader_Replay(const char *Cmd
) { 
 326         uint8_t readerType 
= 0; 
 327         uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00}; 
 330                 PrintAndLog("Usage:  hf iclass replay <MAC>"); 
 331                 PrintAndLog("        sample: hf iclass replay 00112233"); 
 335         if (param_gethex(Cmd
, 0, MAC
, 8)) { 
 336                 PrintAndLog("MAC must include 8 HEX symbols"); 
 340         UsbCommand c 
= {CMD_READER_ICLASS_REPLAY
, {readerType
}}; 
 341         memcpy(c
.d
.asBytes
, MAC
, 4); 
 342         clearCommandBuffer(); 
 347 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) { 
 348         UsbCommand c 
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}}; 
 349         memcpy(c
.d
.asBytes
, data
, blocksCount 
* 16); 
 350         clearCommandBuffer(); 
 355 int CmdHFiClassELoad(const char *Cmd
) { 
 357         char opt 
= param_getchar(Cmd
, 0); 
 358         if (strlen(Cmd
)<1 || opt 
== 'h' || opt 
== 'H') return usage_hf_iclass_eload(); 
 360         //File handling and reading 
 362         char filename
[FILE_PATH_SIZE
]; 
 363         if(opt 
== 'f' && param_getstr(Cmd
, 1, filename
) > 0) { 
 364                 f 
= fopen(filename
, "rb"); 
 366                 return usage_hf_iclass_eload(); 
 370                 PrintAndLog("Failed to read from file '%s'", filename
); 
 374         fseek(f
, 0, SEEK_END
); 
 375         long fsize 
= ftell(f
); 
 376         fseek(f
, 0, SEEK_SET
); 
 379                 prnlog("Error, when getting filesize"); 
 384         uint8_t *dump 
= malloc(fsize
); 
 386         size_t bytes_read 
= fread(dump
, 1, fsize
, f
); 
 389         printIclassDumpInfo(dump
); 
 392         if (bytes_read 
< fsize
) { 
 393                 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize 
); 
 398         uint32_t bytes_sent 
= 0; 
 399         uint32_t bytes_remaining  
= bytes_read
; 
 401         while(bytes_remaining 
> 0){ 
 402                 uint32_t bytes_in_packet 
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
); 
 403                 UsbCommand c 
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}}; 
 404                 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
); 
 405                 clearCommandBuffer(); 
 407                 bytes_remaining 
-= bytes_in_packet
; 
 408                 bytes_sent 
+= bytes_in_packet
; 
 411         PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
); 
 415 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) { 
 416         FILE *f 
= fopen(filename
, "rb"); 
 418                 PrintAndLog("Failed to read from file '%s'", filename
); 
 421         fseek(f
, 0, SEEK_END
); 
 422         long fsize 
= ftell(f
); 
 423         fseek(f
, 0, SEEK_SET
); 
 424         size_t bytes_read 
= fread(buffer
, 1, len
, f
); 
 428                 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
); 
 432         if(bytes_read 
!= len
) { 
 433                 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
); 
 439 int CmdHFiClassDecrypt(const char *Cmd
) { 
 440         uint8_t key
[16] = { 0 }; 
 441         if(readKeyfile("iclass_decryptionkey.bin", 16, key
)) return usage_hf_iclass_decrypt(); 
 443         PrintAndLog("Decryption file found... "); 
 444         char opt 
= param_getchar(Cmd
, 0); 
 445         if (strlen(Cmd
)<1 || opt 
== 'h' || opt 
== 'H') return usage_hf_iclass_decrypt(); 
 447         //Open the tagdump-file 
 449         char filename
[FILE_PATH_SIZE
]; 
 450         if(opt 
== 'f' && param_getstr(Cmd
, 1, filename
) > 0) { 
 451                 if ( (f 
= fopen(filename
, "rb")) == NULL
) { 
 452                         PrintAndLog("Could not find file %s", filename
); 
 456                 return usage_hf_iclass_decrypt(); 
 459         fseek(f
, 0, SEEK_END
); 
 460         long fsize 
= ftell(f
); 
 461         fseek(f
, 0, SEEK_SET
); 
 464                 PrintAndLog("Error, when getting filesize"); 
 469         uint8_t *decrypted 
= malloc(fsize
); 
 471         size_t bytes_read 
= fread(decrypted
, 1, fsize
, f
); 
 473         if ( bytes_read 
== 0) { 
 474                 PrintAndLog("File reading error"); 
 479         picopass_hdr 
*hdr 
= (picopass_hdr 
*)decrypted
; 
 481         uint8_t mem 
= hdr
->conf
.mem_config
; 
 482         uint8_t chip 
= hdr
->conf
.chip_config
; 
 483         uint8_t applimit 
= hdr
->conf
.app_limit
; 
 485         uint8_t app_areas 
= 2; 
 486         uint8_t max_blk 
= 31; 
 487         getMemConfig(mem
, chip
, &max_blk
, &app_areas
, &kb
);      
 489         //Use the first block (CSN) for filename 
 490         char outfilename
[FILE_PATH_SIZE
] = {0}; 
 491         snprintf(outfilename
, FILE_PATH_SIZE
, "iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted", 
 492                          hdr
->csn
[0],hdr
->csn
[1],hdr
->csn
[2],hdr
->csn
[3], 
 493                          hdr
->csn
[4],hdr
->csn
[5],hdr
->csn
[6],hdr
->csn
[7]); 
 496         des3_context ctx 
= { DES_DECRYPT 
,{ 0 } }; 
 497         des3_set2key_dec( &ctx
, key
); 
 499         uint8_t enc_dump
[8] = {0}; 
 500         uint8_t empty
[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; 
 501         for(uint16_t blocknum
=0; blocknum 
< applimit
; ++blocknum
) { 
 503                 uint8_t idx 
= blocknum
*8; 
 504                 memcpy(enc_dump
, decrypted 
+ idx
, 8); 
 506                 // block 7 or higher,  and not empty 0xFF 
 507                 if(blocknum 
> 6 &&  memcmp(enc_dump
, empty
, 8) != 0 ) { 
 508                         des3_crypt_ecb(&ctx
, enc_dump
, decrypted 
+ idx 
); 
 510                 //printvar("decrypted block", decrypted + idx, 8); 
 513         saveFile(outfilename
, "bin", decrypted
, fsize
); 
 516         printIclassDumpContents(decrypted
, 1, (fsize
/8), fsize
); 
 520 static int iClassEncryptBlkData(uint8_t *blkData
) { 
 521         uint8_t key
[16] = { 0 }; 
 522         if(readKeyfile("iclass_decryptionkey.bin", 16, key
)) { 
 523                 usage_hf_iclass_encrypt(); 
 526         PrintAndLog("Decryption file found... "); 
 527         uint8_t encryptedData
[16]; 
 528         uint8_t *encrypted 
= encryptedData
; 
 529         des3_context ctx 
= { DES_DECRYPT 
,{ 0 } }; 
 530         des3_set2key_enc( &ctx
, key
); 
 532         des3_crypt_ecb(&ctx
, blkData
,encrypted
); 
 533         //printvar("decrypted block", decrypted, 8); 
 534         memcpy(blkData
,encrypted
,8); 
 539 int CmdHFiClassEncryptBlk(const char *Cmd
) { 
 540         uint8_t blkData
[8] = {0}; 
 541         char opt 
= param_getchar(Cmd
, 0); 
 542         if (strlen(Cmd
)<1 || opt 
== 'h' || opt 
== 'H') return usage_hf_iclass_encrypt(); 
 544         //get the bytes to encrypt 
 545         if (param_gethex(Cmd
, 0, blkData
, 16)) { 
 546                 PrintAndLog("BlockData must include 16 HEX symbols"); 
 549         if (!iClassEncryptBlkData(blkData
)) return 0; 
 551         printvar("encrypted block", blkData
, 8); 
 555 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) { 
 558         memcpy(WB 
+ 1,data
,8); 
 559         doMAC_N(WB
,sizeof(WB
),div_key
,MAC
); 
 560         //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]); 
 563 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) { 
 566         UsbCommand c 
= {CMD_READER_ICLASS
, {0}}; 
 567         c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE 
| FLAG_ICLASS_READER_CC 
| FLAG_ICLASS_READER_ONE_TRY
; 
 569                 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
; 
 571         clearCommandBuffer(); 
 573         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) { 
 574                 PrintAndLog("Command execute timeout"); 
 578         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 579         uint8_t *data 
= resp
.d
.asBytes
; 
 584                 memcpy(CCNR
,data
+16,8); 
 587                 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8)); 
 591                 PrintAndLog("Failed to obtain CC! Aborting"); 
 597 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
) { 
 598         uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 599         uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 601         if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
)) 
 606                 memcpy(div_key
, KEY
, 8); 
 608                 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
); 
 610         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]); 
 612         doMAC(CCNR
, div_key
, MAC
); 
 614         UsbCommand d 
= {CMD_ICLASS_AUTHENTICATION
, {0}}; 
 615         memcpy(d
.d
.asBytes
, MAC
, 4); 
 616         clearCommandBuffer(); 
 618         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) { 
 619                 PrintAndLog("Auth Command execute timeout"); 
 622         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 624                 PrintAndLog("Authentication error"); 
 630 int CmdHFiClassReader_Dump(const char *Cmd
) { 
 632         uint8_t MAC
[4] = {0x00,0x00,0x00,0x00}; 
 633         uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 634         uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 638         uint8_t app_areas 
= 1; 
 640         uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 641         uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 644         uint8_t fileNameLen 
= 0; 
 645         char filename
[FILE_PATH_SIZE
]={0}; 
 646         char tempStr
[50] = {0}; 
 647         bool have_debit_key 
= false; 
 648         bool have_credit_key 
= false; 
 649         bool use_credit_key 
= false; 
 655         while(param_getchar(Cmd
, cmdp
) != 0x00) 
 657                 switch(param_getchar(Cmd
, cmdp
)) 
 661                         return usage_hf_iclass_dump(); 
 664                         have_credit_key 
= true; 
 665                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
 667                                 errors 
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
); 
 668                         } else if (dataLen 
== 1) { 
 669                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
 670                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
 671                                         memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8); 
 673                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
 677                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
 689                         fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
);  
 690                         if (fileNameLen 
< 1) { 
 691                                 PrintAndLog("No filename found after f"); 
 698                         have_debit_key 
= true; 
 699                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
 701                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
 702                         } else if (dataLen 
== 1) { 
 703                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
 704                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
 705                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
 707                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
 711                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
 722                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
 726                 if(errors
) return usage_hf_iclass_dump(); 
 729         if (cmdp 
< 2) return usage_hf_iclass_dump(); 
 730         // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work) 
 731         if (!have_debit_key 
&& have_credit_key
) use_credit_key 
= true; 
 733         //get config and first 3 blocks 
 734         UsbCommand c 
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN 
| 
 735                                         FLAG_ICLASS_READER_CONF 
| FLAG_ICLASS_READER_ONLY_ONCE 
| FLAG_ICLASS_READER_ONE_TRY
}}; 
 737         uint8_t tag_data
[255*8]; 
 739         clearCommandBuffer(); 
 741         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 742                 PrintAndLog("Command execute timeout"); 
 743                 ul_switch_off_field(); 
 746         uint8_t readStatus 
= resp
.arg
[0] & 0xff; 
 747         uint8_t * data  
= resp
.d
.asBytes
; 
 750                 PrintAndLog("No tag found..."); 
 751                 ul_switch_off_field(); 
 755         if( readStatus 
& (FLAG_ICLASS_READER_CSN 
| FLAG_ICLASS_READER_CONF 
| FLAG_ICLASS_READER_CC
)){ 
 756                 memcpy(tag_data
, data
, 8*3); 
 757                 blockno 
+= 2; // 2 to force re-read of block 2 later. (seems to respond differently..) 
 759                 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
); 
 760                 // large memory - not able to dump pages currently 
 761                 if (numblks 
> maxBlk
) numblks 
= maxBlk
; 
 764         ul_switch_off_field(); 
 765         // authenticate debit key and get div_key - later store in dump block 3 
 766         if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){ 
 767                 //try twice - for some reason it sometimes fails the first time... 
 768                 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){ 
 769                         ul_switch_off_field(); 
 775         UsbCommand w 
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}}; 
 776         clearCommandBuffer(); 
 778         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 779                 PrintAndLog("Command execute time-out 1"); 
 780                 ul_switch_off_field(); 
 783         uint32_t blocksRead 
= resp
.arg
[1]; 
 784         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 785         if (!isOK 
&& !blocksRead
) { 
 786                 PrintAndLog("Read Block Failed"); 
 787                 ul_switch_off_field(); 
 790         uint32_t startindex 
= resp
.arg
[2]; 
 791         if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) { 
 792                 PrintAndLog("Data exceeded Buffer size!"); 
 793                 blocksRead 
= (sizeof(tag_data
)/8) - blockno
; 
 795         // response ok - now get bigbuf content of the dump 
 796         GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
); 
 797         WaitForResponse(CMD_ACK
,NULL
); 
 798         size_t gotBytes 
= blocksRead
*8 + blockno
*8; 
 801         if (have_credit_key
) { 
 802                 //turn off hf field before authenticating with different key 
 803                 ul_switch_off_field(); 
 805                 // AA2 authenticate credit key and git c_div_key - later store in dump block 4 
 806                 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){ 
 807                         //try twice - for some reason it sometimes fails the first time... 
 808                         if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){ 
 809                                 ul_switch_off_field(); 
 813                 // do we still need to read more block?  (aa2 enabled?) 
 814                 if (maxBlk 
> blockno
+numblks
+1) { 
 815                         // setup dump and start 
 816                         w
.arg
[0] = blockno 
+ blocksRead
; 
 817                         w
.arg
[1] = maxBlk 
- (blockno 
+ blocksRead
); 
 818                         clearCommandBuffer(); 
 820                         if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) { 
 821                                 PrintAndLog("Command execute timeout 2"); 
 822                                 ul_switch_off_field(); 
 825                         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 826                         blocksRead 
= resp
.arg
[1]; 
 827                         if (!isOK 
&& !blocksRead
) { 
 828                                 PrintAndLog("Read Block Failed 2"); 
 829                                 ul_switch_off_field(); 
 833                         startindex 
= resp
.arg
[2]; 
 834                         if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) { 
 835                                 PrintAndLog("Data exceeded Buffer size!"); 
 836                                 blocksRead 
= (sizeof(tag_data
) - gotBytes
)/8; 
 838                         // get dumped data from bigbuf 
 839                         GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
); 
 840                         WaitForResponse(CMD_ACK
,NULL
); 
 842                         gotBytes 
+= blocksRead
*8;                        
 843                 } else { //field is still on - turn it off... 
 844                         ul_switch_off_field(); 
 848         // add diversified keys to dump 
 849         if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8); 
 850         if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8); 
 852         printf("Num of bytes:  %u\n", gotBytes
); 
 855         printf("------+--+-------------------------+\n"); 
 856         printf("CSN   |00| %s|\n", sprint_hex(tag_data
, 8));     
 857         //printIclassDumpContents(tag_data, 1, (gotBytes/8)-1, gotBytes-8); 
 858         printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
); 
 860         if (filename
[0] == 0){ 
 861                 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x", 
 862                     tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3], 
 863                     tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]); 
 866         // save the dump to .bin file 
 867         PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8); 
 868         saveFile(filename
, "bin", tag_data
, gotBytes
); 
 872 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) { 
 873         uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
 874         uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 875         if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
)) 
 880         Calc_wb_mac(blockno
,bldata
,div_key
,MAC
); 
 881         UsbCommand w 
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}}; 
 882         memcpy(w
.d
.asBytes
, bldata
, 8); 
 883         memcpy(w
.d
.asBytes 
+ 8, MAC
, 4); 
 885         clearCommandBuffer(); 
 887         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) { 
 888                 PrintAndLog("Write Command execute timeout"); 
 891         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
 893                 PrintAndLog("Write Block Failed"); 
 896         PrintAndLog("Write Block Successful"); 
 900 int CmdHFiClass_WriteBlock(const char *Cmd
) { 
 902         uint8_t bldata
[8]={0,0,0,0,0,0,0,0}; 
 903         uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 906         char tempStr
[50] = {0}; 
 907         bool use_credit_key 
= false; 
 912         while(param_getchar(Cmd
, cmdp
) != 0x00) 
 914                 switch(param_getchar(Cmd
, cmdp
)) 
 918                         return usage_hf_iclass_writeblock(); 
 921                         if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) { 
 922                                 PrintAndLog("Block No must include 2 HEX symbols\n"); 
 929                         use_credit_key 
= true; 
 934                         if (param_gethex(Cmd
, cmdp
+1, bldata
, 16)) 
 936                                 PrintAndLog("KEY must include 16 HEX symbols\n"); 
 948                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
 950                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
 951                         } else if (dataLen 
== 1) { 
 952                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
 953                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
 954                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
 956                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
 960                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
 971                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
 975                 if(errors
) return usage_hf_iclass_writeblock(); 
 978         if (cmdp 
< 6) return usage_hf_iclass_writeblock(); 
 979         int ans 
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true); 
 980         ul_switch_off_field(); 
 984 int CmdHFiClassCloneTag(const char *Cmd
) { 
 985         char filename
[FILE_PATH_SIZE
] = { 0x00 }; 
 986         char tempStr
[50]={0}; 
 987         uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
 989         uint8_t fileNameLen 
= 0; 
 990         uint8_t startblock 
= 0; 
 991         uint8_t endblock 
= 0; 
 993         bool use_credit_key 
= false; 
 998         while(param_getchar(Cmd
, cmdp
) != 0x00) 
1000                 switch(param_getchar(Cmd
, cmdp
)) 
1004                         return usage_hf_iclass_clone(); 
1007                         if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) { 
1008                                 PrintAndLog("Start Block No must include 2 HEX symbols\n"); 
1015                         use_credit_key 
= true; 
1025                         fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
);  
1026                         if (fileNameLen 
< 1) { 
1027                                 PrintAndLog("No filename found after f"); 
1034                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1035                         if (dataLen 
== 16) {  
1036                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1037                         } else if (dataLen 
== 1) { 
1038                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1039                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1040                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
1042                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
1046                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
1053                         if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) { 
1054                                 PrintAndLog("Start Block No must include 2 HEX symbols\n"); 
1065                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1069                 if(errors
) return usage_hf_iclass_clone(); 
1072         if (cmdp 
< 8) return usage_hf_iclass_clone(); 
1076         iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12]; 
1078         if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) { 
1079                 PrintAndLog("Trying to write too many blocks at once.  Max: %d", USB_CMD_DATA_SIZE
/8); 
1081         // file handling and reading 
1082         f 
= fopen(filename
,"rb"); 
1084                 PrintAndLog("Failed to read from file '%s'", filename
); 
1089                 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4"); 
1093         // now read data from the file from block 6 --- 19 
1094         // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data 
1095         // 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, 
1096         // else we have to create a share memory 
1098         fseek(f
,startblock
*8,SEEK_SET
); 
1099         size_t bytes_read 
= fread(tag_data
,sizeof(iclass_block_t
),endblock 
- startblock 
+ 1,f
); 
1100         if ( bytes_read 
== 0){ 
1101                 PrintAndLog("File reading error."); 
1106         uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
1107         uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1109         if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true)) 
1112         UsbCommand w 
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}}; 
1114         // calculate all mac for every the block we will write 
1115         for (i 
= startblock
; i 
<= endblock
; i
++){ 
1116             Calc_wb_mac(i
,tag_data
[i 
- startblock
].d
,div_key
,MAC
); 
1117             // usb command d start pointer = d + (i - 6) * 12 
1118             // memcpy(pointer,tag_data[i - 6],8) 8 bytes 
1119             // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes; 
1121             ptr 
= w
.d
.asBytes 
+ (i 
- startblock
) * 12; 
1122             memcpy(ptr
, &(tag_data
[i 
- startblock
].d
[0]), 8); 
1123             memcpy(ptr 
+ 8,MAC
, 4); 
1126         for (i 
= 0; i 
<= endblock 
- startblock
;i
++){ 
1127             memcpy(p
,w
.d
.asBytes 
+ (i 
* 12),12); 
1128             printf("Block |%02x|",i 
+ startblock
); 
1129             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]); 
1130             printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]); 
1133         clearCommandBuffer(); 
1135         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) { 
1136                 PrintAndLog("Command execute timeout"); 
1142 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
) { 
1143         uint8_t MAC
[4]={0x00,0x00,0x00,0x00}; 
1144         uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1146         if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
)) 
1150         UsbCommand w 
= {CMD_ICLASS_READBLOCK
, {blockno
}}; 
1151         clearCommandBuffer(); 
1153         if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) { 
1154                 PrintAndLog("Command execute timeout"); 
1158         uint8_t isOK 
= resp
.arg
[0] & 0xff; 
1160                 PrintAndLog("Read Block Failed"); 
1163         //data read is stored in: resp.d.asBytes[0-15] 
1164         if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8)); 
1168 int CmdHFiClass_ReadBlock(const char *Cmd
) { 
1170         uint8_t keyType 
= 0x88; //debit key 
1171         uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1173         uint8_t dataLen 
= 0; 
1174         char tempStr
[50] = {0}; 
1176         bool rawkey 
= false; 
1177         bool errors 
= false; 
1179         while(param_getchar(Cmd
, cmdp
) != 0x00) 
1181                 switch(param_getchar(Cmd
, cmdp
)) 
1185                         return usage_hf_iclass_readblock(); 
1188                         if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) { 
1189                                 PrintAndLog("Block No must include 2 HEX symbols\n"); 
1206                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1207                         if (dataLen 
== 16) {  
1208                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1209                         } else if (dataLen 
== 1) { 
1210                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1211                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1212                                         memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8); 
1214                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
1218                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
1229                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1233                 if(errors
) return usage_hf_iclass_readblock(); 
1236         if (cmdp 
< 4) return usage_hf_iclass_readblock(); 
1238         return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true); 
1241 int CmdHFiClass_loclass(const char *Cmd
) { 
1242         char opt 
= param_getchar(Cmd
, 0); 
1244         if (strlen(Cmd
)<1 || opt 
== 'h') { 
1245                 PrintAndLog("Usage: hf iclass loclass [options]"); 
1246                 PrintAndLog("Options:"); 
1247                 PrintAndLog("h             Show this help"); 
1248                 PrintAndLog("t             Perform self-test"); 
1249                 PrintAndLog("f <filename>  Bruteforce iclass dumpfile"); 
1250                 PrintAndLog("                   An iclass dumpfile is assumed to consist of an arbitrary number of"); 
1251                 PrintAndLog("                   malicious CSNs, and their protocol responses"); 
1252                 PrintAndLog("                   The binary format of the file is expected to be as follows: "); 
1253                 PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); 
1254                 PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); 
1255                 PrintAndLog("                   <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>"); 
1256                 PrintAndLog("                  ... totalling N*24 bytes"); 
1259         char fileName
[255] = {0}; 
1261                 if(param_getstr(Cmd
, 1, fileName
) > 0) { 
1262                         return bruteforceFileNoKeys(fileName
); 
1264                         PrintAndLog("You must specify a filename"); 
1268         else if(opt 
== 't') { 
1269                 int errors 
= testCipherUtils(); 
1270                 errors 
+= testMAC(); 
1271                 errors 
+= doKeyTests(0); 
1272                 errors 
+= testElite(); 
1273                 if(errors
) prnlog("OBS! There were errors!!!"); 
1279 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) { 
1281         memcpy(&mem_config
, iclass_dump 
+ 13,1); 
1282         uint8_t maxmemcount
; 
1284         uint8_t filemaxblock 
= filesize 
/ 8; 
1286         if (mem_config 
& 0x80) 
1291         if (startblock 
== 0) 
1294         if ((endblock 
> maxmemcount
) || (endblock 
== 0)) 
1295                 endblock 
= maxmemcount
; 
1297         // remember endblock needs to relate to zero-index arrays. 
1298         if (endblock 
> filemaxblock
-1) 
1299                 endblock 
= filemaxblock
-1; 
1301         //PrintAndLog   ("startblock: %d, endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d",startblock, endblock,filesize, maxmemcount, filemaxblock); 
1304         printf("------+--+-------------------------+\n"); 
1305         while (i 
<= endblock
){ 
1306                 uint8_t *blk 
= iclass_dump 
+ (i 
* 8); 
1307                 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );    
1310         printf("------+--+-------------------------+\n"); 
1313 int CmdHFiClassReadTagFile(const char *Cmd
) { 
1318         char filename
[FILE_PATH_SIZE
]; 
1319         if (param_getstr(Cmd
, 0, filename
) < 1) 
1320                 return usage_hf_iclass_readtagfile(); 
1322         if (param_getstr(Cmd
,1,(char *)&tempnum
) < 1) 
1325                 sscanf(tempnum
,"%d",&startblock
); 
1327         if (param_getstr(Cmd
,2,(char *)&tempnum
) < 1) 
1330                 sscanf(tempnum
,"%d",&endblock
); 
1332         // file handling and reading 
1333         f 
= fopen(filename
,"rb"); 
1335                 PrintAndLog("Failed to read from file '%s'", filename
); 
1338         fseek(f
, 0, SEEK_END
); 
1339         long fsize 
= ftell(f
); 
1340         fseek(f
, 0, SEEK_SET
); 
1343                 PrintAndLog("Error, when getting filesize"); 
1348         uint8_t *dump 
= malloc(fsize
); 
1349         size_t bytes_read 
= fread(dump
, 1, fsize
, f
); 
1352         uint8_t *csn 
= dump
; 
1353         printf("------+--+-------------------------+\n"); 
1354         printf("CSN   |00| %s|\n", sprint_hex(csn
, 8) ); 
1355         printIclassDumpContents(dump
, startblock
, endblock
, bytes_read
); 
1361 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) { 
1362         uint64_t new_div = 0x00; 
1368 uint64_t hexarray_to_uint64(uint8_t *key) { 
1371         for (int i = 0;i < 8;i++) 
1372                 sprintf(&temp[(i *2)],"%02X",key[i]); 
1374         if (sscanf(temp,"%016"llX,&uint_key) < 1) 
1379 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t   *KEY
, uint8_t *div_key
, bool elite
){ 
1380         uint8_t keytable
[128] = {0}; 
1381         uint8_t key_index
[8] = {0}; 
1383                 uint8_t key_sel
[8] = { 0 }; 
1384                 uint8_t key_sel_p
[8] = { 0 }; 
1385                 hash2(KEY
, keytable
); 
1386                 hash1(CSN
, key_index
); 
1387                 for(uint8_t i 
= 0; i 
< 8 ; i
++) 
1388                         key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF; 
1390                 //Permute from iclass format to standard format 
1391                 permutekey_rev(key_sel
, key_sel_p
); 
1392                 diversifyKey(CSN
, key_sel_p
, div_key
);   
1394                 diversifyKey(CSN
, KEY
, div_key
); 
1398 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite) 
1399 //calculate and return xor_div_key (ready for a key write command) 
1400 //print all div_keys if verbose 
1401 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){ 
1402         uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1403         uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1405         HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
); 
1407         HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
); 
1409         for (uint8_t i 
= 0; i 
< sizeof(old_div_key
); i
++){ 
1410                 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
]; 
1413                 printf("Old div key : %s\n",sprint_hex(old_div_key
,8)); 
1414                 printf("New div key : %s\n",sprint_hex(new_div_key
,8)); 
1415                 printf("Xor div key : %s\n",sprint_hex(xor_div_key
,8));          
1419 int CmdHFiClassCalcNewKey(const char *Cmd
) { 
1420         uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1421         uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1422         uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1423         uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1424         uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; 
1426         uint8_t dataLen 
= 0; 
1427         char tempStr
[50] = {0}; 
1428         bool givenCSN 
= false; 
1429         bool oldElite 
= false; 
1431         bool errors 
= false; 
1433         while(param_getchar(Cmd
, cmdp
) != 0x00) 
1435                 switch(param_getchar(Cmd
, cmdp
)) 
1439                         return usage_hf_iclass_calc_newkey(); 
1442                         dataLen 
= param_getstr(Cmd
, cmdp
, tempStr
); 
1450                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1451                         if (dataLen 
== 16) {  
1452                                 errors 
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
); 
1453                         } else if (dataLen 
== 1) { 
1454                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1455                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1456                                         memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8); 
1458                                         PrintAndLog("\nERROR: NewKey Nbr is invalid\n"); 
1462                                 PrintAndLog("\nERROR: NewKey is incorrect length\n"); 
1469                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1470                         if (dataLen 
== 16) {  
1471                                 errors 
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
); 
1472                         } else if (dataLen 
== 1) { 
1473                                 keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1474                                 if (keyNbr 
< ICLASS_KEYS_MAX
) { 
1475                                         memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8); 
1477                                         PrintAndLog("\nERROR: Credit KeyNbr is invalid\n"); 
1481                                 PrintAndLog("\nERROR: Credit Key is incorrect length\n"); 
1489                         if (param_gethex(Cmd
, cmdp
+1, CSN
, 16)) 
1490                                 return usage_hf_iclass_calc_newkey(); 
1494                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1498                 if(errors
) return usage_hf_iclass_calc_newkey(); 
1501         if (cmdp 
< 4) return usage_hf_iclass_calc_newkey(); 
1504                 if (!select_only(CSN
, CCNR
, false, true)) 
1507         HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true); 
1511 static int loadKeys(char *filename
) { 
1513         f 
= fopen(filename
,"rb"); 
1515                 PrintAndLog("Failed to read from file '%s'", filename
); 
1518         fseek(f
, 0, SEEK_END
); 
1519         long fsize 
= ftell(f
); 
1520         fseek(f
, 0, SEEK_SET
); 
1523                 PrintAndLog("Error, when getting filesize"); 
1528         uint8_t *dump 
= malloc(fsize
); 
1530         size_t bytes_read 
= fread(dump
, 1, fsize
, f
); 
1532         if (bytes_read 
> ICLASS_KEYS_MAX 
* 8){ 
1533                 PrintAndLog("File is too long to load - bytes: %u", bytes_read
); 
1538         for (; i 
< bytes_read
/8; i
++) 
1539                 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8); 
1542         PrintAndLog("%u keys loaded", i
); 
1546 static int saveKeys(char *filename
) { 
1548         f 
= fopen(filename
,"wb"); 
1550                 printf("error opening file %s\n",filename
); 
1553         for (uint8_t i 
= 0; i 
< ICLASS_KEYS_MAX
; i
++){ 
1554                 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){ 
1555                         PrintAndLog("save key failed to write to file: %s", filename
); 
1563 static int printKeys(void) { 
1565         for (uint8_t i 
= 0; i 
< ICLASS_KEYS_MAX
; i
++) 
1566                 PrintAndLog("%u: %s", i
, sprint_hex(iClass_Key_Table
[i
],8)); 
1571 int CmdHFiClassManageKeys(const char *Cmd
) { 
1573         uint8_t dataLen 
= 0; 
1574         uint8_t KEY
[8] = {0}; 
1575         char filename
[FILE_PATH_SIZE
]; 
1576         uint8_t fileNameLen 
= 0; 
1577         bool errors 
= false; 
1578         uint8_t operation 
= 0; 
1582         while(param_getchar(Cmd
, cmdp
) != 0x00) 
1584                 switch(param_getchar(Cmd
, cmdp
)) 
1588                         return usage_hf_iclass_managekeys(); 
1591                         fileNameLen 
= param_getstr(Cmd
, cmdp
+1, filename
);  
1592                         if (fileNameLen 
< 1) { 
1593                                 PrintAndLog("No filename found after f"); 
1600                         keyNbr 
= param_get8(Cmd
, cmdp
+1); 
1602                                 PrintAndLog("Wrong block number"); 
1609                         operation 
+= 3; //set key  
1610                         dataLen 
= param_getstr(Cmd
, cmdp
+1, tempStr
); 
1611                         if (dataLen 
== 16) { //ul-c or ev1/ntag key length 
1612                                 errors 
= param_gethex(tempStr
, 0, KEY
, dataLen
); 
1614                                 PrintAndLog("\nERROR: Key is incorrect length\n"); 
1621                         operation 
+= 4; //print keys in memory 
1626                         operation 
+= 5; //load keys from file 
1631                         operation 
+= 6; //save keys to file 
1635                         PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
)); 
1639                 if(errors
) return usage_hf_iclass_managekeys(); 
1641         if (operation 
== 0){ 
1642                 PrintAndLog("no operation specified (load, save, or print)\n"); 
1643                 return usage_hf_iclass_managekeys(); 
1646                 PrintAndLog("Too many operations specified\n"); 
1647                 return usage_hf_iclass_managekeys(); 
1649         if (operation 
> 4 && fileNameLen 
== 0){ 
1650                 PrintAndLog("You must enter a filename when loading or saving\n"); 
1651                 return usage_hf_iclass_managekeys(); 
1655                 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1; 
1656                 case 4: return printKeys(); 
1657                 case 5: return loadKeys(filename
); 
1658                 case 6: return saveKeys(filename
); 
1664 static command_t CommandTable
[] = { 
1665         {"help",                CmdHelp
,                                                1,      "This help"}, 
1666         {"calcnewkey",  CmdHFiClassCalcNewKey
,          1,      "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"}, 
1667         {"clone",       CmdHFiClassCloneTag
,            0,      "[options..] Authenticate and Clone from iClass bin file"}, 
1668         {"decrypt",     CmdHFiClassDecrypt
,             1,      "[f <fname>] Decrypt tagdump" }, 
1669         {"dump",        CmdHFiClassReader_Dump
,         0,      "[options..] Authenticate and Dump iClass tag's AA1"}, 
1670         {"eload",       CmdHFiClassELoad
,               0,      "[f <fname>] (experimental) Load data into iClass emulator memory"}, 
1671         {"encryptblk",  CmdHFiClassEncryptBlk
,          1,      "<BlockData> Encrypt given block data"}, 
1672         {"list",        CmdHFiClassList
,                0,      "            (Deprecated) List iClass history"}, 
1673         {"loclass",     CmdHFiClass_loclass
,            1,      "[options..] Use loclass to perform bruteforce of reader attack dump"}, 
1674         {"managekeys",  CmdHFiClassManageKeys
,          1,      "[options..] Manage the keys to use with iClass"}, 
1675         {"readblk",     CmdHFiClass_ReadBlock
,          0,      "[options..] Authenticate and Read iClass block"}, 
1676         {"reader",              CmdHFiClassReader
,                              0,      "Read an iClass tag"}, 
1677         {"readtagfile", CmdHFiClassReadTagFile
,         1,      "[options..] Display Content from tagfile"}, 
1678         {"replay",      CmdHFiClassReader_Replay
,       0,      "<mac>       Read an iClass tag via Reply Attack"}, 
1679         {"sim",         CmdHFiClassSim
,                 0,      "[options..] Simulate iClass tag"}, 
1680         {"snoop",       CmdHFiClassSnoop
,               0,      "            Eavesdrop iClass communication"}, 
1681         {"writeblk",    CmdHFiClass_WriteBlock
,         0,      "[options..] Authenticate and Write iClass block"}, 
1682         {NULL
, NULL
, 0, NULL
} 
1685 int CmdHFiClass(const char *Cmd
) { 
1686         clearCommandBuffer(); 
1687         CmdsParse(CommandTable
, Cmd
); 
1691 int CmdHelp(const char *Cmd
) { 
1692         CmdsHelp(CommandTable
);