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