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