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