]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhficlass.c
chg: travis ci again
[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
d3fd5fd6 883 printf("Num of bytes: %d\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
1391/*
1392uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
1393 uint64_t new_div = 0x00;
1394 new_div ^= sdiv;
1395 new_div ^= hdiv;
1396 return new_div;
1397}
1398
1399uint64_t hexarray_to_uint64(uint8_t *key) {
1400 char temp[17];
1401 uint64_t uint_key;
1402 for (int i = 0;i < 8;i++)
1403 sprintf(&temp[(i *2)],"%02X",key[i]);
1404 temp[16] = '\0';
1405 if (sscanf(temp,"%016"llX,&uint_key) < 1)
1406 return 0;
1407 return uint_key;
1408}
1409*/
1410void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite){
1411 uint8_t keytable[128] = {0};
1412 uint8_t key_index[8] = {0};
1413 if (elite) {
1414 uint8_t key_sel[8] = { 0 };
1415 uint8_t key_sel_p[8] = { 0 };
1416 hash2(KEY, keytable);
1417 hash1(CSN, key_index);
1418 for(uint8_t i = 0; i < 8 ; i++)
1419 key_sel[i] = keytable[key_index[i]] & 0xFF;
1420
1421 //Permute from iclass format to standard format
1422 permutekey_rev(key_sel, key_sel_p);
1423 diversifyKey(CSN, key_sel_p, div_key);
1424 } else {
1425 diversifyKey(CSN, KEY, div_key);
1426 }
1427}
1428
1429//when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1430//calculate and return xor_div_key (ready for a key write command)
1431//print all div_keys if verbose
1432static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, uint8_t *xor_div_key, bool elite, bool oldElite, bool verbose){
1433 uint8_t old_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1434 uint8_t new_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1435 //get old div key
1436 HFiClassCalcDivKey(CSN, OLDKEY, old_div_key, oldElite);
1437 //get new div key
1438 HFiClassCalcDivKey(CSN, NEWKEY, new_div_key, elite);
1439
1440 for (uint8_t i = 0; i < sizeof(old_div_key); i++){
1441 xor_div_key[i] = old_div_key[i] ^ new_div_key[i];
1442 }
1443 if (verbose) {
c5af4b5d 1444 printf("Old div key : %s\n",sprint_hex(old_div_key,8));
1445 printf("New div key : %s\n",sprint_hex(new_div_key,8));
1446 printf("Xor div key : %s\n",sprint_hex(xor_div_key,8));
e98572a1 1447 }
1448}
1449
e98572a1 1450int CmdHFiClassCalcNewKey(const char *Cmd) {
1451 uint8_t OLDKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1452 uint8_t NEWKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1453 uint8_t xor_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1454 uint8_t CSN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1455 uint8_t CCNR[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1456 uint8_t keyNbr = 0;
1457 uint8_t dataLen = 0;
1458 char tempStr[50] = {0};
1459 bool givenCSN = false;
1460 bool oldElite = false;
1461 bool elite = false;
1462 bool errors = false;
1463 uint8_t cmdp = 0;
1464 while(param_getchar(Cmd, cmdp) != 0x00)
1465 {
1466 switch(param_getchar(Cmd, cmdp))
1467 {
1468 case 'h':
1469 case 'H':
1470 return usage_hf_iclass_calc_newkey();
1471 case 'e':
1472 case 'E':
1473 dataLen = param_getstr(Cmd, cmdp, tempStr);
1474 if (dataLen==2)
1475 oldElite = true;
1476 elite = true;
1477 cmdp++;
1478 break;
1479 case 'n':
1480 case 'N':
1481 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1482 if (dataLen == 16) {
1483 errors = param_gethex(tempStr, 0, NEWKEY, dataLen);
1484 } else if (dataLen == 1) {
1485 keyNbr = param_get8(Cmd, cmdp+1);
f7c30d80 1486 if (keyNbr < ICLASS_KEYS_MAX) {
e98572a1 1487 memcpy(NEWKEY, iClass_Key_Table[keyNbr], 8);
1488 } else {
1489 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1490 errors = true;
1491 }
1492 } else {
1493 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1494 errors = true;
1495 }
1496 cmdp += 2;
1497 break;
1498 case 'o':
1499 case 'O':
1500 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1501 if (dataLen == 16) {
1502 errors = param_gethex(tempStr, 0, OLDKEY, dataLen);
1503 } else if (dataLen == 1) {
1504 keyNbr = param_get8(Cmd, cmdp+1);
f7c30d80 1505 if (keyNbr < ICLASS_KEYS_MAX) {
e98572a1 1506 memcpy(OLDKEY, iClass_Key_Table[keyNbr], 8);
1507 } else {
1508 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1509 errors = true;
1510 }
1511 } else {
1512 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1513 errors = true;
1514 }
1515 cmdp += 2;
1516 break;
1517 case 's':
1518 case 'S':
1519 givenCSN = true;
1520 if (param_gethex(Cmd, cmdp+1, CSN, 16))
1521 return usage_hf_iclass_calc_newkey();
1522 cmdp += 2;
1523 break;
1524 default:
1525 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1526 errors = true;
1527 break;
1528 }
1529 if(errors) return usage_hf_iclass_calc_newkey();
1530 }
1531
1532 if (cmdp < 4) return usage_hf_iclass_calc_newkey();
1533
1534 if (!givenCSN)
1535 if (!select_only(CSN, CCNR, false, true))
1536 return 0;
1537
1538 HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, oldElite, true);
1539 return 0;
1540}
1541
1542static int loadKeys(char *filename) {
1543 FILE *f;
1544 f = fopen(filename,"rb");
1545 if(!f) {
1546 PrintAndLog("Failed to read from file '%s'", filename);
1547 return 0;
1548 }
1549 fseek(f, 0, SEEK_END);
1550 long fsize = ftell(f);
1551 fseek(f, 0, SEEK_SET);
1552
4bb17c66 1553 if ( fsize < 0 ) {
1554 PrintAndLog("Error, when getting filesize");
1555 fclose(f);
1556 return 1;
1557 }
1558
e98572a1 1559 uint8_t *dump = malloc(fsize);
1560
1561 size_t bytes_read = fread(dump, 1, fsize, f);
1562 fclose(f);
1563 if (bytes_read > ICLASS_KEYS_MAX * 8){
1564 PrintAndLog("File is too long to load - bytes: %u", bytes_read);
1565 free(dump);
1566 return 0;
1567 }
1568 uint8_t i = 0;
c5af4b5d 1569 for (; i < bytes_read/8; i++)
e98572a1 1570 memcpy(iClass_Key_Table[i],dump+(i*8),8);
c5af4b5d 1571
e98572a1 1572 free(dump);
1573 PrintAndLog("%u keys loaded", i);
1574 return 1;
1575}
1576
1577static int saveKeys(char *filename) {
1578 FILE *f;
1579 f = fopen(filename,"wb");
db289ea7 1580 if (!f) {
e98572a1 1581 printf("error opening file %s\n",filename);
1582 return 0;
1583 }
1584 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1585 if (fwrite(iClass_Key_Table[i],8,1,f) != 1){
1586 PrintAndLog("save key failed to write to file: %s", filename);
1587 break;
1588 }
1589 }
1590 fclose(f);
1591 return 0;
1592}
1593
1594static int printKeys(void) {
1595 PrintAndLog("");
c5af4b5d 1596 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++)
67d78d0c 1597 PrintAndLog("%u: %s", i, sprint_hex(iClass_Key_Table[i],8));
e98572a1 1598 PrintAndLog("");
1599 return 0;
1600}
1601
e98572a1 1602int CmdHFiClassManageKeys(const char *Cmd) {
1603 uint8_t keyNbr = 0;
1604 uint8_t dataLen = 0;
1605 uint8_t KEY[8] = {0};
1606 char filename[FILE_PATH_SIZE];
1607 uint8_t fileNameLen = 0;
1608 bool errors = false;
1609 uint8_t operation = 0;
1610 char tempStr[20];
1611 uint8_t cmdp = 0;
1612
1613 while(param_getchar(Cmd, cmdp) != 0x00)
1614 {
1615 switch(param_getchar(Cmd, cmdp))
1616 {
1617 case 'h':
1618 case 'H':
1619 return usage_hf_iclass_managekeys();
1620 case 'f':
1621 case 'F':
1622 fileNameLen = param_getstr(Cmd, cmdp+1, filename);
1623 if (fileNameLen < 1) {
1624 PrintAndLog("No filename found after f");
1625 errors = true;
1626 }
1627 cmdp += 2;
1628 break;
1629 case 'n':
1630 case 'N':
1631 keyNbr = param_get8(Cmd, cmdp+1);
8b15860e 1632 if (keyNbr == 0) {
e98572a1 1633 PrintAndLog("Wrong block number");
1634 errors = true;
1635 }
1636 cmdp += 2;
1637 break;
1638 case 'k':
1639 case 'K':
1640 operation += 3; //set key
1641 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1642 if (dataLen == 16) { //ul-c or ev1/ntag key length
1643 errors = param_gethex(tempStr, 0, KEY, dataLen);
1644 } else {
1645 PrintAndLog("\nERROR: Key is incorrect length\n");
1646 errors = true;
1647 }
1648 cmdp += 2;
1649 break;
1650 case 'p':
1651 case 'P':
1652 operation += 4; //print keys in memory
1653 cmdp++;
1654 break;
1655 case 'l':
1656 case 'L':
1657 operation += 5; //load keys from file
1658 cmdp++;
1659 break;
1660 case 's':
1661 case 'S':
1662 operation += 6; //save keys to file
1663 cmdp++;
1664 break;
1665 default:
1666 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1667 errors = true;
1668 break;
1669 }
1670 if(errors) return usage_hf_iclass_managekeys();
1671 }
1672 if (operation == 0){
1673 PrintAndLog("no operation specified (load, save, or print)\n");
1674 return usage_hf_iclass_managekeys();
1675 }
1676 if (operation > 6){
1677 PrintAndLog("Too many operations specified\n");
1678 return usage_hf_iclass_managekeys();
1679 }
1680 if (operation > 4 && fileNameLen == 0){
1681 PrintAndLog("You must enter a filename when loading or saving\n");
1682 return usage_hf_iclass_managekeys();
1683 }
1684
1685 switch (operation){
1686 case 3: memcpy(iClass_Key_Table[keyNbr], KEY, 8); return 1;
1687 case 4: return printKeys();
1688 case 5: return loadKeys(filename);
1689 case 6: return saveKeys(filename);
1690 break;
1691 }
1692 return 0;
1693}
1694
67d78d0c 1695static command_t CommandTable[] = {
f80cd7e6 1696 {"help", CmdHelp, 1, "This help"},
e98572a1 1697 {"calcnewkey", CmdHFiClassCalcNewKey, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1698 {"clone", CmdHFiClassCloneTag, 0, "[options..] Authenticate and Clone from iClass bin file"},
1699 {"decrypt", CmdHFiClassDecrypt, 1, "[f <fname>] Decrypt tagdump" },
1700 {"dump", CmdHFiClassReader_Dump, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1701 {"eload", CmdHFiClassELoad, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1702 {"encryptblk", CmdHFiClassEncryptBlk, 1, "<BlockData> Encrypt given block data"},
1703 {"list", CmdHFiClassList, 0, " (Deprecated) List iClass history"},
1704 {"loclass", CmdHFiClass_loclass, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1705 {"managekeys", CmdHFiClassManageKeys, 1, "[options..] Manage the keys to use with iClass"},
1706 {"readblk", CmdHFiClass_ReadBlock, 0, "[options..] Authenticate and Read iClass block"},
f80cd7e6 1707 {"reader", CmdHFiClassReader, 0, "Read an iClass tag"},
e98572a1 1708 {"readtagfile", CmdHFiClassReadTagFile, 1, "[options..] Display Content from tagfile"},
1709 {"replay", CmdHFiClassReader_Replay, 0, "<mac> Read an iClass tag via Reply Attack"},
1710 {"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"},
1711 {"snoop", CmdHFiClassSnoop, 0, " Eavesdrop iClass communication"},
1712 {"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"},
6f101995 1713 {NULL, NULL, 0, NULL}
cee5a30d 1714};
1715
67d78d0c 1716int CmdHFiClass(const char *Cmd) {
1717 clearCommandBuffer();
53444513
MHS
1718 CmdsParse(CommandTable, Cmd);
1719 return 0;
cee5a30d 1720}
1721
67d78d0c 1722int CmdHelp(const char *Cmd) {
53444513
MHS
1723 CmdsHelp(CommandTable);
1724 return 0;
cee5a30d 1725}
Impressum, Datenschutz