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("Usage: hf iclass chk [h] <f (*.dic)>");
58 PrintAndLog("Options:");
59 PrintAndLog("h Show this help");
60 PrintAndLog("f <filename> Dictionary file with default iclass keys");
64 int xorbits_8(uint8_t val
) {
65 uint8_t res
= val
^ (val
>> 1); //1st pass
66 res
= res
^ (res
>> 1); // 2nd pass
67 res
= res
^ (res
>> 2); // 3rd pass
68 res
= res
^ (res
>> 4); // 4th pass
72 int CmdHFiClassList(const char *Cmd
) {
73 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
77 int CmdHFiClassSnoop(const char *Cmd
) {
78 UsbCommand c
= {CMD_SNOOP_ICLASS
};
83 int usage_hf_iclass_sim(void) {
84 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
85 PrintAndLog(" options");
86 PrintAndLog(" 0 <CSN> simulate the given CSN");
87 PrintAndLog(" 1 simulate default CSN");
88 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
89 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
90 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
91 PrintAndLog(" example: hf iclass sim 2");
92 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
93 PrintAndLog(" hf iclass sim 3");
98 int CmdHFiClassSim(const char *Cmd
) {
100 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
103 return usage_hf_iclass_sim();
105 simType
= param_get8ex(Cmd
, 0, 0, 10);
109 if (param_gethex(Cmd
, 1, CSN
, 16)) {
110 PrintAndLog("A CSN should consist of 16 HEX symbols");
111 return usage_hf_iclass_sim();
114 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
118 PrintAndLog("Undefined simptype %d", simType
);
119 return usage_hf_iclass_sim();
122 uint8_t numberOfCSNs
=0;
125 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
126 UsbCommand resp
= {0};
128 uint8_t csns
[8*NUM_CSNS
] = {
129 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
130 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
131 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
132 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
133 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
134 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
135 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
136 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
137 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
138 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
139 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
140 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
141 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
142 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
143 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
145 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
148 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
149 PrintAndLog("Command timed out");
153 uint8_t num_mac_responses
= resp
.arg
[1];
154 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
156 size_t datalen
= NUM_CSNS
*24;
158 * Now, time to dump to file. We'll use this format:
159 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
160 * So, it should wind up as
163 * The returndata from the pm3 is on the following format
164 * <4 byte NR><4 byte MAC>
165 * CC are all zeroes, CSN is the same as was sent in
167 void* dump
= malloc(datalen
);
168 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
170 for(i
= 0 ; i
< NUM_CSNS
; i
++)
172 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
173 //8 zero bytes here...
174 //Then comes NR_MAC (eight bytes from the response)
175 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
178 /** Now, save to dumpfile **/
179 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
183 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
184 memcpy(c
.d
.asBytes
, CSN
, 8);
191 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
192 bool tagFound
= false;
193 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
194 FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_AA
|
195 FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
} };
196 // loop in client not device - else on windows have a communication error
200 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
201 uint8_t readStatus
= resp
.arg
[0] & 0xff;
202 uint8_t *data
= resp
.d
.asBytes
;
204 // no tag found or button pressed
205 if( (readStatus
== 0 && !loop
) || readStatus
== 0xFF) {
207 if (verbose
) PrintAndLog("Quitting...");
211 if( readStatus
& FLAG_ICLASS_READER_CSN
) {
212 PrintAndLog(" CSN: %s",sprint_hex(data
,8));
215 if( readStatus
& FLAG_ICLASS_READER_CC
) {
216 PrintAndLog(" CC: %s",sprint_hex(data
+16,8));
218 if( readStatus
& FLAG_ICLASS_READER_CONF
) {
219 printIclassDumpInfo(data
);
221 if (readStatus
& FLAG_ICLASS_READER_AA
) {
223 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*5,8));
224 for (int i
= 0; i
<8; i
++) {
225 if (data
[8*5+i
] != 0xFF) {
229 PrintAndLog(" : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)");
232 if (tagFound
&& !loop
) return 1;
234 if (verbose
) PrintAndLog("Command execute timeout");
241 int CmdHFiClassReader(const char *Cmd
) {
242 return HFiClassReader(Cmd
, true, true);
245 int CmdHFiClassReader_Replay(const char *Cmd
) {
246 uint8_t readerType
= 0;
247 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
250 PrintAndLog("Usage: hf iclass replay <MAC>");
251 PrintAndLog(" sample: hf iclass replay 00112233");
255 if (param_gethex(Cmd
, 0, MAC
, 8)) {
256 PrintAndLog("MAC must include 8 HEX symbols");
260 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
261 memcpy(c
.d
.asBytes
, MAC
, 4);
267 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
268 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
269 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
274 int hf_iclass_eload_usage(void) {
275 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
276 PrintAndLog("Usage: hf iclass eload f <filename>");
278 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
282 int CmdHFiClassELoad(const char *Cmd
) {
284 char opt
= param_getchar(Cmd
, 0);
285 if (strlen(Cmd
)<1 || opt
== 'h')
286 return hf_iclass_eload_usage();
288 //File handling and reading
290 char filename
[FILE_PATH_SIZE
];
291 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0)
293 f
= fopen(filename
, "rb");
295 return hf_iclass_eload_usage();
299 PrintAndLog("Failed to read from file '%s'", filename
);
303 fseek(f
, 0, SEEK_END
);
304 long fsize
= ftell(f
);
305 fseek(f
, 0, SEEK_SET
);
308 PrintAndLog("Error, when getting filesize");
313 uint8_t *dump
= malloc(fsize
);
315 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
318 printIclassDumpInfo(dump
);
321 if (bytes_read
< fsize
)
323 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
328 uint32_t bytes_sent
= 0;
329 uint32_t bytes_remaining
= bytes_read
;
331 while(bytes_remaining
> 0){
332 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
333 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
334 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
336 bytes_remaining
-= bytes_in_packet
;
337 bytes_sent
+= bytes_in_packet
;
340 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
344 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
345 FILE *f
= fopen(filename
, "rb");
347 PrintAndLog("Failed to read from file '%s'", filename
);
350 fseek(f
, 0, SEEK_END
);
351 long fsize
= ftell(f
);
352 fseek(f
, 0, SEEK_SET
);
353 size_t bytes_read
= fread(buffer
, 1, len
, f
);
357 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
360 if(bytes_read
!= len
)
362 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
368 int usage_hf_iclass_decrypt(void) {
369 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
371 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
372 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
374 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
376 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
377 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
378 PrintAndLog("which is defined by the configuration block.");
382 int CmdHFiClassDecrypt(const char *Cmd
) {
383 uint8_t key
[16] = { 0 };
384 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
386 usage_hf_iclass_decrypt();
389 PrintAndLog("Decryption file found... ");
390 char opt
= param_getchar(Cmd
, 0);
391 if (strlen(Cmd
)<1 || opt
== 'h')
392 return usage_hf_iclass_decrypt();
394 //Open the tagdump-file
396 char filename
[FILE_PATH_SIZE
];
397 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) {
398 f
= fopen(filename
, "rb");
400 PrintAndLog("Could not find file %s", filename
);
404 return usage_hf_iclass_decrypt();
407 fseek(f
, 0, SEEK_END
);
408 long fsize
= ftell(f
);
409 fseek(f
, 0, SEEK_SET
);
410 uint8_t enc_dump
[8] = {0};
411 uint8_t *decrypted
= malloc(fsize
);
412 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
413 des3_set2key_dec( &ctx
, key
);
414 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
416 //Use the first block (CSN) for filename
417 char outfilename
[FILE_PATH_SIZE
] = { 0 };
418 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
419 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
420 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
423 while(bytes_read
== 8)
427 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
429 des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
431 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
432 bytes_read
= fread(enc_dump
, 1, 8, f
);
437 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
442 int usage_hf_iclass_encrypt(void) {
443 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
445 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
446 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
448 PrintAndLog("example: hf iclass encrypt 0102030405060708");
453 static int iClassEncryptBlkData(uint8_t *blkData
) {
454 uint8_t key
[16] = { 0 };
455 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
457 usage_hf_iclass_encrypt();
460 PrintAndLog("Decryption file found... ");
462 uint8_t encryptedData
[16];
463 uint8_t *encrypted
= encryptedData
;
464 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
465 des3_set2key_enc( &ctx
, key
);
467 des3_crypt_ecb(&ctx
, blkData
,encrypted
);
468 //printvar("decrypted block", decrypted, 8);
469 memcpy(blkData
,encrypted
,8);
474 int CmdHFiClassEncryptBlk(const char *Cmd
) {
475 uint8_t blkData
[8] = {0};
476 char opt
= param_getchar(Cmd
, 0);
477 if (strlen(Cmd
)<1 || opt
== 'h')
478 return usage_hf_iclass_encrypt();
480 //get the bytes to encrypt
481 if (param_gethex(Cmd
, 0, blkData
, 16))
483 PrintAndLog("BlockData must include 16 HEX symbols");
486 if (!iClassEncryptBlkData(blkData
)) return 0;
488 printvar("encrypted block", blkData
, 8);
492 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
495 memcpy(WB
+ 1,data
,8);
496 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
497 //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]);
500 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
503 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
504 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
506 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
508 clearCommandBuffer();
510 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
512 PrintAndLog("Command execute timeout");
516 uint8_t isOK
= resp
.arg
[0] & 0xff;
517 uint8_t *data
= resp
.d
.asBytes
;
520 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
523 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
526 PrintAndLog("Failed to obtain CC! Aborting");
532 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
) {
533 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
534 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
536 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
541 memcpy(div_key
, KEY
, 8);
543 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
544 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]);
546 doMAC(CCNR
, div_key
, MAC
);
548 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
549 memcpy(d
.d
.asBytes
, MAC
, 4);
550 clearCommandBuffer();
552 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
554 if (verbose
) PrintAndLog("Auth Command execute timeout");
557 uint8_t isOK
= resp
.arg
[0] & 0xff;
559 if (verbose
) PrintAndLog("Authentication error");
565 int usage_hf_iclass_dump(void) {
566 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
567 PrintAndLog("Options:");
568 PrintAndLog(" f <filename> : specify a filename to save dump to");
569 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
570 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
571 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
572 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
573 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
574 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
575 PrintAndLog(" NOTE: * = required");
576 PrintAndLog("Samples:");
577 PrintAndLog(" hf iclass dump k 001122334455667B");
578 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
579 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
583 int CmdHFiClassReader_Dump(const char *Cmd
) {
585 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
586 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
587 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
591 uint8_t app_areas
= 1;
593 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
594 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
597 uint8_t fileNameLen
= 0;
598 char filename
[FILE_PATH_SIZE
]={0};
599 char tempStr
[50] = {0};
600 bool have_debit_key
= false;
601 bool have_credit_key
= false;
602 bool use_credit_key
= false;
608 while(param_getchar(Cmd
, cmdp
) != 0x00)
610 switch(param_getchar(Cmd
, cmdp
))
614 return usage_hf_iclass_dump();
617 have_credit_key
= true;
618 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
620 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
621 } else if (dataLen
== 1) {
622 keyNbr
= param_get8(Cmd
, cmdp
+1);
623 if (keyNbr
< ICLASS_KEYS_MAX
) {
624 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
626 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
630 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
642 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
643 if (fileNameLen
< 1) {
644 PrintAndLog("No filename found after f");
651 have_debit_key
= true;
652 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
654 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
655 } else if (dataLen
== 1) {
656 keyNbr
= param_get8(Cmd
, cmdp
+1);
657 if (keyNbr
< ICLASS_KEYS_MAX
) {
658 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
660 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
664 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
675 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
679 if(errors
) return usage_hf_iclass_dump();
682 if (cmdp
< 2) return usage_hf_iclass_dump();
683 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
684 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
686 //get config and first 3 blocks
687 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
688 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
690 uint8_t tag_data
[255*8];
692 clearCommandBuffer();
694 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
695 PrintAndLog("Command execute timeout");
699 uint8_t readStatus
= resp
.arg
[0] & 0xff;
700 uint8_t *data
= resp
.d
.asBytes
;
703 PrintAndLog("No tag found...");
707 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
708 memcpy(tag_data
, data
, 8*3);
709 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
711 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
712 // large memory - not able to dump pages currently
713 if (numblks
> maxBlk
) numblks
= maxBlk
;
716 // authenticate debit key and get div_key - later store in dump block 3
717 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
718 //try twice - for some reason it sometimes fails the first time...
719 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
726 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
727 clearCommandBuffer();
729 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
730 PrintAndLog("Command execute time-out 1");
734 uint32_t blocksRead
= resp
.arg
[1];
735 uint8_t isOK
= resp
.arg
[0] & 0xff;
736 if (!isOK
&& !blocksRead
) {
737 PrintAndLog("Read Block Failed");
741 uint32_t startindex
= resp
.arg
[2];
742 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
743 PrintAndLog("Data exceeded Buffer size!");
744 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
746 // response ok - now get bigbuf content of the dump
747 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
);
748 WaitForResponse(CMD_ACK
,NULL
);
749 size_t gotBytes
= blocksRead
*8 + blockno
*8;
752 if (have_credit_key
) {
753 //turn off hf field before authenticating with different key
756 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
757 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
758 //try twice - for some reason it sometimes fails the first time...
759 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
764 // do we still need to read more block? (aa2 enabled?)
765 if (maxBlk
> blockno
+numblks
+1) {
766 // setup dump and start
767 w
.arg
[0] = blockno
+ blocksRead
;
768 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
769 clearCommandBuffer();
771 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
772 PrintAndLog("Command execute timeout 2");
776 uint8_t isOK
= resp
.arg
[0] & 0xff;
777 blocksRead
= resp
.arg
[1];
778 if (!isOK
&& !blocksRead
) {
779 PrintAndLog("Read Block Failed 2");
784 startindex
= resp
.arg
[2];
785 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
786 PrintAndLog("Data exceeded Buffer size!");
787 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
789 // get dumped data from bigbuf
790 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
);
791 WaitForResponse(CMD_ACK
,NULL
);
793 gotBytes
+= blocksRead
*8;
794 } else { //field is still on - turn it off...
799 // add diversified keys to dump
800 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
801 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
803 printf("------+--+-------------------------+\n");
804 printf("CSN |00| %s|\n",sprint_hex(tag_data
, 8));
805 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
807 if (filename
[0] == 0){
808 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
809 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
810 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
813 // save the dump to .bin file
814 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
815 saveFile(filename
, "bin", tag_data
, gotBytes
);
819 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
820 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
821 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
822 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
827 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
828 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
829 memcpy(w
.d
.asBytes
, bldata
, 8);
830 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
832 clearCommandBuffer();
834 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
836 PrintAndLog("Write Command execute timeout");
839 uint8_t isOK
= resp
.arg
[0] & 0xff;
841 PrintAndLog("Write Block Failed");
844 PrintAndLog("Write Block Successful");
848 int usage_hf_iclass_writeblock(void) {
849 PrintAndLog("Options:");
850 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
851 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
852 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
853 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
854 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
855 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
856 PrintAndLog("Samples:");
857 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
858 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
859 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
863 int CmdHFiClass_WriteBlock(const char *Cmd
) {
865 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
866 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
869 char tempStr
[50] = {0};
870 bool use_credit_key
= false;
875 while(param_getchar(Cmd
, cmdp
) != 0x00)
877 switch(param_getchar(Cmd
, cmdp
))
881 return usage_hf_iclass_writeblock();
884 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
885 PrintAndLog("Block No must include 2 HEX symbols\n");
892 use_credit_key
= true;
897 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
899 PrintAndLog("KEY must include 16 HEX symbols\n");
911 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
913 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
914 } else if (dataLen
== 1) {
915 keyNbr
= param_get8(Cmd
, cmdp
+1);
916 if (keyNbr
< ICLASS_KEYS_MAX
) {
917 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
919 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
923 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
934 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
938 if(errors
) return usage_hf_iclass_writeblock();
941 if (cmdp
< 6) return usage_hf_iclass_writeblock();
942 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
947 int usage_hf_iclass_clone(void) {
948 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
949 PrintAndLog("Options:");
950 PrintAndLog(" f <filename>: specify a filename to clone from");
951 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
952 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
953 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
954 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
955 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
956 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
957 PrintAndLog("Samples:");
958 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
959 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
960 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
964 int CmdHFiClassCloneTag(const char *Cmd
) {
965 char filename
[FILE_PATH_SIZE
] = {0};
966 char tempStr
[50]={0};
967 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
969 uint8_t fileNameLen
= 0;
970 uint8_t startblock
= 0;
971 uint8_t endblock
= 0;
973 bool use_credit_key
= false;
978 while(param_getchar(Cmd
, cmdp
) != 0x00)
980 switch(param_getchar(Cmd
, cmdp
))
984 return usage_hf_iclass_clone();
987 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
988 PrintAndLog("Start Block No must include 2 HEX symbols\n");
995 use_credit_key
= true;
1005 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1006 if (fileNameLen
< 1) {
1007 PrintAndLog("No filename found after f");
1014 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1015 if (dataLen
== 16) {
1016 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1017 } else if (dataLen
== 1) {
1018 keyNbr
= param_get8(Cmd
, cmdp
+1);
1019 if (keyNbr
< ICLASS_KEYS_MAX
) {
1020 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1022 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1026 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1033 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1034 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1045 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1049 if(errors
) return usage_hf_iclass_clone();
1052 if (cmdp
< 8) return usage_hf_iclass_clone();
1056 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1058 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1059 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1061 // file handling and reading
1062 f
= fopen(filename
,"rb");
1064 PrintAndLog("Failed to read from file '%s'", filename
);
1069 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1073 // now read data from the file from block 6 --- 19
1074 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1075 // 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,
1076 // else we have to create a share memory
1078 fseek(f
,startblock
*8,SEEK_SET
);
1079 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1080 PrintAndLog("File reading error.");
1085 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1086 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1088 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1091 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1093 // calculate all mac for every the block we will write
1094 for (i
= startblock
; i
<= endblock
; i
++){
1095 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1096 // usb command d start pointer = d + (i - 6) * 12
1097 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1098 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1100 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1101 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1102 memcpy(ptr
+ 8,MAC
, 4);
1105 for (i
= 0; i
<= endblock
- startblock
;i
++){
1106 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1107 printf("Block |%02x|",i
+ startblock
);
1108 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]);
1109 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1113 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1115 PrintAndLog("Command execute timeout");
1121 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) {
1122 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1123 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1126 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1129 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1130 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1131 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
))
1136 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1137 clearCommandBuffer();
1139 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1141 PrintAndLog("Command execute timeout");
1144 uint8_t isOK
= resp
.arg
[0] & 0xff;
1146 PrintAndLog("Read Block Failed");
1149 //data read is stored in: resp.d.asBytes[0-15]
1150 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1154 int usage_hf_iclass_readblock(void) {
1155 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1156 PrintAndLog("Options:");
1157 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1158 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1159 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1160 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1161 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1162 PrintAndLog("Samples:");
1163 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1164 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1165 PrintAndLog(" hf iclass readblk b 0A k 0");
1169 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1171 uint8_t keyType
= 0x88; //debit key
1172 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1174 uint8_t dataLen
= 0;
1175 char tempStr
[50] = {0};
1177 bool rawkey
= false;
1178 bool errors
= false;
1181 while(param_getchar(Cmd
, cmdp
) != 0x00)
1183 switch(param_getchar(Cmd
, cmdp
))
1187 return usage_hf_iclass_readblock();
1190 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1191 PrintAndLog("Block No must include 2 HEX symbols\n");
1209 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1210 if (dataLen
== 16) {
1211 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1212 } else if (dataLen
== 1) {
1213 keyNbr
= param_get8(Cmd
, cmdp
+1);
1214 if (keyNbr
< ICLASS_KEYS_MAX
) {
1215 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1217 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1221 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1232 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1236 if(errors
) return usage_hf_iclass_readblock();
1239 if (cmdp
< 2) return usage_hf_iclass_readblock();
1241 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1242 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
);
1245 int CmdHFiClass_loclass(const char *Cmd
) {
1246 char opt
= param_getchar(Cmd
, 0);
1248 if (strlen(Cmd
)<1 || opt
== 'h') {
1249 PrintAndLog("Usage: hf iclass loclass [options]");
1250 PrintAndLog("Options:");
1251 PrintAndLog("h Show this help");
1252 PrintAndLog("t Perform self-test");
1253 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1254 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1255 PrintAndLog(" malicious CSNs, and their protocol responses");
1256 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1257 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1258 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1259 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1260 PrintAndLog(" ... totalling N*24 bytes");
1263 char fileName
[255] = {0};
1266 if(param_getstr(Cmd
, 1, fileName
, sizeof(fileName
)) > 0)
1268 return bruteforceFileNoKeys(fileName
);
1271 PrintAndLog("You must specify a filename");
1276 int errors
= testCipherUtils();
1277 errors
+= testMAC();
1278 errors
+= doKeyTests(0);
1279 errors
+= testElite();
1282 prnlog("OBS! There were errors!!!");
1290 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1292 memcpy(&mem_config
, iclass_dump
+ 13,1);
1293 uint8_t maxmemcount
;
1294 uint8_t filemaxblock
= filesize
/ 8;
1295 if (mem_config
& 0x80)
1299 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1301 if (startblock
== 0)
1303 if ((endblock
> maxmemcount
) || (endblock
== 0))
1304 endblock
= maxmemcount
;
1306 // remember endblock need to relate to zero-index arrays.
1307 if (endblock
> filemaxblock
-1)
1308 endblock
= filemaxblock
;
1311 printf("------+--+-------------------------+\n");
1312 while (i
<= endblock
) {
1313 uint8_t *blk
= iclass_dump
+ (i
* 8);
1314 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );
1317 printf("------+--+-------------------------+\n");
1320 int usage_hf_iclass_readtagfile() {
1321 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1325 int CmdHFiClassReadTagFile(const char *Cmd
) {
1330 char filename
[FILE_PATH_SIZE
];
1331 if (param_getstr(Cmd
, 0, filename
, sizeof(filename
)) < 1)
1332 return usage_hf_iclass_readtagfile();
1333 if (param_getstr(Cmd
, 1, tempnum
, sizeof(tempnum
)) < 1)
1336 sscanf(tempnum
,"%d",&startblock
);
1338 if (param_getstr(Cmd
,2, tempnum
, sizeof(tempnum
)) < 1)
1341 sscanf(tempnum
,"%d",&endblock
);
1342 // file handling and reading
1343 f
= fopen(filename
,"rb");
1345 PrintAndLog("Failed to read from file '%s'", filename
);
1348 fseek(f
, 0, SEEK_END
);
1349 long fsize
= ftell(f
);
1350 fseek(f
, 0, SEEK_SET
);
1353 PrintAndLog("Error, when getting filesize");
1358 uint8_t *dump
= malloc(fsize
);
1360 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1362 uint8_t *csn
= dump
;
1363 printf("------+--+-------------------------+\n");
1364 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1365 // printIclassDumpInfo(dump);
1366 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1372 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1373 uint64_t new_div = 0x00;
1379 uint64_t hexarray_to_uint64(uint8_t *key) {
1382 for (int i = 0;i < 8;i++)
1383 sprintf(&temp[(i *2)],"%02X",key[i]);
1385 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1390 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1391 uint8_t keytable
[128] = {0};
1392 uint8_t key_index
[8] = {0};
1394 uint8_t key_sel
[8] = { 0 };
1395 uint8_t key_sel_p
[8] = { 0 };
1396 hash2(KEY
, keytable
);
1397 hash1(CSN
, key_index
);
1398 for(uint8_t i
= 0; i
< 8 ; i
++)
1399 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1401 //Permute from iclass format to standard format
1402 permutekey_rev(key_sel
, key_sel_p
);
1403 diversifyKey(CSN
, key_sel_p
, div_key
);
1405 diversifyKey(CSN
, KEY
, div_key
);
1409 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1410 //calculate and return xor_div_key (ready for a key write command)
1411 //print all div_keys if verbose
1412 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1413 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1414 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1416 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1418 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1420 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1421 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1424 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1425 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1426 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1430 int usage_hf_iclass_calc_newkey(void) {
1431 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1432 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1433 PrintAndLog(" Options:");
1434 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1435 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1436 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1437 PrintAndLog(" e : specify new key as elite calc");
1438 PrintAndLog(" ee : specify old and new key as elite calc");
1439 PrintAndLog("Samples:");
1440 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1441 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1442 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1443 PrintAndLog("NOTE: * = required\n");
1448 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1449 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1450 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1451 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1452 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1453 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1455 uint8_t dataLen
= 0;
1456 char tempStr
[50] = {0};
1457 bool givenCSN
= false;
1458 bool oldElite
= false;
1460 bool errors
= false;
1462 while(param_getchar(Cmd
, cmdp
) != 0x00)
1464 switch(param_getchar(Cmd
, cmdp
))
1468 return usage_hf_iclass_calc_newkey();
1471 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
, sizeof(tempStr
));
1479 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1480 if (dataLen
== 16) {
1481 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1482 } else if (dataLen
== 1) {
1483 keyNbr
= param_get8(Cmd
, cmdp
+1);
1484 if (keyNbr
< ICLASS_KEYS_MAX
) {
1485 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1487 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1491 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1498 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1499 if (dataLen
== 16) {
1500 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1501 } else if (dataLen
== 1) {
1502 keyNbr
= param_get8(Cmd
, cmdp
+1);
1503 if (keyNbr
< ICLASS_KEYS_MAX
) {
1504 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1506 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1510 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1518 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1519 return usage_hf_iclass_calc_newkey();
1523 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1527 if(errors
) return usage_hf_iclass_calc_newkey();
1530 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1533 if (!select_only(CSN
, CCNR
, false, true))
1536 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1540 static int loadKeys(char *filename
) {
1542 f
= fopen(filename
,"rb");
1544 PrintAndLog("Failed to read from file '%s'", filename
);
1547 fseek(f
, 0, SEEK_END
);
1548 long fsize
= ftell(f
);
1549 fseek(f
, 0, SEEK_SET
);
1552 PrintAndLog("Error, when getting filesize");
1557 uint8_t *dump
= malloc(fsize
);
1559 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1561 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1562 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1567 for (; i
< bytes_read
/8; i
++){
1568 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1571 PrintAndLog("%u keys loaded", i
);
1575 static int saveKeys(char *filename
) {
1577 f
= fopen(filename
,"wb");
1579 printf("error opening file %s\n",filename
);
1582 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1583 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1584 PrintAndLog("save key failed to write to file: %s", filename
);
1592 static int printKeys(void) {
1594 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1595 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1601 int usage_hf_iclass_managekeys(void) {
1602 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1603 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1604 PrintAndLog(" Options:");
1605 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1606 PrintAndLog(" k <key> : set a key in memory");
1607 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1608 PrintAndLog(" s : save keys in memory to file specified by filename");
1609 PrintAndLog(" l : load keys to memory from file specified by filename");
1610 PrintAndLog(" p : print keys loaded into memory\n");
1611 PrintAndLog("Samples:");
1612 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1613 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1614 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1615 PrintAndLog(" print keys : hf iclass managekeys p\n");
1619 int CmdHFiClassManageKeys(const char *Cmd
) {
1621 uint8_t dataLen
= 0;
1622 uint8_t KEY
[8] = {0};
1623 char filename
[FILE_PATH_SIZE
];
1624 uint8_t fileNameLen
= 0;
1625 bool errors
= false;
1626 uint8_t operation
= 0;
1630 while(param_getchar(Cmd
, cmdp
) != 0x00)
1632 switch(param_getchar(Cmd
, cmdp
))
1636 return usage_hf_iclass_managekeys();
1639 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1640 if (fileNameLen
< 1) {
1641 PrintAndLog("No filename found after f");
1648 keyNbr
= param_get8(Cmd
, cmdp
+1);
1649 if (keyNbr
>= ICLASS_KEYS_MAX
) {
1650 PrintAndLog("Invalid block number");
1657 operation
+= 3; //set key
1658 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1659 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1660 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1662 PrintAndLog("\nERROR: Key is incorrect length\n");
1669 operation
+= 4; //print keys in memory
1674 operation
+= 5; //load keys from file
1679 operation
+= 6; //save keys to file
1683 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1687 if(errors
) return usage_hf_iclass_managekeys();
1689 if (operation
== 0){
1690 PrintAndLog("no operation specified (load, save, or print)\n");
1691 return usage_hf_iclass_managekeys();
1694 PrintAndLog("Too many operations specified\n");
1695 return usage_hf_iclass_managekeys();
1697 if (operation
> 4 && fileNameLen
== 0){
1698 PrintAndLog("You must enter a filename when loading or saving\n");
1699 return usage_hf_iclass_managekeys();
1703 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1704 case 4: return printKeys();
1705 case 5: return loadKeys(filename
);
1706 case 6: return saveKeys(filename
);
1712 int CmdHFiClassCheckKeys(const char *Cmd
) {
1715 ctmp
= param_getchar(Cmd
, 0);
1716 if (ctmp
== 'h' || ctmp
== 'H') return usage_hf_iclass_chk();
1718 uint8_t mac
[4] = {0x00,0x00,0x00,0x00};
1719 uint8_t key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1720 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1722 // elite key, raw key, standard key
1724 bool rawkey
= false;
1725 bool found_debit
= false;
1726 bool found_credit
= false;
1729 char filename
[FILE_PATH_SIZE
] = {0};
1731 uint8_t *keyBlock
= NULL
, *p
;
1732 int keyitems
= 0, keycnt
= 0;
1735 // May be a dictionary file
1736 if ( param_getstr(Cmd
, 1, filename
, sizeof(filename
)) >= FILE_PATH_SIZE
) {
1737 PrintAndLog("File name too long");
1742 if ( !(f
= fopen( filename
, "r")) ) {
1743 PrintAndLog("File: %s: not found or locked.", filename
);
1748 while( fgets(buf
, sizeof(buf
), f
) ){
1749 if (strlen(buf
) < 16 || buf
[15] == '\n')
1752 while (fgetc(f
) != '\n' && !feof(f
)) ; //goto next line
1754 if( buf
[0]=='#' ) continue; //The line start with # is comment, skip
1756 if (!isxdigit(buf
[0])){
1757 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf
);
1763 p
= realloc(keyBlock
, 8 * (keyitems
+= 64));
1765 PrintAndLog("Cannot allocate memory for default keys");
1772 memset(keyBlock
+ 8 * keycnt
, 0, 8);
1773 num_to_bytes(strtoull(buf
, NULL
, 16), 8, keyBlock
+ 8 * keycnt
);
1775 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1777 memset(buf
, 0, sizeof(buf
));
1780 PrintAndLog("Loaded %2d keys from %s", keycnt
, filename
);
1783 uint64_t t1
= msclock();
1785 for (uint32_t c
= 0; c
< keycnt
; c
+= 1) {
1786 printf("."); fflush(stdout
);
1788 int gc
= getchar(); (void)gc
;
1789 printf("\naborted via keyboard!\n");
1793 memcpy(key
, keyBlock
+ 8 * c
, 8);
1795 // debit key. try twice
1796 for (int foo
= 0; foo
< 2 && !found_debit
; foo
++) {
1797 if (!select_and_auth(key
, mac
, div_key
, false, elite
, rawkey
, false))
1801 PrintAndLog("\n--------------------------------------------------------");
1802 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key
, 8));
1806 // credit key. try twice
1807 for (int foo
= 0; foo
< 2 && !found_credit
; foo
++) {
1808 if (!select_and_auth(key
, mac
, div_key
, true, elite
, rawkey
, false))
1812 PrintAndLog("\n--------------------------------------------------------");
1813 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key
, 8));
1814 found_credit
= true;
1818 if ( found_debit
&& found_credit
)
1822 t1
= msclock() - t1
;
1824 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1
/1000.0);
1832 static command_t CommandTable
[] =
1834 {"help", CmdHelp
, 1, "This help"},
1835 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1836 {"chk", CmdHFiClassCheckKeys
, 0, " Check keys"},
1837 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1838 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1839 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1840 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1841 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1842 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1843 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1844 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1845 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1846 {"reader", CmdHFiClassReader
, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1847 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1848 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1849 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1850 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1851 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1852 {NULL
, NULL
, 0, NULL
}
1855 int CmdHFiClass(const char *Cmd
)
1857 clearCommandBuffer();
1858 CmdsParse(CommandTable
, Cmd
);
1862 int CmdHelp(const char *Cmd
)
1864 CmdsHelp(CommandTable
);