mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-20 21:33:47 -07:00
hf 14a: add config loopholes to deal with badly configured cards: invalid ATQA, invalid BCC, invalid SAK
This commit is contained in:
parent
007fc0893d
commit
b751354ea2
11 changed files with 243 additions and 22 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Add `hf 14a config` to deal with badly configured cards: invalid ATQA/BCC/SAK (@doegox)"
|
||||
- Mikron JSC Russia Ultralight EV1 41 pages tag type support (@McEloff)
|
||||
- Add test for Ultralight gen2 magic 'hf search' (@McEloff)
|
||||
- Add test for Ultralight EV1 gen2 magic 'hf search' (@McEloff)
|
||||
|
|
|
@ -355,8 +355,11 @@ static void SendStatus(void) {
|
|||
I2C_print_status();
|
||||
#endif
|
||||
#ifdef WITH_LF
|
||||
printConfig(); // LF Sampling config
|
||||
printLFConfig(); // LF Sampling config
|
||||
printT55xxConfig(); // LF T55XX Config
|
||||
#endif
|
||||
#ifdef WITH_ISO14443a
|
||||
printHf14aConfig(); // HF 14a config
|
||||
#endif
|
||||
printConnSpeed();
|
||||
DbpString(_CYAN_("Various"));
|
||||
|
@ -739,7 +742,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
break;
|
||||
}
|
||||
case CMD_LF_SAMPLING_PRINT_CONFIG: {
|
||||
printConfig();
|
||||
printLFConfig();
|
||||
break;
|
||||
}
|
||||
case CMD_LF_SAMPLING_GET_CONFIG: {
|
||||
|
@ -1058,8 +1061,8 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
uint8_t uid[8];
|
||||
} PACKED;
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
SetTag15693Uid(payload->uid);
|
||||
break;
|
||||
SetTag15693Uid(payload->uid);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1145,6 +1148,21 @@ static void PacketReceived(PacketCommandNG *packet) {
|
|||
#endif
|
||||
|
||||
#ifdef WITH_ISO14443a
|
||||
case CMD_HF_ISO14443A_PRINT_CONFIG: {
|
||||
printHf14aConfig();
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443A_GET_CONFIG: {
|
||||
hf14a_config *hf14aconfig = getHf14aConfig();
|
||||
reply_ng(CMD_HF_ISO14443A_GET_CONFIG, PM3_SUCCESS, (uint8_t *)hf14aconfig, sizeof(hf14a_config));
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443A_SET_CONFIG: {
|
||||
hf14a_config c;
|
||||
memcpy(&c, packet->data.asBytes, sizeof(hf14a_config));
|
||||
setHf14aConfig(&c);
|
||||
break;
|
||||
}
|
||||
case CMD_HF_ISO14443A_SNIFF: {
|
||||
SniffIso14443a(packet->data.asBytes[0]);
|
||||
reply_ng(CMD_HF_ISO14443A_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
|
|
|
@ -122,6 +122,47 @@ static uint32_t LastProxToAirDuration;
|
|||
#define SEC_Y 0x00
|
||||
#define SEC_Z 0xc0
|
||||
|
||||
/*
|
||||
Default HF 14a config is set to:
|
||||
forceanticol = false
|
||||
obeybadbcc = false
|
||||
forcecl2 = 0 (auto)
|
||||
forcecl3 = 0 (auto)
|
||||
*/
|
||||
static hf14a_config hf14aconfig = { 0, 0, 0, 0 } ;
|
||||
|
||||
void printHf14aConfig(void) {
|
||||
DbpString(_CYAN_("HF 14a config"));
|
||||
Dbprintf("[a] Force std anticol.....%s", (hf14aconfig.forceanticol) ? _RED_("Yes") " (even if bad ATQA)" : _GREEN_("No"));
|
||||
Dbprintf("[b] Force obey bad BCC....%s", (hf14aconfig.obeybadbcc) ? _RED_("Yes") : _GREEN_("No"));
|
||||
Dbprintf("[2] Force CL2 override ...%s%s%s", (hf14aconfig.forcecl2==0) ? _GREEN_("No") : "", (hf14aconfig.forcecl2==1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcecl2==-1) ? _RED_("Yes: Always skip CL2") : "");
|
||||
Dbprintf("[3] Force CL3 override ...%s%s%s", (hf14aconfig.forcecl3==0) ? _GREEN_("No") : "", (hf14aconfig.forcecl3==1) ? _RED_("Yes: Always do CL3") : "", (hf14aconfig.forcecl3==-1) ? _RED_("Yes: Always skip CL3") : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Called from the USB-handler to set the 14a configuration
|
||||
* The 14a config is used for card selection sequence.
|
||||
*
|
||||
* Values set to '-1' implies no change
|
||||
* @brief setSamplingConfig
|
||||
* @param sc
|
||||
*/
|
||||
void setHf14aConfig(hf14a_config *hc) {
|
||||
|
||||
if (hc->forceanticol > -1)
|
||||
hf14aconfig.forceanticol = (hc->forceanticol > 0) ? 1 : 0;
|
||||
if (hc->obeybadbcc > -1)
|
||||
hf14aconfig.obeybadbcc = (hc->obeybadbcc > 0) ? 1 : 0;
|
||||
if ((hc->forcecl2 >= -1) && (hc->forcecl2 <= 1))
|
||||
hf14aconfig.forcecl2 = hc->forcecl2;
|
||||
if ((hc->forcecl3 >= -1) && (hc->forcecl3 <= 1))
|
||||
hf14aconfig.forcecl3 = hc->forcecl3;
|
||||
}
|
||||
|
||||
hf14a_config *getHf14aConfig(void) {
|
||||
return &hf14aconfig;
|
||||
}
|
||||
|
||||
void iso14a_set_trigger(bool enable) {
|
||||
g_trigger = enable;
|
||||
}
|
||||
|
@ -2335,7 +2376,8 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
|||
uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller
|
||||
uint8_t resp_par[MAX_PARITY_SIZE] = {0};
|
||||
|
||||
uint8_t sak = 0x04; // cascade uid
|
||||
uint8_t sak; // cascade uid
|
||||
bool do_cascade = 1;
|
||||
int cascade_level = 0;
|
||||
|
||||
if (p_card) {
|
||||
|
@ -2359,17 +2401,19 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
|||
memset(uid_ptr, 0, 10);
|
||||
}
|
||||
|
||||
// check for proprietary anticollision:
|
||||
if ((resp[0] & 0x1F) == 0) return 3;
|
||||
if ( ! hf14aconfig.forceanticol ) {
|
||||
// check for proprietary anticollision:
|
||||
if ((resp[0] & 0x1F) == 0) return 3;
|
||||
}
|
||||
|
||||
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
|
||||
// which case we need to make a cascade 2 request and select - this is a long UID
|
||||
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
|
||||
for (; sak & 0x04; cascade_level++) {
|
||||
for (; do_cascade; cascade_level++) {
|
||||
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
|
||||
uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 };
|
||||
uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
uint8_t uid_resp[4] = {0};
|
||||
uint8_t uid_resp[5] = {0}; // UID + original BCC
|
||||
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
|
||||
|
||||
if (anticollision) {
|
||||
|
@ -2378,7 +2422,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
|||
if (!ReaderReceive(resp, resp_par)) return 0;
|
||||
|
||||
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
|
||||
memset(uid_resp, 0, 4);
|
||||
memset(uid_resp, 0, 5);
|
||||
uint16_t uid_resp_bits = 0;
|
||||
uint16_t collision_answer_offset = 0;
|
||||
// anti-collision-loop:
|
||||
|
@ -2390,7 +2434,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
|||
}
|
||||
uid_resp[uid_resp_bits / 8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
|
||||
uid_resp_bits++;
|
||||
// construct anticollosion command:
|
||||
// construct anticollision command:
|
||||
sel_uid[1] = ((2 + uid_resp_bits / 8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
|
||||
for (uint16_t i = 0; i <= uid_resp_bits / 8; i++) {
|
||||
sel_uid[2 + i] = uid_resp[i];
|
||||
|
@ -2406,7 +2450,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
|||
}
|
||||
|
||||
} else { // no collision, use the response to SELECT_ALL as current uid
|
||||
memcpy(uid_resp, resp, 4);
|
||||
memcpy(uid_resp, resp, 5); // UID + original BCC
|
||||
}
|
||||
|
||||
} else {
|
||||
|
@ -2425,8 +2469,22 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
|||
|
||||
// Construct SELECT UID command
|
||||
sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
|
||||
memcpy(sel_uid + 2, uid_resp, 4); // the UID received during anticollision, or the provided UID
|
||||
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
|
||||
|
||||
if (anticollision) {
|
||||
memcpy(sel_uid + 2, uid_resp, 5); // the UID received during anticollision with original BCC
|
||||
uint8_t bcc = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate BCC
|
||||
if (sel_uid[6] != bcc) {
|
||||
Dbprintf("BCC%d incorrect, got 0x%02x, expected 0x%02x. Will use " NOLF, cascade_level, sel_uid[6], bcc);
|
||||
if (! hf14aconfig.obeybadbcc) {
|
||||
sel_uid[6] = bcc;
|
||||
}
|
||||
Dbprintf("0x%02x", sel_uid[6]);
|
||||
}
|
||||
} else {
|
||||
memcpy(sel_uid + 2, uid_resp, 4); // the provided UID
|
||||
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
|
||||
}
|
||||
|
||||
AddCrc14A(sel_uid, 7); // calculate and add CRC
|
||||
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
|
||||
|
||||
|
@ -2436,7 +2494,21 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
|||
sak = resp[0];
|
||||
|
||||
// Test if more parts of the uid are coming
|
||||
if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
|
||||
do_cascade = (((sak & 0x04) /* && uid_resp[0] == 0x88 */) > 0);
|
||||
if (cascade_level==0) {
|
||||
if (hf14aconfig.forcecl2==-1) {
|
||||
do_cascade = false;
|
||||
} else if (hf14aconfig.forcecl2==1) {
|
||||
do_cascade = true;
|
||||
} // else 0==auto
|
||||
} else if (cascade_level==1) {
|
||||
if (hf14aconfig.forcecl3==-1) {
|
||||
do_cascade = false;
|
||||
} else if (hf14aconfig.forcecl3==1) {
|
||||
do_cascade = true;
|
||||
} // else 0==auto
|
||||
}
|
||||
if (do_cascade) {
|
||||
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
|
||||
// http://www.nxp.com/documents/application_note/AN10927.pdf
|
||||
uid_resp[0] = uid_resp[1];
|
||||
|
@ -2458,7 +2530,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
|
|||
p_card->sak = sak;
|
||||
}
|
||||
|
||||
// PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0)
|
||||
// PICC compliant with iso14443a-4 ---> (SAK & 0x20 != 0)
|
||||
if ((sak & 0x20) == 0) return 2;
|
||||
|
||||
// RATS, Request for answer to select
|
||||
|
|
|
@ -96,6 +96,9 @@ typedef struct {
|
|||
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
|
||||
#endif
|
||||
|
||||
void printHf14aConfig(void);
|
||||
void setHf14aConfig(hf14a_config *hc);
|
||||
hf14a_config *getHf14aConfig(void);
|
||||
void iso14a_set_timeout(uint32_t timeout);
|
||||
uint32_t iso14a_get_timeout(void);
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ static BitstreamOut data = {0, 0, 0};
|
|||
// internal struct to keep track of samples gathered
|
||||
static sampling_t samples = {0, 0, 0, 0};
|
||||
|
||||
void printConfig(void) {
|
||||
void printLFConfig(void) {
|
||||
uint32_t d = config.divisor;
|
||||
DbpString(_CYAN_("LF Sampling config"));
|
||||
Dbprintf(" [q] divisor.............%d ( "_GREEN_("%d.%02d kHz")" )", d, 12000 / (d + 1), ((1200000 + (d + 1) / 2) / (d + 1)) - ((12000 / (d + 1)) * 100));
|
||||
|
@ -97,7 +97,7 @@ void setSamplingConfig(sample_config *sc) {
|
|||
config.samples_to_skip = sc->samples_to_skip;
|
||||
|
||||
if (sc->verbose)
|
||||
printConfig();
|
||||
printLFConfig();
|
||||
}
|
||||
|
||||
sample_config *getSamplingConfig(void) {
|
||||
|
@ -376,7 +376,7 @@ uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t samp
|
|||
|
||||
static uint32_t ReadLF(bool reader_field, bool verbose, uint32_t sample_size) {
|
||||
if (verbose)
|
||||
printConfig();
|
||||
printLFConfig();
|
||||
|
||||
LFSetupFPGAForADC(config.divisor, reader_field);
|
||||
uint32_t ret = DoAcquisition_config(verbose, sample_size);
|
||||
|
|
|
@ -99,7 +99,7 @@ void setSamplingConfig(sample_config *sc);
|
|||
|
||||
sample_config *getSamplingConfig(void);
|
||||
|
||||
void printConfig(void);
|
||||
void printLFConfig(void);
|
||||
void printSamples(void);
|
||||
|
||||
#endif // __LFSAMPLING_H
|
||||
|
|
|
@ -168,6 +168,23 @@ const char *getTagInfo(uint8_t uid) {
|
|||
static uint16_t frameLength = 0;
|
||||
uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256};
|
||||
|
||||
static int usage_hf_14a_config(void) {
|
||||
PrintAndLogEx(NORMAL, "Usage: hf 14a config [a 0|1] [b 0|1]");
|
||||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h This help");
|
||||
PrintAndLogEx(NORMAL, " a 0|1 Force standard anticollision sequence even if ATQA tells not to do it");
|
||||
PrintAndLogEx(NORMAL, " b 0|1 Obey bad BCC in anticollision sequence");
|
||||
PrintAndLogEx(NORMAL, " 2 0|1|-1 Override CL2 decision: 0=auto, 1=always perform CL2, -1=never perform CL2");
|
||||
PrintAndLogEx(NORMAL, " 3 0|1|-1 Override CL3 decision: 0=auto, 1=always perform CL3, -1=never perform CL3");
|
||||
PrintAndLogEx(NORMAL, "Examples:");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config ")" Print current configuration");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a ")" Force standard anticollision");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config a 0 ")" Restore ATQA interpretation");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b ")" Force obey bad BCC in anticollision");
|
||||
PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a config b 0 ")" Restore BCC computation in anticollision");
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_hf_14a_sim(void) {
|
||||
// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n");
|
||||
PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n");
|
||||
|
@ -234,6 +251,98 @@ static int CmdHF14AList(const char *Cmd) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
int hf14a_getconfig(hf14a_config *config) {
|
||||
if (!session.pm3_present) return PM3_ENOTTY;
|
||||
|
||||
if (config == NULL)
|
||||
return PM3_EINVARG;
|
||||
|
||||
clearCommandBuffer();
|
||||
|
||||
SendCommandNG(CMD_HF_ISO14443A_GET_CONFIG, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (!WaitForResponseTimeout(CMD_HF_ISO14443A_GET_CONFIG, &resp, 2000)) {
|
||||
PrintAndLogEx(WARNING, "command execution time out");
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
memcpy(config, resp.data.asBytes, sizeof(hf14a_config));
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int hf14a_setconfig(hf14a_config *config) {
|
||||
if (!session.pm3_present) return PM3_ENOTTY;
|
||||
|
||||
clearCommandBuffer();
|
||||
if (config != NULL)
|
||||
SendCommandNG(CMD_HF_ISO14443A_SET_CONFIG, (uint8_t *)config, sizeof(hf14a_config));
|
||||
else
|
||||
SendCommandNG(CMD_HF_ISO14443A_PRINT_CONFIG, NULL, 0);
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdHf14AConfig(const char *Cmd) {
|
||||
|
||||
if (!session.pm3_present) return PM3_ENOTTY;
|
||||
|
||||
// if called with no params, just print the device config
|
||||
if (strlen(Cmd) == 0) {
|
||||
return hf14a_setconfig(NULL);
|
||||
}
|
||||
|
||||
hf14a_config config = {
|
||||
.forceanticol = -1,
|
||||
.obeybadbcc = -1,
|
||||
.forcecl2 = -2,
|
||||
.forcecl3 = -2
|
||||
};
|
||||
|
||||
bool errors = false;
|
||||
char cl[3] = {0};
|
||||
uint8_t cmdp = 0;
|
||||
while (param_getchar(Cmd, cmdp) != 0x00 && !errors) {
|
||||
switch (param_getchar(Cmd, cmdp)) {
|
||||
case 'h':
|
||||
return usage_hf_14a_config();
|
||||
case 'a':
|
||||
config.forceanticol = (param_getchar(Cmd, cmdp + 1) == '1');
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'b':
|
||||
config.obeybadbcc = (param_getchar(Cmd, cmdp + 1) == '1');
|
||||
cmdp += 2;
|
||||
break;
|
||||
case '2':
|
||||
param_getstr(Cmd, cmdp + 1, cl, sizeof(cl));
|
||||
if (strcmp(cl, "-1") == 0) {
|
||||
config.forcecl2 = -1;
|
||||
} else {
|
||||
config.forcecl2 = strcmp(cl, "1") == 0;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
case '3':
|
||||
param_getstr(Cmd, cmdp + 1, cl, sizeof(cl));
|
||||
if (strcmp(cl, "-1") == 0) {
|
||||
config.forcecl3 = -1;
|
||||
} else {
|
||||
config.forcecl3 = strcmp(cl, "1") == 0;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
default:
|
||||
PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp));
|
||||
errors = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// validations
|
||||
if (errors) return usage_hf_14a_config();
|
||||
|
||||
return hf14a_setconfig(&config);
|
||||
}
|
||||
|
||||
int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
|
||||
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0);
|
||||
|
||||
|
@ -1241,6 +1350,7 @@ static command_t CommandTable[] = {
|
|||
{"chaining", CmdHF14AChaining, IfPm3Iso14443a, "Control ISO 14443-4 input chaining"},
|
||||
{"raw", CmdHF14ACmdRaw, IfPm3Iso14443a, "Send raw hex data to tag"},
|
||||
{"antifuzz", CmdHF14AAntiFuzz, IfPm3Iso14443a, "Fuzzing the anticollision phase. Warning! Readers may react strange"},
|
||||
{"config", CmdHf14AConfig, IfPm3Iso14443a, "Configure 14a settings (use with caution)"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
#define CMDHF14A_H__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "pm3_cmd.h" //hf14a_config
|
||||
#include "mifare.h" // structs
|
||||
|
||||
// structure and database for uid -> tagtype lookups
|
||||
|
@ -26,6 +26,8 @@ int CmdHF14A(const char *Cmd);
|
|||
int CmdHF14ASniff(const char *Cmd); // used by hf topaz sniff
|
||||
int CmdHF14ASim(const char *Cmd); // used by hf mfu sim
|
||||
|
||||
int hf14a_getconfig(hf14a_config *config);
|
||||
int hf14a_setconfig(hf14a_config *config);
|
||||
int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search);
|
||||
const char *getTagInfo(uint8_t uid);
|
||||
int Hf14443_4aGetCardData(iso14a_card_select_t *card);
|
||||
|
|
|
@ -22,7 +22,6 @@ extern "C" {
|
|||
#define _USE_MATH_DEFINES
|
||||
|
||||
typedef enum logLevel {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG, INPLACE, HINT} logLevel_t;
|
||||
#define NOLF "\xff"
|
||||
typedef enum emojiMode {ALIAS, EMOJI, ALTTEXT, ERASE} emojiMode_t;
|
||||
typedef enum clientdebugLevel {cdbOFF, cdbSIMPLE, cdbFULL} clientdebugLevel_t;
|
||||
// typedef enum devicedebugLevel {ddbOFF, ddbERROR, ddbINFO, ddbDEBUG, ddbEXTENDED} devicedebugLevel_t;
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#ifndef __ANSI_H
|
||||
#define __ANSI_H
|
||||
|
||||
// Not ANSI but dirty trick to specify we don't want a \n
|
||||
#define NOLF "\xff"
|
||||
|
||||
#define AEND "\x1b[0m"
|
||||
|
||||
#define _BLUE_(s) "\x1b[34m" s AEND
|
||||
|
|
|
@ -122,6 +122,14 @@ typedef struct {
|
|||
bool verbose;
|
||||
} PACKED sample_config;
|
||||
|
||||
// A struct used to send hf14a-configs over USB
|
||||
typedef struct {
|
||||
int8_t forceanticol; // bool but also -1 if to be ignored
|
||||
int8_t obeybadbcc; // bool but also -1 if to be ignored
|
||||
int8_t forcecl2; // 0:auto 1:force executing CL2 -1:force skipping CL2
|
||||
int8_t forcecl3; // 0:auto 1:force executing CL3 -1:force skipping CL3
|
||||
} PACKED hf14a_config;
|
||||
|
||||
// Tracelog Header struct
|
||||
typedef struct {
|
||||
uint32_t timestamp;
|
||||
|
@ -569,6 +577,11 @@ typedef struct {
|
|||
#define CMD_HF_FELICALITE_DUMP 0x03AA
|
||||
#define CMD_HF_FELICALITE_SIMULATE 0x03AB
|
||||
|
||||
// For 14a config
|
||||
#define CMD_HF_ISO14443A_PRINT_CONFIG 0x03B0
|
||||
#define CMD_HF_ISO14443A_GET_CONFIG 0x03B1
|
||||
#define CMD_HF_ISO14443A_SET_CONFIG 0x03B2
|
||||
|
||||
// For measurements of the antenna tuning
|
||||
#define CMD_MEASURE_ANTENNA_TUNING 0x0400
|
||||
#define CMD_MEASURE_ANTENNA_TUNING_HF 0x0401
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue