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