1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3 // Copyright (C) 2011 Gerhard de Koning Gans
4 // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende
6 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
7 // at your option, any later version. See the LICENSE.txt file for the text of
9 //-----------------------------------------------------------------------------
10 // High frequency iClass commands
11 //-----------------------------------------------------------------------------
17 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
19 #include "proxmark3.h"
21 #include "cmdparser.h"
22 #include "cmdhficlass.h"
26 #include "loclass/des.h"
27 #include "loclass/cipherutils.h"
28 #include "loclass/cipher.h"
29 #include "loclass/ikeys.h"
30 #include "loclass/elite_crack.h"
31 #include "loclass/fileutils.h"
32 #include "protocols.h"
36 static int CmdHelp(const char *Cmd
);
38 #define ICLASS_KEYS_MAX 8
39 static uint8_t iClass_Key_Table
[ICLASS_KEYS_MAX
][8] = {
40 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
41 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
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 }
50 typedef struct iclass_block
{
54 int xorbits_8(uint8_t val
) {
55 uint8_t res
= val
^ (val
>> 1); //1st pass
56 res
= res
^ (res
>> 1); // 2nd pass
57 res
= res
^ (res
>> 2); // 3rd pass
58 res
= res
^ (res
>> 4); // 4th pass
62 int CmdHFiClassList(const char *Cmd
) {
63 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
67 int CmdHFiClassSnoop(const char *Cmd
) {
68 UsbCommand c
= {CMD_SNOOP_ICLASS
};
73 int usage_hf_iclass_sim(void) {
74 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
75 PrintAndLog(" options");
76 PrintAndLog(" 0 <CSN> simulate the given CSN");
77 PrintAndLog(" 1 simulate default CSN");
78 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
79 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
80 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
81 PrintAndLog(" example: hf iclass sim 2");
82 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
83 PrintAndLog(" hf iclass sim 3");
88 int CmdHFiClassSim(const char *Cmd
) {
90 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
93 return usage_hf_iclass_sim();
95 simType
= param_get8ex(Cmd
, 0, 0, 10);
99 if (param_gethex(Cmd
, 1, CSN
, 16)) {
100 PrintAndLog("A CSN should consist of 16 HEX symbols");
101 return usage_hf_iclass_sim();
104 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
108 PrintAndLog("Undefined simptype %d", simType
);
109 return usage_hf_iclass_sim();
112 uint8_t numberOfCSNs
=0;
115 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
116 UsbCommand resp
= {0};
118 uint8_t csns
[8*NUM_CSNS
] = {
119 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
120 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
121 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
122 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
123 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
124 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
125 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
126 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
127 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
128 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
129 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
130 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
131 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
132 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
133 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
135 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
138 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
139 PrintAndLog("Command timed out");
143 uint8_t num_mac_responses
= resp
.arg
[1];
144 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
146 size_t datalen
= NUM_CSNS
*24;
148 * Now, time to dump to file. We'll use this format:
149 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
150 * So, it should wind up as
153 * The returndata from the pm3 is on the following format
154 * <4 byte NR><4 byte MAC>
155 * CC are all zeroes, CSN is the same as was sent in
157 void* dump
= malloc(datalen
);
158 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
160 for(i
= 0 ; i
< NUM_CSNS
; i
++)
162 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
163 //8 zero bytes here...
164 //Then comes NR_MAC (eight bytes from the response)
165 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
168 /** Now, save to dumpfile **/
169 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
173 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
174 memcpy(c
.d
.asBytes
, CSN
, 8);
181 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
182 bool tagFound
= false;
183 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
184 FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_AA
}};
185 // loop in client not device - else on windows have a communication error
186 c
.arg
[0] |= FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
;
190 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
191 uint8_t readStatus
= resp
.arg
[0] & 0xff;
192 uint8_t *data
= resp
.d
.asBytes
;
195 PrintAndLog("Readstatus:%02x", readStatus
);
196 if( readStatus
== 0){
198 if (verbose
) PrintAndLog("Quitting...");
201 if( readStatus
& FLAG_ICLASS_READER_CSN
){
202 PrintAndLog(" CSN: %s",sprint_hex(data
,8));
205 if( readStatus
& FLAG_ICLASS_READER_CC
) PrintAndLog(" CC: %s",sprint_hex(data
+16,8));
206 if( readStatus
& FLAG_ICLASS_READER_CONF
){
207 printIclassDumpInfo(data
);
209 //TODO add iclass read block 05 and test iclass type..
210 if (readStatus
& FLAG_ICLASS_READER_AA
) {
212 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*4,8));
213 for (int i
= 0; i
<8; i
++) {
214 if (data
[8*4+i
] != 0xFF) {
218 PrintAndLog(" : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)");
221 if (tagFound
&& !loop
) return 1;
223 if (verbose
) PrintAndLog("Command execute timeout");
230 int CmdHFiClassReader(const char *Cmd
) {
231 return HFiClassReader(Cmd
, true, true);
234 int CmdHFiClassReader_Replay(const char *Cmd
) {
235 uint8_t readerType
= 0;
236 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
239 PrintAndLog("Usage: hf iclass replay <MAC>");
240 PrintAndLog(" sample: hf iclass replay 00112233");
244 if (param_gethex(Cmd
, 0, MAC
, 8)) {
245 PrintAndLog("MAC must include 8 HEX symbols");
249 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
250 memcpy(c
.d
.asBytes
, MAC
, 4);
256 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
257 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
258 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
263 int hf_iclass_eload_usage(void) {
264 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
265 PrintAndLog("Usage: hf iclass eload f <filename>");
267 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
271 int CmdHFiClassELoad(const char *Cmd
) {
273 char opt
= param_getchar(Cmd
, 0);
274 if (strlen(Cmd
)<1 || opt
== 'h')
275 return hf_iclass_eload_usage();
277 //File handling and reading
279 char filename
[FILE_PATH_SIZE
];
280 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0)
282 f
= fopen(filename
, "rb");
284 return hf_iclass_eload_usage();
288 PrintAndLog("Failed to read from file '%s'", filename
);
292 fseek(f
, 0, SEEK_END
);
293 long fsize
= ftell(f
);
294 fseek(f
, 0, SEEK_SET
);
297 PrintAndLog("Error, when getting filesize");
302 uint8_t *dump
= malloc(fsize
);
304 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
307 printIclassDumpInfo(dump
);
310 if (bytes_read
< fsize
)
312 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
317 uint32_t bytes_sent
= 0;
318 uint32_t bytes_remaining
= bytes_read
;
320 while(bytes_remaining
> 0){
321 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
322 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
323 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
325 bytes_remaining
-= bytes_in_packet
;
326 bytes_sent
+= bytes_in_packet
;
329 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
333 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
334 FILE *f
= fopen(filename
, "rb");
336 PrintAndLog("Failed to read from file '%s'", filename
);
339 fseek(f
, 0, SEEK_END
);
340 long fsize
= ftell(f
);
341 fseek(f
, 0, SEEK_SET
);
342 size_t bytes_read
= fread(buffer
, 1, len
, f
);
346 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
349 if(bytes_read
!= len
)
351 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
357 int usage_hf_iclass_decrypt(void) {
358 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
360 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
361 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
363 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
365 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
366 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
367 PrintAndLog("which is defined by the configuration block.");
371 int CmdHFiClassDecrypt(const char *Cmd
) {
372 uint8_t key
[16] = { 0 };
373 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
375 usage_hf_iclass_decrypt();
378 PrintAndLog("Decryption file found... ");
379 char opt
= param_getchar(Cmd
, 0);
380 if (strlen(Cmd
)<1 || opt
== 'h')
381 return usage_hf_iclass_decrypt();
383 //Open the tagdump-file
385 char filename
[FILE_PATH_SIZE
];
386 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0) {
387 f
= fopen(filename
, "rb");
389 PrintAndLog("Could not find file %s", filename
);
393 return usage_hf_iclass_decrypt();
396 fseek(f
, 0, SEEK_END
);
397 long fsize
= ftell(f
);
398 fseek(f
, 0, SEEK_SET
);
399 uint8_t enc_dump
[8] = {0};
400 uint8_t *decrypted
= malloc(fsize
);
401 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
402 des3_set2key_dec( &ctx
, key
);
403 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
405 //Use the first block (CSN) for filename
406 char outfilename
[FILE_PATH_SIZE
] = { 0 };
407 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
408 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
409 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
412 while(bytes_read
== 8)
416 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
418 des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
420 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
421 bytes_read
= fread(enc_dump
, 1, 8, f
);
426 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
431 int usage_hf_iclass_encrypt(void) {
432 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
434 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
435 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
437 PrintAndLog("example: hf iclass encrypt 0102030405060708");
442 static int iClassEncryptBlkData(uint8_t *blkData
) {
443 uint8_t key
[16] = { 0 };
444 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
446 usage_hf_iclass_encrypt();
449 PrintAndLog("Decryption file found... ");
451 uint8_t encryptedData
[16];
452 uint8_t *encrypted
= encryptedData
;
453 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
454 des3_set2key_enc( &ctx
, key
);
456 des3_crypt_ecb(&ctx
, blkData
,encrypted
);
457 //printvar("decrypted block", decrypted, 8);
458 memcpy(blkData
,encrypted
,8);
463 int CmdHFiClassEncryptBlk(const char *Cmd
) {
464 uint8_t blkData
[8] = {0};
465 char opt
= param_getchar(Cmd
, 0);
466 if (strlen(Cmd
)<1 || opt
== 'h')
467 return usage_hf_iclass_encrypt();
469 //get the bytes to encrypt
470 if (param_gethex(Cmd
, 0, blkData
, 16))
472 PrintAndLog("BlockData must include 16 HEX symbols");
475 if (!iClassEncryptBlkData(blkData
)) return 0;
477 printvar("encrypted block", blkData
, 8);
481 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
484 memcpy(WB
+ 1,data
,8);
485 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
486 //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]);
489 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
492 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
493 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
495 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
497 clearCommandBuffer();
499 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
501 PrintAndLog("Command execute timeout");
505 uint8_t isOK
= resp
.arg
[0] & 0xff;
506 uint8_t *data
= resp
.d
.asBytes
;
509 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
512 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
515 PrintAndLog("Failed to obtain CC! Aborting");
521 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
) {
522 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
523 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
525 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
530 memcpy(div_key
, KEY
, 8);
532 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
533 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]);
535 doMAC(CCNR
, div_key
, MAC
);
537 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
538 memcpy(d
.d
.asBytes
, MAC
, 4);
539 clearCommandBuffer();
541 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
543 PrintAndLog("Auth Command execute timeout");
546 uint8_t isOK
= resp
.arg
[0] & 0xff;
548 PrintAndLog("Authentication error");
554 int usage_hf_iclass_dump(void) {
555 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
556 PrintAndLog("Options:");
557 PrintAndLog(" f <filename> : specify a filename to save dump to");
558 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
559 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
560 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
561 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
562 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
563 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
564 PrintAndLog(" NOTE: * = required");
565 PrintAndLog("Samples:");
566 PrintAndLog(" hf iclass dump k 001122334455667B");
567 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
568 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
572 int CmdHFiClassReader_Dump(const char *Cmd
) {
574 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
575 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
576 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
580 uint8_t app_areas
= 1;
582 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
583 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
586 uint8_t fileNameLen
= 0;
587 char filename
[FILE_PATH_SIZE
]={0};
588 char tempStr
[50] = {0};
589 bool have_debit_key
= false;
590 bool have_credit_key
= false;
591 bool use_credit_key
= false;
597 while(param_getchar(Cmd
, cmdp
) != 0x00)
599 switch(param_getchar(Cmd
, cmdp
))
603 return usage_hf_iclass_dump();
606 have_credit_key
= true;
607 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
609 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
610 } else if (dataLen
== 1) {
611 keyNbr
= param_get8(Cmd
, cmdp
+1);
612 if (keyNbr
< ICLASS_KEYS_MAX
) {
613 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
615 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
619 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
631 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
632 if (fileNameLen
< 1) {
633 PrintAndLog("No filename found after f");
640 have_debit_key
= true;
641 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
643 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
644 } else if (dataLen
== 1) {
645 keyNbr
= param_get8(Cmd
, cmdp
+1);
646 if (keyNbr
< ICLASS_KEYS_MAX
) {
647 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
649 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
653 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
664 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
668 if(errors
) return usage_hf_iclass_dump();
671 if (cmdp
< 2) return usage_hf_iclass_dump();
672 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
673 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
675 //get config and first 3 blocks
676 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
677 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
679 uint8_t tag_data
[255*8];
681 clearCommandBuffer();
683 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
684 PrintAndLog("Command execute timeout");
685 ul_switch_off_field();
688 uint8_t readStatus
= resp
.arg
[0] & 0xff;
689 uint8_t *data
= resp
.d
.asBytes
;
692 PrintAndLog("No tag found...");
693 ul_switch_off_field();
696 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
697 memcpy(tag_data
, data
, 8*3);
698 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
700 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
701 // large memory - not able to dump pages currently
702 if (numblks
> maxBlk
) numblks
= maxBlk
;
704 ul_switch_off_field();
705 // authenticate debit key and get div_key - later store in dump block 3
706 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
707 //try twice - for some reason it sometimes fails the first time...
708 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
709 ul_switch_off_field();
715 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
716 clearCommandBuffer();
718 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
719 PrintAndLog("Command execute time-out 1");
720 ul_switch_off_field();
723 uint32_t blocksRead
= resp
.arg
[1];
724 uint8_t isOK
= resp
.arg
[0] & 0xff;
725 if (!isOK
&& !blocksRead
) {
726 PrintAndLog("Read Block Failed");
727 ul_switch_off_field();
730 uint32_t startindex
= resp
.arg
[2];
731 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
732 PrintAndLog("Data exceeded Buffer size!");
733 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
735 // response ok - now get bigbuf content of the dump
736 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
);
737 WaitForResponse(CMD_ACK
,NULL
);
738 size_t gotBytes
= blocksRead
*8 + blockno
*8;
741 if (have_credit_key
) {
742 //turn off hf field before authenticating with different key
743 ul_switch_off_field();
745 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
746 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
747 //try twice - for some reason it sometimes fails the first time...
748 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
749 ul_switch_off_field();
753 // do we still need to read more block? (aa2 enabled?)
754 if (maxBlk
> blockno
+numblks
+1) {
755 // setup dump and start
756 w
.arg
[0] = blockno
+ blocksRead
;
757 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
758 clearCommandBuffer();
760 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
761 PrintAndLog("Command execute timeout 2");
762 ul_switch_off_field();
765 uint8_t isOK
= resp
.arg
[0] & 0xff;
766 blocksRead
= resp
.arg
[1];
767 if (!isOK
&& !blocksRead
) {
768 PrintAndLog("Read Block Failed 2");
769 ul_switch_off_field();
773 startindex
= resp
.arg
[2];
774 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
775 PrintAndLog("Data exceeded Buffer size!");
776 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
778 // get dumped data from bigbuf
779 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
);
780 WaitForResponse(CMD_ACK
,NULL
);
782 gotBytes
+= blocksRead
*8;
783 } else { //field is still on - turn it off...
784 ul_switch_off_field();
788 // add diversified keys to dump
789 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
790 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
792 printf("------+--+-------------------------+\n");
793 printf("CSN |00| %s|\n",sprint_hex(tag_data
, 8));
794 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
796 if (filename
[0] == 0){
797 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
798 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
799 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
802 // save the dump to .bin file
803 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
804 saveFile(filename
, "bin", tag_data
, gotBytes
);
808 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
809 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
810 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
811 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
816 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
817 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
818 memcpy(w
.d
.asBytes
, bldata
, 8);
819 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
821 clearCommandBuffer();
823 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
825 PrintAndLog("Write Command execute timeout");
828 uint8_t isOK
= resp
.arg
[0] & 0xff;
830 PrintAndLog("Write Block Failed");
833 PrintAndLog("Write Block Successful");
837 int usage_hf_iclass_writeblock(void) {
838 PrintAndLog("Options:");
839 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
840 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
841 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
842 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
843 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
844 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
845 PrintAndLog("Samples:");
846 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
847 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
848 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
852 int CmdHFiClass_WriteBlock(const char *Cmd
) {
854 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
855 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
858 char tempStr
[50] = {0};
859 bool use_credit_key
= false;
864 while(param_getchar(Cmd
, cmdp
) != 0x00)
866 switch(param_getchar(Cmd
, cmdp
))
870 return usage_hf_iclass_writeblock();
873 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
874 PrintAndLog("Block No must include 2 HEX symbols\n");
881 use_credit_key
= true;
886 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
888 PrintAndLog("KEY must include 16 HEX symbols\n");
900 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
902 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
903 } else if (dataLen
== 1) {
904 keyNbr
= param_get8(Cmd
, cmdp
+1);
905 if (keyNbr
< ICLASS_KEYS_MAX
) {
906 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
908 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
912 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
923 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
927 if(errors
) return usage_hf_iclass_writeblock();
930 if (cmdp
< 6) return usage_hf_iclass_writeblock();
931 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
932 ul_switch_off_field();
936 int usage_hf_iclass_clone(void) {
937 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
938 PrintAndLog("Options:");
939 PrintAndLog(" f <filename>: specify a filename to clone from");
940 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
941 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
942 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
943 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
944 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
945 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
946 PrintAndLog("Samples:");
947 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
948 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
949 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
953 int CmdHFiClassCloneTag(const char *Cmd
) {
954 char filename
[FILE_PATH_SIZE
] = {0};
955 char tempStr
[50]={0};
956 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
958 uint8_t fileNameLen
= 0;
959 uint8_t startblock
= 0;
960 uint8_t endblock
= 0;
962 bool use_credit_key
= false;
967 while(param_getchar(Cmd
, cmdp
) != 0x00)
969 switch(param_getchar(Cmd
, cmdp
))
973 return usage_hf_iclass_clone();
976 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
977 PrintAndLog("Start Block No must include 2 HEX symbols\n");
984 use_credit_key
= true;
994 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
995 if (fileNameLen
< 1) {
996 PrintAndLog("No filename found after f");
1003 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1004 if (dataLen
== 16) {
1005 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1006 } else if (dataLen
== 1) {
1007 keyNbr
= param_get8(Cmd
, cmdp
+1);
1008 if (keyNbr
< ICLASS_KEYS_MAX
) {
1009 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1011 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1015 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1022 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1023 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1034 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1038 if(errors
) return usage_hf_iclass_clone();
1041 if (cmdp
< 8) return usage_hf_iclass_clone();
1045 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1047 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1048 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1050 // file handling and reading
1051 f
= fopen(filename
,"rb");
1053 PrintAndLog("Failed to read from file '%s'", filename
);
1058 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1062 // now read data from the file from block 6 --- 19
1063 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1064 // 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,
1065 // else we have to create a share memory
1067 fseek(f
,startblock
*8,SEEK_SET
);
1068 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1069 PrintAndLog("File reading error.");
1074 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1075 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1077 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1080 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1082 // calculate all mac for every the block we will write
1083 for (i
= startblock
; i
<= endblock
; i
++){
1084 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1085 // usb command d start pointer = d + (i - 6) * 12
1086 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1087 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1089 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1090 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1091 memcpy(ptr
+ 8,MAC
, 4);
1094 for (i
= 0; i
<= endblock
- startblock
;i
++){
1095 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1096 printf("Block |%02x|",i
+ startblock
);
1097 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]);
1098 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1102 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1104 PrintAndLog("Command execute timeout");
1110 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) {
1111 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1112 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1115 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1118 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1119 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1120 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
))
1125 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1126 clearCommandBuffer();
1128 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1130 PrintAndLog("Command execute timeout");
1133 uint8_t isOK
= resp
.arg
[0] & 0xff;
1135 PrintAndLog("Read Block Failed");
1138 //data read is stored in: resp.d.asBytes[0-15]
1139 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1143 int usage_hf_iclass_readblock(void) {
1144 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1145 PrintAndLog("Options:");
1146 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1147 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1148 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1149 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1150 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1151 PrintAndLog("Samples:");
1152 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1153 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1154 PrintAndLog(" hf iclass readblk b 0A k 0");
1158 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1160 uint8_t keyType
= 0x88; //debit key
1161 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1163 uint8_t dataLen
= 0;
1164 char tempStr
[50] = {0};
1166 bool rawkey
= false;
1167 bool errors
= false;
1170 while(param_getchar(Cmd
, cmdp
) != 0x00)
1172 switch(param_getchar(Cmd
, cmdp
))
1176 return usage_hf_iclass_readblock();
1179 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1180 PrintAndLog("Block No must include 2 HEX symbols\n");
1198 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1199 if (dataLen
== 16) {
1200 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1201 } else if (dataLen
== 1) {
1202 keyNbr
= param_get8(Cmd
, cmdp
+1);
1203 if (keyNbr
< ICLASS_KEYS_MAX
) {
1204 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1206 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1210 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1221 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1225 if(errors
) return usage_hf_iclass_readblock();
1228 if (cmdp
< 2) return usage_hf_iclass_readblock();
1230 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1231 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
);
1234 int CmdHFiClass_loclass(const char *Cmd
) {
1235 char opt
= param_getchar(Cmd
, 0);
1237 if (strlen(Cmd
)<1 || opt
== 'h') {
1238 PrintAndLog("Usage: hf iclass loclass [options]");
1239 PrintAndLog("Options:");
1240 PrintAndLog("h Show this help");
1241 PrintAndLog("t Perform self-test");
1242 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1243 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1244 PrintAndLog(" malicious CSNs, and their protocol responses");
1245 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1246 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1247 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1248 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1249 PrintAndLog(" ... totalling N*24 bytes");
1252 char fileName
[255] = {0};
1255 if(param_getstr(Cmd
, 1, fileName
) > 0)
1257 return bruteforceFileNoKeys(fileName
);
1260 PrintAndLog("You must specify a filename");
1265 int errors
= testCipherUtils();
1266 errors
+= testMAC();
1267 errors
+= doKeyTests(0);
1268 errors
+= testElite();
1271 prnlog("OBS! There were errors!!!");
1279 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1281 memcpy(&mem_config
, iclass_dump
+ 13,1);
1282 uint8_t maxmemcount
;
1283 uint8_t filemaxblock
= filesize
/ 8;
1284 if (mem_config
& 0x80)
1288 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1290 if (startblock
== 0)
1292 if ((endblock
> maxmemcount
) || (endblock
== 0))
1293 endblock
= maxmemcount
;
1295 // remember endblock need to relate to zero-index arrays.
1296 if (endblock
> filemaxblock
-1)
1297 endblock
= filemaxblock
;
1300 printf("------+--+-------------------------+\n");
1301 while (i
<= endblock
) {
1302 uint8_t *blk
= iclass_dump
+ (i
* 8);
1303 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );
1306 printf("------+--+-------------------------+\n");
1309 int usage_hf_iclass_readtagfile() {
1310 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1314 int CmdHFiClassReadTagFile(const char *Cmd
) {
1319 char filename
[FILE_PATH_SIZE
];
1320 if (param_getstr(Cmd
, 0, filename
) < 1)
1321 return usage_hf_iclass_readtagfile();
1322 if (param_getstr(Cmd
,1,(char *)&tempnum
) < 1)
1325 sscanf(tempnum
,"%d",&startblock
);
1327 if (param_getstr(Cmd
,2,(char *)&tempnum
) < 1)
1330 sscanf(tempnum
,"%d",&endblock
);
1331 // file handling and reading
1332 f
= fopen(filename
,"rb");
1334 PrintAndLog("Failed to read from file '%s'", filename
);
1337 fseek(f
, 0, SEEK_END
);
1338 long fsize
= ftell(f
);
1339 fseek(f
, 0, SEEK_SET
);
1342 PrintAndLog("Error, when getting filesize");
1347 uint8_t *dump
= malloc(fsize
);
1349 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1351 uint8_t *csn
= dump
;
1352 printf("------+--+-------------------------+\n");
1353 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1354 // printIclassDumpInfo(dump);
1355 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1361 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1362 uint64_t new_div = 0x00;
1368 uint64_t hexarray_to_uint64(uint8_t *key) {
1371 for (int i = 0;i < 8;i++)
1372 sprintf(&temp[(i *2)],"%02X",key[i]);
1374 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1379 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1380 uint8_t keytable
[128] = {0};
1381 uint8_t key_index
[8] = {0};
1383 uint8_t key_sel
[8] = { 0 };
1384 uint8_t key_sel_p
[8] = { 0 };
1385 hash2(KEY
, keytable
);
1386 hash1(CSN
, key_index
);
1387 for(uint8_t i
= 0; i
< 8 ; i
++)
1388 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1390 //Permute from iclass format to standard format
1391 permutekey_rev(key_sel
, key_sel_p
);
1392 diversifyKey(CSN
, key_sel_p
, div_key
);
1394 diversifyKey(CSN
, KEY
, div_key
);
1398 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1399 //calculate and return xor_div_key (ready for a key write command)
1400 //print all div_keys if verbose
1401 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1402 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1403 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1405 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1407 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1409 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1410 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1413 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1414 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1415 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1419 int usage_hf_iclass_calc_newkey(void) {
1420 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1421 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1422 PrintAndLog(" Options:");
1423 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1424 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1425 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1426 PrintAndLog(" e : specify new key as elite calc");
1427 PrintAndLog(" ee : specify old and new key as elite calc");
1428 PrintAndLog("Samples:");
1429 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1430 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1431 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1432 PrintAndLog("NOTE: * = required\n");
1437 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1438 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1439 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1440 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1441 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1442 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1444 uint8_t dataLen
= 0;
1445 char tempStr
[50] = {0};
1446 bool givenCSN
= false;
1447 bool oldElite
= false;
1449 bool errors
= false;
1451 while(param_getchar(Cmd
, cmdp
) != 0x00)
1453 switch(param_getchar(Cmd
, cmdp
))
1457 return usage_hf_iclass_calc_newkey();
1460 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
);
1468 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1469 if (dataLen
== 16) {
1470 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1471 } else if (dataLen
== 1) {
1472 keyNbr
= param_get8(Cmd
, cmdp
+1);
1473 if (keyNbr
< ICLASS_KEYS_MAX
) {
1474 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1476 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1480 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1487 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1488 if (dataLen
== 16) {
1489 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1490 } else if (dataLen
== 1) {
1491 keyNbr
= param_get8(Cmd
, cmdp
+1);
1492 if (keyNbr
< ICLASS_KEYS_MAX
) {
1493 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1495 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1499 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1507 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1508 return usage_hf_iclass_calc_newkey();
1512 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1516 if(errors
) return usage_hf_iclass_calc_newkey();
1519 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1522 if (!select_only(CSN
, CCNR
, false, true))
1525 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1529 static int loadKeys(char *filename
) {
1531 f
= fopen(filename
,"rb");
1533 PrintAndLog("Failed to read from file '%s'", filename
);
1536 fseek(f
, 0, SEEK_END
);
1537 long fsize
= ftell(f
);
1538 fseek(f
, 0, SEEK_SET
);
1541 PrintAndLog("Error, when getting filesize");
1546 uint8_t *dump
= malloc(fsize
);
1548 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1550 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1551 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1556 for (; i
< bytes_read
/8; i
++){
1557 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1560 PrintAndLog("%u keys loaded", i
);
1564 static int saveKeys(char *filename
) {
1566 f
= fopen(filename
,"wb");
1568 printf("error opening file %s\n",filename
);
1571 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1572 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1573 PrintAndLog("save key failed to write to file: %s", filename
);
1581 static int printKeys(void) {
1583 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1584 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1590 int usage_hf_iclass_managekeys(void) {
1591 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1592 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1593 PrintAndLog(" Options:");
1594 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1595 PrintAndLog(" k <key> : set a key in memory");
1596 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1597 PrintAndLog(" s : save keys in memory to file specified by filename");
1598 PrintAndLog(" l : load keys to memory from file specified by filename");
1599 PrintAndLog(" p : print keys loaded into memory\n");
1600 PrintAndLog("Samples:");
1601 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1602 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1603 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1604 PrintAndLog(" print keys : hf iclass managekeys p\n");
1608 int CmdHFiClassManageKeys(const char *Cmd
) {
1610 uint8_t dataLen
= 0;
1611 uint8_t KEY
[8] = {0};
1612 char filename
[FILE_PATH_SIZE
];
1613 uint8_t fileNameLen
= 0;
1614 bool errors
= false;
1615 uint8_t operation
= 0;
1619 while(param_getchar(Cmd
, cmdp
) != 0x00)
1621 switch(param_getchar(Cmd
, cmdp
))
1625 return usage_hf_iclass_managekeys();
1628 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
1629 if (fileNameLen
< 1) {
1630 PrintAndLog("No filename found after f");
1637 keyNbr
= param_get8(Cmd
, cmdp
+1);
1638 if (keyNbr
>= ICLASS_KEYS_MAX
) {
1639 PrintAndLog("Invalid block number");
1646 operation
+= 3; //set key
1647 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1648 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1649 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1651 PrintAndLog("\nERROR: Key is incorrect length\n");
1658 operation
+= 4; //print keys in memory
1663 operation
+= 5; //load keys from file
1668 operation
+= 6; //save keys to file
1672 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1676 if(errors
) return usage_hf_iclass_managekeys();
1678 if (operation
== 0){
1679 PrintAndLog("no operation specified (load, save, or print)\n");
1680 return usage_hf_iclass_managekeys();
1683 PrintAndLog("Too many operations specified\n");
1684 return usage_hf_iclass_managekeys();
1686 if (operation
> 4 && fileNameLen
== 0){
1687 PrintAndLog("You must enter a filename when loading or saving\n");
1688 return usage_hf_iclass_managekeys();
1692 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1693 case 4: return printKeys();
1694 case 5: return loadKeys(filename
);
1695 case 6: return saveKeys(filename
);
1701 static command_t CommandTable
[] =
1703 {"help", CmdHelp
, 1, "This help"},
1704 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1705 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1706 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1707 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1708 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1709 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1710 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1711 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1712 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1713 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1714 {"reader", CmdHFiClassReader
, 0, " Read an iClass tag"},
1715 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1716 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1717 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1718 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1719 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1720 {NULL
, NULL
, 0, NULL
}
1723 int CmdHFiClass(const char *Cmd
)
1725 CmdsParse(CommandTable
, Cmd
);
1729 int CmdHelp(const char *Cmd
)
1731 CmdsHelp(CommandTable
);