fix auth and

This commit is contained in:
iceman1001
2020-07-19 20:45:47 +02:00
parent 3354f0d9d3
commit a1529b44ca
8 changed files with 367 additions and 257 deletions

View File

@@ -47,7 +47,7 @@ static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = {
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
};
static int usage_hf_iclass_sim(void) {
@@ -379,6 +379,28 @@ static inline uint32_t leadingzeros(uint64_t a) {
#endif
}
// iclass card descriptors
const char * card_types[] = {
"PicoPass 16K / 16", // 000
"PicoPass 32K with current book 16K / 16", // 001
"Unknown Card Type!", // 010
"Unknown Card Type!", // 011
"PicoPass 2K", // 100
"Unknown Card Type!", // 101
"PicoPass 16K / 2", // 110
"PicoPass 32K with current book 16K / 2", // 111
};
uint8_t card_app2_limit[] = {
0xff,
0xff,
0xff,
0xff,
0x1f,
0xff,
0xff,
0xff,
};
static uint8_t isset(uint8_t val, uint8_t mask) {
return (val & mask);
@@ -434,7 +456,7 @@ static void fuse_config(const picopass_hdr *hdr) {
);
}
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) {
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas, uint8_t *kb) {
// mem-bit 5, mem-bit 7, chip-bit 4: defines chip type
uint8_t k16 = isset(mem_cfg, 0x80);
//uint8_t k2 = isset(mem_cfg, 0x08);
@@ -443,47 +465,54 @@ static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, ui
if (isset(chip_cfg, 0x10) && !k16 && !book) {
*kb = 2;
*app_areas = 2;
*max_blk = 31;
} else if (isset(chip_cfg, 0x10) && k16 && !book) {
*kb = 16;
*app_areas = 2;
*max_blk = 255; //16kb
} else if (notset(chip_cfg, 0x10) && !k16 && !book) {
*kb = 16;
*app_areas = 16;
*max_blk = 255; //16kb
} else if (isset(chip_cfg, 0x10) && k16 && book) {
*kb = 32;
*app_areas = 3;
*max_blk = 255; //16kb
} else if (notset(chip_cfg, 0x10) && !k16 && book) {
*kb = 32;
*app_areas = 17;
*max_blk = 255; //16kb
} else {
*kb = 32;
*app_areas = 2;
*max_blk = 255;
}
}
static uint8_t get_mem_config(const picopass_hdr *hdr) {
uint8_t mem = hdr->conf.mem_config;
uint8_t chip = hdr->conf.chip_config;
// three configuration bits that decides sizes
uint8_t type = (chip & 0x10) >> 2;
type |= (mem & 0x80) >> 6;
type |= (mem & 0x20) >> 5;
return type;
}
static void mem_app_config(const picopass_hdr *hdr) {
uint8_t mem = hdr->conf.mem_config;
uint8_t chip = hdr->conf.chip_config;
uint8_t applimit = hdr->conf.app_limit;
uint8_t kb = 2;
uint8_t app_areas = 2;
uint8_t max_blk = 31;
getMemConfig(mem, chip, &max_blk, &app_areas, &kb);
getMemConfig(mem, chip, &app_areas, &kb);
if (applimit < 6) applimit = 26;
if (kb == 2 && (applimit > 0x1f)) applimit = 26;
// three configuration bits that decides sizes
uint8_t type = (chip & 0x10) >> 2;
type |= (mem & 0x80) >> 6;
type |= (mem & 0x20) >> 5;
uint8_t app1_limit = hdr->conf.app_limit - 5; // minus header blocks
uint8_t app2_limit = card_app2_limit[type];
PrintAndLogEx(INFO, "------ " _CYAN_("Memory") " ------");
PrintAndLogEx(INFO, " %u KBits/%u App Areas (%u bytes), max blocks 0x%02X (%02d)", kb, app_areas, max_blk * 8, mem, mem);
PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", applimit - 5 , applimit, applimit);
PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", max_blk - applimit, applimit + 1, max_blk, applimit + 1, max_blk);
PrintAndLogEx(INFO, " %u KBits/%u App Areas (%u bytes)", kb, app_areas, app2_limit * 8);
PrintAndLogEx(INFO, " AA1 blocks %u { 0x06 - 0x%02X (06 - %02d) }", app1_limit , app1_limit + 5, app1_limit + 5);
PrintAndLogEx(INFO, " AA2 blocks %u { 0x%02X - 0x%02X (%02d - %02d) }", app2_limit - app1_limit, app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit);
PrintAndLogEx(INFO, "------ " _CYAN_("KeyAccess") " ------");
PrintAndLogEx(INFO, " Kd = Debit key (AA1), Kc = Credit key (AA2)");
@@ -552,7 +581,15 @@ static int CmdHFiClassSniff(const char *Cmd) {
payload.jam_search_len = sizeof(update_epurse_sequence);
memcpy(payload.jam_search_string, update_epurse_sequence, sizeof(payload.jam_search_string));
}
PacketResponseNG resp;
clearCommandBuffer();
SendCommandNG(CMD_HF_ICLASS_SNIFF, (uint8_t *)&payload, sizeof(payload));
WaitForResponse(CMD_HF_ICLASS_SNIFF, &resp);
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass list") "` to look at the collected trace");
PrintAndLogEx(HINT, "Try `" _YELLOW_("trace save h") "` to save tracelog for later analysing");
return PM3_SUCCESS;
}
@@ -956,6 +993,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
}
if (have_file) {
picopass_hdr *hdr = (picopass_hdr *)decrypted;
uint8_t mem = hdr->conf.mem_config;
@@ -963,10 +1001,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
uint8_t applimit = hdr->conf.app_limit;
uint8_t kb = 2;
uint8_t app_areas = 2;
uint8_t max_blk = 31;
getMemConfig(mem, chip, &max_blk, &app_areas, &kb);
getMemConfig(mem, chip, &app_areas, &kb);
BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03);
@@ -976,7 +1011,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
PrintAndLogEx(WARNING, "Actual file len " _YELLOW_("%zu") " vs HID app-limit len " _YELLOW_("%u"), decryptedlen, applimit * 8);
PrintAndLogEx(INFO, "Setting limit to " _GREEN_("%u"), limit * 8);
}
uint8_t numblocks4userid = GetNumberBlocksForUserId(decrypted + (6 * 8));
//uint8_t numblocks4userid = GetNumberBlocksForUserId(decrypted + (6 * 8));
for (uint16_t blocknum = 0; blocknum < limit; ++blocknum) {
@@ -987,7 +1023,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
continue;
// Decrypted block 7,8,9 if configured.
if (blocknum > 6 && blocknum <= 6 + numblocks4userid && memcmp(enc_data, empty, 8) != 0) {
if (blocknum > 6 && blocknum <= 9 && memcmp(enc_data, empty, 8) != 0) {
if (use_sc) {
Decrypt(enc_data, decrypted + idx);
} else {
@@ -996,13 +1032,14 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
}
}
//Use the first block (CSN) for filename
// use the first block (CSN) for filename
char *fptr = calloc(50, sizeof(uint8_t));
if (!fptr) {
if (fptr == false) {
PrintAndLogEx(WARNING, "Failed to allocate memory");
free(decrypted);
return PM3_EMALLOC;
}
strcat(fptr, "hf-iclass-");
FillFileNameByUID(fptr, hdr->csn, "-dump-decrypted", sizeof(hdr->csn));
@@ -1013,6 +1050,8 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
PrintAndLogEx(INFO, "Following output skips CSN / block0");
printIclassDumpContents(decrypted, 1, (decryptedlen / 8), decryptedlen);
PrintAndLogEx(NORMAL, "");
// decode block 6
if (memcmp(decrypted + (8 * 6), empty, 8) != 0) {
if (use_sc) {
@@ -1029,7 +1068,7 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
mid = bytes_to_num(decrypted + (8 * 7), 4);
bot = bytes_to_num(decrypted + (8 * 7) + 4, 4);
PrintAndLogEx(INFO, "Block 7 binary");
PrintAndLogEx(INFO, "Block 7 decoder");
char hexstr[8 + 1] = {0};
hex_to_buffer((uint8_t *)hexstr, decrypted + (8 * 7), 8, sizeof(hexstr) - 1, 0, 0, true);
@@ -1039,15 +1078,36 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
uint8_t i = 0;
while (i < strlen(binstr) && binstr[i++] == '0');
PrintAndLogEx(SUCCESS, "%s", binstr + i);
PrintAndLogEx(SUCCESS, "Binary..................... " _GREEN_("%s"), binstr + i);
PrintAndLogEx(INFO, "Wiegand decode");
wiegand_message_t packed = initialize_message_object(top, mid, bot);
HIDTryUnpack(&packed, true);
PrintAndLogEx(INFO, "-----------------------------------------------------------------");
} else {
PrintAndLogEx(INFO, "No credential found.");
}
// decode block 9
if (memcmp(decrypted + (8 * 9), empty, 8) != 0) {
uint8_t usr_blk_len = GetNumberBlocksForUserId(decrypted + (8 * 6));
if (usr_blk_len < 3) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "Block 9 decoder");
uint8_t pinsize = 10;
if (use_sc) {
pinsize = GetPinSize(decrypted + (8 * 6));
}
uint64_t pin = bytes_to_num(decrypted + (8 * 9), 5);
char tmp[17] = {0};
sprintf(tmp, "%."PRIu64, BCD2DEC(pin));
PrintAndLogEx(INFO, "PIN........................ " _GREEN_("%.*s"), pinsize, tmp);
}
}
PrintAndLogEx(INFO, "-----------------------------------------------------------------");
free(decrypted);
free(fptr);
@@ -1178,7 +1238,7 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
.use_credit_key = use_credit_key
};
memcpy(payload.key, KEY, 8);
SendCommandNG(CMD_HF_ICLASS_AUTH, (uint8_t*)&payload, sizeof(payload));
PacketResponseNG resp;
clearCommandBuffer();
@@ -1205,7 +1265,9 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u
if (MAC)
memcpy(MAC, packet->mac, sizeof(packet->mac));
if (verbose) PrintAndLogEx(SUCCESS, "authing with %s: %s", rawkey ? "raw key" : "diversified key", sprint_hex(div_key, 8));
if (verbose)
PrintAndLogEx(SUCCESS, "authing with %s: %s", rawkey ? "raw key" : "diversified key", sprint_hex(div_key, 8));
return true;
}
@@ -1214,15 +1276,11 @@ static int CmdHFiClassDump(const char *Cmd) {
uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00};
uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t c_div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t blockno = 0;
uint8_t numblks = 0;
uint8_t maxBlk = 31;
uint8_t app_areas = 1;
uint8_t kb = 2;
uint8_t KEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t CreditKEY[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t keyNbr = 0;
uint8_t dataLen = 0;
uint8_t app_limit1, app_limit2 = 0;
uint8_t fileNameLen = 0;
char filename[FILE_PATH_SIZE] = {0};
char tempStr[50] = {0};
@@ -1329,6 +1387,7 @@ static int CmdHFiClassDump(const char *Cmd) {
uint8_t readStatus = resp.oldarg[0] & 0xff;
uint8_t *data = resp.data.asBytes;
picopass_hdr *hdr = (picopass_hdr *)data;
if (readStatus == 0) {
PrintAndLogEx(FAILED, "no tag found");
@@ -1338,11 +1397,14 @@ static int CmdHFiClassDump(const char *Cmd) {
if (readStatus & (FLAG_ICLASS_CSN | FLAG_ICLASS_CONF | FLAG_ICLASS_CC)) {
memcpy(tag_data, data, 8 * 3);
blockno += 2; // 2 to force re-read of block 2 later. (seems to respond differently..)
numblks = data[8];
getMemConfig(data[13], data[12], &maxBlk, &app_areas, &kb);
// large memory - not able to dump pages currently
if (numblks > maxBlk) numblks = maxBlk;
uint8_t type = get_mem_config(hdr);
app_limit1 = hdr->conf.app_limit;
app_limit2 = card_app2_limit[type];
} else {
PrintAndLogEx(FAILED, "failed to read block 0,1,2");
DropField();
return PM3_ESOFT;
}
// authenticate debit key and get div_key - later store in dump block 3
@@ -1356,8 +1418,8 @@ static int CmdHFiClassDump(const char *Cmd) {
uint8_t start_blockno;
uint8_t numblks;
} PACKED payload;
payload.start_blockno = blockno;
payload.numblks = numblks - blockno + 1;
payload.start_blockno = 5;
payload.numblks = app_limit1 - 5;
clearCommandBuffer();
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t*)&payload, sizeof(payload));
@@ -1397,20 +1459,24 @@ static int CmdHFiClassDump(const char *Cmd) {
return PM3_ESOFT;
}
uint16_t offset = (5 * 8);
uint32_t startindex = packet->bb_offset;
if (blocks_read * 8 > sizeof(tag_data) - (blockno * 8)) {
if (blocks_read * 8 > sizeof(tag_data) - offset) {
PrintAndLogEx(FAILED, "data exceeded buffer size!");
blocks_read = (sizeof(tag_data) / 8) - blockno;
blocks_read = (sizeof(tag_data) / 8) - 5;
}
// response ok - now get bigbuf content of the dump
if (!GetFromDevice(BIG_BUF, tag_data + (blockno * 8), blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
if (!GetFromDevice(BIG_BUF, tag_data + offset, blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
PrintAndLogEx(INFO, "BB start index :: %u", startindex);
PrintAndLogEx(INFO, "BB :: %s", sprint_hex(tag_data + (5*8), 32));
size_t gotBytes = blocks_read * 8 + blockno * 8;
offset += (blocks_read * 8);
// try AA2 Kc, Credit
if (have_credit_key) {
@@ -1424,46 +1490,44 @@ static int CmdHFiClassDump(const char *Cmd) {
return PM3_ESOFT;
}
// do we still need to read more block? (aa2 enabled?)
if (maxBlk > blockno + numblks + 1) {
payload.start_blockno = app_limit1;
payload.numblks = app_limit2 - app_limit1 - 5;
payload.start_blockno = blockno + blocks_read;
payload.numblks = maxBlk - (blockno + blocks_read);
clearCommandBuffer();
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t*)&payload, sizeof(payload));
clearCommandBuffer();
SendCommandNG(CMD_HF_ICLASS_DUMP, (uint8_t*)&payload, sizeof(payload));
if (!WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000)) {
PrintAndLogEx(WARNING, "command execute timeout 2");
return PM3_ETIMEOUT;
}
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to communicate with card");
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;
}
blocks_read = packet->block_cnt;
startindex = packet->bb_offset;
if (blocks_read * 8 > sizeof(tag_data) - gotBytes) {
PrintAndLogEx(FAILED, "data exceeded buffer size!");
blocks_read = (sizeof(tag_data) - gotBytes) / 8;
}
// get dumped data from bigbuf
if (!GetFromDevice(BIG_BUF, tag_data + gotBytes, blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
gotBytes += blocks_read * 8;
if (!WaitForResponseTimeout(CMD_HF_ICLASS_DUMP, &resp, 2000)) {
PrintAndLogEx(WARNING, "command execute timeout 2");
return PM3_ETIMEOUT;
}
if (resp.status != PM3_SUCCESS) {
PrintAndLogEx(ERR, "failed to communicate with card");
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;
}
//
blocks_read = packet->block_cnt;
startindex = packet->bb_offset;
if (blocks_read * 8 > sizeof(tag_data) - offset) {
PrintAndLogEx(FAILED, "data exceeded buffer size!");
blocks_read = (sizeof(tag_data) - offset) / 8;
}
// get dumped data from bigbuf
if (!GetFromDevice(BIG_BUF, tag_data + offset, blocks_read * 8, startindex, NULL, 0, NULL, 2500, false)) {
PrintAndLogEx(WARNING, "command execution time out");
return PM3_ETIMEOUT;
}
offset += blocks_read * 8;
}
DropField();
@@ -1480,7 +1544,7 @@ static int CmdHFiClassDump(const char *Cmd) {
PrintAndLogEx(NORMAL, "");
PrintAndLogEx(INFO, "------+--+-------------------------+----------");
PrintAndLogEx(INFO, " CSN |00| " _GREEN_("%s") "|", sprint_hex(tag_data, 8));
printIclassDumpContents(tag_data, 1, (gotBytes / 8), gotBytes);
printIclassDumpContents(tag_data, 1, (offset / 8), offset);
if (filename[0] == 0) {
//Use the first block (CSN) for filename
@@ -1489,10 +1553,10 @@ static int CmdHFiClassDump(const char *Cmd) {
}
// save the dump to .bin file
PrintAndLogEx(SUCCESS, "saving dump file - %zu blocks read", gotBytes / 8);
saveFile(filename, ".bin", tag_data, gotBytes);
saveFileEML(filename, tag_data, gotBytes, 8);
saveFileJSON(filename, jsfIclass, tag_data, gotBytes, NULL);
PrintAndLogEx(SUCCESS, "saving dump file - %zu blocks read", offset / 8);
saveFile(filename, ".bin", tag_data, offset);
saveFileEML(filename, tag_data, offset, 8);
saveFileJSON(filename, jsfIclass, tag_data, offset, NULL);
return PM3_SUCCESS;
}
@@ -1825,25 +1889,22 @@ static int CmdHFiClassCloneTag(const char *Cmd) {
static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, bool rawkey, bool verbose, bool auth) {
// return data.
struct p {
bool isOK;
uint8_t blockdata[8];
} PACKED;
struct p *result = NULL;
// block 0,1 should always be able to read, and block 5 on some cards.
if (auth || blockno >= 2) {
uint8_t MAC[4] = {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) == false) {
if (verbose) PrintAndLogEx(FAILED, "select/auth failed");
DropField();
return PM3_ESOFT;
}
} else {
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};
if (select_only(CSN, CCNR, (keyType == 0x18), verbose) == false) {
return PM3_ESOFT;
if (verbose) PrintAndLogEx(FAILED, "select only failed");
DropField();
return PM3_ESOFT;
}
}
@@ -1851,22 +1912,29 @@ static int iclass_read_block(uint8_t *KEY, uint8_t blockno, uint8_t keyType, boo
clearCommandBuffer();
SendCommandNG(CMD_HF_ICLASS_READBL, (uint8_t *)&blockno, sizeof(uint8_t));
if (WaitForResponseTimeout(CMD_HF_ICLASS_READBL, &resp, 2000) == 0) {
if (WaitForResponseTimeout(CMD_HF_ICLASS_READBL, &resp, 2000) == false) {
if (verbose) PrintAndLogEx(WARNING, "Command execute timeout");
DropField();
return PM3_ETIMEOUT;
}
DropField();
if (resp.status != PM3_SUCCESS) {
if (verbose) PrintAndLogEx(ERR, "failed to communicate with card");
return PM3_EWRONGANSWER;
}
result = (struct p *)resp.data.asBytes;
if (result->isOK == false)
return PM3_ESOFT;
// return data.
struct p {
bool isOK;
uint8_t blockdata[8];
} PACKED;
DropField();
struct p *result = (struct p *)resp.data.asBytes;
if (result->isOK == false) {
return PM3_ESOFT;
}
PrintAndLogEx(SUCCESS, " block %02X : " _GREEN_("%s"), blockno, sprint_hex(result->blockdata, sizeof(result->blockdata)));
@@ -1943,6 +2011,7 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
bool auth = false;
bool verbose = false;
uint8_t cmdp = 0;
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
switch (tolower(param_getchar(Cmd, cmdp))) {
case 'h':
@@ -2000,10 +2069,10 @@ static int CmdHFiClass_ReadBlock(const char *Cmd) {
if (got_blockno == false)
errors = true;
if (errors || cmdp < 4) return usage_hf_iclass_readblock();
if (errors) return usage_hf_iclass_readblock();
if (!auth)
PrintAndLogEx(FAILED, "warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
if (auth == false)
PrintAndLogEx(WARNING, "warning: no authentication used with read, only a few specific blocks can be read accurately without authentication.");
return iclass_read_block(KEY, blockno, keyType, elite, rawkey, verbose, auth);
}
@@ -2993,6 +3062,20 @@ int CmdHFiClass(const char *Cmd) {
return CmdsParse(CommandTable, Cmd);
}
//static void test_credential_type(void) {
// need AA1 key
// Block 5 -> tells if its a legacy or SIO, also tells which key to use.
// tech | blocks used | desc | num of payloads
// -------+-----------------------+-----------------------------------+------
// legacy | 6,7,8,9 | AA!, Access control payload | 1
// SE | 6,7,8,9,10,11,12 | AA1, Secure identity object (SIO) | 1
// SR | 6,7,8,9, | AA1, Access control payload | 2
// | 10,11,12,13,14,15,16 | AA1, Secure identity object (SIO) |
// SEOS | | |
//}
int readIclass(bool loop, bool verbose) {
bool tagFound = false;
@@ -3079,6 +3162,10 @@ int readIclass(bool loop, bool verbose) {
}
}
uint8_t cardtype = get_mem_config(hdr);
PrintAndLogEx(SUCCESS, "%s", card_types[cardtype]);
if (tagFound && !loop) {
PrintAndLogEx(NORMAL, "");
DropField();

View File

@@ -27,19 +27,6 @@ typedef struct iclass_prekey {
uint8_t key[8];
} 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 readIclass(bool loop, bool verbose);