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