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");
104 int CmdHFiClassSim(const char *Cmd
) {
106 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
109 return usage_hf_iclass_sim();
111 simType
= param_get8ex(Cmd
, 0, 0, 10);
115 if (param_gethex(Cmd
, 1, CSN
, 16)) {
116 PrintAndLog("A CSN should consist of 16 HEX symbols");
117 return usage_hf_iclass_sim();
120 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
124 PrintAndLog("Undefined simptype %d", simType
);
125 return usage_hf_iclass_sim();
128 uint8_t numberOfCSNs
=0;
131 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
132 UsbCommand resp
= {0};
134 uint8_t csns
[8*NUM_CSNS
] = {
135 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
136 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
137 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
138 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
139 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
140 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
141 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
142 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
143 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
144 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
145 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
146 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
147 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
148 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
149 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
151 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
154 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
155 PrintAndLog("Command timed out");
159 uint8_t num_mac_responses
= resp
.arg
[1];
160 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
162 size_t datalen
= NUM_CSNS
*24;
164 * Now, time to dump to file. We'll use this format:
165 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
166 * So, it should wind up as
169 * The returndata from the pm3 is on the following format
170 * <4 byte NR><4 byte MAC>
171 * CC are all zeroes, CSN is the same as was sent in
173 void* dump
= malloc(datalen
);
174 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
176 for(i
= 0 ; i
< NUM_CSNS
; i
++)
178 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
179 //8 zero bytes here...
180 //Then comes NR_MAC (eight bytes from the response)
181 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
184 /** Now, save to dumpfile **/
185 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
189 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
190 memcpy(c
.d
.asBytes
, CSN
, 8);
197 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
198 bool tagFound
= false;
199 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
200 FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_AA
|
201 FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
} };
202 // loop in client not device - else on windows have a communication error
206 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
207 uint8_t readStatus
= resp
.arg
[0] & 0xff;
208 uint8_t *data
= resp
.d
.asBytes
;
210 // no tag found or button pressed
211 if( (readStatus
== 0 && !loop
) || readStatus
== 0xFF) {
213 if (verbose
) PrintAndLog("Quitting...");
217 if( readStatus
& FLAG_ICLASS_READER_CSN
) {
218 PrintAndLog(" CSN: %s",sprint_hex(data
,8));
221 if( readStatus
& FLAG_ICLASS_READER_CC
) {
222 PrintAndLog(" CC: %s",sprint_hex(data
+16,8));
224 if( readStatus
& FLAG_ICLASS_READER_CONF
) {
225 printIclassDumpInfo(data
);
227 if (readStatus
& FLAG_ICLASS_READER_AA
) {
229 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*5,8));
230 for (int i
= 0; i
<8; i
++) {
231 if (data
[8*5+i
] != 0xFF) {
235 PrintAndLog(" : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)");
238 if (tagFound
&& !loop
) return 1;
240 if (verbose
) PrintAndLog("Command execute timeout");
247 int CmdHFiClassReader(const char *Cmd
) {
248 return HFiClassReader(Cmd
, true, true);
251 int CmdHFiClassReader_Replay(const char *Cmd
) {
252 uint8_t readerType
= 0;
253 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
256 PrintAndLog("Usage: hf iclass replay <MAC>");
257 PrintAndLog(" sample: hf iclass replay 00112233");
261 if (param_gethex(Cmd
, 0, MAC
, 8)) {
262 PrintAndLog("MAC must include 8 HEX symbols");
266 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
267 memcpy(c
.d
.asBytes
, MAC
, 4);
273 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
274 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
275 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
280 int hf_iclass_eload_usage(void) {
281 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
282 PrintAndLog("Usage: hf iclass eload f <filename>");
284 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
288 int CmdHFiClassELoad(const char *Cmd
) {
290 char opt
= param_getchar(Cmd
, 0);
291 if (strlen(Cmd
)<1 || opt
== 'h')
292 return hf_iclass_eload_usage();
294 //File handling and reading
296 char filename
[FILE_PATH_SIZE
];
297 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0)
299 f
= fopen(filename
, "rb");
301 return hf_iclass_eload_usage();
305 PrintAndLog("Failed to read from file '%s'", filename
);
309 fseek(f
, 0, SEEK_END
);
310 long fsize
= ftell(f
);
311 fseek(f
, 0, SEEK_SET
);
314 PrintAndLog("Error, when getting filesize");
319 uint8_t *dump
= malloc(fsize
);
321 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
324 printIclassDumpInfo(dump
);
327 if (bytes_read
< fsize
)
329 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
334 uint32_t bytes_sent
= 0;
335 uint32_t bytes_remaining
= bytes_read
;
337 while(bytes_remaining
> 0){
338 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
339 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
340 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
342 bytes_remaining
-= bytes_in_packet
;
343 bytes_sent
+= bytes_in_packet
;
346 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
350 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
351 FILE *f
= fopen(filename
, "rb");
353 PrintAndLog("Failed to read from file '%s'", filename
);
356 fseek(f
, 0, SEEK_END
);
357 long fsize
= ftell(f
);
358 fseek(f
, 0, SEEK_SET
);
359 size_t bytes_read
= fread(buffer
, 1, len
, f
);
363 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
366 if(bytes_read
!= len
)
368 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
374 int usage_hf_iclass_decrypt(void) {
375 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
377 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
378 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
380 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
382 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
383 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
384 PrintAndLog("which is defined by the configuration block.");
388 int CmdHFiClassDecrypt(const char *Cmd
) {
389 uint8_t key
[16] = { 0 };
390 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
392 usage_hf_iclass_decrypt();
395 PrintAndLog("Decryption file found... ");
396 char opt
= param_getchar(Cmd
, 0);
397 if (strlen(Cmd
)<1 || opt
== 'h')
398 return usage_hf_iclass_decrypt();
400 //Open the tagdump-file
402 char filename
[FILE_PATH_SIZE
];
403 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) {
404 f
= fopen(filename
, "rb");
406 PrintAndLog("Could not find file %s", filename
);
410 return usage_hf_iclass_decrypt();
413 fseek(f
, 0, SEEK_END
);
414 long fsize
= ftell(f
);
415 fseek(f
, 0, SEEK_SET
);
416 uint8_t enc_dump
[8] = {0};
417 uint8_t *decrypted
= malloc(fsize
);
418 mbedtls_des3_context ctx
= { {0} };
419 mbedtls_des3_set2key_dec( &ctx
, key
);
420 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
422 //Use the first block (CSN) for filename
423 char outfilename
[FILE_PATH_SIZE
] = { 0 };
424 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
425 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
426 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
429 while(bytes_read
== 8)
433 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
435 mbedtls_des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
437 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
438 bytes_read
= fread(enc_dump
, 1, 8, f
);
443 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
448 int usage_hf_iclass_encrypt(void) {
449 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
451 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
452 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
454 PrintAndLog("example: hf iclass encrypt 0102030405060708");
459 static int iClassEncryptBlkData(uint8_t *blkData
) {
460 uint8_t key
[16] = { 0 };
461 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
463 usage_hf_iclass_encrypt();
466 PrintAndLog("Decryption file found... ");
468 uint8_t encryptedData
[16];
469 uint8_t *encrypted
= encryptedData
;
470 mbedtls_des3_context ctx
= { {0} };
471 mbedtls_des3_set2key_enc( &ctx
, key
);
473 mbedtls_des3_crypt_ecb(&ctx
, blkData
,encrypted
);
474 //printvar("decrypted block", decrypted, 8);
475 memcpy(blkData
,encrypted
,8);
480 int CmdHFiClassEncryptBlk(const char *Cmd
) {
481 uint8_t blkData
[8] = {0};
482 char opt
= param_getchar(Cmd
, 0);
483 if (strlen(Cmd
)<1 || opt
== 'h')
484 return usage_hf_iclass_encrypt();
486 //get the bytes to encrypt
487 if (param_gethex(Cmd
, 0, blkData
, 16))
489 PrintAndLog("BlockData must include 16 HEX symbols");
492 if (!iClassEncryptBlkData(blkData
)) return 0;
494 printvar("encrypted block", blkData
, 8);
498 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
501 memcpy(WB
+ 1,data
,8);
502 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
503 //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]);
506 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
509 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
510 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
512 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
514 clearCommandBuffer();
516 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
518 PrintAndLog("Command execute timeout");
522 uint8_t isOK
= resp
.arg
[0] & 0xff;
523 uint8_t *data
= resp
.d
.asBytes
;
526 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
529 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
532 PrintAndLog("Failed to obtain CC! Aborting");
538 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
) {
539 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
540 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
542 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
547 memcpy(div_key
, KEY
, 8);
549 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
550 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]);
552 doMAC(CCNR
, div_key
, MAC
);
554 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
555 memcpy(d
.d
.asBytes
, MAC
, 4);
556 clearCommandBuffer();
558 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
560 if (verbose
) PrintAndLog("Auth Command execute timeout");
563 uint8_t isOK
= resp
.arg
[0] & 0xff;
565 if (verbose
) PrintAndLog("Authentication error");
571 int usage_hf_iclass_dump(void) {
572 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
573 PrintAndLog("Options:");
574 PrintAndLog(" f <filename> : specify a filename to save dump to");
575 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
576 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
577 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
578 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
579 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
580 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
581 PrintAndLog(" NOTE: * = required");
582 PrintAndLog("Samples:");
583 PrintAndLog(" hf iclass dump k 001122334455667B");
584 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
585 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
589 int CmdHFiClassReader_Dump(const char *Cmd
) {
591 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
592 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
593 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
597 uint8_t app_areas
= 1;
599 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
600 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
603 uint8_t fileNameLen
= 0;
604 char filename
[FILE_PATH_SIZE
]={0};
605 char tempStr
[50] = {0};
606 bool have_debit_key
= false;
607 bool have_credit_key
= false;
608 bool use_credit_key
= false;
614 while(param_getchar(Cmd
, cmdp
) != 0x00)
616 switch(param_getchar(Cmd
, cmdp
))
620 return usage_hf_iclass_dump();
623 have_credit_key
= true;
624 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
626 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
627 } else if (dataLen
== 1) {
628 keyNbr
= param_get8(Cmd
, cmdp
+1);
629 if (keyNbr
< ICLASS_KEYS_MAX
) {
630 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
632 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
636 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
648 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
649 if (fileNameLen
< 1) {
650 PrintAndLog("No filename found after f");
657 have_debit_key
= true;
658 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
660 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
661 } else if (dataLen
== 1) {
662 keyNbr
= param_get8(Cmd
, cmdp
+1);
663 if (keyNbr
< ICLASS_KEYS_MAX
) {
664 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
666 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
670 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
681 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
685 if(errors
) return usage_hf_iclass_dump();
688 if (cmdp
< 2) return usage_hf_iclass_dump();
689 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
690 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
692 //get config and first 3 blocks
693 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
694 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
696 uint8_t tag_data
[255*8];
698 clearCommandBuffer();
700 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
701 PrintAndLog("Command execute timeout");
705 uint8_t readStatus
= resp
.arg
[0] & 0xff;
706 uint8_t *data
= resp
.d
.asBytes
;
709 PrintAndLog("No tag found...");
713 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
714 memcpy(tag_data
, data
, 8*3);
715 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
717 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
718 // large memory - not able to dump pages currently
719 if (numblks
> maxBlk
) numblks
= maxBlk
;
722 // authenticate debit key and get div_key - later store in dump block 3
723 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
724 //try twice - for some reason it sometimes fails the first time...
725 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
732 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
733 clearCommandBuffer();
735 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
736 PrintAndLog("Command execute time-out 1");
740 uint32_t blocksRead
= resp
.arg
[1];
741 uint8_t isOK
= resp
.arg
[0] & 0xff;
742 if (!isOK
&& !blocksRead
) {
743 PrintAndLog("Read Block Failed");
747 uint32_t startindex
= resp
.arg
[2];
748 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
749 PrintAndLog("Data exceeded Buffer size!");
750 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
752 // response ok - now get bigbuf content of the dump
753 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
, NULL
, -1, false);
754 size_t gotBytes
= blocksRead
*8 + blockno
*8;
757 if (have_credit_key
) {
758 //turn off hf field before authenticating with different key
761 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
762 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
763 //try twice - for some reason it sometimes fails the first time...
764 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
769 // do we still need to read more block? (aa2 enabled?)
770 if (maxBlk
> blockno
+numblks
+1) {
771 // setup dump and start
772 w
.arg
[0] = blockno
+ blocksRead
;
773 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
774 clearCommandBuffer();
776 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
777 PrintAndLog("Command execute timeout 2");
781 uint8_t isOK
= resp
.arg
[0] & 0xff;
782 blocksRead
= resp
.arg
[1];
783 if (!isOK
&& !blocksRead
) {
784 PrintAndLog("Read Block Failed 2");
789 startindex
= resp
.arg
[2];
790 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
791 PrintAndLog("Data exceeded Buffer size!");
792 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
794 // get dumped data from bigbuf
795 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
, NULL
, -1, false);
797 gotBytes
+= blocksRead
*8;
798 } else { //field is still on - turn it off...
803 // add diversified keys to dump
804 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
805 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
807 printf("------+--+-------------------------+\n");
808 printf("CSN |00| %s|\n",sprint_hex(tag_data
, 8));
809 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
811 if (filename
[0] == 0){
812 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
813 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
814 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
817 // save the dump to .bin file
818 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
819 saveFile(filename
, "bin", tag_data
, gotBytes
);
823 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
824 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
825 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
826 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
831 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
832 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
833 memcpy(w
.d
.asBytes
, bldata
, 8);
834 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
836 clearCommandBuffer();
838 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
840 PrintAndLog("Write Command execute timeout");
843 uint8_t isOK
= resp
.arg
[0] & 0xff;
845 PrintAndLog("Write Block Failed");
848 PrintAndLog("Write Block Successful");
852 int usage_hf_iclass_writeblock(void) {
853 PrintAndLog("Options:");
854 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
855 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
856 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
857 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
858 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
859 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
860 PrintAndLog("Samples:");
861 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
862 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
863 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
867 int CmdHFiClass_WriteBlock(const char *Cmd
) {
869 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
870 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
873 char tempStr
[50] = {0};
874 bool use_credit_key
= false;
879 while(param_getchar(Cmd
, cmdp
) != 0x00)
881 switch(param_getchar(Cmd
, cmdp
))
885 return usage_hf_iclass_writeblock();
888 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
889 PrintAndLog("Block No must include 2 HEX symbols\n");
896 use_credit_key
= true;
901 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
903 PrintAndLog("KEY must include 16 HEX symbols\n");
915 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
917 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
918 } else if (dataLen
== 1) {
919 keyNbr
= param_get8(Cmd
, cmdp
+1);
920 if (keyNbr
< ICLASS_KEYS_MAX
) {
921 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
923 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
927 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
938 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
942 if(errors
) return usage_hf_iclass_writeblock();
945 if (cmdp
< 6) return usage_hf_iclass_writeblock();
946 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
951 int usage_hf_iclass_clone(void) {
952 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
953 PrintAndLog("Options:");
954 PrintAndLog(" f <filename>: specify a filename to clone from");
955 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
956 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
957 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
958 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
959 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
960 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
961 PrintAndLog("Samples:");
962 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
963 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
964 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
968 int CmdHFiClassCloneTag(const char *Cmd
) {
969 char filename
[FILE_PATH_SIZE
] = {0};
970 char tempStr
[50]={0};
971 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
973 uint8_t fileNameLen
= 0;
974 uint8_t startblock
= 0;
975 uint8_t endblock
= 0;
977 bool use_credit_key
= false;
982 while(param_getchar(Cmd
, cmdp
) != 0x00)
984 switch(param_getchar(Cmd
, cmdp
))
988 return usage_hf_iclass_clone();
991 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
992 PrintAndLog("Start Block No must include 2 HEX symbols\n");
999 use_credit_key
= true;
1009 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1010 if (fileNameLen
< 1) {
1011 PrintAndLog("No filename found after f");
1018 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1019 if (dataLen
== 16) {
1020 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1021 } else if (dataLen
== 1) {
1022 keyNbr
= param_get8(Cmd
, cmdp
+1);
1023 if (keyNbr
< ICLASS_KEYS_MAX
) {
1024 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1026 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1030 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1037 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1038 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1049 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1053 if(errors
) return usage_hf_iclass_clone();
1056 if (cmdp
< 8) return usage_hf_iclass_clone();
1060 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1062 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1063 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1065 // file handling and reading
1066 f
= fopen(filename
,"rb");
1068 PrintAndLog("Failed to read from file '%s'", filename
);
1073 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1077 // now read data from the file from block 6 --- 19
1078 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1079 // 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,
1080 // else we have to create a share memory
1082 fseek(f
,startblock
*8,SEEK_SET
);
1083 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1084 PrintAndLog("File reading error.");
1089 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1090 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1092 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1095 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1097 // calculate all mac for every the block we will write
1098 for (i
= startblock
; i
<= endblock
; i
++){
1099 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1100 // usb command d start pointer = d + (i - 6) * 12
1101 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1102 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1104 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1105 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1106 memcpy(ptr
+ 8,MAC
, 4);
1109 for (i
= 0; i
<= endblock
- startblock
;i
++){
1110 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1111 printf("Block |%02x|",i
+ startblock
);
1112 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]);
1113 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1117 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1119 PrintAndLog("Command execute timeout");
1125 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) {
1126 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1127 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1130 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1133 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1134 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1135 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
))
1140 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1141 clearCommandBuffer();
1143 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1145 PrintAndLog("Command execute timeout");
1148 uint8_t isOK
= resp
.arg
[0] & 0xff;
1150 PrintAndLog("Read Block Failed");
1153 //data read is stored in: resp.d.asBytes[0-15]
1154 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1158 int usage_hf_iclass_readblock(void) {
1159 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1160 PrintAndLog("Options:");
1161 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1162 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1163 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1164 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1165 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1166 PrintAndLog("Samples:");
1167 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1168 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1169 PrintAndLog(" hf iclass readblk b 0A k 0");
1173 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1175 uint8_t keyType
= 0x88; //debit key
1176 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1178 uint8_t dataLen
= 0;
1179 char tempStr
[50] = {0};
1181 bool rawkey
= false;
1182 bool errors
= false;
1185 while(param_getchar(Cmd
, cmdp
) != 0x00)
1187 switch(param_getchar(Cmd
, cmdp
))
1191 return usage_hf_iclass_readblock();
1194 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1195 PrintAndLog("Block No must include 2 HEX symbols\n");
1213 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1214 if (dataLen
== 16) {
1215 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1216 } else if (dataLen
== 1) {
1217 keyNbr
= param_get8(Cmd
, cmdp
+1);
1218 if (keyNbr
< ICLASS_KEYS_MAX
) {
1219 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1221 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1225 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1236 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1240 if(errors
) return usage_hf_iclass_readblock();
1243 if (cmdp
< 2) return usage_hf_iclass_readblock();
1245 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1246 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
);
1249 int CmdHFiClass_loclass(const char *Cmd
) {
1250 char opt
= param_getchar(Cmd
, 0);
1252 if (strlen(Cmd
)<1 || opt
== 'h') {
1253 PrintAndLog("Usage: hf iclass loclass [options]");
1254 PrintAndLog("Options:");
1255 PrintAndLog("h Show this help");
1256 PrintAndLog("t Perform self-test");
1257 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1258 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1259 PrintAndLog(" malicious CSNs, and their protocol responses");
1260 PrintAndLog(" The binary format of the file is expected to be as follows: ");
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(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1264 PrintAndLog(" ... totalling N*24 bytes");
1267 char fileName
[255] = {0};
1270 if(param_getstr(Cmd
, 1, fileName
, sizeof(fileName
)) > 0)
1272 return bruteforceFileNoKeys(fileName
);
1275 PrintAndLog("You must specify a filename");
1280 int errors
= testCipherUtils();
1281 errors
+= testMAC();
1282 errors
+= doKeyTests(0);
1283 errors
+= testElite();
1286 prnlog("OBS! There were errors!!!");
1294 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1296 memcpy(&mem_config
, iclass_dump
+ 13,1);
1297 uint8_t maxmemcount
;
1298 uint8_t filemaxblock
= filesize
/ 8;
1299 if (mem_config
& 0x80)
1303 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1305 if (startblock
== 0)
1307 if ((endblock
> maxmemcount
) || (endblock
== 0))
1308 endblock
= maxmemcount
;
1310 // remember endblock need to relate to zero-index arrays.
1311 if (endblock
> filemaxblock
-1)
1312 endblock
= filemaxblock
;
1315 printf("------+--+-------------------------+\n");
1316 while (i
<= endblock
) {
1317 uint8_t *blk
= iclass_dump
+ (i
* 8);
1318 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );
1321 printf("------+--+-------------------------+\n");
1324 int usage_hf_iclass_readtagfile() {
1325 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1329 int CmdHFiClassReadTagFile(const char *Cmd
) {
1334 char filename
[FILE_PATH_SIZE
];
1335 if (param_getstr(Cmd
, 0, filename
, sizeof(filename
)) < 1)
1336 return usage_hf_iclass_readtagfile();
1337 if (param_getstr(Cmd
, 1, tempnum
, sizeof(tempnum
)) < 1)
1340 sscanf(tempnum
,"%d",&startblock
);
1342 if (param_getstr(Cmd
,2, tempnum
, sizeof(tempnum
)) < 1)
1345 sscanf(tempnum
,"%d",&endblock
);
1346 // file handling and reading
1347 f
= fopen(filename
,"rb");
1349 PrintAndLog("Failed to read from file '%s'", filename
);
1352 fseek(f
, 0, SEEK_END
);
1353 long fsize
= ftell(f
);
1354 fseek(f
, 0, SEEK_SET
);
1357 PrintAndLog("Error, when getting filesize");
1362 uint8_t *dump
= malloc(fsize
);
1364 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1366 uint8_t *csn
= dump
;
1367 printf("------+--+-------------------------+\n");
1368 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1369 // printIclassDumpInfo(dump);
1370 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1376 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1377 uint64_t new_div = 0x00;
1383 uint64_t hexarray_to_uint64(uint8_t *key) {
1386 for (int i = 0;i < 8;i++)
1387 sprintf(&temp[(i *2)],"%02X",key[i]);
1389 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1394 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1395 uint8_t keytable
[128] = {0};
1396 uint8_t key_index
[8] = {0};
1398 uint8_t key_sel
[8] = { 0 };
1399 uint8_t key_sel_p
[8] = { 0 };
1400 hash2(KEY
, keytable
);
1401 hash1(CSN
, key_index
);
1402 for(uint8_t i
= 0; i
< 8 ; i
++)
1403 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1405 //Permute from iclass format to standard format
1406 permutekey_rev(key_sel
, key_sel_p
);
1407 diversifyKey(CSN
, key_sel_p
, div_key
);
1409 diversifyKey(CSN
, KEY
, div_key
);
1413 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1414 //calculate and return xor_div_key (ready for a key write command)
1415 //print all div_keys if verbose
1416 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1417 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1418 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1420 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1422 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1424 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1425 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1428 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1429 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1430 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1434 int usage_hf_iclass_calc_newkey(void) {
1435 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1436 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1437 PrintAndLog(" Options:");
1438 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1439 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1440 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1441 PrintAndLog(" e : specify new key as elite calc");
1442 PrintAndLog(" ee : specify old and new key as elite calc");
1443 PrintAndLog("Samples:");
1444 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1445 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1446 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1447 PrintAndLog("NOTE: * = required\n");
1452 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1453 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1454 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1455 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1456 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1457 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1459 uint8_t dataLen
= 0;
1460 char tempStr
[50] = {0};
1461 bool givenCSN
= false;
1462 bool oldElite
= false;
1464 bool errors
= false;
1466 while(param_getchar(Cmd
, cmdp
) != 0x00)
1468 switch(param_getchar(Cmd
, cmdp
))
1472 return usage_hf_iclass_calc_newkey();
1475 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
, sizeof(tempStr
));
1483 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1484 if (dataLen
== 16) {
1485 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1486 } else if (dataLen
== 1) {
1487 keyNbr
= param_get8(Cmd
, cmdp
+1);
1488 if (keyNbr
< ICLASS_KEYS_MAX
) {
1489 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1491 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1495 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1502 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1503 if (dataLen
== 16) {
1504 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1505 } else if (dataLen
== 1) {
1506 keyNbr
= param_get8(Cmd
, cmdp
+1);
1507 if (keyNbr
< ICLASS_KEYS_MAX
) {
1508 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1510 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1514 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1522 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1523 return usage_hf_iclass_calc_newkey();
1527 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1531 if(errors
) return usage_hf_iclass_calc_newkey();
1534 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1537 if (!select_only(CSN
, CCNR
, false, true))
1540 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1544 static int loadKeys(char *filename
) {
1546 f
= fopen(filename
,"rb");
1548 PrintAndLog("Failed to read from file '%s'", filename
);
1551 fseek(f
, 0, SEEK_END
);
1552 long fsize
= ftell(f
);
1553 fseek(f
, 0, SEEK_SET
);
1556 PrintAndLog("Error, when getting filesize");
1561 uint8_t *dump
= malloc(fsize
);
1563 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1565 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1566 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1571 for (; i
< bytes_read
/8; i
++){
1572 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1575 PrintAndLog("%u keys loaded", i
);
1579 static int saveKeys(char *filename
) {
1581 f
= fopen(filename
,"wb");
1583 printf("error opening file %s\n",filename
);
1586 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1587 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1588 PrintAndLog("save key failed to write to file: %s", filename
);
1596 static int printKeys(void) {
1598 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1599 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1605 int usage_hf_iclass_managekeys(void) {
1606 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1607 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1608 PrintAndLog(" Options:");
1609 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1610 PrintAndLog(" k <key> : set a key in memory");
1611 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1612 PrintAndLog(" s : save keys in memory to file specified by filename");
1613 PrintAndLog(" l : load keys to memory from file specified by filename");
1614 PrintAndLog(" p : print keys loaded into memory\n");
1615 PrintAndLog("Samples:");
1616 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1617 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1618 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1619 PrintAndLog(" print keys : hf iclass managekeys p\n");
1623 int CmdHFiClassManageKeys(const char *Cmd
) {
1625 uint8_t dataLen
= 0;
1626 uint8_t KEY
[8] = {0};
1627 char filename
[FILE_PATH_SIZE
];
1628 uint8_t fileNameLen
= 0;
1629 bool errors
= false;
1630 uint8_t operation
= 0;
1634 while(param_getchar(Cmd
, cmdp
) != 0x00)
1636 switch(param_getchar(Cmd
, cmdp
))
1640 return usage_hf_iclass_managekeys();
1643 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1644 if (fileNameLen
< 1) {
1645 PrintAndLog("No filename found after f");
1652 keyNbr
= param_get8(Cmd
, cmdp
+1);
1653 if (keyNbr
>= ICLASS_KEYS_MAX
) {
1654 PrintAndLog("Invalid block number");
1661 operation
+= 3; //set key
1662 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1663 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1664 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1666 PrintAndLog("\nERROR: Key is incorrect length\n");
1673 operation
+= 4; //print keys in memory
1678 operation
+= 5; //load keys from file
1683 operation
+= 6; //save keys to file
1687 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1691 if(errors
) return usage_hf_iclass_managekeys();
1693 if (operation
== 0){
1694 PrintAndLog("no operation specified (load, save, or print)\n");
1695 return usage_hf_iclass_managekeys();
1698 PrintAndLog("Too many operations specified\n");
1699 return usage_hf_iclass_managekeys();
1701 if (operation
> 4 && fileNameLen
== 0){
1702 PrintAndLog("You must enter a filename when loading or saving\n");
1703 return usage_hf_iclass_managekeys();
1707 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1708 case 4: return printKeys();
1709 case 5: return loadKeys(filename
);
1710 case 6: return saveKeys(filename
);
1716 int CmdHFiClassCheckKeys(const char *Cmd
) {
1718 uint8_t mac
[4] = {0x00,0x00,0x00,0x00};
1719 uint8_t key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1720 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1722 // elite key, raw key, standard key
1723 bool use_elite
= false;
1724 bool use_raw
= false;
1725 bool found_debit
= false;
1726 bool found_credit
= false;
1727 bool errors
= false;
1728 uint8_t cmdp
= 0x00;
1730 char filename
[FILE_PATH_SIZE
] = {0};
1731 uint8_t fileNameLen
= 0;
1733 uint8_t *keyBlock
= NULL
, *p
;
1734 int keyitems
= 0, keycnt
= 0;
1736 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
1737 switch (param_getchar(Cmd
, cmdp
)) {
1740 return usage_hf_iclass_chk();
1743 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1744 if (fileNameLen
< 1) {
1745 PrintAndLog("No filename found after f");
1761 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1766 if (errors
) return usage_hf_iclass_chk();
1768 if ( !(f
= fopen( filename
, "r")) ) {
1769 PrintAndLog("File: %s: not found or locked.", filename
);
1773 while( fgets(buf
, sizeof(buf
), f
) ){
1774 if (strlen(buf
) < 16 || buf
[15] == '\n')
1777 while (fgetc(f
) != '\n' && !feof(f
)) ; //goto next line
1779 if( buf
[0]=='#' ) continue; //The line start with # is comment, skip
1781 if (!isxdigit(buf
[0])){
1782 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf
);
1788 p
= realloc(keyBlock
, 8 * (keyitems
+= 64));
1790 PrintAndLog("Cannot allocate memory for default keys");
1797 memset(keyBlock
+ 8 * keycnt
, 0, 8);
1798 num_to_bytes(strtoull(buf
, NULL
, 16), 8, keyBlock
+ 8 * keycnt
);
1800 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1802 memset(buf
, 0, sizeof(buf
));
1805 PrintAndLog("Loaded %2d keys from %s", keycnt
, filename
);
1808 uint64_t t1
= msclock();
1810 for (uint32_t c
= 0; c
< keycnt
; c
+= 1) {
1811 printf("."); fflush(stdout
);
1813 int gc
= getchar(); (void)gc
;
1814 printf("\naborted via keyboard!\n");
1818 memcpy(key
, keyBlock
+ 8 * c
, 8);
1820 // debit key. try twice
1821 for (int foo
= 0; foo
< 2 && !found_debit
; foo
++) {
1822 if (!select_and_auth(key
, mac
, div_key
, false, use_elite
, use_raw
, false))
1826 PrintAndLog("\n--------------------------------------------------------");
1827 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key
, 8));
1831 // credit key. try twice
1832 for (int foo
= 0; foo
< 2 && !found_credit
; foo
++) {
1833 if (!select_and_auth(key
, mac
, div_key
, true, use_elite
, use_raw
, false))
1837 PrintAndLog("\n--------------------------------------------------------");
1838 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key
, 8));
1839 found_credit
= true;
1843 if ( found_debit
&& found_credit
)
1847 t1
= msclock() - t1
;
1849 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1
/1000.0);
1857 static command_t CommandTable
[] =
1859 {"help", CmdHelp
, 1, "This help"},
1860 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1861 {"chk", CmdHFiClassCheckKeys
, 0, " Check keys"},
1862 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1863 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1864 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1865 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1866 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1867 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1868 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1869 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1870 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1871 {"reader", CmdHFiClassReader
, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1872 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1873 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1874 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1875 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1876 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1877 {NULL
, NULL
, 0, NULL
}
1880 int CmdHFiClass(const char *Cmd
)
1882 clearCommandBuffer();
1883 CmdsParse(CommandTable
, Cmd
);
1887 int CmdHelp(const char *Cmd
)
1889 CmdsHelp(CommandTable
);