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