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