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