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