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