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"
37 static int CmdHelp(const char *Cmd
);
39 #define ICLASS_KEYS_MAX 8
40 static uint8_t iClass_Key_Table
[ICLASS_KEYS_MAX
][8] = {
41 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
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 }
51 typedef struct iclass_block
{
55 int usage_hf_iclass_chk(void) {
56 PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");
57 PrintAndLog("Usage: hf iclass chk [h|e|r] <f (*.dic)>");
58 PrintAndLog("Options:");
59 PrintAndLog("h Show this help");
60 PrintAndLog("f <filename> Dictionary file with default iclass keys");
61 PrintAndLog(" e target Elite / High security key scheme");
62 PrintAndLog(" r interpret dictionary file as raw (diversified keys)");
63 PrintAndLog("Samples:");
64 PrintAndLog(" hf iclass chk f default_iclass_keys.dic");
65 PrintAndLog(" hf iclass chk f default_iclass_keys.dic e");
69 int xorbits_8(uint8_t val
) {
70 uint8_t res
= val
^ (val
>> 1); //1st pass
71 res
= res
^ (res
>> 1); // 2nd pass
72 res
= res
^ (res
>> 2); // 3rd pass
73 res
= res
^ (res
>> 4); // 4th pass
77 int CmdHFiClassList(const char *Cmd
) {
78 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
82 int CmdHFiClassSnoop(const char *Cmd
) {
83 UsbCommand c
= {CMD_SNOOP_ICLASS
};
88 int usage_hf_iclass_sim(void) {
89 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
90 PrintAndLog(" options");
91 PrintAndLog(" 0 <CSN> simulate the given CSN");
92 PrintAndLog(" 1 simulate default CSN");
93 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
94 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
95 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
96 PrintAndLog(" example: hf iclass sim 2");
97 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
98 PrintAndLog(" hf iclass sim 3");
103 int CmdHFiClassSim(const char *Cmd
) {
105 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
108 return usage_hf_iclass_sim();
110 simType
= param_get8ex(Cmd
, 0, 0, 10);
114 if (param_gethex(Cmd
, 1, CSN
, 16)) {
115 PrintAndLog("A CSN should consist of 16 HEX symbols");
116 return usage_hf_iclass_sim();
119 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
123 PrintAndLog("Undefined simptype %d", simType
);
124 return usage_hf_iclass_sim();
127 uint8_t numberOfCSNs
=0;
130 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
131 UsbCommand resp
= {0};
133 uint8_t csns
[8*NUM_CSNS
] = {
134 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
135 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
136 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
137 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
138 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
139 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
140 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
141 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
142 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
143 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
144 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
145 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
146 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
147 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
148 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
150 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
153 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
154 PrintAndLog("Command timed out");
158 uint8_t num_mac_responses
= resp
.arg
[1];
159 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
161 size_t datalen
= NUM_CSNS
*24;
163 * Now, time to dump to file. We'll use this format:
164 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
165 * So, it should wind up as
168 * The returndata from the pm3 is on the following format
169 * <4 byte NR><4 byte MAC>
170 * CC are all zeroes, CSN is the same as was sent in
172 void* dump
= malloc(datalen
);
173 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
175 for(i
= 0 ; i
< NUM_CSNS
; i
++)
177 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
178 //8 zero bytes here...
179 //Then comes NR_MAC (eight bytes from the response)
180 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
183 /** Now, save to dumpfile **/
184 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
188 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
189 memcpy(c
.d
.asBytes
, CSN
, 8);
196 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
197 bool tagFound
= false;
198 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
199 FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_AA
|
200 FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
} };
201 // loop in client not device - else on windows have a communication error
205 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
206 uint8_t readStatus
= resp
.arg
[0] & 0xff;
207 uint8_t *data
= resp
.d
.asBytes
;
209 // no tag found or button pressed
210 if( (readStatus
== 0 && !loop
) || readStatus
== 0xFF) {
212 if (verbose
) PrintAndLog("Quitting...");
216 if( readStatus
& FLAG_ICLASS_READER_CSN
) {
217 PrintAndLog(" CSN: %s",sprint_hex(data
,8));
220 if( readStatus
& FLAG_ICLASS_READER_CC
) {
221 PrintAndLog(" CC: %s",sprint_hex(data
+16,8));
223 if( readStatus
& FLAG_ICLASS_READER_CONF
) {
224 printIclassDumpInfo(data
);
226 if (readStatus
& FLAG_ICLASS_READER_AA
) {
228 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*5,8));
229 for (int i
= 0; i
<8; i
++) {
230 if (data
[8*5+i
] != 0xFF) {
234 PrintAndLog(" : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)");
237 if (tagFound
&& !loop
) return 1;
239 if (verbose
) PrintAndLog("Command execute timeout");
246 int CmdHFiClassReader(const char *Cmd
) {
247 return HFiClassReader(Cmd
, true, true);
250 int CmdHFiClassReader_Replay(const char *Cmd
) {
251 uint8_t readerType
= 0;
252 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
255 PrintAndLog("Usage: hf iclass replay <MAC>");
256 PrintAndLog(" sample: hf iclass replay 00112233");
260 if (param_gethex(Cmd
, 0, MAC
, 8)) {
261 PrintAndLog("MAC must include 8 HEX symbols");
265 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
266 memcpy(c
.d
.asBytes
, MAC
, 4);
272 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
273 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
274 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
279 int hf_iclass_eload_usage(void) {
280 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
281 PrintAndLog("Usage: hf iclass eload f <filename>");
283 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
287 int CmdHFiClassELoad(const char *Cmd
) {
289 char opt
= param_getchar(Cmd
, 0);
290 if (strlen(Cmd
)<1 || opt
== 'h')
291 return hf_iclass_eload_usage();
293 //File handling and reading
295 char filename
[FILE_PATH_SIZE
];
296 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0)
298 f
= fopen(filename
, "rb");
300 return hf_iclass_eload_usage();
304 PrintAndLog("Failed to read from file '%s'", filename
);
308 fseek(f
, 0, SEEK_END
);
309 long fsize
= ftell(f
);
310 fseek(f
, 0, SEEK_SET
);
313 PrintAndLog("Error, when getting filesize");
318 uint8_t *dump
= malloc(fsize
);
320 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
323 printIclassDumpInfo(dump
);
326 if (bytes_read
< fsize
)
328 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
333 uint32_t bytes_sent
= 0;
334 uint32_t bytes_remaining
= bytes_read
;
336 while(bytes_remaining
> 0){
337 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
338 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
339 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
341 bytes_remaining
-= bytes_in_packet
;
342 bytes_sent
+= bytes_in_packet
;
345 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
349 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
350 FILE *f
= fopen(filename
, "rb");
352 PrintAndLog("Failed to read from file '%s'", filename
);
355 fseek(f
, 0, SEEK_END
);
356 long fsize
= ftell(f
);
357 fseek(f
, 0, SEEK_SET
);
358 size_t bytes_read
= fread(buffer
, 1, len
, f
);
362 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
365 if(bytes_read
!= len
)
367 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
373 int usage_hf_iclass_decrypt(void) {
374 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
376 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
377 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
379 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
381 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
382 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
383 PrintAndLog("which is defined by the configuration block.");
387 int CmdHFiClassDecrypt(const char *Cmd
) {
388 uint8_t key
[16] = { 0 };
389 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
391 usage_hf_iclass_decrypt();
394 PrintAndLog("Decryption file found... ");
395 char opt
= param_getchar(Cmd
, 0);
396 if (strlen(Cmd
)<1 || opt
== 'h')
397 return usage_hf_iclass_decrypt();
399 //Open the tagdump-file
401 char filename
[FILE_PATH_SIZE
];
402 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) {
403 f
= fopen(filename
, "rb");
405 PrintAndLog("Could not find file %s", filename
);
409 return usage_hf_iclass_decrypt();
412 fseek(f
, 0, SEEK_END
);
413 long fsize
= ftell(f
);
414 fseek(f
, 0, SEEK_SET
);
415 uint8_t enc_dump
[8] = {0};
416 uint8_t *decrypted
= malloc(fsize
);
417 mbedtls_des3_context ctx
= { 0 };
418 mbedtls_des3_set2key_dec( &ctx
, key
);
419 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
421 //Use the first block (CSN) for filename
422 char outfilename
[FILE_PATH_SIZE
] = { 0 };
423 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
424 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
425 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
428 while(bytes_read
== 8)
432 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
434 mbedtls_des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
436 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
437 bytes_read
= fread(enc_dump
, 1, 8, f
);
442 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
447 int usage_hf_iclass_encrypt(void) {
448 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
450 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
451 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
453 PrintAndLog("example: hf iclass encrypt 0102030405060708");
458 static int iClassEncryptBlkData(uint8_t *blkData
) {
459 uint8_t key
[16] = { 0 };
460 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
462 usage_hf_iclass_encrypt();
465 PrintAndLog("Decryption file found... ");
467 uint8_t encryptedData
[16];
468 uint8_t *encrypted
= encryptedData
;
469 mbedtls_des3_context ctx
= { 0 };
470 mbedtls_des3_set2key_enc( &ctx
, key
);
472 mbedtls_des3_crypt_ecb(&ctx
, blkData
,encrypted
);
473 //printvar("decrypted block", decrypted, 8);
474 memcpy(blkData
,encrypted
,8);
479 int CmdHFiClassEncryptBlk(const char *Cmd
) {
480 uint8_t blkData
[8] = {0};
481 char opt
= param_getchar(Cmd
, 0);
482 if (strlen(Cmd
)<1 || opt
== 'h')
483 return usage_hf_iclass_encrypt();
485 //get the bytes to encrypt
486 if (param_gethex(Cmd
, 0, blkData
, 16))
488 PrintAndLog("BlockData must include 16 HEX symbols");
491 if (!iClassEncryptBlkData(blkData
)) return 0;
493 printvar("encrypted block", blkData
, 8);
497 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
500 memcpy(WB
+ 1,data
,8);
501 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
502 //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]);
505 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
508 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
509 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
511 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
513 clearCommandBuffer();
515 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
517 PrintAndLog("Command execute timeout");
521 uint8_t isOK
= resp
.arg
[0] & 0xff;
522 uint8_t *data
= resp
.d
.asBytes
;
525 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
528 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
531 PrintAndLog("Failed to obtain CC! Aborting");
537 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
) {
538 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
539 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
541 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
546 memcpy(div_key
, KEY
, 8);
548 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
549 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]);
551 doMAC(CCNR
, div_key
, MAC
);
553 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
554 memcpy(d
.d
.asBytes
, MAC
, 4);
555 clearCommandBuffer();
557 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
559 if (verbose
) PrintAndLog("Auth Command execute timeout");
562 uint8_t isOK
= resp
.arg
[0] & 0xff;
564 if (verbose
) PrintAndLog("Authentication error");
570 int usage_hf_iclass_dump(void) {
571 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
572 PrintAndLog("Options:");
573 PrintAndLog(" f <filename> : specify a filename to save dump to");
574 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
575 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
576 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
577 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
578 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
579 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
580 PrintAndLog(" NOTE: * = required");
581 PrintAndLog("Samples:");
582 PrintAndLog(" hf iclass dump k 001122334455667B");
583 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
584 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
588 int CmdHFiClassReader_Dump(const char *Cmd
) {
590 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
591 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
592 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
596 uint8_t app_areas
= 1;
598 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
599 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
602 uint8_t fileNameLen
= 0;
603 char filename
[FILE_PATH_SIZE
]={0};
604 char tempStr
[50] = {0};
605 bool have_debit_key
= false;
606 bool have_credit_key
= false;
607 bool use_credit_key
= false;
613 while(param_getchar(Cmd
, cmdp
) != 0x00)
615 switch(param_getchar(Cmd
, cmdp
))
619 return usage_hf_iclass_dump();
622 have_credit_key
= true;
623 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
625 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
626 } else if (dataLen
== 1) {
627 keyNbr
= param_get8(Cmd
, cmdp
+1);
628 if (keyNbr
< ICLASS_KEYS_MAX
) {
629 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
631 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
635 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
647 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
648 if (fileNameLen
< 1) {
649 PrintAndLog("No filename found after f");
656 have_debit_key
= true;
657 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
659 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
660 } else if (dataLen
== 1) {
661 keyNbr
= param_get8(Cmd
, cmdp
+1);
662 if (keyNbr
< ICLASS_KEYS_MAX
) {
663 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
665 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
669 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
680 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
684 if(errors
) return usage_hf_iclass_dump();
687 if (cmdp
< 2) return usage_hf_iclass_dump();
688 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
689 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
691 //get config and first 3 blocks
692 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
693 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
695 uint8_t tag_data
[255*8];
697 clearCommandBuffer();
699 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
700 PrintAndLog("Command execute timeout");
704 uint8_t readStatus
= resp
.arg
[0] & 0xff;
705 uint8_t *data
= resp
.d
.asBytes
;
708 PrintAndLog("No tag found...");
712 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
713 memcpy(tag_data
, data
, 8*3);
714 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
716 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
717 // large memory - not able to dump pages currently
718 if (numblks
> maxBlk
) numblks
= maxBlk
;
721 // authenticate debit key and get div_key - later store in dump block 3
722 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
723 //try twice - for some reason it sometimes fails the first time...
724 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
731 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
732 clearCommandBuffer();
734 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
735 PrintAndLog("Command execute time-out 1");
739 uint32_t blocksRead
= resp
.arg
[1];
740 uint8_t isOK
= resp
.arg
[0] & 0xff;
741 if (!isOK
&& !blocksRead
) {
742 PrintAndLog("Read Block Failed");
746 uint32_t startindex
= resp
.arg
[2];
747 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
748 PrintAndLog("Data exceeded Buffer size!");
749 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
751 // response ok - now get bigbuf content of the dump
752 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
, NULL
, -1, false);
753 size_t gotBytes
= blocksRead
*8 + blockno
*8;
756 if (have_credit_key
) {
757 //turn off hf field before authenticating with different key
760 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
761 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
762 //try twice - for some reason it sometimes fails the first time...
763 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
768 // do we still need to read more block? (aa2 enabled?)
769 if (maxBlk
> blockno
+numblks
+1) {
770 // setup dump and start
771 w
.arg
[0] = blockno
+ blocksRead
;
772 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
773 clearCommandBuffer();
775 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
776 PrintAndLog("Command execute timeout 2");
780 uint8_t isOK
= resp
.arg
[0] & 0xff;
781 blocksRead
= resp
.arg
[1];
782 if (!isOK
&& !blocksRead
) {
783 PrintAndLog("Read Block Failed 2");
788 startindex
= resp
.arg
[2];
789 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
790 PrintAndLog("Data exceeded Buffer size!");
791 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
793 // get dumped data from bigbuf
794 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
, NULL
, -1, false);
796 gotBytes
+= blocksRead
*8;
797 } else { //field is still on - turn it off...
802 // add diversified keys to dump
803 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
804 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
806 printf("------+--+-------------------------+\n");
807 printf("CSN |00| %s|\n",sprint_hex(tag_data
, 8));
808 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
810 if (filename
[0] == 0){
811 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
812 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
813 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
816 // save the dump to .bin file
817 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
818 saveFile(filename
, "bin", tag_data
, gotBytes
);
822 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
823 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
824 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
825 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
830 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
831 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
832 memcpy(w
.d
.asBytes
, bldata
, 8);
833 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
835 clearCommandBuffer();
837 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
839 PrintAndLog("Write Command execute timeout");
842 uint8_t isOK
= resp
.arg
[0] & 0xff;
844 PrintAndLog("Write Block Failed");
847 PrintAndLog("Write Block Successful");
851 int usage_hf_iclass_writeblock(void) {
852 PrintAndLog("Options:");
853 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
854 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
855 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
856 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
857 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
858 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
859 PrintAndLog("Samples:");
860 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
861 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
862 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
866 int CmdHFiClass_WriteBlock(const char *Cmd
) {
868 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
869 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
872 char tempStr
[50] = {0};
873 bool use_credit_key
= false;
878 while(param_getchar(Cmd
, cmdp
) != 0x00)
880 switch(param_getchar(Cmd
, cmdp
))
884 return usage_hf_iclass_writeblock();
887 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
888 PrintAndLog("Block No must include 2 HEX symbols\n");
895 use_credit_key
= true;
900 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
902 PrintAndLog("KEY must include 16 HEX symbols\n");
914 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
916 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
917 } else if (dataLen
== 1) {
918 keyNbr
= param_get8(Cmd
, cmdp
+1);
919 if (keyNbr
< ICLASS_KEYS_MAX
) {
920 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
922 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
926 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
937 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
941 if(errors
) return usage_hf_iclass_writeblock();
944 if (cmdp
< 6) return usage_hf_iclass_writeblock();
945 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
950 int usage_hf_iclass_clone(void) {
951 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
952 PrintAndLog("Options:");
953 PrintAndLog(" f <filename>: specify a filename to clone from");
954 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
955 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
956 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
957 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
958 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
959 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
960 PrintAndLog("Samples:");
961 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
962 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
963 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
967 int CmdHFiClassCloneTag(const char *Cmd
) {
968 char filename
[FILE_PATH_SIZE
] = {0};
969 char tempStr
[50]={0};
970 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
972 uint8_t fileNameLen
= 0;
973 uint8_t startblock
= 0;
974 uint8_t endblock
= 0;
976 bool use_credit_key
= false;
981 while(param_getchar(Cmd
, cmdp
) != 0x00)
983 switch(param_getchar(Cmd
, cmdp
))
987 return usage_hf_iclass_clone();
990 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
991 PrintAndLog("Start Block No must include 2 HEX symbols\n");
998 use_credit_key
= true;
1008 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1009 if (fileNameLen
< 1) {
1010 PrintAndLog("No filename found after f");
1017 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1018 if (dataLen
== 16) {
1019 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1020 } else if (dataLen
== 1) {
1021 keyNbr
= param_get8(Cmd
, cmdp
+1);
1022 if (keyNbr
< ICLASS_KEYS_MAX
) {
1023 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1025 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1029 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1036 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1037 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1048 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1052 if(errors
) return usage_hf_iclass_clone();
1055 if (cmdp
< 8) return usage_hf_iclass_clone();
1059 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1061 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1062 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1064 // file handling and reading
1065 f
= fopen(filename
,"rb");
1067 PrintAndLog("Failed to read from file '%s'", filename
);
1072 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1076 // now read data from the file from block 6 --- 19
1077 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1078 // 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,
1079 // else we have to create a share memory
1081 fseek(f
,startblock
*8,SEEK_SET
);
1082 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1083 PrintAndLog("File reading error.");
1088 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1089 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1091 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1094 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1096 // calculate all mac for every the block we will write
1097 for (i
= startblock
; i
<= endblock
; i
++){
1098 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1099 // usb command d start pointer = d + (i - 6) * 12
1100 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1101 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1103 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1104 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1105 memcpy(ptr
+ 8,MAC
, 4);
1108 for (i
= 0; i
<= endblock
- startblock
;i
++){
1109 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1110 printf("Block |%02x|",i
+ startblock
);
1111 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]);
1112 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1116 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1118 PrintAndLog("Command execute timeout");
1124 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) {
1125 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1126 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1129 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1132 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1133 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1134 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
))
1139 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1140 clearCommandBuffer();
1142 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1144 PrintAndLog("Command execute timeout");
1147 uint8_t isOK
= resp
.arg
[0] & 0xff;
1149 PrintAndLog("Read Block Failed");
1152 //data read is stored in: resp.d.asBytes[0-15]
1153 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1157 int usage_hf_iclass_readblock(void) {
1158 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1159 PrintAndLog("Options:");
1160 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1161 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1162 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1163 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1164 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1165 PrintAndLog("Samples:");
1166 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1167 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1168 PrintAndLog(" hf iclass readblk b 0A k 0");
1172 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1174 uint8_t keyType
= 0x88; //debit key
1175 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1177 uint8_t dataLen
= 0;
1178 char tempStr
[50] = {0};
1180 bool rawkey
= false;
1181 bool errors
= false;
1184 while(param_getchar(Cmd
, cmdp
) != 0x00)
1186 switch(param_getchar(Cmd
, cmdp
))
1190 return usage_hf_iclass_readblock();
1193 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1194 PrintAndLog("Block No must include 2 HEX symbols\n");
1212 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1213 if (dataLen
== 16) {
1214 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1215 } else if (dataLen
== 1) {
1216 keyNbr
= param_get8(Cmd
, cmdp
+1);
1217 if (keyNbr
< ICLASS_KEYS_MAX
) {
1218 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1220 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1224 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1235 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1239 if(errors
) return usage_hf_iclass_readblock();
1242 if (cmdp
< 2) return usage_hf_iclass_readblock();
1244 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1245 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
);
1248 int CmdHFiClass_loclass(const char *Cmd
) {
1249 char opt
= param_getchar(Cmd
, 0);
1251 if (strlen(Cmd
)<1 || opt
== 'h') {
1252 PrintAndLog("Usage: hf iclass loclass [options]");
1253 PrintAndLog("Options:");
1254 PrintAndLog("h Show this help");
1255 PrintAndLog("t Perform self-test");
1256 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1257 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1258 PrintAndLog(" malicious CSNs, and their protocol responses");
1259 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1260 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1261 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1262 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1263 PrintAndLog(" ... totalling N*24 bytes");
1266 char fileName
[255] = {0};
1269 if(param_getstr(Cmd
, 1, fileName
, sizeof(fileName
)) > 0)
1271 return bruteforceFileNoKeys(fileName
);
1274 PrintAndLog("You must specify a filename");
1279 int errors
= testCipherUtils();
1280 errors
+= testMAC();
1281 errors
+= doKeyTests(0);
1282 errors
+= testElite();
1285 prnlog("OBS! There were errors!!!");
1293 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1295 memcpy(&mem_config
, iclass_dump
+ 13,1);
1296 uint8_t maxmemcount
;
1297 uint8_t filemaxblock
= filesize
/ 8;
1298 if (mem_config
& 0x80)
1302 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1304 if (startblock
== 0)
1306 if ((endblock
> maxmemcount
) || (endblock
== 0))
1307 endblock
= maxmemcount
;
1309 // remember endblock need to relate to zero-index arrays.
1310 if (endblock
> filemaxblock
-1)
1311 endblock
= filemaxblock
;
1314 printf("------+--+-------------------------+\n");
1315 while (i
<= endblock
) {
1316 uint8_t *blk
= iclass_dump
+ (i
* 8);
1317 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );
1320 printf("------+--+-------------------------+\n");
1323 int usage_hf_iclass_readtagfile() {
1324 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1328 int CmdHFiClassReadTagFile(const char *Cmd
) {
1333 char filename
[FILE_PATH_SIZE
];
1334 if (param_getstr(Cmd
, 0, filename
, sizeof(filename
)) < 1)
1335 return usage_hf_iclass_readtagfile();
1336 if (param_getstr(Cmd
, 1, tempnum
, sizeof(tempnum
)) < 1)
1339 sscanf(tempnum
,"%d",&startblock
);
1341 if (param_getstr(Cmd
,2, tempnum
, sizeof(tempnum
)) < 1)
1344 sscanf(tempnum
,"%d",&endblock
);
1345 // file handling and reading
1346 f
= fopen(filename
,"rb");
1348 PrintAndLog("Failed to read from file '%s'", filename
);
1351 fseek(f
, 0, SEEK_END
);
1352 long fsize
= ftell(f
);
1353 fseek(f
, 0, SEEK_SET
);
1356 PrintAndLog("Error, when getting filesize");
1361 uint8_t *dump
= malloc(fsize
);
1363 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1365 uint8_t *csn
= dump
;
1366 printf("------+--+-------------------------+\n");
1367 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1368 // printIclassDumpInfo(dump);
1369 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1375 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1376 uint64_t new_div = 0x00;
1382 uint64_t hexarray_to_uint64(uint8_t *key) {
1385 for (int i = 0;i < 8;i++)
1386 sprintf(&temp[(i *2)],"%02X",key[i]);
1388 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1393 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1394 uint8_t keytable
[128] = {0};
1395 uint8_t key_index
[8] = {0};
1397 uint8_t key_sel
[8] = { 0 };
1398 uint8_t key_sel_p
[8] = { 0 };
1399 hash2(KEY
, keytable
);
1400 hash1(CSN
, key_index
);
1401 for(uint8_t i
= 0; i
< 8 ; i
++)
1402 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1404 //Permute from iclass format to standard format
1405 permutekey_rev(key_sel
, key_sel_p
);
1406 diversifyKey(CSN
, key_sel_p
, div_key
);
1408 diversifyKey(CSN
, KEY
, div_key
);
1412 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1413 //calculate and return xor_div_key (ready for a key write command)
1414 //print all div_keys if verbose
1415 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1416 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1417 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1419 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1421 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1423 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1424 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1427 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1428 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1429 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1433 int usage_hf_iclass_calc_newkey(void) {
1434 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1435 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1436 PrintAndLog(" Options:");
1437 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1438 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1439 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1440 PrintAndLog(" e : specify new key as elite calc");
1441 PrintAndLog(" ee : specify old and new key as elite calc");
1442 PrintAndLog("Samples:");
1443 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1444 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1445 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1446 PrintAndLog("NOTE: * = required\n");
1451 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1452 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1453 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1454 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1455 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1456 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1458 uint8_t dataLen
= 0;
1459 char tempStr
[50] = {0};
1460 bool givenCSN
= false;
1461 bool oldElite
= false;
1463 bool errors
= false;
1465 while(param_getchar(Cmd
, cmdp
) != 0x00)
1467 switch(param_getchar(Cmd
, cmdp
))
1471 return usage_hf_iclass_calc_newkey();
1474 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
, sizeof(tempStr
));
1482 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1483 if (dataLen
== 16) {
1484 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1485 } else if (dataLen
== 1) {
1486 keyNbr
= param_get8(Cmd
, cmdp
+1);
1487 if (keyNbr
< ICLASS_KEYS_MAX
) {
1488 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1490 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1494 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1501 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1502 if (dataLen
== 16) {
1503 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1504 } else if (dataLen
== 1) {
1505 keyNbr
= param_get8(Cmd
, cmdp
+1);
1506 if (keyNbr
< ICLASS_KEYS_MAX
) {
1507 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1509 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1513 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1521 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1522 return usage_hf_iclass_calc_newkey();
1526 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1530 if(errors
) return usage_hf_iclass_calc_newkey();
1533 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1536 if (!select_only(CSN
, CCNR
, false, true))
1539 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1543 static int loadKeys(char *filename
) {
1545 f
= fopen(filename
,"rb");
1547 PrintAndLog("Failed to read from file '%s'", filename
);
1550 fseek(f
, 0, SEEK_END
);
1551 long fsize
= ftell(f
);
1552 fseek(f
, 0, SEEK_SET
);
1555 PrintAndLog("Error, when getting filesize");
1560 uint8_t *dump
= malloc(fsize
);
1562 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1564 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1565 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1570 for (; i
< bytes_read
/8; i
++){
1571 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1574 PrintAndLog("%u keys loaded", i
);
1578 static int saveKeys(char *filename
) {
1580 f
= fopen(filename
,"wb");
1582 printf("error opening file %s\n",filename
);
1585 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1586 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1587 PrintAndLog("save key failed to write to file: %s", filename
);
1595 static int printKeys(void) {
1597 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1598 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1604 int usage_hf_iclass_managekeys(void) {
1605 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1606 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1607 PrintAndLog(" Options:");
1608 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1609 PrintAndLog(" k <key> : set a key in memory");
1610 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1611 PrintAndLog(" s : save keys in memory to file specified by filename");
1612 PrintAndLog(" l : load keys to memory from file specified by filename");
1613 PrintAndLog(" p : print keys loaded into memory\n");
1614 PrintAndLog("Samples:");
1615 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1616 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1617 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1618 PrintAndLog(" print keys : hf iclass managekeys p\n");
1622 int CmdHFiClassManageKeys(const char *Cmd
) {
1624 uint8_t dataLen
= 0;
1625 uint8_t KEY
[8] = {0};
1626 char filename
[FILE_PATH_SIZE
];
1627 uint8_t fileNameLen
= 0;
1628 bool errors
= false;
1629 uint8_t operation
= 0;
1633 while(param_getchar(Cmd
, cmdp
) != 0x00)
1635 switch(param_getchar(Cmd
, cmdp
))
1639 return usage_hf_iclass_managekeys();
1642 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1643 if (fileNameLen
< 1) {
1644 PrintAndLog("No filename found after f");
1651 keyNbr
= param_get8(Cmd
, cmdp
+1);
1652 if (keyNbr
>= ICLASS_KEYS_MAX
) {
1653 PrintAndLog("Invalid block number");
1660 operation
+= 3; //set key
1661 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1662 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1663 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1665 PrintAndLog("\nERROR: Key is incorrect length\n");
1672 operation
+= 4; //print keys in memory
1677 operation
+= 5; //load keys from file
1682 operation
+= 6; //save keys to file
1686 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1690 if(errors
) return usage_hf_iclass_managekeys();
1692 if (operation
== 0){
1693 PrintAndLog("no operation specified (load, save, or print)\n");
1694 return usage_hf_iclass_managekeys();
1697 PrintAndLog("Too many operations specified\n");
1698 return usage_hf_iclass_managekeys();
1700 if (operation
> 4 && fileNameLen
== 0){
1701 PrintAndLog("You must enter a filename when loading or saving\n");
1702 return usage_hf_iclass_managekeys();
1706 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1707 case 4: return printKeys();
1708 case 5: return loadKeys(filename
);
1709 case 6: return saveKeys(filename
);
1715 int CmdHFiClassCheckKeys(const char *Cmd
) {
1717 uint8_t mac
[4] = {0x00,0x00,0x00,0x00};
1718 uint8_t key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1719 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1721 // elite key, raw key, standard key
1722 bool use_elite
= false;
1723 bool use_raw
= false;
1724 bool found_debit
= false;
1725 bool found_credit
= false;
1726 bool errors
= false;
1727 uint8_t cmdp
= 0x00;
1729 char filename
[FILE_PATH_SIZE
] = {0};
1730 uint8_t fileNameLen
= 0;
1732 uint8_t *keyBlock
= NULL
, *p
;
1733 int keyitems
= 0, keycnt
= 0;
1735 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
1736 switch (param_getchar(Cmd
, cmdp
)) {
1739 return usage_hf_iclass_chk();
1742 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1743 if (fileNameLen
< 1) {
1744 PrintAndLog("No filename found after f");
1760 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1765 if (errors
) return usage_hf_iclass_chk();
1767 if ( !(f
= fopen( filename
, "r")) ) {
1768 PrintAndLog("File: %s: not found or locked.", filename
);
1772 while( fgets(buf
, sizeof(buf
), f
) ){
1773 if (strlen(buf
) < 16 || buf
[15] == '\n')
1776 while (fgetc(f
) != '\n' && !feof(f
)) ; //goto next line
1778 if( buf
[0]=='#' ) continue; //The line start with # is comment, skip
1780 if (!isxdigit(buf
[0])){
1781 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf
);
1787 p
= realloc(keyBlock
, 8 * (keyitems
+= 64));
1789 PrintAndLog("Cannot allocate memory for default keys");
1796 memset(keyBlock
+ 8 * keycnt
, 0, 8);
1797 num_to_bytes(strtoull(buf
, NULL
, 16), 8, keyBlock
+ 8 * keycnt
);
1799 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1801 memset(buf
, 0, sizeof(buf
));
1804 PrintAndLog("Loaded %2d keys from %s", keycnt
, filename
);
1807 uint64_t t1
= msclock();
1809 for (uint32_t c
= 0; c
< keycnt
; c
+= 1) {
1810 printf("."); fflush(stdout
);
1812 int gc
= getchar(); (void)gc
;
1813 printf("\naborted via keyboard!\n");
1817 memcpy(key
, keyBlock
+ 8 * c
, 8);
1819 // debit key. try twice
1820 for (int foo
= 0; foo
< 2 && !found_debit
; foo
++) {
1821 if (!select_and_auth(key
, mac
, div_key
, false, use_elite
, use_raw
, false))
1825 PrintAndLog("\n--------------------------------------------------------");
1826 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key
, 8));
1830 // credit key. try twice
1831 for (int foo
= 0; foo
< 2 && !found_credit
; foo
++) {
1832 if (!select_and_auth(key
, mac
, div_key
, true, use_elite
, use_raw
, false))
1836 PrintAndLog("\n--------------------------------------------------------");
1837 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key
, 8));
1838 found_credit
= true;
1842 if ( found_debit
&& found_credit
)
1846 t1
= msclock() - t1
;
1848 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1
/1000.0);
1856 static command_t CommandTable
[] =
1858 {"help", CmdHelp
, 1, "This help"},
1859 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1860 {"chk", CmdHFiClassCheckKeys
, 0, " Check keys"},
1861 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1862 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1863 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1864 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1865 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1866 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1867 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1868 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1869 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1870 {"reader", CmdHFiClassReader
, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1871 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1872 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1873 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1874 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1875 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1876 {NULL
, NULL
, 0, NULL
}
1879 int CmdHFiClass(const char *Cmd
)
1881 clearCommandBuffer();
1882 CmdsParse(CommandTable
, Cmd
);
1886 int CmdHelp(const char *Cmd
)
1888 CmdsHelp(CommandTable
);