1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3 // Copyright (C) 2011 Gerhard de Koning Gans
4 // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende
6 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
7 // at your option, any later version. See the LICENSE.txt file for the text of
9 //-----------------------------------------------------------------------------
10 // High frequency iClass commands
11 //-----------------------------------------------------------------------------
18 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
21 #include "cmdparser.h"
22 #include "cmdhficlass.h"
26 #include "mbedtls/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"
35 #include "util_posix.h"
36 #include "cmdhf14a.h" // DropField()
38 static int CmdHelp(const char *Cmd
);
40 #define ICLASS_KEYS_MAX 8
41 static uint8_t iClass_Key_Table
[ICLASS_KEYS_MAX
][8] = {
42 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
43 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
44 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
45 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
46 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
47 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
48 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
49 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
52 typedef struct iclass_block
{
56 int usage_hf_iclass_chk(void) {
57 PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");
58 PrintAndLog("Usage: hf iclass chk [h|e|r] <f (*.dic)>");
59 PrintAndLog("Options:");
60 PrintAndLog("h Show this help");
61 PrintAndLog("f <filename> Dictionary file with default iclass keys");
62 PrintAndLog(" e target Elite / High security key scheme");
63 PrintAndLog(" r interpret dictionary file as raw (diversified keys)");
64 PrintAndLog("Samples:");
65 PrintAndLog(" hf iclass chk f default_iclass_keys.dic");
66 PrintAndLog(" hf iclass chk f default_iclass_keys.dic e");
70 int xorbits_8(uint8_t val
) {
71 uint8_t res
= val
^ (val
>> 1); //1st pass
72 res
= res
^ (res
>> 1); // 2nd pass
73 res
= res
^ (res
>> 2); // 3rd pass
74 res
= res
^ (res
>> 4); // 4th pass
78 int CmdHFiClassList(const char *Cmd
) {
79 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
83 int CmdHFiClassSnoop(const char *Cmd
) {
84 UsbCommand c
= {CMD_SNOOP_ICLASS
};
89 int usage_hf_iclass_sim(void) {
90 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
91 PrintAndLog(" options");
92 PrintAndLog(" 0 <CSN> simulate the given CSN");
93 PrintAndLog(" 1 simulate default CSN");
94 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
95 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
96 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
97 PrintAndLog(" example: hf iclass sim 2");
98 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
99 PrintAndLog(" hf iclass sim 3");
104 int CmdHFiClassSim(const char *Cmd
) {
106 uint8_t CSN
[8] = {0, 0, 0, 0, 0, 0, 0, 0};
109 return usage_hf_iclass_sim();
111 simType
= param_get8ex(Cmd
, 0, 0, 10);
113 if (simType
== ICLASS_SIM_MODE_CSN
) {
114 if (param_gethex(Cmd
, 1, CSN
, 16)) {
115 PrintAndLog("A CSN should consist of 16 HEX symbols");
116 return usage_hf_iclass_sim();
118 PrintAndLog("--simtype:%02x csn:%s", simType
, sprint_hex(CSN
, 8));
121 uint8_t numberOfCSNs
= 0;
122 if (simType
== ICLASS_SIM_MODE_READER_ATTACK
) {
123 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
, NUM_CSNS
}};
124 UsbCommand resp
= {0};
126 uint8_t csns
[8 * NUM_CSNS
] = {
127 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
128 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
129 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
130 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
131 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
132 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
133 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
134 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
135 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
136 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
137 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
138 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
139 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
140 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
141 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
143 memcpy(c
.d
.asBytes
, csns
, 8 * NUM_CSNS
);
146 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, -1)) {
147 PrintAndLog("Command timed out");
151 uint8_t num_mac_responses
= resp
.arg
[1];
152 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses
, NUM_CSNS
);
154 size_t datalen
= NUM_CSNS
* 24;
156 * Now, time to dump to file. We'll use this format:
157 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
158 * So, it should wind up as
161 * The returndata from the pm3 is on the following format
162 * <8 byte CC><4 byte NR><4 byte MAC>
163 * CSN is the same as was sent in
165 void* dump
= malloc(datalen
);
166 for(int i
= 0; i
< NUM_CSNS
; i
++) {
167 memcpy(dump
+ i
*24, csns
+i
*8, 8); //CSN
168 //copy CC from response
169 memcpy(dump
+ i
*24 + 8, resp
.d
.asBytes
+ i
*16, 8);
170 //Then comes NR_MAC (eight bytes from the response)
171 memcpy(dump
+ i
*24 + 16, resp
.d
.asBytes
+ i
*16 + 8, 8);
173 /** Now, save to dumpfile **/
174 saveFile("iclass_mac_attack", "bin", dump
,datalen
);
177 } else if (simType
== ICLASS_SIM_MODE_CSN
|| simType
== ICLASS_SIM_MODE_CSN_DEFAULT
) {
178 UsbCommand c
= {CMD_SIMULATE_TAG_ICLASS
, {simType
, numberOfCSNs
}};
179 memcpy(c
.d
.asBytes
, CSN
, 8);
183 PrintAndLog("Undefined simtype %d", simType
);
184 return usage_hf_iclass_sim();
190 int HFiClassReader(const char *Cmd
, bool loop
, bool verbose
) {
191 bool tagFound
= false;
192 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
193 FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_AA
|
194 FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
} };
195 // loop in client not device - else on windows have a communication error
199 if (WaitForResponseTimeout(CMD_ACK
,&resp
, 4500)) {
200 uint8_t readStatus
= resp
.arg
[0] & 0xff;
201 uint8_t *data
= resp
.d
.asBytes
;
203 // no tag found or button pressed
204 if( (readStatus
== 0 && !loop
) || readStatus
== 0xFF) {
206 if (verbose
) PrintAndLog("Quitting...");
210 if( readStatus
& FLAG_ICLASS_READER_CSN
) {
211 PrintAndLog(" CSN: %s",sprint_hex(data
,8));
214 if( readStatus
& FLAG_ICLASS_READER_CC
) {
215 PrintAndLog(" CC: %s",sprint_hex(data
+16,8));
217 if( readStatus
& FLAG_ICLASS_READER_CONF
) {
218 printIclassDumpInfo(data
);
220 if (readStatus
& FLAG_ICLASS_READER_AA
) {
222 PrintAndLog(" AppIA: %s",sprint_hex(data
+8*5,8));
223 for (int i
= 0; i
<8; i
++) {
224 if (data
[8*5+i
] != 0xFF) {
228 PrintAndLog(" : Possible iClass %s",(legacy
) ? "(legacy tag)" : "(NOT legacy tag)");
231 if (tagFound
&& !loop
) return 1;
233 if (verbose
) PrintAndLog("Command execute timeout");
240 int CmdHFiClassReader(const char *Cmd
) {
241 return HFiClassReader(Cmd
, true, true);
244 int CmdHFiClassReader_Replay(const char *Cmd
) {
245 uint8_t readerType
= 0;
246 uint8_t MAC
[4]={0x00, 0x00, 0x00, 0x00};
249 PrintAndLog("Usage: hf iclass replay <MAC>");
250 PrintAndLog(" sample: hf iclass replay 00112233");
254 if (param_gethex(Cmd
, 0, MAC
, 8)) {
255 PrintAndLog("MAC must include 8 HEX symbols");
259 UsbCommand c
= {CMD_READER_ICLASS_REPLAY
, {readerType
}};
260 memcpy(c
.d
.asBytes
, MAC
, 4);
266 int iclassEmlSetMem(uint8_t *data
, int blockNum
, int blocksCount
) {
267 UsbCommand c
= {CMD_MIFARE_EML_MEMSET
, {blockNum
, blocksCount
, 0}};
268 memcpy(c
.d
.asBytes
, data
, blocksCount
* 16);
273 int hf_iclass_eload_usage(void) {
274 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
275 PrintAndLog("Usage: hf iclass eload f <filename>");
277 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
281 int CmdHFiClassELoad(const char *Cmd
) {
283 char opt
= param_getchar(Cmd
, 0);
284 if (strlen(Cmd
)<1 || opt
== 'h')
285 return hf_iclass_eload_usage();
287 //File handling and reading
289 char filename
[FILE_PATH_SIZE
];
290 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0)
292 f
= fopen(filename
, "rb");
294 return hf_iclass_eload_usage();
298 PrintAndLog("Failed to read from file '%s'", filename
);
302 fseek(f
, 0, SEEK_END
);
303 long fsize
= ftell(f
);
304 fseek(f
, 0, SEEK_SET
);
307 PrintAndLog("Error, when getting filesize");
312 uint8_t *dump
= malloc(fsize
);
314 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
317 printIclassDumpInfo(dump
);
320 if (bytes_read
< fsize
)
322 prnlog("Error, could only read %d bytes (should be %d)",bytes_read
, fsize
);
327 uint32_t bytes_sent
= 0;
328 uint32_t bytes_remaining
= bytes_read
;
330 while(bytes_remaining
> 0){
331 uint32_t bytes_in_packet
= MIN(USB_CMD_DATA_SIZE
, bytes_remaining
);
332 UsbCommand c
= {CMD_ICLASS_EML_MEMSET
, {bytes_sent
,bytes_in_packet
,0}};
333 memcpy(c
.d
.asBytes
, dump
, bytes_in_packet
);
335 bytes_remaining
-= bytes_in_packet
;
336 bytes_sent
+= bytes_in_packet
;
339 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent
);
343 static int readKeyfile(const char *filename
, size_t len
, uint8_t* buffer
) {
344 FILE *f
= fopen(filename
, "rb");
346 PrintAndLog("Failed to read from file '%s'", filename
);
349 fseek(f
, 0, SEEK_END
);
350 long fsize
= ftell(f
);
351 fseek(f
, 0, SEEK_SET
);
352 size_t bytes_read
= fread(buffer
, 1, len
, f
);
356 PrintAndLog("Warning, file size is %d, expected %d", fsize
, len
);
359 if(bytes_read
!= len
)
361 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read
, len
);
367 int usage_hf_iclass_decrypt(void) {
368 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
370 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
371 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
373 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
375 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
376 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
377 PrintAndLog("which is defined by the configuration block.");
381 int CmdHFiClassDecrypt(const char *Cmd
) {
382 uint8_t key
[16] = { 0 };
383 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
385 usage_hf_iclass_decrypt();
388 PrintAndLog("Decryption file found... ");
389 char opt
= param_getchar(Cmd
, 0);
390 if (strlen(Cmd
)<1 || opt
== 'h')
391 return usage_hf_iclass_decrypt();
393 //Open the tagdump-file
395 char filename
[FILE_PATH_SIZE
];
396 if(opt
== 'f' && param_getstr(Cmd
, 1, filename
, sizeof(filename
)) > 0) {
397 f
= fopen(filename
, "rb");
399 PrintAndLog("Could not find file %s", filename
);
403 return usage_hf_iclass_decrypt();
406 fseek(f
, 0, SEEK_END
);
407 long fsize
= ftell(f
);
408 fseek(f
, 0, SEEK_SET
);
409 uint8_t enc_dump
[8] = {0};
410 uint8_t *decrypted
= malloc(fsize
);
411 mbedtls_des3_context ctx
= { {0} };
412 mbedtls_des3_set2key_dec( &ctx
, key
);
413 size_t bytes_read
= fread(enc_dump
, 1, 8, f
);
415 //Use the first block (CSN) for filename
416 char outfilename
[FILE_PATH_SIZE
] = { 0 };
417 snprintf(outfilename
,FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
418 enc_dump
[0],enc_dump
[1],enc_dump
[2],enc_dump
[3],
419 enc_dump
[4],enc_dump
[5],enc_dump
[6],enc_dump
[7]);
422 while(bytes_read
== 8)
426 memcpy(decrypted
+(blocknum
*8), enc_dump
, 8);
428 mbedtls_des3_crypt_ecb(&ctx
, enc_dump
,decrypted
+(blocknum
*8) );
430 printvar("decrypted block", decrypted
+(blocknum
*8), 8);
431 bytes_read
= fread(enc_dump
, 1, 8, f
);
436 saveFile(outfilename
,"bin", decrypted
, blocknum
*8);
441 int usage_hf_iclass_encrypt(void) {
442 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
444 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
445 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
447 PrintAndLog("example: hf iclass encrypt 0102030405060708");
452 static int iClassEncryptBlkData(uint8_t *blkData
) {
453 uint8_t key
[16] = { 0 };
454 if(readKeyfile("iclass_decryptionkey.bin", 16, key
))
456 usage_hf_iclass_encrypt();
459 PrintAndLog("Decryption file found... ");
461 uint8_t encryptedData
[16];
462 uint8_t *encrypted
= encryptedData
;
463 mbedtls_des3_context ctx
= { {0} };
464 mbedtls_des3_set2key_enc( &ctx
, key
);
466 mbedtls_des3_crypt_ecb(&ctx
, blkData
,encrypted
);
467 //printvar("decrypted block", decrypted, 8);
468 memcpy(blkData
,encrypted
,8);
473 int CmdHFiClassEncryptBlk(const char *Cmd
) {
474 uint8_t blkData
[8] = {0};
475 char opt
= param_getchar(Cmd
, 0);
476 if (strlen(Cmd
)<1 || opt
== 'h')
477 return usage_hf_iclass_encrypt();
479 //get the bytes to encrypt
480 if (param_gethex(Cmd
, 0, blkData
, 16))
482 PrintAndLog("BlockData must include 16 HEX symbols");
485 if (!iClassEncryptBlkData(blkData
)) return 0;
487 printvar("encrypted block", blkData
, 8);
491 void Calc_wb_mac(uint8_t blockno
, uint8_t *data
, uint8_t *div_key
, uint8_t MAC
[4]) {
494 memcpy(WB
+ 1,data
,8);
495 doMAC_N(WB
,sizeof(WB
),div_key
,MAC
);
496 //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]);
499 static bool select_only(uint8_t *CSN
, uint8_t *CCNR
, bool use_credit_key
, bool verbose
) {
502 UsbCommand c
= {CMD_READER_ICLASS
, {0}};
503 c
.arg
[0] = FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_CC
| FLAG_ICLASS_READER_ONE_TRY
;
505 c
.arg
[0] |= FLAG_ICLASS_READER_CEDITKEY
;
507 clearCommandBuffer();
509 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
511 PrintAndLog("Command execute timeout");
515 uint8_t isOK
= resp
.arg
[0] & 0xff;
516 uint8_t *data
= resp
.d
.asBytes
;
519 if (CCNR
!=NULL
)memcpy(CCNR
,data
+16,8);
522 if (verbose
) PrintAndLog("CSN: %s",sprint_hex(CSN
,8));
525 PrintAndLog("Failed to obtain CC! Aborting");
531 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
) {
532 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
533 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
535 if (!select_only(CSN
, CCNR
, use_credit_key
, verbose
))
540 memcpy(div_key
, KEY
, 8);
542 HFiClassCalcDivKey(CSN
, KEY
, div_key
, elite
);
543 if (verbose
) PrintAndLog("Authing with %s: %02x%02x%02x%02x%02x%02x%02x%02x", rawkey
? "raw key" : "diversified key", div_key
[0],div_key
[1],div_key
[2],div_key
[3],div_key
[4],div_key
[5],div_key
[6],div_key
[7]);
545 doMAC(CCNR
, div_key
, MAC
);
547 UsbCommand d
= {CMD_ICLASS_AUTHENTICATION
, {0}};
548 memcpy(d
.d
.asBytes
, MAC
, 4);
549 clearCommandBuffer();
551 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
553 if (verbose
) PrintAndLog("Auth Command execute timeout");
556 uint8_t isOK
= resp
.arg
[0] & 0xff;
558 if (verbose
) PrintAndLog("Authentication error");
564 int usage_hf_iclass_dump(void) {
565 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
566 PrintAndLog("Options:");
567 PrintAndLog(" f <filename> : specify a filename to save dump to");
568 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
569 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
570 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
571 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
572 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
573 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
574 PrintAndLog(" NOTE: * = required");
575 PrintAndLog("Samples:");
576 PrintAndLog(" hf iclass dump k 001122334455667B");
577 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
578 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
582 int CmdHFiClassReader_Dump(const char *Cmd
) {
584 uint8_t MAC
[4] = {0x00,0x00,0x00,0x00};
585 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
586 uint8_t c_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
590 uint8_t app_areas
= 1;
592 uint8_t KEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
593 uint8_t CreditKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
596 uint8_t fileNameLen
= 0;
597 char filename
[FILE_PATH_SIZE
]={0};
598 char tempStr
[50] = {0};
599 bool have_debit_key
= false;
600 bool have_credit_key
= false;
601 bool use_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
, sizeof(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
, sizeof(filename
));
642 if (fileNameLen
< 1) {
643 PrintAndLog("No filename found after f");
650 have_debit_key
= true;
651 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
653 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
654 } else if (dataLen
== 1) {
655 keyNbr
= param_get8(Cmd
, cmdp
+1);
656 if (keyNbr
< ICLASS_KEYS_MAX
) {
657 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
659 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
663 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
674 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
678 if(errors
) return usage_hf_iclass_dump();
681 if (cmdp
< 2) return usage_hf_iclass_dump();
682 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
683 if (!have_debit_key
&& have_credit_key
) use_credit_key
= true;
685 //get config and first 3 blocks
686 UsbCommand c
= {CMD_READER_ICLASS
, {FLAG_ICLASS_READER_CSN
|
687 FLAG_ICLASS_READER_CONF
| FLAG_ICLASS_READER_ONLY_ONCE
| FLAG_ICLASS_READER_ONE_TRY
}};
689 uint8_t tag_data
[255*8];
691 clearCommandBuffer();
693 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
694 PrintAndLog("Command execute timeout");
698 uint8_t readStatus
= resp
.arg
[0] & 0xff;
699 uint8_t *data
= resp
.d
.asBytes
;
702 PrintAndLog("No tag found...");
706 if( readStatus
& (FLAG_ICLASS_READER_CSN
|FLAG_ICLASS_READER_CONF
|FLAG_ICLASS_READER_CC
)){
707 memcpy(tag_data
, data
, 8*3);
708 blockno
+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
710 getMemConfig(data
[13], data
[12], &maxBlk
, &app_areas
, &kb
);
711 // large memory - not able to dump pages currently
712 if (numblks
> maxBlk
) numblks
= maxBlk
;
715 // authenticate debit key and get div_key - later store in dump block 3
716 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
717 //try twice - for some reason it sometimes fails the first time...
718 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, false)){
725 UsbCommand w
= {CMD_ICLASS_DUMP
, {blockno
, numblks
-blockno
+1}};
726 clearCommandBuffer();
728 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
729 PrintAndLog("Command execute time-out 1");
733 uint32_t blocksRead
= resp
.arg
[1];
734 uint8_t isOK
= resp
.arg
[0] & 0xff;
735 if (!isOK
&& !blocksRead
) {
736 PrintAndLog("Read Block Failed");
740 uint32_t startindex
= resp
.arg
[2];
741 if (blocksRead
*8 > sizeof(tag_data
)-(blockno
*8)) {
742 PrintAndLog("Data exceeded Buffer size!");
743 blocksRead
= (sizeof(tag_data
)/8) - blockno
;
745 // response ok - now get bigbuf content of the dump
746 GetFromBigBuf(tag_data
+(blockno
*8), blocksRead
*8, startindex
, NULL
, -1, false);
747 size_t gotBytes
= blocksRead
*8 + blockno
*8;
750 if (have_credit_key
) {
751 //turn off hf field before authenticating with different key
754 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
755 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
756 //try twice - for some reason it sometimes fails the first time...
757 if (!select_and_auth(CreditKEY
, MAC
, c_div_key
, true, false, false, false)){
762 // do we still need to read more block? (aa2 enabled?)
763 if (maxBlk
> blockno
+numblks
+1) {
764 // setup dump and start
765 w
.arg
[0] = blockno
+ blocksRead
;
766 w
.arg
[1] = maxBlk
- (blockno
+ blocksRead
);
767 clearCommandBuffer();
769 if (!WaitForResponseTimeout(CMD_ACK
, &resp
, 4500)) {
770 PrintAndLog("Command execute timeout 2");
774 uint8_t isOK
= resp
.arg
[0] & 0xff;
775 blocksRead
= resp
.arg
[1];
776 if (!isOK
&& !blocksRead
) {
777 PrintAndLog("Read Block Failed 2");
782 startindex
= resp
.arg
[2];
783 if (blocksRead
*8 > sizeof(tag_data
)-gotBytes
) {
784 PrintAndLog("Data exceeded Buffer size!");
785 blocksRead
= (sizeof(tag_data
) - gotBytes
)/8;
787 // get dumped data from bigbuf
788 GetFromBigBuf(tag_data
+gotBytes
, blocksRead
*8, startindex
, NULL
, -1, false);
790 gotBytes
+= blocksRead
*8;
791 } else { //field is still on - turn it off...
796 // add diversified keys to dump
797 if (have_debit_key
) memcpy(tag_data
+(3*8),div_key
,8);
798 if (have_credit_key
) memcpy(tag_data
+(4*8),c_div_key
,8);
800 printf("------+--+-------------------------+\n");
801 printf("CSN |00| %s|\n",sprint_hex(tag_data
, 8));
802 printIclassDumpContents(tag_data
, 1, (gotBytes
/8), gotBytes
);
804 if (filename
[0] == 0){
805 snprintf(filename
, FILE_PATH_SIZE
,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
806 tag_data
[0],tag_data
[1],tag_data
[2],tag_data
[3],
807 tag_data
[4],tag_data
[5],tag_data
[6],tag_data
[7]);
810 // save the dump to .bin file
811 PrintAndLog("Saving dump file - %d blocks read", gotBytes
/8);
812 saveFile(filename
, "bin", tag_data
, gotBytes
);
816 static int WriteBlock(uint8_t blockno
, uint8_t *bldata
, uint8_t *KEY
, bool use_credit_key
, bool elite
, bool rawkey
, bool verbose
) {
817 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
818 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
819 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, verbose
))
824 Calc_wb_mac(blockno
,bldata
,div_key
,MAC
);
825 UsbCommand w
= {CMD_ICLASS_WRITEBLOCK
, {blockno
}};
826 memcpy(w
.d
.asBytes
, bldata
, 8);
827 memcpy(w
.d
.asBytes
+ 8, MAC
, 4);
829 clearCommandBuffer();
831 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
833 PrintAndLog("Write Command execute timeout");
836 uint8_t isOK
= resp
.arg
[0] & 0xff;
838 PrintAndLog("Write Block Failed");
841 PrintAndLog("Write Block Successful");
845 int usage_hf_iclass_writeblock(void) {
846 PrintAndLog("Options:");
847 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
848 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
849 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
850 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
851 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
852 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
853 PrintAndLog("Samples:");
854 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
855 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
856 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
860 int CmdHFiClass_WriteBlock(const char *Cmd
) {
862 uint8_t bldata
[8]={0,0,0,0,0,0,0,0};
863 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
866 char tempStr
[50] = {0};
867 bool use_credit_key
= false;
872 while(param_getchar(Cmd
, cmdp
) != 0x00)
874 switch(param_getchar(Cmd
, cmdp
))
878 return usage_hf_iclass_writeblock();
881 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
882 PrintAndLog("Block No must include 2 HEX symbols\n");
889 use_credit_key
= true;
894 if (param_gethex(Cmd
, cmdp
+1, bldata
, 16))
896 PrintAndLog("KEY must include 16 HEX symbols\n");
908 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
910 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
911 } else if (dataLen
== 1) {
912 keyNbr
= param_get8(Cmd
, cmdp
+1);
913 if (keyNbr
< ICLASS_KEYS_MAX
) {
914 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
916 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
920 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
931 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
935 if(errors
) return usage_hf_iclass_writeblock();
938 if (cmdp
< 6) return usage_hf_iclass_writeblock();
939 int ans
= WriteBlock(blockno
, bldata
, KEY
, use_credit_key
, elite
, rawkey
, true);
944 int usage_hf_iclass_clone(void) {
945 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
946 PrintAndLog("Options:");
947 PrintAndLog(" f <filename>: specify a filename to clone from");
948 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
949 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
950 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
951 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
952 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
953 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
954 PrintAndLog("Samples:");
955 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
956 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
957 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
961 int CmdHFiClassCloneTag(const char *Cmd
) {
962 char filename
[FILE_PATH_SIZE
] = {0};
963 char tempStr
[50]={0};
964 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
966 uint8_t fileNameLen
= 0;
967 uint8_t startblock
= 0;
968 uint8_t endblock
= 0;
970 bool use_credit_key
= false;
975 while(param_getchar(Cmd
, cmdp
) != 0x00)
977 switch(param_getchar(Cmd
, cmdp
))
981 return usage_hf_iclass_clone();
984 if (param_gethex(Cmd
, cmdp
+1, &startblock
, 2)) {
985 PrintAndLog("Start Block No must include 2 HEX symbols\n");
992 use_credit_key
= true;
1002 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1003 if (fileNameLen
< 1) {
1004 PrintAndLog("No filename found after f");
1011 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1012 if (dataLen
== 16) {
1013 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1014 } else if (dataLen
== 1) {
1015 keyNbr
= param_get8(Cmd
, cmdp
+1);
1016 if (keyNbr
< ICLASS_KEYS_MAX
) {
1017 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1019 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1023 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1030 if (param_gethex(Cmd
, cmdp
+1, &endblock
, 2)) {
1031 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1042 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1046 if(errors
) return usage_hf_iclass_clone();
1049 if (cmdp
< 8) return usage_hf_iclass_clone();
1053 iclass_block_t tag_data
[USB_CMD_DATA_SIZE
/12];
1055 if ((endblock
-startblock
+1)*12 > USB_CMD_DATA_SIZE
) {
1056 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE
/8);
1058 // file handling and reading
1059 f
= fopen(filename
,"rb");
1061 PrintAndLog("Failed to read from file '%s'", filename
);
1066 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1070 // now read data from the file from block 6 --- 19
1071 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1072 // 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,
1073 // else we have to create a share memory
1075 fseek(f
,startblock
*8,SEEK_SET
);
1076 if ( fread(tag_data
,sizeof(iclass_block_t
),endblock
- startblock
+ 1,f
) == 0 ) {
1077 PrintAndLog("File reading error.");
1082 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1083 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1085 if (!select_and_auth(KEY
, MAC
, div_key
, use_credit_key
, elite
, rawkey
, true))
1088 UsbCommand w
= {CMD_ICLASS_CLONE
,{startblock
,endblock
}};
1090 // calculate all mac for every the block we will write
1091 for (i
= startblock
; i
<= endblock
; i
++){
1092 Calc_wb_mac(i
,tag_data
[i
- startblock
].d
,div_key
,MAC
);
1093 // usb command d start pointer = d + (i - 6) * 12
1094 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1095 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1097 ptr
= w
.d
.asBytes
+ (i
- startblock
) * 12;
1098 memcpy(ptr
, &(tag_data
[i
- startblock
].d
[0]), 8);
1099 memcpy(ptr
+ 8,MAC
, 4);
1102 for (i
= 0; i
<= endblock
- startblock
;i
++){
1103 memcpy(p
,w
.d
.asBytes
+ (i
* 12),12);
1104 printf("Block |%02x|",i
+ startblock
);
1105 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]);
1106 printf(" MAC |%02x%02x%02x%02x|\n",p
[8],p
[9],p
[10],p
[11]);
1110 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1112 PrintAndLog("Command execute timeout");
1118 static int ReadBlock(uint8_t *KEY
, uint8_t blockno
, uint8_t keyType
, bool elite
, bool rawkey
, bool verbose
, bool auth
) {
1119 uint8_t MAC
[4]={0x00,0x00,0x00,0x00};
1120 uint8_t div_key
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1123 if (!select_and_auth(KEY
, MAC
, div_key
, (keyType
==0x18), elite
, rawkey
, verbose
))
1126 uint8_t CSN
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1127 uint8_t CCNR
[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1128 if (!select_only(CSN
, CCNR
, (keyType
==0x18), verbose
))
1133 UsbCommand w
= {CMD_ICLASS_READBLOCK
, {blockno
}};
1134 clearCommandBuffer();
1136 if (!WaitForResponseTimeout(CMD_ACK
,&resp
,4500))
1138 PrintAndLog("Command execute timeout");
1141 uint8_t isOK
= resp
.arg
[0] & 0xff;
1143 PrintAndLog("Read Block Failed");
1146 //data read is stored in: resp.d.asBytes[0-15]
1147 if (verbose
) PrintAndLog("Block %02X: %s\n",blockno
, sprint_hex(resp
.d
.asBytes
,8));
1151 int usage_hf_iclass_readblock(void) {
1152 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1153 PrintAndLog("Options:");
1154 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1155 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1156 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1157 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1158 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1159 PrintAndLog("Samples:");
1160 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1161 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1162 PrintAndLog(" hf iclass readblk b 0A k 0");
1166 int CmdHFiClass_ReadBlock(const char *Cmd
) {
1168 uint8_t keyType
= 0x88; //debit key
1169 uint8_t KEY
[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1171 uint8_t dataLen
= 0;
1172 char tempStr
[50] = {0};
1174 bool rawkey
= false;
1175 bool errors
= false;
1178 while(param_getchar(Cmd
, cmdp
) != 0x00)
1180 switch(param_getchar(Cmd
, cmdp
))
1184 return usage_hf_iclass_readblock();
1187 if (param_gethex(Cmd
, cmdp
+1, &blockno
, 2)) {
1188 PrintAndLog("Block No must include 2 HEX symbols\n");
1206 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1207 if (dataLen
== 16) {
1208 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1209 } else if (dataLen
== 1) {
1210 keyNbr
= param_get8(Cmd
, cmdp
+1);
1211 if (keyNbr
< ICLASS_KEYS_MAX
) {
1212 memcpy(KEY
, iClass_Key_Table
[keyNbr
], 8);
1214 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1218 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1229 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1233 if(errors
) return usage_hf_iclass_readblock();
1236 if (cmdp
< 2) return usage_hf_iclass_readblock();
1238 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1239 return ReadBlock(KEY
, blockno
, keyType
, elite
, rawkey
, true, auth
);
1242 int CmdHFiClass_loclass(const char *Cmd
) {
1243 char opt
= param_getchar(Cmd
, 0);
1245 if (strlen(Cmd
)<1 || opt
== 'h') {
1246 PrintAndLog("Usage: hf iclass loclass [options]");
1247 PrintAndLog("Options:");
1248 PrintAndLog("h Show this help");
1249 PrintAndLog("t Perform self-test");
1250 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1251 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1252 PrintAndLog(" malicious CSNs, and their protocol responses");
1253 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1254 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1255 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1256 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1257 PrintAndLog(" ... totalling N*24 bytes");
1260 char fileName
[255] = {0};
1262 if(param_getstr(Cmd
, 1, fileName
, sizeof(fileName
)) > 0) {
1263 return bruteforceFileNoKeys(fileName
);
1265 PrintAndLog("You must specify a filename");
1267 } else if(opt
== 't') {
1268 int errors
= testCipherUtils();
1269 errors
+= testMAC();
1270 errors
+= doKeyTests(0);
1271 errors
+= testElite();
1273 prnlog("OBS! There were errors!!!");
1281 void printIclassDumpContents(uint8_t *iclass_dump
, uint8_t startblock
, uint8_t endblock
, size_t filesize
) {
1283 memcpy(&mem_config
, iclass_dump
+ 13,1);
1284 uint8_t maxmemcount
;
1285 uint8_t filemaxblock
= filesize
/ 8;
1286 if (mem_config
& 0x80)
1290 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1292 if (startblock
== 0)
1294 if ((endblock
> maxmemcount
) || (endblock
== 0))
1295 endblock
= maxmemcount
;
1297 // remember endblock need to relate to zero-index arrays.
1298 if (endblock
> filemaxblock
-1)
1299 endblock
= filemaxblock
;
1302 printf("------+--+-------------------------+\n");
1303 while (i
<= endblock
) {
1304 uint8_t *blk
= iclass_dump
+ (i
* 8);
1305 printf("Block |%02X| %s|\n", i
, sprint_hex(blk
, 8) );
1308 printf("------+--+-------------------------+\n");
1311 int usage_hf_iclass_readtagfile() {
1312 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1316 int CmdHFiClassReadTagFile(const char *Cmd
) {
1321 char filename
[FILE_PATH_SIZE
];
1322 if (param_getstr(Cmd
, 0, filename
, sizeof(filename
)) < 1)
1323 return usage_hf_iclass_readtagfile();
1324 if (param_getstr(Cmd
, 1, tempnum
, sizeof(tempnum
)) < 1)
1327 sscanf(tempnum
,"%d",&startblock
);
1329 if (param_getstr(Cmd
,2, tempnum
, sizeof(tempnum
)) < 1)
1332 sscanf(tempnum
,"%d",&endblock
);
1333 // file handling and reading
1334 f
= fopen(filename
,"rb");
1336 PrintAndLog("Failed to read from file '%s'", filename
);
1339 fseek(f
, 0, SEEK_END
);
1340 long fsize
= ftell(f
);
1341 fseek(f
, 0, SEEK_SET
);
1344 PrintAndLog("Error, when getting filesize");
1349 uint8_t *dump
= malloc(fsize
);
1351 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1353 uint8_t *csn
= dump
;
1354 printf("------+--+-------------------------+\n");
1355 printf("CSN |00| %s|\n", sprint_hex(csn
, 8) );
1356 // printIclassDumpInfo(dump);
1357 printIclassDumpContents(dump
,startblock
,endblock
,bytes_read
);
1363 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1364 uint64_t new_div = 0x00;
1370 uint64_t hexarray_to_uint64(uint8_t *key) {
1373 for (int i = 0;i < 8;i++)
1374 sprintf(&temp[(i *2)],"%02X",key[i]);
1376 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1381 void HFiClassCalcDivKey(uint8_t *CSN
, uint8_t *KEY
, uint8_t *div_key
, bool elite
){
1382 uint8_t keytable
[128] = {0};
1383 uint8_t key_index
[8] = {0};
1385 uint8_t key_sel
[8] = { 0 };
1386 uint8_t key_sel_p
[8] = { 0 };
1387 hash2(KEY
, keytable
);
1388 hash1(CSN
, key_index
);
1389 for(uint8_t i
= 0; i
< 8 ; i
++)
1390 key_sel
[i
] = keytable
[key_index
[i
]] & 0xFF;
1392 //Permute from iclass format to standard format
1393 permutekey_rev(key_sel
, key_sel_p
);
1394 diversifyKey(CSN
, key_sel_p
, div_key
);
1396 diversifyKey(CSN
, KEY
, div_key
);
1400 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1401 //calculate and return xor_div_key (ready for a key write command)
1402 //print all div_keys if verbose
1403 static void HFiClassCalcNewKey(uint8_t *CSN
, uint8_t *OLDKEY
, uint8_t *NEWKEY
, uint8_t *xor_div_key
, bool elite
, bool oldElite
, bool verbose
){
1404 uint8_t old_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1405 uint8_t new_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1407 HFiClassCalcDivKey(CSN
, OLDKEY
, old_div_key
, oldElite
);
1409 HFiClassCalcDivKey(CSN
, NEWKEY
, new_div_key
, elite
);
1411 for (uint8_t i
= 0; i
< sizeof(old_div_key
); i
++){
1412 xor_div_key
[i
] = old_div_key
[i
] ^ new_div_key
[i
];
1415 printf("Old Div Key : %s\n",sprint_hex(old_div_key
,8));
1416 printf("New Div Key : %s\n",sprint_hex(new_div_key
,8));
1417 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key
,8));
1421 int usage_hf_iclass_calc_newkey(void) {
1422 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1423 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1424 PrintAndLog(" Options:");
1425 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1426 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1427 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1428 PrintAndLog(" e : specify new key as elite calc");
1429 PrintAndLog(" ee : specify old and new key as elite calc");
1430 PrintAndLog("Samples:");
1431 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1432 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1433 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1434 PrintAndLog("NOTE: * = required\n");
1439 int CmdHFiClassCalcNewKey(const char *Cmd
) {
1440 uint8_t OLDKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1441 uint8_t NEWKEY
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1442 uint8_t xor_div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1443 uint8_t CSN
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1444 uint8_t CCNR
[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1446 uint8_t dataLen
= 0;
1447 char tempStr
[50] = {0};
1448 bool givenCSN
= false;
1449 bool oldElite
= false;
1451 bool errors
= false;
1453 while(param_getchar(Cmd
, cmdp
) != 0x00)
1455 switch(param_getchar(Cmd
, cmdp
))
1459 return usage_hf_iclass_calc_newkey();
1462 dataLen
= param_getstr(Cmd
, cmdp
, tempStr
, sizeof(tempStr
));
1470 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1471 if (dataLen
== 16) {
1472 errors
= param_gethex(tempStr
, 0, NEWKEY
, dataLen
);
1473 } else if (dataLen
== 1) {
1474 keyNbr
= param_get8(Cmd
, cmdp
+1);
1475 if (keyNbr
< ICLASS_KEYS_MAX
) {
1476 memcpy(NEWKEY
, iClass_Key_Table
[keyNbr
], 8);
1478 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1482 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1489 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1490 if (dataLen
== 16) {
1491 errors
= param_gethex(tempStr
, 0, OLDKEY
, dataLen
);
1492 } else if (dataLen
== 1) {
1493 keyNbr
= param_get8(Cmd
, cmdp
+1);
1494 if (keyNbr
< ICLASS_KEYS_MAX
) {
1495 memcpy(OLDKEY
, iClass_Key_Table
[keyNbr
], 8);
1497 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1501 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1509 if (param_gethex(Cmd
, cmdp
+1, CSN
, 16))
1510 return usage_hf_iclass_calc_newkey();
1514 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1518 if(errors
) return usage_hf_iclass_calc_newkey();
1521 if (cmdp
< 4) return usage_hf_iclass_calc_newkey();
1524 if (!select_only(CSN
, CCNR
, false, true))
1527 HFiClassCalcNewKey(CSN
, OLDKEY
, NEWKEY
, xor_div_key
, elite
, oldElite
, true);
1531 static int loadKeys(char *filename
) {
1533 f
= fopen(filename
,"rb");
1535 PrintAndLog("Failed to read from file '%s'", filename
);
1538 fseek(f
, 0, SEEK_END
);
1539 long fsize
= ftell(f
);
1540 fseek(f
, 0, SEEK_SET
);
1543 PrintAndLog("Error, when getting filesize");
1548 uint8_t *dump
= malloc(fsize
);
1550 size_t bytes_read
= fread(dump
, 1, fsize
, f
);
1552 if (bytes_read
> ICLASS_KEYS_MAX
* 8){
1553 PrintAndLog("File is too long to load - bytes: %u", bytes_read
);
1558 for (; i
< bytes_read
/8; i
++){
1559 memcpy(iClass_Key_Table
[i
],dump
+(i
*8),8);
1562 PrintAndLog("%u keys loaded", i
);
1566 static int saveKeys(char *filename
) {
1568 f
= fopen(filename
,"wb");
1570 printf("error opening file %s\n",filename
);
1573 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1574 if (fwrite(iClass_Key_Table
[i
],8,1,f
) != 1){
1575 PrintAndLog("save key failed to write to file: %s", filename
);
1583 static int printKeys(void) {
1585 for (uint8_t i
= 0; i
< ICLASS_KEYS_MAX
; i
++){
1586 PrintAndLog("%u: %s",i
,sprint_hex(iClass_Key_Table
[i
],8));
1592 int usage_hf_iclass_managekeys(void) {
1593 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1594 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1595 PrintAndLog(" Options:");
1596 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1597 PrintAndLog(" k <key> : set a key in memory");
1598 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1599 PrintAndLog(" s : save keys in memory to file specified by filename");
1600 PrintAndLog(" l : load keys to memory from file specified by filename");
1601 PrintAndLog(" p : print keys loaded into memory\n");
1602 PrintAndLog("Samples:");
1603 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1604 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1605 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1606 PrintAndLog(" print keys : hf iclass managekeys p\n");
1610 int CmdHFiClassManageKeys(const char *Cmd
) {
1612 uint8_t dataLen
= 0;
1613 uint8_t KEY
[8] = {0};
1614 char filename
[FILE_PATH_SIZE
];
1615 uint8_t fileNameLen
= 0;
1616 bool errors
= false;
1617 uint8_t operation
= 0;
1621 while(param_getchar(Cmd
, cmdp
) != 0x00)
1623 switch(param_getchar(Cmd
, cmdp
))
1627 return usage_hf_iclass_managekeys();
1630 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1631 if (fileNameLen
< 1) {
1632 PrintAndLog("No filename found after f");
1639 keyNbr
= param_get8(Cmd
, cmdp
+1);
1640 if (keyNbr
>= ICLASS_KEYS_MAX
) {
1641 PrintAndLog("Invalid block number");
1648 operation
+= 3; //set key
1649 dataLen
= param_getstr(Cmd
, cmdp
+1, tempStr
, sizeof(tempStr
));
1650 if (dataLen
== 16) { //ul-c or ev1/ntag key length
1651 errors
= param_gethex(tempStr
, 0, KEY
, dataLen
);
1653 PrintAndLog("\nERROR: Key is incorrect length\n");
1660 operation
+= 4; //print keys in memory
1665 operation
+= 5; //load keys from file
1670 operation
+= 6; //save keys to file
1674 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1678 if(errors
) return usage_hf_iclass_managekeys();
1680 if (operation
== 0){
1681 PrintAndLog("no operation specified (load, save, or print)\n");
1682 return usage_hf_iclass_managekeys();
1685 PrintAndLog("Too many operations specified\n");
1686 return usage_hf_iclass_managekeys();
1688 if (operation
> 4 && fileNameLen
== 0){
1689 PrintAndLog("You must enter a filename when loading or saving\n");
1690 return usage_hf_iclass_managekeys();
1694 case 3: memcpy(iClass_Key_Table
[keyNbr
], KEY
, 8); return 1;
1695 case 4: return printKeys();
1696 case 5: return loadKeys(filename
);
1697 case 6: return saveKeys(filename
);
1703 int CmdHFiClassCheckKeys(const char *Cmd
) {
1705 uint8_t mac
[4] = {0x00,0x00,0x00,0x00};
1706 uint8_t key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1707 uint8_t div_key
[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1709 // elite key, raw key, standard key
1710 bool use_elite
= false;
1711 bool use_raw
= false;
1712 bool found_debit
= false;
1713 bool found_credit
= false;
1714 bool errors
= false;
1715 uint8_t cmdp
= 0x00;
1717 char filename
[FILE_PATH_SIZE
] = {0};
1718 uint8_t fileNameLen
= 0;
1720 uint8_t *keyBlock
= NULL
, *p
;
1721 int keyitems
= 0, keycnt
= 0;
1723 while (param_getchar(Cmd
, cmdp
) != 0x00 && !errors
) {
1724 switch (param_getchar(Cmd
, cmdp
)) {
1727 return usage_hf_iclass_chk();
1730 fileNameLen
= param_getstr(Cmd
, cmdp
+1, filename
, sizeof(filename
));
1731 if (fileNameLen
< 1) {
1732 PrintAndLog("No filename found after f");
1748 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd
, cmdp
));
1753 if (errors
) return usage_hf_iclass_chk();
1755 if ( !(f
= fopen( filename
, "r")) ) {
1756 PrintAndLog("File: %s: not found or locked.", filename
);
1760 while( fgets(buf
, sizeof(buf
), f
) ){
1761 if (strlen(buf
) < 16 || buf
[15] == '\n')
1764 while (fgetc(f
) != '\n' && !feof(f
)) ; //goto next line
1766 if( buf
[0]=='#' ) continue; //The line start with # is comment, skip
1768 if (!isxdigit(buf
[0])){
1769 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf
);
1775 p
= realloc(keyBlock
, 8 * (keyitems
+= 64));
1777 PrintAndLog("Cannot allocate memory for default keys");
1784 memset(keyBlock
+ 8 * keycnt
, 0, 8);
1785 num_to_bytes(strtoull(buf
, NULL
, 16), 8, keyBlock
+ 8 * keycnt
);
1787 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1789 memset(buf
, 0, sizeof(buf
));
1792 PrintAndLog("Loaded %2d keys from %s", keycnt
, filename
);
1795 uint64_t t1
= msclock();
1797 for (uint32_t c
= 0; c
< keycnt
; c
+= 1) {
1798 printf("."); fflush(stdout
);
1800 int gc
= getchar(); (void)gc
;
1801 printf("\naborted via keyboard!\n");
1805 memcpy(key
, keyBlock
+ 8 * c
, 8);
1807 // debit key. try twice
1808 for (int foo
= 0; foo
< 2 && !found_debit
; foo
++) {
1809 if (!select_and_auth(key
, mac
, div_key
, false, use_elite
, use_raw
, false))
1813 PrintAndLog("\n--------------------------------------------------------");
1814 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key
, 8));
1818 // credit key. try twice
1819 for (int foo
= 0; foo
< 2 && !found_credit
; foo
++) {
1820 if (!select_and_auth(key
, mac
, div_key
, true, use_elite
, use_raw
, false))
1824 PrintAndLog("\n--------------------------------------------------------");
1825 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key
, 8));
1826 found_credit
= true;
1830 if ( found_debit
&& found_credit
)
1834 t1
= msclock() - t1
;
1836 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1
/1000.0);
1844 static command_t CommandTable
[] =
1846 {"help", CmdHelp
, 1, "This help"},
1847 {"calcnewkey", CmdHFiClassCalcNewKey
, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1848 {"chk", CmdHFiClassCheckKeys
, 0, " Check keys"},
1849 {"clone", CmdHFiClassCloneTag
, 0, "[options..] Authenticate and Clone from iClass bin file"},
1850 {"decrypt", CmdHFiClassDecrypt
, 1, "[f <fname>] Decrypt tagdump" },
1851 {"dump", CmdHFiClassReader_Dump
, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1852 {"eload", CmdHFiClassELoad
, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1853 {"encryptblk", CmdHFiClassEncryptBlk
, 1, "<BlockData> Encrypt given block data"},
1854 {"list", CmdHFiClassList
, 0, " (Deprecated) List iClass history"},
1855 {"loclass", CmdHFiClass_loclass
, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1856 {"managekeys", CmdHFiClassManageKeys
, 1, "[options..] Manage the keys to use with iClass"},
1857 {"readblk", CmdHFiClass_ReadBlock
, 0, "[options..] Authenticate and Read iClass block"},
1858 {"reader", CmdHFiClassReader
, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1859 {"readtagfile", CmdHFiClassReadTagFile
, 1, "[options..] Display Content from tagfile"},
1860 {"replay", CmdHFiClassReader_Replay
, 0, "<mac> Read an iClass tag via Reply Attack"},
1861 {"sim", CmdHFiClassSim
, 0, "[options..] Simulate iClass tag"},
1862 {"snoop", CmdHFiClassSnoop
, 0, " Eavesdrop iClass communication"},
1863 {"writeblk", CmdHFiClass_WriteBlock
, 0, "[options..] Authenticate and Write iClass block"},
1864 {NULL
, NULL
, 0, NULL
}
1867 int CmdHFiClass(const char *Cmd
)
1869 clearCommandBuffer();
1870 CmdsParse(CommandTable
, Cmd
);
1874 int CmdHelp(const char *Cmd
)
1876 CmdsHelp(CommandTable
);