]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhficlass.c
FIX: had to make it clientside only
[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
cee5a30d 13#include "cmdhficlass.h"
e98572a1 14
cee5a30d 15static int CmdHelp(const char *Cmd);
16
76c74bf9 17#define NUM_CSNS 15
e98572a1 18#define ICLASS_KEYS_MAX 8
19static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = {
20 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
21 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
22 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
23 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
24 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
25 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
26 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
27 { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }
28};
29
30typedef struct iclass_block {
31 uint8_t d[8];
32} iclass_block_t;
33
76c74bf9 34int usage_hf_iclass_sim(void) {
35 PrintAndLog("Usage: hf iclass sim <option> [CSN]");
36 PrintAndLog(" options");
37 PrintAndLog(" 0 <CSN> simulate the given CSN");
38 PrintAndLog(" 1 simulate default CSN");
39 PrintAndLog(" 2 Reader-attack, gather reader responses to extract elite key");
40 PrintAndLog(" 3 Full simulation using emulator memory (see 'hf iclass eload')");
41 PrintAndLog(" example: hf iclass sim 0 031FEC8AF7FF12E0");
42 PrintAndLog(" example: hf iclass sim 2");
43 PrintAndLog(" example: hf iclass eload 'tagdump.bin'");
44 PrintAndLog(" hf iclass sim 3");
45 return 0;
46}
47int usage_hf_iclass_eload(void) {
48 PrintAndLog("Loads iclass tag-dump into emulator memory on device");
49 PrintAndLog("Usage: hf iclass eload f <filename>");
50 PrintAndLog("");
51 PrintAndLog("Example: hf iclass eload f iclass_tagdump-aa162d30f8ff12f1.bin");
52 return 0;
53}
54int usage_hf_iclass_decrypt(void) {
55 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
56 PrintAndLog("");
57 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
58 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
59 PrintAndLog("");
60 PrintAndLog("example: hf iclass decrypt f tagdump_12312342343.bin");
61 PrintAndLog("");
62 PrintAndLog("OBS! This is pretty stupid implementation, it tries to decrypt every block after block 6. ");
63 PrintAndLog("Correct behaviour would be to decrypt only the application areas where the key is valid,");
64 PrintAndLog("which is defined by the configuration block.");
65 return 1;
66}
67int usage_hf_iclass_encrypt(void) {
68 PrintAndLog("Usage: hf iclass encrypt <BlockData>");
69 PrintAndLog("");
70 PrintAndLog("OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside");
71 PrintAndLog("in the working directory. The file should be 16 bytes binary data");
72 PrintAndLog("");
73 PrintAndLog("example: hf iclass encrypt 0102030405060708");
74 PrintAndLog("");
75 return 0;
76}
77int usage_hf_iclass_dump(void) {
78 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
79 PrintAndLog("Options:");
80 PrintAndLog(" f <filename> : specify a filename to save dump to");
81 PrintAndLog(" k <Key> : *Access Key as 16 hex symbols or 1 hex to select key from memory");
82 PrintAndLog(" c <CreditKey>: Credit Key as 16 hex symbols or 1 hex to select key from memory");
83 PrintAndLog(" e : If 'e' is specified, the key is interpreted as the 16 byte");
84 PrintAndLog(" Custom Key (KCus), which can be obtained via reader-attack");
85 PrintAndLog(" See 'hf iclass sim 2'. This key should be on iclass-format");
86 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
87 PrintAndLog(" NOTE: * = required");
88 PrintAndLog("Samples:");
89 PrintAndLog(" hf iclass dump k 001122334455667B");
90 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA c 001122334455667B");
91 PrintAndLog(" hf iclass dump k AAAAAAAAAAAAAAAA e");
92 return 0;
93}
94int usage_hf_iclass_clone(void) {
95 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
96 PrintAndLog("Options:");
97 PrintAndLog(" f <filename>: specify a filename to clone from");
98 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
99 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
100 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
101 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
102 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
103 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
104 PrintAndLog("Samples:");
105 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
106 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
107 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
108 return -1;
109}
110int usage_hf_iclass_writeblock(void) {
111 PrintAndLog("Options:");
112 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
113 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
114 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
115 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
116 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
117 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
118 PrintAndLog("Samples:");
119 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
120 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
121 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
122 return 0;
123}
124int usage_hf_iclass_readblock(void) {
125 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
126 PrintAndLog("Options:");
127 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
128 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
129 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
130 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
131 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
132 PrintAndLog("Samples:");
133 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
134 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
135 PrintAndLog(" hf iclass readblk b 0A k 0");
136 return 0;
137}
138int usage_hf_iclass_readtagfile() {
139 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
140 return 1;
141}
142int usage_hf_iclass_calc_newkey(void) {
143 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
144 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
145 PrintAndLog(" Options:");
146 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
147 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
148 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
149 PrintAndLog(" e : specify new key as elite calc");
150 PrintAndLog(" ee : specify old and new key as elite calc");
151 PrintAndLog("Samples:");
152 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
153 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
154 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
155 PrintAndLog("NOTE: * = required\n");
156 return 1;
157}
158int usage_hf_iclass_managekeys(void) {
159 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
160 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
161 PrintAndLog(" Options:");
162 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
163 PrintAndLog(" k <key> : set a key in memory");
164 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
165 PrintAndLog(" s : save keys in memory to file specified by filename");
166 PrintAndLog(" l : load keys to memory from file specified by filename");
167 PrintAndLog(" p : print keys loaded into memory\n");
168 PrintAndLog("Samples:");
169 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
170 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
171 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
172 PrintAndLog(" print keys : hf iclass managekeys p\n");
173 return 0;
174}
042db564 175int usage_hf_iclass_reader(void) {
176 PrintAndLog("HELP : Act as a Iclass reader:\n");
177 PrintAndLog("Usage: hf iclass reader [h] [1]\n");
178 PrintAndLog("Options:");
179 PrintAndLog(" h This help text");
180 PrintAndLog(" 1 read only 1 tag");
181 PrintAndLog("Samples:");
182 PrintAndLog(" hf iclass reader 1");
183 return 0;
184}
185int usage_hf_iclass_replay(void){
186 PrintAndLog("HELP: Replay a collected mac message");
187 PrintAndLog("Usage: hf iclass replay [h] <mac>");
188 PrintAndLog("Options:");
189 PrintAndLog(" h This help text");
190 PrintAndLog(" <mac> Mac bytes to replay (8 hexsymbols)");
191 PrintAndLog("Samples:");
192 PrintAndLog(" hf iclass replay 00112233");
193 return 0;
194}
195int usage_hf_iclass_snoop(void){
196 PrintAndLog("HELP: Snoops the communication between reader and tag");
197 PrintAndLog("Usage: hf iclass snoop [h]");
198 PrintAndLog("Samples:");
199 PrintAndLog(" hf iclass snoop");
200 return 0;
201}
e98572a1 202int xorbits_8(uint8_t val) {
53444513
MHS
203 uint8_t res = val ^ (val >> 1); //1st pass
204 res = res ^ (res >> 1); // 2nd pass
205 res = res ^ (res >> 2); // 3rd pass
206 res = res ^ (res >> 4); // 4th pass
207 return res & 1;
17cba269
MHS
208}
209
e98572a1 210int CmdHFiClassList(const char *Cmd) {
9332b857 211 //PrintAndLog("Deprecated command, use 'hf list iclass' instead");
212 CmdHFList("iclass");
17cba269
MHS
213 return 0;
214}
215
e98572a1 216int CmdHFiClassSnoop(const char *Cmd) {
042db564 217 char cmdp = param_getchar(Cmd, 0);
218 if (cmdp == 'h' || cmdp == 'H') return usage_hf_iclass_snoop();
219
53444513
MHS
220 UsbCommand c = {CMD_SNOOP_ICLASS};
221 SendCommand(&c);
222 return 0;
cee5a30d 223}
e98572a1 224
e98572a1 225int CmdHFiClassSim(const char *Cmd) {
53444513
MHS
226 uint8_t simType = 0;
227 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
228
67d78d0c 229 if (strlen(Cmd)<1) return usage_hf_iclass_sim();
230
1defcf60 231 simType = param_get8ex(Cmd, 0, 0, 10);
53444513
MHS
232
233 if(simType == 0)
234 {
235 if (param_gethex(Cmd, 1, CSN, 16)) {
236 PrintAndLog("A CSN should consist of 16 HEX symbols");
41524d8a 237 return usage_hf_iclass_sim();
53444513 238 }
53444513 239
41524d8a 240 PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
53444513 241 }
67d78d0c 242
41524d8a 243 if(simType > 3)
53444513
MHS
244 {
245 PrintAndLog("Undefined simptype %d", simType);
41524d8a 246 return usage_hf_iclass_sim();
53444513 247 }
1e262141 248
41524d8a 249 uint8_t numberOfCSNs=0;
9f6e9d15
MHS
250 if(simType == 2)
251 {
6116c796 252 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
9f6e9d15 253 UsbCommand resp = {0};
17cba269 254
53444513
MHS
255 uint8_t csns[8*NUM_CSNS] = {
256 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
257 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
258 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
259 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
260 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
261 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
262 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
263 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
264 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
265 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
266 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
267 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
268 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
269 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
270 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
6116c796
MHS
271
272 memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
67d78d0c 273 clearCommandBuffer();
9f6e9d15
MHS
274 SendCommand(&c);
275 if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
276 PrintAndLog("Command timed out");
277 return 0;
278 }
1e262141 279
77abe781 280 uint8_t num_mac_responses = resp.arg[1];
6116c796 281 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
9f6e9d15 282
6116c796 283 size_t datalen = NUM_CSNS*24;
9f6e9d15
MHS
284 /*
285 * Now, time to dump to file. We'll use this format:
77abe781 286 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
9f6e9d15 287 * So, it should wind up as
77abe781
MHS
288 * 8 * 24 bytes.
289 *
290 * The returndata from the pm3 is on the following format
291 * <4 byte NR><4 byte MAC>
292 * CC are all zeroes, CSN is the same as was sent in
9f6e9d15 293 **/
77abe781
MHS
294 void* dump = malloc(datalen);
295 memset(dump,0,datalen);//<-- Need zeroes for the CC-field
9f6e9d15 296 uint8_t i = 0;
67d78d0c 297 for(i = 0 ; i < NUM_CSNS ; i++) {
298 memcpy(dump+i*24, csns+i*8, 8); //CSN
77abe781
MHS
299 //8 zero bytes here...
300 //Then comes NR_MAC (eight bytes from the response)
67d78d0c 301 memcpy(dump+i*24+16, resp.d.asBytes+i*8, 8);
9f6e9d15
MHS
302 }
303 /** Now, save to dumpfile **/
67d78d0c 304 saveFile("iclass_mac_attack", "bin", dump, datalen);
77abe781 305 free(dump);
67d78d0c 306 } else {
9f6e9d15
MHS
307 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
308 memcpy(c.d.asBytes, CSN, 8);
67d78d0c 309 clearCommandBuffer();
9f6e9d15
MHS
310 SendCommand(&c);
311 }
53444513 312 return 0;
1e262141 313}
314
e98572a1 315int HFiClassReader(const char *Cmd, bool loop, bool verbose) {
8949bb5d 316 bool tagFound = false;
67d78d0c 317 UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN |
318 FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_AA}};
e98572a1 319 // loop in client not device - else on windows have a communication error
320 c.arg[0] |= FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY;
53444513
MHS
321 UsbCommand resp;
322 while(!ukbhit()){
67d78d0c 323 clearCommandBuffer();
e98572a1 324 SendCommand(&c);
6ce0e538 325 if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
67d78d0c 326 uint8_t readStatus = resp.arg[0] & 0xff;
6ce0e538 327 uint8_t *data = resp.d.asBytes;
53444513 328
67d78d0c 329 if (verbose) PrintAndLog("Readstatus:%02x", readStatus);
caaf9618 330 if( readStatus == 0){
53444513 331 //Aborted
8949bb5d 332 if (verbose) PrintAndLog("Quitting...");
53444513
MHS
333 return 0;
334 }
8949bb5d 335 if( readStatus & FLAG_ICLASS_READER_CSN){
336 PrintAndLog("CSN: %s",sprint_hex(data,8));
337 tagFound = true;
338 }
67d78d0c 339 if( readStatus & FLAG_ICLASS_READER_CC) PrintAndLog("CC: %s", sprint_hex(data+16, 8));
340 if( readStatus & FLAG_ICLASS_READER_CONF) printIclassDumpInfo(data);
8949bb5d 341 if (tagFound && !loop) return 1;
53444513 342 } else {
8949bb5d 343 if (verbose) PrintAndLog("Command execute timeout");
53444513 344 }
8949bb5d 345 if (!loop) break;
53444513 346 }
53444513 347 return 0;
8949bb5d 348}
349
042db564 350int CmdHFiClassReader(const char *Cmd) {
351 char cmdp = param_getchar(Cmd, 0);
352 if (cmdp == 'h' || cmdp == 'H') return usage_hf_iclass_reader();
353 bool findone = (cmdp == '1') ? FALSE : TRUE;
354 return HFiClassReader(Cmd, findone, true);
c3963755 355}
356
e98572a1 357int CmdHFiClassReader_Replay(const char *Cmd) {
53444513
MHS
358 uint8_t readerType = 0;
359 uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
c3963755 360
042db564 361 if (strlen(Cmd)<1) return usage_hf_iclass_replay();
c3963755 362
53444513
MHS
363 if (param_gethex(Cmd, 0, MAC, 8)) {
364 PrintAndLog("MAC must include 8 HEX symbols");
365 return 1;
366 }
c3963755 367
53444513
MHS
368 UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
369 memcpy(c.d.asBytes, MAC, 4);
67d78d0c 370 clearCommandBuffer();
53444513 371 SendCommand(&c);
53444513 372 return 0;
1e262141 373}
374
e98572a1 375int iclassEmlSetMem(uint8_t *data, int blockNum, int blocksCount) {
376 UsbCommand c = {CMD_MIFARE_EML_MEMSET, {blockNum, blocksCount, 0}};
377 memcpy(c.d.asBytes, data, blocksCount * 16);
67d78d0c 378 clearCommandBuffer();
53444513 379 SendCommand(&c);
53444513 380 return 0;
1e262141 381}
382
e98572a1 383int CmdHFiClassELoad(const char *Cmd) {
7781a656
MHS
384
385 char opt = param_getchar(Cmd, 0);
76c74bf9 386 if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_eload();
7781a656
MHS
387
388 //File handling and reading
389 FILE *f;
390 char filename[FILE_PATH_SIZE];
9c4e28a4 391 if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0) {
7781a656 392 f = fopen(filename, "rb");
9c4e28a4 393 } else {
76c74bf9 394 return usage_hf_iclass_eload();
7781a656
MHS
395 }
396
397 if(!f) {
398 PrintAndLog("Failed to read from file '%s'", filename);
399 return 1;
400 }
401
402 fseek(f, 0, SEEK_END);
403 long fsize = ftell(f);
404 fseek(f, 0, SEEK_SET);
405
9c4e28a4 406 if (fsize < 0) {
407 prnlog("Error, when getting filesize");
4bb17c66 408 fclose(f);
9c4e28a4 409 return 1;
410 }
411
9c4e28a4 412 uint8_t *dump = malloc(fsize);
1defcf60 413
7781a656
MHS
414 size_t bytes_read = fread(dump, 1, fsize, f);
415 fclose(f);
416
1defcf60 417 printIclassDumpInfo(dump);
7781a656
MHS
418 //Validate
419
67d78d0c 420 if (bytes_read < fsize) {
7781a656
MHS
421 prnlog("Error, could only read %d bytes (should be %d)",bytes_read, fsize );
422 free(dump);
423 return 1;
424 }
425 //Send to device
426 uint32_t bytes_sent = 0;
427 uint32_t bytes_remaining = bytes_read;
428
429 while(bytes_remaining > 0){
430 uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining);
431 UsbCommand c = {CMD_ICLASS_EML_MEMSET, {bytes_sent,bytes_in_packet,0}};
432 memcpy(c.d.asBytes, dump, bytes_in_packet);
67d78d0c 433 clearCommandBuffer();
7781a656
MHS
434 SendCommand(&c);
435 bytes_remaining -= bytes_in_packet;
436 bytes_sent += bytes_in_packet;
437 }
438 free(dump);
439 PrintAndLog("Sent %d bytes of data to device emulator memory", bytes_sent);
440 return 0;
441}
442
e98572a1 443static int readKeyfile(const char *filename, size_t len, uint8_t* buffer) {
41524d8a
MHS
444 FILE *f = fopen(filename, "rb");
445 if(!f) {
446 PrintAndLog("Failed to read from file '%s'", filename);
447 return 1;
448 }
449 fseek(f, 0, SEEK_END);
450 long fsize = ftell(f);
451 fseek(f, 0, SEEK_SET);
452 size_t bytes_read = fread(buffer, 1, len, f);
453 fclose(f);
67d78d0c 454
455 if(fsize != len) {
41524d8a
MHS
456 PrintAndLog("Warning, file size is %d, expected %d", fsize, len);
457 return 1;
458 }
67d78d0c 459
460 if(bytes_read != len) {
41524d8a
MHS
461 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len);
462 return 1;
463 }
464 return 0;
465}
466
e98572a1 467int CmdHFiClassDecrypt(const char *Cmd) {
042db564 468
469 char opt = param_getchar(Cmd, 0);
470 if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_decrypt();
471
41524d8a 472 uint8_t key[16] = { 0 };
76c74bf9 473 if(readKeyfile("iclass_decryptionkey.bin", 16, key)) return usage_hf_iclass_decrypt();
474
db289ea7 475 PrintAndLog("Decryption key loaded from file [ok]");
41524d8a
MHS
476
477 //Open the tagdump-file
478 FILE *f;
479 char filename[FILE_PATH_SIZE];
3c406169 480 if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0) {
db289ea7 481 f = fopen(filename, "rb");
482 if (!f) {
3c406169 483 PrintAndLog("Could not find file %s", filename);
484 return 1;
67d78d0c 485 }
3c406169 486 } else {
41524d8a 487 return usage_hf_iclass_decrypt();
3c406169 488 }
41524d8a
MHS
489
490 fseek(f, 0, SEEK_END);
491 long fsize = ftell(f);
492 fseek(f, 0, SEEK_SET);
76c74bf9 493
494 if ( fsize < 0 ) {
495 PrintAndLog("Error, when getting filesize");
496 fclose(f);
497 return 2;
498 }
499
41524d8a 500 uint8_t *decrypted = malloc(fsize);
76c74bf9 501
502 size_t bytes_read = fread(decrypted, 1, fsize, f);
503 fclose(f);
504 if ( bytes_read == 0) {
505 PrintAndLog("File reading error");
506 free(decrypted);
507 return 3;
508 }
41524d8a 509
76c74bf9 510 picopass_hdr *hdr = (picopass_hdr *)decrypted;
511
512 uint8_t mem = hdr->conf.mem_config;
513 uint8_t chip = hdr->conf.chip_config;
514 uint8_t applimit = hdr->conf.app_limit;
515 uint8_t kb = 2;
516 uint8_t app_areas = 2;
517 uint8_t max_blk = 31;
518 getMemConfig(mem, chip, &max_blk, &app_areas, &kb);
519
41524d8a 520 //Use the first block (CSN) for filename
76c74bf9 521 char outfilename[FILE_PATH_SIZE] = {0};
522 snprintf(outfilename, FILE_PATH_SIZE, "iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted",
523 hdr->csn[0],hdr->csn[1],hdr->csn[2],hdr->csn[3],
524 hdr->csn[4],hdr->csn[5],hdr->csn[6],hdr->csn[7]);
41524d8a 525
76c74bf9 526 // tripledes
527 des3_context ctx = { DES_DECRYPT ,{ 0 } };
528 des3_set2key_dec( &ctx, key);
529
530 uint8_t enc_dump[8] = {0};
531 uint8_t empty[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
532 for(uint16_t blocknum=0; blocknum < applimit; ++blocknum) {
533
534 uint8_t idx = blocknum*8;
535 memcpy(enc_dump, decrypted + idx, 8);
536
537 // block 7 or higher, and not empty 0xFF
538 if(blocknum > 6 && memcmp(enc_dump, empty, 8) != 0 ) {
539 des3_crypt_ecb(&ctx, enc_dump, decrypted + idx );
41524d8a 540 }
76c74bf9 541 //printvar("decrypted block", decrypted + idx, 8);
41524d8a 542 }
76c74bf9 543
544 saveFile(outfilename, "bin", decrypted, fsize);
ab7bb494 545 free(decrypted);
76c74bf9 546
547 printIclassDumpContents(decrypted, 1, (fsize/8), fsize);
e98572a1 548 return 0;
549}
550
551static int iClassEncryptBlkData(uint8_t *blkData) {
552 uint8_t key[16] = { 0 };
67d78d0c 553 if(readKeyfile("iclass_decryptionkey.bin", 16, key)) {
e98572a1 554 usage_hf_iclass_encrypt();
555 return 1;
556 }
557 PrintAndLog("Decryption file found... ");
e98572a1 558 uint8_t encryptedData[16];
559 uint8_t *encrypted = encryptedData;
560 des3_context ctx = { DES_DECRYPT ,{ 0 } };
561 des3_set2key_enc( &ctx, key);
562
563 des3_crypt_ecb(&ctx, blkData,encrypted);
564 //printvar("decrypted block", decrypted, 8);
565 memcpy(blkData,encrypted,8);
566
567 return 1;
568}
53444513 569
e98572a1 570int CmdHFiClassEncryptBlk(const char *Cmd) {
571 uint8_t blkData[8] = {0};
572 char opt = param_getchar(Cmd, 0);
67d78d0c 573 if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_encrypt();
e98572a1 574
575 //get the bytes to encrypt
67d78d0c 576 if (param_gethex(Cmd, 0, blkData, 16)) {
e98572a1 577 PrintAndLog("BlockData must include 16 HEX symbols");
53444513
MHS
578 return 0;
579 }
e98572a1 580 if (!iClassEncryptBlkData(blkData)) return 0;
53444513 581
e98572a1 582 printvar("encrypted block", blkData, 8);
583 return 1;
584}
585
586void Calc_wb_mac(uint8_t blockno, uint8_t *data, uint8_t *div_key, uint8_t MAC[4]) {
587 uint8_t WB[9];
588 WB[0] = blockno;
589 memcpy(WB + 1,data,8);
590 doMAC_N(WB,sizeof(WB),div_key,MAC);
591 //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]);
592}
593
594static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose) {
595 UsbCommand resp;
596
597 UsbCommand c = {CMD_READER_ICLASS, {0}};
598 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_ONE_TRY;
599 if (use_credit_key)
600 c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY;
601
602 clearCommandBuffer();
603 SendCommand(&c);
67d78d0c 604 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
e98572a1 605 PrintAndLog("Command execute timeout");
606 return false;
53444513
MHS
607 }
608
e98572a1 609 uint8_t isOK = resp.arg[0] & 0xff;
610 uint8_t *data = resp.d.asBytes;
611
612 memcpy(CSN,data,8);
67d78d0c 613
614 if (CCNR!=NULL)
615 memcpy(CCNR,data+16,8);
616
617 if(isOK > 0) {
e98572a1 618 if (verbose) PrintAndLog("CSN: %s",sprint_hex(CSN,8));
619 }
67d78d0c 620
e98572a1 621 if(isOK <= 1){
622 PrintAndLog("Failed to obtain CC! Aborting");
623 return false;
53444513 624 }
e98572a1 625 return true;
626}
627
a7474bb3 628static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
e98572a1 629 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
630 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
631
632 if (!select_only(CSN, CCNR, use_credit_key, verbose))
633 return false;
634
635 //get div_key
a7474bb3 636 if(rawkey)
637 memcpy(div_key, KEY, 8);
638 else
67d78d0c 639 HFiClassCalcDivKey(CSN, KEY, div_key, elite);
640
a7474bb3 641 PrintAndLog("Authing with %s: %02x%02x%02x%02x%02x%02x%02x%02x", rawkey ? "raw key" : "diversified key", div_key[0],div_key[1],div_key[2],div_key[3],div_key[4],div_key[5],div_key[6],div_key[7]);
e98572a1 642
643 doMAC(CCNR, div_key, MAC);
644 UsbCommand resp;
645 UsbCommand d = {CMD_ICLASS_AUTHENTICATION, {0}};
646 memcpy(d.d.asBytes, MAC, 4);
647 clearCommandBuffer();
648 SendCommand(&d);
67d78d0c 649 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
e98572a1 650 PrintAndLog("Auth Command execute timeout");
651 return false;
652 }
67d78d0c 653 uint8_t isOK = resp.arg[0] & 0xff;
e98572a1 654 if (!isOK) {
655 PrintAndLog("Authentication error");
656 return false;
53444513 657 }
e98572a1 658 return true;
659}
53444513 660
e98572a1 661int CmdHFiClassReader_Dump(const char *Cmd) {
662
663 uint8_t MAC[4] = {0x00,0x00,0x00,0x00};
664 uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
665 uint8_t c_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
666 uint8_t blockno = 0;
667 uint8_t numblks = 0;
668 uint8_t maxBlk = 31;
669 uint8_t app_areas = 1;
670 uint8_t kb = 2;
671 uint8_t KEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
672 uint8_t CreditKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
673 uint8_t keyNbr = 0;
674 uint8_t dataLen = 0;
675 uint8_t fileNameLen = 0;
676 char filename[FILE_PATH_SIZE]={0};
677 char tempStr[50] = {0};
678 bool have_debit_key = false;
679 bool have_credit_key = false;
680 bool use_credit_key = false;
681 bool elite = false;
a7474bb3 682 bool rawkey = false;
e98572a1 683 bool errors = false;
684 uint8_t cmdp = 0;
685
686 while(param_getchar(Cmd, cmdp) != 0x00)
687 {
688 switch(param_getchar(Cmd, cmdp))
689 {
690 case 'h':
691 case 'H':
692 return usage_hf_iclass_dump();
693 case 'c':
694 case 'C':
695 have_credit_key = true;
696 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
697 if (dataLen == 16) {
698 errors = param_gethex(tempStr, 0, CreditKEY, dataLen);
699 } else if (dataLen == 1) {
700 keyNbr = param_get8(Cmd, cmdp+1);
f7c30d80 701 if (keyNbr < ICLASS_KEYS_MAX) {
e98572a1 702 memcpy(CreditKEY, iClass_Key_Table[keyNbr], 8);
703 } else {
704 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
705 errors = true;
706 }
707 } else {
708 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
709 errors = true;
710 }
711 cmdp += 2;
712 break;
713 case 'e':
714 case 'E':
715 elite = true;
716 cmdp++;
717 break;
718 case 'f':
719 case 'F':
720 fileNameLen = param_getstr(Cmd, cmdp+1, filename);
721 if (fileNameLen < 1) {
722 PrintAndLog("No filename found after f");
723 errors = true;
724 }
725 cmdp += 2;
726 break;
727 case 'k':
728 case 'K':
729 have_debit_key = true;
730 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
731 if (dataLen == 16) {
732 errors = param_gethex(tempStr, 0, KEY, dataLen);
733 } else if (dataLen == 1) {
734 keyNbr = param_get8(Cmd, cmdp+1);
f7c30d80 735 if (keyNbr < ICLASS_KEYS_MAX) {
e98572a1 736 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
737 } else {
738 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
739 errors = true;
740 }
741 } else {
742 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
743 errors = true;
744 }
745 cmdp += 2;
746 break;
a7474bb3 747 case 'r':
748 case 'R':
749 rawkey = true;
750 cmdp++;
751 break;
e98572a1 752 default:
753 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
754 errors = true;
755 break;
756 }
757 if(errors) return usage_hf_iclass_dump();
758 }
759
760 if (cmdp < 2) return usage_hf_iclass_dump();
761 // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
762 if (!have_debit_key && have_credit_key) use_credit_key = true;
763
764 //get config and first 3 blocks
765 UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN |
766 FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY}};
53444513 767 UsbCommand resp;
e98572a1 768 uint8_t tag_data[255*8];
53444513 769
e98572a1 770 clearCommandBuffer();
771 SendCommand(&c);
772 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
773 PrintAndLog("Command execute timeout");
774 ul_switch_off_field();
775 return 0;
776 }
777 uint8_t readStatus = resp.arg[0] & 0xff;
67d78d0c 778 uint8_t * data = resp.d.asBytes;
53444513 779
e98572a1 780 if(readStatus == 0){
781 PrintAndLog("No tag found...");
782 ul_switch_off_field();
67d78d0c 783 return 0;
784 }
785
8b2a5d40 786 if( readStatus & (FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_CC)){
e98572a1 787 memcpy(tag_data, data, 8*3);
8b2a5d40 788 blockno += 2; // 2 to force re-read of block 2 later. (seems to respond differently..)
e98572a1 789 numblks = data[8];
790 getMemConfig(data[13], data[12], &maxBlk, &app_areas, &kb);
791 // large memory - not able to dump pages currently
792 if (numblks > maxBlk) numblks = maxBlk;
793 }
67d78d0c 794
e98572a1 795 ul_switch_off_field();
796 // authenticate debit key and get div_key - later store in dump block 3
a7474bb3 797 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
e98572a1 798 //try twice - for some reason it sometimes fails the first time...
a7474bb3 799 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
e98572a1 800 ul_switch_off_field();
801 return 0;
802 }
53444513 803 }
e98572a1 804
805 // begin dump
806 UsbCommand w = {CMD_ICLASS_DUMP, {blockno, numblks-blockno+1}};
807 clearCommandBuffer();
808 SendCommand(&w);
809 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
810 PrintAndLog("Command execute time-out 1");
811 ul_switch_off_field();
812 return 1;
813 }
814 uint32_t blocksRead = resp.arg[1];
815 uint8_t isOK = resp.arg[0] & 0xff;
816 if (!isOK && !blocksRead) {
817 PrintAndLog("Read Block Failed");
818 ul_switch_off_field();
819 return 0;
820 }
821 uint32_t startindex = resp.arg[2];
822 if (blocksRead*8 > sizeof(tag_data)-(blockno*8)) {
823 PrintAndLog("Data exceeded Buffer size!");
824 blocksRead = (sizeof(tag_data)/8) - blockno;
825 }
826 // response ok - now get bigbuf content of the dump
827 GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex);
828 WaitForResponse(CMD_ACK,NULL);
829 size_t gotBytes = blocksRead*8 + blockno*8;
830
831 // try AA2
832 if (have_credit_key) {
833 //turn off hf field before authenticating with different key
834 ul_switch_off_field();
835 memset(MAC,0,4);
836 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
a7474bb3 837 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
e98572a1 838 //try twice - for some reason it sometimes fails the first time...
a7474bb3 839 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
e98572a1 840 ul_switch_off_field();
841 return 0;
842 }
843 }
844 // do we still need to read more block? (aa2 enabled?)
845 if (maxBlk > blockno+numblks+1) {
846 // setup dump and start
847 w.arg[0] = blockno + blocksRead;
848 w.arg[1] = maxBlk - (blockno + blocksRead);
849 clearCommandBuffer();
850 SendCommand(&w);
851 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
852 PrintAndLog("Command execute timeout 2");
853 ul_switch_off_field();
854 return 0;
855 }
856 uint8_t isOK = resp.arg[0] & 0xff;
857 blocksRead = resp.arg[1];
858 if (!isOK && !blocksRead) {
859 PrintAndLog("Read Block Failed 2");
860 ul_switch_off_field();
861 return 0;
862 }
53444513 863
e98572a1 864 startindex = resp.arg[2];
865 if (blocksRead*8 > sizeof(tag_data)-gotBytes) {
866 PrintAndLog("Data exceeded Buffer size!");
867 blocksRead = (sizeof(tag_data) - gotBytes)/8;
868 }
869 // get dumped data from bigbuf
870 GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex);
871 WaitForResponse(CMD_ACK,NULL);
53444513 872
e98572a1 873 gotBytes += blocksRead*8;
874 } else { //field is still on - turn it off...
875 ul_switch_off_field();
876 }
877 }
53444513 878
e98572a1 879 // add diversified keys to dump
880 if (have_debit_key) memcpy(tag_data+(3*8),div_key,8);
881 if (have_credit_key) memcpy(tag_data+(4*8),c_div_key,8);
8b2a5d40 882
ced74271 883 printf("Num of bytes: %zu\n", gotBytes);
8b2a5d40 884
e98572a1 885 // print the dump
c5af4b5d 886 printf("------+--+-------------------------+\n");
887 printf("CSN |00| %s|\n", sprint_hex(tag_data, 8));
8b2a5d40 888 //printIclassDumpContents(tag_data, 1, (gotBytes/8)-1, gotBytes-8);
889 printIclassDumpContents(tag_data, 1, (gotBytes/8), gotBytes);
e98572a1 890
891 if (filename[0] == 0){
892 snprintf(filename, FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
893 tag_data[0],tag_data[1],tag_data[2],tag_data[3],
894 tag_data[4],tag_data[5],tag_data[6],tag_data[7]);
895 }
53444513 896
e98572a1 897 // save the dump to .bin file
898 PrintAndLog("Saving dump file - %d blocks read", gotBytes/8);
899 saveFile(filename, "bin", tag_data, gotBytes);
900 return 1;
901}
53444513 902
a7474bb3 903static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
e98572a1 904 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
905 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
a7474bb3 906 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose))
e98572a1 907 return 0;
908
909 UsbCommand resp;
910
911 Calc_wb_mac(blockno,bldata,div_key,MAC);
912 UsbCommand w = {CMD_ICLASS_WRITEBLOCK, {blockno}};
913 memcpy(w.d.asBytes, bldata, 8);
914 memcpy(w.d.asBytes + 8, MAC, 4);
915
916 clearCommandBuffer();
917 SendCommand(&w);
67d78d0c 918 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
e98572a1 919 PrintAndLog("Write Command execute timeout");
920 return 0;
921 }
922 uint8_t isOK = resp.arg[0] & 0xff;
923 if (!isOK) {
924 PrintAndLog("Write Block Failed");
925 return 0;
926 }
927 PrintAndLog("Write Block Successful");
928 return 1;
929}
930
e98572a1 931int CmdHFiClass_WriteBlock(const char *Cmd) {
932 uint8_t blockno=0;
933 uint8_t bldata[8]={0,0,0,0,0,0,0,0};
934 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
935 uint8_t keyNbr = 0;
936 uint8_t dataLen = 0;
937 char tempStr[50] = {0};
938 bool use_credit_key = false;
939 bool elite = false;
a7474bb3 940 bool rawkey= false;
e98572a1 941 bool errors = false;
942 uint8_t cmdp = 0;
943 while(param_getchar(Cmd, cmdp) != 0x00)
944 {
945 switch(param_getchar(Cmd, cmdp))
946 {
947 case 'h':
948 case 'H':
949 return usage_hf_iclass_writeblock();
950 case 'b':
951 case 'B':
952 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
953 PrintAndLog("Block No must include 2 HEX symbols\n");
954 errors = true;
955 }
956 cmdp += 2;
957 break;
958 case 'c':
959 case 'C':
960 use_credit_key = true;
961 cmdp++;
962 break;
963 case 'd':
964 case 'D':
965 if (param_gethex(Cmd, cmdp+1, bldata, 16))
966 {
967 PrintAndLog("KEY must include 16 HEX symbols\n");
968 errors = true;
969 }
970 cmdp += 2;
971 break;
972 case 'e':
973 case 'E':
974 elite = true;
975 cmdp++;
976 break;
977 case 'k':
978 case 'K':
979 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
980 if (dataLen == 16) {
981 errors = param_gethex(tempStr, 0, KEY, dataLen);
982 } else if (dataLen == 1) {
983 keyNbr = param_get8(Cmd, cmdp+1);
f7c30d80 984 if (keyNbr < ICLASS_KEYS_MAX) {
e98572a1 985 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
986 } else {
987 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
988 errors = true;
989 }
990 } else {
991 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
992 errors = true;
993 }
994 cmdp += 2;
995 break;
a7474bb3 996 case 'r':
997 case 'R':
998 rawkey = true;
999 cmdp++;
1000 break;
e98572a1 1001 default:
1002 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1003 errors = true;
1004 break;
1005 }
1006 if(errors) return usage_hf_iclass_writeblock();
1007 }
1008
1009 if (cmdp < 6) return usage_hf_iclass_writeblock();
a7474bb3 1010 int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, true);
e98572a1 1011 ul_switch_off_field();
1012 return ans;
1013}
1014
e98572a1 1015int CmdHFiClassCloneTag(const char *Cmd) {
5cba4462 1016 char filename[FILE_PATH_SIZE] = { 0x00 };
e98572a1 1017 char tempStr[50]={0};
1018 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1019 uint8_t keyNbr = 0;
1020 uint8_t fileNameLen = 0;
1021 uint8_t startblock = 0;
1022 uint8_t endblock = 0;
1023 uint8_t dataLen = 0;
1024 bool use_credit_key = false;
1025 bool elite = false;
a7474bb3 1026 bool rawkey = false;
e98572a1 1027 bool errors = false;
1028 uint8_t cmdp = 0;
1029 while(param_getchar(Cmd, cmdp) != 0x00)
1030 {
1031 switch(param_getchar(Cmd, cmdp))
1032 {
1033 case 'h':
1034 case 'H':
1035 return usage_hf_iclass_clone();
1036 case 'b':
1037 case 'B':
1038 if (param_gethex(Cmd, cmdp+1, &startblock, 2)) {
1039 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1040 errors = true;
1041 }
1042 cmdp += 2;
1043 break;
1044 case 'c':
1045 case 'C':
1046 use_credit_key = true;
1047 cmdp++;
1048 break;
1049 case 'e':
1050 case 'E':
1051 elite = true;
1052 cmdp++;
1053 break;
1054 case 'f':
1055 case 'F':
1056 fileNameLen = param_getstr(Cmd, cmdp+1, filename);
1057 if (fileNameLen < 1) {
1058 PrintAndLog("No filename found after f");
1059 errors = true;
1060 }
1061 cmdp += 2;
1062 break;
1063 case 'k':
1064 case 'K':
1065 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1066 if (dataLen == 16) {
1067 errors = param_gethex(tempStr, 0, KEY, dataLen);
1068 } else if (dataLen == 1) {
1069 keyNbr = param_get8(Cmd, cmdp+1);
f7c30d80 1070 if (keyNbr < ICLASS_KEYS_MAX) {
e98572a1 1071 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1072 } else {
1073 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1074 errors = true;
1075 }
1076 } else {
1077 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1078 errors = true;
1079 }
1080 cmdp += 2;
1081 break;
1082 case 'l':
1083 case 'L':
1084 if (param_gethex(Cmd, cmdp+1, &endblock, 2)) {
1085 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1086 errors = true;
1087 }
1088 cmdp += 2;
1089 break;
a7474bb3 1090 case 'r':
1091 case 'R':
1092 rawkey = true;
1093 cmdp++;
1094 break;
e98572a1 1095 default:
1096 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1097 errors = true;
1098 break;
1099 }
1100 if(errors) return usage_hf_iclass_clone();
1101 }
1102
1103 if (cmdp < 8) return usage_hf_iclass_clone();
1104
1105 FILE *f;
1106
1107 iclass_block_t tag_data[USB_CMD_DATA_SIZE/12];
1108
1109 if ((endblock-startblock+1)*12 > USB_CMD_DATA_SIZE) {
1110 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE/8);
1111 }
1112 // file handling and reading
1113 f = fopen(filename,"rb");
1114 if(!f) {
1115 PrintAndLog("Failed to read from file '%s'", filename);
1116 return 1;
1117 }
1118
1119 if (startblock<5) {
1120 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
628d1cb0 1121 fclose(f);
e98572a1 1122 return 0;
1123 }
1124 // now read data from the file from block 6 --- 19
1125 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1126 // 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,
1127 // else we have to create a share memory
1128 int i;
1129 fseek(f,startblock*8,SEEK_SET);
841d7af0 1130 size_t bytes_read = fread(tag_data,sizeof(iclass_block_t),endblock - startblock + 1,f);
1131 if ( bytes_read == 0){
2b9006bd 1132 PrintAndLog("File reading error.");
1133 fclose(f);
1134 return 2;
1135 }
e98572a1 1136
1137 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1138 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1139
a7474bb3 1140 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, true))
e98572a1 1141 return 0;
1142
1143 UsbCommand w = {CMD_ICLASS_CLONE,{startblock,endblock}};
1144 uint8_t *ptr;
1145 // calculate all mac for every the block we will write
1146 for (i = startblock; i <= endblock; i++){
1147 Calc_wb_mac(i,tag_data[i - startblock].d,div_key,MAC);
1148 // usb command d start pointer = d + (i - 6) * 12
1149 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1150 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1151 // next one
1152 ptr = w.d.asBytes + (i - startblock) * 12;
1153 memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
1154 memcpy(ptr + 8,MAC, 4);
1155 }
1156 uint8_t p[12];
1157 for (i = 0; i <= endblock - startblock;i++){
1158 memcpy(p,w.d.asBytes + (i * 12),12);
1159 printf("Block |%02x|",i + startblock);
1160 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]);
1161 printf(" MAC |%02x%02x%02x%02x|\n",p[8],p[9],p[10],p[11]);
1162 }
1163 UsbCommand resp;
67d78d0c 1164 clearCommandBuffer();
e98572a1 1165 SendCommand(&w);
67d78d0c 1166 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
e98572a1 1167 PrintAndLog("Command execute timeout");
1168 return 0;
1169 }
1170 return 1;
1171}
1172
a7474bb3 1173static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose) {
e98572a1 1174 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1175 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1176
a7474bb3 1177 if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, rawkey, verbose))
e98572a1 1178 return 0;
1179
1180 UsbCommand resp;
1181 UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno}};
1182 clearCommandBuffer();
1183 SendCommand(&w);
67d78d0c 1184 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
53444513 1185 PrintAndLog("Command execute timeout");
e98572a1 1186 return 0;
53444513 1187 }
67d78d0c 1188
e98572a1 1189 uint8_t isOK = resp.arg[0] & 0xff;
1190 if (!isOK) {
1191 PrintAndLog("Read Block Failed");
1192 return 0;
1193 }
1194 //data read is stored in: resp.d.asBytes[0-15]
1195 if (verbose) PrintAndLog("Block %02X: %s\n",blockno, sprint_hex(resp.d.asBytes,8));
1196 return 1;
1197}
1198
e98572a1 1199int CmdHFiClass_ReadBlock(const char *Cmd) {
1200 uint8_t blockno=0;
1201 uint8_t keyType = 0x88; //debit key
1202 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1203 uint8_t keyNbr = 0;
1204 uint8_t dataLen = 0;
1205 char tempStr[50] = {0};
1206 bool elite = false;
a7474bb3 1207 bool rawkey = false;
e98572a1 1208 bool errors = false;
1209 uint8_t cmdp = 0;
1210 while(param_getchar(Cmd, cmdp) != 0x00)
1211 {
1212 switch(param_getchar(Cmd, cmdp))
1213 {
1214 case 'h':
1215 case 'H':
1216 return usage_hf_iclass_readblock();
1217 case 'b':
1218 case 'B':
1219 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
1220 PrintAndLog("Block No must include 2 HEX symbols\n");
1221 errors = true;
1222 }
1223 cmdp += 2;
1224 break;
1225 case 'c':
1226 case 'C':
1227 keyType = 0x18;
1228 cmdp++;
1229 break;
1230 case 'e':
1231 case 'E':
1232 elite = true;
1233 cmdp++;
1234 break;
1235 case 'k':
1236 case 'K':
1237 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1238 if (dataLen == 16) {
1239 errors = param_gethex(tempStr, 0, KEY, dataLen);
1240 } else if (dataLen == 1) {
1241 keyNbr = param_get8(Cmd, cmdp+1);
f7c30d80 1242 if (keyNbr < ICLASS_KEYS_MAX) {
e98572a1 1243 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1244 } else {
1245 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1246 errors = true;
1247 }
1248 } else {
1249 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1250 errors = true;
1251 }
1252 cmdp += 2;
1253 break;
a7474bb3 1254 case 'r':
1255 case 'R':
1256 rawkey = true;
1257 cmdp++;
1258 break;
e98572a1 1259 default:
1260 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1261 errors = true;
1262 break;
1263 }
1264 if(errors) return usage_hf_iclass_readblock();
1265 }
1266
1267 if (cmdp < 4) return usage_hf_iclass_readblock();
1268
a7474bb3 1269 return ReadBlock(KEY, blockno, keyType, elite, rawkey, true);
e98572a1 1270}
1271
1272int CmdHFiClass_loclass(const char *Cmd) {
6f101995
MHS
1273 char opt = param_getchar(Cmd, 0);
1274
1275 if (strlen(Cmd)<1 || opt == 'h') {
1276 PrintAndLog("Usage: hf iclass loclass [options]");
1277 PrintAndLog("Options:");
1278 PrintAndLog("h Show this help");
1279 PrintAndLog("t Perform self-test");
1280 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1281 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1282 PrintAndLog(" malicious CSNs, and their protocol responses");
a11ca2f3 1283 PrintAndLog(" The binary format of the file is expected to be as follows: ");
6f101995
MHS
1284 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1285 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1286 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1287 PrintAndLog(" ... totalling N*24 bytes");
1288 return 0;
1289 }
1290 char fileName[255] = {0};
67d78d0c 1291 if(opt == 'f') {
1292 if(param_getstr(Cmd, 1, fileName) > 0) {
53444513 1293 return bruteforceFileNoKeys(fileName);
67d78d0c 1294 } else {
53444513 1295 PrintAndLog("You must specify a filename");
67d78d0c 1296 // no return?
53444513 1297 }
6f101995 1298 }
67d78d0c 1299 else if(opt == 't') {
6f101995
MHS
1300 int errors = testCipherUtils();
1301 errors += testMAC();
1302 errors += doKeyTests(0);
1303 errors += testElite();
67d78d0c 1304 if(errors) prnlog("OBS! There were errors!!!");
6f101995
MHS
1305 return errors;
1306 }
6f101995
MHS
1307 return 0;
1308}
c3963755 1309
e98572a1 1310void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) {
e98572a1 1311 uint8_t mem_config;
1312 memcpy(&mem_config, iclass_dump + 13,1);
1313 uint8_t maxmemcount;
8b2a5d40 1314
e98572a1 1315 uint8_t filemaxblock = filesize / 8;
67d78d0c 1316
e98572a1 1317 if (mem_config & 0x80)
1318 maxmemcount = 255;
1319 else
1320 maxmemcount = 31;
e98572a1 1321
1322 if (startblock == 0)
1323 startblock = 6;
67d78d0c 1324
e98572a1 1325 if ((endblock > maxmemcount) || (endblock == 0))
1326 endblock = maxmemcount;
67d78d0c 1327
8b2a5d40 1328 // remember endblock needs to relate to zero-index arrays.
1329 if (endblock > filemaxblock-1)
1330 endblock = filemaxblock-1;
1331
1332 //PrintAndLog ("startblock: %d, endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d",startblock, endblock,filesize, maxmemcount, filemaxblock);
67d78d0c 1333
e98572a1 1334 int i = startblock;
c5af4b5d 1335 printf("------+--+-------------------------+\n");
e98572a1 1336 while (i <= endblock){
8b2a5d40 1337 uint8_t *blk = iclass_dump + (i * 8);
042db564 1338 printf("Block |%02X| %s\n", i, sprint_hex_ascii(blk, 8) );
e98572a1 1339 i++;
1340 }
c5af4b5d 1341 printf("------+--+-------------------------+\n");
e98572a1 1342}
1343
e98572a1 1344int CmdHFiClassReadTagFile(const char *Cmd) {
1345 int startblock = 0;
1346 int endblock = 0;
1347 char tempnum[5];
1348 FILE *f;
1349 char filename[FILE_PATH_SIZE];
1350 if (param_getstr(Cmd, 0, filename) < 1)
1351 return usage_hf_iclass_readtagfile();
67d78d0c 1352
e98572a1 1353 if (param_getstr(Cmd,1,(char *)&tempnum) < 1)
1354 startblock = 0;
1355 else
1356 sscanf(tempnum,"%d",&startblock);
1357
1358 if (param_getstr(Cmd,2,(char *)&tempnum) < 1)
1359 endblock = 0;
1360 else
1361 sscanf(tempnum,"%d",&endblock);
67d78d0c 1362
e98572a1 1363 // file handling and reading
1364 f = fopen(filename,"rb");
1365 if(!f) {
1366 PrintAndLog("Failed to read from file '%s'", filename);
1367 return 1;
1368 }
1369 fseek(f, 0, SEEK_END);
1370 long fsize = ftell(f);
1371 fseek(f, 0, SEEK_SET);
1372
ddb748a9 1373 if ( fsize < 0 ) {
1374 PrintAndLog("Error, when getting filesize");
1375 fclose(f);
1376 return 1;
1377 }
e98572a1 1378
ddb748a9 1379 uint8_t *dump = malloc(fsize);
e98572a1 1380 size_t bytes_read = fread(dump, 1, fsize, f);
1381 fclose(f);
67d78d0c 1382
e98572a1 1383 uint8_t *csn = dump;
c5af4b5d 1384 printf("------+--+-------------------------+\n");
1385 printf("CSN |00| %s|\n", sprint_hex(csn, 8) );
8b2a5d40 1386 printIclassDumpContents(dump, startblock, endblock, bytes_read);
e98572a1 1387 free(dump);
1388 return 0;
1389}
1390
e98572a1 1391void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite){
1392 uint8_t keytable[128] = {0};
1393 uint8_t key_index[8] = {0};
1394 if (elite) {
1395 uint8_t key_sel[8] = { 0 };
1396 uint8_t key_sel_p[8] = { 0 };
1397 hash2(KEY, keytable);
1398 hash1(CSN, key_index);
1399 for(uint8_t i = 0; i < 8 ; i++)
1400 key_sel[i] = keytable[key_index[i]] & 0xFF;
1401
1402 //Permute from iclass format to standard format
1403 permutekey_rev(key_sel, key_sel_p);
1404 diversifyKey(CSN, key_sel_p, div_key);
1405 } else {
1406 diversifyKey(CSN, KEY, div_key);
1407 }
1408}
1409
1410//when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1411//calculate and return xor_div_key (ready for a key write command)
1412//print all div_keys if verbose
1413static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, uint8_t *xor_div_key, bool elite, bool oldElite, bool verbose){
1414 uint8_t old_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1415 uint8_t new_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1416 //get old div key
1417 HFiClassCalcDivKey(CSN, OLDKEY, old_div_key, oldElite);
1418 //get new div key
1419 HFiClassCalcDivKey(CSN, NEWKEY, new_div_key, elite);
1420
1421 for (uint8_t i = 0; i < sizeof(old_div_key); i++){
1422 xor_div_key[i] = old_div_key[i] ^ new_div_key[i];
1423 }
1424 if (verbose) {
c5af4b5d 1425 printf("Old div key : %s\n",sprint_hex(old_div_key,8));
1426 printf("New div key : %s\n",sprint_hex(new_div_key,8));
1427 printf("Xor div key : %s\n",sprint_hex(xor_div_key,8));
e98572a1 1428 }
1429}
1430
e98572a1 1431int CmdHFiClassCalcNewKey(const char *Cmd) {
1432 uint8_t OLDKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1433 uint8_t NEWKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1434 uint8_t xor_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1435 uint8_t CSN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1436 uint8_t CCNR[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1437 uint8_t keyNbr = 0;
1438 uint8_t dataLen = 0;
1439 char tempStr[50] = {0};
1440 bool givenCSN = false;
1441 bool oldElite = false;
1442 bool elite = false;
1443 bool errors = false;
1444 uint8_t cmdp = 0;
1445 while(param_getchar(Cmd, cmdp) != 0x00)
1446 {
1447 switch(param_getchar(Cmd, cmdp))
1448 {
1449 case 'h':
1450 case 'H':
1451 return usage_hf_iclass_calc_newkey();
1452 case 'e':
1453 case 'E':
1454 dataLen = param_getstr(Cmd, cmdp, tempStr);
1455 if (dataLen==2)
1456 oldElite = true;
1457 elite = true;
1458 cmdp++;
1459 break;
1460 case 'n':
1461 case 'N':
1462 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1463 if (dataLen == 16) {
1464 errors = param_gethex(tempStr, 0, NEWKEY, dataLen);
1465 } else if (dataLen == 1) {
1466 keyNbr = param_get8(Cmd, cmdp+1);
f7c30d80 1467 if (keyNbr < ICLASS_KEYS_MAX) {
e98572a1 1468 memcpy(NEWKEY, iClass_Key_Table[keyNbr], 8);
1469 } else {
1470 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1471 errors = true;
1472 }
1473 } else {
1474 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1475 errors = true;
1476 }
1477 cmdp += 2;
1478 break;
1479 case 'o':
1480 case 'O':
1481 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1482 if (dataLen == 16) {
1483 errors = param_gethex(tempStr, 0, OLDKEY, dataLen);
1484 } else if (dataLen == 1) {
1485 keyNbr = param_get8(Cmd, cmdp+1);
f7c30d80 1486 if (keyNbr < ICLASS_KEYS_MAX) {
e98572a1 1487 memcpy(OLDKEY, iClass_Key_Table[keyNbr], 8);
1488 } else {
1489 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1490 errors = true;
1491 }
1492 } else {
1493 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1494 errors = true;
1495 }
1496 cmdp += 2;
1497 break;
1498 case 's':
1499 case 'S':
1500 givenCSN = true;
1501 if (param_gethex(Cmd, cmdp+1, CSN, 16))
1502 return usage_hf_iclass_calc_newkey();
1503 cmdp += 2;
1504 break;
1505 default:
1506 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1507 errors = true;
1508 break;
1509 }
1510 if(errors) return usage_hf_iclass_calc_newkey();
1511 }
1512
1513 if (cmdp < 4) return usage_hf_iclass_calc_newkey();
1514
1515 if (!givenCSN)
1516 if (!select_only(CSN, CCNR, false, true))
1517 return 0;
1518
1519 HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, oldElite, true);
1520 return 0;
1521}
1522
1523static int loadKeys(char *filename) {
1524 FILE *f;
1525 f = fopen(filename,"rb");
1526 if(!f) {
1527 PrintAndLog("Failed to read from file '%s'", filename);
1528 return 0;
1529 }
1530 fseek(f, 0, SEEK_END);
1531 long fsize = ftell(f);
1532 fseek(f, 0, SEEK_SET);
1533
4bb17c66 1534 if ( fsize < 0 ) {
1535 PrintAndLog("Error, when getting filesize");
1536 fclose(f);
1537 return 1;
1538 }
1539
e98572a1 1540 uint8_t *dump = malloc(fsize);
1541
1542 size_t bytes_read = fread(dump, 1, fsize, f);
1543 fclose(f);
1544 if (bytes_read > ICLASS_KEYS_MAX * 8){
1545 PrintAndLog("File is too long to load - bytes: %u", bytes_read);
1546 free(dump);
1547 return 0;
1548 }
1549 uint8_t i = 0;
c5af4b5d 1550 for (; i < bytes_read/8; i++)
e98572a1 1551 memcpy(iClass_Key_Table[i],dump+(i*8),8);
c5af4b5d 1552
e98572a1 1553 free(dump);
1554 PrintAndLog("%u keys loaded", i);
1555 return 1;
1556}
1557
1558static int saveKeys(char *filename) {
1559 FILE *f;
1560 f = fopen(filename,"wb");
db289ea7 1561 if (!f) {
e98572a1 1562 printf("error opening file %s\n",filename);
1563 return 0;
1564 }
1565 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1566 if (fwrite(iClass_Key_Table[i],8,1,f) != 1){
1567 PrintAndLog("save key failed to write to file: %s", filename);
1568 break;
1569 }
1570 }
1571 fclose(f);
1572 return 0;
1573}
1574
1575static int printKeys(void) {
1576 PrintAndLog("");
c5af4b5d 1577 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++)
67d78d0c 1578 PrintAndLog("%u: %s", i, sprint_hex(iClass_Key_Table[i],8));
e98572a1 1579 PrintAndLog("");
1580 return 0;
1581}
1582
e98572a1 1583int CmdHFiClassManageKeys(const char *Cmd) {
1584 uint8_t keyNbr = 0;
1585 uint8_t dataLen = 0;
1586 uint8_t KEY[8] = {0};
1587 char filename[FILE_PATH_SIZE];
1588 uint8_t fileNameLen = 0;
1589 bool errors = false;
1590 uint8_t operation = 0;
1591 char tempStr[20];
1592 uint8_t cmdp = 0;
1593
1594 while(param_getchar(Cmd, cmdp) != 0x00)
1595 {
1596 switch(param_getchar(Cmd, cmdp))
1597 {
1598 case 'h':
1599 case 'H':
1600 return usage_hf_iclass_managekeys();
1601 case 'f':
1602 case 'F':
1603 fileNameLen = param_getstr(Cmd, cmdp+1, filename);
1604 if (fileNameLen < 1) {
1605 PrintAndLog("No filename found after f");
1606 errors = true;
1607 }
1608 cmdp += 2;
1609 break;
1610 case 'n':
1611 case 'N':
1612 keyNbr = param_get8(Cmd, cmdp+1);
8b15860e 1613 if (keyNbr == 0) {
e98572a1 1614 PrintAndLog("Wrong block number");
1615 errors = true;
1616 }
1617 cmdp += 2;
1618 break;
1619 case 'k':
1620 case 'K':
1621 operation += 3; //set key
1622 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1623 if (dataLen == 16) { //ul-c or ev1/ntag key length
1624 errors = param_gethex(tempStr, 0, KEY, dataLen);
1625 } else {
1626 PrintAndLog("\nERROR: Key is incorrect length\n");
1627 errors = true;
1628 }
1629 cmdp += 2;
1630 break;
1631 case 'p':
1632 case 'P':
1633 operation += 4; //print keys in memory
1634 cmdp++;
1635 break;
1636 case 'l':
1637 case 'L':
1638 operation += 5; //load keys from file
1639 cmdp++;
1640 break;
1641 case 's':
1642 case 'S':
1643 operation += 6; //save keys to file
1644 cmdp++;
1645 break;
1646 default:
1647 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1648 errors = true;
1649 break;
1650 }
1651 if(errors) return usage_hf_iclass_managekeys();
1652 }
1653 if (operation == 0){
1654 PrintAndLog("no operation specified (load, save, or print)\n");
1655 return usage_hf_iclass_managekeys();
1656 }
1657 if (operation > 6){
1658 PrintAndLog("Too many operations specified\n");
1659 return usage_hf_iclass_managekeys();
1660 }
1661 if (operation > 4 && fileNameLen == 0){
1662 PrintAndLog("You must enter a filename when loading or saving\n");
1663 return usage_hf_iclass_managekeys();
1664 }
1665
1666 switch (operation){
1667 case 3: memcpy(iClass_Key_Table[keyNbr], KEY, 8); return 1;
1668 case 4: return printKeys();
1669 case 5: return loadKeys(filename);
1670 case 6: return saveKeys(filename);
1671 break;
1672 }
1673 return 0;
1674}
1675
67d78d0c 1676static command_t CommandTable[] = {
f80cd7e6 1677 {"help", CmdHelp, 1, "This help"},
e98572a1 1678 {"calcnewkey", CmdHFiClassCalcNewKey, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1679 {"clone", CmdHFiClassCloneTag, 0, "[options..] Authenticate and Clone from iClass bin file"},
1680 {"decrypt", CmdHFiClassDecrypt, 1, "[f <fname>] Decrypt tagdump" },
1681 {"dump", CmdHFiClassReader_Dump, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1682 {"eload", CmdHFiClassELoad, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1683 {"encryptblk", CmdHFiClassEncryptBlk, 1, "<BlockData> Encrypt given block data"},
1684 {"list", CmdHFiClassList, 0, " (Deprecated) List iClass history"},
1685 {"loclass", CmdHFiClass_loclass, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1686 {"managekeys", CmdHFiClassManageKeys, 1, "[options..] Manage the keys to use with iClass"},
1687 {"readblk", CmdHFiClass_ReadBlock, 0, "[options..] Authenticate and Read iClass block"},
f80cd7e6 1688 {"reader", CmdHFiClassReader, 0, "Read an iClass tag"},
e98572a1 1689 {"readtagfile", CmdHFiClassReadTagFile, 1, "[options..] Display Content from tagfile"},
1690 {"replay", CmdHFiClassReader_Replay, 0, "<mac> Read an iClass tag via Reply Attack"},
1691 {"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"},
1692 {"snoop", CmdHFiClassSnoop, 0, " Eavesdrop iClass communication"},
1693 {"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"},
6f101995 1694 {NULL, NULL, 0, NULL}
cee5a30d 1695};
1696
67d78d0c 1697int CmdHFiClass(const char *Cmd) {
1698 clearCommandBuffer();
53444513
MHS
1699 CmdsParse(CommandTable, Cmd);
1700 return 0;
cee5a30d 1701}
1702
67d78d0c 1703int CmdHelp(const char *Cmd) {
53444513
MHS
1704 CmdsHelp(CommandTable);
1705 return 0;
cee5a30d 1706}
Impressum, Datenschutz