]> git.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhficlass.c
fix iclass reader functions
[proxmark3-svn] / client / cmdhficlass.c
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
5 //
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
8 // the license.
9 //-----------------------------------------------------------------------------
10 // High frequency iClass commands
11 //-----------------------------------------------------------------------------
12
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <sys/stat.h>
17 #include <ctype.h>
18 #include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
19 #include "comms.h"
20 #include "ui.h"
21 #include "cmdparser.h"
22 #include "cmdhficlass.h"
23 #include "common.h"
24 #include "util.h"
25 #include "cmdmain.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"
33 #include "usb_cmd.h"
34 #include "cmdhfmfu.h"
35 #include "util_posix.h"
36 #include "cmdhf14a.h" // DropField()
37
38 static int CmdHelp(const char *Cmd);
39
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 }
50 };
51
52 typedef struct iclass_block {
53 uint8_t d[8];
54 } iclass_block_t;
55
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");
67 return 0;
68 }
69
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
75 return res & 1;
76 }
77
78 int CmdHFiClassList(const char *Cmd) {
79 PrintAndLog("Deprecated command, use 'hf list iclass' instead");
80 return 0;
81 }
82
83 int CmdHFiClassSnoop(const char *Cmd) {
84 UsbCommand c = {CMD_SNOOP_ICLASS};
85 SendCommand(&c);
86 return 0;
87 }
88
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");
100 return 0;
101 }
102
103 #define NUM_CSNS 15
104 int CmdHFiClassSim(const char *Cmd) {
105 uint8_t simType = 0;
106 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
107
108 if (strlen(Cmd)<1) {
109 return usage_hf_iclass_sim();
110 }
111 simType = param_get8ex(Cmd, 0, 0, 10);
112
113 if(simType == 0)
114 {
115 if (param_gethex(Cmd, 1, CSN, 16)) {
116 PrintAndLog("A CSN should consist of 16 HEX symbols");
117 return usage_hf_iclass_sim();
118 }
119
120 PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
121 }
122 if(simType > 3)
123 {
124 PrintAndLog("Undefined simptype %d", simType);
125 return usage_hf_iclass_sim();
126 }
127
128 uint8_t numberOfCSNs=0;
129 if(simType == 2)
130 {
131 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
132 UsbCommand resp = {0};
133
134 uint8_t csns[8*NUM_CSNS] = {
135 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
136 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
137 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
138 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
139 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
140 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
141 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
142 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
143 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
144 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
145 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
146 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
147 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
148 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
149 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
150
151 memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
152
153 SendCommand(&c);
154 if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
155 PrintAndLog("Command timed out");
156 return 0;
157 }
158
159 uint8_t num_mac_responses = resp.arg[1];
160 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
161
162 size_t datalen = NUM_CSNS*24;
163 /*
164 * Now, time to dump to file. We'll use this format:
165 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
166 * So, it should wind up as
167 * 8 * 24 bytes.
168 *
169 * The returndata from the pm3 is on the following format
170 * <4 byte NR><4 byte MAC>
171 * CC are all zeroes, CSN is the same as was sent in
172 **/
173 void* dump = malloc(datalen);
174 memset(dump,0,datalen);//<-- Need zeroes for the CC-field
175 uint8_t i = 0;
176 for(i = 0 ; i < NUM_CSNS ; i++)
177 {
178 memcpy(dump+i*24, csns+i*8,8); //CSN
179 //8 zero bytes here...
180 //Then comes NR_MAC (eight bytes from the response)
181 memcpy(dump+i*24+16,resp.d.asBytes+i*8,8);
182
183 }
184 /** Now, save to dumpfile **/
185 saveFile("iclass_mac_attack", "bin", dump,datalen);
186 free(dump);
187 }else
188 {
189 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
190 memcpy(c.d.asBytes, CSN, 8);
191 SendCommand(&c);
192 }
193
194 return 0;
195 }
196
197 int HFiClassReader(const char *Cmd, bool loop, bool verbose) {
198 bool tagFound = false;
199 UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN |
200 FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_AA |
201 FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY } };
202 // loop in client not device - else on windows have a communication error
203 UsbCommand resp;
204 while(!ukbhit()){
205 SendCommand(&c);
206 if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
207 uint8_t readStatus = resp.arg[0] & 0xff;
208 uint8_t *data = resp.d.asBytes;
209
210 // no tag found or button pressed
211 if( (readStatus == 0 && !loop) || readStatus == 0xFF) {
212 // abort
213 if (verbose) PrintAndLog("Quitting...");
214 return 0;
215 }
216
217 if( readStatus & FLAG_ICLASS_READER_CSN) {
218 PrintAndLog(" CSN: %s",sprint_hex(data,8));
219 tagFound = true;
220 }
221 if( readStatus & FLAG_ICLASS_READER_CC) {
222 PrintAndLog(" CC: %s",sprint_hex(data+16,8));
223 }
224 if( readStatus & FLAG_ICLASS_READER_CONF) {
225 printIclassDumpInfo(data);
226 }
227 if (readStatus & FLAG_ICLASS_READER_AA) {
228 bool legacy = true;
229 PrintAndLog(" AppIA: %s",sprint_hex(data+8*5,8));
230 for (int i = 0; i<8; i++) {
231 if (data[8*5+i] != 0xFF) {
232 legacy = false;
233 }
234 }
235 PrintAndLog(" : Possible iClass %s",(legacy) ? "(legacy tag)" : "(NOT legacy tag)");
236 }
237
238 if (tagFound && !loop) return 1;
239 } else {
240 if (verbose) PrintAndLog("Command execute timeout");
241 }
242 if (!loop) break;
243 }
244 return 0;
245 }
246
247 int CmdHFiClassReader(const char *Cmd) {
248 return HFiClassReader(Cmd, true, true);
249 }
250
251 int CmdHFiClassReader_Replay(const char *Cmd) {
252 uint8_t readerType = 0;
253 uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
254
255 if (strlen(Cmd)<1) {
256 PrintAndLog("Usage: hf iclass replay <MAC>");
257 PrintAndLog(" sample: hf iclass replay 00112233");
258 return 0;
259 }
260
261 if (param_gethex(Cmd, 0, MAC, 8)) {
262 PrintAndLog("MAC must include 8 HEX symbols");
263 return 1;
264 }
265
266 UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
267 memcpy(c.d.asBytes, MAC, 4);
268 SendCommand(&c);
269
270 return 0;
271 }
272
273 int iclassEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
274 UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};
275 memcpy(c.d.asBytes, data, blocksCount * 16);
276 SendCommand(&c);
277 return 0;
278 }
279
280 int hf_iclass_eload_usage(void) {
281 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
282 PrintAndLog("Usage: hf iclass eload f <filename>");
283 PrintAndLog("");
284 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
285 return 0;
286 }
287
288 int CmdHFiClassELoad(const char *Cmd) {
289
290 char opt = param_getchar(Cmd, 0);
291 if (strlen(Cmd)<1 || opt == 'h')
292 return hf_iclass_eload_usage();
293
294 //File handling and reading
295 FILE *f;
296 char filename[FILE_PATH_SIZE];
297 if (opt == 'f' && param_getstr(Cmd, 1, filename, sizeof(filename)) > 0) {
298 f = fopen(filename, "rb");
299 } else {
300 return hf_iclass_eload_usage();
301 }
302
303 if (!f) {
304 PrintAndLog("Failed to read from file '%s'", filename);
305 return 1;
306 }
307
308 fseek(f, 0, SEEK_END);
309 long fsize = ftell(f);
310 fseek(f, 0, SEEK_SET);
311
312 if (fsize < 0) {
313 PrintAndLog("Error, when getting filesize");
314 fclose(f);
315 return 1;
316 }
317
318 uint8_t *dump = malloc(fsize);
319
320 size_t bytes_read = fread(dump, 1, fsize, f);
321 fclose(f);
322
323 printIclassDumpInfo(dump);
324 //Validate
325
326 if (bytes_read < fsize) {
327 prnlog("Error, could only read %d bytes (should be %d)",bytes_read, fsize );
328 free(dump);
329 return 1;
330 }
331 //Send to device
332 uint32_t bytes_sent = 0;
333 uint32_t bytes_remaining = bytes_read;
334
335 while (bytes_remaining > 0) {
336 uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining);
337 UsbCommand c = {CMD_ICLASS_EML_MEMSET, {bytes_sent,bytes_in_packet,0}};
338 memcpy(c.d.asBytes, dump+bytes_sent, bytes_in_packet);
339 SendCommand(&c);
340 bytes_remaining -= bytes_in_packet;
341 bytes_sent += bytes_in_packet;
342 }
343 free(dump);
344 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent);
345 return 0;
346 }
347
348 static int readKeyfile(const char *filename, size_t len, uint8_t* buffer) {
349 FILE *f = fopen(filename, "rb");
350 if(!f) {
351 PrintAndLog("Failed to read from file '%s'", filename);
352 return 1;
353 }
354 fseek(f, 0, SEEK_END);
355 long fsize = ftell(f);
356 fseek(f, 0, SEEK_SET);
357 size_t bytes_read = fread(buffer, 1, len, f);
358 fclose(f);
359 if(fsize != len)
360 {
361 PrintAndLog("Warning, file size is %d, expected %d", fsize, len);
362 return 1;
363 }
364 if(bytes_read != len)
365 {
366 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len);
367 return 1;
368 }
369 return 0;
370 }
371
372 int usage_hf_iclass_decrypt(void) {
373 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
374 PrintAndLog("");
375 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
376 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
377 PrintAndLog("");
378 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
379 PrintAndLog("");
380 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
381 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
382 PrintAndLog("which is defined by the configuration block.");
383 return 1;
384 }
385
386 int CmdHFiClassDecrypt(const char *Cmd) {
387 uint8_t key[16] = { 0 };
388 if(readKeyfile("iclass_decryptionkey.bin", 16, key))
389 {
390 usage_hf_iclass_decrypt();
391 return 1;
392 }
393 PrintAndLog("Decryption file found... ");
394 char opt = param_getchar(Cmd, 0);
395 if (strlen(Cmd)<1 || opt == 'h')
396 return usage_hf_iclass_decrypt();
397
398 //Open the tagdump-file
399 FILE *f;
400 char filename[FILE_PATH_SIZE];
401 if(opt == 'f' && param_getstr(Cmd, 1, filename, sizeof(filename)) > 0) {
402 f = fopen(filename, "rb");
403 if ( f == NULL ) {
404 PrintAndLog("Could not find file %s", filename);
405 return 1;
406 }
407 } else {
408 return usage_hf_iclass_decrypt();
409 }
410
411 fseek(f, 0, SEEK_END);
412 long fsize = ftell(f);
413 fseek(f, 0, SEEK_SET);
414 uint8_t enc_dump[8] = {0};
415 uint8_t *decrypted = malloc(fsize);
416 mbedtls_des3_context ctx = { {0} };
417 mbedtls_des3_set2key_dec( &ctx, key);
418 size_t bytes_read = fread(enc_dump, 1, 8, f);
419
420 //Use the first block (CSN) for filename
421 char outfilename[FILE_PATH_SIZE] = { 0 };
422 snprintf(outfilename,FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
423 enc_dump[0],enc_dump[1],enc_dump[2],enc_dump[3],
424 enc_dump[4],enc_dump[5],enc_dump[6],enc_dump[7]);
425
426 size_t blocknum =0;
427 while(bytes_read == 8)
428 {
429 if(blocknum < 7)
430 {
431 memcpy(decrypted+(blocknum*8), enc_dump, 8);
432 }else{
433 mbedtls_des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
434 }
435 printvar("decrypted block", decrypted +(blocknum*8), 8);
436 bytes_read = fread(enc_dump, 1, 8, f);
437 blocknum++;
438 }
439 fclose(f);
440
441 saveFile(outfilename,"bin", decrypted, blocknum*8);
442 free(decrypted);
443 return 0;
444 }
445
446 int usage_hf_iclass_encrypt(void) {
447 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
448 PrintAndLog("");
449 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
450 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
451 PrintAndLog("");
452 PrintAndLog("example: hf iclass encrypt 0102030405060708");
453 PrintAndLog("");
454 return 0;
455 }
456
457 static int iClassEncryptBlkData(uint8_t *blkData) {
458 uint8_t key[16] = { 0 };
459 if(readKeyfile("iclass_decryptionkey.bin", 16, key))
460 {
461 usage_hf_iclass_encrypt();
462 return 1;
463 }
464 PrintAndLog("Decryption file found... ");
465
466 uint8_t encryptedData[16];
467 uint8_t *encrypted = encryptedData;
468 mbedtls_des3_context ctx = { {0} };
469 mbedtls_des3_set2key_enc( &ctx, key);
470
471 mbedtls_des3_crypt_ecb(&ctx, blkData,encrypted);
472 //printvar("decrypted block", decrypted, 8);
473 memcpy(blkData,encrypted,8);
474
475 return 1;
476 }
477
478 int CmdHFiClassEncryptBlk(const char *Cmd) {
479 uint8_t blkData[8] = {0};
480 char opt = param_getchar(Cmd, 0);
481 if (strlen(Cmd)<1 || opt == 'h')
482 return usage_hf_iclass_encrypt();
483
484 //get the bytes to encrypt
485 if (param_gethex(Cmd, 0, blkData, 16))
486 {
487 PrintAndLog("BlockData must include 16 HEX symbols");
488 return 0;
489 }
490 if (!iClassEncryptBlkData(blkData)) return 0;
491
492 printvar("encrypted block", blkData, 8);
493 return 1;
494 }
495
496 void Calc_wb_mac(uint8_t blockno, uint8_t *data, uint8_t *div_key, uint8_t MAC[4]) {
497 uint8_t WB[9];
498 WB[0] = blockno;
499 memcpy(WB + 1,data,8);
500 doMAC_N(WB,sizeof(WB),div_key,MAC);
501 //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]);
502 }
503
504 static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose) {
505 UsbCommand resp;
506
507 UsbCommand c = {CMD_READER_ICLASS, {0}};
508 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_ONE_TRY;
509 if (use_credit_key)
510 c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY;
511
512 clearCommandBuffer();
513 SendCommand(&c);
514 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
515 {
516 PrintAndLog("Command execute timeout");
517 return false;
518 }
519
520 uint8_t isOK = resp.arg[0] & 0xff;
521 uint8_t *data = resp.d.asBytes;
522
523 memcpy(CSN,data,8);
524 if (CCNR!=NULL)memcpy(CCNR,data+16,8);
525 if(isOK > 0)
526 {
527 if (verbose) PrintAndLog("CSN: %s",sprint_hex(CSN,8));
528 }
529 if(isOK <= 1){
530 PrintAndLog("Failed to obtain CC! Aborting");
531 return false;
532 }
533 return true;
534 }
535
536 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) {
537 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
538 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
539
540 if (!select_only(CSN, CCNR, use_credit_key, verbose))
541 return false;
542
543 //get div_key
544 if(rawkey)
545 memcpy(div_key, KEY, 8);
546 else
547 HFiClassCalcDivKey(CSN, KEY, div_key, elite);
548 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]);
549
550 doMAC(CCNR, div_key, MAC);
551 UsbCommand resp;
552 UsbCommand d = {CMD_ICLASS_AUTHENTICATION, {0}};
553 memcpy(d.d.asBytes, MAC, 4);
554 clearCommandBuffer();
555 SendCommand(&d);
556 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
557 {
558 if (verbose) PrintAndLog("Auth Command execute timeout");
559 return false;
560 }
561 uint8_t isOK = resp.arg[0] & 0xff;
562 if (!isOK) {
563 if (verbose) PrintAndLog("Authentication error");
564 return false;
565 }
566 return true;
567 }
568
569 int usage_hf_iclass_dump(void) {
570 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
571 PrintAndLog("Options:");
572 PrintAndLog(" f <filename> : specify a filename to save dump to");
573 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
574 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
575 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
576 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
577 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
578 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
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");
584 return 0;
585 }
586
587 int CmdHFiClassReader_Dump(const char *Cmd) {
588
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};
592 uint8_t blockno = 0;
593 uint8_t numblks = 0;
594 uint8_t maxBlk = 31;
595 uint8_t app_areas = 1;
596 uint8_t kb = 2;
597 uint8_t KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
598 uint8_t CreditKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
599 uint8_t keyNbr = 0;
600 uint8_t dataLen = 0;
601 uint8_t fileNameLen = 0;
602 char filename[FILE_PATH_SIZE]={0};
603 char tempStr[50] = {0};
604 bool have_debit_key = false;
605 bool have_credit_key = false;
606 bool use_credit_key = false;
607 bool elite = false;
608 bool rawkey = false;
609 bool errors = false;
610 uint8_t cmdp = 0;
611
612 while(param_getchar(Cmd, cmdp) != 0x00)
613 {
614 switch(param_getchar(Cmd, cmdp))
615 {
616 case 'h':
617 case 'H':
618 return usage_hf_iclass_dump();
619 case 'c':
620 case 'C':
621 have_credit_key = true;
622 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
623 if (dataLen == 16) {
624 errors = param_gethex(tempStr, 0, CreditKEY, dataLen);
625 } else if (dataLen == 1) {
626 keyNbr = param_get8(Cmd, cmdp+1);
627 if (keyNbr < ICLASS_KEYS_MAX) {
628 memcpy(CreditKEY, iClass_Key_Table[keyNbr], 8);
629 } else {
630 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
631 errors = true;
632 }
633 } else {
634 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
635 errors = true;
636 }
637 cmdp += 2;
638 break;
639 case 'e':
640 case 'E':
641 elite = true;
642 cmdp++;
643 break;
644 case 'f':
645 case 'F':
646 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
647 if (fileNameLen < 1) {
648 PrintAndLog("No filename found after f");
649 errors = true;
650 }
651 cmdp += 2;
652 break;
653 case 'k':
654 case 'K':
655 have_debit_key = true;
656 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
657 if (dataLen == 16) {
658 errors = param_gethex(tempStr, 0, KEY, dataLen);
659 } else if (dataLen == 1) {
660 keyNbr = param_get8(Cmd, cmdp+1);
661 if (keyNbr < ICLASS_KEYS_MAX) {
662 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
663 } else {
664 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
665 errors = true;
666 }
667 } else {
668 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
669 errors = true;
670 }
671 cmdp += 2;
672 break;
673 case 'r':
674 case 'R':
675 rawkey = true;
676 cmdp++;
677 break;
678 default:
679 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
680 errors = true;
681 break;
682 }
683 if(errors) return usage_hf_iclass_dump();
684 }
685
686 if (cmdp < 2) return usage_hf_iclass_dump();
687 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
688 if (!have_debit_key && have_credit_key) use_credit_key = true;
689
690 //get config and first 3 blocks
691 UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN |
692 FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY}};
693 UsbCommand resp;
694 uint8_t tag_data[255*8];
695
696 clearCommandBuffer();
697 SendCommand(&c);
698 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
699 PrintAndLog("Command execute timeout");
700 DropField();
701 return 0;
702 }
703 uint8_t readStatus = resp.arg[0] & 0xff;
704 uint8_t *data = resp.d.asBytes;
705
706 if(readStatus == 0){
707 PrintAndLog("No tag found...");
708 DropField();
709 return 0;
710 }
711 if( readStatus & (FLAG_ICLASS_READER_CSN|FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_CC)){
712 memcpy(tag_data, data, 8*3);
713 blockno+=2; // 2 to force re-read of block 2 later. (seems to respond differently..)
714 numblks = data[8];
715 getMemConfig(data[13], data[12], &maxBlk, &app_areas, &kb);
716 // large memory - not able to dump pages currently
717 if (numblks > maxBlk) numblks = maxBlk;
718 }
719 DropField();
720 // authenticate debit key and get div_key - later store in dump block 3
721 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
722 //try twice - for some reason it sometimes fails the first time...
723 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
724 DropField();
725 return 0;
726 }
727 }
728
729 // begin dump
730 UsbCommand w = {CMD_ICLASS_DUMP, {blockno, numblks-blockno+1}};
731 clearCommandBuffer();
732 SendCommand(&w);
733 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
734 PrintAndLog("Command execute time-out 1");
735 DropField();
736 return 1;
737 }
738 uint32_t blocksRead = resp.arg[1];
739 uint8_t isOK = resp.arg[0] & 0xff;
740 if (!isOK && !blocksRead) {
741 PrintAndLog("Read Block Failed");
742 DropField();
743 return 0;
744 }
745 uint32_t startindex = resp.arg[2];
746 if (blocksRead*8 > sizeof(tag_data)-(blockno*8)) {
747 PrintAndLog("Data exceeded Buffer size!");
748 blocksRead = (sizeof(tag_data)/8) - blockno;
749 }
750 // response ok - now get bigbuf content of the dump
751 GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex, NULL, -1, false);
752 size_t gotBytes = blocksRead*8 + blockno*8;
753
754 // try AA2
755 if (have_credit_key) {
756 //turn off hf field before authenticating with different key
757 DropField();
758 memset(MAC,0,4);
759 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
760 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
761 //try twice - for some reason it sometimes fails the first time...
762 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
763 DropField();
764 return 0;
765 }
766 }
767 // do we still need to read more block? (aa2 enabled?)
768 if (maxBlk > blockno+numblks+1) {
769 // setup dump and start
770 w.arg[0] = blockno + blocksRead;
771 w.arg[1] = maxBlk - (blockno + blocksRead);
772 clearCommandBuffer();
773 SendCommand(&w);
774 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
775 PrintAndLog("Command execute timeout 2");
776 DropField();
777 return 0;
778 }
779 uint8_t isOK = resp.arg[0] & 0xff;
780 blocksRead = resp.arg[1];
781 if (!isOK && !blocksRead) {
782 PrintAndLog("Read Block Failed 2");
783 DropField();
784 return 0;
785 }
786
787 startindex = resp.arg[2];
788 if (blocksRead*8 > sizeof(tag_data)-gotBytes) {
789 PrintAndLog("Data exceeded Buffer size!");
790 blocksRead = (sizeof(tag_data) - gotBytes)/8;
791 }
792 // get dumped data from bigbuf
793 GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex, NULL, -1, false);
794
795 gotBytes += blocksRead*8;
796 } else { //field is still on - turn it off...
797 DropField();
798 }
799 }
800
801 // add diversified keys to dump
802 if (have_debit_key) memcpy(tag_data+(3*8),div_key,8);
803 if (have_credit_key) memcpy(tag_data+(4*8),c_div_key,8);
804 // print the dump
805 printf("------+--+-------------------------+\n");
806 printf("CSN |00| %s|\n",sprint_hex(tag_data, 8));
807 printIclassDumpContents(tag_data, 1, (gotBytes/8), gotBytes);
808
809 if (filename[0] == 0){
810 snprintf(filename, FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
811 tag_data[0],tag_data[1],tag_data[2],tag_data[3],
812 tag_data[4],tag_data[5],tag_data[6],tag_data[7]);
813 }
814
815 // save the dump to .bin file
816 PrintAndLog("Saving dump file - %d blocks read", gotBytes/8);
817 saveFile(filename, "bin", tag_data, gotBytes);
818 return 1;
819 }
820
821 static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
822 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
823 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
824 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose))
825 return 0;
826
827 UsbCommand resp;
828
829 Calc_wb_mac(blockno,bldata,div_key,MAC);
830 UsbCommand w = {CMD_ICLASS_WRITEBLOCK, {blockno}};
831 memcpy(w.d.asBytes, bldata, 8);
832 memcpy(w.d.asBytes + 8, MAC, 4);
833
834 clearCommandBuffer();
835 SendCommand(&w);
836 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
837 {
838 PrintAndLog("Write Command execute timeout");
839 return 0;
840 }
841 uint8_t isOK = resp.arg[0] & 0xff;
842 if (!isOK) {
843 PrintAndLog("Write Block Failed");
844 return 0;
845 }
846 PrintAndLog("Write Block Successful");
847 return 1;
848 }
849
850 int usage_hf_iclass_writeblock(void) {
851 PrintAndLog("Options:");
852 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
853 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
854 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
855 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
856 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
857 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
858 PrintAndLog("Samples:");
859 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
860 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
861 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
862 return 0;
863 }
864
865 int CmdHFiClass_WriteBlock(const char *Cmd) {
866 uint8_t blockno=0;
867 uint8_t bldata[8]={0,0,0,0,0,0,0,0};
868 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
869 uint8_t keyNbr = 0;
870 uint8_t dataLen = 0;
871 char tempStr[50] = {0};
872 bool use_credit_key = false;
873 bool elite = false;
874 bool rawkey= false;
875 bool errors = false;
876 uint8_t cmdp = 0;
877 while(param_getchar(Cmd, cmdp) != 0x00)
878 {
879 switch(param_getchar(Cmd, cmdp))
880 {
881 case 'h':
882 case 'H':
883 return usage_hf_iclass_writeblock();
884 case 'b':
885 case 'B':
886 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
887 PrintAndLog("Block No must include 2 HEX symbols\n");
888 errors = true;
889 }
890 cmdp += 2;
891 break;
892 case 'c':
893 case 'C':
894 use_credit_key = true;
895 cmdp++;
896 break;
897 case 'd':
898 case 'D':
899 if (param_gethex(Cmd, cmdp+1, bldata, 16))
900 {
901 PrintAndLog("KEY must include 16 HEX symbols\n");
902 errors = true;
903 }
904 cmdp += 2;
905 break;
906 case 'e':
907 case 'E':
908 elite = true;
909 cmdp++;
910 break;
911 case 'k':
912 case 'K':
913 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
914 if (dataLen == 16) {
915 errors = param_gethex(tempStr, 0, KEY, dataLen);
916 } else if (dataLen == 1) {
917 keyNbr = param_get8(Cmd, cmdp+1);
918 if (keyNbr < ICLASS_KEYS_MAX) {
919 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
920 } else {
921 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
922 errors = true;
923 }
924 } else {
925 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
926 errors = true;
927 }
928 cmdp += 2;
929 break;
930 case 'r':
931 case 'R':
932 rawkey = true;
933 cmdp++;
934 break;
935 default:
936 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
937 errors = true;
938 break;
939 }
940 if(errors) return usage_hf_iclass_writeblock();
941 }
942
943 if (cmdp < 6) return usage_hf_iclass_writeblock();
944 int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, true);
945 DropField();
946 return ans;
947 }
948
949 int usage_hf_iclass_clone(void) {
950 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
951 PrintAndLog("Options:");
952 PrintAndLog(" f <filename>: specify a filename to clone from");
953 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
954 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
955 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
956 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
957 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
958 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
959 PrintAndLog("Samples:");
960 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
961 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
962 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
963 return -1;
964 }
965
966 int CmdHFiClassCloneTag(const char *Cmd) {
967 char filename[FILE_PATH_SIZE] = {0};
968 char tempStr[50]={0};
969 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
970 uint8_t keyNbr = 0;
971 uint8_t fileNameLen = 0;
972 uint8_t startblock = 0;
973 uint8_t endblock = 0;
974 uint8_t dataLen = 0;
975 bool use_credit_key = false;
976 bool elite = false;
977 bool rawkey = false;
978 bool errors = false;
979 uint8_t cmdp = 0;
980 while(param_getchar(Cmd, cmdp) != 0x00)
981 {
982 switch(param_getchar(Cmd, cmdp))
983 {
984 case 'h':
985 case 'H':
986 return usage_hf_iclass_clone();
987 case 'b':
988 case 'B':
989 if (param_gethex(Cmd, cmdp+1, &startblock, 2)) {
990 PrintAndLog("Start Block No must include 2 HEX symbols\n");
991 errors = true;
992 }
993 cmdp += 2;
994 break;
995 case 'c':
996 case 'C':
997 use_credit_key = true;
998 cmdp++;
999 break;
1000 case 'e':
1001 case 'E':
1002 elite = true;
1003 cmdp++;
1004 break;
1005 case 'f':
1006 case 'F':
1007 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
1008 if (fileNameLen < 1) {
1009 PrintAndLog("No filename found after f");
1010 errors = true;
1011 }
1012 cmdp += 2;
1013 break;
1014 case 'k':
1015 case 'K':
1016 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1017 if (dataLen == 16) {
1018 errors = param_gethex(tempStr, 0, KEY, dataLen);
1019 } else if (dataLen == 1) {
1020 keyNbr = param_get8(Cmd, cmdp+1);
1021 if (keyNbr < ICLASS_KEYS_MAX) {
1022 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1023 } else {
1024 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1025 errors = true;
1026 }
1027 } else {
1028 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1029 errors = true;
1030 }
1031 cmdp += 2;
1032 break;
1033 case 'l':
1034 case 'L':
1035 if (param_gethex(Cmd, cmdp+1, &endblock, 2)) {
1036 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1037 errors = true;
1038 }
1039 cmdp += 2;
1040 break;
1041 case 'r':
1042 case 'R':
1043 rawkey = true;
1044 cmdp++;
1045 break;
1046 default:
1047 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1048 errors = true;
1049 break;
1050 }
1051 if(errors) return usage_hf_iclass_clone();
1052 }
1053
1054 if (cmdp < 8) return usage_hf_iclass_clone();
1055
1056 FILE *f;
1057
1058 iclass_block_t tag_data[USB_CMD_DATA_SIZE/12];
1059
1060 if ((endblock-startblock+1)*12 > USB_CMD_DATA_SIZE) {
1061 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE/8);
1062 }
1063 // file handling and reading
1064 f = fopen(filename,"rb");
1065 if(!f) {
1066 PrintAndLog("Failed to read from file '%s'", filename);
1067 return 1;
1068 }
1069
1070 if (startblock<5) {
1071 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1072 fclose(f);
1073 return 0;
1074 }
1075 // now read data from the file from block 6 --- 19
1076 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1077 // 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,
1078 // else we have to create a share memory
1079 int i;
1080 fseek(f,startblock*8,SEEK_SET);
1081 if ( fread(tag_data,sizeof(iclass_block_t),endblock - startblock + 1,f) == 0 ) {
1082 PrintAndLog("File reading error.");
1083 fclose(f);
1084 return 2;
1085 }
1086
1087 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1088 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1089
1090 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, true))
1091 return 0;
1092
1093 UsbCommand w = {CMD_ICLASS_CLONE,{startblock,endblock}};
1094 uint8_t *ptr;
1095 // calculate all mac for every the block we will write
1096 for (i = startblock; i <= endblock; i++){
1097 Calc_wb_mac(i,tag_data[i - startblock].d,div_key,MAC);
1098 // usb command d start pointer = d + (i - 6) * 12
1099 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1100 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1101 // next one
1102 ptr = w.d.asBytes + (i - startblock) * 12;
1103 memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
1104 memcpy(ptr + 8,MAC, 4);
1105 }
1106 uint8_t p[12];
1107 for (i = 0; i <= endblock - startblock;i++){
1108 memcpy(p,w.d.asBytes + (i * 12),12);
1109 printf("Block |%02x|",i + startblock);
1110 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]);
1111 printf(" MAC |%02x%02x%02x%02x|\n",p[8],p[9],p[10],p[11]);
1112 }
1113 UsbCommand resp;
1114 SendCommand(&w);
1115 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
1116 {
1117 PrintAndLog("Command execute timeout");
1118 return 0;
1119 }
1120 return 1;
1121 }
1122
1123 static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
1124 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1125 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1126
1127 if (auth) {
1128 if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, rawkey, verbose))
1129 return 0;
1130 } else {
1131 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1132 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1133 if (!select_only(CSN, CCNR, (keyType==0x18), verbose))
1134 return 0;
1135 }
1136
1137 UsbCommand resp;
1138 UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno}};
1139 clearCommandBuffer();
1140 SendCommand(&w);
1141 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
1142 {
1143 PrintAndLog("Command execute timeout");
1144 return 0;
1145 }
1146 uint8_t isOK = resp.arg[0] & 0xff;
1147 if (!isOK) {
1148 PrintAndLog("Read Block Failed");
1149 return 0;
1150 }
1151 //data read is stored in: resp.d.asBytes[0-15]
1152 if (verbose) PrintAndLog("Block %02X: %s\n",blockno, sprint_hex(resp.d.asBytes,8));
1153 return 1;
1154 }
1155
1156 int usage_hf_iclass_readblock(void) {
1157 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1158 PrintAndLog("Options:");
1159 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1160 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1161 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1162 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1163 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1164 PrintAndLog("Samples:");
1165 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1166 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1167 PrintAndLog(" hf iclass readblk b 0A k 0");
1168 return 0;
1169 }
1170
1171 int CmdHFiClass_ReadBlock(const char *Cmd) {
1172 uint8_t blockno=0;
1173 uint8_t keyType = 0x88; //debit key
1174 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1175 uint8_t keyNbr = 0;
1176 uint8_t dataLen = 0;
1177 char tempStr[50] = {0};
1178 bool elite = false;
1179 bool rawkey = false;
1180 bool errors = false;
1181 bool auth = false;
1182 uint8_t cmdp = 0;
1183 while(param_getchar(Cmd, cmdp) != 0x00)
1184 {
1185 switch(param_getchar(Cmd, cmdp))
1186 {
1187 case 'h':
1188 case 'H':
1189 return usage_hf_iclass_readblock();
1190 case 'b':
1191 case 'B':
1192 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
1193 PrintAndLog("Block No must include 2 HEX symbols\n");
1194 errors = true;
1195 }
1196 cmdp += 2;
1197 break;
1198 case 'c':
1199 case 'C':
1200 keyType = 0x18;
1201 cmdp++;
1202 break;
1203 case 'e':
1204 case 'E':
1205 elite = true;
1206 cmdp++;
1207 break;
1208 case 'k':
1209 case 'K':
1210 auth = true;
1211 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1212 if (dataLen == 16) {
1213 errors = param_gethex(tempStr, 0, KEY, dataLen);
1214 } else if (dataLen == 1) {
1215 keyNbr = param_get8(Cmd, cmdp+1);
1216 if (keyNbr < ICLASS_KEYS_MAX) {
1217 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1218 } else {
1219 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1220 errors = true;
1221 }
1222 } else {
1223 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1224 errors = true;
1225 }
1226 cmdp += 2;
1227 break;
1228 case 'r':
1229 case 'R':
1230 rawkey = true;
1231 cmdp++;
1232 break;
1233 default:
1234 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1235 errors = true;
1236 break;
1237 }
1238 if(errors) return usage_hf_iclass_readblock();
1239 }
1240
1241 if (cmdp < 2) return usage_hf_iclass_readblock();
1242 if (!auth)
1243 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1244 return ReadBlock(KEY, blockno, keyType, elite, rawkey, true, auth);
1245 }
1246
1247 int CmdHFiClass_loclass(const char *Cmd) {
1248 char opt = param_getchar(Cmd, 0);
1249
1250 if (strlen(Cmd)<1 || opt == 'h') {
1251 PrintAndLog("Usage: hf iclass loclass [options]");
1252 PrintAndLog("Options:");
1253 PrintAndLog("h Show this help");
1254 PrintAndLog("t Perform self-test");
1255 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1256 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1257 PrintAndLog(" malicious CSNs, and their protocol responses");
1258 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1259 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1260 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1261 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1262 PrintAndLog(" ... totalling N*24 bytes");
1263 return 0;
1264 }
1265 char fileName[255] = {0};
1266 if(opt == 'f')
1267 {
1268 if(param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0)
1269 {
1270 return bruteforceFileNoKeys(fileName);
1271 }else
1272 {
1273 PrintAndLog("You must specify a filename");
1274 }
1275 }
1276 else if(opt == 't')
1277 {
1278 int errors = testCipherUtils();
1279 errors += testMAC();
1280 errors += doKeyTests(0);
1281 errors += testElite();
1282 if(errors)
1283 {
1284 prnlog("OBS! There were errors!!!");
1285 }
1286 return errors;
1287 }
1288
1289 return 0;
1290 }
1291
1292 void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) {
1293 uint8_t mem_config;
1294 memcpy(&mem_config, iclass_dump + 13,1);
1295 uint8_t maxmemcount;
1296 uint8_t filemaxblock = filesize / 8;
1297 if (mem_config & 0x80)
1298 maxmemcount = 255;
1299 else
1300 maxmemcount = 31;
1301 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1302
1303 if (startblock == 0)
1304 startblock = 6;
1305 if ((endblock > maxmemcount) || (endblock == 0))
1306 endblock = maxmemcount;
1307
1308 // remember endblock need to relate to zero-index arrays.
1309 if (endblock > filemaxblock-1)
1310 endblock = filemaxblock;
1311
1312 int i = startblock;
1313 printf("------+--+-------------------------+\n");
1314 while (i <= endblock) {
1315 uint8_t *blk = iclass_dump + (i * 8);
1316 printf("Block |%02X| %s|\n", i, sprint_hex(blk, 8) );
1317 i++;
1318 }
1319 printf("------+--+-------------------------+\n");
1320 }
1321
1322 int usage_hf_iclass_readtagfile() {
1323 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1324 return 1;
1325 }
1326
1327 int CmdHFiClassReadTagFile(const char *Cmd) {
1328 int startblock = 0;
1329 int endblock = 0;
1330 char tempnum[5];
1331 FILE *f;
1332 char filename[FILE_PATH_SIZE];
1333 if (param_getstr(Cmd, 0, filename, sizeof(filename)) < 1)
1334 return usage_hf_iclass_readtagfile();
1335 if (param_getstr(Cmd, 1, tempnum, sizeof(tempnum)) < 1)
1336 startblock = 0;
1337 else
1338 sscanf(tempnum,"%d",&startblock);
1339
1340 if (param_getstr(Cmd,2, tempnum, sizeof(tempnum)) < 1)
1341 endblock = 0;
1342 else
1343 sscanf(tempnum,"%d",&endblock);
1344 // file handling and reading
1345 f = fopen(filename,"rb");
1346 if(!f) {
1347 PrintAndLog("Failed to read from file '%s'", filename);
1348 return 1;
1349 }
1350 fseek(f, 0, SEEK_END);
1351 long fsize = ftell(f);
1352 fseek(f, 0, SEEK_SET);
1353
1354 if ( fsize < 0 ) {
1355 PrintAndLog("Error, when getting filesize");
1356 fclose(f);
1357 return 1;
1358 }
1359
1360 uint8_t *dump = malloc(fsize);
1361
1362 size_t bytes_read = fread(dump, 1, fsize, f);
1363 fclose(f);
1364 uint8_t *csn = dump;
1365 printf("------+--+-------------------------+\n");
1366 printf("CSN |00| %s|\n", sprint_hex(csn, 8) );
1367 // printIclassDumpInfo(dump);
1368 printIclassDumpContents(dump,startblock,endblock,bytes_read);
1369 free(dump);
1370 return 0;
1371 }
1372
1373 /*
1374 uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1375 uint64_t new_div = 0x00;
1376 new_div ^= sdiv;
1377 new_div ^= hdiv;
1378 return new_div;
1379 }
1380
1381 uint64_t hexarray_to_uint64(uint8_t *key) {
1382 char temp[17];
1383 uint64_t uint_key;
1384 for (int i = 0;i < 8;i++)
1385 sprintf(&temp[(i *2)],"%02X",key[i]);
1386 temp[16] = '\0';
1387 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1388 return 0;
1389 return uint_key;
1390 }
1391 */
1392 void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite){
1393 uint8_t keytable[128] = {0};
1394 uint8_t key_index[8] = {0};
1395 if (elite) {
1396 uint8_t key_sel[8] = { 0 };
1397 uint8_t key_sel_p[8] = { 0 };
1398 hash2(KEY, keytable);
1399 hash1(CSN, key_index);
1400 for(uint8_t i = 0; i < 8 ; i++)
1401 key_sel[i] = keytable[key_index[i]] & 0xFF;
1402
1403 //Permute from iclass format to standard format
1404 permutekey_rev(key_sel, key_sel_p);
1405 diversifyKey(CSN, key_sel_p, div_key);
1406 } else {
1407 diversifyKey(CSN, KEY, div_key);
1408 }
1409 }
1410
1411 //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1412 //calculate and return xor_div_key (ready for a key write command)
1413 //print all div_keys if verbose
1414 static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, uint8_t *xor_div_key, bool elite, bool oldElite, bool verbose){
1415 uint8_t old_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1416 uint8_t new_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1417 //get old div key
1418 HFiClassCalcDivKey(CSN, OLDKEY, old_div_key, oldElite);
1419 //get new div key
1420 HFiClassCalcDivKey(CSN, NEWKEY, new_div_key, elite);
1421
1422 for (uint8_t i = 0; i < sizeof(old_div_key); i++){
1423 xor_div_key[i] = old_div_key[i] ^ new_div_key[i];
1424 }
1425 if (verbose) {
1426 printf("Old Div Key : %s\n",sprint_hex(old_div_key,8));
1427 printf("New Div Key : %s\n",sprint_hex(new_div_key,8));
1428 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key,8));
1429 }
1430 }
1431
1432 int usage_hf_iclass_calc_newkey(void) {
1433 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1434 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1435 PrintAndLog(" Options:");
1436 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1437 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1438 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1439 PrintAndLog(" e : specify new key as elite calc");
1440 PrintAndLog(" ee : specify old and new key as elite calc");
1441 PrintAndLog("Samples:");
1442 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1443 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1444 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1445 PrintAndLog("NOTE: * = required\n");
1446
1447 return 1;
1448 }
1449
1450 int CmdHFiClassCalcNewKey(const char *Cmd) {
1451 uint8_t OLDKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1452 uint8_t NEWKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1453 uint8_t xor_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1454 uint8_t CSN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1455 uint8_t CCNR[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1456 uint8_t keyNbr = 0;
1457 uint8_t dataLen = 0;
1458 char tempStr[50] = {0};
1459 bool givenCSN = false;
1460 bool oldElite = false;
1461 bool elite = false;
1462 bool errors = false;
1463 uint8_t cmdp = 0;
1464 while(param_getchar(Cmd, cmdp) != 0x00)
1465 {
1466 switch(param_getchar(Cmd, cmdp))
1467 {
1468 case 'h':
1469 case 'H':
1470 return usage_hf_iclass_calc_newkey();
1471 case 'e':
1472 case 'E':
1473 dataLen = param_getstr(Cmd, cmdp, tempStr, sizeof(tempStr));
1474 if (dataLen==2)
1475 oldElite = true;
1476 elite = true;
1477 cmdp++;
1478 break;
1479 case 'n':
1480 case 'N':
1481 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1482 if (dataLen == 16) {
1483 errors = param_gethex(tempStr, 0, NEWKEY, dataLen);
1484 } else if (dataLen == 1) {
1485 keyNbr = param_get8(Cmd, cmdp+1);
1486 if (keyNbr < ICLASS_KEYS_MAX) {
1487 memcpy(NEWKEY, iClass_Key_Table[keyNbr], 8);
1488 } else {
1489 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1490 errors = true;
1491 }
1492 } else {
1493 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1494 errors = true;
1495 }
1496 cmdp += 2;
1497 break;
1498 case 'o':
1499 case 'O':
1500 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1501 if (dataLen == 16) {
1502 errors = param_gethex(tempStr, 0, OLDKEY, dataLen);
1503 } else if (dataLen == 1) {
1504 keyNbr = param_get8(Cmd, cmdp+1);
1505 if (keyNbr < ICLASS_KEYS_MAX) {
1506 memcpy(OLDKEY, iClass_Key_Table[keyNbr], 8);
1507 } else {
1508 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1509 errors = true;
1510 }
1511 } else {
1512 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1513 errors = true;
1514 }
1515 cmdp += 2;
1516 break;
1517 case 's':
1518 case 'S':
1519 givenCSN = true;
1520 if (param_gethex(Cmd, cmdp+1, CSN, 16))
1521 return usage_hf_iclass_calc_newkey();
1522 cmdp += 2;
1523 break;
1524 default:
1525 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1526 errors = true;
1527 break;
1528 }
1529 if(errors) return usage_hf_iclass_calc_newkey();
1530 }
1531
1532 if (cmdp < 4) return usage_hf_iclass_calc_newkey();
1533
1534 if (!givenCSN)
1535 if (!select_only(CSN, CCNR, false, true))
1536 return 0;
1537
1538 HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, oldElite, true);
1539 return 0;
1540 }
1541
1542 static int loadKeys(char *filename) {
1543 FILE *f;
1544 f = fopen(filename,"rb");
1545 if(!f) {
1546 PrintAndLog("Failed to read from file '%s'", filename);
1547 return 0;
1548 }
1549 fseek(f, 0, SEEK_END);
1550 long fsize = ftell(f);
1551 fseek(f, 0, SEEK_SET);
1552
1553 if ( fsize < 0 ) {
1554 PrintAndLog("Error, when getting filesize");
1555 fclose(f);
1556 return 1;
1557 }
1558
1559 uint8_t *dump = malloc(fsize);
1560
1561 size_t bytes_read = fread(dump, 1, fsize, f);
1562 fclose(f);
1563 if (bytes_read > ICLASS_KEYS_MAX * 8){
1564 PrintAndLog("File is too long to load - bytes: %u", bytes_read);
1565 free(dump);
1566 return 0;
1567 }
1568 uint8_t i = 0;
1569 for (; i < bytes_read/8; i++){
1570 memcpy(iClass_Key_Table[i],dump+(i*8),8);
1571 }
1572 free(dump);
1573 PrintAndLog("%u keys loaded", i);
1574 return 1;
1575 }
1576
1577 static int saveKeys(char *filename) {
1578 FILE *f;
1579 f = fopen(filename,"wb");
1580 if (f == NULL) {
1581 printf("error opening file %s\n",filename);
1582 return 0;
1583 }
1584 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1585 if (fwrite(iClass_Key_Table[i],8,1,f) != 1){
1586 PrintAndLog("save key failed to write to file: %s", filename);
1587 break;
1588 }
1589 }
1590 fclose(f);
1591 return 0;
1592 }
1593
1594 static int printKeys(void) {
1595 PrintAndLog("");
1596 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1597 PrintAndLog("%u: %s",i,sprint_hex(iClass_Key_Table[i],8));
1598 }
1599 PrintAndLog("");
1600 return 0;
1601 }
1602
1603 int usage_hf_iclass_managekeys(void) {
1604 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1605 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1606 PrintAndLog(" Options:");
1607 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1608 PrintAndLog(" k <key> : set a key in memory");
1609 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1610 PrintAndLog(" s : save keys in memory to file specified by filename");
1611 PrintAndLog(" l : load keys to memory from file specified by filename");
1612 PrintAndLog(" p : print keys loaded into memory\n");
1613 PrintAndLog("Samples:");
1614 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1615 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1616 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1617 PrintAndLog(" print keys : hf iclass managekeys p\n");
1618 return 0;
1619 }
1620
1621 int CmdHFiClassManageKeys(const char *Cmd) {
1622 uint8_t keyNbr = 0;
1623 uint8_t dataLen = 0;
1624 uint8_t KEY[8] = {0};
1625 char filename[FILE_PATH_SIZE];
1626 uint8_t fileNameLen = 0;
1627 bool errors = false;
1628 uint8_t operation = 0;
1629 char tempStr[20];
1630 uint8_t cmdp = 0;
1631
1632 while(param_getchar(Cmd, cmdp) != 0x00)
1633 {
1634 switch(param_getchar(Cmd, cmdp))
1635 {
1636 case 'h':
1637 case 'H':
1638 return usage_hf_iclass_managekeys();
1639 case 'f':
1640 case 'F':
1641 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
1642 if (fileNameLen < 1) {
1643 PrintAndLog("No filename found after f");
1644 errors = true;
1645 }
1646 cmdp += 2;
1647 break;
1648 case 'n':
1649 case 'N':
1650 keyNbr = param_get8(Cmd, cmdp+1);
1651 if (keyNbr >= ICLASS_KEYS_MAX) {
1652 PrintAndLog("Invalid block number");
1653 errors = true;
1654 }
1655 cmdp += 2;
1656 break;
1657 case 'k':
1658 case 'K':
1659 operation += 3; //set key
1660 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1661 if (dataLen == 16) { //ul-c or ev1/ntag key length
1662 errors = param_gethex(tempStr, 0, KEY, dataLen);
1663 } else {
1664 PrintAndLog("\nERROR: Key is incorrect length\n");
1665 errors = true;
1666 }
1667 cmdp += 2;
1668 break;
1669 case 'p':
1670 case 'P':
1671 operation += 4; //print keys in memory
1672 cmdp++;
1673 break;
1674 case 'l':
1675 case 'L':
1676 operation += 5; //load keys from file
1677 cmdp++;
1678 break;
1679 case 's':
1680 case 'S':
1681 operation += 6; //save keys to file
1682 cmdp++;
1683 break;
1684 default:
1685 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1686 errors = true;
1687 break;
1688 }
1689 if(errors) return usage_hf_iclass_managekeys();
1690 }
1691 if (operation == 0){
1692 PrintAndLog("no operation specified (load, save, or print)\n");
1693 return usage_hf_iclass_managekeys();
1694 }
1695 if (operation > 6){
1696 PrintAndLog("Too many operations specified\n");
1697 return usage_hf_iclass_managekeys();
1698 }
1699 if (operation > 4 && fileNameLen == 0){
1700 PrintAndLog("You must enter a filename when loading or saving\n");
1701 return usage_hf_iclass_managekeys();
1702 }
1703
1704 switch (operation){
1705 case 3: memcpy(iClass_Key_Table[keyNbr], KEY, 8); return 1;
1706 case 4: return printKeys();
1707 case 5: return loadKeys(filename);
1708 case 6: return saveKeys(filename);
1709 break;
1710 }
1711 return 0;
1712 }
1713
1714 int CmdHFiClassCheckKeys(const char *Cmd) {
1715
1716 uint8_t mac[4] = {0x00,0x00,0x00,0x00};
1717 uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1718 uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1719
1720 // elite key, raw key, standard key
1721 bool use_elite = false;
1722 bool use_raw = false;
1723 bool found_debit = false;
1724 bool found_credit = false;
1725 bool errors = false;
1726 uint8_t cmdp = 0x00;
1727 FILE * f;
1728 char filename[FILE_PATH_SIZE] = {0};
1729 uint8_t fileNameLen = 0;
1730 char buf[17];
1731 uint8_t *keyBlock = NULL, *p;
1732 int keyitems = 0, keycnt = 0;
1733
1734 while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
1735 switch (param_getchar(Cmd, cmdp)) {
1736 case 'h':
1737 case 'H':
1738 return usage_hf_iclass_chk();
1739 case 'f':
1740 case 'F':
1741 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
1742 if (fileNameLen < 1) {
1743 PrintAndLog("No filename found after f");
1744 errors = true;
1745 }
1746 cmdp += 2;
1747 break;
1748 case 'e':
1749 case 'E':
1750 use_elite = true;
1751 cmdp++;
1752 break;
1753 case 'r':
1754 case 'R':
1755 use_raw = true;
1756 cmdp++;
1757 break;
1758 default:
1759 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1760 errors = true;
1761 break;
1762 }
1763 }
1764 if (errors) return usage_hf_iclass_chk();
1765
1766 if ( !(f = fopen( filename , "r")) ) {
1767 PrintAndLog("File: %s: not found or locked.", filename);
1768 return 1;
1769 }
1770
1771 while( fgets(buf, sizeof(buf), f) ){
1772 if (strlen(buf) < 16 || buf[15] == '\n')
1773 continue;
1774
1775 while (fgetc(f) != '\n' && !feof(f)) ; //goto next line
1776
1777 if( buf[0]=='#' ) continue; //The line start with # is comment, skip
1778
1779 if (!isxdigit(buf[0])){
1780 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf);
1781 continue;
1782 }
1783
1784 buf[16] = 0;
1785
1786 p = realloc(keyBlock, 8 * (keyitems += 64));
1787 if (!p) {
1788 PrintAndLog("Cannot allocate memory for default keys");
1789 free(keyBlock);
1790 fclose(f);
1791 return 2;
1792 }
1793 keyBlock = p;
1794
1795 memset(keyBlock + 8 * keycnt, 0, 8);
1796 num_to_bytes(strtoull(buf, NULL, 16), 8, keyBlock + 8 * keycnt);
1797
1798 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1799 keycnt++;
1800 memset(buf, 0, sizeof(buf));
1801 }
1802 fclose(f);
1803 PrintAndLog("Loaded %2d keys from %s", keycnt, filename);
1804
1805 // time
1806 uint64_t t1 = msclock();
1807
1808 for (uint32_t c = 0; c < keycnt; c += 1) {
1809 printf("."); fflush(stdout);
1810 if (ukbhit()) {
1811 int gc = getchar(); (void)gc;
1812 printf("\naborted via keyboard!\n");
1813 break;
1814 }
1815
1816 memcpy(key, keyBlock + 8 * c , 8);
1817
1818 // debit key. try twice
1819 for (int foo = 0; foo < 2 && !found_debit; foo++) {
1820 if (!select_and_auth(key, mac, div_key, false, use_elite, use_raw, false))
1821 continue;
1822
1823 // key found.
1824 PrintAndLog("\n--------------------------------------------------------");
1825 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key, 8));
1826 found_debit = true;
1827 }
1828
1829 // credit key. try twice
1830 for (int foo = 0; foo < 2 && !found_credit; foo++) {
1831 if (!select_and_auth(key, mac, div_key, true, use_elite, use_raw, false))
1832 continue;
1833
1834 // key found
1835 PrintAndLog("\n--------------------------------------------------------");
1836 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key, 8));
1837 found_credit = true;
1838 }
1839
1840 // both keys found.
1841 if ( found_debit && found_credit )
1842 break;
1843 }
1844
1845 t1 = msclock() - t1;
1846
1847 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1/1000.0);
1848
1849 DropField();
1850 free(keyBlock);
1851 PrintAndLog("");
1852 return 0;
1853 }
1854
1855 static command_t CommandTable[] =
1856 {
1857 {"help", CmdHelp, 1, "This help"},
1858 {"calcnewkey", CmdHFiClassCalcNewKey, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1859 {"chk", CmdHFiClassCheckKeys, 0, " Check keys"},
1860 {"clone", CmdHFiClassCloneTag, 0, "[options..] Authenticate and Clone from iClass bin file"},
1861 {"decrypt", CmdHFiClassDecrypt, 1, "[f <fname>] Decrypt tagdump" },
1862 {"dump", CmdHFiClassReader_Dump, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1863 {"eload", CmdHFiClassELoad, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1864 {"encryptblk", CmdHFiClassEncryptBlk, 1, "<BlockData> Encrypt given block data"},
1865 {"list", CmdHFiClassList, 0, " (Deprecated) List iClass history"},
1866 {"loclass", CmdHFiClass_loclass, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1867 {"managekeys", CmdHFiClassManageKeys, 1, "[options..] Manage the keys to use with iClass"},
1868 {"readblk", CmdHFiClass_ReadBlock, 0, "[options..] Authenticate and Read iClass block"},
1869 {"reader", CmdHFiClassReader, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1870 {"readtagfile", CmdHFiClassReadTagFile, 1, "[options..] Display Content from tagfile"},
1871 {"replay", CmdHFiClassReader_Replay, 0, "<mac> Read an iClass tag via Reply Attack"},
1872 {"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"},
1873 {"snoop", CmdHFiClassSnoop, 0, " Eavesdrop iClass communication"},
1874 {"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"},
1875 {NULL, NULL, 0, NULL}
1876 };
1877
1878 int CmdHFiClass(const char *Cmd)
1879 {
1880 clearCommandBuffer();
1881 CmdsParse(CommandTable, Cmd);
1882 return 0;
1883 }
1884
1885 int CmdHelp(const char *Cmd)
1886 {
1887 CmdsHelp(CommandTable);
1888 return 0;
1889 }
Impressum, Datenschutz