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