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