]> cvs.zerfleddert.de Git - proxmark3-svn/blob - client/cmdhficlass.c
CHG: 'hf iclass decrypt' - adjusted the loops, to only decrypt Application 1. ...
[proxmark3-svn] / client / cmdhficlass.c
1 //-----------------------------------------------------------------------------
2 // Copyright (C) 2010 iZsh <izsh at fail0verflow.com>, Hagen Fritsch
3 // Copyright (C) 2011 Gerhard de Koning Gans
4 // Copyright (C) 2014 Midnitesnake & Andy Davies & Martin Holst Swende
5 //
6 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
7 // at your option, any later version. See the LICENSE.txt file for the text of
8 // the license.
9 //-----------------------------------------------------------------------------
10 // High frequency iClass commands
11 //-----------------------------------------------------------------------------
12
13 #include "cmdhficlass.h"
14
15 static int CmdHelp(const char *Cmd);
16
17 #define NUM_CSNS 15
18 #define ICLASS_KEYS_MAX 8
19 static 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
30 typedef struct iclass_block {
31 uint8_t d[8];
32 } iclass_block_t;
33
34 int 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 }
47 int 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 }
54 int 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 }
67 int 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 }
77 int 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 }
94 int 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 }
110 int 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 }
124 int 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 }
138 int usage_hf_iclass_readtagfile() {
139 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
140 return 1;
141 }
142 int 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 }
158 int 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
176 int xorbits_8(uint8_t val) {
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;
182 }
183
184 int CmdHFiClassList(const char *Cmd) {
185 //PrintAndLog("Deprecated command, use 'hf list iclass' instead");
186 CmdHFList("iclass");
187 return 0;
188 }
189
190 int CmdHFiClassSnoop(const char *Cmd) {
191 UsbCommand c = {CMD_SNOOP_ICLASS};
192 SendCommand(&c);
193 return 0;
194 }
195
196 int CmdHFiClassSim(const char *Cmd) {
197 uint8_t simType = 0;
198 uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
199
200 if (strlen(Cmd)<1) return usage_hf_iclass_sim();
201
202 simType = param_get8ex(Cmd, 0, 0, 10);
203
204 if(simType == 0)
205 {
206 if (param_gethex(Cmd, 1, CSN, 16)) {
207 PrintAndLog("A CSN should consist of 16 HEX symbols");
208 return usage_hf_iclass_sim();
209 }
210
211 PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
212 }
213
214 if(simType > 3)
215 {
216 PrintAndLog("Undefined simptype %d", simType);
217 return usage_hf_iclass_sim();
218 }
219
220 uint8_t numberOfCSNs=0;
221 if(simType == 2)
222 {
223 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
224 UsbCommand resp = {0};
225
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 };
242
243 memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
244 clearCommandBuffer();
245 SendCommand(&c);
246 if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
247 PrintAndLog("Command timed out");
248 return 0;
249 }
250
251 uint8_t num_mac_responses = resp.arg[1];
252 PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
253
254 size_t datalen = NUM_CSNS*24;
255 /*
256 * Now, time to dump to file. We'll use this format:
257 * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
258 * So, it should wind up as
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
264 **/
265 void* dump = malloc(datalen);
266 memset(dump,0,datalen);//<-- Need zeroes for the CC-field
267 uint8_t i = 0;
268 for(i = 0 ; i < NUM_CSNS ; i++) {
269 memcpy(dump+i*24, csns+i*8, 8); //CSN
270 //8 zero bytes here...
271 //Then comes NR_MAC (eight bytes from the response)
272 memcpy(dump+i*24+16, resp.d.asBytes+i*8, 8);
273 }
274 /** Now, save to dumpfile **/
275 saveFile("iclass_mac_attack", "bin", dump, datalen);
276 free(dump);
277 } else {
278 UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
279 memcpy(c.d.asBytes, CSN, 8);
280 clearCommandBuffer();
281 SendCommand(&c);
282 }
283 return 0;
284 }
285
286 int HFiClassReader(const char *Cmd, bool loop, bool verbose) {
287 bool tagFound = false;
288 UsbCommand c = {CMD_READER_ICLASS, {FLAG_ICLASS_READER_CSN |
289 FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_AA}};
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;
292 UsbCommand resp;
293 while(!ukbhit()){
294 clearCommandBuffer();
295 SendCommand(&c);
296 if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) {
297 uint8_t readStatus = resp.arg[0] & 0xff;
298 uint8_t *data = resp.d.asBytes;
299
300 if (verbose) PrintAndLog("Readstatus:%02x", readStatus);
301 if( readStatus == 0){
302 //Aborted
303 if (verbose) PrintAndLog("Quitting...");
304 return 0;
305 }
306 if( readStatus & FLAG_ICLASS_READER_CSN){
307 PrintAndLog("CSN: %s",sprint_hex(data,8));
308 tagFound = true;
309 }
310 if( readStatus & FLAG_ICLASS_READER_CC) PrintAndLog("CC: %s", sprint_hex(data+16, 8));
311 if( readStatus & FLAG_ICLASS_READER_CONF) printIclassDumpInfo(data);
312 if (tagFound && !loop) return 1;
313 } else {
314 if (verbose) PrintAndLog("Command execute timeout");
315 }
316 if (!loop) break;
317 }
318 return 0;
319 }
320
321 int CmdHFiClassReader(const char *Cmd) {
322 return HFiClassReader(Cmd, true, true);
323 }
324
325 int CmdHFiClassReader_Replay(const char *Cmd) {
326 uint8_t readerType = 0;
327 uint8_t MAC[4]={0x00, 0x00, 0x00, 0x00};
328
329 if (strlen(Cmd)<1) {
330 PrintAndLog("Usage: hf iclass replay <MAC>");
331 PrintAndLog(" sample: hf iclass replay 00112233");
332 return 0;
333 }
334
335 if (param_gethex(Cmd, 0, MAC, 8)) {
336 PrintAndLog("MAC must include 8 HEX symbols");
337 return 1;
338 }
339
340 UsbCommand c = {CMD_READER_ICLASS_REPLAY, {readerType}};
341 memcpy(c.d.asBytes, MAC, 4);
342 clearCommandBuffer();
343 SendCommand(&c);
344 return 0;
345 }
346
347 int 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);
350 clearCommandBuffer();
351 SendCommand(&c);
352 return 0;
353 }
354
355 int CmdHFiClassELoad(const char *Cmd) {
356
357 char opt = param_getchar(Cmd, 0);
358 if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_eload();
359
360 //File handling and reading
361 FILE *f;
362 char filename[FILE_PATH_SIZE];
363 if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0) {
364 f = fopen(filename, "rb");
365 } else {
366 return usage_hf_iclass_eload();
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
378 if (fsize < 0) {
379 prnlog("Error, when getting filesize");
380 fclose(f);
381 return 1;
382 }
383
384 uint8_t *dump = malloc(fsize);
385
386 size_t bytes_read = fread(dump, 1, fsize, f);
387 fclose(f);
388
389 printIclassDumpInfo(dump);
390 //Validate
391
392 if (bytes_read < fsize) {
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);
405 clearCommandBuffer();
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
415 static int readKeyfile(const char *filename, size_t len, uint8_t* buffer) {
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);
426
427 if(fsize != len) {
428 PrintAndLog("Warning, file size is %d, expected %d", fsize, len);
429 return 1;
430 }
431
432 if(bytes_read != len) {
433 PrintAndLog("Warning, could only read %d bytes, expected %d" ,bytes_read, len);
434 return 1;
435 }
436 return 0;
437 }
438
439 int CmdHFiClassDecrypt(const char *Cmd) {
440 uint8_t key[16] = { 0 };
441 if(readKeyfile("iclass_decryptionkey.bin", 16, key)) return usage_hf_iclass_decrypt();
442
443 PrintAndLog("Decryption file found... ");
444 char opt = param_getchar(Cmd, 0);
445 if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_decrypt();
446
447 //Open the tagdump-file
448 FILE *f;
449 char filename[FILE_PATH_SIZE];
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;
454 }
455 } else {
456 return usage_hf_iclass_decrypt();
457 }
458
459 fseek(f, 0, SEEK_END);
460 long fsize = ftell(f);
461 fseek(f, 0, SEEK_SET);
462
463 if ( fsize < 0 ) {
464 PrintAndLog("Error, when getting filesize");
465 fclose(f);
466 return 2;
467 }
468
469 uint8_t *decrypted = malloc(fsize);
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 }
478
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
489 //Use the first block (CSN) for filename
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]);
494
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 );
509 }
510 //printvar("decrypted block", decrypted + idx, 8);
511 }
512
513 saveFile(outfilename, "bin", decrypted, fsize);
514 free(decrypted);
515
516 printIclassDumpContents(decrypted, 1, (fsize/8), fsize);
517 return 0;
518 }
519
520 static int iClassEncryptBlkData(uint8_t *blkData) {
521 uint8_t key[16] = { 0 };
522 if(readKeyfile("iclass_decryptionkey.bin", 16, key)) {
523 usage_hf_iclass_encrypt();
524 return 1;
525 }
526 PrintAndLog("Decryption file found... ");
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 }
538
539 int CmdHFiClassEncryptBlk(const char *Cmd) {
540 uint8_t blkData[8] = {0};
541 char opt = param_getchar(Cmd, 0);
542 if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_encrypt();
543
544 //get the bytes to encrypt
545 if (param_gethex(Cmd, 0, blkData, 16)) {
546 PrintAndLog("BlockData must include 16 HEX symbols");
547 return 0;
548 }
549 if (!iClassEncryptBlkData(blkData)) return 0;
550
551 printvar("encrypted block", blkData, 8);
552 return 1;
553 }
554
555 void 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
563 static 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);
573 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
574 PrintAndLog("Command execute timeout");
575 return false;
576 }
577
578 uint8_t isOK = resp.arg[0] & 0xff;
579 uint8_t *data = resp.d.asBytes;
580
581 memcpy(CSN,data,8);
582
583 if (CCNR!=NULL)
584 memcpy(CCNR,data+16,8);
585
586 if(isOK > 0) {
587 if (verbose) PrintAndLog("CSN: %s",sprint_hex(CSN,8));
588 }
589
590 if(isOK <= 1){
591 PrintAndLog("Failed to obtain CC! Aborting");
592 return false;
593 }
594 return true;
595 }
596
597 static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
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
605 if(rawkey)
606 memcpy(div_key, KEY, 8);
607 else
608 HFiClassCalcDivKey(CSN, KEY, div_key, elite);
609
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]);
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);
618 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
619 PrintAndLog("Auth Command execute timeout");
620 return false;
621 }
622 uint8_t isOK = resp.arg[0] & 0xff;
623 if (!isOK) {
624 PrintAndLog("Authentication error");
625 return false;
626 }
627 return true;
628 }
629
630 int 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;
651 bool rawkey = false;
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);
670 if (keyNbr < ICLASS_KEYS_MAX) {
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);
704 if (keyNbr < ICLASS_KEYS_MAX) {
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;
716 case 'r':
717 case 'R':
718 rawkey = true;
719 cmdp++;
720 break;
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}};
736 UsbCommand resp;
737 uint8_t tag_data[255*8];
738
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;
747 uint8_t * data = resp.d.asBytes;
748
749 if(readStatus == 0){
750 PrintAndLog("No tag found...");
751 ul_switch_off_field();
752 return 0;
753 }
754
755 if( readStatus & (FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_CC)){
756 memcpy(tag_data, data, 8*3);
757 blockno += 2; // 2 to force re-read of block 2 later. (seems to respond differently..)
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 }
763
764 ul_switch_off_field();
765 // authenticate debit key and get div_key - later store in dump block 3
766 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
767 //try twice - for some reason it sometimes fails the first time...
768 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
769 ul_switch_off_field();
770 return 0;
771 }
772 }
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
806 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
807 //try twice - for some reason it sometimes fails the first time...
808 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
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 }
832
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);
841
842 gotBytes += blocksRead*8;
843 } else { //field is still on - turn it off...
844 ul_switch_off_field();
845 }
846 }
847
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);
851
852 printf("Num of bytes: %u\n", gotBytes);
853
854 // print the dump
855 printf("------+--+-------------------------+\n");
856 printf("CSN |00| %s|\n", sprint_hex(tag_data, 8));
857 //printIclassDumpContents(tag_data, 1, (gotBytes/8)-1, gotBytes-8);
858 printIclassDumpContents(tag_data, 1, (gotBytes/8), gotBytes);
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 }
865
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 }
871
872 static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
873 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
874 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
875 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose))
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);
887 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
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
900 int 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;
909 bool rawkey= false;
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);
953 if (keyNbr < ICLASS_KEYS_MAX) {
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;
965 case 'r':
966 case 'R':
967 rawkey = true;
968 cmdp++;
969 break;
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();
979 int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, true);
980 ul_switch_off_field();
981 return ans;
982 }
983
984 int CmdHFiClassCloneTag(const char *Cmd) {
985 char filename[FILE_PATH_SIZE] = { 0x00 };
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;
995 bool rawkey = false;
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);
1039 if (keyNbr < ICLASS_KEYS_MAX) {
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;
1059 case 'r':
1060 case 'R':
1061 rawkey = true;
1062 cmdp++;
1063 break;
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");
1090 fclose(f);
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);
1099 size_t bytes_read = fread(tag_data,sizeof(iclass_block_t),endblock - startblock + 1,f);
1100 if ( bytes_read == 0){
1101 PrintAndLog("File reading error.");
1102 fclose(f);
1103 return 2;
1104 }
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
1109 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, true))
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;
1133 clearCommandBuffer();
1134 SendCommand(&w);
1135 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
1136 PrintAndLog("Command execute timeout");
1137 return 0;
1138 }
1139 return 1;
1140 }
1141
1142 static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose) {
1143 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1144 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1145
1146 if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, rawkey, verbose))
1147 return 0;
1148
1149 UsbCommand resp;
1150 UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno}};
1151 clearCommandBuffer();
1152 SendCommand(&w);
1153 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500)) {
1154 PrintAndLog("Command execute timeout");
1155 return 0;
1156 }
1157
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
1168 int 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;
1176 bool rawkey = false;
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);
1211 if (keyNbr < ICLASS_KEYS_MAX) {
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;
1223 case 'r':
1224 case 'R':
1225 rawkey = true;
1226 cmdp++;
1227 break;
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
1238 return ReadBlock(KEY, blockno, keyType, elite, rawkey, true);
1239 }
1240
1241 int CmdHFiClass_loclass(const char *Cmd) {
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");
1252 PrintAndLog(" The binary format of the file is expected to be as follows: ");
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};
1260 if(opt == 'f') {
1261 if(param_getstr(Cmd, 1, fileName) > 0) {
1262 return bruteforceFileNoKeys(fileName);
1263 } else {
1264 PrintAndLog("You must specify a filename");
1265 // no return?
1266 }
1267 }
1268 else if(opt == 't') {
1269 int errors = testCipherUtils();
1270 errors += testMAC();
1271 errors += doKeyTests(0);
1272 errors += testElite();
1273 if(errors) prnlog("OBS! There were errors!!!");
1274 return errors;
1275 }
1276 return 0;
1277 }
1278
1279 void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) {
1280 uint8_t mem_config;
1281 memcpy(&mem_config, iclass_dump + 13,1);
1282 uint8_t maxmemcount;
1283
1284 uint8_t filemaxblock = filesize / 8;
1285
1286 if (mem_config & 0x80)
1287 maxmemcount = 255;
1288 else
1289 maxmemcount = 31;
1290
1291 if (startblock == 0)
1292 startblock = 6;
1293
1294 if ((endblock > maxmemcount) || (endblock == 0))
1295 endblock = maxmemcount;
1296
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);
1302
1303 int i = startblock;
1304 printf("------+--+-------------------------+\n");
1305 while (i <= endblock){
1306 uint8_t *blk = iclass_dump + (i * 8);
1307 printf("Block |%02X| %s|\n", i, sprint_hex(blk, 8) );
1308 i++;
1309 }
1310 printf("------+--+-------------------------+\n");
1311 }
1312
1313 int 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();
1321
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);
1331
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
1342 if ( fsize < 0 ) {
1343 PrintAndLog("Error, when getting filesize");
1344 fclose(f);
1345 return 1;
1346 }
1347
1348 uint8_t *dump = malloc(fsize);
1349 size_t bytes_read = fread(dump, 1, fsize, f);
1350 fclose(f);
1351
1352 uint8_t *csn = dump;
1353 printf("------+--+-------------------------+\n");
1354 printf("CSN |00| %s|\n", sprint_hex(csn, 8) );
1355 printIclassDumpContents(dump, startblock, endblock, bytes_read);
1356 free(dump);
1357 return 0;
1358 }
1359
1360 /*
1361 uint64_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
1368 uint64_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 */
1379 void 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
1401 static 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) {
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));
1416 }
1417 }
1418
1419 int 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);
1455 if (keyNbr < ICLASS_KEYS_MAX) {
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);
1474 if (keyNbr < ICLASS_KEYS_MAX) {
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
1511 static 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
1522 if ( fsize < 0 ) {
1523 PrintAndLog("Error, when getting filesize");
1524 fclose(f);
1525 return 1;
1526 }
1527
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;
1538 for (; i < bytes_read/8; i++)
1539 memcpy(iClass_Key_Table[i],dump+(i*8),8);
1540
1541 free(dump);
1542 PrintAndLog("%u keys loaded", i);
1543 return 1;
1544 }
1545
1546 static 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
1563 static int printKeys(void) {
1564 PrintAndLog("");
1565 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++)
1566 PrintAndLog("%u: %s", i, sprint_hex(iClass_Key_Table[i],8));
1567 PrintAndLog("");
1568 return 0;
1569 }
1570
1571 int 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);
1601 if (keyNbr == 0) {
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
1664 static command_t CommandTable[] = {
1665 {"help", CmdHelp, 1, "This help"},
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"},
1676 {"reader", CmdHFiClassReader, 0, "Read an iClass tag"},
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"},
1682 {NULL, NULL, 0, NULL}
1683 };
1684
1685 int CmdHFiClass(const char *Cmd) {
1686 clearCommandBuffer();
1687 CmdsParse(CommandTable, Cmd);
1688 return 0;
1689 }
1690
1691 int CmdHelp(const char *Cmd) {
1692 CmdsHelp(CommandTable);
1693 return 0;
1694 }
Impressum, Datenschutz