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