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