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