]> cvs.zerfleddert.de Git - proxmark3-svn/blame - client/cmdhficlass.c
whitespace cleaning
[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];
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);
aa0b1c43 418 mbedtls_des3_context ctx = { {0} };
e0991f6a 419 mbedtls_des3_set2key_dec( &ctx, key);
41524d8a
MHS
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{
e0991f6a 435 mbedtls_des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
41524d8a
MHS
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;
aa0b1c43 470 mbedtls_des3_context ctx = { {0} };
e0991f6a 471 mbedtls_des3_set2key_enc( &ctx, key);
aa53efc3 472
e0991f6a 473 mbedtls_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
babca445 753 GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex, NULL, -1, false);
4d68ec02 754 size_t gotBytes = blocksRead*8 + blockno*8;
aa53efc3 755
4d68ec02 756 // try AA2
757 if (have_credit_key) {
758 //turn off hf field before authenticating with different key
872337e0 759 DropField();
aa53efc3 760 memset(MAC,0,4);
4d68ec02 761 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
bc37cfb3 762 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
aa53efc3 763 //try twice - for some reason it sometimes fails the first time...
bc37cfb3 764 if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
872337e0 765 DropField();
aa53efc3 766 return 0;
767 }
768 }
4d68ec02 769 // do we still need to read more block? (aa2 enabled?)
770 if (maxBlk > blockno+numblks+1) {
771 // setup dump and start
772 w.arg[0] = blockno + blocksRead;
773 w.arg[1] = maxBlk - (blockno + blocksRead);
4d68ec02 774 clearCommandBuffer();
775 SendCommand(&w);
776 if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
777 PrintAndLog("Command execute timeout 2");
872337e0 778 DropField();
4d68ec02 779 return 0;
780 }
781 uint8_t isOK = resp.arg[0] & 0xff;
782 blocksRead = resp.arg[1];
783 if (!isOK && !blocksRead) {
784 PrintAndLog("Read Block Failed 2");
872337e0 785 DropField();
4d68ec02 786 return 0;
787 }
aa53efc3 788
4d68ec02 789 startindex = resp.arg[2];
790 if (blocksRead*8 > sizeof(tag_data)-gotBytes) {
791 PrintAndLog("Data exceeded Buffer size!");
792 blocksRead = (sizeof(tag_data) - gotBytes)/8;
793 }
794 // get dumped data from bigbuf
babca445 795 GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex, NULL, -1, false);
aa53efc3 796
4d68ec02 797 gotBytes += blocksRead*8;
798 } else { //field is still on - turn it off...
872337e0 799 DropField();
4d68ec02 800 }
aa53efc3 801 }
802
4d68ec02 803 // add diversified keys to dump
804 if (have_debit_key) memcpy(tag_data+(3*8),div_key,8);
805 if (have_credit_key) memcpy(tag_data+(4*8),c_div_key,8);
806 // print the dump
89696b8b 807 printf("------+--+-------------------------+\n");
808 printf("CSN |00| %s|\n",sprint_hex(tag_data, 8));
809 printIclassDumpContents(tag_data, 1, (gotBytes/8), gotBytes);
810
aa53efc3 811 if (filename[0] == 0){
812 snprintf(filename, FILE_PATH_SIZE,"iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x",
813 tag_data[0],tag_data[1],tag_data[2],tag_data[3],
814 tag_data[4],tag_data[5],tag_data[6],tag_data[7]);
815 }
4d68ec02 816
817 // save the dump to .bin file
aa53efc3 818 PrintAndLog("Saving dump file - %d blocks read", gotBytes/8);
4d68ec02 819 saveFile(filename, "bin", tag_data, gotBytes);
aa53efc3 820 return 1;
821}
822
bc37cfb3 823static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
aa53efc3 824 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
825 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
bc37cfb3 826 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose))
aa53efc3 827 return 0;
828
829 UsbCommand resp;
830
831 Calc_wb_mac(blockno,bldata,div_key,MAC);
3ac22ee1 832 UsbCommand w = {CMD_ICLASS_WRITEBLOCK, {blockno}};
aa53efc3 833 memcpy(w.d.asBytes, bldata, 8);
3ac22ee1 834 memcpy(w.d.asBytes + 8, MAC, 4);
aa53efc3 835
836 clearCommandBuffer();
837 SendCommand(&w);
838 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
839 {
840 PrintAndLog("Write Command execute timeout");
841 return 0;
842 }
843 uint8_t isOK = resp.arg[0] & 0xff;
844 if (!isOK) {
845 PrintAndLog("Write Block Failed");
846 return 0;
847 }
848 PrintAndLog("Write Block Successful");
aa53efc3 849 return 1;
850}
851
4d68ec02 852int usage_hf_iclass_writeblock(void) {
aa53efc3 853 PrintAndLog("Options:");
854 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
855 PrintAndLog(" d <data> : Set the Data to write as 16 hex symbols");
856 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
857 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
858 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
bc37cfb3 859 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
aa53efc3 860 PrintAndLog("Samples:");
861 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA k 001122334455667B");
862 PrintAndLog(" hf iclass writeblk b 1B d AAAAAAAAAAAAAAAA k 001122334455667B c");
863 PrintAndLog(" hf iclass writeblk b 0A d AAAAAAAAAAAAAAAA n 0");
864 return 0;
865}
866
867int CmdHFiClass_WriteBlock(const char *Cmd) {
868 uint8_t blockno=0;
3ac22ee1 869 uint8_t bldata[8]={0,0,0,0,0,0,0,0};
aa53efc3 870 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
871 uint8_t keyNbr = 0;
872 uint8_t dataLen = 0;
873 char tempStr[50] = {0};
874 bool use_credit_key = false;
875 bool elite = false;
bc37cfb3 876 bool rawkey= false;
aa53efc3 877 bool errors = false;
878 uint8_t cmdp = 0;
879 while(param_getchar(Cmd, cmdp) != 0x00)
880 {
881 switch(param_getchar(Cmd, cmdp))
882 {
883 case 'h':
884 case 'H':
885 return usage_hf_iclass_writeblock();
886 case 'b':
887 case 'B':
888 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
889 PrintAndLog("Block No must include 2 HEX symbols\n");
890 errors = true;
891 }
892 cmdp += 2;
893 break;
894 case 'c':
895 case 'C':
896 use_credit_key = true;
897 cmdp++;
898 break;
899 case 'd':
900 case 'D':
901 if (param_gethex(Cmd, cmdp+1, bldata, 16))
902 {
903 PrintAndLog("KEY must include 16 HEX symbols\n");
904 errors = true;
905 }
906 cmdp += 2;
907 break;
908 case 'e':
909 case 'E':
910 elite = true;
911 cmdp++;
912 break;
913 case 'k':
914 case 'K':
874572d4 915 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
aa53efc3 916 if (dataLen == 16) {
917 errors = param_gethex(tempStr, 0, KEY, dataLen);
918 } else if (dataLen == 1) {
919 keyNbr = param_get8(Cmd, cmdp+1);
b0c68b72 920 if (keyNbr < ICLASS_KEYS_MAX) {
aa53efc3 921 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
922 } else {
923 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
924 errors = true;
925 }
926 } else {
927 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
928 errors = true;
929 }
930 cmdp += 2;
931 break;
bc37cfb3
AL
932 case 'r':
933 case 'R':
934 rawkey = true;
935 cmdp++;
936 break;
aa53efc3 937 default:
938 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
939 errors = true;
940 break;
941 }
942 if(errors) return usage_hf_iclass_writeblock();
943 }
944
945 if (cmdp < 6) return usage_hf_iclass_writeblock();
bc37cfb3 946 int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, true);
872337e0 947 DropField();
3ac22ee1 948 return ans;
aa53efc3 949}
950
4d68ec02 951int usage_hf_iclass_clone(void) {
bc37cfb3 952 PrintAndLog("Usage: hf iclass clone f <tagfile.bin> b <first block> l <last block> k <KEY> c e|r");
aa53efc3 953 PrintAndLog("Options:");
954 PrintAndLog(" f <filename>: specify a filename to clone from");
955 PrintAndLog(" b <Block> : The first block to clone as 2 hex symbols");
956 PrintAndLog(" l <Last Blk>: Set the Data to write as 16 hex symbols");
957 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
958 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
959 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
bc37cfb3 960 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
aa53efc3 961 PrintAndLog("Samples:");
962 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 1A k 1122334455667788 e");
963 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 05 l 19 k 0");
964 PrintAndLog(" hf iclass clone f iclass_tagdump-121345.bin b 06 l 19 k 0 e");
965 return -1;
966}
967
968int CmdHFiClassCloneTag(const char *Cmd) {
165e0775 969 char filename[FILE_PATH_SIZE] = {0};
aa53efc3 970 char tempStr[50]={0};
971 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
972 uint8_t keyNbr = 0;
973 uint8_t fileNameLen = 0;
974 uint8_t startblock = 0;
975 uint8_t endblock = 0;
976 uint8_t dataLen = 0;
977 bool use_credit_key = false;
978 bool elite = false;
bc37cfb3 979 bool rawkey = false;
aa53efc3 980 bool errors = false;
981 uint8_t cmdp = 0;
982 while(param_getchar(Cmd, cmdp) != 0x00)
983 {
984 switch(param_getchar(Cmd, cmdp))
985 {
986 case 'h':
987 case 'H':
988 return usage_hf_iclass_clone();
989 case 'b':
990 case 'B':
991 if (param_gethex(Cmd, cmdp+1, &startblock, 2)) {
992 PrintAndLog("Start Block No must include 2 HEX symbols\n");
993 errors = true;
994 }
995 cmdp += 2;
996 break;
997 case 'c':
998 case 'C':
999 use_credit_key = true;
1000 cmdp++;
1001 break;
1002 case 'e':
1003 case 'E':
1004 elite = true;
1005 cmdp++;
1006 break;
1007 case 'f':
1008 case 'F':
874572d4 1009 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
aa53efc3 1010 if (fileNameLen < 1) {
1011 PrintAndLog("No filename found after f");
1012 errors = true;
1013 }
1014 cmdp += 2;
1015 break;
1016 case 'k':
1017 case 'K':
874572d4 1018 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
aa53efc3 1019 if (dataLen == 16) {
1020 errors = param_gethex(tempStr, 0, KEY, dataLen);
1021 } else if (dataLen == 1) {
1022 keyNbr = param_get8(Cmd, cmdp+1);
b0c68b72 1023 if (keyNbr < ICLASS_KEYS_MAX) {
aa53efc3 1024 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1025 } else {
1026 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1027 errors = true;
1028 }
1029 } else {
1030 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1031 errors = true;
1032 }
1033 cmdp += 2;
1034 break;
1035 case 'l':
1036 case 'L':
1037 if (param_gethex(Cmd, cmdp+1, &endblock, 2)) {
1038 PrintAndLog("Start Block No must include 2 HEX symbols\n");
1039 errors = true;
1040 }
1041 cmdp += 2;
1042 break;
bc37cfb3
AL
1043 case 'r':
1044 case 'R':
1045 rawkey = true;
1046 cmdp++;
1047 break;
aa53efc3 1048 default:
1049 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1050 errors = true;
1051 break;
1052 }
1053 if(errors) return usage_hf_iclass_clone();
1054 }
1055
1056 if (cmdp < 8) return usage_hf_iclass_clone();
1057
1058 FILE *f;
1059
1060 iclass_block_t tag_data[USB_CMD_DATA_SIZE/12];
1061
1062 if ((endblock-startblock+1)*12 > USB_CMD_DATA_SIZE) {
1063 PrintAndLog("Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE/8);
1064 }
1065 // file handling and reading
1066 f = fopen(filename,"rb");
1067 if(!f) {
1068 PrintAndLog("Failed to read from file '%s'", filename);
1069 return 1;
1070 }
1071
1072 if (startblock<5) {
1073 PrintAndLog("You cannot write key blocks this way. yet... make your start block > 4");
165e0775 1074 fclose(f);
aa53efc3 1075 return 0;
1076 }
1077 // now read data from the file from block 6 --- 19
1078 // ok we will use this struct [data 8 bytes][MAC 4 bytes] for each block calculate all mac number for each data
1079 // 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,
1080 // else we have to create a share memory
1081 int i;
1082 fseek(f,startblock*8,SEEK_SET);
33c795d0 1083 if ( fread(tag_data,sizeof(iclass_block_t),endblock - startblock + 1,f) == 0 ) {
1084 PrintAndLog("File reading error.");
1085 fclose(f);
1086 return 2;
1087 }
aa53efc3 1088
1089 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1090 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1091
bc37cfb3 1092 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, true))
aa53efc3 1093 return 0;
1094
3ac22ee1 1095 UsbCommand w = {CMD_ICLASS_CLONE,{startblock,endblock}};
aa53efc3 1096 uint8_t *ptr;
1097 // calculate all mac for every the block we will write
1098 for (i = startblock; i <= endblock; i++){
1099 Calc_wb_mac(i,tag_data[i - startblock].d,div_key,MAC);
1100 // usb command d start pointer = d + (i - 6) * 12
1101 // memcpy(pointer,tag_data[i - 6],8) 8 bytes
1102 // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
1103 // next one
1104 ptr = w.d.asBytes + (i - startblock) * 12;
1105 memcpy(ptr, &(tag_data[i - startblock].d[0]), 8);
1106 memcpy(ptr + 8,MAC, 4);
1107 }
1108 uint8_t p[12];
1109 for (i = 0; i <= endblock - startblock;i++){
1110 memcpy(p,w.d.asBytes + (i * 12),12);
4d68ec02 1111 printf("Block |%02x|",i + startblock);
1112 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]);
1113 printf(" MAC |%02x%02x%02x%02x|\n",p[8],p[9],p[10],p[11]);
aa53efc3 1114 }
1115 UsbCommand resp;
1116 SendCommand(&w);
1117 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
1118 {
1119 PrintAndLog("Command execute timeout");
1120 return 0;
1121 }
1122 return 1;
1123}
1124
67e344df 1125static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
aa53efc3 1126 uint8_t MAC[4]={0x00,0x00,0x00,0x00};
1127 uint8_t div_key[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1128
67e344df 1129 if (auth) {
1130 if (!select_and_auth(KEY, MAC, div_key, (keyType==0x18), elite, rawkey, verbose))
1131 return 0;
1132 } else {
1133 uint8_t CSN[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1134 uint8_t CCNR[12]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1135 if (!select_only(CSN, CCNR, (keyType==0x18), verbose))
1136 return 0;
1137 }
aa53efc3 1138
1139 UsbCommand resp;
3ac22ee1 1140 UsbCommand w = {CMD_ICLASS_READBLOCK, {blockno}};
aa53efc3 1141 clearCommandBuffer();
1142 SendCommand(&w);
1143 if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
1144 {
1145 PrintAndLog("Command execute timeout");
1146 return 0;
1147 }
1148 uint8_t isOK = resp.arg[0] & 0xff;
1149 if (!isOK) {
1150 PrintAndLog("Read Block Failed");
1151 return 0;
1152 }
1153 //data read is stored in: resp.d.asBytes[0-15]
1154 if (verbose) PrintAndLog("Block %02X: %s\n",blockno, sprint_hex(resp.d.asBytes,8));
1155 return 1;
1156}
1157
4d68ec02 1158int usage_hf_iclass_readblock(void) {
bc37cfb3 1159 PrintAndLog("Usage: hf iclass readblk b <Block> k <Key> c e|r\n");
aa53efc3 1160 PrintAndLog("Options:");
1161 PrintAndLog(" b <Block> : The block number as 2 hex symbols");
1162 PrintAndLog(" k <Key> : Access Key as 16 hex symbols or 1 hex to select key from memory");
1163 PrintAndLog(" c : If 'c' is specified, the key set is assumed to be the credit key\n");
1164 PrintAndLog(" e : If 'e' is specified, elite computations applied to key");
bc37cfb3 1165 PrintAndLog(" r : If 'r' is specified, no computations applied to key");
aa53efc3 1166 PrintAndLog("Samples:");
1167 PrintAndLog(" hf iclass readblk b 06 k 0011223344556677");
1168 PrintAndLog(" hf iclass readblk b 1B k 0011223344556677 c");
1169 PrintAndLog(" hf iclass readblk b 0A k 0");
1170 return 0;
1171}
1172
4d68ec02 1173int CmdHFiClass_ReadBlock(const char *Cmd) {
aa53efc3 1174 uint8_t blockno=0;
1175 uint8_t keyType = 0x88; //debit key
1176 uint8_t KEY[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1177 uint8_t keyNbr = 0;
1178 uint8_t dataLen = 0;
1179 char tempStr[50] = {0};
1180 bool elite = false;
bc37cfb3 1181 bool rawkey = false;
aa53efc3 1182 bool errors = false;
67e344df 1183 bool auth = false;
aa53efc3 1184 uint8_t cmdp = 0;
1185 while(param_getchar(Cmd, cmdp) != 0x00)
1186 {
1187 switch(param_getchar(Cmd, cmdp))
1188 {
1189 case 'h':
1190 case 'H':
1191 return usage_hf_iclass_readblock();
1192 case 'b':
1193 case 'B':
1194 if (param_gethex(Cmd, cmdp+1, &blockno, 2)) {
1195 PrintAndLog("Block No must include 2 HEX symbols\n");
1196 errors = true;
1197 }
1198 cmdp += 2;
1199 break;
1200 case 'c':
1201 case 'C':
1202 keyType = 0x18;
1203 cmdp++;
1204 break;
1205 case 'e':
1206 case 'E':
1207 elite = true;
1208 cmdp++;
1209 break;
1210 case 'k':
1211 case 'K':
67e344df 1212 auth = true;
874572d4 1213 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
aa53efc3 1214 if (dataLen == 16) {
1215 errors = param_gethex(tempStr, 0, KEY, dataLen);
1216 } else if (dataLen == 1) {
1217 keyNbr = param_get8(Cmd, cmdp+1);
b0c68b72 1218 if (keyNbr < ICLASS_KEYS_MAX) {
aa53efc3 1219 memcpy(KEY, iClass_Key_Table[keyNbr], 8);
1220 } else {
1221 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1222 errors = true;
1223 }
1224 } else {
1225 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1226 errors = true;
1227 }
1228 cmdp += 2;
1229 break;
bc37cfb3
AL
1230 case 'r':
1231 case 'R':
1232 rawkey = true;
1233 cmdp++;
1234 break;
aa53efc3 1235 default:
1236 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1237 errors = true;
1238 break;
1239 }
1240 if(errors) return usage_hf_iclass_readblock();
1241 }
1242
67e344df 1243 if (cmdp < 2) return usage_hf_iclass_readblock();
1244 if (!auth)
1245 PrintAndLog("warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
1246 return ReadBlock(KEY, blockno, keyType, elite, rawkey, true, auth);
aa53efc3 1247}
1248
4d68ec02 1249int CmdHFiClass_loclass(const char *Cmd) {
aa53efc3 1250 char opt = param_getchar(Cmd, 0);
1251
1252 if (strlen(Cmd)<1 || opt == 'h') {
1253 PrintAndLog("Usage: hf iclass loclass [options]");
1254 PrintAndLog("Options:");
1255 PrintAndLog("h Show this help");
6f101995
MHS
1256 PrintAndLog("t Perform self-test");
1257 PrintAndLog("f <filename> Bruteforce iclass dumpfile");
1258 PrintAndLog(" An iclass dumpfile is assumed to consist of an arbitrary number of");
1259 PrintAndLog(" malicious CSNs, and their protocol responses");
b8140ab1 1260 PrintAndLog(" The binary format of the file is expected to be as follows: ");
6f101995
MHS
1261 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1262 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1263 PrintAndLog(" <8 byte CSN><8 byte CC><4 byte NR><4 byte MAC>");
1264 PrintAndLog(" ... totalling N*24 bytes");
1265 return 0;
1266 }
1267 char fileName[255] = {0};
1268 if(opt == 'f')
1269 {
874572d4 1270 if(param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0)
53444513
MHS
1271 {
1272 return bruteforceFileNoKeys(fileName);
1273 }else
1274 {
1275 PrintAndLog("You must specify a filename");
1276 }
6f101995
MHS
1277 }
1278 else if(opt == 't')
1279 {
1280 int errors = testCipherUtils();
1281 errors += testMAC();
1282 errors += doKeyTests(0);
1283 errors += testElite();
1284 if(errors)
1285 {
1286 prnlog("OBS! There were errors!!!");
1287 }
1288 return errors;
1289 }
a66fca86 1290
6f101995
MHS
1291 return 0;
1292}
c3963755 1293
4d68ec02 1294void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize) {
aa53efc3 1295 uint8_t mem_config;
1296 memcpy(&mem_config, iclass_dump + 13,1);
1297 uint8_t maxmemcount;
1298 uint8_t filemaxblock = filesize / 8;
4d68ec02 1299 if (mem_config & 0x80)
aa53efc3 1300 maxmemcount = 255;
1301 else
4d68ec02 1302 maxmemcount = 31;
1303 //PrintAndLog ("endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d", endblock,filesize, maxmemcount, filemaxblock);
aa53efc3 1304
1305 if (startblock == 0)
1306 startblock = 6;
1307 if ((endblock > maxmemcount) || (endblock == 0))
1308 endblock = maxmemcount;
89696b8b 1309
1310 // remember endblock need to relate to zero-index arrays.
1311 if (endblock > filemaxblock-1)
aa53efc3 1312 endblock = filemaxblock;
89696b8b 1313
aa53efc3 1314 int i = startblock;
89696b8b 1315 printf("------+--+-------------------------+\n");
1316 while (i <= endblock) {
1317 uint8_t *blk = iclass_dump + (i * 8);
1318 printf("Block |%02X| %s|\n", i, sprint_hex(blk, 8) );
aa53efc3 1319 i++;
1320 }
89696b8b 1321 printf("------+--+-------------------------+\n");
aa53efc3 1322}
1323
4d68ec02 1324int usage_hf_iclass_readtagfile() {
1325 PrintAndLog("Usage: hf iclass readtagfile <filename> [startblock] [endblock]");
1326 return 1;
1327}
1328
1329int CmdHFiClassReadTagFile(const char *Cmd) {
aa53efc3 1330 int startblock = 0;
1331 int endblock = 0;
1332 char tempnum[5];
1333 FILE *f;
1334 char filename[FILE_PATH_SIZE];
874572d4 1335 if (param_getstr(Cmd, 0, filename, sizeof(filename)) < 1)
aa53efc3 1336 return usage_hf_iclass_readtagfile();
874572d4 1337 if (param_getstr(Cmd, 1, tempnum, sizeof(tempnum)) < 1)
aa53efc3 1338 startblock = 0;
1339 else
1340 sscanf(tempnum,"%d",&startblock);
1341
874572d4 1342 if (param_getstr(Cmd,2, tempnum, sizeof(tempnum)) < 1)
aa53efc3 1343 endblock = 0;
1344 else
1345 sscanf(tempnum,"%d",&endblock);
1346 // file handling and reading
1347 f = fopen(filename,"rb");
1348 if(!f) {
1349 PrintAndLog("Failed to read from file '%s'", filename);
1350 return 1;
1351 }
1352 fseek(f, 0, SEEK_END);
1353 long fsize = ftell(f);
1354 fseek(f, 0, SEEK_SET);
1355
b0c68b72 1356 if ( fsize < 0 ) {
1357 PrintAndLog("Error, when getting filesize");
1358 fclose(f);
1359 return 1;
1360 }
aa53efc3 1361
b0c68b72 1362 uint8_t *dump = malloc(fsize);
aa53efc3 1363
1364 size_t bytes_read = fread(dump, 1, fsize, f);
1365 fclose(f);
1366 uint8_t *csn = dump;
89696b8b 1367 printf("------+--+-------------------------+\n");
1368 printf("CSN |00| %s|\n", sprint_hex(csn, 8) );
aa53efc3 1369 // printIclassDumpInfo(dump);
1370 printIclassDumpContents(dump,startblock,endblock,bytes_read);
1371 free(dump);
1372 return 0;
1373}
1374
4d68ec02 1375/*
1376uint64_t xorcheck(uint64_t sdiv,uint64_t hdiv) {
aa53efc3 1377 uint64_t new_div = 0x00;
1378 new_div ^= sdiv;
1379 new_div ^= hdiv;
1380 return new_div;
1381}
1382
4d68ec02 1383uint64_t hexarray_to_uint64(uint8_t *key) {
aa53efc3 1384 char temp[17];
1385 uint64_t uint_key;
1386 for (int i = 0;i < 8;i++)
1387 sprintf(&temp[(i *2)],"%02X",key[i]);
1388 temp[16] = '\0';
43534cba 1389 if (sscanf(temp,"%016" SCNx64,&uint_key) < 1)
aa53efc3 1390 return 0;
1391 return uint_key;
1392}
4d68ec02 1393*/
1394void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite){
aa53efc3 1395 uint8_t keytable[128] = {0};
1396 uint8_t key_index[8] = {0};
4d68ec02 1397 if (elite) {
1398 uint8_t key_sel[8] = { 0 };
1399 uint8_t key_sel_p[8] = { 0 };
1400 hash2(KEY, keytable);
1401 hash1(CSN, key_index);
1402 for(uint8_t i = 0; i < 8 ; i++)
1403 key_sel[i] = keytable[key_index[i]] & 0xFF;
aa53efc3 1404
4d68ec02 1405 //Permute from iclass format to standard format
1406 permutekey_rev(key_sel, key_sel_p);
1407 diversifyKey(CSN, key_sel_p, div_key);
1408 } else {
1409 diversifyKey(CSN, KEY, div_key);
1410 }
1411}
aa53efc3 1412
4d68ec02 1413//when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite)
1414//calculate and return xor_div_key (ready for a key write command)
1415//print all div_keys if verbose
1416static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, uint8_t *xor_div_key, bool elite, bool oldElite, bool verbose){
1417 uint8_t old_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1418 uint8_t new_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1419 //get old div key
1420 HFiClassCalcDivKey(CSN, OLDKEY, old_div_key, oldElite);
1421 //get new div key
1422 HFiClassCalcDivKey(CSN, NEWKEY, new_div_key, elite);
1423
1424 for (uint8_t i = 0; i < sizeof(old_div_key); i++){
1425 xor_div_key[i] = old_div_key[i] ^ new_div_key[i];
1426 }
1427 if (verbose) {
1428 printf("Old Div Key : %s\n",sprint_hex(old_div_key,8));
1429 printf("New Div Key : %s\n",sprint_hex(new_div_key,8));
1430 printf("Xor Div Key : %s\n",sprint_hex(xor_div_key,8));
1431 }
1432}
aa53efc3 1433
4d68ec02 1434int usage_hf_iclass_calc_newkey(void) {
1435 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1436 PrintAndLog("Usage: hf iclass calc_newkey o <Old key> n <New key> s [csn] e");
1437 PrintAndLog(" Options:");
1438 PrintAndLog(" o <oldkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1439 PrintAndLog(" n <newkey> : *specify a key as 16 hex symbols or a key number as 1 symbol");
1440 PrintAndLog(" s <csn> : specify a card Serial number to diversify the key (if omitted will attempt to read a csn)");
1441 PrintAndLog(" e : specify new key as elite calc");
1442 PrintAndLog(" ee : specify old and new key as elite calc");
1443 PrintAndLog("Samples:");
1444 PrintAndLog(" e key to e key given csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899 s deadbeafdeadbeaf ee");
1445 PrintAndLog(" std key to e key read csn: hf iclass calcnewkey o 1122334455667788 n 2233445566778899 e");
1446 PrintAndLog(" std to std read csn : hf iclass calcnewkey o 1122334455667788 n 2233445566778899");
1447 PrintAndLog("NOTE: * = required\n");
aa53efc3 1448
4d68ec02 1449 return 1;
1450}
aa53efc3 1451
4d68ec02 1452int CmdHFiClassCalcNewKey(const char *Cmd) {
1453 uint8_t OLDKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1454 uint8_t NEWKEY[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1455 uint8_t xor_div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1456 uint8_t CSN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1457 uint8_t CCNR[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1458 uint8_t keyNbr = 0;
1459 uint8_t dataLen = 0;
1460 char tempStr[50] = {0};
1461 bool givenCSN = false;
1462 bool oldElite = false;
1463 bool elite = false;
1464 bool errors = false;
1465 uint8_t cmdp = 0;
1466 while(param_getchar(Cmd, cmdp) != 0x00)
1467 {
1468 switch(param_getchar(Cmd, cmdp))
1469 {
1470 case 'h':
1471 case 'H':
1472 return usage_hf_iclass_calc_newkey();
1473 case 'e':
1474 case 'E':
874572d4 1475 dataLen = param_getstr(Cmd, cmdp, tempStr, sizeof(tempStr));
4d68ec02 1476 if (dataLen==2)
1477 oldElite = true;
1478 elite = true;
1479 cmdp++;
1480 break;
1481 case 'n':
1482 case 'N':
874572d4 1483 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
4d68ec02 1484 if (dataLen == 16) {
1485 errors = param_gethex(tempStr, 0, NEWKEY, dataLen);
1486 } else if (dataLen == 1) {
1487 keyNbr = param_get8(Cmd, cmdp+1);
b0c68b72 1488 if (keyNbr < ICLASS_KEYS_MAX) {
4d68ec02 1489 memcpy(NEWKEY, iClass_Key_Table[keyNbr], 8);
1490 } else {
1491 PrintAndLog("\nERROR: NewKey Nbr is invalid\n");
1492 errors = true;
1493 }
1494 } else {
1495 PrintAndLog("\nERROR: NewKey is incorrect length\n");
1496 errors = true;
1497 }
1498 cmdp += 2;
1499 break;
1500 case 'o':
1501 case 'O':
874572d4 1502 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
4d68ec02 1503 if (dataLen == 16) {
1504 errors = param_gethex(tempStr, 0, OLDKEY, dataLen);
1505 } else if (dataLen == 1) {
1506 keyNbr = param_get8(Cmd, cmdp+1);
b0c68b72 1507 if (keyNbr < ICLASS_KEYS_MAX) {
4d68ec02 1508 memcpy(OLDKEY, iClass_Key_Table[keyNbr], 8);
1509 } else {
1510 PrintAndLog("\nERROR: Credit KeyNbr is invalid\n");
1511 errors = true;
1512 }
1513 } else {
1514 PrintAndLog("\nERROR: Credit Key is incorrect length\n");
1515 errors = true;
1516 }
1517 cmdp += 2;
1518 break;
1519 case 's':
1520 case 'S':
1521 givenCSN = true;
1522 if (param_gethex(Cmd, cmdp+1, CSN, 16))
1523 return usage_hf_iclass_calc_newkey();
1524 cmdp += 2;
1525 break;
1526 default:
1527 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1528 errors = true;
1529 break;
1530 }
1531 if(errors) return usage_hf_iclass_calc_newkey();
1532 }
aa53efc3 1533
4d68ec02 1534 if (cmdp < 4) return usage_hf_iclass_calc_newkey();
aa53efc3 1535
4d68ec02 1536 if (!givenCSN)
1537 if (!select_only(CSN, CCNR, false, true))
1538 return 0;
1539
1540 HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, oldElite, true);
aa53efc3 1541 return 0;
1542}
1543
4d68ec02 1544static int loadKeys(char *filename) {
aa53efc3 1545 FILE *f;
1546 f = fopen(filename,"rb");
1547 if(!f) {
1548 PrintAndLog("Failed to read from file '%s'", filename);
1549 return 0;
1550 }
1551 fseek(f, 0, SEEK_END);
1552 long fsize = ftell(f);
1553 fseek(f, 0, SEEK_SET);
1554
eb5b63b4 1555 if ( fsize < 0 ) {
1556 PrintAndLog("Error, when getting filesize");
1557 fclose(f);
1558 return 1;
1559 }
1560
aa53efc3 1561 uint8_t *dump = malloc(fsize);
1562
1563 size_t bytes_read = fread(dump, 1, fsize, f);
1564 fclose(f);
1565 if (bytes_read > ICLASS_KEYS_MAX * 8){
1566 PrintAndLog("File is too long to load - bytes: %u", bytes_read);
1567 free(dump);
1568 return 0;
1569 }
1570 uint8_t i = 0;
1571 for (; i < bytes_read/8; i++){
1572 memcpy(iClass_Key_Table[i],dump+(i*8),8);
1573 }
1574 free(dump);
1575 PrintAndLog("%u keys loaded", i);
1576 return 1;
1577}
1578
4d68ec02 1579static int saveKeys(char *filename) {
aa53efc3 1580 FILE *f;
1581 f = fopen(filename,"wb");
1582 if (f == NULL) {
1583 printf("error opening file %s\n",filename);
1584 return 0;
1585 }
1586 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1587 if (fwrite(iClass_Key_Table[i],8,1,f) != 1){
1588 PrintAndLog("save key failed to write to file: %s", filename);
1589 break;
1590 }
1591 }
1592 fclose(f);
1593 return 0;
1594}
1595
4d68ec02 1596static int printKeys(void) {
aa53efc3 1597 PrintAndLog("");
1598 for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++){
1599 PrintAndLog("%u: %s",i,sprint_hex(iClass_Key_Table[i],8));
1600 }
1601 PrintAndLog("");
1602 return 0;
1603}
1604
4d68ec02 1605int usage_hf_iclass_managekeys(void) {
aa53efc3 1606 PrintAndLog("HELP : Manage iClass Keys in client memory:\n");
1607 PrintAndLog("Usage: hf iclass managekeys n [keynbr] k [key] f [filename] s l p\n");
1608 PrintAndLog(" Options:");
1609 PrintAndLog(" n <keynbr> : specify the keyNbr to set in memory");
1610 PrintAndLog(" k <key> : set a key in memory");
1611 PrintAndLog(" f <filename>: specify a filename to use with load or save operations");
1612 PrintAndLog(" s : save keys in memory to file specified by filename");
1613 PrintAndLog(" l : load keys to memory from file specified by filename");
1614 PrintAndLog(" p : print keys loaded into memory\n");
1615 PrintAndLog("Samples:");
1616 PrintAndLog(" set key : hf iclass managekeys n 0 k 1122334455667788");
1617 PrintAndLog(" save key file: hf iclass managekeys f mykeys.bin s");
1618 PrintAndLog(" load key file: hf iclass managekeys f mykeys.bin l");
1619 PrintAndLog(" print keys : hf iclass managekeys p\n");
1620 return 0;
1621}
1622
4d68ec02 1623int CmdHFiClassManageKeys(const char *Cmd) {
aa53efc3 1624 uint8_t keyNbr = 0;
1625 uint8_t dataLen = 0;
1626 uint8_t KEY[8] = {0};
1627 char filename[FILE_PATH_SIZE];
1628 uint8_t fileNameLen = 0;
1629 bool errors = false;
1630 uint8_t operation = 0;
1631 char tempStr[20];
1632 uint8_t cmdp = 0;
1633
1634 while(param_getchar(Cmd, cmdp) != 0x00)
1635 {
1636 switch(param_getchar(Cmd, cmdp))
1637 {
1638 case 'h':
1639 case 'H':
1640 return usage_hf_iclass_managekeys();
1641 case 'f':
1642 case 'F':
874572d4 1643 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
aa53efc3 1644 if (fileNameLen < 1) {
1645 PrintAndLog("No filename found after f");
1646 errors = true;
1647 }
1648 cmdp += 2;
1649 break;
1650 case 'n':
1651 case 'N':
1652 keyNbr = param_get8(Cmd, cmdp+1);
b0c68b72 1653 if (keyNbr >= ICLASS_KEYS_MAX) {
1654 PrintAndLog("Invalid block number");
aa53efc3 1655 errors = true;
1656 }
1657 cmdp += 2;
1658 break;
1659 case 'k':
1660 case 'K':
1661 operation += 3; //set key
874572d4 1662 dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
aa53efc3 1663 if (dataLen == 16) { //ul-c or ev1/ntag key length
1664 errors = param_gethex(tempStr, 0, KEY, dataLen);
1665 } else {
1666 PrintAndLog("\nERROR: Key is incorrect length\n");
1667 errors = true;
1668 }
1669 cmdp += 2;
1670 break;
1671 case 'p':
1672 case 'P':
1673 operation += 4; //print keys in memory
1674 cmdp++;
1675 break;
1676 case 'l':
1677 case 'L':
1678 operation += 5; //load keys from file
1679 cmdp++;
1680 break;
1681 case 's':
1682 case 'S':
1683 operation += 6; //save keys to file
1684 cmdp++;
1685 break;
1686 default:
1687 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1688 errors = true;
1689 break;
1690 }
1691 if(errors) return usage_hf_iclass_managekeys();
1692 }
1693 if (operation == 0){
1694 PrintAndLog("no operation specified (load, save, or print)\n");
1695 return usage_hf_iclass_managekeys();
1696 }
1697 if (operation > 6){
1698 PrintAndLog("Too many operations specified\n");
1699 return usage_hf_iclass_managekeys();
1700 }
1701 if (operation > 4 && fileNameLen == 0){
1702 PrintAndLog("You must enter a filename when loading or saving\n");
1703 return usage_hf_iclass_managekeys();
1704 }
1705
1706 switch (operation){
1707 case 3: memcpy(iClass_Key_Table[keyNbr], KEY, 8); return 1;
1708 case 4: return printKeys();
1709 case 5: return loadKeys(filename);
1710 case 6: return saveKeys(filename);
1711 break;
1712 }
1713 return 0;
1714}
1715
385c1a5e
I
1716int CmdHFiClassCheckKeys(const char *Cmd) {
1717
385c1a5e
I
1718 uint8_t mac[4] = {0x00,0x00,0x00,0x00};
1719 uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1720 uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
1721
1722 // elite key, raw key, standard key
5e4932e8
I
1723 bool use_elite = false;
1724 bool use_raw = false;
385c1a5e
I
1725 bool found_debit = false;
1726 bool found_credit = false;
5e4932e8
I
1727 bool errors = false;
1728 uint8_t cmdp = 0x00;
385c1a5e
I
1729 FILE * f;
1730 char filename[FILE_PATH_SIZE] = {0};
5e4932e8 1731 uint8_t fileNameLen = 0;
385c1a5e
I
1732 char buf[17];
1733 uint8_t *keyBlock = NULL, *p;
1734 int keyitems = 0, keycnt = 0;
1735
5e4932e8
I
1736 while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
1737 switch (param_getchar(Cmd, cmdp)) {
1738 case 'h':
1739 case 'H':
1740 return usage_hf_iclass_chk();
1741 case 'f':
1742 case 'F':
1743 fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
1744 if (fileNameLen < 1) {
1745 PrintAndLog("No filename found after f");
1746 errors = true;
1747 }
1748 cmdp += 2;
1749 break;
1750 case 'e':
1751 case 'E':
1752 use_elite = true;
1753 cmdp++;
1754 break;
1755 case 'r':
1756 case 'R':
1757 use_raw = true;
1758 cmdp++;
1759 break;
1760 default:
1761 PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
1762 errors = true;
1763 break;
1764 }
385c1a5e 1765 }
5e4932e8 1766 if (errors) return usage_hf_iclass_chk();
385c1a5e
I
1767
1768 if ( !(f = fopen( filename , "r")) ) {
1769 PrintAndLog("File: %s: not found or locked.", filename);
385c1a5e
I
1770 return 1;
1771 }
1772
1773 while( fgets(buf, sizeof(buf), f) ){
1774 if (strlen(buf) < 16 || buf[15] == '\n')
1775 continue;
1776
1777 while (fgetc(f) != '\n' && !feof(f)) ; //goto next line
1778
1779 if( buf[0]=='#' ) continue; //The line start with # is comment, skip
1780
1781 if (!isxdigit(buf[0])){
1782 PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf);
1783 continue;
1784 }
1785
1786 buf[16] = 0;
1787
1788 p = realloc(keyBlock, 8 * (keyitems += 64));
1789 if (!p) {
1790 PrintAndLog("Cannot allocate memory for default keys");
1791 free(keyBlock);
1792 fclose(f);
1793 return 2;
1794 }
1795 keyBlock = p;
1796
1797 memset(keyBlock + 8 * keycnt, 0, 8);
1798 num_to_bytes(strtoull(buf, NULL, 16), 8, keyBlock + 8 * keycnt);
1799
1800 //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
1801 keycnt++;
1802 memset(buf, 0, sizeof(buf));
1803 }
1804 fclose(f);
1805 PrintAndLog("Loaded %2d keys from %s", keycnt, filename);
1806
1807 // time
1808 uint64_t t1 = msclock();
1809
1810 for (uint32_t c = 0; c < keycnt; c += 1) {
1811 printf("."); fflush(stdout);
1812 if (ukbhit()) {
1813 int gc = getchar(); (void)gc;
1814 printf("\naborted via keyboard!\n");
1815 break;
1816 }
1817
1818 memcpy(key, keyBlock + 8 * c , 8);
1819
1820 // debit key. try twice
1821 for (int foo = 0; foo < 2 && !found_debit; foo++) {
5e4932e8 1822 if (!select_and_auth(key, mac, div_key, false, use_elite, use_raw, false))
385c1a5e
I
1823 continue;
1824
1825 // key found.
1826 PrintAndLog("\n--------------------------------------------------------");
1827 PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key, 8));
1828 found_debit = true;
1829 }
1830
1831 // credit key. try twice
1832 for (int foo = 0; foo < 2 && !found_credit; foo++) {
5e4932e8 1833 if (!select_and_auth(key, mac, div_key, true, use_elite, use_raw, false))
385c1a5e
I
1834 continue;
1835
1836 // key found
1837 PrintAndLog("\n--------------------------------------------------------");
1838 PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key, 8));
1839 found_credit = true;
1840 }
1841
1842 // both keys found.
1843 if ( found_debit && found_credit )
1844 break;
1845 }
1846
1847 t1 = msclock() - t1;
1848
1849 PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1/1000.0);
1850
1851 DropField();
1852 free(keyBlock);
1853 PrintAndLog("");
1854 return 0;
1855}
1856
cee5a30d 1857static command_t CommandTable[] =
1858{
aa53efc3 1859 {"help", CmdHelp, 1, "This help"},
4d68ec02 1860 {"calcnewkey", CmdHFiClassCalcNewKey, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
385c1a5e 1861 {"chk", CmdHFiClassCheckKeys, 0, " Check keys"},
4d68ec02 1862 {"clone", CmdHFiClassCloneTag, 0, "[options..] Authenticate and Clone from iClass bin file"},
1863 {"decrypt", CmdHFiClassDecrypt, 1, "[f <fname>] Decrypt tagdump" },
1864 {"dump", CmdHFiClassReader_Dump, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
1865 {"eload", CmdHFiClassELoad, 0, "[f <fname>] (experimental) Load data into iClass emulator memory"},
1866 {"encryptblk", CmdHFiClassEncryptBlk, 1, "<BlockData> Encrypt given block data"},
1867 {"list", CmdHFiClassList, 0, " (Deprecated) List iClass history"},
1868 {"loclass", CmdHFiClass_loclass, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"},
1869 {"managekeys", CmdHFiClassManageKeys, 1, "[options..] Manage the keys to use with iClass"},
1870 {"readblk", CmdHFiClass_ReadBlock, 0, "[options..] Authenticate and Read iClass block"},
979c7655 1871 {"reader", CmdHFiClassReader, 0, " Look for iClass tags until a key or the pm3 button is pressed"},
4d68ec02 1872 {"readtagfile", CmdHFiClassReadTagFile, 1, "[options..] Display Content from tagfile"},
1873 {"replay", CmdHFiClassReader_Replay, 0, "<mac> Read an iClass tag via Reply Attack"},
1874 {"sim", CmdHFiClassSim, 0, "[options..] Simulate iClass tag"},
1875 {"snoop", CmdHFiClassSnoop, 0, " Eavesdrop iClass communication"},
1876 {"writeblk", CmdHFiClass_WriteBlock, 0, "[options..] Authenticate and Write iClass block"},
6f101995 1877 {NULL, NULL, 0, NULL}
cee5a30d 1878};
1879
1880int CmdHFiClass(const char *Cmd)
1881{
385c1a5e 1882 clearCommandBuffer();
53444513
MHS
1883 CmdsParse(CommandTable, Cmd);
1884 return 0;
cee5a30d 1885}
1886
1887int CmdHelp(const char *Cmd)
1888{
53444513
MHS
1889 CmdsHelp(CommandTable);
1890 return 0;
cee5a30d 1891}
Impressum, Datenschutz