mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-22 14:23:50 -07:00
Merge pull request #2041 from kormax/new-iso14443a-polling
Move custom polling frames to client
This commit is contained in:
commit
3397198127
6 changed files with 166 additions and 133 deletions
|
@ -144,61 +144,10 @@ static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ;
|
||||||
|
|
||||||
|
|
||||||
// Polling frames and configurations
|
// Polling frames and configurations
|
||||||
|
|
||||||
/*static iso14a_polling_frame REQA_FRAME = {
|
|
||||||
{ 0x26 }, 1, 7, 0
|
|
||||||
};*/
|
|
||||||
|
|
||||||
static const iso14a_polling_frame WUPA_FRAME = {
|
|
||||||
{ 0x52 }, 1, 7, 0,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame MAGWUPA1_FRAME = {
|
|
||||||
{ 0x7A }, 1, 7, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame MAGWUPA2_FRAME = {
|
|
||||||
{ 0x7B }, 1, 7, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame MAGWUPA3_FRAME = {
|
|
||||||
{ 0x7C }, 1, 7, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame MAGWUPA4_FRAME = {
|
|
||||||
{ 0x7D }, 1, 7, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
static const iso14a_polling_frame 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
|
|
||||||
};
|
|
||||||
|
|
||||||
static iso14a_polling_parameters WUPA_POLLING_PARAMETERS = {
|
static iso14a_polling_parameters WUPA_POLLING_PARAMETERS = {
|
||||||
.frames = { WUPA_FRAME },
|
.frames={ {{ 0x52 }, 1, 7, 0} },
|
||||||
.frame_count = 1,
|
.frame_count=1,
|
||||||
.extra_timeout = 0,
|
.extra_timeout=0,
|
||||||
};
|
|
||||||
|
|
||||||
static iso14a_polling_parameters MAGSAFE_POLLING_PARAMETERS = {
|
|
||||||
.frames = { WUPA_FRAME, MAGWUPA1_FRAME, MAGWUPA2_FRAME, MAGWUPA3_FRAME, MAGWUPA4_FRAME },
|
|
||||||
.frame_count = 5,
|
|
||||||
.extra_timeout = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
// Extra 100ms give enough time for Apple devices to proccess field info and make a decision
|
|
||||||
static iso14a_polling_parameters ECP_POLLING_PARAMETERS = {
|
|
||||||
.frames = { WUPA_FRAME, ECP_FRAME },
|
|
||||||
.frame_count = 2,
|
|
||||||
.extra_timeout = 100
|
|
||||||
};
|
|
||||||
|
|
||||||
static iso14a_polling_parameters FULL_POLLING_PARAMETERS = {
|
|
||||||
.frames = { WUPA_FRAME, ECP_FRAME, MAGWUPA1_FRAME, MAGWUPA2_FRAME, MAGWUPA3_FRAME, MAGWUPA4_FRAME },
|
|
||||||
.frame_count = 6,
|
|
||||||
.extra_timeout = 100
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -2569,31 +2518,30 @@ static void iso14a_set_ATS_times(const uint8_t *ats) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int GetATQA(uint8_t *resp, uint8_t *resp_par, iso14a_polling_parameters parameters) {
|
static int GetATQA(uint8_t *resp, uint8_t *resp_par, iso14a_polling_parameters *polling_parameters) {
|
||||||
#define WUPA_RETRY_TIMEOUT 10
|
#define WUPA_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.
|
||||||
|
|
||||||
bool first_try = true;
|
bool first_try = true;
|
||||||
uint32_t retry_timeout = WUPA_RETRY_TIMEOUT * parameters.frame_count + parameters.extra_timeout;
|
uint32_t retry_timeout = WUPA_RETRY_TIMEOUT * polling_parameters->frame_count + polling_parameters->extra_timeout;
|
||||||
uint32_t start_time;
|
uint32_t start_time;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
uint8_t current_frame = 0;
|
uint8_t current_frame = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
iso14a_polling_frame frame_parameters = parameters.frames[current_frame];
|
iso14a_polling_frame *frame_parameters = &polling_parameters->frames[current_frame];
|
||||||
|
|
||||||
if (frame_parameters.last_byte_bits == 8) {
|
|
||||||
ReaderTransmit(frame_parameters.frame, frame_parameters.frame_length, NULL);
|
|
||||||
|
|
||||||
|
if (frame_parameters->last_byte_bits == 8) {
|
||||||
|
ReaderTransmit(frame_parameters->frame, frame_parameters->frame_length, NULL);
|
||||||
} else {
|
} else {
|
||||||
ReaderTransmitBitsPar(frame_parameters.frame, frame_parameters.last_byte_bits, NULL, NULL);
|
ReaderTransmitBitsPar(frame_parameters->frame, frame_parameters->last_byte_bits, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame_parameters.extra_delay) {
|
if (frame_parameters->extra_delay) {
|
||||||
SpinDelay(frame_parameters.extra_delay);
|
SpinDelay(frame_parameters->extra_delay);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receive the ATQA
|
// Receive the ATQA
|
||||||
|
@ -2606,8 +2554,8 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par, iso14a_polling_parameters p
|
||||||
|
|
||||||
first_try = false;
|
first_try = false;
|
||||||
|
|
||||||
// Go over frame configurations
|
// Go over frame configurations, loop back when we reach the end
|
||||||
current_frame = current_frame < (parameters.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);
|
||||||
|
@ -2616,29 +2564,17 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par, iso14a_polling_parameters 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, false, false);
|
return iso14443a_select_cardEx(uid_ptr, p_card, cuid_ptr, anticollision, num_cascades, no_rats, &WUPA_POLLING_PARAMETERS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// This method is temporary. Main intention is to move "special" polling frame configuration to the client
|
|
||||||
iso14a_polling_parameters iso14a_get_polling_parameters(bool use_ecp, bool use_magsafe) {
|
|
||||||
if (use_ecp && use_magsafe) {
|
|
||||||
return FULL_POLLING_PARAMETERS;
|
|
||||||
} else if (use_ecp) {
|
|
||||||
return ECP_POLLING_PARAMETERS;
|
|
||||||
} else if (use_magsafe) {
|
|
||||||
return MAGSAFE_POLLING_PARAMETERS;
|
|
||||||
}
|
|
||||||
return WUPA_POLLING_PARAMETERS;
|
|
||||||
}
|
|
||||||
|
|
||||||
// performs iso14443a anticollision (optional) and card select procedure
|
// performs iso14443a anticollision (optional) and card select procedure
|
||||||
// fills the uid and cuid pointer unless NULL
|
// fills the uid and cuid pointer unless NULL
|
||||||
// fills the card info record unless NULL
|
// fills the card info record unless NULL
|
||||||
// if anticollision is false, then the UID must be provided in uid_ptr[]
|
// if anticollision is false, then the UID must be provided in uid_ptr[]
|
||||||
// and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID)
|
// and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID)
|
||||||
// requests ATS unless no_rats is true
|
// requests ATS unless no_rats is true
|
||||||
int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, bool use_ecp, bool use_magsafe) {
|
int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, iso14a_polling_parameters *polling_parameters) {
|
||||||
|
|
||||||
uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller
|
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 resp_par[MAX_PARITY_SIZE] = {0};
|
||||||
|
@ -2653,7 +2589,7 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
|
||||||
p_card->ats_len = 0;
|
p_card->ats_len = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetATQA(resp, resp_par, iso14a_get_polling_parameters(use_ecp, use_magsafe)) == false) {
|
if (GetATQA(resp, resp_par, polling_parameters) == false) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2678,11 +2614,11 @@ int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint
|
||||||
memcpy(p_card->uid, resp, 4);
|
memcpy(p_card->uid, resp, 4);
|
||||||
|
|
||||||
// select again?
|
// select again?
|
||||||
if (GetATQA(resp, resp_par, WUPA_POLLING_PARAMETERS) == false) {
|
if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == false) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (GetATQA(resp, resp_par, WUPA_POLLING_PARAMETERS) == false) {
|
if (GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS) == false) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2881,7 +2817,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 = 0;
|
int cascade_level = 0;
|
||||||
|
|
||||||
if (!GetATQA(resp, resp_par, WUPA_POLLING_PARAMETERS)) {
|
if (!GetATQA(resp, resp_par, &WUPA_POLLING_PARAMETERS)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3089,7 +3025,12 @@ void ReaderIso14443a(PacketCommandNG *c) {
|
||||||
// if failed selecting, turn off antenna and quite.
|
// if failed selecting, turn off antenna and quite.
|
||||||
if (!(param & ISO14A_NO_SELECT)) {
|
if (!(param & ISO14A_NO_SELECT)) {
|
||||||
iso14a_card_select_t *card = (iso14a_card_select_t *)buf;
|
iso14a_card_select_t *card = (iso14a_card_select_t *)buf;
|
||||||
arg0 = iso14443a_select_cardEx(NULL, card, NULL, true, 0, (param & ISO14A_NO_RATS), (param & ISO14A_USE_ECP), (param & ISO14A_USE_MAGSAFE));
|
|
||||||
|
arg0 = iso14443a_select_cardEx(
|
||||||
|
NULL, card, NULL, true, 0, (param & ISO14A_NO_RATS),
|
||||||
|
(param & ISO14A_USE_CUSTOM_POLLING) ? (iso14a_polling_parameters *)cmd : &WUPA_POLLING_PARAMETERS
|
||||||
|
);
|
||||||
|
// TODO: Improve by adding a cmd parser pointer and moving it by struct length to allow combining data with polling params
|
||||||
FpgaDisableTracing();
|
FpgaDisableTracing();
|
||||||
|
|
||||||
reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t));
|
reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t));
|
||||||
|
|
|
@ -108,24 +108,6 @@ typedef enum {
|
||||||
RESP_INDEX_PACK,
|
RESP_INDEX_PACK,
|
||||||
} resp_index_t;
|
} resp_index_t;
|
||||||
|
|
||||||
// Defines a frame that will be used in a polling sequence
|
|
||||||
// ECP Frames are up to (7 + 16) bytes long, this config should cover future and other cases
|
|
||||||
typedef struct {
|
|
||||||
uint8_t frame[32];
|
|
||||||
uint8_t frame_length;
|
|
||||||
uint8_t last_byte_bits;
|
|
||||||
uint16_t extra_delay;
|
|
||||||
} iso14a_polling_frame;
|
|
||||||
|
|
||||||
// Defines polling sequence configuration
|
|
||||||
// 4 magsafe, 1 wupa, 1 reqa, 1 ecp, 1 extra
|
|
||||||
typedef struct {
|
|
||||||
iso14a_polling_frame frames[8];
|
|
||||||
uint8_t frame_count;
|
|
||||||
uint16_t extra_timeout;
|
|
||||||
} iso14a_polling_parameters;
|
|
||||||
|
|
||||||
|
|
||||||
#ifndef AddCrc14A
|
#ifndef AddCrc14A
|
||||||
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
|
# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1)
|
||||||
#endif
|
#endif
|
||||||
|
@ -166,11 +148,10 @@ void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t
|
||||||
void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing);
|
void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing);
|
||||||
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
|
uint16_t ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
|
||||||
|
|
||||||
iso14a_polling_parameters iso14a_get_polling_parameters(bool use_ecp, bool use_magsafe);
|
|
||||||
void iso14443a_setup(uint8_t fpga_minor_mode);
|
void iso14443a_setup(uint8_t fpga_minor_mode);
|
||||||
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res);
|
int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res);
|
||||||
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);
|
||||||
int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, bool use_ecp, bool use_magsafe);
|
int iso14443a_select_cardEx(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats, iso14a_polling_parameters *polling_parameters);
|
||||||
int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
||||||
void iso14a_set_trigger(bool enable);
|
void iso14a_set_trigger(bool enable);
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,35 @@ void Set_apdu_in_framing(bool v) {
|
||||||
static int CmdHelp(const char *Cmd);
|
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 WUPA_FRAME = {
|
||||||
|
{ 0x52 }, 1, 7, 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const iso14a_polling_frame MAGWUPA1_FRAME = {
|
||||||
|
{ 0x7A }, 1, 7, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const iso14a_polling_frame MAGWUPA2_FRAME = {
|
||||||
|
{ 0x7B }, 1, 7, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const iso14a_polling_frame MAGWUPA3_FRAME = {
|
||||||
|
{ 0x7C }, 1, 7, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const iso14a_polling_frame MAGWUPA4_FRAME = {
|
||||||
|
{ 0x7D }, 1, 7, 0
|
||||||
|
};
|
||||||
|
|
||||||
|
static const iso14a_polling_frame 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
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
static const manufactureName_t manufactureMapping[] = {
|
static const manufactureName_t manufactureMapping[] = {
|
||||||
// ID, "Vendor Country"
|
// ID, "Vendor Country"
|
||||||
{ 0x01, "Motorola UK" },
|
{ 0x01, "Motorola UK" },
|
||||||
|
@ -434,6 +463,41 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
iso14a_polling_parameters 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 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 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 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 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",
|
||||||
|
@ -473,12 +537,14 @@ static int CmdHF14AReader(const char *Cmd) {
|
||||||
cm |= ISO14A_NO_RATS;
|
cm |= ISO14A_NO_RATS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_get_lit(ctx, 5)) {
|
bool use_ecp = arg_get_lit(ctx, 5);
|
||||||
cm |= ISO14A_USE_ECP;
|
bool use_magsafe = arg_get_lit(ctx, 6);
|
||||||
}
|
|
||||||
|
|
||||||
if (arg_get_lit(ctx, 6)) {
|
iso14a_polling_parameters * polling_parameters = NULL;
|
||||||
cm |= ISO14A_USE_MAGSAFE;
|
iso14a_polling_parameters 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 continuous = arg_get_lit(ctx, 7);
|
||||||
|
@ -494,7 +560,13 @@ static int CmdHF14AReader(const char *Cmd) {
|
||||||
}
|
}
|
||||||
do {
|
do {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
|
||||||
|
if (cm & ISO14A_USE_CUSTOM_POLLING) {
|
||||||
|
SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, (uint8_t *)polling_parameters, sizeof(iso14a_polling_parameters));
|
||||||
|
} else {
|
||||||
SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (ISO14A_CONNECT & cm) {
|
if (ISO14A_CONNECT & cm) {
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
@ -831,7 +903,6 @@ int CmdHF14ASniff(const char *Cmd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
||||||
uint16_t cmdc = 0;
|
uint16_t cmdc = 0;
|
||||||
*dataoutlen = 0;
|
*dataoutlen = 0;
|
||||||
|
|
||||||
|
@ -893,8 +964,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 *polling_parameters) {
|
||||||
|
|
||||||
// global vars should be prefixed with g_
|
// global vars should be prefixed with g_
|
||||||
gs_frame_len = 0;
|
gs_frame_len = 0;
|
||||||
gs_frames_num = 0;
|
gs_frames_num = 0;
|
||||||
|
@ -907,7 +977,12 @@ int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card
|
||||||
|
|
||||||
// Anticollision + SELECT card
|
// Anticollision + SELECT card
|
||||||
PacketResponseNG resp;
|
PacketResponseNG resp;
|
||||||
|
if (polling_parameters != NULL) {
|
||||||
|
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT | ISO14A_USE_CUSTOM_POLLING, 0, 0, (uint8_t *)polling_parameters, sizeof(iso14a_polling_parameters));
|
||||||
|
} else {
|
||||||
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
|
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
|
||||||
|
}
|
||||||
|
|
||||||
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
|
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
|
||||||
PrintAndLogEx(WARNING, "Command execute timeout");
|
PrintAndLogEx(WARNING, "Command execute timeout");
|
||||||
return PM3_ETIMEOUT;
|
return PM3_ETIMEOUT;
|
||||||
|
@ -973,6 +1048,10 @@ int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card) {
|
||||||
|
return SelectCard14443A_4_WithParameters(disconnect, verbose, card, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) {
|
static int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) {
|
||||||
*chainingout = false;
|
*chainingout = false;
|
||||||
|
|
||||||
|
@ -1354,12 +1433,11 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
|
||||||
flags |= ISO14A_NO_RATS;
|
flags |= ISO14A_NO_RATS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_ecp) {
|
// TODO: allow to use reader command with both data and polling configuration
|
||||||
flags |= ISO14A_USE_ECP;
|
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;
|
||||||
if (use_magsafe) {
|
// flags |= ISO14A_USE_ECP;
|
||||||
flags |= ISO14A_USE_MAGSAFE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Max buffer is PM3_CMD_DATA_SIZE
|
// Max buffer is PM3_CMD_DATA_SIZE
|
||||||
|
|
|
@ -52,7 +52,9 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card);
|
||||||
int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen);
|
int ExchangeAPDU14a(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 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 *polling_parameters);
|
||||||
|
|
||||||
bool Get_apdu_in_framing(void);
|
bool Get_apdu_in_framing(void);
|
||||||
void Set_apdu_in_framing(bool v);
|
void Set_apdu_in_framing(bool v);
|
||||||
|
|
|
@ -41,7 +41,20 @@
|
||||||
#include "mbedtls/ecc_point_compression.h"
|
#include "mbedtls/ecc_point_compression.h"
|
||||||
#include "mbedtls/gcm.h"
|
#include "mbedtls/gcm.h"
|
||||||
|
|
||||||
uint8_t ecpData[] = { 0x6a, 0x01, 0x00, 0x00, 0x04 };
|
static const iso14a_polling_frame WUPA_FRAME = {
|
||||||
|
.frame={ 0x52 },
|
||||||
|
.frame_length=1,
|
||||||
|
.last_byte_bits=7,
|
||||||
|
.extra_delay=0,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const iso14a_polling_frame ECP_VAS_ONLY_FRAME = {
|
||||||
|
.frame={0x6a, 0x01, 0x00, 0x00, 0x02, 0xe4, 0xd2},
|
||||||
|
.frame_length=7,
|
||||||
|
.last_byte_bits=8,
|
||||||
|
.extra_delay=0,
|
||||||
|
};
|
||||||
|
|
||||||
uint8_t aid[] = { 0x4f, 0x53, 0x45, 0x2e, 0x56, 0x41, 0x53, 0x2e, 0x30, 0x31 };
|
uint8_t aid[] = { 0x4f, 0x53, 0x45, 0x2e, 0x56, 0x41, 0x53, 0x2e, 0x30, 0x31 };
|
||||||
uint8_t getVasUrlOnlyP2 = 0x00;
|
uint8_t getVasUrlOnlyP2 = 0x00;
|
||||||
uint8_t getVasFullReqP2 = 0x01;
|
uint8_t getVasFullReqP2 = 0x01;
|
||||||
|
@ -336,12 +349,13 @@ static int DecryptVASCryptogram(uint8_t *pidHash, uint8_t *cryptogram, size_t cr
|
||||||
static int VASReader(uint8_t *pidHash, const char *url, size_t urlLen, uint8_t *cryptogram, size_t *cryptogramLen, bool verbose) {
|
static int VASReader(uint8_t *pidHash, const char *url, size_t urlLen, uint8_t *cryptogram, size_t *cryptogramLen, bool verbose) {
|
||||||
clearCommandBuffer();
|
clearCommandBuffer();
|
||||||
|
|
||||||
uint16_t flags = ISO14A_RAW | ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
|
iso14a_polling_parameters polling_parameters = {
|
||||||
SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(ecpData), 0, ecpData, sizeof(ecpData));
|
.frames={ WUPA_FRAME, ECP_VAS_ONLY_FRAME },
|
||||||
|
.frame_count=2,
|
||||||
|
.extra_timeout=250
|
||||||
|
};
|
||||||
|
|
||||||
msleep(160);
|
if (SelectCard14443A_4_WithParameters(false, false, NULL, &polling_parameters) != PM3_SUCCESS) {
|
||||||
|
|
||||||
if (SelectCard14443A_4(false, false, NULL) != PM3_SUCCESS) {
|
|
||||||
PrintAndLogEx(FAILED, "No card in field");
|
PrintAndLogEx(FAILED, "No card in field");
|
||||||
return PM3_ECARDEXCHANGE;
|
return PM3_ECARDEXCHANGE;
|
||||||
}
|
}
|
||||||
|
@ -349,7 +363,7 @@ static int VASReader(uint8_t *pidHash, const char *url, size_t urlLen, uint8_t *
|
||||||
uint16_t status = 0;
|
uint16_t status = 0;
|
||||||
size_t resLen = 0;
|
size_t resLen = 0;
|
||||||
uint8_t selectResponse[APDU_RES_LEN] = {0};
|
uint8_t selectResponse[APDU_RES_LEN] = {0};
|
||||||
Iso7816Select(CC_CONTACTLESS, true, true, aid, sizeof(aid), selectResponse, APDU_RES_LEN, &resLen, &status);
|
Iso7816Select(CC_CONTACTLESS, false, true, aid, sizeof(aid), selectResponse, APDU_RES_LEN, &resLen, &status);
|
||||||
|
|
||||||
if (status != 0x9000) {
|
if (status != 0x9000) {
|
||||||
PrintAndLogEx(FAILED, "Card doesn't support VAS");
|
PrintAndLogEx(FAILED, "Card doesn't support VAS");
|
||||||
|
|
|
@ -75,9 +75,27 @@ typedef enum ISO14A_COMMAND {
|
||||||
ISO14A_NO_RATS = (1 << 9),
|
ISO14A_NO_RATS = (1 << 9),
|
||||||
ISO14A_SEND_CHAINING = (1 << 10),
|
ISO14A_SEND_CHAINING = (1 << 10),
|
||||||
ISO14A_USE_ECP = (1 << 11),
|
ISO14A_USE_ECP = (1 << 11),
|
||||||
ISO14A_USE_MAGSAFE = (1 << 12)
|
ISO14A_USE_MAGSAFE = (1 << 12),
|
||||||
|
ISO14A_USE_CUSTOM_POLLING = (1 << 13)
|
||||||
} iso14a_command_t;
|
} iso14a_command_t;
|
||||||
|
|
||||||
|
// Defines a frame that will be used in a polling sequence
|
||||||
|
// ECP Frames are up to (7 + 16) bytes long, 24 bytes should cover future and other cases
|
||||||
|
typedef struct {
|
||||||
|
uint8_t frame[24];
|
||||||
|
uint8_t frame_length;
|
||||||
|
uint8_t last_byte_bits;
|
||||||
|
uint16_t extra_delay;
|
||||||
|
} iso14a_polling_frame;
|
||||||
|
|
||||||
|
// Defines polling sequence configuration
|
||||||
|
// 6 would be enough for 4 magsafe, 1 wupa, 1 ecp,
|
||||||
|
typedef struct {
|
||||||
|
iso14a_polling_frame frames[6];
|
||||||
|
uint8_t frame_count;
|
||||||
|
uint16_t extra_timeout;
|
||||||
|
} iso14a_polling_parameters;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t *response;
|
uint8_t *response;
|
||||||
uint8_t *modulation;
|
uint8_t *modulation;
|
||||||
|
@ -137,5 +155,4 @@ typedef struct {
|
||||||
} state;
|
} state;
|
||||||
} PACKED nonces_t;
|
} PACKED nonces_t;
|
||||||
|
|
||||||
|
|
||||||
#endif // _MIFARE_H_
|
#endif // _MIFARE_H_
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue