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