]> cvs.zerfleddert.de Git - proxmark3-svn/blame_incremental - client/cmdhficlass.c
mfkeys.lua: Remove the user input helpers (now in lualibs/utils.lua)
[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 "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
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 des3_context ctx = { DES_DECRYPT ,{ 0 } };
419 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 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 des3_context ctx = { DES_DECRYPT ,{ 0 } };
471 des3_set2key_enc( &ctx, key);
472
473 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);
754 WaitForResponse(CMD_ACK,NULL);
755 size_t gotBytes = blocksRead*8 + blockno*8;
756
757 // try AA2
758 if (have_credit_key) {
759 //turn off hf field before authenticating with different key
760 DropField();
761 memset(MAC,0,4);
762 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
763 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
764 //try twice - for some reason it sometimes fails the first time...
765 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
766 DropField();
767 return 0;
768 }
769 }
770 // do we still need to read more block? (aa2 enabled?)
771 if (maxBlk > blockno+numblks+1) {
772 // setup dump and start
773 w.arg[0] = blockno + blocksRead;
774 w.arg[1] = maxBlk - (blockno + blocksRead);
775 clearCommandBuffer();
776 SendCommand(&w);
777 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
778 PrintAndLog("Command execute timeout 2");
779 DropField();
780 return 0;
781 }
782 uint8_t isOK = resp.arg[0] & 0xff;
783 blocksRead = resp.arg[1];
784 if (!isOK && !blocksRead) {
785 PrintAndLog("Read Block Failed 2");
786 DropField();
787 return 0;
788 }
789
790 startindex = resp.arg[2];
791 if (blocksRead*8 > sizeof(tag_data)-gotBytes) {
792 PrintAndLog("Data exceeded Buffer size!");
793 blocksRead = (sizeof(tag_data) - gotBytes)/8;
794 }
795 // get dumped data from bigbuf
796 GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex);
797 WaitForResponse(CMD_ACK,NULL);
798
799 gotBytes += blocksRead*8;
800 } else { //field is still on - turn it off...
801 DropField();
802 }
803 }
804
805 // add diversified keys to dump
806 if (have_debit_key) memcpy(tag_data+(3*8),div_key,8);
807 if (have_credit_key) memcpy(tag_data+(4*8),c_div_key,8);
808 // print the dump
809 printf("------+--+-------------------------+\n");
810 printf("CSN |00| %s|\n",sprint_hex(tag_data, 8));
811 printIclassDumpContents(tag_data, 1, (gotBytes/8), gotBytes);
812
813 if (filename[0] == 0){
814 snprintf(filename, FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
815 tag_data[0],tag_data[1],tag_data[2],tag_data[3],
816 tag_data[4],tag_data[5],tag_data[6],tag_data[7]);
817 }
818
819 // save the dump to .bin file
820 PrintAndLog("Saving dump file - %d blocks read", gotBytes/8);
821 saveFile(filename, "bin", tag_data, gotBytes);
822 return 1;
823}
824
825static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
826 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
827 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
828 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose))
829 return 0;
830
831 UsbCommand resp;
832
833 Calc_wb_mac(blockno,bldata,div_key,MAC);
834 UsbCommand w = {CMD_ICLASS_WRITEBLOCK, {blockno}};
835 memcpy(w.d.asBytes, bldata, 8);
836 memcpy(w.d.asBytes + 8, MAC, 4);
837
838 clearCommandBuffer();
839 SendCommand(&w);
840 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
841 {
842 PrintAndLog("Write Command execute timeout");
843 return 0;
844 }
845 uint8_t isOK = resp.arg[0] & 0xff;
846 if (!isOK) {
847 PrintAndLog("Write Block Failed");
848 return 0;
849 }
850 PrintAndLog("Write Block Successful");
851 return 1;
852}
853
854int usage_hf_iclass_writeblock(void) {
855 PrintAndLog("Options:");
856 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
857 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
858 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
859 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
860 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
861 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
862 PrintAndLog("Samples:");
863 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
864 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
865 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
866 return 0;
867}
868
869int CmdHFiClass_WriteBlock(const char *Cmd) {
870 uint8_t blockno=0;
871 uint8_t bldata[8]={0,0,0,0,0,0,0,0};
872 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
873 uint8_t keyNbr = 0;
874 uint8_t dataLen = 0;
875 char tempStr[50] = {0};
876 bool use_credit_key = false;
877 bool elite = false;
878 bool rawkey= false;
879 bool errors = false;
880 uint8_t cmdp = 0;
881 while(param_getchar(Cmd, cmdp) != 0x00)
882 {
883 switch(param_getchar(Cmd, cmdp))
884 {
885 case 'h':
886 case 'H':
887 return usage_hf_iclass_writeblock();
888 case 'b':
889 case 'B':
890 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
891 PrintAndLog("Block No must include 2 HEX symbols\n");
892 errors = true;
893 }
894 cmdp += 2;
895 break;
896 case 'c':
897 case 'C':
898 use_credit_key = true;
899 cmdp++;
900 break;
901 case 'd':
902 case 'D':
903 if (param_gethex(Cmd, cmdp+1, bldata, 16))
904 {
905 PrintAndLog("KEY must include 16 HEX symbols\n");
906 errors = true;
907 }
908 cmdp += 2;
909 break;
910 case 'e':
911 case 'E':
912 elite = true;
913 cmdp++;
914 break;
915 case 'k':
916 case 'K':
917 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
918 if (dataLen == 16) {
919 errors = param_gethex(tempStr, 0, KEY, dataLen);
920 } else if (dataLen == 1) {
921 keyNbr = param_get8(Cmd, cmdp+1);
922 if (keyNbr < ICLASS_KEYS_MAX) {
923 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
924 } else {
925 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
926 errors = true;
927 }
928 } else {
929 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
930 errors = true;
931 }
932 cmdp += 2;
933 break;
934 case 'r':
935 case 'R':
936 rawkey = true;
937 cmdp++;
938 break;
939 default:
940 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
941 errors = true;
942 break;
943 }
944 if(errors) return usage_hf_iclass_writeblock();
945 }
946
947 if (cmdp < 6) return usage_hf_iclass_writeblock();
948 int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, true);
949 DropField();
950 return ans;
951}
952
953int usage_hf_iclass_clone(void) {
954 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
955 PrintAndLog("Options:");
956 PrintAndLog(" f <filename>: specify a filename to clone from");
957 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
958 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
959 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
960 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
961 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
962 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
963 PrintAndLog("Samples:");
964 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
965 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
966 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
967 return -1;
968}
969
970int CmdHFiClassCloneTag(const char *Cmd) {
971 char filename[FILE_PATH_SIZE] = {0};
972 char tempStr[50]={0};
973 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
974 uint8_t keyNbr = 0;
975 uint8_t fileNameLen = 0;
976 uint8_t startblock = 0;
977 uint8_t endblock = 0;
978 uint8_t dataLen = 0;
979 bool use_credit_key = false;
980 bool elite = false;
981 bool rawkey = false;
982 bool errors = false;
983 uint8_t cmdp = 0;
984 while(param_getchar(Cmd, cmdp) != 0x00)
985 {
986 switch(param_getchar(Cmd, cmdp))
987 {
988 case 'h':
989 case 'H':
990 return usage_hf_iclass_clone();
991 case 'b':
992 case 'B':
993 if (param_gethex(Cmd, cmdp+1, &startblock, 2)) {
994 PrintAndLog("Start Block No must include 2 HEX symbols\n");
995 errors = true;
996 }
997 cmdp += 2;
998 break;
999 case 'c':
1000 case 'C':
1001 use_credit_key = true;
1002 cmdp++;
1003 break;
1004 case 'e':
1005 case 'E':
1006 elite = true;
1007 cmdp++;
1008 break;
1009 case 'f':
1010 case 'F':
1011 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
1012 if (fileNameLen < 1) {
1013 PrintAndLog("No filename found after f");
1014 errors = true;
1015 }
1016 cmdp += 2;
1017 break;
1018 case 'k':
1019 case 'K':
1020 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1021 if (dataLen == 16) {
1022 errors = param_gethex(tempStr, 0, KEY, dataLen);
1023 } else if (dataLen == 1) {
1024 keyNbr = param_get8(Cmd, cmdp+1);
1025 if (keyNbr < ICLASS_KEYS_MAX) {
1026 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1027 } else {
1028 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1029 errors = true;
1030 }
1031 } else {
1032 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1033 errors = true;
1034 }
1035 cmdp += 2;
1036 break;
1037 case 'l':
1038 case 'L':
1039 if (param_gethex(Cmd, cmdp+1, &endblock, 2)) {
1040 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1041 errors = true;
1042 }
1043 cmdp += 2;
1044 break;
1045 case 'r':
1046 case 'R':
1047 rawkey = true;
1048 cmdp++;
1049 break;
1050 default:
1051 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1052 errors = true;
1053 break;
1054 }
1055 if(errors) return usage_hf_iclass_clone();
1056 }
1057
1058 if (cmdp < 8) return usage_hf_iclass_clone();
1059
1060 FILE *f;
1061
1062 iclass_block_t tag_data[USB_CMD_DATA_SIZE/12];
1063
1064 if ((endblock-startblock+1)*12 > USB_CMD_DATA_SIZE) {
1065 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE/8);
1066 }
1067 // file handling and reading
1068 f = fopen(filename,"rb");
1069 if(!f) {
1070 PrintAndLog("Failed to read from file '%s'", filename);
1071 return 1;
1072 }
1073
1074 if (startblock<5) {
1075 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
1076 fclose(f);
1077 return 0;
1078 }
1079 // now read data from the file from block 6 --- 19
1080 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1081 // 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,
1082 // else we have to create a share memory
1083 int i;
1084 fseek(f,startblock*8,SEEK_SET);
1085 if ( fread(tag_data,sizeof(iclass_block_t),endblock - startblock + 1,f) == 0 ) {
1086 PrintAndLog("File reading error.");
1087 fclose(f);
1088 return 2;
1089 }
1090
1091 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1092 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1093
1094 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, true))
1095 return 0;
1096
1097 UsbCommand w = {CMD_ICLASS_CLONE,{startblock,endblock}};
1098 uint8_t *ptr;
1099 // calculate all mac for every the block we will write
1100 for (i = startblock; i <= endblock; i++){
1101 Calc_wb_mac(i,tag_data[i - startblock].d,div_key,MAC);
1102 // usb command d start pointer = d + (i - 6) * 12
1103 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1104 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1105 // next one
1106 ptr = w.d.asBytes + (i - startblock) * 12;
1107 memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
1108 memcpy(ptr + 8,MAC, 4);
1109 }
1110 uint8_t p[12];
1111 for (i = 0; i <= endblock - startblock;i++){
1112 memcpy(p,w.d.asBytes + (i * 12),12);
1113 printf("Block |%02x|",i + startblock);
1114 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]);
1115 printf(" MAC |%02x%02x%02x%02x|\n",p[8],p[9],p[10],p[11]);
1116 }
1117 UsbCommand resp;
1118 SendCommand(&w);
1119 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
1120 {
1121 PrintAndLog("Command execute timeout");
1122 return 0;
1123 }
1124 return 1;
1125}
1126
1127static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
1128 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1129 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1130
1131 if (auth) {
1132 if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, rawkey, verbose))
1133 return 0;
1134 } else {
1135 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1136 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1137 if (!select_only(CSN, CCNR, (keyType==0x18), verbose))
1138 return 0;
1139 }
1140
1141 UsbCommand resp;
1142 UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno}};
1143 clearCommandBuffer();
1144 SendCommand(&w);
1145 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
1146 {
1147 PrintAndLog("Command execute timeout");
1148 return 0;
1149 }
1150 uint8_t isOK = resp.arg[0] & 0xff;
1151 if (!isOK) {
1152 PrintAndLog("Read Block Failed");
1153 return 0;
1154 }
1155 //data read is stored in: resp.d.asBytes[0-15]
1156 if (verbose) PrintAndLog("Block %02X: %s\n",blockno, sprint_hex(resp.d.asBytes,8));
1157 return 1;
1158}
1159
1160int usage_hf_iclass_readblock(void) {
1161 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
1162 PrintAndLog("Options:");
1163 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1164 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1165 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1166 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
1167 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
1168 PrintAndLog("Samples:");
1169 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1170 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1171 PrintAndLog(" hf iclass readblk b 0A k 0");
1172 return 0;
1173}
1174
1175int CmdHFiClass_ReadBlock(const char *Cmd) {
1176 uint8_t blockno=0;
1177 uint8_t keyType = 0x88; //debit key
1178 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1179 uint8_t keyNbr = 0;
1180 uint8_t dataLen = 0;
1181 char tempStr[50] = {0};
1182 bool elite = false;
1183 bool rawkey = false;
1184 bool errors = false;
1185 bool auth = false;
1186 uint8_t cmdp = 0;
1187 while(param_getchar(Cmd, cmdp) != 0x00)
1188 {
1189 switch(param_getchar(Cmd, cmdp))
1190 {
1191 case 'h':
1192 case 'H':
1193 return usage_hf_iclass_readblock();
1194 case 'b':
1195 case 'B':
1196 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
1197 PrintAndLog("Block No must include 2 HEX symbols\n");
1198 errors = true;
1199 }
1200 cmdp += 2;
1201 break;
1202 case 'c':
1203 case 'C':
1204 keyType = 0x18;
1205 cmdp++;
1206 break;
1207 case 'e':
1208 case 'E':
1209 elite = true;
1210 cmdp++;
1211 break;
1212 case 'k':
1213 case 'K':
1214 auth = true;
1215 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1216 if (dataLen == 16) {
1217 errors = param_gethex(tempStr, 0, KEY, dataLen);
1218 } else if (dataLen == 1) {
1219 keyNbr = param_get8(Cmd, cmdp+1);
1220 if (keyNbr < ICLASS_KEYS_MAX) {
1221 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1222 } else {
1223 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1224 errors = true;
1225 }
1226 } else {
1227 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1228 errors = true;
1229 }
1230 cmdp += 2;
1231 break;
1232 case 'r':
1233 case 'R':
1234 rawkey = true;
1235 cmdp++;
1236 break;
1237 default:
1238 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1239 errors = true;
1240 break;
1241 }
1242 if(errors) return usage_hf_iclass_readblock();
1243 }
1244
1245 if (cmdp < 2) return usage_hf_iclass_readblock();
1246 if (!auth)
1247 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1248 return ReadBlock(KEY, blockno, keyType, elite, rawkey, true, auth);
1249}
1250
1251int CmdHFiClass_loclass(const char *Cmd) {
1252 char opt = param_getchar(Cmd, 0);
1253
1254 if (strlen(Cmd)<1 || opt == 'h') {
1255 PrintAndLog("Usage: hf iclass loclass [options]");
1256 PrintAndLog("Options:");
1257 PrintAndLog("h Show this help");
1258 PrintAndLog("t Perform self-test");
1259 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1260 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1261 PrintAndLog(" malicious CSNs, and their protocol responses");
1262 PrintAndLog(" The binary format of the file is expected to be as follows: ");
1263 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1264 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1265 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1266 PrintAndLog(" ... totalling N*24 bytes");
1267 return 0;
1268 }
1269 char fileName[255] = {0};
1270 if(opt == 'f')
1271 {
1272 if(param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0)
1273 {
1274 return bruteforceFileNoKeys(fileName);
1275 }else
1276 {
1277 PrintAndLog("You must specify a filename");
1278 }
1279 }
1280 else if(opt == 't')
1281 {
1282 int errors = testCipherUtils();
1283 errors += testMAC();
1284 errors += doKeyTests(0);
1285 errors += testElite();
1286 if(errors)
1287 {
1288 prnlog("OBS! There were errors!!!");
1289 }
1290 return errors;
1291 }
1292
1293 return 0;
1294}
1295
1296void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) {
1297 uint8_t mem_config;
1298 memcpy(&mem_config, iclass_dump + 13,1);
1299 uint8_t maxmemcount;
1300 uint8_t filemaxblock = filesize / 8;
1301 if (mem_config & 0x80)
1302 maxmemcount = 255;
1303 else
1304 maxmemcount = 31;
1305 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
1306
1307 if (startblock == 0)
1308 startblock = 6;
1309 if ((endblock > maxmemcount) || (endblock == 0))
1310 endblock = maxmemcount;
1311
1312 // remember endblock need to relate to zero-index arrays.
1313 if (endblock > filemaxblock-1)
1314 endblock = filemaxblock;
1315
1316 int i = startblock;
1317 printf("------+--+-------------------------+\n");
1318 while (i <= endblock) {
1319 uint8_t *blk = iclass_dump + (i * 8);
1320 printf("Block |%02X| %s|\n", i, sprint_hex(blk, 8) );
1321 i++;
1322 }
1323 printf("------+--+-------------------------+\n");
1324}
1325
1326int usage_hf_iclass_readtagfile() {
1327 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1328 return 1;
1329}
1330
1331int CmdHFiClassReadTagFile(const char *Cmd) {
1332 int startblock = 0;
1333 int endblock = 0;
1334 char tempnum[5];
1335 FILE *f;
1336 char filename[FILE_PATH_SIZE];
1337 if (param_getstr(Cmd, 0, filename, sizeof(filename)) < 1)
1338 return usage_hf_iclass_readtagfile();
1339 if (param_getstr(Cmd, 1, tempnum, sizeof(tempnum)) < 1)
1340 startblock = 0;
1341 else
1342 sscanf(tempnum,"%d",&startblock);
1343
1344 if (param_getstr(Cmd,2, tempnum, sizeof(tempnum)) < 1)
1345 endblock = 0;
1346 else
1347 sscanf(tempnum,"%d",&endblock);
1348 // file handling and reading
1349 f = fopen(filename,"rb");
1350 if(!f) {
1351 PrintAndLog("Failed to read from file '%s'", filename);
1352 return 1;
1353 }
1354 fseek(f, 0, SEEK_END);
1355 long fsize = ftell(f);
1356 fseek(f, 0, SEEK_SET);
1357
1358 if ( fsize < 0 ) {
1359 PrintAndLog("Error, when getting filesize");
1360 fclose(f);
1361 return 1;
1362 }
1363
1364 uint8_t *dump = malloc(fsize);
1365
1366 size_t bytes_read = fread(dump, 1, fsize, f);
1367 fclose(f);
1368 uint8_t *csn = dump;
1369 printf("------+--+-------------------------+\n");
1370 printf("CSN |00| %s|\n", sprint_hex(csn, 8) );
1371 // printIclassDumpInfo(dump);
1372 printIclassDumpContents(dump,startblock,endblock,bytes_read);
1373 free(dump);
1374 return 0;
1375}
1376
1377/*
1378uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1379 uint64_t new_div = 0x00;
1380 new_div ^= sdiv;
1381 new_div ^= hdiv;
1382 return new_div;
1383}
1384
1385uint64_t hexarray_to_uint64(uint8_t *key) {
1386 char temp[17];
1387 uint64_t uint_key;
1388 for (int i = 0;i < 8;i++)
1389 sprintf(&temp[(i *2)],"%02X",key[i]);
1390 temp[16] = '\0';
1391 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
1392 return 0;
1393 return uint_key;
1394}
1395*/
1396void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite){
1397 uint8_t keytable[128] = {0};
1398 uint8_t key_index[8] = {0};
1399 if (elite) {
1400 uint8_t key_sel[8] = { 0 };
1401 uint8_t key_sel_p[8] = { 0 };
1402 hash2(KEY, keytable);
1403 hash1(CSN, key_index);
1404 for(uint8_t i = 0; i < 8 ; i++)
1405 key_sel[i] = keytable[key_index[i]] & 0xFF;
1406
1407 //Permute from iclass format to standard format
1408 permutekey_rev(key_sel, key_sel_p);
1409 diversifyKey(CSN, key_sel_p, div_key);
1410 } else {
1411 diversifyKey(CSN, KEY, div_key);
1412 }
1413}
1414
1415//when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1416//calculate and return xor_div_key (ready for a key write command)
1417//print all div_keys if verbose
1418static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, uint8_t *xor_div_key, bool elite, bool oldElite, bool verbose){
1419 uint8_t old_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1420 uint8_t new_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1421 //get old div key
1422 HFiClassCalcDivKey(CSN, OLDKEY, old_div_key, oldElite);
1423 //get new div key
1424 HFiClassCalcDivKey(CSN, NEWKEY, new_div_key, elite);
1425
1426 for (uint8_t i = 0; i < sizeof(old_div_key); i++){
1427 xor_div_key[i] = old_div_key[i] ^ new_div_key[i];
1428 }
1429 if (verbose) {
1430 printf("Old Div Key : %s\n",sprint_hex(old_div_key,8));
1431 printf("New Div Key : %s\n",sprint_hex(new_div_key,8));
1432 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key,8));
1433 }
1434}
1435
1436int usage_hf_iclass_calc_newkey(void) {
1437 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1438 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1439 PrintAndLog(" Options:");
1440 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1441 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1442 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1443 PrintAndLog(" e : specify new key as elite calc");
1444 PrintAndLog(" ee : specify old and new key as elite calc");
1445 PrintAndLog("Samples:");
1446 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1447 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1448 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1449 PrintAndLog("NOTE: * = required\n");
1450
1451 return 1;
1452}
1453
1454int CmdHFiClassCalcNewKey(const char *Cmd) {
1455 uint8_t OLDKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1456 uint8_t NEWKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1457 uint8_t xor_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1458 uint8_t CSN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1459 uint8_t CCNR[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1460 uint8_t keyNbr = 0;
1461 uint8_t dataLen = 0;
1462 char tempStr[50] = {0};
1463 bool givenCSN = false;
1464 bool oldElite = false;
1465 bool elite = false;
1466 bool errors = false;
1467 uint8_t cmdp = 0;
1468 while(param_getchar(Cmd, cmdp) != 0x00)
1469 {
1470 switch(param_getchar(Cmd, cmdp))
1471 {
1472 case 'h':
1473 case 'H':
1474 return usage_hf_iclass_calc_newkey();
1475 case 'e':
1476 case 'E':
1477 dataLen = param_getstr(Cmd, cmdp, tempStr, sizeof(tempStr));
1478 if (dataLen==2)
1479 oldElite = true;
1480 elite = true;
1481 cmdp++;
1482 break;
1483 case 'n':
1484 case 'N':
1485 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1486 if (dataLen == 16) {
1487 errors = param_gethex(tempStr, 0, NEWKEY, dataLen);
1488 } else if (dataLen == 1) {
1489 keyNbr = param_get8(Cmd, cmdp+1);
1490 if (keyNbr < ICLASS_KEYS_MAX) {
1491 memcpy(NEWKEY, iClass_Key_Table[keyNbr], 8);
1492 } else {
1493 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1494 errors = true;
1495 }
1496 } else {
1497 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1498 errors = true;
1499 }
1500 cmdp += 2;
1501 break;
1502 case 'o':
1503 case 'O':
1504 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1505 if (dataLen == 16) {
1506 errors = param_gethex(tempStr, 0, OLDKEY, dataLen);
1507 } else if (dataLen == 1) {
1508 keyNbr = param_get8(Cmd, cmdp+1);
1509 if (keyNbr < ICLASS_KEYS_MAX) {
1510 memcpy(OLDKEY, iClass_Key_Table[keyNbr], 8);
1511 } else {
1512 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1513 errors = true;
1514 }
1515 } else {
1516 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1517 errors = true;
1518 }
1519 cmdp += 2;
1520 break;
1521 case 's':
1522 case 'S':
1523 givenCSN = true;
1524 if (param_gethex(Cmd, cmdp+1, CSN, 16))
1525 return usage_hf_iclass_calc_newkey();
1526 cmdp += 2;
1527 break;
1528 default:
1529 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1530 errors = true;
1531 break;
1532 }
1533 if(errors) return usage_hf_iclass_calc_newkey();
1534 }
1535
1536 if (cmdp < 4) return usage_hf_iclass_calc_newkey();
1537
1538 if (!givenCSN)
1539 if (!select_only(CSN, CCNR, false, true))
1540 return 0;
1541
1542 HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, oldElite, true);
1543 return 0;
1544}
1545
1546static int loadKeys(char *filename) {
1547 FILE *f;
1548 f = fopen(filename,"rb");
1549 if(!f) {
1550 PrintAndLog("Failed to read from file '%s'", filename);
1551 return 0;
1552 }
1553 fseek(f, 0, SEEK_END);
1554 long fsize = ftell(f);
1555 fseek(f, 0, SEEK_SET);
1556
1557 if ( fsize < 0 ) {
1558 PrintAndLog("Error, when getting filesize");
1559 fclose(f);
1560 return 1;
1561 }
1562
1563 uint8_t *dump = malloc(fsize);
1564
1565 size_t bytes_read = fread(dump, 1, fsize, f);
1566 fclose(f);
1567 if (bytes_read > ICLASS_KEYS_MAX * 8){
1568 PrintAndLog("File is too long to load - bytes: %u", bytes_read);
1569 free(dump);
1570 return 0;
1571 }
1572 uint8_t i = 0;
1573 for (; i < bytes_read/8; i++){
1574 memcpy(iClass_Key_Table[i],dump+(i*8),8);
1575 }
1576 free(dump);
1577 PrintAndLog("%u keys loaded", i);
1578 return 1;
1579}
1580
1581static int saveKeys(char *filename) {
1582 FILE *f;
1583 f = fopen(filename,"wb");
1584 if (f == NULL) {
1585 printf("error opening file %s\n",filename);
1586 return 0;
1587 }
1588 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1589 if (fwrite(iClass_Key_Table[i],8,1,f) != 1){
1590 PrintAndLog("save key failed to write to file: %s", filename);
1591 break;
1592 }
1593 }
1594 fclose(f);
1595 return 0;
1596}
1597
1598static int printKeys(void) {
1599 PrintAndLog("");
1600 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1601 PrintAndLog("%u: %s",i,sprint_hex(iClass_Key_Table[i],8));
1602 }
1603 PrintAndLog("");
1604 return 0;
1605}
1606
1607int usage_hf_iclass_managekeys(void) {
1608 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1609 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1610 PrintAndLog(" Options:");
1611 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1612 PrintAndLog(" k <key> : set a key in memory");
1613 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1614 PrintAndLog(" s : save keys in memory to file specified by filename");
1615 PrintAndLog(" l : load keys to memory from file specified by filename");
1616 PrintAndLog(" p : print keys loaded into memory\n");
1617 PrintAndLog("Samples:");
1618 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1619 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1620 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1621 PrintAndLog(" print keys : hf iclass managekeys p\n");
1622 return 0;
1623}
1624
1625int CmdHFiClassManageKeys(const char *Cmd) {
1626 uint8_t keyNbr = 0;
1627 uint8_t dataLen = 0;
1628 uint8_t KEY[8] = {0};
1629 char filename[FILE_PATH_SIZE];
1630 uint8_t fileNameLen = 0;
1631 bool errors = false;
1632 uint8_t operation = 0;
1633 char tempStr[20];
1634 uint8_t cmdp = 0;
1635
1636 while(param_getchar(Cmd, cmdp) != 0x00)
1637 {
1638 switch(param_getchar(Cmd, cmdp))
1639 {
1640 case 'h':
1641 case 'H':
1642 return usage_hf_iclass_managekeys();
1643 case 'f':
1644 case 'F':
1645 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
1646 if (fileNameLen < 1) {
1647 PrintAndLog("No filename found after f");
1648 errors = true;
1649 }
1650 cmdp += 2;
1651 break;
1652 case 'n':
1653 case 'N':
1654 keyNbr = param_get8(Cmd, cmdp+1);
1655 if (keyNbr >= ICLASS_KEYS_MAX) {
1656 PrintAndLog("Invalid block number");
1657 errors = true;
1658 }
1659 cmdp += 2;
1660 break;
1661 case 'k':
1662 case 'K':
1663 operation += 3; //set key
1664 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
1665 if (dataLen == 16) { //ul-c or ev1/ntag key length
1666 errors = param_gethex(tempStr, 0, KEY, dataLen);
1667 } else {
1668 PrintAndLog("\nERROR: Key is incorrect length\n");
1669 errors = true;
1670 }
1671 cmdp += 2;
1672 break;
1673 case 'p':
1674 case 'P':
1675 operation += 4; //print keys in memory
1676 cmdp++;
1677 break;
1678 case 'l':
1679 case 'L':
1680 operation += 5; //load keys from file
1681 cmdp++;
1682 break;
1683 case 's':
1684 case 'S':
1685 operation += 6; //save keys to file
1686 cmdp++;
1687 break;
1688 default:
1689 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1690 errors = true;
1691 break;
1692 }
1693 if(errors) return usage_hf_iclass_managekeys();
1694 }
1695 if (operation == 0){
1696 PrintAndLog("no operation specified (load, save, or print)\n");
1697 return usage_hf_iclass_managekeys();
1698 }
1699 if (operation > 6){
1700 PrintAndLog("Too many operations specified\n");
1701 return usage_hf_iclass_managekeys();
1702 }
1703 if (operation > 4 && fileNameLen == 0){
1704 PrintAndLog("You must enter a filename when loading or saving\n");
1705 return usage_hf_iclass_managekeys();
1706 }
1707
1708 switch (operation){
1709 case 3: memcpy(iClass_Key_Table[keyNbr], KEY, 8); return 1;
1710 case 4: return printKeys();
1711 case 5: return loadKeys(filename);
1712 case 6: return saveKeys(filename);
1713 break;
1714 }
1715 return 0;
1716}
1717
1718int CmdHFiClassCheckKeys(const char *Cmd) {
1719
1720 uint8_t mac[4] = {0x00,0x00,0x00,0x00};
1721 uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1722 uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1723
1724 // elite key, raw key, standard key
1725 bool use_elite = false;
1726 bool use_raw = false;
1727 bool found_debit = false;
1728 bool found_credit = false;
1729 bool errors = false;
1730 uint8_t cmdp = 0x00;
1731 FILE * f;
1732 char filename[FILE_PATH_SIZE] = {0};
1733 uint8_t fileNameLen = 0;
1734 char buf[17];
1735 uint8_t *keyBlock = NULL, *p;
1736 int keyitems = 0, keycnt = 0;
1737
1738 while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
1739 switch (param_getchar(Cmd, cmdp)) {
1740 case 'h':
1741 case 'H':
1742 return usage_hf_iclass_chk();
1743 case 'f':
1744 case 'F':
1745 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
1746 if (fileNameLen < 1) {
1747 PrintAndLog("No filename found after f");
1748 errors = true;
1749 }
1750 cmdp += 2;
1751 break;
1752 case 'e':
1753 case 'E':
1754 use_elite = true;
1755 cmdp++;
1756 break;
1757 case 'r':
1758 case 'R':
1759 use_raw = true;
1760 cmdp++;
1761 break;
1762 default:
1763 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1764 errors = true;
1765 break;
1766 }
1767 }
1768 if (errors) return usage_hf_iclass_chk();
1769
1770 if ( !(f = fopen( filename , "r")) ) {
1771 PrintAndLog("File: %s: not found or locked.", filename);
1772 return 1;
1773 }
1774
1775 while( fgets(buf, sizeof(buf), f) ){
1776 if (strlen(buf) < 16 || buf[15] == '\n')
1777 continue;
1778
1779 while (fgetc(f) != '\n' && !feof(f)) ; //goto next line
1780
1781 if( buf[0]=='#' ) continue; //The line start with # is comment, skip
1782
1783 if (!isxdigit(buf[0])){
1784 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf);
1785 continue;
1786 }
1787
1788 buf[16] = 0;
1789
1790 p = realloc(keyBlock, 8 * (keyitems += 64));
1791 if (!p) {
1792 PrintAndLog("Cannot allocate memory for default keys");
1793 free(keyBlock);
1794 fclose(f);
1795 return 2;
1796 }
1797 keyBlock = p;
1798
1799 memset(keyBlock + 8 * keycnt, 0, 8);
1800 num_to_bytes(strtoull(buf, NULL, 16), 8, keyBlock + 8 * keycnt);
1801
1802 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1803 keycnt++;
1804 memset(buf, 0, sizeof(buf));
1805 }
1806 fclose(f);
1807 PrintAndLog("Loaded %2d keys from %s", keycnt, filename);
1808
1809 // time
1810 uint64_t t1 = msclock();
1811
1812 for (uint32_t c = 0; c < keycnt; c += 1) {
1813 printf("."); fflush(stdout);
1814 if (ukbhit()) {
1815 int gc = getchar(); (void)gc;
1816 printf("\naborted via keyboard!\n");
1817 break;
1818 }
1819
1820 memcpy(key, keyBlock + 8 * c , 8);
1821
1822 // debit key. try twice
1823 for (int foo = 0; foo < 2 && !found_debit; foo++) {
1824 if (!select_and_auth(key, mac, div_key, false, use_elite, use_raw, false))
1825 continue;
1826
1827 // key found.
1828 PrintAndLog("\n--------------------------------------------------------");
1829 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key, 8));
1830 found_debit = true;
1831 }
1832
1833 // credit key. try twice
1834 for (int foo = 0; foo < 2 && !found_credit; foo++) {
1835 if (!select_and_auth(key, mac, div_key, true, use_elite, use_raw, false))
1836 continue;
1837
1838 // key found
1839 PrintAndLog("\n--------------------------------------------------------");
1840 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key, 8));
1841 found_credit = true;
1842 }
1843
1844 // both keys found.
1845 if ( found_debit && found_credit )
1846 break;
1847 }
1848
1849 t1 = msclock() - t1;
1850
1851 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1/1000.0);
1852
1853 DropField();
1854 free(keyBlock);
1855 PrintAndLog("");
1856 return 0;
1857}
1858
1859static command_t CommandTable[] =
1860{
1861 {"help", CmdHelp, 1, "This help"},
1862 {"calcnewkey", CmdHFiClassCalcNewKey, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1863 {"chk", CmdHFiClassCheckKeys, 0, " Check keys"},
1864 {"clone", CmdHFiClassCloneTag, 0, "[options..] Authenticate and Clone from iClass bin file"},
1865 {"decrypt", CmdHFiClassDecrypt, 1, "[f <fname>] Decrypt tagdump" },
1866 {"dump", CmdHFiClassReader_Dump, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1867 {"eload", CmdHFiClassELoad, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1868 {"encryptblk", CmdHFiClassEncryptBlk, 1, "<BlockData> Encrypt given block data"},
1869 {"list", CmdHFiClassList, 0, " (Deprecated) List iClass history"},
1870 {"loclass", CmdHFiClass_loclass, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1871 {"managekeys", CmdHFiClassManageKeys, 1, "[options..] Manage the keys to use with iClass"},
1872 {"readblk", CmdHFiClass_ReadBlock, 0, "[options..] Authenticate and Read iClass block"},
1873 {"reader", CmdHFiClassReader, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
1874 {"readtagfile", CmdHFiClassReadTagFile, 1, "[options..] Display Content from tagfile"},
1875 {"replay", CmdHFiClassReader_Replay, 0, "<mac> Read an iClass tag via Reply Attack"},
1876 {"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"},
1877 {"snoop", CmdHFiClassSnoop, 0, " Eavesdrop iClass communication"},
1878 {"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"},
1879 {NULL, NULL, 0, NULL}
1880};
1881
1882int CmdHFiClass(const char *Cmd)
1883{
1884 clearCommandBuffer();
1885 CmdsParse(CommandTable, Cmd);
1886 return 0;
1887}
1888
1889int CmdHelp(const char *Cmd)
1890{
1891 CmdsHelp(CommandTable);
1892 return 0;
1893}
Impressum, Datenschutz