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