#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
+#include <ctype.h>
#include "iso14443crc.h" // Can also be used for iClass, using 0xE012 as CRC-type
-#include "data.h"
-#include "proxmark3.h"
+#include "comms.h"
#include "ui.h"
#include "cmdparser.h"
#include "cmdhficlass.h"
#include "common.h"
#include "util.h"
#include "cmdmain.h"
-#include "loclass/des.h"
+#include "mbedtls/des.h"
#include "loclass/cipherutils.h"
#include "loclass/cipher.h"
#include "loclass/ikeys.h"
#include "protocols.h"
#include "usb_cmd.h"
#include "cmdhfmfu.h"
+#include "util_posix.h"
+#include "cmdhf14a.h" // DropField()
static int CmdHelp(const char *Cmd);
uint8_t d[8];
} iclass_block_t;
+int usage_hf_iclass_chk(void) {
+ PrintAndLog("Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag");
+ PrintAndLog("Usage: hf iclass chk [h|e|r] <f (*.dic)>");
+ PrintAndLog("Options:");
+ PrintAndLog("h Show this help");
+ PrintAndLog("f <filename> Dictionary file with default iclass keys");
+ PrintAndLog(" e target Elite / High security key scheme");
+ PrintAndLog(" r interpret dictionary file as raw (diversified keys)");
+ PrintAndLog("Samples:");
+ PrintAndLog(" hf iclass chk f default_iclass_keys.dic");
+ PrintAndLog(" hf iclass chk f default_iclass_keys.dic e");
+ return 0;
+}
+
int xorbits_8(uint8_t val) {
uint8_t res = val ^ (val >> 1); //1st pass
res = res ^ (res >> 1); // 2nd pass
return 0;
}
+// the original malicious IDs from Flavio D. Garcia, Gerhard de Koning Gans, Roel Verdult,
+// and Milosch Meriac. Dismantling iClass and iClass Elite.
#define NUM_CSNS 15
+static uint8_t csns[8 * NUM_CSNS] = {
+ 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
+ 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
+
+
+// pre-defined 9 CSNs by iceman.
+// only one csn depend on several others.
+// six depends only on the first csn, (0,1, 0x45)
+
+// #define NUM_CSNS 9
+// static uint8_t csns[8 * NUM_CSNS] = {
+ // 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x10, 0x97, 0x83, 0x7B, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x13, 0x97, 0x82, 0x7A, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x07, 0x0E, 0x0D, 0xF9, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x14, 0x96, 0x84, 0x76, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0x17, 0x96, 0x85, 0x71, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0xCE, 0xC5, 0x0F, 0x77, 0xF7, 0xFF, 0x12, 0xE0,
+ // 0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0
+ // //0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0
+// };
+
+
int CmdHFiClassSim(const char *Cmd) {
uint8_t simType = 0;
uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0};
}
simType = param_get8ex(Cmd, 0, 0, 10);
- if(simType == 0)
- {
+ if (simType == ICLASS_SIM_MODE_CSN) {
if (param_gethex(Cmd, 1, CSN, 16)) {
PrintAndLog("A CSN should consist of 16 HEX symbols");
return usage_hf_iclass_sim();
}
-
PrintAndLog("--simtype:%02x csn:%s", simType, sprint_hex(CSN, 8));
}
- if(simType > 3)
- {
- PrintAndLog("Undefined simptype %d", simType);
- return usage_hf_iclass_sim();
- }
- uint8_t numberOfCSNs=0;
- if(simType == 2)
- {
- UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,NUM_CSNS}};
+ uint8_t numberOfCSNs = 0;
+ if (simType == ICLASS_SIM_MODE_READER_ATTACK) {
+ UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType, NUM_CSNS}};
UsbCommand resp = {0};
- uint8_t csns[8*NUM_CSNS] = {
- 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x04, 0x0E, 0x08, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x09, 0x0D, 0x05, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x0A, 0x0C, 0x06, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x0F, 0x0B, 0x03, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x08, 0x0A, 0x0C, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x0D, 0x09, 0x09, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x0E, 0x08, 0x0A, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x03, 0x07, 0x17, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x3C, 0x06, 0xE0, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x01, 0x05, 0x1D, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0,
- 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 };
-
- memcpy(c.d.asBytes, csns, 8*NUM_CSNS);
+ memcpy(c.d.asBytes, csns, 8 * NUM_CSNS);
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, -1)) {
}
uint8_t num_mac_responses = resp.arg[1];
- PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses,NUM_CSNS);
+ PrintAndLog("Mac responses: %d MACs obtained (should be %d)", num_mac_responses, NUM_CSNS);
- size_t datalen = NUM_CSNS*24;
+ size_t datalen = NUM_CSNS * 24;
/*
* Now, time to dump to file. We'll use this format:
* <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>....
* 8 * 24 bytes.
*
* The returndata from the pm3 is on the following format
- * <4 byte NR><4 byte MAC>
- * CC are all zeroes, CSN is the same as was sent in
+ * <8 byte CC><4 byte NR><4 byte MAC>
+ * CSN is the same as was sent in
**/
void* dump = malloc(datalen);
- memset(dump,0,datalen);//<-- Need zeroes for the CC-field
- uint8_t i = 0;
- for(i = 0 ; i < NUM_CSNS ; i++)
- {
- memcpy(dump+i*24, csns+i*8,8); //CSN
- //8 zero bytes here...
+ for(int i = 0; i < NUM_CSNS; i++) {
+ memcpy(dump + i*24, csns+i*8, 8); //CSN
+ //copy CC from response
+ memcpy(dump + i*24 + 8, resp.d.asBytes + i*16, 8);
//Then comes NR_MAC (eight bytes from the response)
- memcpy(dump+i*24+16,resp.d.asBytes+i*8,8);
-
+ memcpy(dump + i*24 + 16, resp.d.asBytes + i*16 + 8, 8);
}
/** Now, save to dumpfile **/
saveFile("iclass_mac_attack", "bin", dump,datalen);
free(dump);
- }else
- {
- UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType,numberOfCSNs}};
+
+ } else if (simType == ICLASS_SIM_MODE_CSN || simType == ICLASS_SIM_MODE_CSN_DEFAULT) {
+ UsbCommand c = {CMD_SIMULATE_TAG_ICLASS, {simType, numberOfCSNs}};
memcpy(c.d.asBytes, CSN, 8);
SendCommand(&c);
+
+ } else {
+ PrintAndLog("Undefined simtype %d", simType);
+ return usage_hf_iclass_sim();
}
return 0;
//File handling and reading
FILE *f;
char filename[FILE_PATH_SIZE];
- if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0)
+ if(opt == 'f' && param_getstr(Cmd, 1, filename, sizeof(filename)) > 0)
{
f = fopen(filename, "rb");
}else{
//Open the tagdump-file
FILE *f;
char filename[FILE_PATH_SIZE];
- if(opt == 'f' && param_getstr(Cmd, 1, filename) > 0) {
+ if(opt == 'f' && param_getstr(Cmd, 1, filename, sizeof(filename)) > 0) {
f = fopen(filename, "rb");
if ( f == NULL ) {
PrintAndLog("Could not find file %s", filename);
fseek(f, 0, SEEK_SET);
uint8_t enc_dump[8] = {0};
uint8_t *decrypted = malloc(fsize);
- des3_context ctx = { DES_DECRYPT ,{ 0 } };
- des3_set2key_dec( &ctx, key);
+ mbedtls_des3_context ctx = { {0} };
+ mbedtls_des3_set2key_dec( &ctx, key);
size_t bytes_read = fread(enc_dump, 1, 8, f);
//Use the first block (CSN) for filename
{
memcpy(decrypted+(blocknum*8), enc_dump, 8);
}else{
- des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
+ mbedtls_des3_crypt_ecb(&ctx, enc_dump,decrypted +(blocknum*8) );
}
printvar("decrypted block", decrypted +(blocknum*8), 8);
bytes_read = fread(enc_dump, 1, 8, f);
uint8_t encryptedData[16];
uint8_t *encrypted = encryptedData;
- des3_context ctx = { DES_DECRYPT ,{ 0 } };
- des3_set2key_enc( &ctx, key);
+ mbedtls_des3_context ctx = { {0} };
+ mbedtls_des3_set2key_enc( &ctx, key);
- des3_crypt_ecb(&ctx, blkData,encrypted);
+ mbedtls_des3_crypt_ecb(&ctx, blkData,encrypted);
//printvar("decrypted block", decrypted, 8);
memcpy(blkData,encrypted,8);
memcpy(div_key, KEY, 8);
else
HFiClassCalcDivKey(CSN, KEY, div_key, elite);
- 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]);
+ 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]);
doMAC(CCNR, div_key, MAC);
UsbCommand resp;
SendCommand(&d);
if (!WaitForResponseTimeout(CMD_ACK,&resp,4500))
{
- PrintAndLog("Auth Command execute timeout");
+ if (verbose) PrintAndLog("Auth Command execute timeout");
return false;
}
uint8_t isOK = resp.arg[0] & 0xff;
if (!isOK) {
- PrintAndLog("Authentication error");
+ if (verbose) PrintAndLog("Authentication error");
return false;
}
return true;
case 'c':
case 'C':
have_credit_key = true;
- dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+ dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
if (dataLen == 16) {
errors = param_gethex(tempStr, 0, CreditKEY, dataLen);
} else if (dataLen == 1) {
break;
case 'f':
case 'F':
- fileNameLen = param_getstr(Cmd, cmdp+1, filename);
+ fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
if (fileNameLen < 1) {
PrintAndLog("No filename found after f");
errors = true;
case 'k':
case 'K':
have_debit_key = true;
- dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+ dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
if (dataLen == 16) {
errors = param_gethex(tempStr, 0, KEY, dataLen);
} else if (dataLen == 1) {
SendCommand(&c);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
PrintAndLog("Command execute timeout");
- ul_switch_off_field();
+ DropField();
return 0;
}
uint8_t readStatus = resp.arg[0] & 0xff;
if(readStatus == 0){
PrintAndLog("No tag found...");
- ul_switch_off_field();
+ DropField();
return 0;
}
if( readStatus & (FLAG_ICLASS_READER_CSN|FLAG_ICLASS_READER_CONF|FLAG_ICLASS_READER_CC)){
// large memory - not able to dump pages currently
if (numblks > maxBlk) numblks = maxBlk;
}
- ul_switch_off_field();
+ DropField();
// authenticate debit key and get div_key - later store in dump block 3
if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
//try twice - for some reason it sometimes fails the first time...
if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, false)){
- ul_switch_off_field();
+ DropField();
return 0;
}
}
SendCommand(&w);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
PrintAndLog("Command execute time-out 1");
- ul_switch_off_field();
+ DropField();
return 1;
}
uint32_t blocksRead = resp.arg[1];
uint8_t isOK = resp.arg[0] & 0xff;
if (!isOK && !blocksRead) {
PrintAndLog("Read Block Failed");
- ul_switch_off_field();
+ DropField();
return 0;
}
uint32_t startindex = resp.arg[2];
blocksRead = (sizeof(tag_data)/8) - blockno;
}
// response ok - now get bigbuf content of the dump
- GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex);
- WaitForResponse(CMD_ACK,NULL);
+ GetFromBigBuf(tag_data+(blockno*8), blocksRead*8, startindex, NULL, -1, false);
size_t gotBytes = blocksRead*8 + blockno*8;
// try AA2
if (have_credit_key) {
//turn off hf field before authenticating with different key
- ul_switch_off_field();
+ DropField();
memset(MAC,0,4);
// AA2 authenticate credit key and git c_div_key - later store in dump block 4
if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
//try twice - for some reason it sometimes fails the first time...
if (!select_and_auth(CreditKEY, MAC, c_div_key, true, false, false, false)){
- ul_switch_off_field();
+ DropField();
return 0;
}
}
SendCommand(&w);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
PrintAndLog("Command execute timeout 2");
- ul_switch_off_field();
+ DropField();
return 0;
}
uint8_t isOK = resp.arg[0] & 0xff;
blocksRead = resp.arg[1];
if (!isOK && !blocksRead) {
PrintAndLog("Read Block Failed 2");
- ul_switch_off_field();
+ DropField();
return 0;
}
blocksRead = (sizeof(tag_data) - gotBytes)/8;
}
// get dumped data from bigbuf
- GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex);
- WaitForResponse(CMD_ACK,NULL);
+ GetFromBigBuf(tag_data+gotBytes, blocksRead*8, startindex, NULL, -1, false);
gotBytes += blocksRead*8;
} else { //field is still on - turn it off...
- ul_switch_off_field();
+ DropField();
}
}
break;
case 'k':
case 'K':
- dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+ dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
if (dataLen == 16) {
errors = param_gethex(tempStr, 0, KEY, dataLen);
} else if (dataLen == 1) {
if (cmdp < 6) return usage_hf_iclass_writeblock();
int ans = WriteBlock(blockno, bldata, KEY, use_credit_key, elite, rawkey, true);
- ul_switch_off_field();
+ DropField();
return ans;
}
break;
case 'f':
case 'F':
- fileNameLen = param_getstr(Cmd, cmdp+1, filename);
+ fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
if (fileNameLen < 1) {
PrintAndLog("No filename found after f");
errors = true;
break;
case 'k':
case 'K':
- dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+ dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
if (dataLen == 16) {
errors = param_gethex(tempStr, 0, KEY, dataLen);
} else if (dataLen == 1) {
case 'k':
case 'K':
auth = true;
- dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+ dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
if (dataLen == 16) {
errors = param_gethex(tempStr, 0, KEY, dataLen);
} else if (dataLen == 1) {
return 0;
}
char fileName[255] = {0};
- if(opt == 'f')
- {
- if(param_getstr(Cmd, 1, fileName) > 0)
- {
+ if(opt == 'f') {
+ if(param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0) {
return bruteforceFileNoKeys(fileName);
- }else
- {
+ } else {
PrintAndLog("You must specify a filename");
}
- }
- else if(opt == 't')
- {
+ } else if(opt == 't') {
int errors = testCipherUtils();
errors += testMAC();
errors += doKeyTests(0);
errors += testElite();
- if(errors)
- {
+ if(errors) {
prnlog("OBS! There were errors!!!");
}
return errors;
char tempnum[5];
FILE *f;
char filename[FILE_PATH_SIZE];
- if (param_getstr(Cmd, 0, filename) < 1)
+ if (param_getstr(Cmd, 0, filename, sizeof(filename)) < 1)
return usage_hf_iclass_readtagfile();
- if (param_getstr(Cmd,1,(char *)&tempnum) < 1)
+ if (param_getstr(Cmd, 1, tempnum, sizeof(tempnum)) < 1)
startblock = 0;
else
sscanf(tempnum,"%d",&startblock);
- if (param_getstr(Cmd,2,(char *)&tempnum) < 1)
+ if (param_getstr(Cmd,2, tempnum, sizeof(tempnum)) < 1)
endblock = 0;
else
sscanf(tempnum,"%d",&endblock);
return usage_hf_iclass_calc_newkey();
case 'e':
case 'E':
- dataLen = param_getstr(Cmd, cmdp, tempStr);
+ dataLen = param_getstr(Cmd, cmdp, tempStr, sizeof(tempStr));
if (dataLen==2)
oldElite = true;
elite = true;
break;
case 'n':
case 'N':
- dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+ dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
if (dataLen == 16) {
errors = param_gethex(tempStr, 0, NEWKEY, dataLen);
} else if (dataLen == 1) {
break;
case 'o':
case 'O':
- dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+ dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
if (dataLen == 16) {
errors = param_gethex(tempStr, 0, OLDKEY, dataLen);
} else if (dataLen == 1) {
return usage_hf_iclass_managekeys();
case 'f':
case 'F':
- fileNameLen = param_getstr(Cmd, cmdp+1, filename);
+ fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
if (fileNameLen < 1) {
PrintAndLog("No filename found after f");
errors = true;
case 'k':
case 'K':
operation += 3; //set key
- dataLen = param_getstr(Cmd, cmdp+1, tempStr);
+ dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr));
if (dataLen == 16) { //ul-c or ev1/ntag key length
errors = param_gethex(tempStr, 0, KEY, dataLen);
} else {
return 0;
}
+int CmdHFiClassCheckKeys(const char *Cmd) {
+
+ uint8_t mac[4] = {0x00,0x00,0x00,0x00};
+ uint8_t key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+ uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
+
+ // elite key, raw key, standard key
+ bool use_elite = false;
+ bool use_raw = false;
+ bool found_debit = false;
+ bool found_credit = false;
+ bool errors = false;
+ uint8_t cmdp = 0x00;
+ FILE * f;
+ char filename[FILE_PATH_SIZE] = {0};
+ uint8_t fileNameLen = 0;
+ char buf[17];
+ uint8_t *keyBlock = NULL, *p;
+ int keyitems = 0, keycnt = 0;
+
+ while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
+ switch (param_getchar(Cmd, cmdp)) {
+ case 'h':
+ case 'H':
+ return usage_hf_iclass_chk();
+ case 'f':
+ case 'F':
+ fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename));
+ if (fileNameLen < 1) {
+ PrintAndLog("No filename found after f");
+ errors = true;
+ }
+ cmdp += 2;
+ break;
+ case 'e':
+ case 'E':
+ use_elite = true;
+ cmdp++;
+ break;
+ case 'r':
+ case 'R':
+ use_raw = true;
+ cmdp++;
+ break;
+ default:
+ PrintAndLog("Unknown parameter '%c'\n", param_getchar(Cmd, cmdp));
+ errors = true;
+ break;
+ }
+ }
+ if (errors) return usage_hf_iclass_chk();
+
+ if ( !(f = fopen( filename , "r")) ) {
+ PrintAndLog("File: %s: not found or locked.", filename);
+ return 1;
+ }
+
+ while( fgets(buf, sizeof(buf), f) ){
+ if (strlen(buf) < 16 || buf[15] == '\n')
+ continue;
+
+ while (fgetc(f) != '\n' && !feof(f)) ; //goto next line
+
+ if( buf[0]=='#' ) continue; //The line start with # is comment, skip
+
+ if (!isxdigit(buf[0])){
+ PrintAndLog("File content error. '%s' must include 16 HEX symbols",buf);
+ continue;
+ }
+
+ buf[16] = 0;
+
+ p = realloc(keyBlock, 8 * (keyitems += 64));
+ if (!p) {
+ PrintAndLog("Cannot allocate memory for default keys");
+ free(keyBlock);
+ fclose(f);
+ return 2;
+ }
+ keyBlock = p;
+
+ memset(keyBlock + 8 * keycnt, 0, 8);
+ num_to_bytes(strtoull(buf, NULL, 16), 8, keyBlock + 8 * keycnt);
+
+ //PrintAndLog("check key[%2d] %016" PRIx64, keycnt, bytes_to_num(keyBlock + 8*keycnt, 8));
+ keycnt++;
+ memset(buf, 0, sizeof(buf));
+ }
+ fclose(f);
+ PrintAndLog("Loaded %2d keys from %s", keycnt, filename);
+
+ // time
+ uint64_t t1 = msclock();
+
+ for (uint32_t c = 0; c < keycnt; c += 1) {
+ printf("."); fflush(stdout);
+ if (ukbhit()) {
+ int gc = getchar(); (void)gc;
+ printf("\naborted via keyboard!\n");
+ break;
+ }
+
+ memcpy(key, keyBlock + 8 * c , 8);
+
+ // debit key. try twice
+ for (int foo = 0; foo < 2 && !found_debit; foo++) {
+ if (!select_and_auth(key, mac, div_key, false, use_elite, use_raw, false))
+ continue;
+
+ // key found.
+ PrintAndLog("\n--------------------------------------------------------");
+ PrintAndLog(" Found AA1 debit key\t\t[%s]", sprint_hex(key, 8));
+ found_debit = true;
+ }
+
+ // credit key. try twice
+ for (int foo = 0; foo < 2 && !found_credit; foo++) {
+ if (!select_and_auth(key, mac, div_key, true, use_elite, use_raw, false))
+ continue;
+
+ // key found
+ PrintAndLog("\n--------------------------------------------------------");
+ PrintAndLog(" Found AA2 credit key\t\t[%s]", sprint_hex(key, 8));
+ found_credit = true;
+ }
+
+ // both keys found.
+ if ( found_debit && found_credit )
+ break;
+ }
+
+ t1 = msclock() - t1;
+
+ PrintAndLog("\nTime in iclass checkkeys: %.0f seconds\n", (float)t1/1000.0);
+
+ DropField();
+ free(keyBlock);
+ PrintAndLog("");
+ return 0;
+}
+
static command_t CommandTable[] =
{
{"help", CmdHelp, 1, "This help"},
{"calcnewkey", CmdHFiClassCalcNewKey, 1, "[options..] Calc Diversified keys (blocks 3 & 4) to write new keys"},
+ {"chk", CmdHFiClassCheckKeys, 0, " Check keys"},
{"clone", CmdHFiClassCloneTag, 0, "[options..] Authenticate and Clone from iClass bin file"},
{"decrypt", CmdHFiClassDecrypt, 1, "[f <fname>] Decrypt tagdump" },
{"dump", CmdHFiClassReader_Dump, 0, "[options..] Authenticate and Dump iClass tag's AA1"},
int CmdHFiClass(const char *Cmd)
{
+ clearCommandBuffer();
CmdsParse(CommandTable, Cmd);
return 0;
}