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