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 //-----------------------------------------------------------------------------
18 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
21 #include "cmdparser.h"
22 #include "cmdhficlass.h"
26 #include "mbedtls/des.h"
27 #include "loclass/cipherutils.h"
28 #include "loclass/cipher.h"
29 #include "loclass/ikeys.h"
30 #include "loclass/elite_crack.h"
31 #include "loclass/fileutils.h"
32 #include "protocols.h"
35 #include "util_posix.h"
36 #include "cmdhf14a.h" // DropField()
38 static int CmdHelp(const char *Cmd
);
40 #define ICLASS_KEYS_MAX 8
41 static uint8_t iClass_Key_Table
[ICLASS_KEYS_MAX
][8] = {
42 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
43 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
44 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
45 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
46 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
47 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
48 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
49 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
52 typedef struct iclass_block
{
56 int usage_hf_iclass_chk(void) {
57 PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");
58 PrintAndLog("Usage: hf iclass chk [h|e|r] <f (*.dic)>");
59 PrintAndLog("Options:");
60 PrintAndLog("h Show this help");
61 PrintAndLog("f <filename> Dictionary file with default iclass keys");
62 PrintAndLog(" e target Elite / High security key scheme");
63 PrintAndLog(" r interpret dictionary file as raw (diversified keys)");
64 PrintAndLog("Samples:");
65 PrintAndLog(" hf iclass chk f default_iclass_keys.dic");
66 PrintAndLog(" hf iclass chk f default_iclass_keys.dic e");
70 int xorbits_8(uint8_t val
) {
71 uint8_t res
= val
^ (val
>> 1); //1st pass
72 res
= res
^ (res
>> 1); // 2nd pass
73 res
= res
^ (res
>> 2); // 3rd pass
74 res
= res
^ (res
>> 4); // 4th pass
78 int CmdHFiClassList(const char *Cmd
) {
79 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
83 int CmdHFiClassSnoop(const char *Cmd
) {
84 UsbCommand c
= {CMD_SNOOP_ICLASS
};
89 int usage_hf_iclass_sim(void) {
90 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
91 PrintAndLog(" options");
92 PrintAndLog(" 0 <CSN> simulate the given CSN");
93 PrintAndLog(" 1 simulate default CSN");
94 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
95 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
96 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
97 PrintAndLog(" example: hf iclass sim 2");
98 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
99 PrintAndLog(" hf iclass sim 3");
103 // the original malicious IDs from Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult,
104 // and Milosch Meriac. Dismantling iClass and iClass Elite.
106 static uint8_t csns
[8 * NUM_CSNS
] = {
107 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
108 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
109 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
110 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
111 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
112 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
113 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
114 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
115 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
116 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
117 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
118 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
119 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
120 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
121 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
124 // pre-defined 9 CSNs by iceman.
125 // only one csn depend on several others.
126 // six depends only on the first csn, (0,1, 0x45)
128 // #define NUM_CSNS 9
129 // static uint8_t csns[8 * NUM_CSNS] = {
130 // 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
131 // 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0,
132 // 0x10, 0x97, 0x83, 0x7B, 0xF7, 0xFF, 0x12, 0xE0,
133 // 0x13, 0x97, 0x82, 0x7A, 0xF7, 0xFF, 0x12, 0xE0,
134 // 0x07, 0x0E, 0x0D, 0xF9, 0xF7, 0xFF, 0x12, 0xE0,
135 // 0x14, 0x96, 0x84, 0x76, 0xF7, 0xFF, 0x12, 0xE0,
136 // 0x17, 0x96, 0x85, 0x71, 0xF7, 0xFF, 0x12, 0xE0,
137 // 0xCE, 0xC5, 0x0F, 0x77, 0xF7, 0xFF, 0x12, 0xE0,
138 // 0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0
139 // //0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0
143 int CmdHFiClassSim(const char *Cmd
) {
145 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
148 return usage_hf_iclass_sim();
150 simType
= param_get8ex(Cmd
, 0, 0, 10);
152 if (simType
== ICLASS_SIM_MODE_CSN
) {
153 if (param_gethex(Cmd
, 1, CSN
, 16)) {
154 PrintAndLog("A CSN should consist of 16 HEX symbols");
155 return usage_hf_iclass_sim();
157 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
160 uint8_t numberOfCSNs
= 0;
161 if (simType
== ICLASS_SIM_MODE_READER_ATTACK
) {
162 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
, NUM_CSNS
}};
163 UsbCommand resp
= {0};
165 memcpy(c
.d
.asBytes
, csns
, 8 * NUM_CSNS
);
168 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
169 PrintAndLog("Command timed out");
173 uint8_t num_mac_responses
= resp
.arg
[1];
174 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
, NUM_CSNS
);
176 size_t datalen
= NUM_CSNS
* 24;
178 * Now, time to dump to file. We'll use this format:
179 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
180 * So, it should wind up as
183 * The returndata from the pm3 is on the following format
184 * <8 byte CC><4 byte NR><4 byte MAC>
185 * CSN is the same as was sent in
187 void* dump
= malloc(datalen
);
188 for(int i
= 0; i
< NUM_CSNS
; i
++) {
189 memcpy(dump
+ i
*24, csns
+i
*8, 8); //CSN
190 //copy CC from response
191 memcpy(dump
+ i
*24 + 8, resp
.d
.asBytes
+ i
*16, 8);
192 //Then comes NR_MAC (eight bytes from the response)
193 memcpy(dump
+ i
*24 + 16, resp
.d
.asBytes
+ i
*16 + 8, 8);
195 /** Now, save to dumpfile **/
196 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
199 } else if (simType
== ICLASS_SIM_MODE_CSN
|| simType
== ICLASS_SIM_MODE_CSN_DEFAULT
) {
200 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
, numberOfCSNs
}};
201 memcpy(c
.d
.asBytes
, CSN
, 8);
205 PrintAndLog("Undefined simtype %d", simType
);
206 return usage_hf_iclass_sim();
212 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
213 bool tagFound
= false;
214 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
215 FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_AA
|
216 FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
} };
217 // loop in client not device - else on windows have a communication error
221 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
222 uint8_t readStatus
= resp
.arg
[0] & 0xff;
223 uint8_t *data
= resp
.d
.asBytes
;
225 // no tag found or button pressed
226 if( (readStatus
== 0 && !loop
) || readStatus
== 0xFF) {
228 if (verbose
) PrintAndLog("Quitting...");
232 if( readStatus
& FLAG_ICLASS_READER_CSN
) {
233 PrintAndLog(" CSN: %s",sprint_hex(data
,8));
236 if( readStatus
& FLAG_ICLASS_READER_CC
) {
237 PrintAndLog(" CC: %s",sprint_hex(data
+16,8));
239 if( readStatus
& FLAG_ICLASS_READER_CONF
) {
240 printIclassDumpInfo(data
);
242 if (readStatus
& FLAG_ICLASS_READER_AA
) {
244 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*5,8));
245 for (int i
= 0; i
<8; i
++) {
246 if (data
[8*5+i
] != 0xFF) {
250 PrintAndLog(" : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)");
253 if (tagFound
&& !loop
) return 1;
255 if (verbose
) PrintAndLog("Command execute timeout");
262 int CmdHFiClassReader(const char *Cmd
) {
263 return HFiClassReader(Cmd
, true, true);
266 int CmdHFiClassReader_Replay(const char *Cmd
) {
267 uint8_t readerType
= 0;
268 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
271 PrintAndLog("Usage: hf iclass replay <MAC>");
272 PrintAndLog(" sample: hf iclass replay 00112233");
276 if (param_gethex(Cmd
, 0, MAC
, 8)) {
277 PrintAndLog("MAC must include 8 HEX symbols");
281 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
282 memcpy(c
.d
.asBytes
, MAC
, 4);
288 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
289 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
290 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
295 int hf_iclass_eload_usage(void) {
296 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
297 PrintAndLog("Usage: hf iclass eload f <filename>");
299 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
303 int CmdHFiClassELoad(const char *Cmd
) {
305 char opt
= param_getchar(Cmd
, 0);
306 if (strlen(Cmd
)<1 || opt
== 'h')
307 return hf_iclass_eload_usage();
309 //File handling and reading
311 char filename
[FILE_PATH_SIZE
];
312 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0)
314 f
= fopen(filename
, "rb");
316 return hf_iclass_eload_usage();
320 PrintAndLog("Failed to read from file '%s'", filename
);
324 fseek(f
, 0, SEEK_END
);
325 long fsize
= ftell(f
);
326 fseek(f
, 0, SEEK_SET
);
329 PrintAndLog("Error, when getting filesize");
334 uint8_t *dump
= malloc(fsize
);
336 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
339 printIclassDumpInfo(dump
);
342 if (bytes_read
< fsize
)
344 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
349 uint32_t bytes_sent
= 0;
350 uint32_t bytes_remaining
= bytes_read
;
352 while(bytes_remaining
> 0){
353 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
354 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
355 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
357 bytes_remaining
-= bytes_in_packet
;
358 bytes_sent
+= bytes_in_packet
;
361 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
365 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
366 FILE *f
= fopen(filename
, "rb");
368 PrintAndLog("Failed to read from file '%s'", filename
);
371 fseek(f
, 0, SEEK_END
);
372 long fsize
= ftell(f
);
373 fseek(f
, 0, SEEK_SET
);
374 size_t bytes_read
= fread(buffer
, 1, len
, f
);
378 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
381 if(bytes_read
!= len
)
383 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
389 int usage_hf_iclass_decrypt(void) {
390 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
392 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
393 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
395 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
397 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
398 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
399 PrintAndLog("which is defined by the configuration block.");
403 int CmdHFiClassDecrypt(const char *Cmd
) {
404 uint8_t key
[16] = { 0 };
405 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
407 usage_hf_iclass_decrypt();
410 PrintAndLog("Decryption file found... ");
411 char opt
= param_getchar(Cmd
, 0);
412 if (strlen(Cmd
)<1 || opt
== 'h')
413 return usage_hf_iclass_decrypt();
415 //Open the tagdump-file
417 char filename
[FILE_PATH_SIZE
];
418 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) {
419 f
= fopen(filename
, "rb");
421 PrintAndLog("Could not find file %s", filename
);
425 return usage_hf_iclass_decrypt();
428 fseek(f
, 0, SEEK_END
);
429 long fsize
= ftell(f
);
430 fseek(f
, 0, SEEK_SET
);
431 uint8_t enc_dump
[8] = {0};
432 uint8_t *decrypted
= malloc(fsize
);
433 mbedtls_des3_context ctx
= { {0} };
434 mbedtls_des3_set2key_dec( &ctx
, key
);
435 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
437 //Use the first block (CSN) for filename
438 char outfilename
[FILE_PATH_SIZE
] = { 0 };
439 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
440 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
441 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
444 while(bytes_read
== 8)
448 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
450 mbedtls_des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
452 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
453 bytes_read
= fread(enc_dump
, 1, 8, f
);
458 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
463 int usage_hf_iclass_encrypt(void) {
464 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
466 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
467 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
469 PrintAndLog("example: hf iclass encrypt 0102030405060708");
474 static int iClassEncryptBlkData(uint8_t *blkData
) {
475 uint8_t key
[16] = { 0 };
476 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
478 usage_hf_iclass_encrypt();
481 PrintAndLog("Decryption file found... ");
483 uint8_t encryptedData
[16];
484 uint8_t *encrypted
= encryptedData
;
485 mbedtls_des3_context ctx
= { {0} };
486 mbedtls_des3_set2key_enc( &ctx
, key
);
488 mbedtls_des3_crypt_ecb(&ctx
, blkData
,encrypted
);
489 //printvar("decrypted block", decrypted, 8);
490 memcpy(blkData
,encrypted
,8);
495 int CmdHFiClassEncryptBlk(const char *Cmd
) {
496 uint8_t blkData
[8] = {0};
497 char opt
= param_getchar(Cmd
, 0);
498 if (strlen(Cmd
)<1 || opt
== 'h')
499 return usage_hf_iclass_encrypt();
501 //get the bytes to encrypt
502 if (param_gethex(Cmd
, 0, blkData
, 16))
504 PrintAndLog("BlockData must include 16 HEX symbols");
507 if (!iClassEncryptBlkData(blkData
)) return 0;
509 printvar("encrypted block", blkData
, 8);
513 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
516 memcpy(WB
+ 1,data
,8);
517 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
518 //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]);
521 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
524 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
525 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
527 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
529 clearCommandBuffer();
531 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
533 PrintAndLog("Command execute timeout");
537 uint8_t isOK
= resp
.arg
[0] & 0xff;
538 uint8_t *data
= resp
.d
.asBytes
;
541 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
544 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
547 PrintAndLog("Failed to obtain CC! Aborting");
553 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
) {
554 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
555 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
557 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
562 memcpy(div_key
, KEY
, 8);
564 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
565 if (verbose
) 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]);
567 doMAC(CCNR
, div_key
, MAC
);
569 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
570 memcpy(d
.d
.asBytes
, MAC
, 4);
571 clearCommandBuffer();
573 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
575 if (verbose
) PrintAndLog("Auth Command execute timeout");
578 uint8_t isOK
= resp
.arg
[0] & 0xff;
580 if (verbose
) PrintAndLog("Authentication error");
586 int usage_hf_iclass_dump(void) {
587 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
588 PrintAndLog("Options:");
589 PrintAndLog(" f <filename> : specify a filename to save dump to");
590 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
591 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
592 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
593 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
594 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
595 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
596 PrintAndLog(" NOTE: * = required");
597 PrintAndLog("Samples:");
598 PrintAndLog(" hf iclass dump k 001122334455667B");
599 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
600 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
604 int CmdHFiClassReader_Dump(const char *Cmd
) {
606 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
607 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
608 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
612 uint8_t app_areas
= 1;
614 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
615 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
618 uint8_t fileNameLen
= 0;
619 char filename
[FILE_PATH_SIZE
]={0};
620 char tempStr
[50] = {0};
621 bool have_debit_key
= false;
622 bool have_credit_key
= false;
623 bool use_credit_key
= false;
629 while(param_getchar(Cmd
, cmdp
) != 0x00)
631 switch(param_getchar(Cmd
, cmdp
))
635 return usage_hf_iclass_dump();
638 have_credit_key
= true;
639 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
641 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
642 } else if (dataLen
== 1) {
643 keyNbr
= param_get8(Cmd
, cmdp
+1);
644 if (keyNbr
< ICLASS_KEYS_MAX
) {
645 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
647 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
651 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
663 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
664 if (fileNameLen
< 1) {
665 PrintAndLog("No filename found after f");
672 have_debit_key
= true;
673 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
675 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
676 } else if (dataLen
== 1) {
677 keyNbr
= param_get8(Cmd
, cmdp
+1);
678 if (keyNbr
< ICLASS_KEYS_MAX
) {
679 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
681 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
685 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
696 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
700 if(errors
) return usage_hf_iclass_dump();
703 if (cmdp
< 2) return usage_hf_iclass_dump();
704 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
705 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
707 //get config and first 3 blocks
708 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
709 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
711 uint8_t tag_data
[255*8];
713 clearCommandBuffer();
715 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
716 PrintAndLog("Command execute timeout");
720 uint8_t readStatus
= resp
.arg
[0] & 0xff;
721 uint8_t *data
= resp
.d
.asBytes
;
724 PrintAndLog("No tag found...");
728 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
729 memcpy(tag_data
, data
, 8*3);
730 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
732 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
733 // large memory - not able to dump pages currently
734 if (numblks
> maxBlk
) numblks
= maxBlk
;
737 // authenticate debit key and get div_key - later store in dump block 3
738 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
739 //try twice - for some reason it sometimes fails the first time...
740 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
747 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
748 clearCommandBuffer();
750 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
751 PrintAndLog("Command execute time-out 1");
755 uint32_t blocksRead
= resp
.arg
[1];
756 uint8_t isOK
= resp
.arg
[0] & 0xff;
757 if (!isOK
&& !blocksRead
) {
758 PrintAndLog("Read Block Failed");
762 uint32_t startindex
= resp
.arg
[2];
763 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
764 PrintAndLog("Data exceeded Buffer size!");
765 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
767 // response ok - now get bigbuf content of the dump
768 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
, NULL
, -1, false);
769 size_t gotBytes
= blocksRead
*8 + blockno
*8;
772 if (have_credit_key
) {
773 //turn off hf field before authenticating with different key
776 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
777 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
778 //try twice - for some reason it sometimes fails the first time...
779 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
784 // do we still need to read more block? (aa2 enabled?)
785 if (maxBlk
> blockno
+numblks
+1) {
786 // setup dump and start
787 w
.arg
[0] = blockno
+ blocksRead
;
788 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
789 clearCommandBuffer();
791 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
792 PrintAndLog("Command execute timeout 2");
796 uint8_t isOK
= resp
.arg
[0] & 0xff;
797 blocksRead
= resp
.arg
[1];
798 if (!isOK
&& !blocksRead
) {
799 PrintAndLog("Read Block Failed 2");
804 startindex
= resp
.arg
[2];
805 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
806 PrintAndLog("Data exceeded Buffer size!");
807 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
809 // get dumped data from bigbuf
810 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
, NULL
, -1, false);
812 gotBytes
+= blocksRead
*8;
813 } else { //field is still on - turn it off...
818 // add diversified keys to dump
819 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
820 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
822 printf("------+--+-------------------------+\n");
823 printf("CSN |00| %s|\n",sprint_hex(tag_data
, 8));
824 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
826 if (filename
[0] == 0){
827 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
828 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
829 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
832 // save the dump to .bin file
833 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
834 saveFile(filename
, "bin", tag_data
, gotBytes
);
838 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
839 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
840 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
841 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
846 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
847 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
848 memcpy(w
.d
.asBytes
, bldata
, 8);
849 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
851 clearCommandBuffer();
853 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
855 PrintAndLog("Write Command execute timeout");
858 uint8_t isOK
= resp
.arg
[0] & 0xff;
860 PrintAndLog("Write Block Failed");
863 PrintAndLog("Write Block Successful");
867 int usage_hf_iclass_writeblock(void) {
868 PrintAndLog("Options:");
869 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
870 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
871 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
872 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
873 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
874 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
875 PrintAndLog("Samples:");
876 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
877 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
878 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
882 int CmdHFiClass_WriteBlock(const char *Cmd
) {
884 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
885 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
888 char tempStr
[50] = {0};
889 bool use_credit_key
= false;
894 while(param_getchar(Cmd
, cmdp
) != 0x00)
896 switch(param_getchar(Cmd
, cmdp
))
900 return usage_hf_iclass_writeblock();
903 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
904 PrintAndLog("Block No must include 2 HEX symbols\n");
911 use_credit_key
= true;
916 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
918 PrintAndLog("KEY must include 16 HEX symbols\n");
930 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
932 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
933 } else if (dataLen
== 1) {
934 keyNbr
= param_get8(Cmd
, cmdp
+1);
935 if (keyNbr
< ICLASS_KEYS_MAX
) {
936 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
938 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
942 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
953 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
957 if(errors
) return usage_hf_iclass_writeblock();
960 if (cmdp
< 6) return usage_hf_iclass_writeblock();
961 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
966 int usage_hf_iclass_clone(void) {
967 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
968 PrintAndLog("Options:");
969 PrintAndLog(" f <filename>: specify a filename to clone from");
970 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
971 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
972 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
973 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
974 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
975 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
976 PrintAndLog("Samples:");
977 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
978 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
979 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
983 int CmdHFiClassCloneTag(const char *Cmd
) {
984 char filename
[FILE_PATH_SIZE
] = {0};
985 char tempStr
[50]={0};
986 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
988 uint8_t fileNameLen
= 0;
989 uint8_t startblock
= 0;
990 uint8_t endblock
= 0;
992 bool use_credit_key
= false;
997 while(param_getchar(Cmd
, cmdp
) != 0x00)
999 switch(param_getchar(Cmd
, cmdp
))
1003 return usage_hf_iclass_clone();
1006 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
1007 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1014 use_credit_key
= true;
1024 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1025 if (fileNameLen
< 1) {
1026 PrintAndLog("No filename found after f");
1033 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1034 if (dataLen
== 16) {
1035 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1036 } else if (dataLen
== 1) {
1037 keyNbr
= param_get8(Cmd
, cmdp
+1);
1038 if (keyNbr
< ICLASS_KEYS_MAX
) {
1039 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1041 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1045 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1052 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1053 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1064 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1068 if(errors
) return usage_hf_iclass_clone();
1071 if (cmdp
< 8) return usage_hf_iclass_clone();
1075 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1077 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1078 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1080 // file handling and reading
1081 f
= fopen(filename
,"rb");
1083 PrintAndLog("Failed to read from file '%s'", filename
);
1088 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1092 // now read data from the file from block 6 --- 19
1093 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1094 // 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,
1095 // else we have to create a share memory
1097 fseek(f
,startblock
*8,SEEK_SET
);
1098 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1099 PrintAndLog("File reading error.");
1104 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1105 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1107 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1110 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1112 // calculate all mac for every the block we will write
1113 for (i
= startblock
; i
<= endblock
; i
++){
1114 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1115 // usb command d start pointer = d + (i - 6) * 12
1116 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1117 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1119 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1120 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1121 memcpy(ptr
+ 8,MAC
, 4);
1124 for (i
= 0; i
<= endblock
- startblock
;i
++){
1125 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1126 printf("Block |%02x|",i
+ startblock
);
1127 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]);
1128 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1132 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1134 PrintAndLog("Command execute timeout");
1140 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) {
1141 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1142 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1145 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1148 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1149 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1150 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
))
1155 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1156 clearCommandBuffer();
1158 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1160 PrintAndLog("Command execute timeout");
1163 uint8_t isOK
= resp
.arg
[0] & 0xff;
1165 PrintAndLog("Read Block Failed");
1168 //data read is stored in: resp.d.asBytes[0-15]
1169 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1173 int usage_hf_iclass_readblock(void) {
1174 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1175 PrintAndLog("Options:");
1176 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1177 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1178 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1179 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1180 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1181 PrintAndLog("Samples:");
1182 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1183 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1184 PrintAndLog(" hf iclass readblk b 0A k 0");
1188 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1190 uint8_t keyType
= 0x88; //debit key
1191 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1193 uint8_t dataLen
= 0;
1194 char tempStr
[50] = {0};
1196 bool rawkey
= false;
1197 bool errors
= false;
1200 while(param_getchar(Cmd
, cmdp
) != 0x00)
1202 switch(param_getchar(Cmd
, cmdp
))
1206 return usage_hf_iclass_readblock();
1209 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1210 PrintAndLog("Block No must include 2 HEX symbols\n");
1228 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1229 if (dataLen
== 16) {
1230 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1231 } else if (dataLen
== 1) {
1232 keyNbr
= param_get8(Cmd
, cmdp
+1);
1233 if (keyNbr
< ICLASS_KEYS_MAX
) {
1234 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1236 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1240 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1251 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1255 if(errors
) return usage_hf_iclass_readblock();
1258 if (cmdp
< 2) return usage_hf_iclass_readblock();
1260 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1261 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
);
1264 int CmdHFiClass_loclass(const char *Cmd
) {
1265 char opt
= param_getchar(Cmd
, 0);
1267 if (strlen(Cmd
)<1 || opt
== 'h') {
1268 PrintAndLog("Usage: hf iclass loclass [options]");
1269 PrintAndLog("Options:");
1270 PrintAndLog("h Show this help");
1271 PrintAndLog("t Perform self-test");
1272 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1273 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1274 PrintAndLog(" malicious CSNs, and their protocol responses");
1275 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1276 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1277 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1278 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1279 PrintAndLog(" ... totalling N*24 bytes");
1282 char fileName
[255] = {0};
1284 if(param_getstr(Cmd
, 1, fileName
, sizeof(fileName
)) > 0) {
1285 return bruteforceFileNoKeys(fileName
);
1287 PrintAndLog("You must specify a filename");
1289 } else if(opt
== 't') {
1290 int errors
= testCipherUtils();
1291 errors
+= testMAC();
1292 errors
+= doKeyTests(0);
1293 errors
+= testElite();
1295 prnlog("OBS! There were errors!!!");
1303 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1305 memcpy(&mem_config
, iclass_dump
+ 13,1);
1306 uint8_t maxmemcount
;
1307 uint8_t filemaxblock
= filesize
/ 8;
1308 if (mem_config
& 0x80)
1312 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1314 if (startblock
== 0)
1316 if ((endblock
> maxmemcount
) || (endblock
== 0))
1317 endblock
= maxmemcount
;
1319 // remember endblock need to relate to zero-index arrays.
1320 if (endblock
> filemaxblock
-1)
1321 endblock
= filemaxblock
;
1324 printf("------+--+-------------------------+\n");
1325 while (i
<= endblock
) {
1326 uint8_t *blk
= iclass_dump
+ (i
* 8);
1327 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );
1330 printf("------+--+-------------------------+\n");
1333 int usage_hf_iclass_readtagfile() {
1334 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1338 int CmdHFiClassReadTagFile(const char *Cmd
) {
1343 char filename
[FILE_PATH_SIZE
];
1344 if (param_getstr(Cmd
, 0, filename
, sizeof(filename
)) < 1)
1345 return usage_hf_iclass_readtagfile();
1346 if (param_getstr(Cmd
, 1, tempnum
, sizeof(tempnum
)) < 1)
1349 sscanf(tempnum
,"%d",&startblock
);
1351 if (param_getstr(Cmd
,2, tempnum
, sizeof(tempnum
)) < 1)
1354 sscanf(tempnum
,"%d",&endblock
);
1355 // file handling and reading
1356 f
= fopen(filename
,"rb");
1358 PrintAndLog("Failed to read from file '%s'", filename
);
1361 fseek(f
, 0, SEEK_END
);
1362 long fsize
= ftell(f
);
1363 fseek(f
, 0, SEEK_SET
);
1366 PrintAndLog("Error, when getting filesize");
1371 uint8_t *dump
= malloc(fsize
);
1373 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1375 uint8_t *csn
= dump
;
1376 printf("------+--+-------------------------+\n");
1377 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1378 // printIclassDumpInfo(dump);
1379 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1385 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1386 uint64_t new_div = 0x00;
1392 uint64_t hexarray_to_uint64(uint8_t *key) {
1395 for (int i = 0;i < 8;i++)
1396 sprintf(&temp[(i *2)],"%02X",key[i]);
1398 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1403 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1404 uint8_t keytable
[128] = {0};
1405 uint8_t key_index
[8] = {0};
1407 uint8_t key_sel
[8] = { 0 };
1408 uint8_t key_sel_p
[8] = { 0 };
1409 hash2(KEY
, keytable
);
1410 hash1(CSN
, key_index
);
1411 for(uint8_t i
= 0; i
< 8 ; i
++)
1412 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1414 //Permute from iclass format to standard format
1415 permutekey_rev(key_sel
, key_sel_p
);
1416 diversifyKey(CSN
, key_sel_p
, div_key
);
1418 diversifyKey(CSN
, KEY
, div_key
);
1422 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1423 //calculate and return xor_div_key (ready for a key write command)
1424 //print all div_keys if verbose
1425 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1426 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1427 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1429 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1431 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1433 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1434 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1437 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1438 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1439 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1443 int usage_hf_iclass_calc_newkey(void) {
1444 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1445 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1446 PrintAndLog(" Options:");
1447 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1448 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1449 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1450 PrintAndLog(" e : specify new key as elite calc");
1451 PrintAndLog(" ee : specify old and new key as elite calc");
1452 PrintAndLog("Samples:");
1453 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1454 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1455 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1456 PrintAndLog("NOTE: * = required\n");
1461 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1462 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1463 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1464 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1465 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1466 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1468 uint8_t dataLen
= 0;
1469 char tempStr
[50] = {0};
1470 bool givenCSN
= false;
1471 bool oldElite
= false;
1473 bool errors
= false;
1475 while(param_getchar(Cmd
, cmdp
) != 0x00)
1477 switch(param_getchar(Cmd
, cmdp
))
1481 return usage_hf_iclass_calc_newkey();
1484 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
, sizeof(tempStr
));
1492 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1493 if (dataLen
== 16) {
1494 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1495 } else if (dataLen
== 1) {
1496 keyNbr
= param_get8(Cmd
, cmdp
+1);
1497 if (keyNbr
< ICLASS_KEYS_MAX
) {
1498 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1500 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1504 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1511 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1512 if (dataLen
== 16) {
1513 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1514 } else if (dataLen
== 1) {
1515 keyNbr
= param_get8(Cmd
, cmdp
+1);
1516 if (keyNbr
< ICLASS_KEYS_MAX
) {
1517 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1519 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1523 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1531 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1532 return usage_hf_iclass_calc_newkey();
1536 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1540 if(errors
) return usage_hf_iclass_calc_newkey();
1543 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1546 if (!select_only(CSN
, CCNR
, false, true))
1549 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1553 static int loadKeys(char *filename
) {
1555 f
= fopen(filename
,"rb");
1557 PrintAndLog("Failed to read from file '%s'", filename
);
1560 fseek(f
, 0, SEEK_END
);
1561 long fsize
= ftell(f
);
1562 fseek(f
, 0, SEEK_SET
);
1565 PrintAndLog("Error, when getting filesize");
1570 uint8_t *dump
= malloc(fsize
);
1572 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1574 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1575 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1580 for (; i
< bytes_read
/8; i
++){
1581 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1584 PrintAndLog("%u keys loaded", i
);
1588 static int saveKeys(char *filename
) {
1590 f
= fopen(filename
,"wb");
1592 printf("error opening file %s\n",filename
);
1595 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1596 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1597 PrintAndLog("save key failed to write to file: %s", filename
);
1605 static int printKeys(void) {
1607 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1608 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1614 int usage_hf_iclass_managekeys(void) {
1615 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1616 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1617 PrintAndLog(" Options:");
1618 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1619 PrintAndLog(" k <key> : set a key in memory");
1620 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1621 PrintAndLog(" s : save keys in memory to file specified by filename");
1622 PrintAndLog(" l : load keys to memory from file specified by filename");
1623 PrintAndLog(" p : print keys loaded into memory\n");
1624 PrintAndLog("Samples:");
1625 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1626 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1627 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1628 PrintAndLog(" print keys : hf iclass managekeys p\n");
1632 int CmdHFiClassManageKeys(const char *Cmd
) {
1634 uint8_t dataLen
= 0;
1635 uint8_t KEY
[8] = {0};
1636 char filename
[FILE_PATH_SIZE
];
1637 uint8_t fileNameLen
= 0;
1638 bool errors
= false;
1639 uint8_t operation
= 0;
1643 while(param_getchar(Cmd
, cmdp
) != 0x00)
1645 switch(param_getchar(Cmd
, cmdp
))
1649 return usage_hf_iclass_managekeys();
1652 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1653 if (fileNameLen
< 1) {
1654 PrintAndLog("No filename found after f");
1661 keyNbr
= param_get8(Cmd
, cmdp
+1);
1662 if (keyNbr
>= ICLASS_KEYS_MAX
) {
1663 PrintAndLog("Invalid block number");
1670 operation
+= 3; //set key
1671 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1672 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1673 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1675 PrintAndLog("\nERROR: Key is incorrect length\n");
1682 operation
+= 4; //print keys in memory
1687 operation
+= 5; //load keys from file
1692 operation
+= 6; //save keys to file
1696 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1700 if(errors
) return usage_hf_iclass_managekeys();
1702 if (operation
== 0){
1703 PrintAndLog("no operation specified (load, save, or print)\n");
1704 return usage_hf_iclass_managekeys();
1707 PrintAndLog("Too many operations specified\n");
1708 return usage_hf_iclass_managekeys();
1710 if (operation
> 4 && fileNameLen
== 0){
1711 PrintAndLog("You must enter a filename when loading or saving\n");
1712 return usage_hf_iclass_managekeys();
1716 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1717 case 4: return printKeys();
1718 case 5: return loadKeys(filename
);
1719 case 6: return saveKeys(filename
);
1725 int CmdHFiClassCheckKeys(const char *Cmd
) {
1727 uint8_t mac
[4] = {0x00,0x00,0x00,0x00};
1728 uint8_t key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1729 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1731 // elite key, raw key, standard key
1732 bool use_elite
= false;
1733 bool use_raw
= false;
1734 bool found_debit
= false;
1735 bool found_credit
= false;
1736 bool errors
= false;
1737 uint8_t cmdp
= 0x00;
1739 char filename
[FILE_PATH_SIZE
] = {0};
1740 uint8_t fileNameLen
= 0;
1742 uint8_t *keyBlock
= NULL
, *p
;
1743 int keyitems
= 0, keycnt
= 0;
1745 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
1746 switch (param_getchar(Cmd
, cmdp
)) {
1749 return usage_hf_iclass_chk();
1752 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1753 if (fileNameLen
< 1) {
1754 PrintAndLog("No filename found after f");
1770 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1775 if (errors
) return usage_hf_iclass_chk();
1777 if ( !(f
= fopen( filename
, "r")) ) {
1778 PrintAndLog("File: %s: not found or locked.", filename
);
1782 while( fgets(buf
, sizeof(buf
), f
) ){
1783 if (strlen(buf
) < 16 || buf
[15] == '\n')
1786 while (fgetc(f
) != '\n' && !feof(f
)) ; //goto next line
1788 if( buf
[0]=='#' ) continue; //The line start with # is comment, skip
1790 if (!isxdigit(buf
[0])){
1791 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf
);
1797 p
= realloc(keyBlock
, 8 * (keyitems
+= 64));
1799 PrintAndLog("Cannot allocate memory for default keys");
1806 memset(keyBlock
+ 8 * keycnt
, 0, 8);
1807 num_to_bytes(strtoull(buf
, NULL
, 16), 8, keyBlock
+ 8 * keycnt
);
1809 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1811 memset(buf
, 0, sizeof(buf
));
1814 PrintAndLog("Loaded %2d keys from %s", keycnt
, filename
);
1817 uint64_t t1
= msclock();
1819 for (uint32_t c
= 0; c
< keycnt
; c
+= 1) {
1820 printf("."); fflush(stdout
);
1822 int gc
= getchar(); (void)gc
;
1823 printf("\naborted via keyboard!\n");
1827 memcpy(key
, keyBlock
+ 8 * c
, 8);
1829 // debit key. try twice
1830 for (int foo
= 0; foo
< 2 && !found_debit
; foo
++) {
1831 if (!select_and_auth(key
, mac
, div_key
, false, use_elite
, use_raw
, false))
1835 PrintAndLog("\n--------------------------------------------------------");
1836 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key
, 8));
1840 // credit key. try twice
1841 for (int foo
= 0; foo
< 2 && !found_credit
; foo
++) {
1842 if (!select_and_auth(key
, mac
, div_key
, true, use_elite
, use_raw
, false))
1846 PrintAndLog("\n--------------------------------------------------------");
1847 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key
, 8));
1848 found_credit
= true;
1852 if ( found_debit
&& found_credit
)
1856 t1
= msclock() - t1
;
1858 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1
/1000.0);
1866 static command_t CommandTable
[] =
1868 {"help", CmdHelp
, 1, "This help"},
1869 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1870 {"chk", CmdHFiClassCheckKeys
, 0, " Check keys"},
1871 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1872 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1873 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1874 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1875 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1876 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1877 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1878 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1879 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1880 {"reader", CmdHFiClassReader
, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1881 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1882 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1883 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1884 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1885 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1886 {NULL
, NULL
, 0, NULL
}
1889 int CmdHFiClass(const char *Cmd
)
1891 clearCommandBuffer();
1892 CmdsParse(CommandTable
, Cmd
);
1896 int CmdHelp(const char *Cmd
)
1898 CmdsHelp(CommandTable
);