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