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