mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 05:13:46 -07:00
fixes to hf iclass configcard mem setup, textual output, MIX->NG convertion
This commit is contained in:
parent
89554501bb
commit
0a4c9f83ac
9 changed files with 414 additions and 295 deletions
|
@ -23,6 +23,7 @@
|
|||
#include "printf.h"
|
||||
#include "legicrf.h"
|
||||
#include "BigBuf.h"
|
||||
#include "iclass_cmd.h"
|
||||
#include "iso14443a.h"
|
||||
#include "iso14443b.h"
|
||||
#include "iso15693.h"
|
||||
|
@ -1685,7 +1686,8 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_READER: {
|
||||
ReaderIClass(packet->oldarg[0]);
|
||||
iclass_card_select_t *payload = (iclass_card_select_t *) packet->data.asBytes;
|
||||
ReaderIClass(payload->flags);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ICLASS_EML_MEMSET: {
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include "protocols.h"
|
||||
#include "ticks.h"
|
||||
#include "iso15693.h"
|
||||
#include "iclass_cmd.h" /* iclass_card_select_t struct */
|
||||
|
||||
static uint8_t get_pagemap(const picopass_hdr_t *hdr) {
|
||||
return (hdr->conf.fuses & (FUSE_CRYPT0 | FUSE_CRYPT1)) >> 3;
|
||||
|
@ -1402,13 +1403,8 @@ bool select_iclass_tag(picopass_hdr_t *hdr, bool use_credit_key, uint32_t *eof_t
|
|||
// turn off afterwards
|
||||
void ReaderIClass(uint8_t flags) {
|
||||
|
||||
picopass_hdr_t hdr = {0};
|
||||
// uint8_t last_csn[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
|
||||
memset(resp, 0xFF, sizeof(resp));
|
||||
|
||||
// bool flag_readonce = flags & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully
|
||||
bool use_credit_key = flags & FLAG_ICLASS_READER_CREDITKEY; // flag to use credit key
|
||||
// flag to use credit key
|
||||
bool use_credit_key = ((flags & FLAG_ICLASS_READER_CREDITKEY) == FLAG_ICLASS_READER_CREDITKEY);
|
||||
|
||||
if ((flags & FLAG_ICLASS_READER_INIT) == FLAG_ICLASS_READER_INIT) {
|
||||
Iso15693InitReader();
|
||||
|
@ -1418,13 +1414,14 @@ void ReaderIClass(uint8_t flags) {
|
|||
clear_trace();
|
||||
}
|
||||
|
||||
uint8_t result_status = 0;
|
||||
|
||||
uint8_t res = 0;
|
||||
uint32_t eof_time = 0;
|
||||
bool status = select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &result_status);
|
||||
if (status == false) {
|
||||
reply_mix(CMD_ACK, 0xFF, 0, 0, NULL, 0);
|
||||
switch_off();
|
||||
return;
|
||||
picopass_hdr_t hdr = {0};
|
||||
|
||||
if (select_iclass_tag_ex(&hdr, use_credit_key, &eof_time, &res) == false) {
|
||||
reply_ng(CMD_HF_ICLASS_READER, PM3_ERFTRANS, NULL, 0);
|
||||
goto out;
|
||||
}
|
||||
|
||||
// Page mapping for secure mode
|
||||
|
@ -1443,30 +1440,14 @@ void ReaderIClass(uint8_t flags) {
|
|||
// Return to client, e 6 * 8 bytes of data.
|
||||
// with 0xFF:s in block 3 and 4.
|
||||
|
||||
LED_B_ON();
|
||||
reply_mix(CMD_ACK, result_status, 0, 0, (uint8_t *)&hdr, sizeof(hdr));
|
||||
iclass_card_select_resp_t payload = {
|
||||
.status = res
|
||||
};
|
||||
memcpy(&payload.header.hdr, &hdr, sizeof(picopass_hdr_t));
|
||||
|
||||
//Send back to client, but don't bother if we already sent this -
|
||||
// only useful if looping in arm (not try_once && not abort_after_read)
|
||||
/*
|
||||
if (memcmp(last_csn, card_data, 8) != 0) {
|
||||
|
||||
reply_mix(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
|
||||
if (flag_readonce) {
|
||||
LED_B_OFF();
|
||||
return;
|
||||
}
|
||||
LED_B_OFF();
|
||||
}
|
||||
*/
|
||||
|
||||
// if (userCancelled) {
|
||||
// reply_mix(CMD_ACK, 0xFF, 0, 0, card_data, 0);
|
||||
// switch_off();
|
||||
// } else {
|
||||
// reply_mix(CMD_ACK, result_status, 0, 0, card_data, 0);
|
||||
// }
|
||||
reply_ng(CMD_HF_ICLASS_READER, PM3_SUCCESS, (uint8_t*)&payload, sizeof(iclass_card_select_resp_t));
|
||||
|
||||
out:
|
||||
switch_off();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#define __ICLASS_H
|
||||
|
||||
#include "common.h"
|
||||
#include "pm3_cmd.h"
|
||||
#include "iclass_cmd.h"
|
||||
|
||||
void SniffIClass(uint8_t jam_search_len, uint8_t *jam_search_string);
|
||||
void ReaderIClass(uint8_t flags);
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "wiegand_formatutils.h"
|
||||
#include "cmdsmartcard.h" // smart select fct
|
||||
#include "proxendian.h"
|
||||
#include "iclass_cmd.h"
|
||||
|
||||
#define NUM_CSNS 9
|
||||
#define ICLASS_KEYS_MAX 8
|
||||
|
@ -165,7 +166,7 @@ static const char *card_types[] = {
|
|||
};
|
||||
|
||||
static uint8_t card_app2_limit[] = {
|
||||
0xff,
|
||||
0x1f,
|
||||
0xff,
|
||||
0xff,
|
||||
0xff,
|
||||
|
@ -278,7 +279,8 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
|
|||
// calc diversified key for selected card
|
||||
HFiClassCalcDivKey(cc->csn, iClass_Key_Table[0], cc->key_d, false);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "failed to read a card, will use default config card data");
|
||||
PrintAndLogEx(FAILED, "failed to read a card");
|
||||
PrintAndLogEx(INFO,"falling back to default config card");
|
||||
}
|
||||
|
||||
// generate dump file
|
||||
|
@ -323,35 +325,47 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
|
|||
return PM3_EMALLOC;
|
||||
}
|
||||
data = p;
|
||||
memset(data, 0xFF, tot_bytes);
|
||||
}
|
||||
|
||||
memset(data + sizeof(picopass_hdr_t), 0xFF, tot_bytes - sizeof(picopass_hdr_t));
|
||||
|
||||
bool old = GetFlushAfterWrite();
|
||||
SetFlushAfterWrite(true);
|
||||
|
||||
// KEYROLL need to encrypt
|
||||
PrintAndLogEx(INFO, "Setting up encryption... " NOLF);
|
||||
uint8_t ffs[8] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
|
||||
if (Encrypt(ffs, ffs) == false) {
|
||||
PrintAndLogEx(WARNING, "failed to encrypt FF");
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
}
|
||||
|
||||
// local key copy
|
||||
PrintAndLogEx(INFO, "Encrypting local key... " NOLF);
|
||||
uint8_t lkey[8];
|
||||
memcpy(lkey, key, sizeof(lkey));
|
||||
|
||||
uint8_t enckey1[8];
|
||||
if (Encrypt(lkey, enckey1) == false) {
|
||||
PrintAndLogEx(WARNING, "failed to encrypt key1");
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, "Copy data... " NOLF);
|
||||
memcpy(data, cc, sizeof(picopass_hdr_t));
|
||||
memcpy(data + (6 * 8), o->data, sizeof(o->data));
|
||||
|
||||
// encrypted keyroll key 0D
|
||||
memcpy(data + (0xD * 8), enckey1, sizeof(enckey1));
|
||||
// encrypted 0xFF
|
||||
for (uint8_t i = 0xe; i < 0x14; i++) {
|
||||
for (uint8_t i = 0xD; i < 0x14; i++) {
|
||||
memcpy(data + (i * 8), ffs, sizeof(ffs));
|
||||
}
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
|
||||
// encrypted partial keyroll key 14
|
||||
PrintAndLogEx(INFO, "Setting encrypted partial key14... " NOLF);
|
||||
uint8_t foo[8] = {0x15};
|
||||
memcpy(foo + 1, lkey, 7);
|
||||
uint8_t enckey2[8];
|
||||
|
@ -359,34 +373,43 @@ static int generate_config_card(const iclass_config_card_item_t *o, uint8_t *ke
|
|||
PrintAndLogEx(WARNING, "failed to encrypt partial 1");
|
||||
}
|
||||
memcpy(data + (0x14 * 8), enckey2, sizeof(enckey2));
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
|
||||
|
||||
// encrypted partial keyroll key 15
|
||||
PrintAndLogEx(INFO, "Setting encrypted partial key15... " NOLF);
|
||||
memset(foo, 0xFF, sizeof(foo));
|
||||
foo[0] = lkey[7];
|
||||
if (Encrypt(foo, enckey2) == false) {
|
||||
PrintAndLogEx(WARNING, "failed to encrypt partial 2");
|
||||
}
|
||||
memcpy(data + (0x15 * 8), enckey2, sizeof(enckey2));
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
|
||||
// encrypted 0xFF
|
||||
PrintAndLogEx(INFO, "Setting 0xFF's... " NOLF);
|
||||
for (uint8_t i = 0x16; i <= app1_limit; i++) {
|
||||
memcpy(data + (i * 8), ffs, sizeof(ffs));
|
||||
}
|
||||
PrintAndLogEx(NORMAL,"( " _GREEN_("ok") " )");
|
||||
|
||||
// revert potential modified app1_limit
|
||||
cc->conf.app_limit = old_limit;
|
||||
|
||||
SetFlushAfterWrite(old);
|
||||
} else {
|
||||
memcpy(data, cc, sizeof(picopass_hdr_t));
|
||||
memcpy(data + (6 * 8), o->data, sizeof(o->data));
|
||||
}
|
||||
|
||||
//Send to device
|
||||
PrintAndLogEx(INFO, "Uploading to device... ");
|
||||
uint16_t bytes_sent = 0;
|
||||
iclass_upload_emul(data, tot_bytes, &bytes_sent);
|
||||
free(data);
|
||||
|
||||
PrintAndLogEx(SUCCESS, "sent %u bytes of data to device emulator memory", bytes_sent);
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(SUCCESS, "sent " _YELLOW_("%u") " bytes of data to device emulator memory", bytes_sent);
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass eview") "` to view dump file");
|
||||
PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass sim -t 3") "` to start simulating config card");
|
||||
return PM3_SUCCESS;
|
||||
|
@ -454,15 +477,21 @@ static void fuse_config(const picopass_hdr_t *hdr) {
|
|||
PrintAndLogEx(SUCCESS, " RA........... Read access enabled (non-secure mode)");
|
||||
else
|
||||
PrintAndLogEx(INFO, " RA........... Read access not enabled");
|
||||
|
||||
if (notset(fuses, FUSE_FPROD0) && isset(fuses, FUSE_FPROD1)) {
|
||||
PrintAndLogEx(INFO, " PROD0/1...... Default production fuses");
|
||||
}
|
||||
}
|
||||
|
||||
static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, 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, uint8_t *books, uint8_t *pages) {
|
||||
// How to determine chip type
|
||||
|
||||
// mem-bit 7 = 16K
|
||||
// mem-bit 5 = Book
|
||||
// mem-bit 4 = 2K
|
||||
// chip-bit 4 = Multi App
|
||||
*books = 1;
|
||||
*pages = 1;
|
||||
|
||||
uint8_t k16 = isset(mem_cfg, 0x80);
|
||||
//uint8_t k2 = isset(mem_cfg, 0x10);
|
||||
|
@ -477,12 +506,16 @@ static void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *app_areas,
|
|||
} else if (notset(chip_cfg, 0x10) && !k16 && !book) {
|
||||
*kb = 16;
|
||||
*app_areas = 16;
|
||||
*pages = 8;
|
||||
} else if (isset(chip_cfg, 0x10) && k16 && book) {
|
||||
*kb = 32;
|
||||
*app_areas = 3;
|
||||
*books = 2;
|
||||
} else if (notset(chip_cfg, 0x10) && !k16 && book) {
|
||||
*kb = 32;
|
||||
*app_areas = 17;
|
||||
*pages = 8;
|
||||
*books = 2;
|
||||
} else {
|
||||
*kb = 32;
|
||||
*app_areas = 2;
|
||||
|
@ -506,8 +539,10 @@ static void mem_app_config(const picopass_hdr_t *hdr) {
|
|||
uint8_t chip = hdr->conf.chip_config;
|
||||
uint8_t kb = 2;
|
||||
uint8_t app_areas = 2;
|
||||
uint8_t books = 1;
|
||||
uint8_t pages = 1;
|
||||
|
||||
getMemConfig(mem, chip, &app_areas, &kb);
|
||||
getMemConfig(mem, chip, &app_areas, &kb, &books, &pages);
|
||||
|
||||
uint8_t type = get_mem_config(hdr);
|
||||
uint8_t app1_limit = hdr->conf.app_limit - 5; // minus header blocks
|
||||
|
@ -522,9 +557,26 @@ static void mem_app_config(const picopass_hdr_t *hdr) {
|
|||
return;
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, " %u KBits/%u App Areas ( " _YELLOW_("%u") " bytes )", kb, app_areas, (app2_limit + 1) * 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, " %u KBits/%u App Areas ( " _YELLOW_("%u") " bytes )"
|
||||
, kb
|
||||
, app_areas
|
||||
, ((app2_limit + 1) * 8) * books * pages);
|
||||
|
||||
PrintAndLogEx(INFO, " %u books / %u pages"
|
||||
, books
|
||||
, pages
|
||||
);
|
||||
PrintAndLogEx(INFO, " First book / first page configuration");
|
||||
PrintAndLogEx(INFO, " Config | 0 - 5 ( 0x00 - 0x05 ) - 6 blocks ");
|
||||
PrintAndLogEx(INFO, " AA1 | 6 - %2d ( 0x06 - 0x%02X ) - %u blocks", app1_limit + 5, app1_limit + 5, app1_limit);
|
||||
if (app1_limit + 5 < app2_limit ) {
|
||||
PrintAndLogEx(INFO, " AA2 | %2d - %2d ( 0x%02X - 0x%02X ) - %u blocks", app1_limit + 5 + 1, app2_limit, app1_limit + 5 + 1, app2_limit, app2_limit - app1_limit);
|
||||
}
|
||||
/*
|
||||
[=] 32 KBits/3 App Areas ( 2048 bytes )
|
||||
[=] AA1 blocks 250 { 0x06 - 0xFF (06 - 255) }
|
||||
[=] AA2 blocks 5 { 0x100 - 0xFF (256 - 255) }
|
||||
*/
|
||||
|
||||
PrintAndLogEx(INFO, "------------------------- " _CYAN_("KeyAccess") " ------------------------");
|
||||
PrintAndLogEx(INFO, " * Kd, Debit key, AA1 Kc, Credit key, AA2 *");
|
||||
|
@ -557,8 +609,19 @@ void print_picopass_header(const picopass_hdr_t *hdr) {
|
|||
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn)));
|
||||
PrintAndLogEx(SUCCESS, " Config: %s Card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
|
||||
PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
|
||||
PrintAndLogEx(SUCCESS, " Kd: %s Debit key, hidden", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
PrintAndLogEx(SUCCESS, " Kc: %s Credit key, hidden", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
|
||||
if (memcmp(hdr->key_d, zeros, sizeof(zeros)) && memcmp(hdr->key_d, empty, sizeof(empty))) {
|
||||
PrintAndLogEx(SUCCESS, " Kd: " _YELLOW_("%s") " debit key", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " Kd: %s debit key ( hidden )", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
}
|
||||
|
||||
if (memcmp(hdr->key_c, zeros, sizeof(zeros)) && memcmp(hdr->key_c, empty, sizeof(empty))) {
|
||||
PrintAndLogEx(SUCCESS, " Kc: " _YELLOW_("%s") " credit key", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " Kc: %s credit key ( hidden )", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " AIA: %s Application Issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
|
||||
}
|
||||
|
||||
|
@ -834,25 +897,28 @@ static int CmdHFiClassInfo(const char *Cmd) {
|
|||
|
||||
int read_iclass_csn(bool loop, bool verbose) {
|
||||
|
||||
uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
|
||||
iclass_card_select_t payload = {
|
||||
.flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE)
|
||||
};
|
||||
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
do {
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload, sizeof(iclass_card_select_t));
|
||||
|
||||
uint8_t status = resp.oldarg[0] & 0xff;
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000)) {
|
||||
|
||||
iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes;
|
||||
if (loop) {
|
||||
if (status == 0xFF) {
|
||||
if (resp.status == PM3_ERFTRANS) {
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (status == 0 || status == 0xFF) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "iCLASS / ISO15693 card select failed");
|
||||
if (r->status == FLAG_ICLASS_NULL || resp.status == PM3_ERFTRANS) {
|
||||
if (verbose) PrintAndLogEx(WARNING, "iCLASS / Picopass card select failed ( %d )", r->status);
|
||||
res = PM3_EOPABORTED;
|
||||
break;
|
||||
}
|
||||
|
@ -860,13 +926,17 @@ int read_iclass_csn(bool loop, bool verbose) {
|
|||
|
||||
picopass_hdr_t *card = calloc(1, sizeof(picopass_hdr_t));
|
||||
if (card) {
|
||||
memcpy(card, (picopass_hdr_t *)resp.data.asBytes, sizeof(picopass_hdr_t));
|
||||
memcpy(card, &r->header.hdr, sizeof(picopass_hdr_t));
|
||||
if (loop == false) {
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "iCLASS / Picopass CSN: " _GREEN_("%s"), sprint_hex(card->csn, sizeof(card->csn)));
|
||||
iclass_set_last_known_card(card);
|
||||
free(card);
|
||||
res = PM3_SUCCESS;
|
||||
} else {
|
||||
PrintAndLogEx(FAILED, "failed to allocate memory");
|
||||
res = PM3_EMALLOC;
|
||||
}
|
||||
}
|
||||
} while (loop && kbd_enter_pressed() == false);
|
||||
|
@ -1240,7 +1310,9 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
} else {
|
||||
mbedtls_des3_crypt_ecb(&ctx, enc_data, dec_data);
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "Data: %s", sprint_hex(dec_data, sizeof(dec_data)));
|
||||
|
||||
PrintAndLogEx(SUCCESS, "encrypted... %s", sprint_hex_inrow(enc_data, sizeof(enc_data)));
|
||||
PrintAndLogEx(SUCCESS, "plain....... " _YELLOW_("%s"), sprint_hex_inrow(dec_data, sizeof(dec_data)));
|
||||
|
||||
if (use_sc && use_decode6)
|
||||
DecodeBlock6(dec_data);
|
||||
|
@ -1256,7 +1328,9 @@ static int CmdHFiClassDecrypt(const char *Cmd) {
|
|||
uint8_t applimit = hdr->conf.app_limit;
|
||||
uint8_t kb = 2;
|
||||
uint8_t app_areas = 2;
|
||||
getMemConfig(mem, chip, &app_areas, &kb);
|
||||
uint8_t books = 1;
|
||||
uint8_t pages = 1;
|
||||
getMemConfig(mem, chip, &app_areas, &kb, &books, &pages);
|
||||
|
||||
BLOCK79ENCRYPTION aa1_encryption = (decrypted[(6 * 8) + 7] & 0x03);
|
||||
|
||||
|
@ -1455,39 +1529,45 @@ static int CmdHFiClassEncryptBlk(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
PrintAndLogEx(SUCCESS, "plain....... %s", sprint_hex_inrow(blk_data, sizeof(blk_data)));
|
||||
|
||||
if (use_sc) {
|
||||
Encrypt(blk_data, blk_data);
|
||||
} else {
|
||||
iclass_encrypt_block_data(blk_data, key);
|
||||
}
|
||||
PrintAndLogEx(SUCCESS, "encrypted block %s", sprint_hex(blk_data, 8));
|
||||
|
||||
PrintAndLogEx(SUCCESS, "encrypted... " _YELLOW_("%s"), sprint_hex_inrow(blk_data, sizeof(blk_data)));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool verbose) {
|
||||
|
||||
uint8_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
|
||||
iclass_card_select_t payload = {
|
||||
.flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE)
|
||||
};
|
||||
|
||||
clearCommandBuffer();
|
||||
PacketResponseNG resp;
|
||||
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) == false) {
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload, sizeof(iclass_card_select_t));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t isok = resp.oldarg[0] & 0xff;
|
||||
iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes;
|
||||
picopass_hdr_t *hdr = &r->header.hdr;
|
||||
|
||||
// no tag found or button pressed
|
||||
if ((isok == 0) || isok == 0xFF) {
|
||||
if (r->status == FLAG_ICLASS_NULL || resp.status == PM3_ERFTRANS) {
|
||||
if (verbose) {
|
||||
PrintAndLogEx(FAILED, "failed tag-select, aborting... (%d)", isok);
|
||||
PrintAndLogEx(FAILED, "failed tag-select, aborting... (%d)", r->status);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes;
|
||||
|
||||
if (CSN != NULL)
|
||||
memcpy(CSN, hdr->csn, 8);
|
||||
|
||||
|
@ -1614,34 +1694,41 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
|
||||
uint8_t app_limit1 = 0, app_limit2 = 0;
|
||||
|
||||
uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
|
||||
|
||||
//get CSN and config
|
||||
PacketResponseNG resp;
|
||||
uint8_t tag_data[0x100 * 8];
|
||||
memset(tag_data, 0xFF, sizeof(tag_data));
|
||||
|
||||
|
||||
iclass_card_select_t payload_rdr = {
|
||||
.flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE)
|
||||
};
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
||||
if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
PacketResponseNG resp;
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload_rdr, sizeof(iclass_card_select_t));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) {
|
||||
PrintAndLogEx(WARNING, "command execute timeout");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
DropField();
|
||||
|
||||
uint8_t readStatus = resp.oldarg[0] & 0xff;
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes;
|
||||
|
||||
if (readStatus == 0) {
|
||||
if (resp.status == PM3_ERFTRANS) {
|
||||
PrintAndLogEx(FAILED, "no tag found");
|
||||
DropField();
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes;
|
||||
if (r->status == FLAG_ICLASS_NULL) {
|
||||
PrintAndLogEx(FAILED, "failed to read block 0,1,2");
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
picopass_hdr_t *hdr = &r->header.hdr;
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
|
||||
if (readStatus & (FLAG_ICLASS_CSN | FLAG_ICLASS_CONF | FLAG_ICLASS_CC)) {
|
||||
if (r->status & (FLAG_ICLASS_CSN | FLAG_ICLASS_CONF | FLAG_ICLASS_CC)) {
|
||||
|
||||
memcpy(tag_data, hdr, 24);
|
||||
|
||||
|
@ -1661,11 +1748,6 @@ static int CmdHFiClassDump(const char *Cmd) {
|
|||
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;
|
||||
}
|
||||
|
||||
if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) {
|
||||
|
@ -2470,11 +2552,10 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
|
|||
);
|
||||
*/
|
||||
uint8_t pagemap = get_pagemap(hdr);
|
||||
|
||||
|
||||
|
||||
int i = startblock;
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "-------------------------- " _CYAN_("Tag memory") " ---------------------------");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, " block# | data | ascii |lck| info");
|
||||
PrintAndLogEx(INFO, "---------+-------------------------+----------+---+--------------");
|
||||
|
@ -2484,7 +2565,7 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e
|
|||
);
|
||||
|
||||
if (i != 1)
|
||||
PrintAndLogEx(INFO, "....");
|
||||
PrintAndLogEx(INFO, " ......");
|
||||
|
||||
while (i <= endblock) {
|
||||
uint8_t *blk = iclass_dump + (i * 8);
|
||||
|
@ -3956,33 +4037,37 @@ int CmdHFiClass(const char *Cmd) {
|
|||
|
||||
int info_iclass(void) {
|
||||
|
||||
uint32_t flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE);
|
||||
|
||||
iclass_card_select_t payload = {
|
||||
.flags = (FLAG_ICLASS_READER_INIT | FLAG_ICLASS_READER_CLEARTRACE)
|
||||
};
|
||||
clearCommandBuffer();
|
||||
SendCommandMIX(CMD_HF_ICLASS_READER, flags, 0, 0, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
SendCommandNG(CMD_HF_ICLASS_READER, (uint8_t*)&payload, sizeof(iclass_card_select_t));
|
||||
|
||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) {
|
||||
if (WaitForResponseTimeout(CMD_HF_ICLASS_READER, &resp, 2000) == false) {
|
||||
DropField();
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
DropField();
|
||||
|
||||
uint8_t readStatus = resp.oldarg[0] & 0xff;
|
||||
iclass_card_select_resp_t *r = (iclass_card_select_resp_t*)resp.data.asBytes;
|
||||
|
||||
// no tag found or button pressed
|
||||
if (readStatus == 0 || readStatus == 0xFF) {
|
||||
DropField();
|
||||
if (r->status == FLAG_ICLASS_NULL || resp.status == PM3_ERFTRANS) {
|
||||
return PM3_EOPABORTED;
|
||||
}
|
||||
|
||||
picopass_hdr_t *hdr = (picopass_hdr_t *)resp.data.asBytes;
|
||||
picopass_ns_hdr_t *ns_hdr = (picopass_ns_hdr_t *)resp.data.asBytes;
|
||||
picopass_hdr_t *hdr = &r->header.hdr;
|
||||
picopass_ns_hdr_t *ns_hdr = &r->header.ns_hdr;
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
PrintAndLogEx(INFO, "--------------------- " _CYAN_("Tag Information") " ----------------------");
|
||||
|
||||
if (readStatus & FLAG_ICLASS_CSN) {
|
||||
if ((r->status & FLAG_ICLASS_CSN) == FLAG_ICLASS_CSN) {
|
||||
PrintAndLogEx(SUCCESS, " CSN: " _GREEN_("%s") " uid", sprint_hex(hdr->csn, sizeof(hdr->csn)));
|
||||
}
|
||||
|
||||
if (readStatus & FLAG_ICLASS_CONF) {
|
||||
if ((r->status & FLAG_ICLASS_CONF) == FLAG_ICLASS_CONF) {
|
||||
PrintAndLogEx(SUCCESS, " Config: %s card configuration", sprint_hex((uint8_t *)&hdr->conf, sizeof(hdr->conf)));
|
||||
}
|
||||
|
||||
|
@ -3993,19 +4078,29 @@ int info_iclass(void) {
|
|||
PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(ns_hdr->app_issuer_area, sizeof(ns_hdr->app_issuer_area)));
|
||||
} else {
|
||||
|
||||
if (readStatus & FLAG_ICLASS_CC) {
|
||||
if ((r->status & FLAG_ICLASS_CC) == FLAG_ICLASS_CC) {
|
||||
PrintAndLogEx(SUCCESS, "E-purse: %s Card challenge, CC", sprint_hex(hdr->epurse, sizeof(hdr->epurse)));
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, " Kd: %s debit key, hidden", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
PrintAndLogEx(SUCCESS, " Kc: %s credit key, hidden", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
if (memcmp(hdr->key_d, zeros, sizeof(zeros))) {
|
||||
PrintAndLogEx(SUCCESS, " Kd: " _YELLOW_("%s") " debit key", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " Kd: %s debit key ( hidden )", sprint_hex(hdr->key_d, sizeof(hdr->key_d)));
|
||||
}
|
||||
|
||||
if (readStatus & FLAG_ICLASS_AIA) {
|
||||
if (memcmp(hdr->key_c, zeros, sizeof(zeros))) {
|
||||
PrintAndLogEx(SUCCESS, " Kc: " _YELLOW_("%s") " credit key", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, " Kc: %s credit key ( hidden )", sprint_hex(hdr->key_c, sizeof(hdr->key_c)));
|
||||
}
|
||||
|
||||
|
||||
if ((r->status & FLAG_ICLASS_AIA) == FLAG_ICLASS_AIA) {
|
||||
PrintAndLogEx(SUCCESS, " AIA: %s application issuer area", sprint_hex(hdr->app_issuer_area, sizeof(hdr->app_issuer_area)));
|
||||
}
|
||||
}
|
||||
|
||||
if (readStatus & FLAG_ICLASS_CONF) {
|
||||
if ((r->status & FLAG_ICLASS_CONF) == FLAG_ICLASS_CONF) {
|
||||
print_picopass_info(hdr);
|
||||
}
|
||||
|
||||
|
@ -4036,8 +4131,7 @@ int info_iclass(void) {
|
|||
|
||||
uint8_t cardtype = get_mem_config(hdr);
|
||||
PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]);
|
||||
}
|
||||
DropField();
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,21 +13,7 @@
|
|||
|
||||
#include "common.h"
|
||||
#include "fileutils.h"
|
||||
#include "pm3_cmd.h"
|
||||
|
||||
typedef struct iclass_block {
|
||||
uint8_t d[8];
|
||||
} iclass_block_t;
|
||||
|
||||
typedef struct iclass_prekey {
|
||||
uint8_t mac[4];
|
||||
uint8_t key[8];
|
||||
} iclass_prekey_t;
|
||||
|
||||
typedef struct {
|
||||
char desc[70];
|
||||
uint8_t data[16];
|
||||
} iclass_config_card_item_t;
|
||||
#include "iclass_cmd.h"
|
||||
|
||||
int CmdHFiClass(const char *Cmd);
|
||||
|
||||
|
|
|
@ -47,7 +47,7 @@ double g_PlotGridX = 0, g_PlotGridY = 0, g_PlotGridXdefault = 64, g_PlotGridYdef
|
|||
uint32_t g_CursorCPos = 0, g_CursorDPos = 0, g_GraphStop = 0;
|
||||
uint32_t g_GraphStart = 0; // Starting point/offset for the left side of the graph
|
||||
double g_GraphPixelsPerPoint = 1.f; // How many visual pixels are between each sample point (x axis)
|
||||
static bool flushAfterWrite = 0;
|
||||
static bool flushAfterWrite = false;
|
||||
double g_GridOffset = 0;
|
||||
bool g_GridLocked = false;
|
||||
|
||||
|
@ -411,6 +411,10 @@ void SetFlushAfterWrite(bool value) {
|
|||
flushAfterWrite = value;
|
||||
}
|
||||
|
||||
bool GetFlushAfterWrite(void) {
|
||||
return flushAfterWrite;
|
||||
}
|
||||
|
||||
void memcpy_filter_rlmarkers(void *dest, const void *src, size_t n) {
|
||||
uint8_t *rdest = (uint8_t *)dest;
|
||||
uint8_t *rsrc = (uint8_t *)src;
|
||||
|
|
|
@ -63,6 +63,7 @@ extern session_arg_t g_session;
|
|||
void PrintAndLogOptions(const char *str[][2], size_t size, size_t space);
|
||||
void PrintAndLogEx(logLevel_t level, const char *fmt, ...);
|
||||
void SetFlushAfterWrite(bool value);
|
||||
bool GetFlushAfterWrite(void);
|
||||
void memcpy_filter_ansi(void *dest, const void *src, size_t n, bool filter);
|
||||
void memcpy_filter_rlmarkers(void *dest, const void *src, size_t n);
|
||||
void memcpy_filter_emoji(void *dest, const void *src, size_t n, emojiMode_t mode);
|
||||
|
|
159
include/iclass_cmd.h
Normal file
159
include/iclass_cmd.h
Normal file
|
@ -0,0 +1,159 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// (c) 2021 Iceman
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// iCLASS type prototyping
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef _ICLASS_CMD_H_
|
||||
#define _ICLASS_CMD_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// iCLASS / PICOPASS
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// iCLASS reader flags
|
||||
#define FLAG_ICLASS_READER_INIT 0x01
|
||||
#define FLAG_ICLASS_READER_CLEARTRACE 0x02
|
||||
//#define FLAG_ICLASS_READER_ONLY_ONCE 0x04
|
||||
#define FLAG_ICLASS_READER_CREDITKEY 0x08
|
||||
#define FLAG_ICLASS_READER_AIA 0x10
|
||||
|
||||
// iCLASS reader status flags
|
||||
#define FLAG_ICLASS_NULL 0x00
|
||||
#define FLAG_ICLASS_CSN 0x01
|
||||
#define FLAG_ICLASS_CC 0x02
|
||||
#define FLAG_ICLASS_CONF 0x04
|
||||
#define FLAG_ICLASS_AIA 0x08
|
||||
|
||||
// iCLASS simulation modes
|
||||
#define ICLASS_SIM_MODE_CSN 0
|
||||
#define ICLASS_SIM_MODE_CSN_DEFAULT 1
|
||||
#define ICLASS_SIM_MODE_READER_ATTACK 2
|
||||
#define ICLASS_SIM_MODE_FULL 3
|
||||
#define ICLASS_SIM_MODE_READER_ATTACK_KEYROLL 4
|
||||
#define ICLASS_SIM_MODE_EXIT_AFTER_MAC 5 // note: device internal only
|
||||
#define ICLASS_SIM_MODE_CONFIG_CARD 6
|
||||
|
||||
|
||||
// iCLASS auth request data structure
|
||||
// used with read block, dump, write block
|
||||
typedef struct {
|
||||
uint8_t key[8];
|
||||
bool use_raw;
|
||||
bool use_elite;
|
||||
bool use_credit_key;
|
||||
bool use_replay;
|
||||
bool send_reply;
|
||||
bool do_auth;
|
||||
uint8_t blockno;
|
||||
} PACKED iclass_auth_req_t;
|
||||
|
||||
// iCLASS read block response data structure
|
||||
typedef struct {
|
||||
bool isOK;
|
||||
uint8_t div_key[8];
|
||||
uint8_t mac[4];
|
||||
uint8_t data[8];
|
||||
} PACKED iclass_readblock_resp_t;
|
||||
|
||||
// iCLASS dump data structure
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t start_block;
|
||||
uint8_t end_block;
|
||||
} PACKED iclass_dump_req_t;
|
||||
|
||||
// iCLASS write block request data structure
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t data[8];
|
||||
} PACKED iclass_writeblock_req_t;
|
||||
|
||||
// iCLASS dump data structure
|
||||
typedef struct {
|
||||
uint8_t blockno;
|
||||
uint8_t data[8];
|
||||
} PACKED iclass_restore_item_t;
|
||||
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t item_cnt;
|
||||
iclass_restore_item_t blocks[];
|
||||
} PACKED iclass_restore_req_t;
|
||||
|
||||
typedef struct iclass_premac {
|
||||
uint8_t mac[4];
|
||||
} PACKED iclass_premac_t;
|
||||
|
||||
typedef struct {
|
||||
bool use_credit_key;
|
||||
uint8_t count;
|
||||
iclass_premac_t items[];
|
||||
} PACKED iclass_chk_t;
|
||||
|
||||
typedef struct iclass_block {
|
||||
uint8_t d[8];
|
||||
} iclass_block_t;
|
||||
|
||||
typedef struct iclass_prekey {
|
||||
uint8_t mac[4];
|
||||
uint8_t key[8];
|
||||
} iclass_prekey_t;
|
||||
|
||||
typedef struct {
|
||||
char desc[70];
|
||||
uint8_t data[16];
|
||||
} iclass_config_card_item_t;
|
||||
|
||||
|
||||
// iclass / picopass chip config structures and shared routines
|
||||
typedef struct {
|
||||
uint8_t app_limit; //[8]
|
||||
uint8_t otp[2]; //[9-10]
|
||||
uint8_t block_writelock;//[11]
|
||||
uint8_t chip_config; //[12]
|
||||
uint8_t mem_config; //[13]
|
||||
uint8_t eas; //[14]
|
||||
uint8_t fuses; //[15]
|
||||
} PACKED picopass_conf_block_t;
|
||||
|
||||
// iCLASS secure mode memory mapping
|
||||
typedef struct {
|
||||
uint8_t csn[8];
|
||||
picopass_conf_block_t conf;
|
||||
uint8_t epurse[8];
|
||||
uint8_t key_d[8];
|
||||
uint8_t key_c[8];
|
||||
uint8_t app_issuer_area[8];
|
||||
} PACKED picopass_hdr_t;
|
||||
|
||||
// iCLASS non-secure mode memory mapping
|
||||
typedef struct {
|
||||
uint8_t csn[8];
|
||||
picopass_conf_block_t conf;
|
||||
uint8_t app_issuer_area[8];
|
||||
} PACKED picopass_ns_hdr_t;
|
||||
|
||||
// reader flags
|
||||
typedef struct {
|
||||
uint8_t flags;
|
||||
} PACKED iclass_card_select_t;
|
||||
|
||||
// reader flags
|
||||
typedef struct {
|
||||
uint8_t status;
|
||||
union {
|
||||
picopass_hdr_t hdr;
|
||||
picopass_ns_hdr_t ns_hdr;
|
||||
} header;
|
||||
} PACKED iclass_card_select_resp_t;
|
||||
|
||||
|
||||
#endif // _ICLASS_H_
|
|
@ -291,92 +291,6 @@ typedef struct {
|
|||
} PACKED ecdsa_publickey_t;
|
||||
|
||||
|
||||
// iCLASS auth request data structure
|
||||
// used with read block, dump, write block
|
||||
typedef struct {
|
||||
uint8_t key[8];
|
||||
bool use_raw;
|
||||
bool use_elite;
|
||||
bool use_credit_key;
|
||||
bool use_replay;
|
||||
bool send_reply;
|
||||
bool do_auth;
|
||||
uint8_t blockno;
|
||||
} PACKED iclass_auth_req_t;
|
||||
|
||||
// iCLASS read block response data structure
|
||||
typedef struct {
|
||||
bool isOK;
|
||||
uint8_t div_key[8];
|
||||
uint8_t mac[4];
|
||||
uint8_t data[8];
|
||||
} PACKED iclass_readblock_resp_t;
|
||||
|
||||
// iCLASS dump data structure
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t start_block;
|
||||
uint8_t end_block;
|
||||
} PACKED iclass_dump_req_t;
|
||||
|
||||
// iCLASS write block request data structure
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t data[8];
|
||||
} PACKED iclass_writeblock_req_t;
|
||||
|
||||
// iCLASS dump data structure
|
||||
typedef struct {
|
||||
uint8_t blockno;
|
||||
uint8_t data[8];
|
||||
} PACKED iclass_restore_item_t;
|
||||
|
||||
typedef struct {
|
||||
iclass_auth_req_t req;
|
||||
uint8_t item_cnt;
|
||||
iclass_restore_item_t blocks[];
|
||||
} PACKED iclass_restore_req_t;
|
||||
|
||||
typedef struct iclass_premac {
|
||||
uint8_t mac[4];
|
||||
} PACKED iclass_premac_t;
|
||||
|
||||
typedef struct {
|
||||
bool use_credit_key;
|
||||
uint8_t count;
|
||||
iclass_premac_t items[];
|
||||
} PACKED iclass_chk_t;
|
||||
|
||||
|
||||
// iclass / picopass chip config structures and shared routines
|
||||
typedef struct {
|
||||
uint8_t app_limit; //[8]
|
||||
uint8_t otp[2]; //[9-10]
|
||||
uint8_t block_writelock;//[11]
|
||||
uint8_t chip_config; //[12]
|
||||
uint8_t mem_config; //[13]
|
||||
uint8_t eas; //[14]
|
||||
uint8_t fuses; //[15]
|
||||
} PACKED picopass_conf_block_t;
|
||||
|
||||
// iCLASS secure mode memory mapping
|
||||
typedef struct {
|
||||
uint8_t csn[8];
|
||||
picopass_conf_block_t conf;
|
||||
uint8_t epurse[8];
|
||||
uint8_t key_d[8];
|
||||
uint8_t key_c[8];
|
||||
uint8_t app_issuer_area[8];
|
||||
} PACKED picopass_hdr_t;
|
||||
|
||||
// iCLASS non-secure mode memory mapping
|
||||
typedef struct {
|
||||
uint8_t csn[8];
|
||||
picopass_conf_block_t conf;
|
||||
uint8_t app_issuer_area[8];
|
||||
} PACKED picopass_ns_hdr_t;
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t delay_us;
|
||||
bool on;
|
||||
|
@ -767,28 +681,6 @@ typedef struct {
|
|||
#define FLAG_CVE21_0430 0x2000
|
||||
|
||||
|
||||
// iCLASS reader flags
|
||||
#define FLAG_ICLASS_READER_INIT 0x01
|
||||
#define FLAG_ICLASS_READER_CLEARTRACE 0x02
|
||||
#define FLAG_ICLASS_READER_ONLY_ONCE 0x04
|
||||
#define FLAG_ICLASS_READER_CREDITKEY 0x08
|
||||
#define FLAG_ICLASS_READER_AIA 0x10
|
||||
|
||||
// iCLASS reader status flags
|
||||
#define FLAG_ICLASS_CSN 0x01
|
||||
#define FLAG_ICLASS_CC 0x02
|
||||
#define FLAG_ICLASS_CONF 0x04
|
||||
#define FLAG_ICLASS_AIA 0x08
|
||||
|
||||
// iCLASS simulation modes
|
||||
#define ICLASS_SIM_MODE_CSN 0
|
||||
#define ICLASS_SIM_MODE_CSN_DEFAULT 1
|
||||
#define ICLASS_SIM_MODE_READER_ATTACK 2
|
||||
#define ICLASS_SIM_MODE_FULL 3
|
||||
#define ICLASS_SIM_MODE_READER_ATTACK_KEYROLL 4
|
||||
#define ICLASS_SIM_MODE_EXIT_AFTER_MAC 5 // note: device internal only
|
||||
#define ICLASS_SIM_MODE_CONFIG_CARD 6
|
||||
|
||||
#define MODE_SIM_CSN 0
|
||||
#define MODE_EXIT_AFTER_MAC 1
|
||||
#define MODE_FULLSIM 2
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue