]> 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");
288 return 1;
289 }
1defcf60 290
7a616c0d 291 uint8_t *dump = malloc(fsize);
1defcf60 292
7781a656
MHS
293 size_t bytes_read = fread(dump, 1, fsize, f);
294 fclose(f);
295
1defcf60 296 printIclassDumpInfo(dump);
7781a656
MHS
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
4d68ec02 322static int readKeyfile(const char *filename, size_t len, uint8_t* buffer) {
41524d8a
MHS
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
4d68ec02 346int usage_hf_iclass_decrypt(void) {
347 PrintAndLog("Usage: hf iclass decrypt f <tagdump>");
aa53efc3 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
4d68ec02 360int CmdHFiClassDecrypt(const char *Cmd) {
41524d8a
MHS
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 {
9a9bcea8 400 if(blocknum < 7)
41524d8a
MHS
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);
c4c3af7c 413 free(decrypted);
41524d8a
MHS
414 return 0;
415}
7781a656 416
4d68ec02 417int usage_hf_iclass_encrypt(void) {
aa53efc3 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
4d68ec02 428static int iClassEncryptBlkData(uint8_t *blkData) {
aa53efc3 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... ");
53444513 436
4d68ec02 437 uint8_t encryptedData[16];
438 uint8_t *encrypted = encryptedData;
aa53efc3 439 des3_context ctx = { DES_DECRYPT ,{ 0 } };
440 des3_set2key_enc( &ctx, key);
441
4d68ec02 442 des3_crypt_ecb(&ctx, blkData,encrypted);
aa53efc3 443 //printvar("decrypted block", decrypted, 8);
4d68ec02 444 memcpy(blkData,encrypted,8);
aa53efc3 445
446 return 1;
447}
448
4d68ec02 449int CmdHFiClassEncryptBlk(const char *Cmd) {
aa53efc3 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();
53444513 454
aa53efc3 455 //get the bytes to encrypt
456 if (param_gethex(Cmd, 0, blkData, 16))
53444513 457 {
aa53efc3 458 PrintAndLog("BlockData must include 16 HEX symbols");
53444513
MHS
459 return 0;
460 }
aa53efc3 461 if (!iClassEncryptBlkData(blkData)) return 0;
53444513 462
aa53efc3 463 printvar("encrypted block", blkData, 8);
464 return 1;
465}
53444513 466
4d68ec02 467void Calc_wb_mac(uint8_t blockno, uint8_t *data, uint8_t *div_key, uint8_t MAC[4]) {
aa53efc3 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}
53444513 474
4d68ec02 475static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose) {
53444513
MHS
476 UsbCommand resp;
477
aa53efc3 478 UsbCommand c = {CMD_READER_ICLASS, {0}};
3ac22ee1 479 c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_ONE_TRY;
aa53efc3 480 if (use_credit_key)
481 c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY;
53444513 482
aa53efc3 483 clearCommandBuffer();
484 SendCommand(&c);
485 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
486 {
53444513 487 PrintAndLog("Command execute timeout");
aa53efc3 488 return false;
53444513
MHS
489 }
490
aa53efc3 491 uint8_t isOK = resp.arg[0] & 0xff;
492 uint8_t *data = resp.d.asBytes;
53444513 493
aa53efc3 494 memcpy(CSN,data,8);
495 if (CCNR!=NULL)memcpy(CCNR,data+16,8);
aa53efc3 496 if(isOK > 0)
497 {
498 if (verbose) PrintAndLog("CSN: %s",sprint_hex(CSN,8));
53444513 499 }
aa53efc3 500 if(isOK <= 1){
501 PrintAndLog("Failed to obtain CC! Aborting");
502 return false;
503 }
504 return true;
a66fca86 505}
6f101995 506
bc37cfb3 507static 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 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};
aa53efc3 510
511 if (!select_only(CSN, CCNR, use_credit_key, verbose))
512 return false;
513
4d68ec02 514 //get div_key
bc37cfb3
AL
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]);
4d68ec02 520
aa53efc3 521 doMAC(CCNR, div_key, MAC);
aa53efc3 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
4d68ec02 540int usage_hf_iclass_dump(void) {
bc37cfb3 541 PrintAndLog("Usage: hf iclass dump f <fileName> k <Key> c <CreditKey> e|r\n");
aa53efc3 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");
bc37cfb3 549 PrintAndLog(" r : If 'r' is specified, the key is interpreted as raw block 3/4");
aa53efc3 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
4d68ec02 558int CmdHFiClassReader_Dump(const char *Cmd) {
aa53efc3 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;
4d68ec02 565 uint8_t maxBlk = 31;
bbd19bec 566 uint8_t app_areas = 1;
b82d8098 567 uint8_t kb = 2;
aa53efc3 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};
4d68ec02 575 bool have_debit_key = false;
aa53efc3 576 bool have_credit_key = false;
4d68ec02 577 bool use_credit_key = false;
aa53efc3 578 bool elite = false;
bc37cfb3 579 bool rawkey = false;
aa53efc3 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':
4d68ec02 626 have_debit_key = true;
aa53efc3 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;
bc37cfb3
AL
644 case 'r':
645 case 'R':
646 rawkey = true;
647 cmdp++;
648 break;
aa53efc3 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();
4d68ec02 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;
aa53efc3 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];
4d68ec02 666
aa53efc3 667 clearCommandBuffer();
668 SendCommand(&c);
4d68ec02 669 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
aa53efc3 670 PrintAndLog("Command execute timeout");
3ac22ee1 671 ul_switch_off_field();
aa53efc3 672 return 0;
673 }
4d68ec02 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...");
3ac22ee1 679 ul_switch_off_field();
4d68ec02 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];
bbd19bec 686 getMemConfig(data[13], data[12], &maxBlk, &app_areas, &kb);
b82d8098 687 // large memory - not able to dump pages currently
4d68ec02 688 if (numblks > maxBlk) numblks = maxBlk;
689 }
3ac22ee1 690 ul_switch_off_field();
4d68ec02 691 // authenticate debit key and get div_key - later store in dump block 3
bc37cfb3 692 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
aa53efc3 693 //try twice - for some reason it sometimes fails the first time...
bc37cfb3 694 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
aa53efc3 695 ul_switch_off_field();
696 return 0;
697 }
698 }
aa53efc3 699
4d68ec02 700 // begin dump
3ac22ee1 701 UsbCommand w = {CMD_ICLASS_DUMP, {blockno, numblks-blockno+1}};
aa53efc3 702 clearCommandBuffer();
703 SendCommand(&w);
704 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
705 PrintAndLog("Command execute time-out 1");
3ac22ee1 706 ul_switch_off_field();
aa53efc3 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");
3ac22ee1 713 ul_switch_off_field();
aa53efc3 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 }
4d68ec02 721 // response ok - now get bigbuf content of the dump
aa53efc3 722 GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex);
723 WaitForResponse(CMD_ACK,NULL);
4d68ec02 724 size_t gotBytes = blocksRead*8 + blockno*8;
aa53efc3 725
4d68ec02 726 // try AA2
727 if (have_credit_key) {
728 //turn off hf field before authenticating with different key
aa53efc3 729 ul_switch_off_field();
aa53efc3 730 memset(MAC,0,4);
4d68ec02 731 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
bc37cfb3 732 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
aa53efc3 733 //try twice - for some reason it sometimes fails the first time...
bc37cfb3 734 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
aa53efc3 735 ul_switch_off_field();
736 return 0;
737 }
738 }
4d68ec02 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);
4d68ec02 744 clearCommandBuffer();
745 SendCommand(&w);
746 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
747 PrintAndLog("Command execute timeout 2");
3ac22ee1 748 ul_switch_off_field();
4d68ec02 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");
3ac22ee1 755 ul_switch_off_field();
4d68ec02 756 return 0;
757 }
aa53efc3 758
4d68ec02 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);
aa53efc3 767
4d68ec02 768 gotBytes += blocksRead*8;
769 } else { //field is still on - turn it off...
770 ul_switch_off_field();
771 }
aa53efc3 772 }
773
4d68ec02 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);
aa53efc3 781
aa53efc3 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 }
4d68ec02 787
788 // save the dump to .bin file
aa53efc3 789 PrintAndLog("Saving dump file - %d blocks read", gotBytes/8);
4d68ec02 790 saveFile(filename, "bin", tag_data, gotBytes);
aa53efc3 791 return 1;
792}
793
bc37cfb3 794static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
aa53efc3 795 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
796 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
bc37cfb3 797 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose))
aa53efc3 798 return 0;
799
800 UsbCommand resp;
801
802 Calc_wb_mac(blockno,bldata,div_key,MAC);
3ac22ee1 803 UsbCommand w = {CMD_ICLASS_WRITEBLOCK, {blockno}};
aa53efc3 804 memcpy(w.d.asBytes, bldata, 8);
3ac22ee1 805 memcpy(w.d.asBytes + 8, MAC, 4);
aa53efc3 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");
aa53efc3 820 return 1;
821}
822
4d68ec02 823int usage_hf_iclass_writeblock(void) {
aa53efc3 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");
bc37cfb3 830 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
aa53efc3 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
838int CmdHFiClass_WriteBlock(const char *Cmd) {
839 uint8_t blockno=0;
3ac22ee1 840 uint8_t bldata[8]={0,0,0,0,0,0,0,0};
aa53efc3 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;
bc37cfb3 847 bool rawkey= false;
aa53efc3 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;
bc37cfb3
AL
903 case 'r':
904 case 'R':
905 rawkey = true;
906 cmdp++;
907 break;
aa53efc3 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();
bc37cfb3 917 int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, true);
3ac22ee1 918 ul_switch_off_field();
919 return ans;
aa53efc3 920}
921
4d68ec02 922int usage_hf_iclass_clone(void) {
bc37cfb3 923 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
aa53efc3 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");
bc37cfb3 931 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
aa53efc3 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
939int 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;
bc37cfb3 950 bool rawkey = false;
aa53efc3 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;
bc37cfb3
AL
1014 case 'r':
1015 case 'R':
1016 rawkey = true;
1017 cmdp++;
1018 break;
aa53efc3 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);
33c795d0 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 }
aa53efc3 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
bc37cfb3 1062 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, true))
aa53efc3 1063 return 0;
1064
3ac22ee1 1065 UsbCommand w = {CMD_ICLASS_CLONE,{startblock,endblock}};
aa53efc3 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);
4d68ec02 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]);
aa53efc3 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
bc37cfb3 1095static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose) {
aa53efc3 1096 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1097 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1098
bc37cfb3 1099 if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, rawkey, verbose))
aa53efc3 1100 return 0;
1101
1102 UsbCommand resp;
3ac22ee1 1103 UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno}};
aa53efc3 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
4d68ec02 1121int usage_hf_iclass_readblock(void) {
bc37cfb3 1122 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
aa53efc3 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");
bc37cfb3 1128 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
aa53efc3 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
4d68ec02 1136int CmdHFiClass_ReadBlock(const char *Cmd) {
aa53efc3 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;
bc37cfb3 1144 bool rawkey = false;
aa53efc3 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;
bc37cfb3
AL
1191 case 'r':
1192 case 'R':
1193 rawkey = true;
1194 cmdp++;
1195 break;
aa53efc3 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();
4d68ec02 1205
bc37cfb3 1206 return ReadBlock(KEY, blockno, keyType, elite, rawkey, true);
aa53efc3 1207}
1208
4d68ec02 1209int CmdHFiClass_loclass(const char *Cmd) {
aa53efc3 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");
6f101995
MHS
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 {
53444513
MHS
1230 if(param_getstr(Cmd, 1, fileName) > 0)
1231 {
1232 return bruteforceFileNoKeys(fileName);
1233 }else
1234 {
1235 PrintAndLog("You must specify a filename");
1236 }
6f101995
MHS
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 }
a66fca86 1250
6f101995
MHS
1251 return 0;
1252}
c3963755 1253
4d68ec02 1254void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) {
aa53efc3 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;
4d68ec02 1260 if (mem_config & 0x80)
aa53efc3 1261 maxmemcount = 255;
1262 else
4d68ec02 1263 maxmemcount = 31;
1264 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
aa53efc3 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;
4d68ec02 1274 while (i <= endblock){
1275 printf("Block |%02X| ",i);
aa53efc3 1276 memcpy(blockdata,iclass_dump + (i * 8),8);
1277 for (j = 0;j < 8;j++)
1278 printf("%02X ",blockdata[j]);
4d68ec02 1279 printf("|\n");
aa53efc3 1280 i++;
1281 }
aa53efc3 1282}
1283
4d68ec02 1284int usage_hf_iclass_readtagfile() {
1285 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1286 return 1;
1287}
1288
1289int CmdHFiClassReadTagFile(const char *Cmd) {
aa53efc3 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;
4d68ec02 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]);
aa53efc3 1323 // printIclassDumpInfo(dump);
1324 printIclassDumpContents(dump,startblock,endblock,bytes_read);
1325 free(dump);
1326 return 0;
1327}
1328
4d68ec02 1329/*
1330uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
aa53efc3 1331 uint64_t new_div = 0x00;
1332 new_div ^= sdiv;
1333 new_div ^= hdiv;
1334 return new_div;
1335}
1336
4d68ec02 1337uint64_t hexarray_to_uint64(uint8_t *key) {
aa53efc3 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}
4d68ec02 1347*/
1348void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite){
aa53efc3 1349 uint8_t keytable[128] = {0};
1350 uint8_t key_index[8] = {0};
4d68ec02 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;
aa53efc3 1358
4d68ec02 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}
aa53efc3 1366
4d68ec02 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
1370static 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}
aa53efc3 1387
4d68ec02 1388int 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");
aa53efc3 1402
4d68ec02 1403 return 1;
1404}
aa53efc3 1405
4d68ec02 1406int 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 }
aa53efc3 1487
4d68ec02 1488 if (cmdp < 4) return usage_hf_iclass_calc_newkey();
aa53efc3 1489
4d68ec02 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);
aa53efc3 1495 return 0;
1496}
1497
4d68ec02 1498static int loadKeys(char *filename) {
aa53efc3 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
4d68ec02 1527static int saveKeys(char *filename) {
aa53efc3 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
4d68ec02 1544static int printKeys(void) {
aa53efc3 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
4d68ec02 1553int usage_hf_iclass_managekeys(void) {
aa53efc3 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
4d68ec02 1571int CmdHFiClassManageKeys(const char *Cmd) {
aa53efc3 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
cee5a30d 1664static command_t CommandTable[] =
1665{
aa53efc3 1666 {"help", CmdHelp, 1, "This help"},
4d68ec02 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"},
6f101995 1683 {NULL, NULL, 0, NULL}
cee5a30d 1684};
1685
1686int CmdHFiClass(const char *Cmd)
1687{
53444513
MHS
1688 CmdsParse(CommandTable, Cmd);
1689 return 0;
cee5a30d 1690}
1691
1692int CmdHelp(const char *Cmd)
1693{
53444513
MHS
1694 CmdsHelp(CommandTable);
1695 return 0;
cee5a30d 1696}
Impressum, Datenschutz