mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 04:50:12 -07:00
Merge pull request #2824 from kormax/magsafe-polling-config
Move `mag`safe polling argument to `hf 14a config`
This commit is contained in:
commit
430d5cd3b9
6 changed files with 146 additions and 194 deletions
|
@ -133,6 +133,36 @@ static uint32_t LastProxToAirDuration;
|
||||||
#define SEC_Y 0x00
|
#define SEC_Y 0x00
|
||||||
#define SEC_Z 0xc0
|
#define SEC_Z 0xc0
|
||||||
|
|
||||||
|
|
||||||
|
static const iso14a_polling_frame_t WUPA_CMD = {
|
||||||
|
{ ISO14443A_CMD_WUPA }, 1, 7, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const iso14a_polling_frame_t REQA_CMD = {
|
||||||
|
{ISO14443A_CMD_REQA }, 1, 7, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const iso14a_polling_frame_t MAGWUPA_COMMANDS[4] = {
|
||||||
|
{{ 0x7A }, 1, 7, 0},
|
||||||
|
{{ 0x7B }, 1, 7, 0},
|
||||||
|
{{ 0x7C }, 1, 7, 0},
|
||||||
|
{{ 0x7D }, 1, 7, 0}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Polling frames and configurations
|
||||||
|
iso14a_polling_parameters_t WUPA_POLLING_PARAMETERS = {
|
||||||
|
.frames = { WUPA_CMD },
|
||||||
|
.frame_count = 1,
|
||||||
|
.extra_timeout = 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
iso14a_polling_parameters_t REQA_POLLING_PARAMETERS = {
|
||||||
|
.frames = { REQA_CMD },
|
||||||
|
.frame_count = 1,
|
||||||
|
.extra_timeout = 0,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Default HF 14a config is set to:
|
Default HF 14a config is set to:
|
||||||
forceanticol = 0 (auto)
|
forceanticol = 0 (auto)
|
||||||
|
@ -140,21 +170,17 @@ Default HF 14a config is set to:
|
||||||
forcecl2 = 0 (auto)
|
forcecl2 = 0 (auto)
|
||||||
forcecl3 = 0 (auto)
|
forcecl3 = 0 (auto)
|
||||||
forcerats = 0 (auto)
|
forcerats = 0 (auto)
|
||||||
|
magsafe = 0 (disabled)
|
||||||
|
polling_loop_annotation = {{0}, 0, 0, 0} (disabled)
|
||||||
*/
|
*/
|
||||||
static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0, {{0}, 0, 0, 0} };
|
static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0, 0, {{0}, 0, 0, 0} };
|
||||||
|
|
||||||
|
static iso14a_polling_parameters_t hf14a_polling_parameters = {
|
||||||
|
.frames = { WUPA_CMD },
|
||||||
|
.frame_count = 1,
|
||||||
|
.extra_timeout = 0
|
||||||
|
};
|
||||||
|
|
||||||
// Polling frames and configurations
|
|
||||||
iso14a_polling_parameters_t WUPA_POLLING_PARAMETERS = {
|
|
||||||
.frames = { {{ ISO14443A_CMD_WUPA }, 1, 7, 0} },
|
|
||||||
.frame_count = 1,
|
|
||||||
.extra_timeout = 0,
|
|
||||||
};
|
|
||||||
iso14a_polling_parameters_t REQA_POLLING_PARAMETERS = {
|
|
||||||
.frames = { {{ ISO14443A_CMD_REQA }, 1, 7, 0} },
|
|
||||||
.frame_count = 1,
|
|
||||||
.extra_timeout = 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
// parity isn't used much
|
// parity isn't used much
|
||||||
static uint8_t parity_array[MAX_PARITY_SIZE] = {0};
|
static uint8_t parity_array[MAX_PARITY_SIZE] = {0};
|
||||||
|
@ -191,6 +217,9 @@ void printHf14aConfig(void) {
|
||||||
(hf14aconfig.forcerats == 1) ? _RED_("force") " ( always do RATS )" : "",
|
(hf14aconfig.forcerats == 1) ? _RED_("force") " ( always do RATS )" : "",
|
||||||
(hf14aconfig.forcerats == 2) ? _RED_("skip") " ( always skip RATS )" : ""
|
(hf14aconfig.forcerats == 2) ? _RED_("skip") " ( always skip RATS )" : ""
|
||||||
);
|
);
|
||||||
|
Dbprintf(" [m] Magsafe polling............... %s",
|
||||||
|
(hf14aconfig.magsafe == 1) ? _GREEN_("enabled") : _YELLOW_("disabled")
|
||||||
|
);
|
||||||
Dbprintf(" [p] Polling loop annotation....... %s %*D",
|
Dbprintf(" [p] Polling loop annotation....... %s %*D",
|
||||||
(hf14aconfig.polling_loop_annotation.frame_length <= 0) ? _YELLOW_("disabled") : _GREEN_("enabled"),
|
(hf14aconfig.polling_loop_annotation.frame_length <= 0) ? _YELLOW_("disabled") : _GREEN_("enabled"),
|
||||||
hf14aconfig.polling_loop_annotation.frame_length,
|
hf14aconfig.polling_loop_annotation.frame_length,
|
||||||
|
@ -208,7 +237,6 @@ void printHf14aConfig(void) {
|
||||||
* @param sc
|
* @param sc
|
||||||
*/
|
*/
|
||||||
void setHf14aConfig(const hf14a_config *hc) {
|
void setHf14aConfig(const hf14a_config *hc) {
|
||||||
|
|
||||||
if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2))
|
if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2))
|
||||||
hf14aconfig.forceanticol = hc->forceanticol;
|
hf14aconfig.forceanticol = hc->forceanticol;
|
||||||
if ((hc->forcebcc >= 0) && (hc->forcebcc <= 2))
|
if ((hc->forcebcc >= 0) && (hc->forcebcc <= 2))
|
||||||
|
@ -219,12 +247,30 @@ void setHf14aConfig(const hf14a_config *hc) {
|
||||||
hf14aconfig.forcecl3 = hc->forcecl3;
|
hf14aconfig.forcecl3 = hc->forcecl3;
|
||||||
if ((hc->forcerats >= 0) && (hc->forcerats <= 2))
|
if ((hc->forcerats >= 0) && (hc->forcerats <= 2))
|
||||||
hf14aconfig.forcerats = hc->forcerats;
|
hf14aconfig.forcerats = hc->forcerats;
|
||||||
|
if ((hc->magsafe >= 0) && (hc->magsafe <= 1))
|
||||||
if (hc->polling_loop_annotation.frame_length > 0) {
|
hf14aconfig.magsafe = hc->magsafe;
|
||||||
|
if (hc->polling_loop_annotation.frame_length >= 0) {
|
||||||
memcpy(&hf14aconfig.polling_loop_annotation, &hc->polling_loop_annotation, sizeof(iso14a_polling_frame_t));
|
memcpy(&hf14aconfig.polling_loop_annotation, &hc->polling_loop_annotation, sizeof(iso14a_polling_frame_t));
|
||||||
} else if (hc->polling_loop_annotation.frame_length < 0) {
|
}
|
||||||
// Reset if set to empty
|
|
||||||
hf14aconfig.polling_loop_annotation.frame_length = 0;
|
// Derive polling loop configuration based on 14a config
|
||||||
|
hf14a_polling_parameters.frames[0] = WUPA_CMD;
|
||||||
|
hf14a_polling_parameters.frame_count = 1;
|
||||||
|
hf14a_polling_parameters.extra_timeout = 0;
|
||||||
|
if (hf14aconfig.magsafe == 1) {
|
||||||
|
for (int i = 0; i < ARRAYLEN(MAGWUPA_COMMANDS); i++) {
|
||||||
|
if (hf14a_polling_parameters.frame_count < ARRAYLEN(hf14a_polling_parameters.frames) - 1) {
|
||||||
|
hf14a_polling_parameters.frames[hf14a_polling_parameters.frame_count] = MAGWUPA_COMMANDS[i];
|
||||||
|
hf14a_polling_parameters.frame_count += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hf14aconfig.polling_loop_annotation.frame_length > 0) {
|
||||||
|
if (hf14a_polling_parameters.frame_count < ARRAYLEN(hf14a_polling_parameters.frames)) {
|
||||||
|
hf14a_polling_parameters.frames[hf14a_polling_parameters.frame_count] = hf14aconfig.polling_loop_annotation;
|
||||||
|
hf14a_polling_parameters.frame_count += 1;
|
||||||
|
}
|
||||||
|
hf14a_polling_parameters.extra_timeout = 250;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2560,8 +2606,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint16_t rec_max
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing) {
|
void ReaderTransmitBitsPar(const uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing) {
|
||||||
|
|
||||||
CodeIso14443aBitsAsReaderPar(frame, bits, par);
|
CodeIso14443aBitsAsReaderPar(frame, bits, par);
|
||||||
// Send command to tag
|
// Send command to tag
|
||||||
tosend_t *ts = get_tosend();
|
tosend_t *ts = get_tosend();
|
||||||
|
@ -2571,17 +2616,17 @@ void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t
|
||||||
LogTrace(frame, nbytes(bits), (LastTimeProxToAirStart << 4) + DELAY_ARM2AIR_AS_READER, ((LastTimeProxToAirStart + LastProxToAirDuration) << 4) + DELAY_ARM2AIR_AS_READER, par, true);
|
LogTrace(frame, nbytes(bits), (LastTimeProxToAirStart << 4) + DELAY_ARM2AIR_AS_READER, ((LastTimeProxToAirStart + LastProxToAirDuration) << 4) + DELAY_ARM2AIR_AS_READER, par, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing) {
|
void ReaderTransmitPar(const uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing) {
|
||||||
ReaderTransmitBitsPar(frame, len * 8, par, timing);
|
ReaderTransmitBitsPar(frame, len * 8, par, timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ReaderTransmitBits(uint8_t *frame, uint16_t len, uint32_t *timing) {
|
static void ReaderTransmitBits(const uint8_t *frame, uint16_t len, uint32_t *timing) {
|
||||||
// Generate parity and redirect
|
// Generate parity and redirect
|
||||||
GetParity(frame, len / 8, parity_array);
|
GetParity(frame, len / 8, parity_array);
|
||||||
ReaderTransmitBitsPar(frame, len, parity_array, timing);
|
ReaderTransmitBitsPar(frame, len, parity_array, timing);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing) {
|
void ReaderTransmit(const uint8_t *frame, uint16_t len, uint32_t *timing) {
|
||||||
// Generate parity and redirect
|
// Generate parity and redirect
|
||||||
GetParity(frame, len, parity_array);
|
GetParity(frame, len, parity_array);
|
||||||
ReaderTransmitBitsPar(frame, len * 8, parity_array, timing);
|
ReaderTransmitBitsPar(frame, len * 8, parity_array, timing);
|
||||||
|
@ -2708,42 +2753,23 @@ static void iso14a_set_ATS_times(const uint8_t *ats) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int GetATQA(uint8_t *resp, uint16_t resp_len, uint8_t *resp_par, iso14a_polling_parameters_t *polling_parameters) {
|
static int GetATQA(uint8_t *resp, uint16_t resp_len, uint8_t *resp_par, const iso14a_polling_parameters_t *polling_parameters) {
|
||||||
#define WUPA_RETRY_TIMEOUT 10
|
#define RETRY_TIMEOUT 10
|
||||||
|
|
||||||
uint32_t save_iso14a_timeout = iso14a_get_timeout();
|
uint32_t save_iso14a_timeout = iso14a_get_timeout();
|
||||||
iso14a_set_timeout(1236 / 128 + 1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer.
|
iso14a_set_timeout(1236 / 128 + 1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer.
|
||||||
|
|
||||||
// Create temporary polling parameters structure that might include both standard and custom frames
|
polling_parameters = polling_parameters != NULL ? polling_parameters : &hf14a_polling_parameters;
|
||||||
iso14a_polling_parameters_t temp_params;
|
|
||||||
memcpy(&temp_params, polling_parameters, sizeof(iso14a_polling_parameters_t));
|
|
||||||
|
|
||||||
// If we have a custom polling frame annotation, add it to the temporary structure
|
|
||||||
if (hf14aconfig.polling_loop_annotation.frame_length > 0) {
|
|
||||||
// Only add if we have space in the frames array
|
|
||||||
if (temp_params.frame_count < ARRAYLEN(temp_params.frames)) {
|
|
||||||
// Add the custom frame at the end of the frames array
|
|
||||||
memcpy(&temp_params.frames[temp_params.frame_count],
|
|
||||||
&hf14aconfig.polling_loop_annotation,
|
|
||||||
sizeof(iso14a_polling_frame_t));
|
|
||||||
temp_params.frame_count++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increase timeout if polling loop annotation is provided, as target may respond slower
|
|
||||||
if (temp_params.extra_timeout == 0) {
|
|
||||||
temp_params.extra_timeout = 250;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool first_try = true;
|
bool first_try = true;
|
||||||
int len;
|
int len;
|
||||||
uint32_t retry_timeout = WUPA_RETRY_TIMEOUT * temp_params.frame_count + temp_params.extra_timeout;
|
uint32_t retry_timeout = RETRY_TIMEOUT * polling_parameters->frame_count + polling_parameters->extra_timeout;
|
||||||
uint32_t start_time = 0;
|
uint32_t start_time = 0;
|
||||||
uint8_t current_frame = 0;
|
uint8_t current_frame = 0;
|
||||||
|
|
||||||
// Use the temporary polling parameters
|
// Use the temporary polling parameters
|
||||||
do {
|
do {
|
||||||
iso14a_polling_frame_t *frame_parameters = &temp_params.frames[current_frame];
|
const iso14a_polling_frame_t *frame_parameters = &polling_parameters->frames[current_frame];
|
||||||
|
|
||||||
if (frame_parameters->last_byte_bits == 8) {
|
if (frame_parameters->last_byte_bits == 8) {
|
||||||
ReaderTransmit(frame_parameters->frame, frame_parameters->frame_length, NULL);
|
ReaderTransmit(frame_parameters->frame, frame_parameters->frame_length, NULL);
|
||||||
|
@ -2765,7 +2791,7 @@ static int GetATQA(uint8_t *resp, uint16_t resp_len, uint8_t *resp_par, iso14a_p
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go over frame configurations, loop back when we reach the end
|
// Go over frame configurations, loop back when we reach the end
|
||||||
current_frame = current_frame < (temp_params.frame_count - 1) ? current_frame + 1 : 0;
|
current_frame = current_frame < (polling_parameters->frame_count - 1) ? current_frame + 1 : 0;
|
||||||
} while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout);
|
} while (len == 0 && GetTickCountDelta(start_time) <= retry_timeout);
|
||||||
|
|
||||||
iso14a_set_timeout(save_iso14a_timeout);
|
iso14a_set_timeout(save_iso14a_timeout);
|
||||||
|
@ -2774,7 +2800,7 @@ static int GetATQA(uint8_t *resp, uint16_t resp_len, uint8_t *resp_par, iso14a_p
|
||||||
|
|
||||||
|
|
||||||
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) {
|
int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) {
|
||||||
return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, no_rats, &WUPA_POLLING_PARAMETERS);
|
return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, no_rats, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -3047,7 +3073,7 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) {
|
||||||
uint8_t sak = 0x04; // cascade uid
|
uint8_t sak = 0x04; // cascade uid
|
||||||
int cascade_level = 1;
|
int cascade_level = 1;
|
||||||
|
|
||||||
if (GetATQA(resp, sizeof(resp), resp_par, &WUPA_POLLING_PARAMETERS) == 0) {
|
if (GetATQA(resp, sizeof(resp), resp_par, NULL) == 0) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3280,7 +3306,7 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
||||||
true,
|
true,
|
||||||
0,
|
0,
|
||||||
((param & ISO14A_NO_RATS) == ISO14A_NO_RATS),
|
((param & ISO14A_NO_RATS) == ISO14A_NO_RATS),
|
||||||
((param & ISO14A_USE_CUSTOM_POLLING) == ISO14A_USE_CUSTOM_POLLING) ? (iso14a_polling_parameters_t *)cmd : &WUPA_POLLING_PARAMETERS
|
((param & ISO14A_USE_CUSTOM_POLLING) == ISO14A_USE_CUSTOM_POLLING) ? (iso14a_polling_parameters_t *)cmd : NULL
|
||||||
);
|
);
|
||||||
// TODO: Improve by adding a cmd parser pointer and moving it by struct length to allow combining data with polling params
|
// TODO: Improve by adding a cmd parser pointer and moving it by struct length to allow combining data with polling params
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
|
|
@ -157,9 +157,9 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data,
|
||||||
bool GetIso14443aCommandFromReader(uint8_t *received, uint16_t received_maxlen, uint8_t *par, int *len);
|
bool GetIso14443aCommandFromReader(uint8_t *received, uint16_t received_maxlen, uint8_t *par, int *len);
|
||||||
void iso14443a_antifuzz(uint32_t flags);
|
void iso14443a_antifuzz(uint32_t flags);
|
||||||
void ReaderIso14443a(PacketCommandNG *c);
|
void ReaderIso14443a(PacketCommandNG *c);
|
||||||
void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing);
|
void ReaderTransmit(const uint8_t *frame, uint16_t len, uint32_t *timing);
|
||||||
void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing);
|
void ReaderTransmitBitsPar(const uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing);
|
||||||
void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing);
|
void ReaderTransmitPar(const uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing);
|
||||||
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint16_t answer_maxlen, uint8_t *par);
|
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint16_t answer_maxlen, uint8_t *par);
|
||||||
|
|
||||||
void iso14443a_setup(uint8_t fpga_minor_mode);
|
void iso14443a_setup(uint8_t fpga_minor_mode);
|
||||||
|
|
|
@ -58,34 +58,6 @@ static int CmdHelp(const char *Cmd);
|
||||||
static int waitCmd(bool i_select, uint32_t timeout, bool verbose);
|
static int waitCmd(bool i_select, uint32_t timeout, bool verbose);
|
||||||
|
|
||||||
|
|
||||||
static const iso14a_polling_frame_t WUPA_FRAME = {
|
|
||||||
{ 0x52 }, 1, 7, 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame_t MAGWUPA1_FRAME = {
|
|
||||||
{ 0x7A }, 1, 7, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame_t MAGWUPA2_FRAME = {
|
|
||||||
{ 0x7B }, 1, 7, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame_t MAGWUPA3_FRAME = {
|
|
||||||
{ 0x7C }, 1, 7, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame_t MAGWUPA4_FRAME = {
|
|
||||||
{ 0x7D }, 1, 7, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame_t ECP_FRAME = {
|
|
||||||
.frame = { 0x6a, 0x02, 0xC8, 0x01, 0x00, 0x03, 0x00, 0x02, 0x79, 0x00, 0x00, 0x00, 0x00, 0xC2, 0xD8},
|
|
||||||
.frame_length = 15,
|
|
||||||
.last_byte_bits = 8,
|
|
||||||
.extra_delay = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// based on ISO/IEC JTC1/SC17 STANDING DOCUMENT 5 (Updated 20 September 2024) Register of IC manufacturers
|
// based on ISO/IEC JTC1/SC17 STANDING DOCUMENT 5 (Updated 20 September 2024) Register of IC manufacturers
|
||||||
static const manufactureName_t manufactureMapping[] = {
|
static const manufactureName_t manufactureMapping[] = {
|
||||||
// ID, "Vendor Country"
|
// ID, "Vendor Country"
|
||||||
|
@ -370,8 +342,10 @@ static int CmdHf14AConfig(const char *Cmd) {
|
||||||
"hf 14a config --rats std -> Follow standard\n"
|
"hf 14a config --rats std -> Follow standard\n"
|
||||||
"hf 14a config --rats force -> Execute RATS\n"
|
"hf 14a config --rats force -> Execute RATS\n"
|
||||||
"hf 14a config --rats skip -> Skip RATS\n"
|
"hf 14a config --rats skip -> Skip RATS\n"
|
||||||
|
"hf 14a config --mag on -> Enable Apple magsafe polling\n"
|
||||||
|
"hf 14a config --mag off -> Disable Apple magsafe polling\n"
|
||||||
"hf 14a config --pla <hex> -> Set polling loop annotation (max 22 bytes)\n"
|
"hf 14a config --pla <hex> -> Set polling loop annotation (max 22 bytes)\n"
|
||||||
"hf 14a config --pla skip -> Disable polling loop annotation\n");
|
"hf 14a config --pla off -> Disable polling loop annotation\n");
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
arg_param_begin,
|
arg_param_begin,
|
||||||
arg_str0(NULL, "atqa", "<std|force|skip>", "Configure ATQA<>anticollision behavior"),
|
arg_str0(NULL, "atqa", "<std|force|skip>", "Configure ATQA<>anticollision behavior"),
|
||||||
|
@ -379,14 +353,15 @@ static int CmdHf14AConfig(const char *Cmd) {
|
||||||
arg_str0(NULL, "cl2", "<std|force|skip>", "Configure SAK<>CL2 behavior"),
|
arg_str0(NULL, "cl2", "<std|force|skip>", "Configure SAK<>CL2 behavior"),
|
||||||
arg_str0(NULL, "cl3", "<std|force|skip>", "Configure SAK<>CL3 behavior"),
|
arg_str0(NULL, "cl3", "<std|force|skip>", "Configure SAK<>CL3 behavior"),
|
||||||
arg_str0(NULL, "rats", "<std|force|skip>", "Configure RATS behavior"),
|
arg_str0(NULL, "rats", "<std|force|skip>", "Configure RATS behavior"),
|
||||||
arg_str0(NULL, "pla", "<hex|skip>", "Configure polling loop annotation"),
|
arg_str0(NULL, "mag", "<on|off>", "Configure Apple MagSafe polling"),
|
||||||
|
arg_str0(NULL, "pla", "<hex|off>", "Configure polling loop annotation"),
|
||||||
arg_lit0(NULL, "std", "Reset default configuration: follow all standard"),
|
arg_lit0(NULL, "std", "Reset default configuration: follow all standard"),
|
||||||
arg_lit0("v", "verbose", "verbose output"),
|
arg_lit0("v", "verbose", "verbose output"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
};
|
};
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
bool defaults = arg_get_lit(ctx, 7);
|
bool defaults = arg_get_lit(ctx, 8);
|
||||||
bool verbose = arg_get_lit(ctx, 8);
|
bool verbose = arg_get_lit(ctx, 9);
|
||||||
|
|
||||||
int vlen = 0;
|
int vlen = 0;
|
||||||
char value[64];
|
char value[64];
|
||||||
|
@ -450,39 +425,57 @@ static int CmdHf14AConfig(const char *Cmd) {
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
int magsafe = defaults ? 0 : -1;
|
||||||
|
CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)value, sizeof(value), &vlen);
|
||||||
|
if (vlen > 0) {
|
||||||
|
if (strcmp(value, "std") == 0) magsafe = 0;
|
||||||
|
else if (strcmp(value, "skip") == 0) magsafe = 0;
|
||||||
|
else if (strcmp(value, "disable") == 0) magsafe = 0;
|
||||||
|
else if (strcmp(value, "off") == 0) magsafe = 0;
|
||||||
|
else if (strcmp(value, "enable") == 0) magsafe = 1;
|
||||||
|
else if (strcmp(value, "on") == 0) magsafe = 1;
|
||||||
|
else {
|
||||||
|
PrintAndLogEx(ERR, "magsafe argument must be 'std', 'skip', 'off', 'disable', 'on' or 'enable'");
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Handle polling loop annotation parameter
|
// Handle polling loop annotation parameter
|
||||||
iso14a_polling_frame_t pla = {
|
iso14a_polling_frame_t pla = {
|
||||||
// -1 signals that PLA has to be disabled, 0 signals that no change has to be made
|
// 0 signals that PLA has to be disabled, -1 signals that no change has to be made
|
||||||
.frame_length = defaults ? -1 : 0,
|
.frame_length = defaults ? 0 : -1,
|
||||||
.last_byte_bits = 8,
|
.last_byte_bits = 8,
|
||||||
.extra_delay = 5
|
.extra_delay = 5
|
||||||
};
|
};
|
||||||
CLIParamStrToBuf(arg_get_str(ctx, 6), (uint8_t *)value, sizeof(value), &vlen);
|
CLIParamStrToBuf(arg_get_str(ctx, 7), (uint8_t *)value, sizeof(value), &vlen);
|
||||||
if (vlen > 0 && (strncmp((char *)value, "skip", 4) || strncmp((char *)value, "std", 3)) == 0) {
|
if (vlen > 0) {
|
||||||
pla.frame_length = -1;
|
if (strncmp((char *)value, "std", 3) == 0) pla.frame_length = 0;
|
||||||
} else if (vlen > 0) {
|
else if (strncmp((char *)value, "skip", 4) == 0) pla.frame_length = 0;
|
||||||
// Convert hex string to bytes
|
else if (strncmp((char *)value, "disable", 3) == 0) pla.frame_length = 0;
|
||||||
int length = 0;
|
else if (strncmp((char *)value, "off", 3) == 0) pla.frame_length = 0;
|
||||||
if (param_gethex_to_eol((char *)value, 0, pla.frame, sizeof(pla.frame), &length) != 0) {
|
else {
|
||||||
PrintAndLogEx(ERR, "Error parsing polling loop annotation bytes");
|
// Convert hex string to bytes
|
||||||
CLIParserFree(ctx);
|
int length = 0;
|
||||||
return PM3_EINVARG;
|
if (param_gethex_to_eol((char *)value, 0, pla.frame, sizeof(pla.frame), &length) != 0) {
|
||||||
}
|
PrintAndLogEx(ERR, "Error parsing polling loop annotation bytes");
|
||||||
pla.frame_length = length;
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
pla.frame_length = length;
|
||||||
|
|
||||||
// Validate length before adding CRC
|
// Validate length before adding CRC
|
||||||
if (pla.frame_length < 1 || pla.frame_length > 22) {
|
if (pla.frame_length < 1 || pla.frame_length > 22) {
|
||||||
PrintAndLogEx(ERR, "Polling loop annotation length invalid: min %d; max %d", 1, 22);
|
PrintAndLogEx(ERR, "Polling loop annotation length invalid: min %d; max %d", 1, 22);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t first, second;
|
uint8_t first, second;
|
||||||
compute_crc(CRC_14443_A, pla.frame, pla.frame_length, &first, &second);
|
compute_crc(CRC_14443_A, pla.frame, pla.frame_length, &first, &second);
|
||||||
pla.frame[pla.frame_length++] = first;
|
pla.frame[pla.frame_length++] = first;
|
||||||
pla.frame[pla.frame_length++] = second;
|
pla.frame[pla.frame_length++] = second;
|
||||||
PrintAndLogEx(INFO, "Added CRC16A to polling loop annotation: %s", sprint_hex(pla.frame, pla.frame_length));
|
PrintAndLogEx(INFO, "Added CRC16A to polling loop annotation: %s", sprint_hex(pla.frame, pla.frame_length));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
@ -503,6 +496,7 @@ static int CmdHf14AConfig(const char *Cmd) {
|
||||||
.forcecl2 = cl2,
|
.forcecl2 = cl2,
|
||||||
.forcecl3 = cl3,
|
.forcecl3 = cl3,
|
||||||
.forcerats = rats,
|
.forcerats = rats,
|
||||||
|
.magsafe = magsafe,
|
||||||
.polling_loop_annotation = pla
|
.polling_loop_annotation = pla
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -595,48 +589,12 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
iso14a_polling_parameters_t iso14a_get_polling_parameters(bool use_ecp, bool use_magsafe) {
|
|
||||||
// Extra 100ms give enough time for Apple (ECP) devices to proccess field info and make a decision
|
|
||||||
|
|
||||||
if (use_ecp && use_magsafe) {
|
|
||||||
iso14a_polling_parameters_t full_polling_parameters = {
|
|
||||||
.frames = { WUPA_FRAME, ECP_FRAME, MAGWUPA1_FRAME, MAGWUPA2_FRAME, MAGWUPA3_FRAME, MAGWUPA4_FRAME },
|
|
||||||
.frame_count = 6,
|
|
||||||
.extra_timeout = 100
|
|
||||||
};
|
|
||||||
return full_polling_parameters;
|
|
||||||
} else if (use_ecp) {
|
|
||||||
iso14a_polling_parameters_t ecp_polling_parameters = {
|
|
||||||
.frames = { WUPA_FRAME, ECP_FRAME },
|
|
||||||
.frame_count = 2,
|
|
||||||
.extra_timeout = 100
|
|
||||||
};
|
|
||||||
return ecp_polling_parameters;
|
|
||||||
} else if (use_magsafe) {
|
|
||||||
iso14a_polling_parameters_t magsafe_polling_parameters = {
|
|
||||||
.frames = { WUPA_FRAME, MAGWUPA1_FRAME, MAGWUPA2_FRAME, MAGWUPA3_FRAME, MAGWUPA4_FRAME },
|
|
||||||
.frame_count = 5,
|
|
||||||
.extra_timeout = 0
|
|
||||||
};
|
|
||||||
return magsafe_polling_parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
iso14a_polling_parameters_t wupa_polling_parameters = {
|
|
||||||
.frames = { WUPA_FRAME },
|
|
||||||
.frame_count = 1,
|
|
||||||
.extra_timeout = 0,
|
|
||||||
};
|
|
||||||
return wupa_polling_parameters;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int CmdHF14AReader(const char *Cmd) {
|
static int CmdHF14AReader(const char *Cmd) {
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
CLIParserInit(&ctx, "hf 14a reader",
|
CLIParserInit(&ctx, "hf 14a reader",
|
||||||
"Act as a ISO-14443a reader to identify tag. Look for ISO-14443a tags until Enter or the pm3 button is pressed",
|
"Act as a ISO-14443a reader to identify tag. Look for ISO-14443a tags until Enter or the pm3 button is pressed",
|
||||||
"hf 14a reader\n"
|
"hf 14a reader\n"
|
||||||
"hf 14a reader -@ -> Continuous mode\n"
|
"hf 14a reader -@ -> Continuous mode\n"
|
||||||
"hf 14a reader --ecp -> trigger apple enhanced contactless polling\n"
|
|
||||||
"hf 14a reader --mag -> trigger apple magsafe polling\n"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
void *argtable[] = {
|
void *argtable[] = {
|
||||||
|
@ -645,8 +603,6 @@ static int CmdHF14AReader(const char *Cmd) {
|
||||||
arg_lit0("s", "silent", "silent (no messages)"),
|
arg_lit0("s", "silent", "silent (no messages)"),
|
||||||
arg_lit0(NULL, "drop", "just drop the signal field"),
|
arg_lit0(NULL, "drop", "just drop the signal field"),
|
||||||
arg_lit0(NULL, "skip", "ISO14443-3 select only (skip RATS)"),
|
arg_lit0(NULL, "skip", "ISO14443-3 select only (skip RATS)"),
|
||||||
arg_lit0(NULL, "ecp", "Use enhanced contactless polling"),
|
|
||||||
arg_lit0(NULL, "mag", "Use Apple magsafe polling"),
|
|
||||||
arg_lit0("@", NULL, "continuous reader mode"),
|
arg_lit0("@", NULL, "continuous reader mode"),
|
||||||
arg_lit0("w", "wait", "wait for card"),
|
arg_lit0("w", "wait", "wait for card"),
|
||||||
arg_param_end
|
arg_param_end
|
||||||
|
@ -669,18 +625,8 @@ static int CmdHF14AReader(const char *Cmd) {
|
||||||
cm |= ISO14A_NO_RATS;
|
cm |= ISO14A_NO_RATS;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool use_ecp = arg_get_lit(ctx, 5);
|
bool continuous = arg_get_lit(ctx, 5);
|
||||||
bool use_magsafe = arg_get_lit(ctx, 6);
|
bool wait = arg_get_lit(ctx, 6);
|
||||||
|
|
||||||
iso14a_polling_parameters_t *polling_parameters = NULL;
|
|
||||||
iso14a_polling_parameters_t parameters = iso14a_get_polling_parameters(use_ecp, use_magsafe);
|
|
||||||
if (use_ecp || use_magsafe) {
|
|
||||||
cm |= ISO14A_USE_CUSTOM_POLLING;
|
|
||||||
polling_parameters = ¶meters;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool continuous = arg_get_lit(ctx, 7);
|
|
||||||
bool wait = arg_get_lit(ctx, 8);
|
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
|
@ -695,12 +641,7 @@ static int CmdHF14AReader(const char *Cmd) {
|
||||||
int res = PM3_SUCCESS;
|
int res = PM3_SUCCESS;
|
||||||
do {
|
do {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, NULL, 0);
|
||||||
if ((cm & ISO14A_USE_CUSTOM_POLLING) == ISO14A_USE_CUSTOM_POLLING) {
|
|
||||||
SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, (uint8_t *)polling_parameters, sizeof(iso14a_polling_parameters_t));
|
|
||||||
} else {
|
|
||||||
SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, NULL, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((cm & ISO14A_CONNECT) == ISO14A_CONNECT) {
|
if ((cm & ISO14A_CONNECT) == ISO14A_CONNECT) {
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
@ -1462,9 +1403,10 @@ static int CmdHF14AAPDU(const char *Cmd) {
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool extendedAPDU = arg_get_lit(ctx, 6);
|
bool extendedAPDU = arg_get_lit(ctx, 6);
|
||||||
int le = arg_get_int_def(ctx, 7, 0);
|
int le = arg_get_int_def(ctx, 7, 0);
|
||||||
|
|
||||||
uint8_t data[PM3_CMD_DATA_SIZE];
|
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||||
int datalen = 0;
|
int datalen = 0;
|
||||||
|
|
||||||
|
@ -1546,7 +1488,6 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
||||||
"Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
|
"Sends raw bytes over ISO14443a. With option to use TOPAZ 14a mode.",
|
||||||
"hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
|
"hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n"
|
||||||
"hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
|
"hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n"
|
||||||
"hf 14a raw --ecp -s -> send ECP before select\n"
|
|
||||||
"Crypto1 session example, with special auth shortcut 6xxx<key>:\n"
|
"Crypto1 session example, with special auth shortcut 6xxx<key>:\n"
|
||||||
"hf 14a raw --crypto1 -skc 6000FFFFFFFFFFFF\n"
|
"hf 14a raw --crypto1 -skc 6000FFFFFFFFFFFF\n"
|
||||||
"hf 14a raw --crypto1 -kc 3000\n"
|
"hf 14a raw --crypto1 -kc 3000\n"
|
||||||
|
@ -1565,8 +1506,6 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
||||||
arg_int0("t", "timeout", "<ms>", "Timeout in milliseconds"),
|
arg_int0("t", "timeout", "<ms>", "Timeout in milliseconds"),
|
||||||
arg_int0("b", NULL, "<dec>", "Number of bits to send. Useful for send partial byte"),
|
arg_int0("b", NULL, "<dec>", "Number of bits to send. Useful for send partial byte"),
|
||||||
arg_lit0("v", "verbose", "Verbose output"),
|
arg_lit0("v", "verbose", "Verbose output"),
|
||||||
arg_lit0(NULL, "ecp", "Use enhanced contactless polling"),
|
|
||||||
arg_lit0(NULL, "mag", "Use Apple magsafe polling"),
|
|
||||||
arg_lit0(NULL, "topaz", "Use Topaz protocol to send command"),
|
arg_lit0(NULL, "topaz", "Use Topaz protocol to send command"),
|
||||||
arg_lit0(NULL, "crypto1", "Use crypto1 session"),
|
arg_lit0(NULL, "crypto1", "Use crypto1 session"),
|
||||||
arg_strx1(NULL, NULL, "<hex>", "Raw bytes to send"),
|
arg_strx1(NULL, NULL, "<hex>", "Raw bytes to send"),
|
||||||
|
@ -1583,14 +1522,12 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
||||||
uint32_t timeout = (uint32_t)arg_get_int_def(ctx, 7, 0);
|
uint32_t timeout = (uint32_t)arg_get_int_def(ctx, 7, 0);
|
||||||
uint16_t numbits = (uint16_t)arg_get_int_def(ctx, 8, 0);
|
uint16_t numbits = (uint16_t)arg_get_int_def(ctx, 8, 0);
|
||||||
bool verbose = arg_get_lit(ctx, 9);
|
bool verbose = arg_get_lit(ctx, 9);
|
||||||
bool use_ecp = arg_get_lit(ctx, 10);
|
bool topazmode = arg_get_lit(ctx, 10);
|
||||||
bool use_magsafe = arg_get_lit(ctx, 11);
|
bool crypto1mode = arg_get_lit(ctx, 11);
|
||||||
bool topazmode = arg_get_lit(ctx, 12);
|
|
||||||
bool crypto1mode = arg_get_lit(ctx, 13);
|
|
||||||
|
|
||||||
int datalen = 0;
|
int datalen = 0;
|
||||||
uint8_t data[PM3_CMD_DATA_SIZE_MIX] = {0};
|
uint8_t data[PM3_CMD_DATA_SIZE_MIX] = {0};
|
||||||
CLIGetHexWithReturn(ctx, 14, data, &datalen);
|
CLIGetHexWithReturn(ctx, 12, data, &datalen);
|
||||||
CLIParserFree(ctx);
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
bool bTimeout = (timeout) ? true : false;
|
bool bTimeout = (timeout) ? true : false;
|
||||||
|
@ -1646,7 +1583,7 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
||||||
|
|
||||||
if (crypto1mode) {
|
if (crypto1mode) {
|
||||||
flags |= ISO14A_CRYPTO1MODE;
|
flags |= ISO14A_CRYPTO1MODE;
|
||||||
if (numbits > 0 || topazmode || use_ecp || use_magsafe) {
|
if (numbits > 0 || topazmode) {
|
||||||
PrintAndLogEx(FAILED, "crypto1 mode cannot be used with other modes or partial bytes");
|
PrintAndLogEx(FAILED, "crypto1 mode cannot be used with other modes or partial bytes");
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
@ -1656,13 +1593,6 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
||||||
flags |= ISO14A_NO_RATS;
|
flags |= ISO14A_NO_RATS;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: allow to use reader command with both data and polling configuration
|
|
||||||
if (use_ecp || use_magsafe) {
|
|
||||||
PrintAndLogEx(WARNING, "ECP and Magsafe not supported with this command at this moment. Instead use 'hf 14a reader -sk --ecp/--mag'");
|
|
||||||
// flags |= ISO14A_USE_MAGSAFE;
|
|
||||||
// flags |= ISO14A_USE_ECP;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Max buffer is PM3_CMD_DATA_SIZE_MIX
|
// Max buffer is PM3_CMD_DATA_SIZE_MIX
|
||||||
datalen = (datalen > PM3_CMD_DATA_SIZE_MIX) ? PM3_CMD_DATA_SIZE_MIX : datalen;
|
datalen = (datalen > PM3_CMD_DATA_SIZE_MIX) ? PM3_CMD_DATA_SIZE_MIX : datalen;
|
||||||
|
|
||||||
|
|
|
@ -70,7 +70,6 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card);
|
||||||
int ExchangeAPDU14a(const uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
|
int ExchangeAPDU14a(const uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
|
||||||
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode);
|
int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool silentMode);
|
||||||
|
|
||||||
iso14a_polling_parameters_t iso14a_get_polling_parameters(bool use_ecp, bool use_magsafe);
|
|
||||||
int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card);
|
int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card);
|
||||||
int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card_select_t *card, iso14a_polling_parameters_t *polling_parameters);
|
int SelectCard14443A_4_WithParameters(bool disconnect, bool verbose, iso14a_card_select_t *card, iso14a_polling_parameters_t *polling_parameters);
|
||||||
|
|
||||||
|
|
|
@ -1324,7 +1324,6 @@
|
||||||
"notes": [
|
"notes": [
|
||||||
"hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'",
|
"hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'",
|
||||||
"hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40",
|
"hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40",
|
||||||
"hf 14a raw --ecp -s -> send ECP before select",
|
|
||||||
"Crypto1 session example, with special auth shortcut 6xxx<key>:",
|
"Crypto1 session example, with special auth shortcut 6xxx<key>:",
|
||||||
"hf 14a raw --crypto1 -skc 6000FFFFFFFFFFFF",
|
"hf 14a raw --crypto1 -skc 6000FFFFFFFFFFFF",
|
||||||
"hf 14a raw --crypto1 -kc 3000",
|
"hf 14a raw --crypto1 -kc 3000",
|
||||||
|
@ -1343,13 +1342,12 @@
|
||||||
"-t, --timeout <ms> Timeout in milliseconds",
|
"-t, --timeout <ms> Timeout in milliseconds",
|
||||||
"-b <dec> Number of bits to send. Useful for send partial byte",
|
"-b <dec> Number of bits to send. Useful for send partial byte",
|
||||||
"-v, --verbose Verbose output",
|
"-v, --verbose Verbose output",
|
||||||
"--ecp Use enhanced contactless polling",
|
|
||||||
"--mag Use Apple magsafe polling",
|
"--mag Use Apple magsafe polling",
|
||||||
"--topaz Use Topaz protocol to send command",
|
"--topaz Use Topaz protocol to send command",
|
||||||
"--crypto1 Use crypto1 session",
|
"--crypto1 Use crypto1 session",
|
||||||
"<hex> Raw bytes to send"
|
"<hex> Raw bytes to send"
|
||||||
],
|
],
|
||||||
"usage": "hf 14a raw [-hack3rsv] [-t <ms>] [-b <dec>] [--ecp] [--mag] [--topaz] [--crypto1] <hex> [<hex>]..."
|
"usage": "hf 14a raw [-hack3rsv] [-t <ms>] [-b <dec>] [--topaz] [--crypto1] <hex> [<hex>]..."
|
||||||
},
|
},
|
||||||
"hf 14a reader": {
|
"hf 14a reader": {
|
||||||
"command": "hf 14a reader",
|
"command": "hf 14a reader",
|
||||||
|
@ -1357,7 +1355,6 @@
|
||||||
"notes": [
|
"notes": [
|
||||||
"hf 14a reader",
|
"hf 14a reader",
|
||||||
"hf 14a reader -@ -> Continuous mode",
|
"hf 14a reader -@ -> Continuous mode",
|
||||||
"hf 14a reader --ecp -> trigger apple enhanced contactless polling",
|
|
||||||
"hf 14a reader --mag -> trigger apple magsafe polling"
|
"hf 14a reader --mag -> trigger apple magsafe polling"
|
||||||
],
|
],
|
||||||
"offline": false,
|
"offline": false,
|
||||||
|
@ -1367,12 +1364,11 @@
|
||||||
"-s, --silent silent (no messages)",
|
"-s, --silent silent (no messages)",
|
||||||
"--drop just drop the signal field",
|
"--drop just drop the signal field",
|
||||||
"--skip ISO14443-3 select only (skip RATS)",
|
"--skip ISO14443-3 select only (skip RATS)",
|
||||||
"--ecp Use enhanced contactless polling",
|
|
||||||
"--mag Use Apple magsafe polling",
|
"--mag Use Apple magsafe polling",
|
||||||
"-@ continuous reader mode",
|
"-@ continuous reader mode",
|
||||||
"-w, --wait wait for card"
|
"-w, --wait wait for card"
|
||||||
],
|
],
|
||||||
"usage": "hf 14a reader [-hks@w] [--drop] [--skip] [--ecp] [--mag]"
|
"usage": "hf 14a reader [-hks@w] [--drop] [--skip]"
|
||||||
},
|
},
|
||||||
"hf 14a sim": {
|
"hf 14a sim": {
|
||||||
"command": "hf 14a sim",
|
"command": "hf 14a sim",
|
||||||
|
|
|
@ -133,7 +133,7 @@ typedef struct {
|
||||||
|
|
||||||
|
|
||||||
// Defines a frame that will be used in a polling sequence
|
// Defines a frame that will be used in a polling sequence
|
||||||
// Polling loop annotations are up to (7 + 16) bytes long, 24 bytes should cover future and other cases
|
// Polling loop annotations are up to 20 bytes long, 24 bytes should cover future and other cases
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t frame[24];
|
uint8_t frame[24];
|
||||||
// negative values can be used to carry special info
|
// negative values can be used to carry special info
|
||||||
|
@ -144,8 +144,8 @@ typedef struct {
|
||||||
|
|
||||||
|
|
||||||
// Defines polling sequence configuration
|
// Defines polling sequence configuration
|
||||||
// 6 would be enough for 4 magsafe, 1 wupa, 1 pla,
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
// 6 would be enough for 4 magsafe, 1 wupa, 1 pla,
|
||||||
iso14a_polling_frame_t frames[6];
|
iso14a_polling_frame_t frames[6];
|
||||||
int8_t frame_count;
|
int8_t frame_count;
|
||||||
uint16_t extra_timeout;
|
uint16_t extra_timeout;
|
||||||
|
@ -159,6 +159,7 @@ typedef struct {
|
||||||
int8_t forcecl2; // 0:auto 1:force executing CL2 2:force skipping CL2
|
int8_t forcecl2; // 0:auto 1:force executing CL2 2:force skipping CL2
|
||||||
int8_t forcecl3; // 0:auto 1:force executing CL3 2:force skipping CL3
|
int8_t forcecl3; // 0:auto 1:force executing CL3 2:force skipping CL3
|
||||||
int8_t forcerats; // 0:auto 1:force executing RATS 2:force skipping RATS
|
int8_t forcerats; // 0:auto 1:force executing RATS 2:force skipping RATS
|
||||||
|
int8_t magsafe; // 0:disabled 1:enabled
|
||||||
iso14a_polling_frame_t polling_loop_annotation; // Polling loop annotation
|
iso14a_polling_frame_t polling_loop_annotation; // Polling loop annotation
|
||||||
} PACKED hf14a_config;
|
} PACKED hf14a_config;
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue