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
);