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