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
20 #include "proxmark3.h"
22 #include "cmdparser.h"
23 #include "cmdhficlass.h"
27 #include "polarssl/des.h"
28 #include "loclass/cipherutils.h"
29 #include "loclass/cipher.h"
30 #include "loclass/ikeys.h"
31 #include "loclass/elite_crack.h"
32 #include "loclass/fileutils.h"
33 #include "protocols.h"
36 #include "util_posix.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 usage_hf_iclass_chk(void) {
57 PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");
58 PrintAndLog("Usage: hf iclass chk [h|e|r] <f (*.dic)>");
59 PrintAndLog("Options:");
60 PrintAndLog("h Show this help");
61 PrintAndLog("f <filename> Dictionary file with default iclass keys");
62 PrintAndLog(" e target Elite / High security key scheme");
63 PrintAndLog(" r interpret dictionary file as raw (diversified keys)");
64 PrintAndLog("Samples:");
65 PrintAndLog(" hf iclass chk f default_iclass_keys.dic");
66 PrintAndLog(" hf iclass chk f default_iclass_keys.dic e");
70 int xorbits_8(uint8_t val
) {
71 uint8_t res
= val
^ (val
>> 1); //1st pass
72 res
= res
^ (res
>> 1); // 2nd pass
73 res
= res
^ (res
>> 2); // 3rd pass
74 res
= res
^ (res
>> 4); // 4th pass
78 int CmdHFiClassList(const char *Cmd
) {
79 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
83 int CmdHFiClassSnoop(const char *Cmd
) {
84 UsbCommand c
= {CMD_SNOOP_ICLASS
};
89 int usage_hf_iclass_sim(void) {
90 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
91 PrintAndLog(" options");
92 PrintAndLog(" 0 <CSN> simulate the given CSN");
93 PrintAndLog(" 1 simulate default CSN");
94 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
95 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
96 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
97 PrintAndLog(" example: hf iclass sim 2");
98 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
99 PrintAndLog(" hf iclass sim 3");
104 int CmdHFiClassSim(const char *Cmd
) {
106 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
109 return usage_hf_iclass_sim();
111 simType
= param_get8ex(Cmd
, 0, 0, 10);
115 if (param_gethex(Cmd
, 1, CSN
, 16)) {
116 PrintAndLog("A CSN should consist of 16 HEX symbols");
117 return usage_hf_iclass_sim();
120 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
124 PrintAndLog("Undefined simptype %d", simType
);
125 return usage_hf_iclass_sim();
128 uint8_t numberOfCSNs
=0;
131 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
132 UsbCommand resp
= {0};
134 uint8_t csns
[8*NUM_CSNS
] = {
135 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
136 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
137 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
138 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
139 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
140 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
141 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
142 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
143 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
144 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
145 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
146 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
147 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
148 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
149 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
151 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
154 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
155 PrintAndLog("Command timed out");
159 uint8_t num_mac_responses
= resp
.arg
[1];
160 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
162 size_t datalen
= NUM_CSNS
*24;
164 * Now, time to dump to file. We'll use this format:
165 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
166 * So, it should wind up as
169 * The returndata from the pm3 is on the following format
170 * <4 byte NR><4 byte MAC>
171 * CC are all zeroes, CSN is the same as was sent in
173 void* dump
= malloc(datalen
);
174 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
176 for(i
= 0 ; i
< NUM_CSNS
; i
++)
178 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
179 //8 zero bytes here...
180 //Then comes NR_MAC (eight bytes from the response)
181 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
184 /** Now, save to dumpfile **/
185 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
189 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
190 memcpy(c
.d
.asBytes
, CSN
, 8);
197 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
198 bool tagFound
= false;
199 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
200 FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_AA
|
201 FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
} };
202 // loop in client not device - else on windows have a communication error
206 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
207 uint8_t readStatus
= resp
.arg
[0] & 0xff;
208 uint8_t *data
= resp
.d
.asBytes
;
210 // no tag found or button pressed
211 if( (readStatus
== 0 && !loop
) || readStatus
== 0xFF) {
213 if (verbose
) PrintAndLog("Quitting...");
217 if( readStatus
& FLAG_ICLASS_READER_CSN
) {
218 PrintAndLog(" CSN: %s",sprint_hex(data
,8));
221 if( readStatus
& FLAG_ICLASS_READER_CC
) {
222 PrintAndLog(" CC: %s",sprint_hex(data
+16,8));
224 if( readStatus
& FLAG_ICLASS_READER_CONF
) {
225 printIclassDumpInfo(data
);
227 if (readStatus
& FLAG_ICLASS_READER_AA
) {
229 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*5,8));
230 for (int i
= 0; i
<8; i
++) {
231 if (data
[8*5+i
] != 0xFF) {
235 PrintAndLog(" : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)");
238 if (tagFound
&& !loop
) return 1;
240 if (verbose
) PrintAndLog("Command execute timeout");
247 int CmdHFiClassReader(const char *Cmd
) {
248 return HFiClassReader(Cmd
, true, true);
251 int CmdHFiClassReader_Replay(const char *Cmd
) {
252 uint8_t readerType
= 0;
253 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
256 PrintAndLog("Usage: hf iclass replay <MAC>");
257 PrintAndLog(" sample: hf iclass replay 00112233");
261 if (param_gethex(Cmd
, 0, MAC
, 8)) {
262 PrintAndLog("MAC must include 8 HEX symbols");
266 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
267 memcpy(c
.d
.asBytes
, MAC
, 4);
273 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
274 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
275 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
280 int hf_iclass_eload_usage(void) {
281 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
282 PrintAndLog("Usage: hf iclass eload f <filename>");
284 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
288 int CmdHFiClassELoad(const char *Cmd
) {
290 char opt
= param_getchar(Cmd
, 0);
291 if (strlen(Cmd
)<1 || opt
== 'h')
292 return hf_iclass_eload_usage();
294 //File handling and reading
296 char filename
[FILE_PATH_SIZE
];
297 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0)
299 f
= fopen(filename
, "rb");
301 return hf_iclass_eload_usage();
305 PrintAndLog("Failed to read from file '%s'", filename
);
309 fseek(f
, 0, SEEK_END
);
310 long fsize
= ftell(f
);
311 fseek(f
, 0, SEEK_SET
);
314 PrintAndLog("Error, when getting filesize");
319 uint8_t *dump
= malloc(fsize
);
321 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
324 printIclassDumpInfo(dump
);
327 if (bytes_read
< fsize
)
329 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
334 uint32_t bytes_sent
= 0;
335 uint32_t bytes_remaining
= bytes_read
;
337 while(bytes_remaining
> 0){
338 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
339 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
340 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
342 bytes_remaining
-= bytes_in_packet
;
343 bytes_sent
+= bytes_in_packet
;
346 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
350 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
351 FILE *f
= fopen(filename
, "rb");
353 PrintAndLog("Failed to read from file '%s'", filename
);
356 fseek(f
, 0, SEEK_END
);
357 long fsize
= ftell(f
);
358 fseek(f
, 0, SEEK_SET
);
359 size_t bytes_read
= fread(buffer
, 1, len
, f
);
363 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
366 if(bytes_read
!= len
)
368 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
374 int usage_hf_iclass_decrypt(void) {
375 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
377 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
378 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
380 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
382 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
383 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
384 PrintAndLog("which is defined by the configuration block.");
388 int CmdHFiClassDecrypt(const char *Cmd
) {
389 uint8_t key
[16] = { 0 };
390 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
392 usage_hf_iclass_decrypt();
395 PrintAndLog("Decryption file found... ");
396 char opt
= param_getchar(Cmd
, 0);
397 if (strlen(Cmd
)<1 || opt
== 'h')
398 return usage_hf_iclass_decrypt();
400 //Open the tagdump-file
402 char filename
[FILE_PATH_SIZE
];
403 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) {
404 f
= fopen(filename
, "rb");
406 PrintAndLog("Could not find file %s", filename
);
410 return usage_hf_iclass_decrypt();
413 fseek(f
, 0, SEEK_END
);
414 long fsize
= ftell(f
);
415 fseek(f
, 0, SEEK_SET
);
416 uint8_t enc_dump
[8] = {0};
417 uint8_t *decrypted
= malloc(fsize
);
418 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
419 des3_set2key_dec( &ctx
, key
);
420 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
422 //Use the first block (CSN) for filename
423 char outfilename
[FILE_PATH_SIZE
] = { 0 };
424 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
425 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
426 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
429 while(bytes_read
== 8)
433 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
435 des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
437 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
438 bytes_read
= fread(enc_dump
, 1, 8, f
);
443 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
448 int usage_hf_iclass_encrypt(void) {
449 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
451 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
452 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
454 PrintAndLog("example: hf iclass encrypt 0102030405060708");
459 static int iClassEncryptBlkData(uint8_t *blkData
) {
460 uint8_t key
[16] = { 0 };
461 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
463 usage_hf_iclass_encrypt();
466 PrintAndLog("Decryption file found... ");
468 uint8_t encryptedData
[16];
469 uint8_t *encrypted
= encryptedData
;
470 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
471 des3_set2key_enc( &ctx
, key
);
473 des3_crypt_ecb(&ctx
, blkData
,encrypted
);
474 //printvar("decrypted block", decrypted, 8);
475 memcpy(blkData
,encrypted
,8);
480 int CmdHFiClassEncryptBlk(const char *Cmd
) {
481 uint8_t blkData
[8] = {0};
482 char opt
= param_getchar(Cmd
, 0);
483 if (strlen(Cmd
)<1 || opt
== 'h')
484 return usage_hf_iclass_encrypt();
486 //get the bytes to encrypt
487 if (param_gethex(Cmd
, 0, blkData
, 16))
489 PrintAndLog("BlockData must include 16 HEX symbols");
492 if (!iClassEncryptBlkData(blkData
)) return 0;
494 printvar("encrypted block", blkData
, 8);
498 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
501 memcpy(WB
+ 1,data
,8);
502 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
503 //printf("Cal wb mac block [%02x][%02x%02x%02x%02x%02x%02x%02x%02x] : MAC [%02x%02x%02x%02x]",WB[0],WB[1],WB[2],WB[3],WB[4],WB[5],WB[6],WB[7],WB[8],MAC[0],MAC[1],MAC[2],MAC[3]);
506 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
509 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
510 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
512 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
514 clearCommandBuffer();
516 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
518 PrintAndLog("Command execute timeout");
522 uint8_t isOK
= resp
.arg
[0] & 0xff;
523 uint8_t *data
= resp
.d
.asBytes
;
526 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
529 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
532 PrintAndLog("Failed to obtain CC! Aborting");
538 static bool select_and_auth(uint8_t *KEY
, uint8_t *MAC
, uint8_t *div_key
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
539 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
540 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
542 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
547 memcpy(div_key
, KEY
, 8);
549 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
550 if (verbose
) PrintAndLog("Authing with %s: %02x%02x%02x%02x%02x%02x%02x%02x", rawkey
? "raw key" : "diversified key", div_key
[0],div_key
[1],div_key
[2],div_key
[3],div_key
[4],div_key
[5],div_key
[6],div_key
[7]);
552 doMAC(CCNR
, div_key
, MAC
);
554 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
555 memcpy(d
.d
.asBytes
, MAC
, 4);
556 clearCommandBuffer();
558 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
560 if (verbose
) PrintAndLog("Auth Command execute timeout");
563 uint8_t isOK
= resp
.arg
[0] & 0xff;
565 if (verbose
) PrintAndLog("Authentication error");
571 int usage_hf_iclass_dump(void) {
572 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
573 PrintAndLog("Options:");
574 PrintAndLog(" f <filename> : specify a filename to save dump to");
575 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
576 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
577 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
578 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
579 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
580 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
581 PrintAndLog(" NOTE: * = required");
582 PrintAndLog("Samples:");
583 PrintAndLog(" hf iclass dump k 001122334455667B");
584 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
585 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
589 int CmdHFiClassReader_Dump(const char *Cmd
) {
591 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
592 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
593 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
597 uint8_t app_areas
= 1;
599 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
600 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
603 uint8_t fileNameLen
= 0;
604 char filename
[FILE_PATH_SIZE
]={0};
605 char tempStr
[50] = {0};
606 bool have_debit_key
= false;
607 bool have_credit_key
= false;
608 bool use_credit_key
= false;
614 while(param_getchar(Cmd
, cmdp
) != 0x00)
616 switch(param_getchar(Cmd
, cmdp
))
620 return usage_hf_iclass_dump();
623 have_credit_key
= true;
624 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
626 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
627 } else if (dataLen
== 1) {
628 keyNbr
= param_get8(Cmd
, cmdp
+1);
629 if (keyNbr
< ICLASS_KEYS_MAX
) {
630 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
632 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
636 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
648 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
649 if (fileNameLen
< 1) {
650 PrintAndLog("No filename found after f");
657 have_debit_key
= true;
658 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
660 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
661 } else if (dataLen
== 1) {
662 keyNbr
= param_get8(Cmd
, cmdp
+1);
663 if (keyNbr
< ICLASS_KEYS_MAX
) {
664 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
666 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
670 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
681 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
685 if(errors
) return usage_hf_iclass_dump();
688 if (cmdp
< 2) return usage_hf_iclass_dump();
689 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
690 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
692 //get config and first 3 blocks
693 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
694 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
696 uint8_t tag_data
[255*8];
698 clearCommandBuffer();
700 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
701 PrintAndLog("Command execute timeout");
705 uint8_t readStatus
= resp
.arg
[0] & 0xff;
706 uint8_t *data
= resp
.d
.asBytes
;
709 PrintAndLog("No tag found...");
713 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
714 memcpy(tag_data
, data
, 8*3);
715 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
717 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
718 // large memory - not able to dump pages currently
719 if (numblks
> maxBlk
) numblks
= maxBlk
;
722 // authenticate debit key and get div_key - later store in dump block 3
723 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
724 //try twice - for some reason it sometimes fails the first time...
725 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
732 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
733 clearCommandBuffer();
735 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
736 PrintAndLog("Command execute time-out 1");
740 uint32_t blocksRead
= resp
.arg
[1];
741 uint8_t isOK
= resp
.arg
[0] & 0xff;
742 if (!isOK
&& !blocksRead
) {
743 PrintAndLog("Read Block Failed");
747 uint32_t startindex
= resp
.arg
[2];
748 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
749 PrintAndLog("Data exceeded Buffer size!");
750 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
752 // response ok - now get bigbuf content of the dump
753 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
);
754 WaitForResponse(CMD_ACK
,NULL
);
755 size_t gotBytes
= blocksRead
*8 + blockno
*8;
758 if (have_credit_key
) {
759 //turn off hf field before authenticating with different key
762 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
763 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
764 //try twice - for some reason it sometimes fails the first time...
765 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
770 // do we still need to read more block? (aa2 enabled?)
771 if (maxBlk
> blockno
+numblks
+1) {
772 // setup dump and start
773 w
.arg
[0] = blockno
+ blocksRead
;
774 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
775 clearCommandBuffer();
777 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
778 PrintAndLog("Command execute timeout 2");
782 uint8_t isOK
= resp
.arg
[0] & 0xff;
783 blocksRead
= resp
.arg
[1];
784 if (!isOK
&& !blocksRead
) {
785 PrintAndLog("Read Block Failed 2");
790 startindex
= resp
.arg
[2];
791 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
792 PrintAndLog("Data exceeded Buffer size!");
793 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
795 // get dumped data from bigbuf
796 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
);
797 WaitForResponse(CMD_ACK
,NULL
);
799 gotBytes
+= blocksRead
*8;
800 } else { //field is still on - turn it off...
805 // add diversified keys to dump
806 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
807 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
809 printf("------+--+-------------------------+\n");
810 printf("CSN |00| %s|\n",sprint_hex(tag_data
, 8));
811 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
813 if (filename
[0] == 0){
814 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
815 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
816 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
819 // save the dump to .bin file
820 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
821 saveFile(filename
, "bin", tag_data
, gotBytes
);
825 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
826 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
827 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
828 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
833 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
834 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
835 memcpy(w
.d
.asBytes
, bldata
, 8);
836 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
838 clearCommandBuffer();
840 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
842 PrintAndLog("Write Command execute timeout");
845 uint8_t isOK
= resp
.arg
[0] & 0xff;
847 PrintAndLog("Write Block Failed");
850 PrintAndLog("Write Block Successful");
854 int usage_hf_iclass_writeblock(void) {
855 PrintAndLog("Options:");
856 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
857 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
858 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
859 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
860 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
861 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
862 PrintAndLog("Samples:");
863 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
864 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
865 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
869 int CmdHFiClass_WriteBlock(const char *Cmd
) {
871 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
872 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
875 char tempStr
[50] = {0};
876 bool use_credit_key
= false;
881 while(param_getchar(Cmd
, cmdp
) != 0x00)
883 switch(param_getchar(Cmd
, cmdp
))
887 return usage_hf_iclass_writeblock();
890 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
891 PrintAndLog("Block No must include 2 HEX symbols\n");
898 use_credit_key
= true;
903 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
905 PrintAndLog("KEY must include 16 HEX symbols\n");
917 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
919 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
920 } else if (dataLen
== 1) {
921 keyNbr
= param_get8(Cmd
, cmdp
+1);
922 if (keyNbr
< ICLASS_KEYS_MAX
) {
923 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
925 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
929 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
940 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
944 if(errors
) return usage_hf_iclass_writeblock();
947 if (cmdp
< 6) return usage_hf_iclass_writeblock();
948 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
953 int usage_hf_iclass_clone(void) {
954 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
955 PrintAndLog("Options:");
956 PrintAndLog(" f <filename>: specify a filename to clone from");
957 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
958 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
959 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
960 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
961 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
962 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
963 PrintAndLog("Samples:");
964 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
965 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
966 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
970 int CmdHFiClassCloneTag(const char *Cmd
) {
971 char filename
[FILE_PATH_SIZE
] = {0};
972 char tempStr
[50]={0};
973 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
975 uint8_t fileNameLen
= 0;
976 uint8_t startblock
= 0;
977 uint8_t endblock
= 0;
979 bool use_credit_key
= false;
984 while(param_getchar(Cmd
, cmdp
) != 0x00)
986 switch(param_getchar(Cmd
, cmdp
))
990 return usage_hf_iclass_clone();
993 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
994 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1001 use_credit_key
= true;
1011 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1012 if (fileNameLen
< 1) {
1013 PrintAndLog("No filename found after f");
1020 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1021 if (dataLen
== 16) {
1022 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1023 } else if (dataLen
== 1) {
1024 keyNbr
= param_get8(Cmd
, cmdp
+1);
1025 if (keyNbr
< ICLASS_KEYS_MAX
) {
1026 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1028 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1032 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1039 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1040 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1051 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1055 if(errors
) return usage_hf_iclass_clone();
1058 if (cmdp
< 8) return usage_hf_iclass_clone();
1062 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1064 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1065 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1067 // file handling and reading
1068 f
= fopen(filename
,"rb");
1070 PrintAndLog("Failed to read from file '%s'", filename
);
1075 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1079 // now read data from the file from block 6 --- 19
1080 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1081 // 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,
1082 // else we have to create a share memory
1084 fseek(f
,startblock
*8,SEEK_SET
);
1085 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1086 PrintAndLog("File reading error.");
1091 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1092 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1094 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1097 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1099 // calculate all mac for every the block we will write
1100 for (i
= startblock
; i
<= endblock
; i
++){
1101 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1102 // usb command d start pointer = d + (i - 6) * 12
1103 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1104 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1106 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1107 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1108 memcpy(ptr
+ 8,MAC
, 4);
1111 for (i
= 0; i
<= endblock
- startblock
;i
++){
1112 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1113 printf("Block |%02x|",i
+ startblock
);
1114 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]);
1115 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1119 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1121 PrintAndLog("Command execute timeout");
1127 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) {
1128 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1129 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1132 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1135 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1136 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1137 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
))
1142 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1143 clearCommandBuffer();
1145 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1147 PrintAndLog("Command execute timeout");
1150 uint8_t isOK
= resp
.arg
[0] & 0xff;
1152 PrintAndLog("Read Block Failed");
1155 //data read is stored in: resp.d.asBytes[0-15]
1156 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1160 int usage_hf_iclass_readblock(void) {
1161 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1162 PrintAndLog("Options:");
1163 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1164 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1165 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1166 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1167 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1168 PrintAndLog("Samples:");
1169 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1170 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1171 PrintAndLog(" hf iclass readblk b 0A k 0");
1175 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1177 uint8_t keyType
= 0x88; //debit key
1178 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1180 uint8_t dataLen
= 0;
1181 char tempStr
[50] = {0};
1183 bool rawkey
= false;
1184 bool errors
= false;
1187 while(param_getchar(Cmd
, cmdp
) != 0x00)
1189 switch(param_getchar(Cmd
, cmdp
))
1193 return usage_hf_iclass_readblock();
1196 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1197 PrintAndLog("Block No must include 2 HEX symbols\n");
1215 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1216 if (dataLen
== 16) {
1217 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1218 } else if (dataLen
== 1) {
1219 keyNbr
= param_get8(Cmd
, cmdp
+1);
1220 if (keyNbr
< ICLASS_KEYS_MAX
) {
1221 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1223 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1227 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1238 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1242 if(errors
) return usage_hf_iclass_readblock();
1245 if (cmdp
< 2) return usage_hf_iclass_readblock();
1247 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1248 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
);
1251 int CmdHFiClass_loclass(const char *Cmd
) {
1252 char opt
= param_getchar(Cmd
, 0);
1254 if (strlen(Cmd
)<1 || opt
== 'h') {
1255 PrintAndLog("Usage: hf iclass loclass [options]");
1256 PrintAndLog("Options:");
1257 PrintAndLog("h Show this help");
1258 PrintAndLog("t Perform self-test");
1259 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1260 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1261 PrintAndLog(" malicious CSNs, and their protocol responses");
1262 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1263 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1264 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1265 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1266 PrintAndLog(" ... totalling N*24 bytes");
1269 char fileName
[255] = {0};
1272 if(param_getstr(Cmd
, 1, fileName
, sizeof(fileName
)) > 0)
1274 return bruteforceFileNoKeys(fileName
);
1277 PrintAndLog("You must specify a filename");
1282 int errors
= testCipherUtils();
1283 errors
+= testMAC();
1284 errors
+= doKeyTests(0);
1285 errors
+= testElite();
1288 prnlog("OBS! There were errors!!!");
1296 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1298 memcpy(&mem_config
, iclass_dump
+ 13,1);
1299 uint8_t maxmemcount
;
1300 uint8_t filemaxblock
= filesize
/ 8;
1301 if (mem_config
& 0x80)
1305 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1307 if (startblock
== 0)
1309 if ((endblock
> maxmemcount
) || (endblock
== 0))
1310 endblock
= maxmemcount
;
1312 // remember endblock need to relate to zero-index arrays.
1313 if (endblock
> filemaxblock
-1)
1314 endblock
= filemaxblock
;
1317 printf("------+--+-------------------------+\n");
1318 while (i
<= endblock
) {
1319 uint8_t *blk
= iclass_dump
+ (i
* 8);
1320 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );
1323 printf("------+--+-------------------------+\n");
1326 int usage_hf_iclass_readtagfile() {
1327 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1331 int CmdHFiClassReadTagFile(const char *Cmd
) {
1336 char filename
[FILE_PATH_SIZE
];
1337 if (param_getstr(Cmd
, 0, filename
, sizeof(filename
)) < 1)
1338 return usage_hf_iclass_readtagfile();
1339 if (param_getstr(Cmd
, 1, tempnum
, sizeof(tempnum
)) < 1)
1342 sscanf(tempnum
,"%d",&startblock
);
1344 if (param_getstr(Cmd
,2, tempnum
, sizeof(tempnum
)) < 1)
1347 sscanf(tempnum
,"%d",&endblock
);
1348 // file handling and reading
1349 f
= fopen(filename
,"rb");
1351 PrintAndLog("Failed to read from file '%s'", filename
);
1354 fseek(f
, 0, SEEK_END
);
1355 long fsize
= ftell(f
);
1356 fseek(f
, 0, SEEK_SET
);
1359 PrintAndLog("Error, when getting filesize");
1364 uint8_t *dump
= malloc(fsize
);
1366 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1368 uint8_t *csn
= dump
;
1369 printf("------+--+-------------------------+\n");
1370 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1371 // printIclassDumpInfo(dump);
1372 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1378 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1379 uint64_t new_div = 0x00;
1385 uint64_t hexarray_to_uint64(uint8_t *key) {
1388 for (int i = 0;i < 8;i++)
1389 sprintf(&temp[(i *2)],"%02X",key[i]);
1391 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1396 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1397 uint8_t keytable
[128] = {0};
1398 uint8_t key_index
[8] = {0};
1400 uint8_t key_sel
[8] = { 0 };
1401 uint8_t key_sel_p
[8] = { 0 };
1402 hash2(KEY
, keytable
);
1403 hash1(CSN
, key_index
);
1404 for(uint8_t i
= 0; i
< 8 ; i
++)
1405 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1407 //Permute from iclass format to standard format
1408 permutekey_rev(key_sel
, key_sel_p
);
1409 diversifyKey(CSN
, key_sel_p
, div_key
);
1411 diversifyKey(CSN
, KEY
, div_key
);
1415 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1416 //calculate and return xor_div_key (ready for a key write command)
1417 //print all div_keys if verbose
1418 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1419 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1420 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1422 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1424 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1426 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1427 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1430 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1431 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1432 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1436 int usage_hf_iclass_calc_newkey(void) {
1437 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1438 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1439 PrintAndLog(" Options:");
1440 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1441 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1442 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1443 PrintAndLog(" e : specify new key as elite calc");
1444 PrintAndLog(" ee : specify old and new key as elite calc");
1445 PrintAndLog("Samples:");
1446 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1447 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1448 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1449 PrintAndLog("NOTE: * = required\n");
1454 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1455 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1456 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1457 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1458 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1459 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1461 uint8_t dataLen
= 0;
1462 char tempStr
[50] = {0};
1463 bool givenCSN
= false;
1464 bool oldElite
= false;
1466 bool errors
= false;
1468 while(param_getchar(Cmd
, cmdp
) != 0x00)
1470 switch(param_getchar(Cmd
, cmdp
))
1474 return usage_hf_iclass_calc_newkey();
1477 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
, sizeof(tempStr
));
1485 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1486 if (dataLen
== 16) {
1487 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1488 } else if (dataLen
== 1) {
1489 keyNbr
= param_get8(Cmd
, cmdp
+1);
1490 if (keyNbr
< ICLASS_KEYS_MAX
) {
1491 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1493 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1497 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1504 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1505 if (dataLen
== 16) {
1506 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1507 } else if (dataLen
== 1) {
1508 keyNbr
= param_get8(Cmd
, cmdp
+1);
1509 if (keyNbr
< ICLASS_KEYS_MAX
) {
1510 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1512 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1516 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1524 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1525 return usage_hf_iclass_calc_newkey();
1529 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1533 if(errors
) return usage_hf_iclass_calc_newkey();
1536 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1539 if (!select_only(CSN
, CCNR
, false, true))
1542 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1546 static int loadKeys(char *filename
) {
1548 f
= fopen(filename
,"rb");
1550 PrintAndLog("Failed to read from file '%s'", filename
);
1553 fseek(f
, 0, SEEK_END
);
1554 long fsize
= ftell(f
);
1555 fseek(f
, 0, SEEK_SET
);
1558 PrintAndLog("Error, when getting filesize");
1563 uint8_t *dump
= malloc(fsize
);
1565 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1567 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1568 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1573 for (; i
< bytes_read
/8; i
++){
1574 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1577 PrintAndLog("%u keys loaded", i
);
1581 static int saveKeys(char *filename
) {
1583 f
= fopen(filename
,"wb");
1585 printf("error opening file %s\n",filename
);
1588 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1589 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1590 PrintAndLog("save key failed to write to file: %s", filename
);
1598 static int printKeys(void) {
1600 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1601 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1607 int usage_hf_iclass_managekeys(void) {
1608 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1609 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1610 PrintAndLog(" Options:");
1611 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1612 PrintAndLog(" k <key> : set a key in memory");
1613 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1614 PrintAndLog(" s : save keys in memory to file specified by filename");
1615 PrintAndLog(" l : load keys to memory from file specified by filename");
1616 PrintAndLog(" p : print keys loaded into memory\n");
1617 PrintAndLog("Samples:");
1618 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1619 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1620 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1621 PrintAndLog(" print keys : hf iclass managekeys p\n");
1625 int CmdHFiClassManageKeys(const char *Cmd
) {
1627 uint8_t dataLen
= 0;
1628 uint8_t KEY
[8] = {0};
1629 char filename
[FILE_PATH_SIZE
];
1630 uint8_t fileNameLen
= 0;
1631 bool errors
= false;
1632 uint8_t operation
= 0;
1636 while(param_getchar(Cmd
, cmdp
) != 0x00)
1638 switch(param_getchar(Cmd
, cmdp
))
1642 return usage_hf_iclass_managekeys();
1645 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1646 if (fileNameLen
< 1) {
1647 PrintAndLog("No filename found after f");
1654 keyNbr
= param_get8(Cmd
, cmdp
+1);
1655 if (keyNbr
>= ICLASS_KEYS_MAX
) {
1656 PrintAndLog("Invalid block number");
1663 operation
+= 3; //set key
1664 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1665 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1666 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1668 PrintAndLog("\nERROR: Key is incorrect length\n");
1675 operation
+= 4; //print keys in memory
1680 operation
+= 5; //load keys from file
1685 operation
+= 6; //save keys to file
1689 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1693 if(errors
) return usage_hf_iclass_managekeys();
1695 if (operation
== 0){
1696 PrintAndLog("no operation specified (load, save, or print)\n");
1697 return usage_hf_iclass_managekeys();
1700 PrintAndLog("Too many operations specified\n");
1701 return usage_hf_iclass_managekeys();
1703 if (operation
> 4 && fileNameLen
== 0){
1704 PrintAndLog("You must enter a filename when loading or saving\n");
1705 return usage_hf_iclass_managekeys();
1709 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1710 case 4: return printKeys();
1711 case 5: return loadKeys(filename
);
1712 case 6: return saveKeys(filename
);
1718 int CmdHFiClassCheckKeys(const char *Cmd
) {
1720 uint8_t mac
[4] = {0x00,0x00,0x00,0x00};
1721 uint8_t key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1722 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1724 // elite key, raw key, standard key
1725 bool use_elite
= false;
1726 bool use_raw
= false;
1727 bool found_debit
= false;
1728 bool found_credit
= false;
1729 bool errors
= false;
1730 uint8_t cmdp
= 0x00;
1732 char filename
[FILE_PATH_SIZE
] = {0};
1733 uint8_t fileNameLen
= 0;
1735 uint8_t *keyBlock
= NULL
, *p
;
1736 int keyitems
= 0, keycnt
= 0;
1738 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
1739 switch (param_getchar(Cmd
, cmdp
)) {
1742 return usage_hf_iclass_chk();
1745 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1746 if (fileNameLen
< 1) {
1747 PrintAndLog("No filename found after f");
1763 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1768 if (errors
) return usage_hf_iclass_chk();
1770 if ( !(f
= fopen( filename
, "r")) ) {
1771 PrintAndLog("File: %s: not found or locked.", filename
);
1775 while( fgets(buf
, sizeof(buf
), f
) ){
1776 if (strlen(buf
) < 16 || buf
[15] == '\n')
1779 while (fgetc(f
) != '\n' && !feof(f
)) ; //goto next line
1781 if( buf
[0]=='#' ) continue; //The line start with # is comment, skip
1783 if (!isxdigit(buf
[0])){
1784 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf
);
1790 p
= realloc(keyBlock
, 8 * (keyitems
+= 64));
1792 PrintAndLog("Cannot allocate memory for default keys");
1799 memset(keyBlock
+ 8 * keycnt
, 0, 8);
1800 num_to_bytes(strtoull(buf
, NULL
, 16), 8, keyBlock
+ 8 * keycnt
);
1802 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1804 memset(buf
, 0, sizeof(buf
));
1807 PrintAndLog("Loaded %2d keys from %s", keycnt
, filename
);
1810 uint64_t t1
= msclock();
1812 for (uint32_t c
= 0; c
< keycnt
; c
+= 1) {
1813 printf("."); fflush(stdout
);
1815 int gc
= getchar(); (void)gc
;
1816 printf("\naborted via keyboard!\n");
1820 memcpy(key
, keyBlock
+ 8 * c
, 8);
1822 // debit key. try twice
1823 for (int foo
= 0; foo
< 2 && !found_debit
; foo
++) {
1824 if (!select_and_auth(key
, mac
, div_key
, false, use_elite
, use_raw
, false))
1828 PrintAndLog("\n--------------------------------------------------------");
1829 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key
, 8));
1833 // credit key. try twice
1834 for (int foo
= 0; foo
< 2 && !found_credit
; foo
++) {
1835 if (!select_and_auth(key
, mac
, div_key
, true, use_elite
, use_raw
, false))
1839 PrintAndLog("\n--------------------------------------------------------");
1840 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key
, 8));
1841 found_credit
= true;
1845 if ( found_debit
&& found_credit
)
1849 t1
= msclock() - t1
;
1851 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1
/1000.0);
1859 static command_t CommandTable
[] =
1861 {"help", CmdHelp
, 1, "This help"},
1862 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1863 {"chk", CmdHFiClassCheckKeys
, 0, " Check keys"},
1864 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1865 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1866 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1867 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1868 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1869 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1870 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1871 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1872 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1873 {"reader", CmdHFiClassReader
, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1874 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1875 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1876 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1877 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1878 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1879 {NULL
, NULL
, 0, NULL
}
1882 int CmdHFiClass(const char *Cmd
)
1884 clearCommandBuffer();
1885 CmdsParse(CommandTable
, Cmd
);
1889 int CmdHelp(const char *Cmd
)
1891 CmdsHelp(CommandTable
);