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 //-----------------------------------------------------------------------------
17 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
19 #include "proxmark3.h"
21 #include "cmdparser.h"
22 #include "cmdhficlass.h"
26 #include "loclass/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"
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 xorbits_8(uint8_t val
) {
57 uint8_t res
= val
^ (val
>> 1); //1st pass
58 res
= res
^ (res
>> 1); // 2nd pass
59 res
= res
^ (res
>> 2); // 3rd pass
60 res
= res
^ (res
>> 4); // 4th pass
64 int CmdHFiClassList(const char *Cmd
) {
65 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
69 int CmdHFiClassSnoop(const char *Cmd
) {
70 UsbCommand c
= {CMD_SNOOP_ICLASS
};
75 int usage_hf_iclass_sim(void) {
76 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
77 PrintAndLog(" options");
78 PrintAndLog(" 0 <CSN> simulate the given CSN");
79 PrintAndLog(" 1 simulate default CSN");
80 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
81 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
82 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
83 PrintAndLog(" example: hf iclass sim 2");
84 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
85 PrintAndLog(" hf iclass sim 3");
90 int CmdHFiClassSim(const char *Cmd
) {
92 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
95 return usage_hf_iclass_sim();
97 simType
= param_get8ex(Cmd
, 0, 0, 10);
101 if (param_gethex(Cmd
, 1, CSN
, 16)) {
102 PrintAndLog("A CSN should consist of 16 HEX symbols");
103 return usage_hf_iclass_sim();
106 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
110 PrintAndLog("Undefined simptype %d", simType
);
111 return usage_hf_iclass_sim();
114 uint8_t numberOfCSNs
=0;
117 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
118 UsbCommand resp
= {0};
120 uint8_t csns
[8*NUM_CSNS
] = {
121 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
122 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
123 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
124 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
125 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
126 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
127 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
128 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
129 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
130 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
131 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
132 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
133 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
134 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
135 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
137 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
140 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
141 PrintAndLog("Command timed out");
145 uint8_t num_mac_responses
= resp
.arg
[1];
146 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
148 size_t datalen
= NUM_CSNS
*24;
150 * Now, time to dump to file. We'll use this format:
151 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
152 * So, it should wind up as
155 * The returndata from the pm3 is on the following format
156 * <4 byte NR><4 byte MAC>
157 * CC are all zeroes, CSN is the same as was sent in
159 void* dump
= malloc(datalen
);
160 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
162 for(i
= 0 ; i
< NUM_CSNS
; i
++)
164 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
165 //8 zero bytes here...
166 //Then comes NR_MAC (eight bytes from the response)
167 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
170 /** Now, save to dumpfile **/
171 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
175 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
176 memcpy(c
.d
.asBytes
, CSN
, 8);
183 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
184 bool tagFound
= false;
185 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
186 FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_AA
}};
187 // loop in client not device - else on windows have a communication error
188 c
.arg
[0] |= FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
;
192 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
193 uint8_t readStatus
= resp
.arg
[0] & 0xff;
194 uint8_t *data
= resp
.d
.asBytes
;
197 PrintAndLog("Readstatus:%02x", readStatus
);
198 if( readStatus
== 0){
200 if (verbose
) PrintAndLog("Quitting...");
203 if( readStatus
& FLAG_ICLASS_READER_CSN
){
204 PrintAndLog("CSN: %s",sprint_hex(data
,8));
207 if( readStatus
& FLAG_ICLASS_READER_CC
) PrintAndLog("CC: %s",sprint_hex(data
+16,8));
208 if( readStatus
& FLAG_ICLASS_READER_CONF
){
209 printIclassDumpInfo(data
);
211 if (tagFound
&& !loop
) return 1;
213 if (verbose
) PrintAndLog("Command execute timeout");
220 int CmdHFiClassReader(const char *Cmd
) {
221 return HFiClassReader(Cmd
, true, true);
224 int CmdHFiClassReader_Replay(const char *Cmd
) {
225 uint8_t readerType
= 0;
226 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
229 PrintAndLog("Usage: hf iclass replay <MAC>");
230 PrintAndLog(" sample: hf iclass replay 00112233");
234 if (param_gethex(Cmd
, 0, MAC
, 8)) {
235 PrintAndLog("MAC must include 8 HEX symbols");
239 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
240 memcpy(c
.d
.asBytes
, MAC
, 4);
246 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
247 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
248 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
253 int hf_iclass_eload_usage(void) {
254 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
255 PrintAndLog("Usage: hf iclass eload f <filename>");
257 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
261 int CmdHFiClassELoad(const char *Cmd
) {
263 char opt
= param_getchar(Cmd
, 0);
264 if (strlen(Cmd
)<1 || opt
== 'h')
265 return hf_iclass_eload_usage();
267 //File handling and reading
269 char filename
[FILE_PATH_SIZE
];
270 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0)
272 f
= fopen(filename
, "rb");
274 return hf_iclass_eload_usage();
278 PrintAndLog("Failed to read from file '%s'", filename
);
282 fseek(f
, 0, SEEK_END
);
283 long fsize
= ftell(f
);
284 fseek(f
, 0, SEEK_SET
);
287 PrintAndLog("Error, when getting filesize");
292 uint8_t *dump
= malloc(fsize
);
294 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
297 printIclassDumpInfo(dump
);
300 if (bytes_read
< fsize
)
302 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
307 uint32_t bytes_sent
= 0;
308 uint32_t bytes_remaining
= bytes_read
;
310 while(bytes_remaining
> 0){
311 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
312 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
313 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
315 bytes_remaining
-= bytes_in_packet
;
316 bytes_sent
+= bytes_in_packet
;
319 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
323 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
324 FILE *f
= fopen(filename
, "rb");
326 PrintAndLog("Failed to read from file '%s'", filename
);
329 fseek(f
, 0, SEEK_END
);
330 long fsize
= ftell(f
);
331 fseek(f
, 0, SEEK_SET
);
332 size_t bytes_read
= fread(buffer
, 1, len
, f
);
336 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
339 if(bytes_read
!= len
)
341 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
347 int usage_hf_iclass_decrypt(void) {
348 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
350 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
351 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
353 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
355 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
356 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
357 PrintAndLog("which is defined by the configuration block.");
361 int CmdHFiClassDecrypt(const char *Cmd
) {
362 uint8_t key
[16] = { 0 };
363 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
365 usage_hf_iclass_decrypt();
368 PrintAndLog("Decryption file found... ");
369 char opt
= param_getchar(Cmd
, 0);
370 if (strlen(Cmd
)<1 || opt
== 'h')
371 return usage_hf_iclass_decrypt();
373 //Open the tagdump-file
375 char filename
[FILE_PATH_SIZE
];
376 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0)
378 f
= fopen(filename
, "rb");
380 return usage_hf_iclass_decrypt();
383 fseek(f
, 0, SEEK_END
);
384 long fsize
= ftell(f
);
385 fseek(f
, 0, SEEK_SET
);
386 uint8_t enc_dump
[8] = {0};
387 uint8_t *decrypted
= malloc(fsize
);
388 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
389 des3_set2key_dec( &ctx
, key
);
390 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
392 //Use the first block (CSN) for filename
393 char outfilename
[FILE_PATH_SIZE
] = { 0 };
394 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
395 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
396 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
399 while(bytes_read
== 8)
403 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
405 des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
407 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
408 bytes_read
= fread(enc_dump
, 1, 8, f
);
413 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
418 int usage_hf_iclass_encrypt(void) {
419 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
421 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
422 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
424 PrintAndLog("example: hf iclass encrypt 0102030405060708");
429 static int iClassEncryptBlkData(uint8_t *blkData
) {
430 uint8_t key
[16] = { 0 };
431 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
433 usage_hf_iclass_encrypt();
436 PrintAndLog("Decryption file found... ");
438 uint8_t encryptedData
[16];
439 uint8_t *encrypted
= encryptedData
;
440 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
441 des3_set2key_enc( &ctx
, key
);
443 des3_crypt_ecb(&ctx
, blkData
,encrypted
);
444 //printvar("decrypted block", decrypted, 8);
445 memcpy(blkData
,encrypted
,8);
450 int CmdHFiClassEncryptBlk(const char *Cmd
) {
451 uint8_t blkData
[8] = {0};
452 char opt
= param_getchar(Cmd
, 0);
453 if (strlen(Cmd
)<1 || opt
== 'h')
454 return usage_hf_iclass_encrypt();
456 //get the bytes to encrypt
457 if (param_gethex(Cmd
, 0, blkData
, 16))
459 PrintAndLog("BlockData must include 16 HEX symbols");
462 if (!iClassEncryptBlkData(blkData
)) return 0;
464 printvar("encrypted block", blkData
, 8);
468 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
471 memcpy(WB
+ 1,data
,8);
472 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
473 //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]);
476 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
479 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
480 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
482 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
484 clearCommandBuffer();
486 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
488 PrintAndLog("Command execute timeout");
492 uint8_t isOK
= resp
.arg
[0] & 0xff;
493 uint8_t *data
= resp
.d
.asBytes
;
496 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
499 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
502 PrintAndLog("Failed to obtain CC! Aborting");
508 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
) {
509 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
510 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
512 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
517 memcpy(div_key
, KEY
, 8);
519 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
520 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]);
522 doMAC(CCNR
, div_key
, MAC
);
524 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
525 memcpy(d
.d
.asBytes
, MAC
, 4);
526 clearCommandBuffer();
528 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
530 PrintAndLog("Auth Command execute timeout");
533 uint8_t isOK
= resp
.arg
[0] & 0xff;
535 PrintAndLog("Authentication error");
541 int usage_hf_iclass_dump(void) {
542 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
543 PrintAndLog("Options:");
544 PrintAndLog(" f <filename> : specify a filename to save dump to");
545 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
546 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
547 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
548 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
549 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
550 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
551 PrintAndLog(" NOTE: * = required");
552 PrintAndLog("Samples:");
553 PrintAndLog(" hf iclass dump k 001122334455667B");
554 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
555 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
559 int CmdHFiClassReader_Dump(const char *Cmd
) {
561 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
562 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
563 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
567 uint8_t app_areas
= 1;
569 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
570 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
573 uint8_t fileNameLen
= 0;
574 char filename
[FILE_PATH_SIZE
]={0};
575 char tempStr
[50] = {0};
576 bool have_debit_key
= false;
577 bool have_credit_key
= false;
578 bool use_credit_key
= false;
584 while(param_getchar(Cmd
, cmdp
) != 0x00)
586 switch(param_getchar(Cmd
, cmdp
))
590 return usage_hf_iclass_dump();
593 have_credit_key
= true;
594 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
596 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
597 } else if (dataLen
== 1) {
598 keyNbr
= param_get8(Cmd
, cmdp
+1);
599 if (keyNbr
<= ICLASS_KEYS_MAX
) {
600 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
602 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
606 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
618 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
619 if (fileNameLen
< 1) {
620 PrintAndLog("No filename found after f");
627 have_debit_key
= true;
628 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
630 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
631 } else if (dataLen
== 1) {
632 keyNbr
= param_get8(Cmd
, cmdp
+1);
633 if (keyNbr
<= ICLASS_KEYS_MAX
) {
634 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
636 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
640 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
651 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
655 if(errors
) return usage_hf_iclass_dump();
658 if (cmdp
< 2) return usage_hf_iclass_dump();
659 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
660 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
662 //get config and first 3 blocks
663 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
664 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
666 uint8_t tag_data
[255*8];
668 clearCommandBuffer();
670 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
671 PrintAndLog("Command execute timeout");
672 ul_switch_off_field();
675 uint8_t readStatus
= resp
.arg
[0] & 0xff;
676 uint8_t *data
= resp
.d
.asBytes
;
679 PrintAndLog("No tag found...");
680 ul_switch_off_field();
683 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
684 memcpy(tag_data
, data
, 8*3);
685 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
687 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
688 // large memory - not able to dump pages currently
689 if (numblks
> maxBlk
) numblks
= maxBlk
;
691 ul_switch_off_field();
692 // authenticate debit key and get div_key - later store in dump block 3
693 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
694 //try twice - for some reason it sometimes fails the first time...
695 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
696 ul_switch_off_field();
702 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
703 clearCommandBuffer();
705 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
706 PrintAndLog("Command execute time-out 1");
707 ul_switch_off_field();
710 uint32_t blocksRead
= resp
.arg
[1];
711 uint8_t isOK
= resp
.arg
[0] & 0xff;
712 if (!isOK
&& !blocksRead
) {
713 PrintAndLog("Read Block Failed");
714 ul_switch_off_field();
717 uint32_t startindex
= resp
.arg
[2];
718 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
719 PrintAndLog("Data exceeded Buffer size!");
720 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
722 // response ok - now get bigbuf content of the dump
723 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
);
724 WaitForResponse(CMD_ACK
,NULL
);
725 size_t gotBytes
= blocksRead
*8 + blockno
*8;
728 if (have_credit_key
) {
729 //turn off hf field before authenticating with different key
730 ul_switch_off_field();
732 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
733 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
734 //try twice - for some reason it sometimes fails the first time...
735 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
736 ul_switch_off_field();
740 // do we still need to read more block? (aa2 enabled?)
741 if (maxBlk
> blockno
+numblks
+1) {
742 // setup dump and start
743 w
.arg
[0] = blockno
+ blocksRead
;
744 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
745 clearCommandBuffer();
747 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
748 PrintAndLog("Command execute timeout 2");
749 ul_switch_off_field();
752 uint8_t isOK
= resp
.arg
[0] & 0xff;
753 blocksRead
= resp
.arg
[1];
754 if (!isOK
&& !blocksRead
) {
755 PrintAndLog("Read Block Failed 2");
756 ul_switch_off_field();
760 startindex
= resp
.arg
[2];
761 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
762 PrintAndLog("Data exceeded Buffer size!");
763 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
765 // get dumped data from bigbuf
766 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
);
767 WaitForResponse(CMD_ACK
,NULL
);
769 gotBytes
+= blocksRead
*8;
770 } else { //field is still on - turn it off...
771 ul_switch_off_field();
775 // add diversified keys to dump
776 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
777 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
779 printf("CSN |00| %02X %02X %02X %02X %02X %02X %02X %02X |\n",tag_data
[0],tag_data
[1],tag_data
[2]
780 ,tag_data
[3],tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
781 printIclassDumpContents(tag_data
, 1, (gotBytes
/8)-1, gotBytes
-8);
783 if (filename
[0] == 0){
784 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
785 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
786 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
789 // save the dump to .bin file
790 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
791 saveFile(filename
, "bin", tag_data
, gotBytes
);
795 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
796 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
797 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
798 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
803 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
804 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
805 memcpy(w
.d
.asBytes
, bldata
, 8);
806 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
808 clearCommandBuffer();
810 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
812 PrintAndLog("Write Command execute timeout");
815 uint8_t isOK
= resp
.arg
[0] & 0xff;
817 PrintAndLog("Write Block Failed");
820 PrintAndLog("Write Block Successful");
824 int usage_hf_iclass_writeblock(void) {
825 PrintAndLog("Options:");
826 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
827 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
828 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
829 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
830 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
831 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
832 PrintAndLog("Samples:");
833 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
834 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
835 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
839 int CmdHFiClass_WriteBlock(const char *Cmd
) {
841 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
842 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
845 char tempStr
[50] = {0};
846 bool use_credit_key
= false;
851 while(param_getchar(Cmd
, cmdp
) != 0x00)
853 switch(param_getchar(Cmd
, cmdp
))
857 return usage_hf_iclass_writeblock();
860 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
861 PrintAndLog("Block No must include 2 HEX symbols\n");
868 use_credit_key
= true;
873 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
875 PrintAndLog("KEY must include 16 HEX symbols\n");
887 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
889 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
890 } else if (dataLen
== 1) {
891 keyNbr
= param_get8(Cmd
, cmdp
+1);
892 if (keyNbr
<= ICLASS_KEYS_MAX
) {
893 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
895 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
899 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
910 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
914 if(errors
) return usage_hf_iclass_writeblock();
917 if (cmdp
< 6) return usage_hf_iclass_writeblock();
918 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
919 ul_switch_off_field();
923 int usage_hf_iclass_clone(void) {
924 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
925 PrintAndLog("Options:");
926 PrintAndLog(" f <filename>: specify a filename to clone from");
927 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
928 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
929 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
930 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
931 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
932 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
933 PrintAndLog("Samples:");
934 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
935 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
936 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
940 int CmdHFiClassCloneTag(const char *Cmd
) {
941 char filename
[FILE_PATH_SIZE
];
942 char tempStr
[50]={0};
943 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
945 uint8_t fileNameLen
= 0;
946 uint8_t startblock
= 0;
947 uint8_t endblock
= 0;
949 bool use_credit_key
= false;
954 while(param_getchar(Cmd
, cmdp
) != 0x00)
956 switch(param_getchar(Cmd
, cmdp
))
960 return usage_hf_iclass_clone();
963 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
964 PrintAndLog("Start Block No must include 2 HEX symbols\n");
971 use_credit_key
= true;
981 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
982 if (fileNameLen
< 1) {
983 PrintAndLog("No filename found after f");
990 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
992 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
993 } else if (dataLen
== 1) {
994 keyNbr
= param_get8(Cmd
, cmdp
+1);
995 if (keyNbr
<= ICLASS_KEYS_MAX
) {
996 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
998 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1002 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1009 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1010 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1021 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1025 if(errors
) return usage_hf_iclass_clone();
1028 if (cmdp
< 8) return usage_hf_iclass_clone();
1032 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1034 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1035 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1037 // file handling and reading
1038 f
= fopen(filename
,"rb");
1040 PrintAndLog("Failed to read from file '%s'", filename
);
1045 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1048 // now read data from the file from block 6 --- 19
1049 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1050 // 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,
1051 // else we have to create a share memory
1053 fseek(f
,startblock
*8,SEEK_SET
);
1054 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1055 PrintAndLog("File reading error.");
1060 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1061 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1063 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1066 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1068 // calculate all mac for every the block we will write
1069 for (i
= startblock
; i
<= endblock
; i
++){
1070 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1071 // usb command d start pointer = d + (i - 6) * 12
1072 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1073 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1075 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1076 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1077 memcpy(ptr
+ 8,MAC
, 4);
1080 for (i
= 0; i
<= endblock
- startblock
;i
++){
1081 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1082 printf("Block |%02x|",i
+ startblock
);
1083 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]);
1084 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1088 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1090 PrintAndLog("Command execute timeout");
1096 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
) {
1097 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1098 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1100 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1104 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1105 clearCommandBuffer();
1107 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1109 PrintAndLog("Command execute timeout");
1112 uint8_t isOK
= resp
.arg
[0] & 0xff;
1114 PrintAndLog("Read Block Failed");
1117 //data read is stored in: resp.d.asBytes[0-15]
1118 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1122 int usage_hf_iclass_readblock(void) {
1123 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1124 PrintAndLog("Options:");
1125 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1126 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1127 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1128 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1129 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1130 PrintAndLog("Samples:");
1131 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1132 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1133 PrintAndLog(" hf iclass readblk b 0A k 0");
1137 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1139 uint8_t keyType
= 0x88; //debit key
1140 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1142 uint8_t dataLen
= 0;
1143 char tempStr
[50] = {0};
1145 bool rawkey
= false;
1146 bool errors
= false;
1148 while(param_getchar(Cmd
, cmdp
) != 0x00)
1150 switch(param_getchar(Cmd
, cmdp
))
1154 return usage_hf_iclass_readblock();
1157 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1158 PrintAndLog("Block No must include 2 HEX symbols\n");
1175 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1176 if (dataLen
== 16) {
1177 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1178 } else if (dataLen
== 1) {
1179 keyNbr
= param_get8(Cmd
, cmdp
+1);
1180 if (keyNbr
<= ICLASS_KEYS_MAX
) {
1181 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1183 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1187 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1198 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1202 if(errors
) return usage_hf_iclass_readblock();
1205 if (cmdp
< 4) return usage_hf_iclass_readblock();
1207 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true);
1210 int CmdHFiClass_loclass(const char *Cmd
) {
1211 char opt
= param_getchar(Cmd
, 0);
1213 if (strlen(Cmd
)<1 || opt
== 'h') {
1214 PrintAndLog("Usage: hf iclass loclass [options]");
1215 PrintAndLog("Options:");
1216 PrintAndLog("h Show this help");
1217 PrintAndLog("t Perform self-test");
1218 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1219 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1220 PrintAndLog(" malicious CSNs, and their protocol responses");
1221 PrintAndLog(" The the binary format of the file is expected to be as follows: ");
1222 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1223 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1224 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1225 PrintAndLog(" ... totalling N*24 bytes");
1228 char fileName
[255] = {0};
1231 if(param_getstr(Cmd
, 1, fileName
) > 0)
1233 return bruteforceFileNoKeys(fileName
);
1236 PrintAndLog("You must specify a filename");
1241 int errors
= testCipherUtils();
1242 errors
+= testMAC();
1243 errors
+= doKeyTests(0);
1244 errors
+= testElite();
1247 prnlog("OBS! There were errors!!!");
1255 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1256 uint8_t blockdata
[8];
1258 memcpy(&mem_config
, iclass_dump
+ 13,1);
1259 uint8_t maxmemcount
;
1260 uint8_t filemaxblock
= filesize
/ 8;
1261 if (mem_config
& 0x80)
1265 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1267 if (startblock
== 0)
1269 if ((endblock
> maxmemcount
) || (endblock
== 0))
1270 endblock
= maxmemcount
;
1271 if (endblock
> filemaxblock
)
1272 endblock
= filemaxblock
;
1275 while (i
<= endblock
){
1276 printf("Block |%02X| ",i
);
1277 memcpy(blockdata
,iclass_dump
+ (i
* 8),8);
1278 for (j
= 0;j
< 8;j
++)
1279 printf("%02X ",blockdata
[j
]);
1285 int usage_hf_iclass_readtagfile() {
1286 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1290 int CmdHFiClassReadTagFile(const char *Cmd
) {
1295 char filename
[FILE_PATH_SIZE
];
1296 if (param_getstr(Cmd
, 0, filename
) < 1)
1297 return usage_hf_iclass_readtagfile();
1298 if (param_getstr(Cmd
,1,(char *)&tempnum
) < 1)
1301 sscanf(tempnum
,"%d",&startblock
);
1303 if (param_getstr(Cmd
,2,(char *)&tempnum
) < 1)
1306 sscanf(tempnum
,"%d",&endblock
);
1307 // file handling and reading
1308 f
= fopen(filename
,"rb");
1310 PrintAndLog("Failed to read from file '%s'", filename
);
1313 fseek(f
, 0, SEEK_END
);
1314 long fsize
= ftell(f
);
1315 fseek(f
, 0, SEEK_SET
);
1317 uint8_t *dump
= malloc(fsize
);
1320 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1322 uint8_t *csn
= dump
;
1323 printf("CSN [00] | %02X %02X %02X %02X %02X %02X %02X %02X |\n",csn
[0],csn
[1],csn
[2],csn
[3],csn
[4],csn
[5],csn
[6],csn
[7]);
1324 // printIclassDumpInfo(dump);
1325 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1331 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1332 uint64_t new_div = 0x00;
1338 uint64_t hexarray_to_uint64(uint8_t *key) {
1341 for (int i = 0;i < 8;i++)
1342 sprintf(&temp[(i *2)],"%02X",key[i]);
1344 if (sscanf(temp,"%016"llX,&uint_key) < 1)
1349 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1350 uint8_t keytable
[128] = {0};
1351 uint8_t key_index
[8] = {0};
1353 uint8_t key_sel
[8] = { 0 };
1354 uint8_t key_sel_p
[8] = { 0 };
1355 hash2(KEY
, keytable
);
1356 hash1(CSN
, key_index
);
1357 for(uint8_t i
= 0; i
< 8 ; i
++)
1358 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1360 //Permute from iclass format to standard format
1361 permutekey_rev(key_sel
, key_sel_p
);
1362 diversifyKey(CSN
, key_sel_p
, div_key
);
1364 diversifyKey(CSN
, KEY
, div_key
);
1368 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1369 //calculate and return xor_div_key (ready for a key write command)
1370 //print all div_keys if verbose
1371 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1372 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1373 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1375 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1377 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1379 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1380 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1383 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1384 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1385 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1389 int usage_hf_iclass_calc_newkey(void) {
1390 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1391 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1392 PrintAndLog(" Options:");
1393 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1394 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1395 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1396 PrintAndLog(" e : specify new key as elite calc");
1397 PrintAndLog(" ee : specify old and new key as elite calc");
1398 PrintAndLog("Samples:");
1399 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1400 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1401 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1402 PrintAndLog("NOTE: * = required\n");
1407 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1408 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1409 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1410 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1411 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1412 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1414 uint8_t dataLen
= 0;
1415 char tempStr
[50] = {0};
1416 bool givenCSN
= false;
1417 bool oldElite
= false;
1419 bool errors
= false;
1421 while(param_getchar(Cmd
, cmdp
) != 0x00)
1423 switch(param_getchar(Cmd
, cmdp
))
1427 return usage_hf_iclass_calc_newkey();
1430 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
);
1438 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1439 if (dataLen
== 16) {
1440 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1441 } else if (dataLen
== 1) {
1442 keyNbr
= param_get8(Cmd
, cmdp
+1);
1443 if (keyNbr
<= ICLASS_KEYS_MAX
) {
1444 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1446 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1450 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1457 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1458 if (dataLen
== 16) {
1459 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1460 } else if (dataLen
== 1) {
1461 keyNbr
= param_get8(Cmd
, cmdp
+1);
1462 if (keyNbr
<= ICLASS_KEYS_MAX
) {
1463 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1465 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1469 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1477 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1478 return usage_hf_iclass_calc_newkey();
1482 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1486 if(errors
) return usage_hf_iclass_calc_newkey();
1489 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1492 if (!select_only(CSN
, CCNR
, false, true))
1495 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1499 static int loadKeys(char *filename
) {
1501 f
= fopen(filename
,"rb");
1503 PrintAndLog("Failed to read from file '%s'", filename
);
1506 fseek(f
, 0, SEEK_END
);
1507 long fsize
= ftell(f
);
1508 fseek(f
, 0, SEEK_SET
);
1511 PrintAndLog("Error, when getting filesize");
1516 uint8_t *dump
= malloc(fsize
);
1518 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1520 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1521 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1526 for (; i
< bytes_read
/8; i
++){
1527 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1530 PrintAndLog("%u keys loaded", i
);
1534 static int saveKeys(char *filename
) {
1536 f
= fopen(filename
,"wb");
1538 printf("error opening file %s\n",filename
);
1541 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1542 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1543 PrintAndLog("save key failed to write to file: %s", filename
);
1551 static int printKeys(void) {
1553 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1554 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1560 int usage_hf_iclass_managekeys(void) {
1561 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1562 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1563 PrintAndLog(" Options:");
1564 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1565 PrintAndLog(" k <key> : set a key in memory");
1566 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1567 PrintAndLog(" s : save keys in memory to file specified by filename");
1568 PrintAndLog(" l : load keys to memory from file specified by filename");
1569 PrintAndLog(" p : print keys loaded into memory\n");
1570 PrintAndLog("Samples:");
1571 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1572 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1573 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1574 PrintAndLog(" print keys : hf iclass managekeys p\n");
1578 int CmdHFiClassManageKeys(const char *Cmd
) {
1580 uint8_t dataLen
= 0;
1581 uint8_t KEY
[8] = {0};
1582 char filename
[FILE_PATH_SIZE
];
1583 uint8_t fileNameLen
= 0;
1584 bool errors
= false;
1585 uint8_t operation
= 0;
1589 while(param_getchar(Cmd
, cmdp
) != 0x00)
1591 switch(param_getchar(Cmd
, cmdp
))
1595 return usage_hf_iclass_managekeys();
1598 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
1599 if (fileNameLen
< 1) {
1600 PrintAndLog("No filename found after f");
1607 keyNbr
= param_get8(Cmd
, cmdp
+1);
1609 PrintAndLog("Wrong block number");
1616 operation
+= 3; //set key
1617 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1618 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1619 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1621 PrintAndLog("\nERROR: Key is incorrect length\n");
1628 operation
+= 4; //print keys in memory
1633 operation
+= 5; //load keys from file
1638 operation
+= 6; //save keys to file
1642 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1646 if(errors
) return usage_hf_iclass_managekeys();
1648 if (operation
== 0){
1649 PrintAndLog("no operation specified (load, save, or print)\n");
1650 return usage_hf_iclass_managekeys();
1653 PrintAndLog("Too many operations specified\n");
1654 return usage_hf_iclass_managekeys();
1656 if (operation
> 4 && fileNameLen
== 0){
1657 PrintAndLog("You must enter a filename when loading or saving\n");
1658 return usage_hf_iclass_managekeys();
1662 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1663 case 4: return printKeys();
1664 case 5: return loadKeys(filename
);
1665 case 6: return saveKeys(filename
);
1671 static command_t CommandTable
[] =
1673 {"help", CmdHelp
, 1, "This help"},
1674 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1675 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1676 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1677 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1678 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1679 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1680 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1681 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1682 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1683 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1684 {"reader", CmdHFiClassReader
, 0, " Read an iClass tag"},
1685 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1686 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1687 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1688 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1689 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1690 {NULL
, NULL
, 0, NULL
}
1693 int CmdHFiClass(const char *Cmd
)
1695 CmdsParse(CommandTable
, Cmd
);
1699 int CmdHelp(const char *Cmd
)
1701 CmdsHelp(CommandTable
);