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) {
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
) {
327 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
332 uint32_t bytes_sent
= 0;
333 uint32_t bytes_remaining
= bytes_read
;
335 while (bytes_remaining
> 0) {
336 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
337 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
338 memcpy(c
.d
.asBytes
, dump
+bytes_sent
, bytes_in_packet
);
340 bytes_remaining
-= bytes_in_packet
;
341 bytes_sent
+= bytes_in_packet
;
344 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
348 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
349 FILE *f
= fopen(filename
, "rb");
351 PrintAndLog("Failed to read from file '%s'", filename
);
354 fseek(f
, 0, SEEK_END
);
355 long fsize
= ftell(f
);
356 fseek(f
, 0, SEEK_SET
);
357 size_t bytes_read
= fread(buffer
, 1, len
, f
);
361 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
364 if(bytes_read
!= len
)
366 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
372 int usage_hf_iclass_decrypt(void) {
373 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
375 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
376 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
378 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
380 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
381 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
382 PrintAndLog("which is defined by the configuration block.");
386 int CmdHFiClassDecrypt(const char *Cmd
) {
387 uint8_t key
[16] = { 0 };
388 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
390 usage_hf_iclass_decrypt();
393 PrintAndLog("Decryption file found... ");
394 char opt
= param_getchar(Cmd
, 0);
395 if (strlen(Cmd
)<1 || opt
== 'h')
396 return usage_hf_iclass_decrypt();
398 //Open the tagdump-file
400 char filename
[FILE_PATH_SIZE
];
401 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) {
402 f
= fopen(filename
, "rb");
404 PrintAndLog("Could not find file %s", filename
);
408 return usage_hf_iclass_decrypt();
411 fseek(f
, 0, SEEK_END
);
412 long fsize
= ftell(f
);
413 fseek(f
, 0, SEEK_SET
);
414 uint8_t enc_dump
[8] = {0};
415 uint8_t *decrypted
= malloc(fsize
);
416 mbedtls_des3_context ctx
= { {0} };
417 mbedtls_des3_set2key_dec( &ctx
, key
);
418 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
420 //Use the first block (CSN) for filename
421 char outfilename
[FILE_PATH_SIZE
] = { 0 };
422 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
423 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
424 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
427 while(bytes_read
== 8)
431 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
433 mbedtls_des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
435 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
436 bytes_read
= fread(enc_dump
, 1, 8, f
);
441 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
446 int usage_hf_iclass_encrypt(void) {
447 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
449 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
450 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
452 PrintAndLog("example: hf iclass encrypt 0102030405060708");
457 static int iClassEncryptBlkData(uint8_t *blkData
) {
458 uint8_t key
[16] = { 0 };
459 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
461 usage_hf_iclass_encrypt();
464 PrintAndLog("Decryption file found... ");
466 uint8_t encryptedData
[16];
467 uint8_t *encrypted
= encryptedData
;
468 mbedtls_des3_context ctx
= { {0} };
469 mbedtls_des3_set2key_enc( &ctx
, key
);
471 mbedtls_des3_crypt_ecb(&ctx
, blkData
,encrypted
);
472 //printvar("decrypted block", decrypted, 8);
473 memcpy(blkData
,encrypted
,8);
478 int CmdHFiClassEncryptBlk(const char *Cmd
) {
479 uint8_t blkData
[8] = {0};
480 char opt
= param_getchar(Cmd
, 0);
481 if (strlen(Cmd
)<1 || opt
== 'h')
482 return usage_hf_iclass_encrypt();
484 //get the bytes to encrypt
485 if (param_gethex(Cmd
, 0, blkData
, 16))
487 PrintAndLog("BlockData must include 16 HEX symbols");
490 if (!iClassEncryptBlkData(blkData
)) return 0;
492 printvar("encrypted block", blkData
, 8);
496 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
499 memcpy(WB
+ 1,data
,8);
500 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
501 //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]);
504 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
507 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
508 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
510 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
512 clearCommandBuffer();
514 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
516 PrintAndLog("Command execute timeout");
520 uint8_t isOK
= resp
.arg
[0] & 0xff;
521 uint8_t *data
= resp
.d
.asBytes
;
524 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
527 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
530 PrintAndLog("Failed to obtain CC! Aborting");
536 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
) {
537 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
538 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
540 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
545 memcpy(div_key
, KEY
, 8);
547 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
548 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]);
550 doMAC(CCNR
, div_key
, MAC
);
552 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
553 memcpy(d
.d
.asBytes
, MAC
, 4);
554 clearCommandBuffer();
556 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
558 if (verbose
) PrintAndLog("Auth Command execute timeout");
561 uint8_t isOK
= resp
.arg
[0] & 0xff;
563 if (verbose
) PrintAndLog("Authentication error");
569 int usage_hf_iclass_dump(void) {
570 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
571 PrintAndLog("Options:");
572 PrintAndLog(" f <filename> : specify a filename to save dump to");
573 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
574 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
575 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
576 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
577 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
578 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
579 PrintAndLog(" NOTE: * = required");
580 PrintAndLog("Samples:");
581 PrintAndLog(" hf iclass dump k 001122334455667B");
582 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
583 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
587 int CmdHFiClassReader_Dump(const char *Cmd
) {
589 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
590 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
591 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
595 uint8_t app_areas
= 1;
597 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
598 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
601 uint8_t fileNameLen
= 0;
602 char filename
[FILE_PATH_SIZE
]={0};
603 char tempStr
[50] = {0};
604 bool have_debit_key
= false;
605 bool have_credit_key
= false;
606 bool use_credit_key
= false;
612 while(param_getchar(Cmd
, cmdp
) != 0x00)
614 switch(param_getchar(Cmd
, cmdp
))
618 return usage_hf_iclass_dump();
621 have_credit_key
= true;
622 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
624 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
625 } else if (dataLen
== 1) {
626 keyNbr
= param_get8(Cmd
, cmdp
+1);
627 if (keyNbr
< ICLASS_KEYS_MAX
) {
628 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
630 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
634 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
646 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
647 if (fileNameLen
< 1) {
648 PrintAndLog("No filename found after f");
655 have_debit_key
= true;
656 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
658 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
659 } else if (dataLen
== 1) {
660 keyNbr
= param_get8(Cmd
, cmdp
+1);
661 if (keyNbr
< ICLASS_KEYS_MAX
) {
662 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
664 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
668 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
679 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
683 if(errors
) return usage_hf_iclass_dump();
686 if (cmdp
< 2) return usage_hf_iclass_dump();
687 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
688 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
690 //get config and first 3 blocks
691 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
692 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
694 uint8_t tag_data
[255*8];
696 clearCommandBuffer();
698 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
699 PrintAndLog("Command execute timeout");
703 uint8_t readStatus
= resp
.arg
[0] & 0xff;
704 uint8_t *data
= resp
.d
.asBytes
;
707 PrintAndLog("No tag found...");
711 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
712 memcpy(tag_data
, data
, 8*3);
713 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
715 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
716 // large memory - not able to dump pages currently
717 if (numblks
> maxBlk
) numblks
= maxBlk
;
720 // authenticate debit key and get div_key - later store in dump block 3
721 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
722 //try twice - for some reason it sometimes fails the first time...
723 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
730 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
731 clearCommandBuffer();
733 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
734 PrintAndLog("Command execute time-out 1");
738 uint32_t blocksRead
= resp
.arg
[1];
739 uint8_t isOK
= resp
.arg
[0] & 0xff;
740 if (!isOK
&& !blocksRead
) {
741 PrintAndLog("Read Block Failed");
745 uint32_t startindex
= resp
.arg
[2];
746 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
747 PrintAndLog("Data exceeded Buffer size!");
748 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
750 // response ok - now get bigbuf content of the dump
751 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
, NULL
, -1, false);
752 size_t gotBytes
= blocksRead
*8 + blockno
*8;
755 if (have_credit_key
) {
756 //turn off hf field before authenticating with different key
759 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
760 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
761 //try twice - for some reason it sometimes fails the first time...
762 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
767 // do we still need to read more block? (aa2 enabled?)
768 if (maxBlk
> blockno
+numblks
+1) {
769 // setup dump and start
770 w
.arg
[0] = blockno
+ blocksRead
;
771 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
772 clearCommandBuffer();
774 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
775 PrintAndLog("Command execute timeout 2");
779 uint8_t isOK
= resp
.arg
[0] & 0xff;
780 blocksRead
= resp
.arg
[1];
781 if (!isOK
&& !blocksRead
) {
782 PrintAndLog("Read Block Failed 2");
787 startindex
= resp
.arg
[2];
788 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
789 PrintAndLog("Data exceeded Buffer size!");
790 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
792 // get dumped data from bigbuf
793 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
, NULL
, -1, false);
795 gotBytes
+= blocksRead
*8;
796 } else { //field is still on - turn it off...
801 // add diversified keys to dump
802 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
803 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
805 printf("------+--+-------------------------+\n");
806 printf("CSN |00| %s|\n",sprint_hex(tag_data
, 8));
807 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
809 if (filename
[0] == 0){
810 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
811 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
812 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
815 // save the dump to .bin file
816 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
817 saveFile(filename
, "bin", tag_data
, gotBytes
);
821 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
822 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
823 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
824 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
829 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
830 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
831 memcpy(w
.d
.asBytes
, bldata
, 8);
832 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
834 clearCommandBuffer();
836 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
838 PrintAndLog("Write Command execute timeout");
841 uint8_t isOK
= resp
.arg
[0] & 0xff;
843 PrintAndLog("Write Block Failed");
846 PrintAndLog("Write Block Successful");
850 int usage_hf_iclass_writeblock(void) {
851 PrintAndLog("Options:");
852 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
853 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
854 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
855 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
856 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
857 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
858 PrintAndLog("Samples:");
859 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
860 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
861 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
865 int CmdHFiClass_WriteBlock(const char *Cmd
) {
867 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
868 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
871 char tempStr
[50] = {0};
872 bool use_credit_key
= false;
877 while(param_getchar(Cmd
, cmdp
) != 0x00)
879 switch(param_getchar(Cmd
, cmdp
))
883 return usage_hf_iclass_writeblock();
886 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
887 PrintAndLog("Block No must include 2 HEX symbols\n");
894 use_credit_key
= true;
899 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
901 PrintAndLog("KEY must include 16 HEX symbols\n");
913 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
915 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
916 } else if (dataLen
== 1) {
917 keyNbr
= param_get8(Cmd
, cmdp
+1);
918 if (keyNbr
< ICLASS_KEYS_MAX
) {
919 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
921 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
925 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
936 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
940 if(errors
) return usage_hf_iclass_writeblock();
943 if (cmdp
< 6) return usage_hf_iclass_writeblock();
944 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
949 int usage_hf_iclass_clone(void) {
950 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
951 PrintAndLog("Options:");
952 PrintAndLog(" f <filename>: specify a filename to clone from");
953 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
954 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
955 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
956 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
957 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
958 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
959 PrintAndLog("Samples:");
960 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
961 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
962 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
966 int CmdHFiClassCloneTag(const char *Cmd
) {
967 char filename
[FILE_PATH_SIZE
] = {0};
968 char tempStr
[50]={0};
969 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
971 uint8_t fileNameLen
= 0;
972 uint8_t startblock
= 0;
973 uint8_t endblock
= 0;
975 bool use_credit_key
= false;
980 while(param_getchar(Cmd
, cmdp
) != 0x00)
982 switch(param_getchar(Cmd
, cmdp
))
986 return usage_hf_iclass_clone();
989 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
990 PrintAndLog("Start Block No must include 2 HEX symbols\n");
997 use_credit_key
= true;
1007 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1008 if (fileNameLen
< 1) {
1009 PrintAndLog("No filename found after f");
1016 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1017 if (dataLen
== 16) {
1018 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1019 } else if (dataLen
== 1) {
1020 keyNbr
= param_get8(Cmd
, cmdp
+1);
1021 if (keyNbr
< ICLASS_KEYS_MAX
) {
1022 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1024 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1028 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1035 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1036 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1047 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1051 if(errors
) return usage_hf_iclass_clone();
1054 if (cmdp
< 8) return usage_hf_iclass_clone();
1058 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1060 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1061 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1063 // file handling and reading
1064 f
= fopen(filename
,"rb");
1066 PrintAndLog("Failed to read from file '%s'", filename
);
1071 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1075 // now read data from the file from block 6 --- 19
1076 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1077 // 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,
1078 // else we have to create a share memory
1080 fseek(f
,startblock
*8,SEEK_SET
);
1081 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1082 PrintAndLog("File reading error.");
1087 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1088 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1090 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1093 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1095 // calculate all mac for every the block we will write
1096 for (i
= startblock
; i
<= endblock
; i
++){
1097 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1098 // usb command d start pointer = d + (i - 6) * 12
1099 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1100 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1102 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1103 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1104 memcpy(ptr
+ 8,MAC
, 4);
1107 for (i
= 0; i
<= endblock
- startblock
;i
++){
1108 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1109 printf("Block |%02x|",i
+ startblock
);
1110 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]);
1111 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1115 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1117 PrintAndLog("Command execute timeout");
1123 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) {
1124 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1125 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1128 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1131 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1132 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1133 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
))
1138 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1139 clearCommandBuffer();
1141 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1143 PrintAndLog("Command execute timeout");
1146 uint8_t isOK
= resp
.arg
[0] & 0xff;
1148 PrintAndLog("Read Block Failed");
1151 //data read is stored in: resp.d.asBytes[0-15]
1152 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1156 int usage_hf_iclass_readblock(void) {
1157 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1158 PrintAndLog("Options:");
1159 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1160 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1161 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1162 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1163 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1164 PrintAndLog("Samples:");
1165 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1166 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1167 PrintAndLog(" hf iclass readblk b 0A k 0");
1171 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1173 uint8_t keyType
= 0x88; //debit key
1174 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1176 uint8_t dataLen
= 0;
1177 char tempStr
[50] = {0};
1179 bool rawkey
= false;
1180 bool errors
= false;
1183 while(param_getchar(Cmd
, cmdp
) != 0x00)
1185 switch(param_getchar(Cmd
, cmdp
))
1189 return usage_hf_iclass_readblock();
1192 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1193 PrintAndLog("Block No must include 2 HEX symbols\n");
1211 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1212 if (dataLen
== 16) {
1213 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1214 } else if (dataLen
== 1) {
1215 keyNbr
= param_get8(Cmd
, cmdp
+1);
1216 if (keyNbr
< ICLASS_KEYS_MAX
) {
1217 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1219 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1223 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1234 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1238 if(errors
) return usage_hf_iclass_readblock();
1241 if (cmdp
< 2) return usage_hf_iclass_readblock();
1243 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1244 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
);
1247 int CmdHFiClass_loclass(const char *Cmd
) {
1248 char opt
= param_getchar(Cmd
, 0);
1250 if (strlen(Cmd
)<1 || opt
== 'h') {
1251 PrintAndLog("Usage: hf iclass loclass [options]");
1252 PrintAndLog("Options:");
1253 PrintAndLog("h Show this help");
1254 PrintAndLog("t Perform self-test");
1255 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1256 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1257 PrintAndLog(" malicious CSNs, and their protocol responses");
1258 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1259 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
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(" ... totalling N*24 bytes");
1265 char fileName
[255] = {0};
1268 if(param_getstr(Cmd
, 1, fileName
, sizeof(fileName
)) > 0)
1270 return bruteforceFileNoKeys(fileName
);
1273 PrintAndLog("You must specify a filename");
1278 int errors
= testCipherUtils();
1279 errors
+= testMAC();
1280 errors
+= doKeyTests(0);
1281 errors
+= testElite();
1284 prnlog("OBS! There were errors!!!");
1292 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1294 memcpy(&mem_config
, iclass_dump
+ 13,1);
1295 uint8_t maxmemcount
;
1296 uint8_t filemaxblock
= filesize
/ 8;
1297 if (mem_config
& 0x80)
1301 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1303 if (startblock
== 0)
1305 if ((endblock
> maxmemcount
) || (endblock
== 0))
1306 endblock
= maxmemcount
;
1308 // remember endblock need to relate to zero-index arrays.
1309 if (endblock
> filemaxblock
-1)
1310 endblock
= filemaxblock
;
1313 printf("------+--+-------------------------+\n");
1314 while (i
<= endblock
) {
1315 uint8_t *blk
= iclass_dump
+ (i
* 8);
1316 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );
1319 printf("------+--+-------------------------+\n");
1322 int usage_hf_iclass_readtagfile() {
1323 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1327 int CmdHFiClassReadTagFile(const char *Cmd
) {
1332 char filename
[FILE_PATH_SIZE
];
1333 if (param_getstr(Cmd
, 0, filename
, sizeof(filename
)) < 1)
1334 return usage_hf_iclass_readtagfile();
1335 if (param_getstr(Cmd
, 1, tempnum
, sizeof(tempnum
)) < 1)
1338 sscanf(tempnum
,"%d",&startblock
);
1340 if (param_getstr(Cmd
,2, tempnum
, sizeof(tempnum
)) < 1)
1343 sscanf(tempnum
,"%d",&endblock
);
1344 // file handling and reading
1345 f
= fopen(filename
,"rb");
1347 PrintAndLog("Failed to read from file '%s'", filename
);
1350 fseek(f
, 0, SEEK_END
);
1351 long fsize
= ftell(f
);
1352 fseek(f
, 0, SEEK_SET
);
1355 PrintAndLog("Error, when getting filesize");
1360 uint8_t *dump
= malloc(fsize
);
1362 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1364 uint8_t *csn
= dump
;
1365 printf("------+--+-------------------------+\n");
1366 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1367 // printIclassDumpInfo(dump);
1368 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1374 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1375 uint64_t new_div = 0x00;
1381 uint64_t hexarray_to_uint64(uint8_t *key) {
1384 for (int i = 0;i < 8;i++)
1385 sprintf(&temp[(i *2)],"%02X",key[i]);
1387 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1392 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1393 uint8_t keytable
[128] = {0};
1394 uint8_t key_index
[8] = {0};
1396 uint8_t key_sel
[8] = { 0 };
1397 uint8_t key_sel_p
[8] = { 0 };
1398 hash2(KEY
, keytable
);
1399 hash1(CSN
, key_index
);
1400 for(uint8_t i
= 0; i
< 8 ; i
++)
1401 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1403 //Permute from iclass format to standard format
1404 permutekey_rev(key_sel
, key_sel_p
);
1405 diversifyKey(CSN
, key_sel_p
, div_key
);
1407 diversifyKey(CSN
, KEY
, div_key
);
1411 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1412 //calculate and return xor_div_key (ready for a key write command)
1413 //print all div_keys if verbose
1414 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1415 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1416 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1418 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1420 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1422 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1423 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1426 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1427 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1428 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1432 int usage_hf_iclass_calc_newkey(void) {
1433 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1434 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1435 PrintAndLog(" Options:");
1436 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1437 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1438 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1439 PrintAndLog(" e : specify new key as elite calc");
1440 PrintAndLog(" ee : specify old and new key as elite calc");
1441 PrintAndLog("Samples:");
1442 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1443 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1444 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1445 PrintAndLog("NOTE: * = required\n");
1450 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1451 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1452 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1453 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1454 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1455 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1457 uint8_t dataLen
= 0;
1458 char tempStr
[50] = {0};
1459 bool givenCSN
= false;
1460 bool oldElite
= false;
1462 bool errors
= false;
1464 while(param_getchar(Cmd
, cmdp
) != 0x00)
1466 switch(param_getchar(Cmd
, cmdp
))
1470 return usage_hf_iclass_calc_newkey();
1473 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
, sizeof(tempStr
));
1481 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1482 if (dataLen
== 16) {
1483 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1484 } else if (dataLen
== 1) {
1485 keyNbr
= param_get8(Cmd
, cmdp
+1);
1486 if (keyNbr
< ICLASS_KEYS_MAX
) {
1487 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1489 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1493 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1500 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1501 if (dataLen
== 16) {
1502 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1503 } else if (dataLen
== 1) {
1504 keyNbr
= param_get8(Cmd
, cmdp
+1);
1505 if (keyNbr
< ICLASS_KEYS_MAX
) {
1506 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1508 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1512 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1520 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1521 return usage_hf_iclass_calc_newkey();
1525 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1529 if(errors
) return usage_hf_iclass_calc_newkey();
1532 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1535 if (!select_only(CSN
, CCNR
, false, true))
1538 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1542 static int loadKeys(char *filename
) {
1544 f
= fopen(filename
,"rb");
1546 PrintAndLog("Failed to read from file '%s'", filename
);
1549 fseek(f
, 0, SEEK_END
);
1550 long fsize
= ftell(f
);
1551 fseek(f
, 0, SEEK_SET
);
1554 PrintAndLog("Error, when getting filesize");
1559 uint8_t *dump
= malloc(fsize
);
1561 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1563 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1564 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1569 for (; i
< bytes_read
/8; i
++){
1570 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1573 PrintAndLog("%u keys loaded", i
);
1577 static int saveKeys(char *filename
) {
1579 f
= fopen(filename
,"wb");
1581 printf("error opening file %s\n",filename
);
1584 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1585 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1586 PrintAndLog("save key failed to write to file: %s", filename
);
1594 static int printKeys(void) {
1596 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1597 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1603 int usage_hf_iclass_managekeys(void) {
1604 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1605 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1606 PrintAndLog(" Options:");
1607 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1608 PrintAndLog(" k <key> : set a key in memory");
1609 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1610 PrintAndLog(" s : save keys in memory to file specified by filename");
1611 PrintAndLog(" l : load keys to memory from file specified by filename");
1612 PrintAndLog(" p : print keys loaded into memory\n");
1613 PrintAndLog("Samples:");
1614 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1615 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1616 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1617 PrintAndLog(" print keys : hf iclass managekeys p\n");
1621 int CmdHFiClassManageKeys(const char *Cmd
) {
1623 uint8_t dataLen
= 0;
1624 uint8_t KEY
[8] = {0};
1625 char filename
[FILE_PATH_SIZE
];
1626 uint8_t fileNameLen
= 0;
1627 bool errors
= false;
1628 uint8_t operation
= 0;
1632 while(param_getchar(Cmd
, cmdp
) != 0x00)
1634 switch(param_getchar(Cmd
, cmdp
))
1638 return usage_hf_iclass_managekeys();
1641 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1642 if (fileNameLen
< 1) {
1643 PrintAndLog("No filename found after f");
1650 keyNbr
= param_get8(Cmd
, cmdp
+1);
1651 if (keyNbr
>= ICLASS_KEYS_MAX
) {
1652 PrintAndLog("Invalid block number");
1659 operation
+= 3; //set key
1660 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1661 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1662 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1664 PrintAndLog("\nERROR: Key is incorrect length\n");
1671 operation
+= 4; //print keys in memory
1676 operation
+= 5; //load keys from file
1681 operation
+= 6; //save keys to file
1685 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1689 if(errors
) return usage_hf_iclass_managekeys();
1691 if (operation
== 0){
1692 PrintAndLog("no operation specified (load, save, or print)\n");
1693 return usage_hf_iclass_managekeys();
1696 PrintAndLog("Too many operations specified\n");
1697 return usage_hf_iclass_managekeys();
1699 if (operation
> 4 && fileNameLen
== 0){
1700 PrintAndLog("You must enter a filename when loading or saving\n");
1701 return usage_hf_iclass_managekeys();
1705 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1706 case 4: return printKeys();
1707 case 5: return loadKeys(filename
);
1708 case 6: return saveKeys(filename
);
1714 int CmdHFiClassCheckKeys(const char *Cmd
) {
1716 uint8_t mac
[4] = {0x00,0x00,0x00,0x00};
1717 uint8_t key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1718 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1720 // elite key, raw key, standard key
1721 bool use_elite
= false;
1722 bool use_raw
= false;
1723 bool found_debit
= false;
1724 bool found_credit
= false;
1725 bool errors
= false;
1726 uint8_t cmdp
= 0x00;
1728 char filename
[FILE_PATH_SIZE
] = {0};
1729 uint8_t fileNameLen
= 0;
1731 uint8_t *keyBlock
= NULL
, *p
;
1732 int keyitems
= 0, keycnt
= 0;
1734 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
1735 switch (param_getchar(Cmd
, cmdp
)) {
1738 return usage_hf_iclass_chk();
1741 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1742 if (fileNameLen
< 1) {
1743 PrintAndLog("No filename found after f");
1759 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1764 if (errors
) return usage_hf_iclass_chk();
1766 if ( !(f
= fopen( filename
, "r")) ) {
1767 PrintAndLog("File: %s: not found or locked.", filename
);
1771 while( fgets(buf
, sizeof(buf
), f
) ){
1772 if (strlen(buf
) < 16 || buf
[15] == '\n')
1775 while (fgetc(f
) != '\n' && !feof(f
)) ; //goto next line
1777 if( buf
[0]=='#' ) continue; //The line start with # is comment, skip
1779 if (!isxdigit(buf
[0])){
1780 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf
);
1786 p
= realloc(keyBlock
, 8 * (keyitems
+= 64));
1788 PrintAndLog("Cannot allocate memory for default keys");
1795 memset(keyBlock
+ 8 * keycnt
, 0, 8);
1796 num_to_bytes(strtoull(buf
, NULL
, 16), 8, keyBlock
+ 8 * keycnt
);
1798 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1800 memset(buf
, 0, sizeof(buf
));
1803 PrintAndLog("Loaded %2d keys from %s", keycnt
, filename
);
1806 uint64_t t1
= msclock();
1808 for (uint32_t c
= 0; c
< keycnt
; c
+= 1) {
1809 printf("."); fflush(stdout
);
1811 int gc
= getchar(); (void)gc
;
1812 printf("\naborted via keyboard!\n");
1816 memcpy(key
, keyBlock
+ 8 * c
, 8);
1818 // debit key. try twice
1819 for (int foo
= 0; foo
< 2 && !found_debit
; foo
++) {
1820 if (!select_and_auth(key
, mac
, div_key
, false, use_elite
, use_raw
, false))
1824 PrintAndLog("\n--------------------------------------------------------");
1825 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key
, 8));
1829 // credit key. try twice
1830 for (int foo
= 0; foo
< 2 && !found_credit
; foo
++) {
1831 if (!select_and_auth(key
, mac
, div_key
, true, use_elite
, use_raw
, false))
1835 PrintAndLog("\n--------------------------------------------------------");
1836 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key
, 8));
1837 found_credit
= true;
1841 if ( found_debit
&& found_credit
)
1845 t1
= msclock() - t1
;
1847 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1
/1000.0);
1855 static command_t CommandTable
[] =
1857 {"help", CmdHelp
, 1, "This help"},
1858 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1859 {"chk", CmdHFiClassCheckKeys
, 0, " Check keys"},
1860 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1861 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1862 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1863 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1864 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1865 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1866 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1867 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1868 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1869 {"reader", CmdHFiClassReader
, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1870 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1871 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1872 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1873 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1874 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1875 {NULL
, NULL
, 0, NULL
}
1878 int CmdHFiClass(const char *Cmd
)
1880 clearCommandBuffer();
1881 CmdsParse(CommandTable
, Cmd
);
1885 int CmdHelp(const char *Cmd
)
1887 CmdsHelp(CommandTable
);