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};
147 if (strlen(Cmd
) < 1) {
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 if (simType
== ICLASS_SIM_MODE_READER_ATTACK
) {
161 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
, NUM_CSNS
}};
162 UsbCommand resp
= {0};
164 memcpy(c
.d
.asBytes
, csns
, 8 * NUM_CSNS
);
167 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
168 PrintAndLog("Command timed out");
172 uint8_t num_mac_responses
= resp
.arg
[1];
173 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
, NUM_CSNS
);
175 size_t datalen
= NUM_CSNS
* 24;
177 * Now, time to dump to file. We'll use this format:
178 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
179 * So, it should wind up as
182 * The returndata from the pm3 is on the following format
183 * <8 byte CC><4 byte NR><4 byte MAC>
184 * CSN is the same as was sent in
186 void* dump
= malloc(datalen
);
187 for(int i
= 0; i
< NUM_CSNS
; i
++) {
188 memcpy(dump
+ i
*24, csns
+i
*8, 8); //CSN
189 //copy CC from response
190 memcpy(dump
+ i
*24 + 8, resp
.d
.asBytes
+ i
*16, 8);
191 //Then comes NR_MAC (eight bytes from the response)
192 memcpy(dump
+ i
*24 + 16, resp
.d
.asBytes
+ i
*16 + 8, 8);
194 /** Now, save to dumpfile **/
195 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
198 } else if (simType
== ICLASS_SIM_MODE_CSN
|| simType
== ICLASS_SIM_MODE_CSN_DEFAULT
|| simType
== ICLASS_SIM_MODE_FULL
) {
199 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
, 0}};
200 memcpy(c
.d
.asBytes
, CSN
, 8);
204 PrintAndLog("Undefined simtype %d", simType
);
205 return usage_hf_iclass_sim();
211 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
212 bool tagFound
= false;
213 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
214 FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_AA
|
215 FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
} };
216 // loop in client not device - else on windows have a communication error
220 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
221 uint8_t readStatus
= resp
.arg
[0] & 0xff;
222 uint8_t *data
= resp
.d
.asBytes
;
224 // no tag found or button pressed
225 if( (readStatus
== 0 && !loop
) || readStatus
== 0xFF) {
227 if (verbose
) PrintAndLog("Quitting...");
231 if( readStatus
& FLAG_ICLASS_READER_CSN
) {
232 PrintAndLog(" CSN: %s",sprint_hex(data
,8));
235 if( readStatus
& FLAG_ICLASS_READER_CC
) {
236 PrintAndLog(" CC: %s",sprint_hex(data
+16,8));
238 if( readStatus
& FLAG_ICLASS_READER_CONF
) {
239 printIclassDumpInfo(data
);
241 if (readStatus
& FLAG_ICLASS_READER_AA
) {
243 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*5,8));
244 for (int i
= 0; i
<8; i
++) {
245 if (data
[8*5+i
] != 0xFF) {
249 PrintAndLog(" : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)");
252 if (tagFound
&& !loop
) return 1;
254 if (verbose
) PrintAndLog("Command execute timeout");
261 int CmdHFiClassReader(const char *Cmd
) {
262 return HFiClassReader(Cmd
, true, true);
265 int CmdHFiClassReader_Replay(const char *Cmd
) {
266 uint8_t readerType
= 0;
267 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
270 PrintAndLog("Usage: hf iclass replay <MAC>");
271 PrintAndLog(" sample: hf iclass replay 00112233");
275 if (param_gethex(Cmd
, 0, MAC
, 8)) {
276 PrintAndLog("MAC must include 8 HEX symbols");
280 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
281 memcpy(c
.d
.asBytes
, MAC
, 4);
287 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
288 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
289 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
294 int hf_iclass_eload_usage(void) {
295 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
296 PrintAndLog("Usage: hf iclass eload f <filename>");
298 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
302 int CmdHFiClassELoad(const char *Cmd
) {
304 char opt
= param_getchar(Cmd
, 0);
305 if (strlen(Cmd
)<1 || opt
== 'h')
306 return hf_iclass_eload_usage();
308 //File handling and reading
310 char filename
[FILE_PATH_SIZE
];
311 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0)
313 f
= fopen(filename
, "rb");
315 return hf_iclass_eload_usage();
319 PrintAndLog("Failed to read from file '%s'", filename
);
323 fseek(f
, 0, SEEK_END
);
324 long fsize
= ftell(f
);
325 fseek(f
, 0, SEEK_SET
);
328 PrintAndLog("Error, when getting filesize");
333 uint8_t *dump
= malloc(fsize
);
335 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
338 printIclassDumpInfo(dump
);
341 if (bytes_read
< fsize
)
343 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
348 uint32_t bytes_sent
= 0;
349 uint32_t bytes_remaining
= bytes_read
;
351 while(bytes_remaining
> 0){
352 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
353 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
354 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
356 bytes_remaining
-= bytes_in_packet
;
357 bytes_sent
+= bytes_in_packet
;
360 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
364 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
365 FILE *f
= fopen(filename
, "rb");
367 PrintAndLog("Failed to read from file '%s'", filename
);
370 fseek(f
, 0, SEEK_END
);
371 long fsize
= ftell(f
);
372 fseek(f
, 0, SEEK_SET
);
373 size_t bytes_read
= fread(buffer
, 1, len
, f
);
377 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
380 if(bytes_read
!= len
)
382 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
388 int usage_hf_iclass_decrypt(void) {
389 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
391 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
392 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
394 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
396 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
397 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
398 PrintAndLog("which is defined by the configuration block.");
402 int CmdHFiClassDecrypt(const char *Cmd
) {
403 uint8_t key
[16] = { 0 };
404 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
406 usage_hf_iclass_decrypt();
409 PrintAndLog("Decryption file found... ");
410 char opt
= param_getchar(Cmd
, 0);
411 if (strlen(Cmd
)<1 || opt
== 'h')
412 return usage_hf_iclass_decrypt();
414 //Open the tagdump-file
416 char filename
[FILE_PATH_SIZE
];
417 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) {
418 f
= fopen(filename
, "rb");
420 PrintAndLog("Could not find file %s", filename
);
424 return usage_hf_iclass_decrypt();
427 fseek(f
, 0, SEEK_END
);
428 long fsize
= ftell(f
);
429 fseek(f
, 0, SEEK_SET
);
430 uint8_t enc_dump
[8] = {0};
431 uint8_t *decrypted
= malloc(fsize
);
432 mbedtls_des3_context ctx
= { {0} };
433 mbedtls_des3_set2key_dec( &ctx
, key
);
434 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
436 //Use the first block (CSN) for filename
437 char outfilename
[FILE_PATH_SIZE
] = { 0 };
438 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
439 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
440 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
443 while(bytes_read
== 8)
447 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
449 mbedtls_des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
451 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
452 bytes_read
= fread(enc_dump
, 1, 8, f
);
457 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
462 int usage_hf_iclass_encrypt(void) {
463 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
465 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
466 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
468 PrintAndLog("example: hf iclass encrypt 0102030405060708");
473 static int iClassEncryptBlkData(uint8_t *blkData
) {
474 uint8_t key
[16] = { 0 };
475 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
477 usage_hf_iclass_encrypt();
480 PrintAndLog("Decryption file found... ");
482 uint8_t encryptedData
[16];
483 uint8_t *encrypted
= encryptedData
;
484 mbedtls_des3_context ctx
= { {0} };
485 mbedtls_des3_set2key_enc( &ctx
, key
);
487 mbedtls_des3_crypt_ecb(&ctx
, blkData
,encrypted
);
488 //printvar("decrypted block", decrypted, 8);
489 memcpy(blkData
,encrypted
,8);
494 int CmdHFiClassEncryptBlk(const char *Cmd
) {
495 uint8_t blkData
[8] = {0};
496 char opt
= param_getchar(Cmd
, 0);
497 if (strlen(Cmd
)<1 || opt
== 'h')
498 return usage_hf_iclass_encrypt();
500 //get the bytes to encrypt
501 if (param_gethex(Cmd
, 0, blkData
, 16))
503 PrintAndLog("BlockData must include 16 HEX symbols");
506 if (!iClassEncryptBlkData(blkData
)) return 0;
508 printvar("encrypted block", blkData
, 8);
512 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
515 memcpy(WB
+ 1,data
,8);
516 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
517 //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]);
520 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
523 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
524 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
526 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
528 clearCommandBuffer();
530 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
532 PrintAndLog("Command execute timeout");
536 uint8_t isOK
= resp
.arg
[0] & 0xff;
537 uint8_t *data
= resp
.d
.asBytes
;
540 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
543 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
546 PrintAndLog("Failed to obtain CC! Aborting");
552 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
) {
553 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
554 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
556 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
561 memcpy(div_key
, KEY
, 8);
563 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
564 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]);
566 doMAC(CCNR
, div_key
, MAC
);
568 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
569 memcpy(d
.d
.asBytes
, MAC
, 4);
570 clearCommandBuffer();
572 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
574 if (verbose
) PrintAndLog("Auth Command execute timeout");
577 uint8_t isOK
= resp
.arg
[0] & 0xff;
579 if (verbose
) PrintAndLog("Authentication error");
585 int usage_hf_iclass_dump(void) {
586 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
587 PrintAndLog("Options:");
588 PrintAndLog(" f <filename> : specify a filename to save dump to");
589 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
590 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
591 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
592 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
593 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
594 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
595 PrintAndLog(" NOTE: * = required");
596 PrintAndLog("Samples:");
597 PrintAndLog(" hf iclass dump k 001122334455667B");
598 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
599 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
603 int CmdHFiClassReader_Dump(const char *Cmd
) {
605 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
606 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
607 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
611 uint8_t app_areas
= 1;
613 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
614 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
617 uint8_t fileNameLen
= 0;
618 char filename
[FILE_PATH_SIZE
]={0};
619 char tempStr
[50] = {0};
620 bool have_debit_key
= false;
621 bool have_credit_key
= false;
622 bool use_credit_key
= false;
628 while(param_getchar(Cmd
, cmdp
) != 0x00)
630 switch(param_getchar(Cmd
, cmdp
))
634 return usage_hf_iclass_dump();
637 have_credit_key
= true;
638 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
640 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
641 } else if (dataLen
== 1) {
642 keyNbr
= param_get8(Cmd
, cmdp
+1);
643 if (keyNbr
< ICLASS_KEYS_MAX
) {
644 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
646 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
650 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
662 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
663 if (fileNameLen
< 1) {
664 PrintAndLog("No filename found after f");
671 have_debit_key
= true;
672 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
674 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
675 } else if (dataLen
== 1) {
676 keyNbr
= param_get8(Cmd
, cmdp
+1);
677 if (keyNbr
< ICLASS_KEYS_MAX
) {
678 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
680 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
684 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
695 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
699 if(errors
) return usage_hf_iclass_dump();
702 if (cmdp
< 2) return usage_hf_iclass_dump();
703 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
704 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
706 //get config and first 3 blocks
707 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
708 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
710 uint8_t tag_data
[255*8];
712 clearCommandBuffer();
714 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
715 PrintAndLog("Command execute timeout");
719 uint8_t readStatus
= resp
.arg
[0] & 0xff;
720 uint8_t *data
= resp
.d
.asBytes
;
723 PrintAndLog("No tag found...");
727 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
728 memcpy(tag_data
, data
, 8*3);
729 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
731 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
732 // large memory - not able to dump pages currently
733 if (numblks
> maxBlk
) numblks
= maxBlk
;
736 // authenticate debit key and get div_key - later store in dump block 3
737 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
738 //try twice - for some reason it sometimes fails the first time...
739 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
746 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
747 clearCommandBuffer();
749 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
750 PrintAndLog("Command execute time-out 1");
754 uint32_t blocksRead
= resp
.arg
[1];
755 uint8_t isOK
= resp
.arg
[0] & 0xff;
756 if (!isOK
&& !blocksRead
) {
757 PrintAndLog("Read Block Failed");
761 uint32_t startindex
= resp
.arg
[2];
762 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
763 PrintAndLog("Data exceeded Buffer size!");
764 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
766 // response ok - now get bigbuf content of the dump
767 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
, NULL
, -1, false);
768 size_t gotBytes
= blocksRead
*8 + blockno
*8;
771 if (have_credit_key
) {
772 //turn off hf field before authenticating with different key
775 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
776 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
777 //try twice - for some reason it sometimes fails the first time...
778 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
783 // do we still need to read more block? (aa2 enabled?)
784 if (maxBlk
> blockno
+numblks
+1) {
785 // setup dump and start
786 w
.arg
[0] = blockno
+ blocksRead
;
787 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
788 clearCommandBuffer();
790 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
791 PrintAndLog("Command execute timeout 2");
795 uint8_t isOK
= resp
.arg
[0] & 0xff;
796 blocksRead
= resp
.arg
[1];
797 if (!isOK
&& !blocksRead
) {
798 PrintAndLog("Read Block Failed 2");
803 startindex
= resp
.arg
[2];
804 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
805 PrintAndLog("Data exceeded Buffer size!");
806 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
808 // get dumped data from bigbuf
809 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
, NULL
, -1, false);
811 gotBytes
+= blocksRead
*8;
812 } else { //field is still on - turn it off...
817 // add diversified keys to dump
818 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
819 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
821 printf("------+--+-------------------------+\n");
822 printf("CSN |00| %s|\n",sprint_hex(tag_data
, 8));
823 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
825 if (filename
[0] == 0){
826 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
827 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
828 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
831 // save the dump to .bin file
832 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
833 saveFile(filename
, "bin", tag_data
, gotBytes
);
837 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
838 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
839 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
840 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
845 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
846 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
847 memcpy(w
.d
.asBytes
, bldata
, 8);
848 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
850 clearCommandBuffer();
852 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
854 PrintAndLog("Write Command execute timeout");
857 uint8_t isOK
= resp
.arg
[0] & 0xff;
859 PrintAndLog("Write Block Failed");
862 PrintAndLog("Write Block Successful");
866 int usage_hf_iclass_writeblock(void) {
867 PrintAndLog("Options:");
868 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
869 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
870 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
871 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
872 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
873 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
874 PrintAndLog("Samples:");
875 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
876 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
877 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
881 int CmdHFiClass_WriteBlock(const char *Cmd
) {
883 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
884 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
887 char tempStr
[50] = {0};
888 bool use_credit_key
= false;
893 while(param_getchar(Cmd
, cmdp
) != 0x00)
895 switch(param_getchar(Cmd
, cmdp
))
899 return usage_hf_iclass_writeblock();
902 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
903 PrintAndLog("Block No must include 2 HEX symbols\n");
910 use_credit_key
= true;
915 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
917 PrintAndLog("KEY must include 16 HEX symbols\n");
929 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
931 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
932 } else if (dataLen
== 1) {
933 keyNbr
= param_get8(Cmd
, cmdp
+1);
934 if (keyNbr
< ICLASS_KEYS_MAX
) {
935 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
937 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
941 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
952 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
956 if(errors
) return usage_hf_iclass_writeblock();
959 if (cmdp
< 6) return usage_hf_iclass_writeblock();
960 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
965 int usage_hf_iclass_clone(void) {
966 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
967 PrintAndLog("Options:");
968 PrintAndLog(" f <filename>: specify a filename to clone from");
969 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
970 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
971 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
972 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
973 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
974 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
975 PrintAndLog("Samples:");
976 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
977 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
978 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
982 int CmdHFiClassCloneTag(const char *Cmd
) {
983 char filename
[FILE_PATH_SIZE
] = {0};
984 char tempStr
[50]={0};
985 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
987 uint8_t fileNameLen
= 0;
988 uint8_t startblock
= 0;
989 uint8_t endblock
= 0;
991 bool use_credit_key
= false;
996 while(param_getchar(Cmd
, cmdp
) != 0x00)
998 switch(param_getchar(Cmd
, cmdp
))
1002 return usage_hf_iclass_clone();
1005 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
1006 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1013 use_credit_key
= true;
1023 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1024 if (fileNameLen
< 1) {
1025 PrintAndLog("No filename found after f");
1032 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1033 if (dataLen
== 16) {
1034 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1035 } else if (dataLen
== 1) {
1036 keyNbr
= param_get8(Cmd
, cmdp
+1);
1037 if (keyNbr
< ICLASS_KEYS_MAX
) {
1038 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1040 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1044 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1051 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1052 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1063 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1067 if(errors
) return usage_hf_iclass_clone();
1070 if (cmdp
< 8) return usage_hf_iclass_clone();
1074 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1076 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1077 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1079 // file handling and reading
1080 f
= fopen(filename
,"rb");
1082 PrintAndLog("Failed to read from file '%s'", filename
);
1087 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1091 // now read data from the file from block 6 --- 19
1092 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1093 // 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,
1094 // else we have to create a share memory
1096 fseek(f
,startblock
*8,SEEK_SET
);
1097 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1098 PrintAndLog("File reading error.");
1103 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1104 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1106 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1109 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1111 // calculate all mac for every the block we will write
1112 for (i
= startblock
; i
<= endblock
; i
++){
1113 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1114 // usb command d start pointer = d + (i - 6) * 12
1115 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1116 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1118 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1119 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1120 memcpy(ptr
+ 8,MAC
, 4);
1123 for (i
= 0; i
<= endblock
- startblock
;i
++){
1124 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1125 printf("Block |%02x|",i
+ startblock
);
1126 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]);
1127 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1131 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1133 PrintAndLog("Command execute timeout");
1139 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) {
1140 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1141 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1144 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1147 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1148 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1149 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
))
1154 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1155 clearCommandBuffer();
1157 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1159 PrintAndLog("Command execute timeout");
1162 uint8_t isOK
= resp
.arg
[0] & 0xff;
1164 PrintAndLog("Read Block Failed");
1167 //data read is stored in: resp.d.asBytes[0-15]
1168 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1172 int usage_hf_iclass_readblock(void) {
1173 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1174 PrintAndLog("Options:");
1175 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1176 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1177 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1178 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1179 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1180 PrintAndLog("Samples:");
1181 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1182 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1183 PrintAndLog(" hf iclass readblk b 0A k 0");
1187 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1189 uint8_t keyType
= 0x88; //debit key
1190 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1192 uint8_t dataLen
= 0;
1193 char tempStr
[50] = {0};
1195 bool rawkey
= false;
1196 bool errors
= false;
1199 while(param_getchar(Cmd
, cmdp
) != 0x00)
1201 switch(param_getchar(Cmd
, cmdp
))
1205 return usage_hf_iclass_readblock();
1208 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1209 PrintAndLog("Block No must include 2 HEX symbols\n");
1227 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1228 if (dataLen
== 16) {
1229 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1230 } else if (dataLen
== 1) {
1231 keyNbr
= param_get8(Cmd
, cmdp
+1);
1232 if (keyNbr
< ICLASS_KEYS_MAX
) {
1233 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1235 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1239 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1250 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1254 if(errors
) return usage_hf_iclass_readblock();
1257 if (cmdp
< 2) return usage_hf_iclass_readblock();
1259 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1260 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
);
1263 int CmdHFiClass_loclass(const char *Cmd
) {
1264 char opt
= param_getchar(Cmd
, 0);
1266 if (strlen(Cmd
)<1 || opt
== 'h') {
1267 PrintAndLog("Usage: hf iclass loclass [options]");
1268 PrintAndLog("Options:");
1269 PrintAndLog("h Show this help");
1270 PrintAndLog("t Perform self-test");
1271 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1272 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1273 PrintAndLog(" malicious CSNs, and their protocol responses");
1274 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1275 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
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(" ... totalling N*24 bytes");
1281 char fileName
[255] = {0};
1283 if(param_getstr(Cmd
, 1, fileName
, sizeof(fileName
)) > 0) {
1284 return bruteforceFileNoKeys(fileName
);
1286 PrintAndLog("You must specify a filename");
1288 } else if(opt
== 't') {
1289 int errors
= testCipherUtils();
1290 errors
+= testMAC();
1291 errors
+= doKeyTests(0);
1292 errors
+= testElite();
1294 prnlog("OBS! There were errors!!!");
1302 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1304 memcpy(&mem_config
, iclass_dump
+ 13,1);
1305 uint8_t maxmemcount
;
1306 uint8_t filemaxblock
= filesize
/ 8;
1307 if (mem_config
& 0x80)
1311 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1313 if (startblock
== 0)
1315 if ((endblock
> maxmemcount
) || (endblock
== 0))
1316 endblock
= maxmemcount
;
1318 // remember endblock need to relate to zero-index arrays.
1319 if (endblock
> filemaxblock
-1)
1320 endblock
= filemaxblock
;
1323 printf("------+--+-------------------------+\n");
1324 while (i
<= endblock
) {
1325 uint8_t *blk
= iclass_dump
+ (i
* 8);
1326 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );
1329 printf("------+--+-------------------------+\n");
1332 int usage_hf_iclass_readtagfile() {
1333 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1337 int CmdHFiClassReadTagFile(const char *Cmd
) {
1342 char filename
[FILE_PATH_SIZE
];
1343 if (param_getstr(Cmd
, 0, filename
, sizeof(filename
)) < 1)
1344 return usage_hf_iclass_readtagfile();
1345 if (param_getstr(Cmd
, 1, tempnum
, sizeof(tempnum
)) < 1)
1348 sscanf(tempnum
,"%d",&startblock
);
1350 if (param_getstr(Cmd
,2, tempnum
, sizeof(tempnum
)) < 1)
1353 sscanf(tempnum
,"%d",&endblock
);
1354 // file handling and reading
1355 f
= fopen(filename
,"rb");
1357 PrintAndLog("Failed to read from file '%s'", filename
);
1360 fseek(f
, 0, SEEK_END
);
1361 long fsize
= ftell(f
);
1362 fseek(f
, 0, SEEK_SET
);
1365 PrintAndLog("Error, when getting filesize");
1370 uint8_t *dump
= malloc(fsize
);
1372 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1374 uint8_t *csn
= dump
;
1375 printf("------+--+-------------------------+\n");
1376 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1377 // printIclassDumpInfo(dump);
1378 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1384 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1385 uint64_t new_div = 0x00;
1391 uint64_t hexarray_to_uint64(uint8_t *key) {
1394 for (int i = 0;i < 8;i++)
1395 sprintf(&temp[(i *2)],"%02X",key[i]);
1397 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1402 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1403 uint8_t keytable
[128] = {0};
1404 uint8_t key_index
[8] = {0};
1406 uint8_t key_sel
[8] = { 0 };
1407 uint8_t key_sel_p
[8] = { 0 };
1408 hash2(KEY
, keytable
);
1409 hash1(CSN
, key_index
);
1410 for(uint8_t i
= 0; i
< 8 ; i
++)
1411 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1413 //Permute from iclass format to standard format
1414 permutekey_rev(key_sel
, key_sel_p
);
1415 diversifyKey(CSN
, key_sel_p
, div_key
);
1417 diversifyKey(CSN
, KEY
, div_key
);
1421 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1422 //calculate and return xor_div_key (ready for a key write command)
1423 //print all div_keys if verbose
1424 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1425 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1426 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1428 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1430 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1432 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1433 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1436 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1437 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1438 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1442 int usage_hf_iclass_calc_newkey(void) {
1443 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1444 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1445 PrintAndLog(" Options:");
1446 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1447 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1448 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1449 PrintAndLog(" e : specify new key as elite calc");
1450 PrintAndLog(" ee : specify old and new key as elite calc");
1451 PrintAndLog("Samples:");
1452 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1453 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1454 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1455 PrintAndLog("NOTE: * = required\n");
1460 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1461 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1462 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1463 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1464 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1465 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1467 uint8_t dataLen
= 0;
1468 char tempStr
[50] = {0};
1469 bool givenCSN
= false;
1470 bool oldElite
= false;
1472 bool errors
= false;
1474 while(param_getchar(Cmd
, cmdp
) != 0x00)
1476 switch(param_getchar(Cmd
, cmdp
))
1480 return usage_hf_iclass_calc_newkey();
1483 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
, sizeof(tempStr
));
1491 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1492 if (dataLen
== 16) {
1493 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1494 } else if (dataLen
== 1) {
1495 keyNbr
= param_get8(Cmd
, cmdp
+1);
1496 if (keyNbr
< ICLASS_KEYS_MAX
) {
1497 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1499 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1503 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1510 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1511 if (dataLen
== 16) {
1512 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1513 } else if (dataLen
== 1) {
1514 keyNbr
= param_get8(Cmd
, cmdp
+1);
1515 if (keyNbr
< ICLASS_KEYS_MAX
) {
1516 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1518 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1522 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1530 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1531 return usage_hf_iclass_calc_newkey();
1535 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1539 if(errors
) return usage_hf_iclass_calc_newkey();
1542 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1545 if (!select_only(CSN
, CCNR
, false, true))
1548 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1552 static int loadKeys(char *filename
) {
1554 f
= fopen(filename
,"rb");
1556 PrintAndLog("Failed to read from file '%s'", filename
);
1559 fseek(f
, 0, SEEK_END
);
1560 long fsize
= ftell(f
);
1561 fseek(f
, 0, SEEK_SET
);
1564 PrintAndLog("Error, when getting filesize");
1569 uint8_t *dump
= malloc(fsize
);
1571 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1573 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1574 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1579 for (; i
< bytes_read
/8; i
++){
1580 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1583 PrintAndLog("%u keys loaded", i
);
1587 static int saveKeys(char *filename
) {
1589 f
= fopen(filename
,"wb");
1591 printf("error opening file %s\n",filename
);
1594 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1595 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1596 PrintAndLog("save key failed to write to file: %s", filename
);
1604 static int printKeys(void) {
1606 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1607 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1613 int usage_hf_iclass_managekeys(void) {
1614 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1615 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1616 PrintAndLog(" Options:");
1617 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1618 PrintAndLog(" k <key> : set a key in memory");
1619 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1620 PrintAndLog(" s : save keys in memory to file specified by filename");
1621 PrintAndLog(" l : load keys to memory from file specified by filename");
1622 PrintAndLog(" p : print keys loaded into memory\n");
1623 PrintAndLog("Samples:");
1624 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1625 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1626 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1627 PrintAndLog(" print keys : hf iclass managekeys p\n");
1631 int CmdHFiClassManageKeys(const char *Cmd
) {
1633 uint8_t dataLen
= 0;
1634 uint8_t KEY
[8] = {0};
1635 char filename
[FILE_PATH_SIZE
];
1636 uint8_t fileNameLen
= 0;
1637 bool errors
= false;
1638 uint8_t operation
= 0;
1642 while(param_getchar(Cmd
, cmdp
) != 0x00)
1644 switch(param_getchar(Cmd
, cmdp
))
1648 return usage_hf_iclass_managekeys();
1651 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1652 if (fileNameLen
< 1) {
1653 PrintAndLog("No filename found after f");
1660 keyNbr
= param_get8(Cmd
, cmdp
+1);
1661 if (keyNbr
>= ICLASS_KEYS_MAX
) {
1662 PrintAndLog("Invalid block number");
1669 operation
+= 3; //set key
1670 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1671 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1672 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1674 PrintAndLog("\nERROR: Key is incorrect length\n");
1681 operation
+= 4; //print keys in memory
1686 operation
+= 5; //load keys from file
1691 operation
+= 6; //save keys to file
1695 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1699 if(errors
) return usage_hf_iclass_managekeys();
1701 if (operation
== 0){
1702 PrintAndLog("no operation specified (load, save, or print)\n");
1703 return usage_hf_iclass_managekeys();
1706 PrintAndLog("Too many operations specified\n");
1707 return usage_hf_iclass_managekeys();
1709 if (operation
> 4 && fileNameLen
== 0){
1710 PrintAndLog("You must enter a filename when loading or saving\n");
1711 return usage_hf_iclass_managekeys();
1715 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1716 case 4: return printKeys();
1717 case 5: return loadKeys(filename
);
1718 case 6: return saveKeys(filename
);
1724 int CmdHFiClassCheckKeys(const char *Cmd
) {
1726 uint8_t mac
[4] = {0x00,0x00,0x00,0x00};
1727 uint8_t key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1728 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1730 // elite key, raw key, standard key
1731 bool use_elite
= false;
1732 bool use_raw
= false;
1733 bool found_debit
= false;
1734 bool found_credit
= false;
1735 bool errors
= false;
1736 uint8_t cmdp
= 0x00;
1738 char filename
[FILE_PATH_SIZE
] = {0};
1739 uint8_t fileNameLen
= 0;
1741 uint8_t *keyBlock
= NULL
, *p
;
1742 int keyitems
= 0, keycnt
= 0;
1744 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
1745 switch (param_getchar(Cmd
, cmdp
)) {
1748 return usage_hf_iclass_chk();
1751 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1752 if (fileNameLen
< 1) {
1753 PrintAndLog("No filename found after f");
1769 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1774 if (errors
) return usage_hf_iclass_chk();
1776 if ( !(f
= fopen( filename
, "r")) ) {
1777 PrintAndLog("File: %s: not found or locked.", filename
);
1781 while( fgets(buf
, sizeof(buf
), f
) ){
1782 if (strlen(buf
) < 16 || buf
[15] == '\n')
1785 while (fgetc(f
) != '\n' && !feof(f
)) ; //goto next line
1787 if( buf
[0]=='#' ) continue; //The line start with # is comment, skip
1789 if (!isxdigit(buf
[0])){
1790 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf
);
1796 p
= realloc(keyBlock
, 8 * (keyitems
+= 64));
1798 PrintAndLog("Cannot allocate memory for default keys");
1805 memset(keyBlock
+ 8 * keycnt
, 0, 8);
1806 num_to_bytes(strtoull(buf
, NULL
, 16), 8, keyBlock
+ 8 * keycnt
);
1808 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1810 memset(buf
, 0, sizeof(buf
));
1813 PrintAndLog("Loaded %2d keys from %s", keycnt
, filename
);
1816 uint64_t t1
= msclock();
1818 for (uint32_t c
= 0; c
< keycnt
; c
+= 1) {
1819 printf("."); fflush(stdout
);
1821 int gc
= getchar(); (void)gc
;
1822 printf("\naborted via keyboard!\n");
1826 memcpy(key
, keyBlock
+ 8 * c
, 8);
1828 // debit key. try twice
1829 for (int foo
= 0; foo
< 2 && !found_debit
; foo
++) {
1830 if (!select_and_auth(key
, mac
, div_key
, false, use_elite
, use_raw
, false))
1834 PrintAndLog("\n--------------------------------------------------------");
1835 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key
, 8));
1839 // credit key. try twice
1840 for (int foo
= 0; foo
< 2 && !found_credit
; foo
++) {
1841 if (!select_and_auth(key
, mac
, div_key
, true, use_elite
, use_raw
, false))
1845 PrintAndLog("\n--------------------------------------------------------");
1846 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key
, 8));
1847 found_credit
= true;
1851 if ( found_debit
&& found_credit
)
1855 t1
= msclock() - t1
;
1857 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1
/1000.0);
1865 static command_t CommandTable
[] =
1867 {"help", CmdHelp
, 1, "This help"},
1868 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1869 {"chk", CmdHFiClassCheckKeys
, 0, " Check keys"},
1870 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1871 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1872 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1873 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1874 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1875 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1876 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1877 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1878 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1879 {"reader", CmdHFiClassReader
, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1880 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1881 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1882 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1883 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1884 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1885 {NULL
, NULL
, 0, NULL
}
1888 int CmdHFiClass(const char *Cmd
)
1890 clearCommandBuffer();
1891 CmdsParse(CommandTable
, Cmd
);
1895 int CmdHelp(const char *Cmd
)
1897 CmdsHelp(CommandTable
);