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