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