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