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