1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3 // Copyright (C) 2011 Gerhard de Koning Gans
4 // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende
6 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
7 // at your option, any later version. See the LICENSE.txt file for the text of
9 //-----------------------------------------------------------------------------
10 // High frequency iClass commands
11 //-----------------------------------------------------------------------------
17 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
19 #include "proxmark3.h"
21 #include "cmdparser.h"
22 #include "cmdhficlass.h"
26 #include "loclass/des.h"
27 #include "loclass/cipherutils.h"
28 #include "loclass/cipher.h"
29 #include "loclass/ikeys.h"
30 #include "loclass/elite_crack.h"
31 #include "loclass/fileutils.h"
32 #include "protocols.h"
38 static int CmdHelp(const char *Cmd
);
40 #define ICLASS_KEYS_MAX 8
41 static uint8_t iClass_Key_Table
[ICLASS_KEYS_MAX
][8] = {
42 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
43 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
44 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
45 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
46 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
47 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
48 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
49 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
52 typedef struct iclass_block
{
56 int xorbits_8(uint8_t val
)
58 uint8_t res
= val
^ (val
>> 1); //1st pass
59 res
= res
^ (res
>> 1); // 2nd pass
60 res
= res
^ (res
>> 2); // 3rd pass
61 res
= res
^ (res
>> 4); // 4th pass
65 int CmdHFiClassList(const char *Cmd
)
67 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
71 int CmdHFiClassSnoop(const char *Cmd
)
73 UsbCommand c
= {CMD_SNOOP_ICLASS
};
77 int usage_hf_iclass_sim()
79 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
80 PrintAndLog(" options");
81 PrintAndLog(" 0 <CSN> simulate the given CSN");
82 PrintAndLog(" 1 simulate default CSN");
83 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
84 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
85 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
86 PrintAndLog(" example: hf iclass sim 2");
87 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
88 PrintAndLog(" hf iclass sim 3");
93 int CmdHFiClassSim(const char *Cmd
)
96 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
99 return usage_hf_iclass_sim();
101 simType
= param_get8ex(Cmd
, 0, 0, 10);
105 if (param_gethex(Cmd
, 1, CSN
, 16)) {
106 PrintAndLog("A CSN should consist of 16 HEX symbols");
107 return usage_hf_iclass_sim();
110 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
114 PrintAndLog("Undefined simptype %d", simType
);
115 return usage_hf_iclass_sim();
118 uint8_t numberOfCSNs
=0;
121 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,NUM_CSNS
}};
122 UsbCommand resp
= {0};
124 uint8_t csns
[8*NUM_CSNS
] = {
125 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
126 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
127 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
128 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
129 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
130 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
131 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
132 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
133 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
134 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
135 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
136 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
137 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
138 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
139 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
141 memcpy(c
.d
.asBytes
, csns
, 8*NUM_CSNS
);
144 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
145 PrintAndLog("Command timed out");
149 uint8_t num_mac_responses
= resp
.arg
[1];
150 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
,NUM_CSNS
);
152 size_t datalen
= NUM_CSNS
*24;
154 * Now, time to dump to file. We'll use this format:
155 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
156 * So, it should wind up as
159 * The returndata from the pm3 is on the following format
160 * <4 byte NR><4 byte MAC>
161 * CC are all zeroes, CSN is the same as was sent in
163 void* dump
= malloc(datalen
);
164 memset(dump
,0,datalen
);//<-- Need zeroes for the CC-field
166 for(i
= 0 ; i
< NUM_CSNS
; i
++)
168 memcpy(dump
+i
*24, csns
+i
*8,8); //CSN
169 //8 zero bytes here...
170 //Then comes NR_MAC (eight bytes from the response)
171 memcpy(dump
+i
*24+16,resp
.d
.asBytes
+i
*8,8);
174 /** Now, save to dumpfile **/
175 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
179 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
,numberOfCSNs
}};
180 memcpy(c
.d
.asBytes
, CSN
, 8);
187 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
)
189 bool tagFound
= false;
190 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
191 FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_AA
}};
192 // loop in client not device - else on windows have a communication error
193 c
.arg
[0] |= FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
;
197 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
198 uint8_t readStatus
= resp
.arg
[0] & 0xff;
199 uint8_t *data
= resp
.d
.asBytes
;
202 PrintAndLog("Readstatus:%02x", readStatus
);
203 if( readStatus
== 0){
205 if (verbose
) PrintAndLog("Quitting...");
208 if( readStatus
& FLAG_ICLASS_READER_CSN
){
209 PrintAndLog("CSN: %s",sprint_hex(data
,8));
212 if( readStatus
& FLAG_ICLASS_READER_CC
) PrintAndLog("CC: %s",sprint_hex(data
+16,8));
213 if( readStatus
& FLAG_ICLASS_READER_CONF
){
214 printIclassDumpInfo(data
);
216 if (tagFound
&& !loop
) return 1;
218 if (verbose
) PrintAndLog("Command execute timeout");
225 int CmdHFiClassReader(const char *Cmd
)
227 return HFiClassReader(Cmd
, true, true);
230 int CmdHFiClassReader_Replay(const char *Cmd
)
232 uint8_t readerType
= 0;
233 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
236 PrintAndLog("Usage: hf iclass replay <MAC>");
237 PrintAndLog(" sample: hf iclass replay 00112233");
241 if (param_gethex(Cmd
, 0, MAC
, 8)) {
242 PrintAndLog("MAC must include 8 HEX symbols");
246 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
247 memcpy(c
.d
.asBytes
, MAC
, 4);
253 int hf_iclass_eload_usage()
255 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
256 PrintAndLog("Usage: hf iclass eload f <filename>");
258 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
262 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
263 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
264 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
268 int CmdHFiClassELoad(const char *Cmd
)
271 char opt
= param_getchar(Cmd
, 0);
272 if (strlen(Cmd
)<1 || opt
== 'h')
273 return hf_iclass_eload_usage();
275 //File handling and reading
277 char filename
[FILE_PATH_SIZE
];
278 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0)
280 f
= fopen(filename
, "rb");
282 return hf_iclass_eload_usage();
286 PrintAndLog("Failed to read from file '%s'", filename
);
290 fseek(f
, 0, SEEK_END
);
291 long fsize
= ftell(f
);
292 fseek(f
, 0, SEEK_SET
);
294 uint8_t *dump
= malloc(fsize
);
297 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
300 printIclassDumpInfo(dump
);
303 if (bytes_read
< fsize
)
305 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
310 uint32_t bytes_sent
= 0;
311 uint32_t bytes_remaining
= bytes_read
;
313 while(bytes_remaining
> 0){
314 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
315 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
316 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
318 bytes_remaining
-= bytes_in_packet
;
319 bytes_sent
+= bytes_in_packet
;
322 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
326 int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
)
328 FILE *f
= fopen(filename
, "rb");
330 PrintAndLog("Failed to read from file '%s'", filename
);
333 fseek(f
, 0, SEEK_END
);
334 long fsize
= ftell(f
);
335 fseek(f
, 0, SEEK_SET
);
336 size_t bytes_read
= fread(buffer
, 1, len
, f
);
340 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
343 if(bytes_read
!= len
)
345 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
351 int usage_hf_iclass_decrypt()
353 PrintAndLog("Usage: hf iclass decrypt f <tagdump> o ");
355 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
356 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
358 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
360 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
361 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
362 PrintAndLog("which is defined by the configuration block.");
366 int CmdHFiClassDecrypt(const char *Cmd
)
368 uint8_t key
[16] = { 0 };
369 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
371 usage_hf_iclass_decrypt();
374 PrintAndLog("Decryption file found... ");
375 char opt
= param_getchar(Cmd
, 0);
376 if (strlen(Cmd
)<1 || opt
== 'h')
377 return usage_hf_iclass_decrypt();
379 //Open the tagdump-file
381 char filename
[FILE_PATH_SIZE
];
382 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
) > 0)
384 f
= fopen(filename
, "rb");
386 return usage_hf_iclass_decrypt();
389 fseek(f
, 0, SEEK_END
);
390 long fsize
= ftell(f
);
391 fseek(f
, 0, SEEK_SET
);
392 uint8_t enc_dump
[8] = {0};
393 uint8_t *decrypted
= malloc(fsize
);
394 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
395 des3_set2key_dec( &ctx
, key
);
396 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
398 //Use the first block (CSN) for filename
399 char outfilename
[FILE_PATH_SIZE
] = { 0 };
400 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
401 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
402 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
405 while(bytes_read
== 8)
409 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
411 des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
413 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
414 bytes_read
= fread(enc_dump
, 1, 8, f
);
419 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
424 int usage_hf_iclass_encrypt(){
425 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
427 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
428 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
430 PrintAndLog("example: hf iclass encrypt 0102030405060708");
435 int iClassEncryptBlkData(uint8_t *blkData
)
437 uint8_t key
[16] = { 0 };
438 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
440 usage_hf_iclass_encrypt();
443 PrintAndLog("Decryption file found... ");
445 uint8_t decryptedData
[16];
446 uint8_t *decrypted
= decryptedData
;
447 des3_context ctx
= { DES_DECRYPT
,{ 0 } };
448 des3_set2key_enc( &ctx
, key
);
450 des3_crypt_ecb(&ctx
, blkData
,decrypted
);
451 //printvar("decrypted block", decrypted, 8);
452 memcpy(blkData
,decrypted
,8);
457 int CmdHFiClassEncryptBlk(const char *Cmd
)
459 uint8_t blkData
[8] = {0};
460 char opt
= param_getchar(Cmd
, 0);
461 if (strlen(Cmd
)<1 || opt
== 'h')
462 return usage_hf_iclass_encrypt();
464 //get the bytes to encrypt
465 if (param_gethex(Cmd
, 0, blkData
, 16))
467 PrintAndLog("BlockData must include 16 HEX symbols");
470 if (!iClassEncryptBlkData(blkData
)) return 0;
472 printvar("encrypted block", blkData
, 8);
476 void Calc_wb_mac(uint8_t blockno
,uint8_t *data
,uint8_t *div_key
,uint8_t MAC
[4]){
479 memcpy(WB
+ 1,data
,8);
480 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
481 //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]);
484 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
){
487 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
488 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
;
490 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
492 clearCommandBuffer();
494 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
496 PrintAndLog("Command execute timeout");
500 uint8_t isOK
= resp
.arg
[0] & 0xff;
501 uint8_t *data
= resp
.d
.asBytes
;
504 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
505 //PrintAndLog("isOk:%02x", isOK);
508 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
511 PrintAndLog("Failed to obtain CC! Aborting");
517 static bool select_and_auth(uint8_t *KEY
, uint8_t *MAC
, uint8_t *div_key
, bool use_credit_key
, bool elite
, bool verbose
) {
518 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
519 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
520 uint8_t keytable
[128] = {0};
522 uint8_t key_sel
[8] = {0};
523 uint8_t key_sel_p
[8] = { 0 };
525 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
529 hash2(KEY
, keytable
);
530 //Get the key index (hash1)
531 uint8_t key_index
[8] = {0};
532 hash1(CSN
, key_index
);
533 //printvar("hash1", key_index,8);
534 for(uint8_t i
= 0; i
< 8 ; i
++)
535 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
536 //PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
537 //printvar("k_sel", key_sel,8);
538 //Permute from iclass format to standard format
539 permutekey_rev(key_sel
, key_sel_p
);
540 used_key
= key_sel_p
;
544 //PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
545 //printvar("Used key",KEY,8);
546 diversifyKey(CSN
, used_key
, div_key
);
547 //PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
548 //printvar("Div key", div_key, 8);
549 //printvar("CC_NR:",CCNR,8);
550 doMAC(CCNR
, div_key
, MAC
);
551 //printvar("MAC", MAC, 4);
553 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
554 memcpy(d
.d
.asBytes
, MAC
, 4);
555 clearCommandBuffer();
557 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
559 PrintAndLog("Auth Command execute timeout");
562 uint8_t isOK
= resp
.arg
[0] & 0xff;
564 PrintAndLog("Authentication error");
570 int usage_hf_iclass_dump(){
571 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e\n");
572 PrintAndLog("Options:");
573 PrintAndLog(" f <filename> : specify a filename to save dump to");
574 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
575 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
576 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
577 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
578 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
579 PrintAndLog(" NOTE: * = required");
580 PrintAndLog("Samples:");
581 PrintAndLog(" hf iclass dump k 001122334455667B");
582 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
583 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
587 int CmdHFiClassReader_Dump(const char *Cmd
){
589 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
590 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
591 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
595 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
596 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
599 uint8_t fileNameLen
= 0;
600 char filename
[FILE_PATH_SIZE
]={0};
601 char tempStr
[50] = {0};
602 bool have_credit_key
= false;
607 while(param_getchar(Cmd
, cmdp
) != 0x00)
609 switch(param_getchar(Cmd
, cmdp
))
613 return usage_hf_iclass_dump();
616 have_credit_key
= true;
617 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
619 errors
= param_gethex(tempStr
, 0, CreditKEY
, dataLen
);
620 } else if (dataLen
== 1) {
621 keyNbr
= param_get8(Cmd
, cmdp
+1);
622 if (keyNbr
<= ICLASS_KEYS_MAX
) {
623 memcpy(CreditKEY
, iClass_Key_Table
[keyNbr
], 8);
625 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
629 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
641 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
642 if (fileNameLen
< 1) {
643 PrintAndLog("No filename found after f");
650 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
652 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
653 } else if (dataLen
== 1) {
654 keyNbr
= param_get8(Cmd
, cmdp
+1);
655 if (keyNbr
<= ICLASS_KEYS_MAX
) {
656 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
658 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
662 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
668 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
672 if(errors
) return usage_hf_iclass_dump();
675 if (cmdp
< 2) return usage_hf_iclass_dump();
677 //get config and first 3 blocks
678 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
679 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
681 uint8_t tag_data
[255*8];
682 clearCommandBuffer();
684 if (WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
685 uint8_t readStatus
= resp
.arg
[0] & 0xff;
686 uint8_t *data
= resp
.d
.asBytes
;
688 if( readStatus
== 0){
690 PrintAndLog("No tag found...");
693 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
694 memcpy(tag_data
, data
, 8*3);
695 /*for (; blockno < 3; blockno++) {
696 PrintAndLog(" | %02X | %02X%02X%02X%02X%02X%02X%02X%02X |", blockno,
697 data[(blockno*8)+0],data[(blockno*8)+1],data[(blockno*8)+2],data[(blockno*8)+3],
698 data[(blockno*8)+4],data[(blockno*8)+5],data[(blockno*8)+6],data[(blockno*8)+7]);
703 if (data
[13] & 0x80) {
704 // large memory - not able to dump pages currently
709 //PrintAndLog("maxBlk: %02X",maxBlk);
712 PrintAndLog("Command execute timeout");
716 if (!select_and_auth(KEY
, MAC
, div_key
, false, elite
, false)){
717 //try twice - for some reason it sometimes fails the first time...
718 if (!select_and_auth(KEY
, MAC
, div_key
, false, elite
, false)){
719 ul_switch_off_field();
723 //print debit div_key
724 //PrintAndLog(" | 03 | %02X%02X%02X%02X%02X%02X%02X%02X |",
725 // div_key[0],div_key[1],div_key[2],div_key[3],
726 // div_key[4],div_key[5],div_key[6],div_key[7]);
728 if (have_credit_key
){
730 //PrintAndLog("attempt 1 to auth with credit key");
731 ul_switch_off_field();
732 memset(c_div_key
,0,8);
734 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false)){
735 //try twice - for some reason it sometimes fails the first time...
736 memset(c_div_key
,0,8);
738 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false)){
739 ul_switch_off_field();
743 //print credit div_key
744 //PrintAndLog(" | 04 | %02X%02X%02X%02X%02X%02X%02X%02X |",
745 // div_key[0],div_key[1],div_key[2],div_key[3],
746 // div_key[4],div_key[5],div_key[6],div_key[7]);
749 //PrintAndLog("attempt 2 to auth with debit key");
750 ul_switch_off_field();
753 if (!select_and_auth(KEY
, MAC
, div_key
, false, elite
, false)){
754 //try twice - for some reason it sometimes fails the first time...
755 if (!select_and_auth(KEY
, MAC
, div_key
, false, elite
, false)){
756 ul_switch_off_field();
761 //PrintAndLog("have %d blocks",blockno);
763 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1, 0x88}};
764 clearCommandBuffer();
766 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
767 PrintAndLog("Command execute time-out 1");
770 uint32_t blocksRead
= resp
.arg
[1];
771 uint8_t isOK
= resp
.arg
[0] & 0xff;
772 if (!isOK
&& !blocksRead
) {
773 PrintAndLog("Read Block Failed");
776 uint32_t startindex
= resp
.arg
[2];
777 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
778 PrintAndLog("Data exceeded Buffer size!");
779 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
781 //PrintAndLog("blocksread: %d, blockno: %d, startindex: %x",blocksRead,blockno,startindex);
782 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
);
783 WaitForResponse(CMD_ACK
,NULL
);
784 uint32_t gotBytes
= blocksRead
*8 + blockno
*8;
786 //PrintAndLog("have %d blocks",gotBytes/8);
788 if (have_credit_key
&& maxBlk
> blockno
+numblks
+1) {
790 ul_switch_off_field();
791 //PrintAndLog("attempt 2 to auth with credit key");
792 memset(c_div_key
,0,8);
794 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false)){
795 //try twice - for some reason it sometimes fails the first time...
796 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false)){
797 ul_switch_off_field();
801 w
.arg
[0] = blockno
+ blocksRead
;
802 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
804 clearCommandBuffer();
806 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
807 PrintAndLog("Command execute timeout 2");
810 uint8_t isOK
= resp
.arg
[0] & 0xff;
811 blocksRead
= resp
.arg
[1];
812 if (!isOK
&& !blocksRead
) {
813 PrintAndLog("Read Block Failed 2");
817 startindex
= resp
.arg
[2];
818 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
819 PrintAndLog("Data exceeded Buffer size!");
820 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
822 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
);
823 WaitForResponse(CMD_ACK
,NULL
);
825 gotBytes
+= blocksRead
*8;
826 //PrintAndLog("have %d blocks",gotBytes/8);
829 memcpy(tag_data
+(3*8),div_key
,8);
830 memcpy(tag_data
+(4*8),c_div_key
,8);
832 for (blockno
= 0; blockno
< gotBytes
/8; blockno
++){
833 PrintAndLog(" | %02X | %02X%02X%02X%02X%02X%02X%02X%02X |", blockno
,
834 tag_data
[(blockno
*8)+0],tag_data
[(blockno
*8)+1],tag_data
[(blockno
*8)+2],tag_data
[(blockno
*8)+3],
835 tag_data
[(blockno
*8)+4],tag_data
[(blockno
*8)+5],tag_data
[(blockno
*8)+6],tag_data
[(blockno
*8)+7]);
837 if (filename
[0] == 0){
838 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
839 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
840 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
842 saveFile(filename
,"bin",tag_data
, gotBytes
);
843 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
848 int CmdHFiClassReader_Dump(const char *Cmd)
850 uint8_t readerType = 0;
851 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
852 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
853 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
854 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
855 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
856 uint8_t keytable[128] = {0};
858 bool use_credit_key = false;
863 return usage_hf_iclass_dump();
866 if (param_gethex(Cmd, 0, KEY, 16))
868 PrintAndLog("KEY must include 16 HEX symbols");
872 if (param_getchar(Cmd, 1) == 'e')
874 PrintAndLog("Elite switch on");
878 hash2(KEY, keytable);
879 printarr_human_readable("keytable", keytable, 128);
881 if (param_getchar(Cmd, 2) == 'c')
882 use_credit_key = true;
883 } else if (param_getchar(Cmd, 1) == 'c'){
884 use_credit_key = true;
888 uint8_t key_sel[8] = {0};
889 uint8_t key_sel_p[8] = { 0 };
891 UsbCommand c = {CMD_READER_ICLASS, {0}};
892 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE| FLAG_ICLASS_READER_CC;
894 c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY;
895 clearCommandBuffer();
898 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
900 PrintAndLog("Command execute timeout");
904 uint8_t isOK = resp.arg[0] & 0xff;
905 uint8_t * data = resp.d.asBytes;
908 memcpy(CCNR,data+16,8);
910 PrintAndLog("isOk:%02x", isOK);
914 PrintAndLog("CSN: %s",sprint_hex(CSN,8));
917 PrintAndLog("Failed to obtain CC! Aborting");
924 //Get the key index (hash1)
925 uint8_t key_index[8] = {0};
927 hash1(CSN, key_index);
928 printvar("hash1", key_index,8);
929 for(i = 0; i < 8 ; i++)
930 key_sel[i] = keytable[key_index[i]] & 0xFF;
931 PrintAndLog("Pre-fortified 'permuted' HS key that would be needed by an iclass reader to talk to above CSN:");
932 printvar("k_sel", key_sel,8);
933 //Permute from iclass format to standard format
934 permutekey_rev(key_sel,key_sel_p);
935 used_key = key_sel_p;
940 PrintAndLog("Pre-fortified key that would be needed by the OmniKey reader to talk to above CSN:");
941 printvar("Used key",used_key,8);
942 diversifyKey(CSN,used_key, div_key);
943 PrintAndLog("Hash0, a.k.a diversified key, that is computed using Ksel and stored in the card (Block 3):");
944 printvar("Div key", div_key, 8);
945 printvar("CC_NR:",CCNR,12);
946 doMAC(CCNR,div_key, MAC);
947 printvar("MAC", MAC, 4);
949 uint8_t iclass_data[32000] = {0};
950 uint32_t iclass_datalen = 0;
951 uint32_t iclass_blocksFailed = 0;//Set to 1 if dump was incomplete
953 UsbCommand d = {CMD_READER_ICLASS_REPLAY, {readerType}};
954 memcpy(d.d.asBytes, MAC, 4);
955 clearCommandBuffer();
957 PrintAndLog("Waiting for device to dump data. Press button on device and key on keyboard to abort...");
962 printf("\naborted via keyboard!\n");
965 if(WaitForResponseTimeout(CMD_ACK,&resp,4500))
967 uint32_t dataLength = resp.arg[0];
968 iclass_blocksFailed |= resp.arg[1];
971 PrintAndLog("Got %d bytes data (total so far %d)" ,dataLength,iclass_datalen);
972 memcpy(iclass_data+iclass_datalen, resp.d.asBytes,dataLength);
973 iclass_datalen += dataLength;
975 {//Last transfer, datalength 0 means the dump is finished
976 PrintAndLog("Dumped %d bytes of data from tag. ", iclass_datalen);
977 if(iclass_blocksFailed)
979 PrintAndLog("OBS! Some blocks failed to be dumped correctly!");
981 if(iclass_datalen > 0)
983 char filename[100] = {0};
984 //create a preferred filename
985 snprintf(filename, 100,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
986 CSN[0],CSN[1],CSN[2],CSN[3],
987 CSN[4],CSN[5],CSN[6],CSN[7]);
988 //Place the div_key in block 3
989 memcpy(iclass_data+(3*8), div_key, 8);
990 saveFile(filename,"bin",iclass_data, iclass_datalen );
992 //Aaaand we're finished
1001 int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool verbose
){
1002 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1003 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1004 uint8_t keyType
= (use_credit_key
) ? 0x18 : 0x88;
1005 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, verbose
))
1010 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
1011 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
, keyType
}};
1012 memcpy(w
.d
.asBytes
, bldata
, 8);
1013 memcpy(w
.d
.asBytes
+ 8,MAC
, 4);
1015 clearCommandBuffer();
1017 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1019 PrintAndLog("Write Command execute timeout");
1022 uint8_t isOK
= resp
.arg
[0] & 0xff;
1024 PrintAndLog("Write Block Failed");
1027 PrintAndLog("Write Block Successful");
1032 int usage_hf_iclass_writeblock() {
1033 PrintAndLog("Options:");
1034 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1035 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
1036 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1037 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1038 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1039 PrintAndLog("Samples:");
1040 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
1041 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
1042 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
1046 int CmdHFiClass_WriteBlock(const char *Cmd
) {
1048 uint8_t bldata
[8]={0};
1049 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1051 uint8_t dataLen
= 0;
1052 char tempStr
[50] = {0};
1053 bool use_credit_key
= false;
1055 bool errors
= false;
1057 while(param_getchar(Cmd
, cmdp
) != 0x00)
1059 switch(param_getchar(Cmd
, cmdp
))
1063 return usage_hf_iclass_writeblock();
1066 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1067 PrintAndLog("Block No must include 2 HEX symbols\n");
1074 use_credit_key
= true;
1079 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
1081 PrintAndLog("KEY must include 16 HEX symbols\n");
1093 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1094 if (dataLen
== 16) {
1095 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1096 } else if (dataLen
== 1) {
1097 keyNbr
= param_get8(Cmd
, cmdp
+1);
1098 if (keyNbr
<= ICLASS_KEYS_MAX
) {
1099 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1101 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1105 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1111 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1115 if(errors
) return usage_hf_iclass_writeblock();
1118 if (cmdp
< 6) return usage_hf_iclass_writeblock();
1120 return WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, true);
1123 int usage_hf_iclass_clone() {
1124 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> e c");
1125 PrintAndLog("Options:");
1126 PrintAndLog(" f <filename>: specify a filename to clone from");
1127 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
1128 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
1129 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1130 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1131 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1132 PrintAndLog("Samples:");
1133 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
1134 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
1135 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
1139 int CmdHFiClassCloneTag(const char *Cmd
) {
1140 char filename
[FILE_PATH_SIZE
];
1141 char tempStr
[50]={0};
1142 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1144 uint8_t fileNameLen
= 0;
1145 uint8_t startblock
= 0;
1146 uint8_t endblock
= 0;
1147 uint8_t dataLen
= 0;
1148 bool use_credit_key
= false;
1150 bool errors
= false;
1152 while(param_getchar(Cmd
, cmdp
) != 0x00)
1154 switch(param_getchar(Cmd
, cmdp
))
1158 return usage_hf_iclass_clone();
1161 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
1162 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1169 use_credit_key
= true;
1179 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
1180 if (fileNameLen
< 1) {
1181 PrintAndLog("No filename found after f");
1188 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1189 if (dataLen
== 16) {
1190 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1191 } else if (dataLen
== 1) {
1192 keyNbr
= param_get8(Cmd
, cmdp
+1);
1193 if (keyNbr
<= ICLASS_KEYS_MAX
) {
1194 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1196 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1200 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1207 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1208 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1214 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1218 if(errors
) return usage_hf_iclass_clone();
1221 if (cmdp
< 8) return usage_hf_iclass_clone();
1225 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1227 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1228 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1230 // file handling and reading
1231 f
= fopen(filename
,"rb");
1233 PrintAndLog("Failed to read from file '%s'", filename
);
1238 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1241 // now read data from the file from block 6 --- 19
1242 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1243 // 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,
1244 // else we have to create a share memory
1246 fseek(f
,startblock
*8,SEEK_SET
);
1247 fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
);
1249 for (i = 0; i < endblock - startblock+1; i++){
1250 printf("block [%02x] [%02x%02x%02x%02x%02x%02x%02x%02x]\n",i + startblock,tag_data[i].d[0],tag_data[i].d[1],tag_data[i].d[2],tag_data[i].d[3],tag_data[i].d[4],tag_data[i].d[5],tag_data[i].d[6],tag_data[i].d[7]);
1253 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1254 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1256 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, true))
1259 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
,((use_credit_key
) ? 0x18 : 0x88)}};
1261 // calculate all mac for every the block we will write
1262 for (i
= startblock
; i
<= endblock
; i
++){
1263 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1264 // usb command d start pointer = d + (i - 6) * 12
1265 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1266 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1268 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1269 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1270 memcpy(ptr
+ 8,MAC
, 4);
1273 for (i
= 0; i
<= endblock
- startblock
;i
++){
1274 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1275 printf("block [%02x]",i
+ startblock
);
1276 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]);
1277 printf(" MAC [%02x%02x%02x%02x]\n",p
[8],p
[9],p
[10],p
[11]);
1281 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1283 PrintAndLog("Command execute timeout");
1289 int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool verbose
){
1290 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1291 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1293 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, verbose
))
1297 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
, keyType
}};
1298 clearCommandBuffer();
1300 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1302 PrintAndLog("Command execute timeout");
1305 uint8_t isOK
= resp
.arg
[0] & 0xff;
1307 PrintAndLog("Read Block Failed");
1310 //data read is stored in: resp.d.asBytes[0-15]
1311 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1315 int usage_hf_iclass_readblock(){
1316 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e\n");
1317 PrintAndLog("Options:");
1318 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1319 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1320 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1321 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1322 PrintAndLog("Samples:");
1323 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1324 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1325 PrintAndLog(" hf iclass readblk b 0A k 0");
1329 int CmdHFiClass_ReadBlock(const char *Cmd
)
1332 uint8_t keyType
= 0x88; //debit key
1333 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1335 uint8_t dataLen
= 0;
1336 char tempStr
[50] = {0};
1338 bool errors
= false;
1340 while(param_getchar(Cmd
, cmdp
) != 0x00)
1342 switch(param_getchar(Cmd
, cmdp
))
1346 return usage_hf_iclass_readblock();
1349 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1350 PrintAndLog("Block No must include 2 HEX symbols\n");
1367 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1368 if (dataLen
== 16) {
1369 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1370 } else if (dataLen
== 1) {
1371 keyNbr
= param_get8(Cmd
, cmdp
+1);
1372 if (keyNbr
<= ICLASS_KEYS_MAX
) {
1373 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1375 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1379 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1385 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1389 if(errors
) return usage_hf_iclass_readblock();
1392 if (cmdp
< 4) return usage_hf_iclass_readblock();
1394 return ReadBlock(KEY
, blockno
, keyType
, elite
, true);
1397 int CmdHFiClass_loclass(const char *Cmd
)
1399 char opt
= param_getchar(Cmd
, 0);
1401 if (strlen(Cmd
)<1 || opt
== 'h') {
1402 PrintAndLog("Usage: hf iclass loclass [options]");
1403 PrintAndLog("Options:");
1404 PrintAndLog("h Show this help");
1405 PrintAndLog("t Perform self-test");
1406 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1407 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1408 PrintAndLog(" malicious CSNs, and their protocol responses");
1409 PrintAndLog(" The the binary format of the file is expected to be as follows: ");
1410 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1411 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1412 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1413 PrintAndLog(" ... totalling N*24 bytes");
1416 char fileName
[255] = {0};
1419 if(param_getstr(Cmd
, 1, fileName
) > 0)
1421 return bruteforceFileNoKeys(fileName
);
1424 PrintAndLog("You must specify a filename");
1429 int errors
= testCipherUtils();
1430 errors
+= testMAC();
1431 errors
+= doKeyTests(0);
1432 errors
+= testElite();
1435 prnlog("OBS! There were errors!!!");
1443 int usage_hf_iclass_readtagfile(){
1444 PrintAndLog("Usage: hf iclass readtagfile <filename>");
1448 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
){
1449 uint8_t blockdata
[8];
1451 memcpy(&mem_config
, iclass_dump
+ 13,1);
1452 uint8_t maxmemcount
;
1453 uint8_t filemaxblock
= filesize
/ 8;
1454 if (mem_config
== 0x80)
1459 if (startblock
== 0)
1461 if ((endblock
> maxmemcount
) || (endblock
== 0))
1462 endblock
= maxmemcount
;
1463 if (endblock
> filemaxblock
)
1464 endblock
= filemaxblock
;
1467 while (i
< endblock
){
1468 printf("block[%02X]: ",i
);
1469 memcpy(blockdata
,iclass_dump
+ (i
* 8),8);
1470 for (j
= 0;j
< 8;j
++)
1471 printf("%02X ",blockdata
[j
]);
1475 if ((i
< filemaxblock
) && (i
< maxmemcount
)){
1476 printf("block[%02X]: ",i
);
1477 memcpy(blockdata
,iclass_dump
+ (i
* 8),8);
1478 for (j
= 0;j
< 8;j
++)
1479 printf("%02X",blockdata
[j
]);
1484 int CmdHFiClassReadTagFile(const char *Cmd
)
1490 char filename
[FILE_PATH_SIZE
];
1491 if (param_getstr(Cmd
, 0, filename
) < 1)
1492 return usage_hf_iclass_readtagfile();
1493 if (param_getstr(Cmd
,1,(char *)&tempnum
) < 1)
1496 sscanf(tempnum
,"%d",&startblock
);
1498 if (param_getstr(Cmd
,2,(char *)&tempnum
) < 1)
1501 sscanf(tempnum
,"%d",&endblock
);
1502 // file handling and reading
1503 f
= fopen(filename
,"rb");
1505 PrintAndLog("Failed to read from file '%s'", filename
);
1508 fseek(f
, 0, SEEK_END
);
1509 long fsize
= ftell(f
);
1510 fseek(f
, 0, SEEK_SET
);
1512 uint8_t *dump
= malloc(fsize
);
1515 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1517 uint8_t *csn
= dump
;
1518 printf("CSN : %02X %02X %02X %02X %02X %02X %02X %02X\n",csn
[0],csn
[1],csn
[2],csn
[3],csn
[4],csn
[5],csn
[6],csn
[7]);
1519 // printIclassDumpInfo(dump);
1520 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1525 uint64_t xorcheck(uint64_t sdiv
,uint64_t hdiv
){
1526 uint64_t new_div
= 0x00;
1532 uint64_t hexarray_to_uint64(uint8_t *key
){
1535 for (int i
= 0;i
< 8;i
++)
1536 sprintf(&temp
[(i
*2)],"%02X",key
[i
]);
1538 if (sscanf(temp
,"%016"llX
,&uint_key
) < 1)
1543 int usage_hf_iclass_calc_ekey(){
1544 PrintAndLog("Usage: hf iclass calc_ekey <STDKEY> <ELITE key> [c]");
1548 int CmdHFiClassCalcEKey(const char *Cmd
){
1550 uint8_t ELITEKEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1551 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1552 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1553 uint8_t std_div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1554 uint8_t elite_div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1555 uint8_t keytable
[128] = {0};
1556 uint8_t key_index
[8] = {0};
1557 uint64_t new_div_key
;
1558 uint64_t i_elite_div_key
;
1559 uint64_t i_std_div_key
;
1560 bool use_credit_key
= false;
1561 //memcpy(STDKEY,GLOBAL_KEY,sizeof(STDKEY));
1563 if (strlen(Cmd
) < 2)
1564 return usage_hf_iclass_calc_ekey();
1566 if (param_gethex(Cmd
, 0, STDKEY
, 16))
1567 return usage_hf_iclass_calc_ekey();
1569 if (param_gethex(Cmd
, 1, ELITEKEY
, 16) != 0)
1570 return usage_hf_iclass_calc_ekey();
1572 if (param_getchar(Cmd
, 2)=='c')
1573 use_credit_key
= true;
1575 hash2(ELITEKEY
, keytable
);
1577 uint8_t key_sel
[8] = { 0 };
1578 uint8_t key_sel_p
[8] = { 0 };
1580 if (!select_only(CSN
, CCNR
, use_credit_key
, true))
1583 diversifyKey(CSN
, STDKEY
, std_div_key
);
1585 // printvar("(S)Div key", std_div_key, 8);
1586 hash1(CSN
, key_index
);
1587 for(i
= 0; i
< 8 ; i
++)
1588 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1590 //Permute from iclass format to standard format
1591 permutekey_rev(key_sel
, key_sel_p
);
1592 diversifyKey(CSN
, key_sel_p
, elite_div_key
);
1593 // printvar("(E)Div key", elite_div_key, 8);
1594 i_elite_div_key
= hexarray_to_uint64(elite_div_key
);
1595 i_std_div_key
= hexarray_to_uint64(std_div_key
);
1596 new_div_key
= xorcheck(i_std_div_key
, i_elite_div_key
);
1597 printf("New Div Key : %016"llX
"\n",new_div_key
);
1601 int loadKeys(char *filename
){
1603 f
= fopen(filename
,"rb");
1605 PrintAndLog("Failed to read from file '%s'", filename
);
1608 fseek(f
, 0, SEEK_END
);
1609 long fsize
= ftell(f
);
1610 fseek(f
, 0, SEEK_SET
);
1612 uint8_t *dump
= malloc(fsize
);
1614 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1616 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1617 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1622 for (; i
< bytes_read
/8; i
++){
1623 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1626 PrintAndLog("%u keys loaded", i
);
1630 int saveKeys(char *filename
){
1632 f
= fopen(filename
,"wb");
1634 printf("error opening file %s\n",filename
);
1637 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1638 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1639 PrintAndLog("save key failed to write to file: %s", filename
);
1649 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1650 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1656 int usage_hf_iclass_managekeys(){
1657 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1658 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1659 PrintAndLog(" Options:");
1660 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1661 PrintAndLog(" k <key> : set a key in memory");
1662 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1663 PrintAndLog(" s : save keys in memory to file specified by filename");
1664 PrintAndLog(" l : load keys to memory from file specified by filename");
1665 PrintAndLog(" p : print keys loaded into memory\n");
1666 PrintAndLog("Samples:");
1667 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1668 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1669 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1670 PrintAndLog(" print keys : hf iclass managekeys p\n");
1674 int CmdManageKeys(const char *Cmd
){
1676 uint8_t dataLen
= 0;
1677 uint8_t KEY
[8] = {0};
1678 char filename
[FILE_PATH_SIZE
];
1679 uint8_t fileNameLen
= 0;
1680 bool errors
= false;
1681 uint8_t operation
= 0;
1685 while(param_getchar(Cmd
, cmdp
) != 0x00)
1687 switch(param_getchar(Cmd
, cmdp
))
1691 return usage_hf_iclass_managekeys();
1694 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
);
1695 if (fileNameLen
< 1) {
1696 PrintAndLog("No filename found after f");
1703 keyNbr
= param_get8(Cmd
, cmdp
+1);
1705 PrintAndLog("Wrong block number");
1712 operation
+= 3; //set key
1713 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
);
1714 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1715 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1717 PrintAndLog("\nERROR: Key is incorrect length\n");
1724 operation
+= 4; //print keys in memory
1729 operation
+= 5; //load keys from file
1734 operation
+= 6; //save keys to file
1738 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1742 if(errors
) return usage_hf_iclass_managekeys();
1744 if (operation
== 0){
1745 PrintAndLog("no operation specified (load, save, or print)\n");
1746 return usage_hf_iclass_managekeys();
1749 PrintAndLog("Too many operations specified\n");
1750 return usage_hf_iclass_managekeys();
1752 if (operation
> 4 && fileNameLen
== 0){
1753 PrintAndLog("You must enter a filename when loading or saving\n");
1754 return usage_hf_iclass_managekeys();
1758 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1759 case 4: return printKeys();
1760 case 5: return loadKeys(filename
);
1761 case 6: return saveKeys(filename
);
1767 static command_t CommandTable
[] =
1769 {"help", CmdHelp
, 1, "This help"},
1770 {"calc_ekey", CmdHFiClassCalcEKey
, 0, "Get Elite Diversified key (block 3) to write to convert std to elite"},
1771 {"clone", CmdHFiClassCloneTag
, 0, "Authenticate and Clone from iClass bin file"},
1772 {"decrypt", CmdHFiClassDecrypt
, 1, "Decrypt tagdump" },
1773 {"dump", CmdHFiClassReader_Dump
, 0, "Authenticate and Dump iClass tag's AA1"},
1774 {"eload", CmdHFiClassELoad
, 0, "[experimental] Load data into iClass emulator memory"},
1775 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "[blockData] Encrypt given block data"},
1776 {"list", CmdHFiClassList
, 0, "[Deprecated] List iClass history"},
1777 //{"load", CmdHFiClass_load, 0, "Load from tagfile to iClass card"},
1778 {"loclass", CmdHFiClass_loclass
, 1, "Use loclass to perform bruteforce of reader attack dump"},
1779 {"managekeys", CmdManageKeys
, 1, "Manage the keys to use with iClass"},
1780 {"readblk", CmdHFiClass_ReadBlock
, 0, "Authenticate and Read iClass block"},
1781 {"reader", CmdHFiClassReader
, 0, "Read an iClass tag"},
1782 {"readtagfile", CmdHFiClassReadTagFile
, 1, "Display Content from tagfile"},
1783 {"replay", CmdHFiClassReader_Replay
, 0, "Read an iClass tag via Reply Attack"},
1784 {"sim", CmdHFiClassSim
, 0, "Simulate iClass tag"},
1785 {"snoop", CmdHFiClassSnoop
, 0, "Eavesdrop iClass communication"},
1786 {"writeblk", CmdHFiClass_WriteBlock
, 0, "Authenticate and Write iClass block"},
1787 {NULL
, NULL
, 0, NULL
}
1790 int CmdHFiClass(const char *Cmd
)
1792 CmdsParse(CommandTable
, Cmd
);
1796 int CmdHelp(const char *Cmd
)
1798 CmdsHelp(CommandTable
);