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