rework iclass dump

This commit is contained in:
iceman1001 2020-07-13 12:29:31 +02:00
commit 52e9d7a750
2 changed files with 102 additions and 85 deletions

View file

@ -1112,7 +1112,7 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) {
return PM3_SUCCESS; return PM3_SUCCESS;
} }
static void Calc_wb_mac(uint8_t blockno, uint8_t *data, uint8_t *div_key, uint8_t MAC[4]) { static void calc_wb_mac(uint8_t blockno, uint8_t *data, uint8_t *div_key, uint8_t *MAC) {
uint8_t wb[9]; uint8_t wb[9];
wb[0] = blockno; wb[0] = blockno;
memcpy(wb + 1, data, 8); memcpy(wb + 1, data, 8);
@ -1120,24 +1120,25 @@ static void Calc_wb_mac(uint8_t blockno, uint8_t *data, uint8_t *div_key, uint8_
} }
static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose) { static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool verbose) {
PacketResponseNG resp;
uint8_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
uint8_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
if (use_credit_key) if (use_credit_key)
flags |= FLAG_ICLASS_READER_CEDITKEY; flags |= FLAG_ICLASS_READER_CEDITKEY;
clearCommandBuffer(); clearCommandBuffer();
PacketResponseNG resp;
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
PrintAndLogEx(WARNING, "command execute timeout"); PrintAndLogEx(WARNING, "command execute timeout");
return false; return false;
} }
uint8_t isOK = resp.oldarg[0] & 0xff; uint8_t isok = resp.oldarg[0] & 0xff;
if (isOK == 0xFF) { // no tag found or button pressed
if ((isok == 0) || isok == 0xFF) {
if (verbose) { if (verbose) {
PrintAndLogEx(FAILED, "failed tag-select, aborting... (%d)", isOK); PrintAndLogEx(FAILED, "failed tag-select, aborting... (%d)", isok);
} }
return false; return false;
} }
@ -1159,17 +1160,12 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v
static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool use_credit_key, bool elite, bool rawkey, bool verbose) { static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool use_credit_key, bool elite, bool rawkey, bool verbose) {
struct { iclass_auth_req_t payload = {
uint8_t key[8]; .use_raw = rawkey,
bool use_raw; .use_elite = elite,
bool use_elite; .use_credit_key = use_credit_key
bool use_credit_key; };
} PACKED payload;
memcpy(payload.key, KEY, 8); memcpy(payload.key, KEY, 8);
payload.use_raw = rawkey;
payload.use_elite = elite;
payload.use_credit_key = use_credit_key;
SendCommandNG(CMD_HF_ICLASS_AUTH, (uint8_t*)&payload, sizeof(payload)); SendCommandNG(CMD_HF_ICLASS_AUTH, (uint8_t*)&payload, sizeof(payload));
PacketResponseNG resp; PacketResponseNG resp;
@ -1184,12 +1180,7 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
return false; return false;
} }
struct p { iclass_auth_resp_t *packet = (iclass_auth_resp_t *)resp.data.asBytes;
bool isOK;
uint8_t div_key[8];
uint8_t mac[4];
} PACKED;
struct p *packet = (struct p *)resp.data.asBytes;
if (packet->isOK == 0) { if (packet->isOK == 0) {
if (verbose) PrintAndLogEx(FAILED, "authentication error"); if (verbose) PrintAndLogEx(FAILED, "authentication error");
@ -1206,7 +1197,7 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
return true; return true;
} }
static int CmdHFiClassReader_Dump(const char *Cmd) { static int CmdHFiClassDump(const char *Cmd) {
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
@ -1245,6 +1236,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
keyNbr = param_get8(Cmd, cmdp + 1); keyNbr = param_get8(Cmd, cmdp + 1);
if (keyNbr < ICLASS_KEYS_MAX) { if (keyNbr < ICLASS_KEYS_MAX) {
memcpy(CreditKEY, iClass_Key_Table[keyNbr], 8); memcpy(CreditKEY, iClass_Key_Table[keyNbr], 8);
PrintAndLogEx(INFO, "AA2 (credit) index %u", keyNbr);
} else { } else {
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
errors = true; errors = true;
@ -1277,6 +1269,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
keyNbr = param_get8(Cmd, cmdp + 1); keyNbr = param_get8(Cmd, cmdp + 1);
if (keyNbr < ICLASS_KEYS_MAX) { if (keyNbr < ICLASS_KEYS_MAX) {
memcpy(KEY, iClass_Key_Table[keyNbr], 8); memcpy(KEY, iClass_Key_Table[keyNbr], 8);
PrintAndLogEx(INFO, "AA1 (debit) index %u", keyNbr);
} else { } else {
PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n"); PrintAndLogEx(WARNING, "\nERROR: Credit KeyNbr is invalid\n");
errors = true; errors = true;
@ -1307,12 +1300,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
// if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work) // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work)
if (!have_debit_key && have_credit_key) use_credit_key = true; if (!have_debit_key && have_credit_key) use_credit_key = true;
uint32_t flags = ( uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
FLAG_ICLASS_READER_INIT |
FLAG_ICLASS_READER_CLEARTRACE |
FLAG_ICLASS_READER_ONLY_ONCE
);
//get config and first 3 blocks //get config and first 3 blocks
PacketResponseNG resp; PacketResponseNG resp;
@ -1320,7 +1308,7 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0); SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
PrintAndLogEx(WARNING, "command execute timeout"); PrintAndLogEx(WARNING, "command execute timeout");
DropField(); DropField();
return PM3_ESOFT; return PM3_ESOFT;
@ -1346,21 +1334,22 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
} }
// authenticate debit key and get div_key - later store in dump block 3 // authenticate debit key and get div_key - later store in dump block 3
int numberAuthRetries = ICLASS_AUTH_RETRY; if (select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose) == false) {
do {
if (select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose))
break;
} while (numberAuthRetries--);
if (numberAuthRetries <= 0) {
PrintAndLogEx(WARNING, "failed authenticating with debit key"); PrintAndLogEx(WARNING, "failed authenticating with debit key");
DropField(); DropField();
return PM3_ESOFT; return PM3_ESOFT;
} }
// begin dump struct {
uint8_t start_blockno;
uint8_t numblks;
} PACKED payload;
payload.start_blockno = blockno;
payload.numblks = numblks - blockno + 1;
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ICLASS_DUMP, blockno, numblks - blockno + 1, 0, NULL, 0); SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t*)&payload, sizeof(payload));
while (true) { while (true) {
printf("."); printf(".");
fflush(stdout); fflush(stdout);
@ -1371,47 +1360,53 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
return PM3_EOPABORTED; return PM3_EOPABORTED;
} }
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) if (WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000))
break; break;
} }
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to communicate with card");
return resp.status;
}
// dump cmd switch off at device when finised. // dump cmd switch off at device when finised.
uint32_t blocksRead = resp.oldarg[1]; struct p_resp {
uint8_t isOK = resp.oldarg[0] & 0xff; bool isOK;
if (!isOK && !blocksRead) { uint8_t block_cnt;
uint32_t bb_offset;
} PACKED;
struct p_resp *packet = (struct p_resp *)resp.data.asBytes;
uint32_t blocks_read = packet->block_cnt;
if (packet->isOK == false) {
PrintAndLogEx(WARNING, "read block failed"); PrintAndLogEx(WARNING, "read block failed");
return PM3_ESOFT; return PM3_ESOFT;
} }
uint32_t startindex = resp.oldarg[2]; uint32_t startindex = packet->bb_offset;
if (blocksRead * 8 > sizeof(tag_data) - (blockno * 8)) {
if (blocks_read * 8 > sizeof(tag_data) - (blockno * 8)) {
PrintAndLogEx(FAILED, "data exceeded buffer size!"); PrintAndLogEx(FAILED, "data exceeded buffer size!");
blocksRead = (sizeof(tag_data) / 8) - blockno; blocks_read = (sizeof(tag_data) / 8) - blockno;
} }
// response ok - now get bigbuf content of the dump // response ok - now get bigbuf content of the dump
if (!GetFromDevice(BIG_BUF, tag_data + (blockno * 8), blocksRead * 8, startindex, NULL, 0, NULL, 2500, false)) { if (!GetFromDevice(BIG_BUF, tag_data + (blockno * 8), blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out"); PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
size_t gotBytes = blocksRead * 8 + blockno * 8; size_t gotBytes = blocks_read * 8 + blockno * 8;
// try AA2 // try AA2 Kc, Credit
if (have_credit_key) { if (have_credit_key) {
//turn off hf field before authenticating with different key
DropField();
memset(MAC, 0, 4); memset(MAC, 0, 4);
// AA2 authenticate credit key and git c_div_key - later store in dump block 4 // AA2 authenticate credit key and git c_div_key - later store in dump block 4
numberAuthRetries = ICLASS_AUTH_RETRY; if (select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, verbose) == false) {
do {
if (select_and_auth(CreditKEY, MAC, c_div_key, true, elite, rawkey, verbose))
break;
} while (numberAuthRetries--);
if (numberAuthRetries <= 0) {
PrintAndLogEx(WARNING, "failed authenticating with credit key"); PrintAndLogEx(WARNING, "failed authenticating with credit key");
DropField(); DropField();
return PM3_ESOFT; return PM3_ESOFT;
@ -1419,32 +1414,43 @@ static int CmdHFiClassReader_Dump(const char *Cmd) {
// do we still need to read more block? (aa2 enabled?) // do we still need to read more block? (aa2 enabled?)
if (maxBlk > blockno + numblks + 1) { if (maxBlk > blockno + numblks + 1) {
// setup dump and start
payload.start_blockno = blockno + blocks_read;
payload.numblks = maxBlk - (blockno + blocks_read);
clearCommandBuffer(); clearCommandBuffer();
SendCommandMIX(CMD_HF_ICLASS_DUMP, blockno + blocksRead, maxBlk - (blockno + blocksRead), 0, NULL, 0); SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t*)&payload, sizeof(payload));
if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) {
if (!WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000)) {
PrintAndLogEx(WARNING, "command execute timeout 2"); PrintAndLogEx(WARNING, "command execute timeout 2");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
isOK = resp.oldarg[0] & 0xff;
blocksRead = resp.oldarg[1]; if (resp.status != PM3_SUCCESS) {
if (!isOK && !blocksRead) { PrintAndLogEx(ERR, "failed to communicate with card");
PrintAndLogEx(WARNING, "read block failed 2"); return resp.status;
}
packet = (struct p_resp *)resp.data.asBytes;
if (packet->isOK == false) {
PrintAndLogEx(WARNING, "read block failed using credit key");
return PM3_ESOFT; return PM3_ESOFT;
} }
startindex = resp.oldarg[2]; blocks_read = packet->block_cnt;
if (blocksRead * 8 > sizeof(tag_data) - gotBytes) { startindex = packet->bb_offset;
if (blocks_read * 8 > sizeof(tag_data) - gotBytes) {
PrintAndLogEx(FAILED, "data exceeded buffer size!"); PrintAndLogEx(FAILED, "data exceeded buffer size!");
blocksRead = (sizeof(tag_data) - gotBytes) / 8; blocks_read = (sizeof(tag_data) - gotBytes) / 8;
} }
// get dumped data from bigbuf // get dumped data from bigbuf
if (!GetFromDevice(BIG_BUF, tag_data + gotBytes, blocksRead * 8, startindex, NULL, 0, NULL, 2500, false)) { if (!GetFromDevice(BIG_BUF, tag_data + gotBytes, blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out"); PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
gotBytes += blocksRead * 8; gotBytes += blocks_read * 8;
} }
} }
@ -1485,13 +1491,13 @@ static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_c
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) { if (select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose) == false) {
numberAuthRetries--; numberAuthRetries--;
DropField(); DropField();
continue; continue;
} }
Calc_wb_mac(blockno, bldata, div_key, MAC); calc_wb_mac(blockno, bldata, div_key, MAC);
struct p { struct p {
uint8_t blockno; uint8_t blockno;
@ -1506,7 +1512,7 @@ static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_c
SendCommandNG(CMD_HF_ICLASS_WRITEBL, (uint8_t *)&payload, sizeof(payload)); SendCommandNG(CMD_HF_ICLASS_WRITEBL, (uint8_t *)&payload, sizeof(payload));
PacketResponseNG resp; PacketResponseNG resp;
if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 4000) == 0) { if (WaitForResponseTimeout(CMD_HF_ICLASS_WRITEBL, &resp, 2000) == 0) {
if (verbose) PrintAndLogEx(WARNING, "Command execute timeout"); if (verbose) PrintAndLogEx(WARNING, "Command execute timeout");
DropField(); DropField();
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
@ -1767,7 +1773,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
// calculate all mac for every the block we will write // calculate all mac for every the block we will write
for (i = startblock; i <= endblock; i++) { for (i = startblock; i <= endblock; i++) {
Calc_wb_mac(i, tag_data[i - startblock].d, div_key, MAC); calc_wb_mac(i, tag_data[i - startblock].d, div_key, MAC);
// usb command d start pointer = d + (i - 6) * 12 // usb command d start pointer = d + (i - 6) * 12
// memcpy(pointer,tag_data[i - 6],8) 8 bytes // memcpy(pointer,tag_data[i - 6],8) 8 bytes
// memcpy(pointer + 8,mac,sizoof(mac) 4 bytes; // memcpy(pointer + 8,mac,sizoof(mac) 4 bytes;
@ -1806,7 +1812,7 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
clearCommandBuffer(); clearCommandBuffer();
SendCommandNG(CMD_HF_ICLASS_CLONE, (uint8_t *)&payload, total_bytes + 2); SendCommandNG(CMD_HF_ICLASS_CLONE, (uint8_t *)&payload, total_bytes + 2);
if (WaitForResponseTimeout(CMD_HF_ICLASS_CLONE, &resp, 4500) == 0) { if (WaitForResponseTimeout(CMD_HF_ICLASS_CLONE, &resp, 2000) == 0) {
PrintAndLogEx(WARNING, "command execute timeout"); PrintAndLogEx(WARNING, "command execute timeout");
DropField(); DropField();
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
@ -1829,7 +1835,6 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
bool isOK; bool isOK;
uint8_t blockdata[8]; uint8_t blockdata[8];
} PACKED; } PACKED;
struct p *result = NULL; struct p *result = NULL;
do { do {
@ -1837,7 +1842,7 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
if (auth || blockno >= 2) { if (auth || blockno >= 2) {
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (!select_and_auth(KEY, MAC, div_key, (keyType == 0x18), elite, rawkey, verbose)) { if (select_and_auth(KEY, MAC, div_key, (keyType == 0x18), elite, rawkey, verbose) == false) {
numberAuthRetries--; numberAuthRetries--;
DropField(); DropField();
continue; continue;
@ -1845,7 +1850,7 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite,
} else { } else {
uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t CSN[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (!select_only(CSN, CCNR, (keyType == 0x18), verbose)) { if (select_only(CSN, CCNR, (keyType == 0x18), verbose) == false) {
numberAuthRetries--; numberAuthRetries--;
DropField(); DropField();
continue; continue;
@ -2156,6 +2161,7 @@ static int CmdHFiClassCalcNewKey(const char *Cmd) {
bool elite = false; bool elite = false;
bool errors = false; bool errors = false;
uint8_t cmdp = 0; uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) { switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h': case 'h':
@ -2217,9 +2223,9 @@ static int CmdHFiClassCalcNewKey(const char *Cmd) {
} }
if (errors || cmdp < 4) return usage_hf_iclass_calc_newkey(); if (errors || cmdp < 4) return usage_hf_iclass_calc_newkey();
if (!givenCSN) { if (givenCSN == false) {
uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; uint8_t CCNR[12] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
if (!select_only(CSN, CCNR, false, true)) { if (select_only(CSN, CCNR, false, true) == false) {
DropField(); DropField();
return PM3_ESOFT; return PM3_ESOFT;
} }
@ -2512,7 +2518,7 @@ static int CmdHFiClassCheckKeys(const char *Cmd) {
SendCommandOLD(CMD_HF_ICLASS_CHKKEYS, flags, keys, 0, pre + key_offset, 4 * keys); SendCommandOLD(CMD_HF_ICLASS_CHKKEYS, flags, keys, 0, pre + key_offset, 4 * keys);
PacketResponseNG resp; PacketResponseNG resp;
while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { while (!WaitForResponseTimeout(CMD_HF_ICLASS_CHKKEYS, &resp, 2000)) {
timeout++; timeout++;
printf("."); printf(".");
fflush(stdout); fflush(stdout);
@ -2927,7 +2933,7 @@ static command_t CommandTable[] = {
{"chk", CmdHFiClassCheckKeys, AlwaysAvailable, "[options..] Check keys"}, {"chk", CmdHFiClassCheckKeys, AlwaysAvailable, "[options..] Check keys"},
{"clone", CmdHFiClassCloneTag, IfPm3Iclass, "[options..] Restore a dump file onto a iClass tag"}, {"clone", CmdHFiClassCloneTag, IfPm3Iclass, "[options..] Restore a dump file onto a iClass tag"},
{"decrypt", CmdHFiClassDecrypt, AlwaysAvailable, "[options..] Decrypt given block data or tag dump file" }, {"decrypt", CmdHFiClassDecrypt, AlwaysAvailable, "[options..] Decrypt given block data or tag dump file" },
{"dump", CmdHFiClassReader_Dump, IfPm3Iclass, "[options..] Dump iClass tag to file"}, {"dump", CmdHFiClassDump, IfPm3Iclass, "[options..] Dump iClass tag to file"},
{"eload", CmdHFiClassELoad, IfPm3Iclass, "[f <fname>] Load iClass dump file into emulator memory"}, {"eload", CmdHFiClassELoad, IfPm3Iclass, "[f <fname>] Load iClass dump file into emulator memory"},
{"encrypt", CmdHFiClassEncryptBlk, AlwaysAvailable, "[options..] Encrypt given block data"}, {"encrypt", CmdHFiClassEncryptBlk, AlwaysAvailable, "[options..] Encrypt given block data"},
{"info", CmdHFiClassInfo, AlwaysAvailable, " Tag information"}, {"info", CmdHFiClassInfo, AlwaysAvailable, " Tag information"},
@ -2979,8 +2985,6 @@ int readIclass(bool loop, bool verbose) {
uint8_t readStatus = resp.oldarg[0] & 0xff; uint8_t readStatus = resp.oldarg[0] & 0xff;
// PrintAndLogEx(NORMAL, "ICE: %x", readStatus);
// no tag found or button pressed // no tag found or button pressed
if ((readStatus == 0 && !loop) || readStatus == 0xFF) { if ((readStatus == 0 && !loop) || readStatus == 0xFF) {
DropField(); DropField();

View file

@ -27,6 +27,19 @@ typedef struct iclass_prekey {
uint8_t key[8]; uint8_t key[8];
} iclass_prekey_t; } iclass_prekey_t;
typedef struct {
uint8_t key[8];
bool use_raw;
bool use_elite;
bool use_credit_key;
} PACKED iclass_auth_req_t;
typedef struct {
bool isOK;
uint8_t div_key[8];
uint8_t mac[4];
} PACKED iclass_auth_resp_t;
int CmdHFiClass(const char *Cmd); int CmdHFiClass(const char *Cmd);
int readIclass(bool loop, bool verbose); int readIclass(bool loop, bool verbose);