]> git.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhficlass.c
fix keyNbr entry error checking
[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);
b0c68b72 599 if (keyNbr < ICLASS_KEYS_MAX) {
aa53efc3 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);
b0c68b72 633 if (keyNbr < ICLASS_KEYS_MAX) {
aa53efc3 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);
b0c68b72 892 if (keyNbr < ICLASS_KEYS_MAX) {
aa53efc3 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);
b0c68b72 995 if (keyNbr < ICLASS_KEYS_MAX) {
aa53efc3 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);
b0c68b72 1180 if (keyNbr < ICLASS_KEYS_MAX) {
aa53efc3 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
b0c68b72 1317 if ( fsize < 0 ) {
1318 PrintAndLog("Error, when getting filesize");
1319 fclose(f);
1320 return 1;
1321 }
aa53efc3 1322
b0c68b72 1323 uint8_t *dump = malloc(fsize);
aa53efc3 1324
1325 size_t bytes_read = fread(dump, 1, fsize, f);
1326 fclose(f);
1327 uint8_t *csn = dump;
4d68ec02 1328 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 1329 // printIclassDumpInfo(dump);
1330 printIclassDumpContents(dump,startblock,endblock,bytes_read);
1331 free(dump);
1332 return 0;
1333}
1334
4d68ec02 1335/*
1336uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
aa53efc3 1337 uint64_t new_div = 0x00;
1338 new_div ^= sdiv;
1339 new_div ^= hdiv;
1340 return new_div;
1341}
1342
4d68ec02 1343uint64_t hexarray_to_uint64(uint8_t *key) {
aa53efc3 1344 char temp[17];
1345 uint64_t uint_key;
1346 for (int i = 0;i < 8;i++)
1347 sprintf(&temp[(i *2)],"%02X",key[i]);
1348 temp[16] = '\0';
1349 if (sscanf(temp,"%016"llX,&uint_key) < 1)
1350 return 0;
1351 return uint_key;
1352}
4d68ec02 1353*/
1354void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite){
aa53efc3 1355 uint8_t keytable[128] = {0};
1356 uint8_t key_index[8] = {0};
4d68ec02 1357 if (elite) {
1358 uint8_t key_sel[8] = { 0 };
1359 uint8_t key_sel_p[8] = { 0 };
1360 hash2(KEY, keytable);
1361 hash1(CSN, key_index);
1362 for(uint8_t i = 0; i < 8 ; i++)
1363 key_sel[i] = keytable[key_index[i]] & 0xFF;
aa53efc3 1364
4d68ec02 1365 //Permute from iclass format to standard format
1366 permutekey_rev(key_sel, key_sel_p);
1367 diversifyKey(CSN, key_sel_p, div_key);
1368 } else {
1369 diversifyKey(CSN, KEY, div_key);
1370 }
1371}
aa53efc3 1372
4d68ec02 1373//when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1374//calculate and return xor_div_key (ready for a key write command)
1375//print all div_keys if verbose
1376static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, uint8_t *xor_div_key, bool elite, bool oldElite, bool verbose){
1377 uint8_t old_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1378 uint8_t new_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1379 //get old div key
1380 HFiClassCalcDivKey(CSN, OLDKEY, old_div_key, oldElite);
1381 //get new div key
1382 HFiClassCalcDivKey(CSN, NEWKEY, new_div_key, elite);
1383
1384 for (uint8_t i = 0; i < sizeof(old_div_key); i++){
1385 xor_div_key[i] = old_div_key[i] ^ new_div_key[i];
1386 }
1387 if (verbose) {
1388 printf("Old Div Key : %s\n",sprint_hex(old_div_key,8));
1389 printf("New Div Key : %s\n",sprint_hex(new_div_key,8));
1390 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key,8));
1391 }
1392}
aa53efc3 1393
4d68ec02 1394int usage_hf_iclass_calc_newkey(void) {
1395 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1396 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1397 PrintAndLog(" Options:");
1398 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1399 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1400 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1401 PrintAndLog(" e : specify new key as elite calc");
1402 PrintAndLog(" ee : specify old and new key as elite calc");
1403 PrintAndLog("Samples:");
1404 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1405 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1406 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1407 PrintAndLog("NOTE: * = required\n");
aa53efc3 1408
4d68ec02 1409 return 1;
1410}
aa53efc3 1411
4d68ec02 1412int CmdHFiClassCalcNewKey(const char *Cmd) {
1413 uint8_t OLDKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1414 uint8_t NEWKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1415 uint8_t xor_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1416 uint8_t CSN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1417 uint8_t CCNR[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1418 uint8_t keyNbr = 0;
1419 uint8_t dataLen = 0;
1420 char tempStr[50] = {0};
1421 bool givenCSN = false;
1422 bool oldElite = false;
1423 bool elite = false;
1424 bool errors = false;
1425 uint8_t cmdp = 0;
1426 while(param_getchar(Cmd, cmdp) != 0x00)
1427 {
1428 switch(param_getchar(Cmd, cmdp))
1429 {
1430 case 'h':
1431 case 'H':
1432 return usage_hf_iclass_calc_newkey();
1433 case 'e':
1434 case 'E':
1435 dataLen = param_getstr(Cmd, cmdp, tempStr);
1436 if (dataLen==2)
1437 oldElite = true;
1438 elite = true;
1439 cmdp++;
1440 break;
1441 case 'n':
1442 case 'N':
1443 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1444 if (dataLen == 16) {
1445 errors = param_gethex(tempStr, 0, NEWKEY, dataLen);
1446 } else if (dataLen == 1) {
1447 keyNbr = param_get8(Cmd, cmdp+1);
b0c68b72 1448 if (keyNbr < ICLASS_KEYS_MAX) {
4d68ec02 1449 memcpy(NEWKEY, iClass_Key_Table[keyNbr], 8);
1450 } else {
1451 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1452 errors = true;
1453 }
1454 } else {
1455 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1456 errors = true;
1457 }
1458 cmdp += 2;
1459 break;
1460 case 'o':
1461 case 'O':
1462 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1463 if (dataLen == 16) {
1464 errors = param_gethex(tempStr, 0, OLDKEY, dataLen);
1465 } else if (dataLen == 1) {
1466 keyNbr = param_get8(Cmd, cmdp+1);
b0c68b72 1467 if (keyNbr < ICLASS_KEYS_MAX) {
4d68ec02 1468 memcpy(OLDKEY, iClass_Key_Table[keyNbr], 8);
1469 } else {
1470 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1471 errors = true;
1472 }
1473 } else {
1474 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1475 errors = true;
1476 }
1477 cmdp += 2;
1478 break;
1479 case 's':
1480 case 'S':
1481 givenCSN = true;
1482 if (param_gethex(Cmd, cmdp+1, CSN, 16))
1483 return usage_hf_iclass_calc_newkey();
1484 cmdp += 2;
1485 break;
1486 default:
1487 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1488 errors = true;
1489 break;
1490 }
1491 if(errors) return usage_hf_iclass_calc_newkey();
1492 }
aa53efc3 1493
4d68ec02 1494 if (cmdp < 4) return usage_hf_iclass_calc_newkey();
aa53efc3 1495
4d68ec02 1496 if (!givenCSN)
1497 if (!select_only(CSN, CCNR, false, true))
1498 return 0;
1499
1500 HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, oldElite, true);
aa53efc3 1501 return 0;
1502}
1503
4d68ec02 1504static int loadKeys(char *filename) {
aa53efc3 1505 FILE *f;
1506 f = fopen(filename,"rb");
1507 if(!f) {
1508 PrintAndLog("Failed to read from file '%s'", filename);
1509 return 0;
1510 }
1511 fseek(f, 0, SEEK_END);
1512 long fsize = ftell(f);
1513 fseek(f, 0, SEEK_SET);
1514
eb5b63b4 1515 if ( fsize < 0 ) {
1516 PrintAndLog("Error, when getting filesize");
1517 fclose(f);
1518 return 1;
1519 }
1520
aa53efc3 1521 uint8_t *dump = malloc(fsize);
1522
1523 size_t bytes_read = fread(dump, 1, fsize, f);
1524 fclose(f);
1525 if (bytes_read > ICLASS_KEYS_MAX * 8){
1526 PrintAndLog("File is too long to load - bytes: %u", bytes_read);
1527 free(dump);
1528 return 0;
1529 }
1530 uint8_t i = 0;
1531 for (; i < bytes_read/8; i++){
1532 memcpy(iClass_Key_Table[i],dump+(i*8),8);
1533 }
1534 free(dump);
1535 PrintAndLog("%u keys loaded", i);
1536 return 1;
1537}
1538
4d68ec02 1539static int saveKeys(char *filename) {
aa53efc3 1540 FILE *f;
1541 f = fopen(filename,"wb");
1542 if (f == NULL) {
1543 printf("error opening file %s\n",filename);
1544 return 0;
1545 }
1546 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1547 if (fwrite(iClass_Key_Table[i],8,1,f) != 1){
1548 PrintAndLog("save key failed to write to file: %s", filename);
1549 break;
1550 }
1551 }
1552 fclose(f);
1553 return 0;
1554}
1555
4d68ec02 1556static int printKeys(void) {
aa53efc3 1557 PrintAndLog("");
1558 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1559 PrintAndLog("%u: %s",i,sprint_hex(iClass_Key_Table[i],8));
1560 }
1561 PrintAndLog("");
1562 return 0;
1563}
1564
4d68ec02 1565int usage_hf_iclass_managekeys(void) {
aa53efc3 1566 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1567 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1568 PrintAndLog(" Options:");
1569 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1570 PrintAndLog(" k <key> : set a key in memory");
1571 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1572 PrintAndLog(" s : save keys in memory to file specified by filename");
1573 PrintAndLog(" l : load keys to memory from file specified by filename");
1574 PrintAndLog(" p : print keys loaded into memory\n");
1575 PrintAndLog("Samples:");
1576 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1577 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1578 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1579 PrintAndLog(" print keys : hf iclass managekeys p\n");
1580 return 0;
1581}
1582
4d68ec02 1583int CmdHFiClassManageKeys(const char *Cmd) {
aa53efc3 1584 uint8_t keyNbr = 0;
1585 uint8_t dataLen = 0;
1586 uint8_t KEY[8] = {0};
1587 char filename[FILE_PATH_SIZE];
1588 uint8_t fileNameLen = 0;
1589 bool errors = false;
1590 uint8_t operation = 0;
1591 char tempStr[20];
1592 uint8_t cmdp = 0;
1593
1594 while(param_getchar(Cmd, cmdp) != 0x00)
1595 {
1596 switch(param_getchar(Cmd, cmdp))
1597 {
1598 case 'h':
1599 case 'H':
1600 return usage_hf_iclass_managekeys();
1601 case 'f':
1602 case 'F':
1603 fileNameLen = param_getstr(Cmd, cmdp+1, filename);
1604 if (fileNameLen < 1) {
1605 PrintAndLog("No filename found after f");
1606 errors = true;
1607 }
1608 cmdp += 2;
1609 break;
1610 case 'n':
1611 case 'N':
1612 keyNbr = param_get8(Cmd, cmdp+1);
b0c68b72 1613 if (keyNbr >= ICLASS_KEYS_MAX) {
1614 PrintAndLog("Invalid block number");
aa53efc3 1615 errors = true;
1616 }
1617 cmdp += 2;
1618 break;
1619 case 'k':
1620 case 'K':
1621 operation += 3; //set key
1622 dataLen = param_getstr(Cmd, cmdp+1, tempStr);
1623 if (dataLen == 16) { //ul-c or ev1/ntag key length
1624 errors = param_gethex(tempStr, 0, KEY, dataLen);
1625 } else {
1626 PrintAndLog("\nERROR: Key is incorrect length\n");
1627 errors = true;
1628 }
1629 cmdp += 2;
1630 break;
1631 case 'p':
1632 case 'P':
1633 operation += 4; //print keys in memory
1634 cmdp++;
1635 break;
1636 case 'l':
1637 case 'L':
1638 operation += 5; //load keys from file
1639 cmdp++;
1640 break;
1641 case 's':
1642 case 'S':
1643 operation += 6; //save keys to file
1644 cmdp++;
1645 break;
1646 default:
1647 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1648 errors = true;
1649 break;
1650 }
1651 if(errors) return usage_hf_iclass_managekeys();
1652 }
1653 if (operation == 0){
1654 PrintAndLog("no operation specified (load, save, or print)\n");
1655 return usage_hf_iclass_managekeys();
1656 }
1657 if (operation > 6){
1658 PrintAndLog("Too many operations specified\n");
1659 return usage_hf_iclass_managekeys();
1660 }
1661 if (operation > 4 && fileNameLen == 0){
1662 PrintAndLog("You must enter a filename when loading or saving\n");
1663 return usage_hf_iclass_managekeys();
1664 }
1665
1666 switch (operation){
1667 case 3: memcpy(iClass_Key_Table[keyNbr], KEY, 8); return 1;
1668 case 4: return printKeys();
1669 case 5: return loadKeys(filename);
1670 case 6: return saveKeys(filename);
1671 break;
1672 }
1673 return 0;
1674}
1675
cee5a30d 1676static command_t CommandTable[] =
1677{
aa53efc3 1678 {"help", CmdHelp, 1, "This help"},
4d68ec02 1679 {"calcnewkey", CmdHFiClassCalcNewKey, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
1680 {"clone", CmdHFiClassCloneTag, 0, "[options..] Authenticate and Clone from iClass bin file"},
1681 {"decrypt", CmdHFiClassDecrypt, 1, "[f <fname>] Decrypt tagdump" },
1682 {"dump", CmdHFiClassReader_Dump, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1683 {"eload", CmdHFiClassELoad, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1684 {"encryptblk", CmdHFiClassEncryptBlk, 1, "<BlockData> Encrypt given block data"},
1685 {"list", CmdHFiClassList, 0, " (Deprecated) List iClass history"},
1686 {"loclass", CmdHFiClass_loclass, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1687 {"managekeys", CmdHFiClassManageKeys, 1, "[options..] Manage the keys to use with iClass"},
1688 {"readblk", CmdHFiClass_ReadBlock, 0, "[options..] Authenticate and Read iClass block"},
1689 {"reader", CmdHFiClassReader, 0, " Read an iClass tag"},
1690 {"readtagfile", CmdHFiClassReadTagFile, 1, "[options..] Display Content from tagfile"},
1691 {"replay", CmdHFiClassReader_Replay, 0, "<mac> Read an iClass tag via Reply Attack"},
1692 {"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"},
1693 {"snoop", CmdHFiClassSnoop, 0, " Eavesdrop iClass communication"},
1694 {"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"},
6f101995 1695 {NULL, NULL, 0, NULL}
cee5a30d 1696};
1697
1698int CmdHFiClass(const char *Cmd)
1699{
53444513
MHS
1700 CmdsParse(CommandTable, Cmd);
1701 return 0;
cee5a30d 1702}
1703
1704int CmdHelp(const char *Cmd)
1705{
53444513
MHS
1706 CmdsHelp(CommandTable);
1707 return 0;
cee5a30d 1708}
Impressum, Datenschutz