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");
175 int usage_hf_iclass_reader(void) {
176 PrintAndLog("HELP : Act as a Iclass reader:\n");
177 PrintAndLog("Usage: hf iclass reader [h] [1]\n");
178 PrintAndLog("Options:");
179 PrintAndLog(" h This help text");
180 PrintAndLog(" 1 read only 1 tag");
181 PrintAndLog("Samples:");
182 PrintAndLog(" hf iclass reader 1");
185 int usage_hf_iclass_replay(void){
186 PrintAndLog("HELP: Replay a collected mac message");
187 PrintAndLog("Usage: hf iclass replay [h] <mac>");
188 PrintAndLog("Options:");
189 PrintAndLog(" h This help text");
190 PrintAndLog(" <mac> Mac bytes to replay (8 hexsymbols)");
191 PrintAndLog("Samples:");
192 PrintAndLog(" hf iclass replay 00112233");
195 int usage_hf_iclass_snoop(void){
196 PrintAndLog("HELP: Snoops the communication between reader and tag");
197 PrintAndLog("Usage: hf iclass snoop [h]");
198 PrintAndLog("Samples:");
199 PrintAndLog(" hf iclass snoop");
203 int xorbits_8(uint8_t val
) {
204 uint8_t res
= val
^ (val
>> 1); //1st pass
205 res
= res
^ (res
>> 1); // 2nd pass
206 res
= res
^ (res
>> 2); // 3rd pass
207 res
= res
^ (res
>> 4); // 4th pass
211 int CmdHFiClassList(const char *Cmd
) {
212 //PrintAndLog("Deprecated command, use 'hf list iclass' instead");
217 int CmdHFiClassSnoop(const char *Cmd
) {
218 char cmdp
= param_getchar(Cmd
, 0);
219 if (cmdp
== 'h' || cmdp
== 'H') return usage_hf_iclass_snoop();
221 UsbCommand c
= {CMD_SNOOP_ICLASS
};
226 int CmdHFiClassSim(const char *Cmd
) {
228 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
230 if (strlen(Cmd
)<1) return usage_hf_iclass_sim();
232 simType
= param_get8ex(Cmd
, 0, 0, 10);
236 if (param_gethex(Cmd
, 1, CSN
, 16)) {
237 PrintAndLog("A CSN should consist of 16 HEX symbols");
238 return usage_hf_iclass_sim();
241 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
246 PrintAndLog("Undefined simptype %d", simType
);
247 return usage_hf_iclass_sim();
250 uint8_t numberOfCSNs
=0;
253 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
254 UsbCommand resp
= {0};
256 uint8_t csns
[8*NUM_CSNS
] = {
257 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
258 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
259 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
260 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
261 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
262 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
263 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
264 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
265 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
266 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
267 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
268 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
269 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
270 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
271 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
273 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
274 clearCommandBuffer();
276 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
277 PrintAndLog("Command timed out");
281 uint8_t num_mac_responses
= resp
.arg
[1];
282 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
284 size_t datalen
= NUM_CSNS
*24;
286 * Now, time to dump to file. We'll use this format:
287 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
288 * So, it should wind up as
291 * The returndata from the pm3 is on the following format
292 * <4 byte NR><4 byte MAC>
293 * CC are all zeroes, CSN is the same as was sent in
295 void* dump
= malloc(datalen
);
296 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
298 for(i
= 0 ; i
< NUM_CSNS
; i
++) {
299 memcpy(dump
+i
*24, csns
+i
*8, 8); //CSN
300 //8 zero bytes here...
301 //Then comes NR_MAC (eight bytes from the response)
302 memcpy(dump
+i
*24+16, resp
.d
.asBytes
+i
*8, 8);
304 /** Now, save to dumpfile **/
305 saveFile("iclass_mac_attack", "bin", dump
, datalen
);
308 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
309 memcpy(c
.d
.asBytes
, CSN
, 8);
310 clearCommandBuffer();
316 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
317 bool tagFound
= false;
318 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
319 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_AA
}};
320 // loop in client not device - else on windows have a communication error
321 c
.arg
[0] |= FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
;
324 clearCommandBuffer();
326 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
327 uint8_t readStatus
= resp
.arg
[0] & 0xff;
328 uint8_t *data
= resp
.d
.asBytes
;
330 if (verbose
) PrintAndLog("Readstatus:%02x", readStatus
);
331 if( readStatus
== 0){
333 if (verbose
) PrintAndLog("Quitting...");
336 if( readStatus
& FLAG_ICLASS_READER_CSN
){
337 PrintAndLog("CSN: %s",sprint_hex(data
,8));
340 if( readStatus
& FLAG_ICLASS_READER_CC
) PrintAndLog("CC: %s", sprint_hex(data
+16, 8));
341 if( readStatus
& FLAG_ICLASS_READER_CONF
) printIclassDumpInfo(data
);
342 if (tagFound
&& !loop
) return 1;
344 if (verbose
) PrintAndLog("Command execute timeout");
351 int CmdHFiClassReader(const char *Cmd
) {
352 char cmdp
= param_getchar(Cmd
, 0);
353 if (cmdp
== 'h' || cmdp
== 'H') return usage_hf_iclass_reader();
354 bool findone
= (cmdp
== '1') ? FALSE
: TRUE
;
355 return HFiClassReader(Cmd
, findone
, true);
358 int CmdHFiClassReader_Replay(const char *Cmd
) {
359 uint8_t readerType
= 0;
360 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
362 if (strlen(Cmd
)<1) return usage_hf_iclass_replay();
364 if (param_gethex(Cmd
, 0, MAC
, 8)) {
365 PrintAndLog("MAC must include 8 HEX symbols");
369 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
370 memcpy(c
.d
.asBytes
, MAC
, 4);
371 clearCommandBuffer();
376 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
377 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
378 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
379 clearCommandBuffer();
384 int CmdHFiClassELoad(const char *Cmd
) {
386 char opt
= param_getchar(Cmd
, 0);
387 if (strlen(Cmd
)<1 || opt
== 'h' || opt
== 'H') return usage_hf_iclass_eload();
389 //File handling and reading
391 char filename
[FILE_PATH_SIZE
];
392 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0) {
393 f
= fopen(filename
, "rb");
395 return usage_hf_iclass_eload();
399 PrintAndLog("Failed to read from file '%s'", filename
);
403 fseek(f
, 0, SEEK_END
);
404 long fsize
= ftell(f
);
405 fseek(f
, 0, SEEK_SET
);
408 prnlog("Error, when getting filesize");
413 uint8_t *dump
= malloc(fsize
);
415 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
418 printIclassDumpInfo(dump
);
421 if (bytes_read
< fsize
) {
422 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
427 uint32_t bytes_sent
= 0;
428 uint32_t bytes_remaining
= bytes_read
;
430 while(bytes_remaining
> 0){
431 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
432 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
433 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
434 clearCommandBuffer();
436 bytes_remaining
-= bytes_in_packet
;
437 bytes_sent
+= bytes_in_packet
;
440 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
444 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
445 FILE *f
= fopen(filename
, "rb");
447 PrintAndLog("Failed to read from file '%s'", filename
);
450 fseek(f
, 0, SEEK_END
);
451 long fsize
= ftell(f
);
452 fseek(f
, 0, SEEK_SET
);
453 size_t bytes_read
= fread(buffer
, 1, len
, f
);
457 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
461 if(bytes_read
!= len
) {
462 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
468 int CmdHFiClassDecrypt(const char *Cmd
) {
470 char opt
= param_getchar(Cmd
, 0);
471 if (strlen(Cmd
)<1 || opt
== 'h' || opt
== 'H') return usage_hf_iclass_decrypt();
473 uint8_t key
[16] = { 0 };
474 if(readKeyfile("iclass_decryptionkey.bin", 16, key
)) return usage_hf_iclass_decrypt();
476 PrintAndLog("Decryption file found...");
478 //Open the tagdump-file
480 char filename
[FILE_PATH_SIZE
];
481 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0) {
482 if ( (f
= fopen(filename
, "rb")) == NULL
) {
483 PrintAndLog("Could not find file %s", filename
);
487 return usage_hf_iclass_decrypt();
490 fseek(f
, 0, SEEK_END
);
491 long fsize
= ftell(f
);
492 fseek(f
, 0, SEEK_SET
);
495 PrintAndLog("Error, when getting filesize");
500 uint8_t *decrypted
= malloc(fsize
);
502 size_t bytes_read
= fread(decrypted
, 1, fsize
, f
);
504 if ( bytes_read
== 0) {
505 PrintAndLog("File reading error");
510 picopass_hdr
*hdr
= (picopass_hdr
*)decrypted
;
512 uint8_t mem
= hdr
->conf
.mem_config
;
513 uint8_t chip
= hdr
->conf
.chip_config
;
514 uint8_t applimit
= hdr
->conf
.app_limit
;
516 uint8_t app_areas
= 2;
517 uint8_t max_blk
= 31;
518 getMemConfig(mem
, chip
, &max_blk
, &app_areas
, &kb
);
520 //Use the first block (CSN) for filename
521 char outfilename
[FILE_PATH_SIZE
] = {0};
522 snprintf(outfilename
, FILE_PATH_SIZE
, "iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
523 hdr
->csn
[0],hdr
->csn
[1],hdr
->csn
[2],hdr
->csn
[3],
524 hdr
->csn
[4],hdr
->csn
[5],hdr
->csn
[6],hdr
->csn
[7]);
527 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
528 des3_set2key_dec( &ctx
, key
);
530 uint8_t enc_dump
[8] = {0};
531 uint8_t empty
[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
532 for(uint16_t blocknum
=0; blocknum
< applimit
; ++blocknum
) {
534 uint8_t idx
= blocknum
*8;
535 memcpy(enc_dump
, decrypted
+ idx
, 8);
537 // block 7 or higher, and not empty 0xFF
538 if(blocknum
> 6 && memcmp(enc_dump
, empty
, 8) != 0 ) {
539 des3_crypt_ecb(&ctx
, enc_dump
, decrypted
+ idx
);
541 //printvar("decrypted block", decrypted + idx, 8);
544 saveFile(outfilename
, "bin", decrypted
, fsize
);
547 printIclassDumpContents(decrypted
, 1, (fsize
/8), fsize
);
551 static int iClassEncryptBlkData(uint8_t *blkData
) {
552 uint8_t key
[16] = { 0 };
553 if(readKeyfile("iclass_decryptionkey.bin", 16, key
)) {
554 usage_hf_iclass_encrypt();
557 PrintAndLog("Decryption file found... ");
558 uint8_t encryptedData
[16];
559 uint8_t *encrypted
= encryptedData
;
560 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
561 des3_set2key_enc( &ctx
, key
);
563 des3_crypt_ecb(&ctx
, blkData
,encrypted
);
564 //printvar("decrypted block", decrypted, 8);
565 memcpy(blkData
,encrypted
,8);
570 int CmdHFiClassEncryptBlk(const char *Cmd
) {
571 uint8_t blkData
[8] = {0};
572 char opt
= param_getchar(Cmd
, 0);
573 if (strlen(Cmd
)<1 || opt
== 'h' || opt
== 'H') return usage_hf_iclass_encrypt();
575 //get the bytes to encrypt
576 if (param_gethex(Cmd
, 0, blkData
, 16)) {
577 PrintAndLog("BlockData must include 16 HEX symbols");
580 if (!iClassEncryptBlkData(blkData
)) return 0;
582 printvar("encrypted block", blkData
, 8);
586 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
589 memcpy(WB
+ 1,data
,8);
590 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
591 //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]);
594 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
597 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
598 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
600 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
602 clearCommandBuffer();
604 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
605 PrintAndLog("Command execute timeout");
609 uint8_t isOK
= resp
.arg
[0] & 0xff;
610 uint8_t *data
= resp
.d
.asBytes
;
615 memcpy(CCNR
,data
+16,8);
618 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
622 PrintAndLog("Failed to obtain CC! Aborting");
628 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
) {
629 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
630 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
632 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
637 memcpy(div_key
, KEY
, 8);
639 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
641 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]);
643 doMAC(CCNR
, div_key
, MAC
);
645 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
646 memcpy(d
.d
.asBytes
, MAC
, 4);
647 clearCommandBuffer();
649 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
650 PrintAndLog("Auth Command execute timeout");
653 uint8_t isOK
= resp
.arg
[0] & 0xff;
655 PrintAndLog("Authentication error");
661 int CmdHFiClassReader_Dump(const char *Cmd
) {
663 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
664 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
665 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
669 uint8_t app_areas
= 1;
671 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
672 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
675 uint8_t fileNameLen
= 0;
676 char filename
[FILE_PATH_SIZE
]={0};
677 char tempStr
[50] = {0};
678 bool have_debit_key
= false;
679 bool have_credit_key
= false;
680 bool use_credit_key
= false;
686 while(param_getchar(Cmd
, cmdp
) != 0x00)
688 switch(param_getchar(Cmd
, cmdp
))
692 return usage_hf_iclass_dump();
695 have_credit_key
= true;
696 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
698 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
699 } else if (dataLen
== 1) {
700 keyNbr
= param_get8(Cmd
, cmdp
+1);
701 if (keyNbr
< ICLASS_KEYS_MAX
) {
702 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
704 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
708 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
720 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
721 if (fileNameLen
< 1) {
722 PrintAndLog("No filename found after f");
729 have_debit_key
= true;
730 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
732 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
733 } else if (dataLen
== 1) {
734 keyNbr
= param_get8(Cmd
, cmdp
+1);
735 if (keyNbr
< ICLASS_KEYS_MAX
) {
736 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
738 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
742 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
753 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
757 if(errors
) return usage_hf_iclass_dump();
760 if (cmdp
< 2) return usage_hf_iclass_dump();
761 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
762 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
764 //get config and first 3 blocks
765 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
766 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
768 uint8_t tag_data
[255*8];
770 clearCommandBuffer();
772 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
773 PrintAndLog("Command execute timeout");
774 ul_switch_off_field();
777 uint8_t readStatus
= resp
.arg
[0] & 0xff;
778 uint8_t * data
= resp
.d
.asBytes
;
781 PrintAndLog("No tag found...");
782 ul_switch_off_field();
786 if( readStatus
& (FLAG_ICLASS_READER_CSN
| FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_CC
)){
787 memcpy(tag_data
, data
, 8*3);
788 blockno
+= 2; // 2 to force re-read of block 2 later. (seems to respond differently..)
790 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
791 // large memory - not able to dump pages currently
792 if (numblks
> maxBlk
) numblks
= maxBlk
;
795 ul_switch_off_field();
796 // authenticate debit key and get div_key - later store in dump block 3
797 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
798 //try twice - for some reason it sometimes fails the first time...
799 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
800 ul_switch_off_field();
806 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
807 clearCommandBuffer();
809 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
810 PrintAndLog("Command execute time-out 1");
811 ul_switch_off_field();
814 uint32_t blocksRead
= resp
.arg
[1];
815 uint8_t isOK
= resp
.arg
[0] & 0xff;
816 if (!isOK
&& !blocksRead
) {
817 PrintAndLog("Read Block Failed");
818 ul_switch_off_field();
821 uint32_t startindex
= resp
.arg
[2];
822 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
823 PrintAndLog("Data exceeded Buffer size!");
824 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
826 // response ok - now get bigbuf content of the dump
827 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
);
828 WaitForResponse(CMD_ACK
,NULL
);
829 size_t gotBytes
= blocksRead
*8 + blockno
*8;
832 if (have_credit_key
) {
833 //turn off hf field before authenticating with different key
834 ul_switch_off_field();
836 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
837 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
838 //try twice - for some reason it sometimes fails the first time...
839 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
840 ul_switch_off_field();
844 // do we still need to read more block? (aa2 enabled?)
845 if (maxBlk
> blockno
+numblks
+1) {
846 // setup dump and start
847 w
.arg
[0] = blockno
+ blocksRead
;
848 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
849 clearCommandBuffer();
851 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
852 PrintAndLog("Command execute timeout 2");
853 ul_switch_off_field();
856 uint8_t isOK
= resp
.arg
[0] & 0xff;
857 blocksRead
= resp
.arg
[1];
858 if (!isOK
&& !blocksRead
) {
859 PrintAndLog("Read Block Failed 2");
860 ul_switch_off_field();
864 startindex
= resp
.arg
[2];
865 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
866 PrintAndLog("Data exceeded Buffer size!");
867 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
869 // get dumped data from bigbuf
870 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
);
871 WaitForResponse(CMD_ACK
,NULL
);
873 gotBytes
+= blocksRead
*8;
874 } else { //field is still on - turn it off...
875 ul_switch_off_field();
879 // add diversified keys to dump
880 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
881 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
883 printf("Num of bytes: %u\n", gotBytes
);
886 printf("------+--+-------------------------+\n");
887 printf("CSN |00| %s|\n", sprint_hex(tag_data
, 8));
888 //printIclassDumpContents(tag_data, 1, (gotBytes/8)-1, gotBytes-8);
889 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
891 if (filename
[0] == 0){
892 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
893 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
894 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
897 // save the dump to .bin file
898 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
899 saveFile(filename
, "bin", tag_data
, gotBytes
);
903 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
904 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
905 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
906 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
911 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
912 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
913 memcpy(w
.d
.asBytes
, bldata
, 8);
914 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
916 clearCommandBuffer();
918 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
919 PrintAndLog("Write Command execute timeout");
922 uint8_t isOK
= resp
.arg
[0] & 0xff;
924 PrintAndLog("Write Block Failed");
927 PrintAndLog("Write Block Successful");
931 int CmdHFiClass_WriteBlock(const char *Cmd
) {
933 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
934 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
937 char tempStr
[50] = {0};
938 bool use_credit_key
= false;
943 while(param_getchar(Cmd
, cmdp
) != 0x00)
945 switch(param_getchar(Cmd
, cmdp
))
949 return usage_hf_iclass_writeblock();
952 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
953 PrintAndLog("Block No must include 2 HEX symbols\n");
960 use_credit_key
= true;
965 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
967 PrintAndLog("KEY must include 16 HEX symbols\n");
979 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
981 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
982 } else if (dataLen
== 1) {
983 keyNbr
= param_get8(Cmd
, cmdp
+1);
984 if (keyNbr
< ICLASS_KEYS_MAX
) {
985 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
987 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
991 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1002 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1006 if(errors
) return usage_hf_iclass_writeblock();
1009 if (cmdp
< 6) return usage_hf_iclass_writeblock();
1010 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
1011 ul_switch_off_field();
1015 int CmdHFiClassCloneTag(const char *Cmd
) {
1016 char filename
[FILE_PATH_SIZE
] = { 0x00 };
1017 char tempStr
[50]={0};
1018 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1020 uint8_t fileNameLen
= 0;
1021 uint8_t startblock
= 0;
1022 uint8_t endblock
= 0;
1023 uint8_t dataLen
= 0;
1024 bool use_credit_key
= false;
1026 bool rawkey
= false;
1027 bool errors
= false;
1029 while(param_getchar(Cmd
, cmdp
) != 0x00)
1031 switch(param_getchar(Cmd
, cmdp
))
1035 return usage_hf_iclass_clone();
1038 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
1039 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1046 use_credit_key
= true;
1056 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
1057 if (fileNameLen
< 1) {
1058 PrintAndLog("No filename found after f");
1065 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1066 if (dataLen
== 16) {
1067 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1068 } else if (dataLen
== 1) {
1069 keyNbr
= param_get8(Cmd
, cmdp
+1);
1070 if (keyNbr
< ICLASS_KEYS_MAX
) {
1071 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1073 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1077 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1084 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1085 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1096 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1100 if(errors
) return usage_hf_iclass_clone();
1103 if (cmdp
< 8) return usage_hf_iclass_clone();
1107 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1109 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1110 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1112 // file handling and reading
1113 f
= fopen(filename
,"rb");
1115 PrintAndLog("Failed to read from file '%s'", filename
);
1120 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1124 // now read data from the file from block 6 --- 19
1125 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1126 // 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,
1127 // else we have to create a share memory
1129 fseek(f
,startblock
*8,SEEK_SET
);
1130 size_t bytes_read
= fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
);
1131 if ( bytes_read
== 0){
1132 PrintAndLog("File reading error.");
1137 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1138 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1140 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1143 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1145 // calculate all mac for every the block we will write
1146 for (i
= startblock
; i
<= endblock
; i
++){
1147 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1148 // usb command d start pointer = d + (i - 6) * 12
1149 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1150 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1152 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1153 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1154 memcpy(ptr
+ 8,MAC
, 4);
1157 for (i
= 0; i
<= endblock
- startblock
;i
++){
1158 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1159 printf("Block |%02x|",i
+ startblock
);
1160 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]);
1161 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1164 clearCommandBuffer();
1166 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
1167 PrintAndLog("Command execute timeout");
1173 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
) {
1174 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1175 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1177 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1181 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1182 clearCommandBuffer();
1184 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500)) {
1185 PrintAndLog("Command execute timeout");
1189 uint8_t isOK
= resp
.arg
[0] & 0xff;
1191 PrintAndLog("Read Block Failed");
1194 //data read is stored in: resp.d.asBytes[0-15]
1195 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1199 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1201 uint8_t keyType
= 0x88; //debit key
1202 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1204 uint8_t dataLen
= 0;
1205 char tempStr
[50] = {0};
1207 bool rawkey
= false;
1208 bool errors
= false;
1210 while(param_getchar(Cmd
, cmdp
) != 0x00)
1212 switch(param_getchar(Cmd
, cmdp
))
1216 return usage_hf_iclass_readblock();
1219 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1220 PrintAndLog("Block No must include 2 HEX symbols\n");
1237 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1238 if (dataLen
== 16) {
1239 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1240 } else if (dataLen
== 1) {
1241 keyNbr
= param_get8(Cmd
, cmdp
+1);
1242 if (keyNbr
< ICLASS_KEYS_MAX
) {
1243 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1245 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1249 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1260 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1264 if(errors
) return usage_hf_iclass_readblock();
1267 if (cmdp
< 4) return usage_hf_iclass_readblock();
1269 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true);
1272 int CmdHFiClass_loclass(const char *Cmd
) {
1273 char opt
= param_getchar(Cmd
, 0);
1275 if (strlen(Cmd
)<1 || opt
== 'h') {
1276 PrintAndLog("Usage: hf iclass loclass [options]");
1277 PrintAndLog("Options:");
1278 PrintAndLog("h Show this help");
1279 PrintAndLog("t Perform self-test");
1280 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1281 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1282 PrintAndLog(" malicious CSNs, and their protocol responses");
1283 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1284 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1285 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1286 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1287 PrintAndLog(" ... totalling N*24 bytes");
1290 char fileName
[255] = {0};
1292 if(param_getstr(Cmd
, 1, fileName
) > 0) {
1293 return bruteforceFileNoKeys(fileName
);
1295 PrintAndLog("You must specify a filename");
1299 else if(opt
== 't') {
1300 int errors
= testCipherUtils();
1301 errors
+= testMAC();
1302 errors
+= doKeyTests(0);
1303 errors
+= testElite();
1304 if(errors
) prnlog("OBS! There were errors!!!");
1310 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1312 memcpy(&mem_config
, iclass_dump
+ 13,1);
1313 uint8_t maxmemcount
;
1315 uint8_t filemaxblock
= filesize
/ 8;
1317 if (mem_config
& 0x80)
1322 if (startblock
== 0)
1325 if ((endblock
> maxmemcount
) || (endblock
== 0))
1326 endblock
= maxmemcount
;
1328 // remember endblock needs to relate to zero-index arrays.
1329 if (endblock
> filemaxblock
-1)
1330 endblock
= filemaxblock
-1;
1332 //PrintAndLog ("startblock: %d, endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d",startblock, endblock,filesize, maxmemcount, filemaxblock);
1335 printf("------+--+-------------------------+\n");
1336 while (i
<= endblock
){
1337 uint8_t *blk
= iclass_dump
+ (i
* 8);
1338 printf("Block |%02X| %s\n", i
, sprint_hex_ascii(blk
, 8) );
1341 printf("------+--+-------------------------+\n");
1344 int CmdHFiClassReadTagFile(const char *Cmd
) {
1349 char filename
[FILE_PATH_SIZE
];
1350 if (param_getstr(Cmd
, 0, filename
) < 1)
1351 return usage_hf_iclass_readtagfile();
1353 if (param_getstr(Cmd
,1,(char *)&tempnum
) < 1)
1356 sscanf(tempnum
,"%d",&startblock
);
1358 if (param_getstr(Cmd
,2,(char *)&tempnum
) < 1)
1361 sscanf(tempnum
,"%d",&endblock
);
1363 // file handling and reading
1364 f
= fopen(filename
,"rb");
1366 PrintAndLog("Failed to read from file '%s'", filename
);
1369 fseek(f
, 0, SEEK_END
);
1370 long fsize
= ftell(f
);
1371 fseek(f
, 0, SEEK_SET
);
1374 PrintAndLog("Error, when getting filesize");
1379 uint8_t *dump
= malloc(fsize
);
1380 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1383 uint8_t *csn
= dump
;
1384 printf("------+--+-------------------------+\n");
1385 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1386 printIclassDumpContents(dump
, startblock
, endblock
, bytes_read
);
1392 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1393 uint64_t new_div = 0x00;
1399 uint64_t hexarray_to_uint64(uint8_t *key) {
1402 for (int i = 0;i < 8;i++)
1403 sprintf(&temp[(i *2)],"%02X",key[i]);
1405 if (sscanf(temp,"%016"llX,&uint_key) < 1)
1410 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1411 uint8_t keytable
[128] = {0};
1412 uint8_t key_index
[8] = {0};
1414 uint8_t key_sel
[8] = { 0 };
1415 uint8_t key_sel_p
[8] = { 0 };
1416 hash2(KEY
, keytable
);
1417 hash1(CSN
, key_index
);
1418 for(uint8_t i
= 0; i
< 8 ; i
++)
1419 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1421 //Permute from iclass format to standard format
1422 permutekey_rev(key_sel
, key_sel_p
);
1423 diversifyKey(CSN
, key_sel_p
, div_key
);
1425 diversifyKey(CSN
, KEY
, div_key
);
1429 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1430 //calculate and return xor_div_key (ready for a key write command)
1431 //print all div_keys if verbose
1432 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1433 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1434 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1436 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1438 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1440 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1441 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1444 printf("Old div key : %s\n",sprint_hex(old_div_key
,8));
1445 printf("New div key : %s\n",sprint_hex(new_div_key
,8));
1446 printf("Xor div key : %s\n",sprint_hex(xor_div_key
,8));
1450 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1451 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1452 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1453 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1454 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1455 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1457 uint8_t dataLen
= 0;
1458 char tempStr
[50] = {0};
1459 bool givenCSN
= false;
1460 bool oldElite
= false;
1462 bool errors
= false;
1464 while(param_getchar(Cmd
, cmdp
) != 0x00)
1466 switch(param_getchar(Cmd
, cmdp
))
1470 return usage_hf_iclass_calc_newkey();
1473 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
);
1481 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1482 if (dataLen
== 16) {
1483 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1484 } else if (dataLen
== 1) {
1485 keyNbr
= param_get8(Cmd
, cmdp
+1);
1486 if (keyNbr
< ICLASS_KEYS_MAX
) {
1487 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1489 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1493 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1500 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1501 if (dataLen
== 16) {
1502 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1503 } else if (dataLen
== 1) {
1504 keyNbr
= param_get8(Cmd
, cmdp
+1);
1505 if (keyNbr
< ICLASS_KEYS_MAX
) {
1506 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1508 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1512 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1520 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1521 return usage_hf_iclass_calc_newkey();
1525 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1529 if(errors
) return usage_hf_iclass_calc_newkey();
1532 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1535 if (!select_only(CSN
, CCNR
, false, true))
1538 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1542 static int loadKeys(char *filename
) {
1544 f
= fopen(filename
,"rb");
1546 PrintAndLog("Failed to read from file '%s'", filename
);
1549 fseek(f
, 0, SEEK_END
);
1550 long fsize
= ftell(f
);
1551 fseek(f
, 0, SEEK_SET
);
1554 PrintAndLog("Error, when getting filesize");
1559 uint8_t *dump
= malloc(fsize
);
1561 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1563 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1564 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1569 for (; i
< bytes_read
/8; i
++)
1570 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1573 PrintAndLog("%u keys loaded", i
);
1577 static int saveKeys(char *filename
) {
1579 f
= fopen(filename
,"wb");
1581 printf("error opening file %s\n",filename
);
1584 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1585 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1586 PrintAndLog("save key failed to write to file: %s", filename
);
1594 static int printKeys(void) {
1596 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++)
1597 PrintAndLog("%u: %s", i
, sprint_hex(iClass_Key_Table
[i
],8));
1602 int CmdHFiClassManageKeys(const char *Cmd
) {
1604 uint8_t dataLen
= 0;
1605 uint8_t KEY
[8] = {0};
1606 char filename
[FILE_PATH_SIZE
];
1607 uint8_t fileNameLen
= 0;
1608 bool errors
= false;
1609 uint8_t operation
= 0;
1613 while(param_getchar(Cmd
, cmdp
) != 0x00)
1615 switch(param_getchar(Cmd
, cmdp
))
1619 return usage_hf_iclass_managekeys();
1622 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
1623 if (fileNameLen
< 1) {
1624 PrintAndLog("No filename found after f");
1631 keyNbr
= param_get8(Cmd
, cmdp
+1);
1633 PrintAndLog("Wrong block number");
1640 operation
+= 3; //set key
1641 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1642 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1643 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1645 PrintAndLog("\nERROR: Key is incorrect length\n");
1652 operation
+= 4; //print keys in memory
1657 operation
+= 5; //load keys from file
1662 operation
+= 6; //save keys to file
1666 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1670 if(errors
) return usage_hf_iclass_managekeys();
1672 if (operation
== 0){
1673 PrintAndLog("no operation specified (load, save, or print)\n");
1674 return usage_hf_iclass_managekeys();
1677 PrintAndLog("Too many operations specified\n");
1678 return usage_hf_iclass_managekeys();
1680 if (operation
> 4 && fileNameLen
== 0){
1681 PrintAndLog("You must enter a filename when loading or saving\n");
1682 return usage_hf_iclass_managekeys();
1686 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1687 case 4: return printKeys();
1688 case 5: return loadKeys(filename
);
1689 case 6: return saveKeys(filename
);
1695 static command_t CommandTable
[] = {
1696 {"help", CmdHelp
, 1, "This help"},
1697 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1698 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1699 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1700 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1701 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1702 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1703 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1704 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1705 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1706 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1707 {"reader", CmdHFiClassReader
, 0, "Read an iClass tag"},
1708 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1709 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1710 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1711 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1712 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1713 {NULL
, NULL
, 0, NULL
}
1716 int CmdHFiClass(const char *Cmd
) {
1717 clearCommandBuffer();
1718 CmdsParse(CommandTable
, Cmd
);
1722 int CmdHelp(const char *Cmd
) {
1723 CmdsHelp(CommandTable
);