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