Move custom polling frame generation logic to client

This commit is contained in:
kormax 2023-07-16 19:27:38 +03:00
parent a9cba02514
commit 7f5e1c9657
5 changed files with 105 additions and 88 deletions

View file

@ -144,19 +144,13 @@ static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ;
// Polling frames and configurations
static const iso14a_polling_frame WUPA_FRAME = {
{ 0x52 }, 1, 7, 0,
};
static iso14a_polling_parameters WUPA_POLLING_PARAMETERS = {
.frames={ WUPA_FRAME },
.frames={ {{ 0x52 }, 1, 7, 0} },
.frame_count=1,
.extra_timeout=0,
};
void printHf14aConfig(void) {
DbpString(_CYAN_("HF 14a config"));
Dbprintf(" [a] Anticol override.... %s%s%s",
@ -3034,9 +3028,9 @@ void ReaderIso14443a(PacketCommandNG *c) {
arg0 = iso14443a_select_cardEx(
NULL, card, NULL, true, 0, (param & ISO14A_NO_RATS),
(param & ISO14A_USE_CUSTOM_POLLING) ? (iso14a_polling_parameters *)cmd : &WUPA_POLLING_PARAMETER
(param & ISO14A_USE_CUSTOM_POLLING) ? (iso14a_polling_parameters *)cmd : &WUPA_POLLING_PARAMETERS
);
// This can be improved 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();
reply_mix(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t));

View file

@ -54,6 +54,35 @@ void Set_apdu_in_framing(bool v) {
static int CmdHelp(const char *Cmd);
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[] = {
// ID, "Vendor Country"
{ 0x01, "Motorola UK" },
@ -435,67 +464,37 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) {
}
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_frame WUPA_FRAME = {
{ 0x52 }, 1, 7, 0,
};
iso14a_polling_frame MAGWUPA1_FRAME = {
{ 0x7A }, 1, 7, 0
};
iso14a_polling_frame MAGWUPA2_FRAME = {
{ 0x7B }, 1, 7, 0
};
iso14a_polling_frame MAGWUPA3_FRAME = {
{ 0x7C }, 1, 7, 0
};
iso14a_polling_frame MAGWUPA4_FRAME = {
{ 0x7D }, 1, 7, 0
};
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
};
iso14a_polling_parameters WUPA_POLLING_PARAMETERS = {
iso14a_polling_parameters wupa_polling_parameters = {
.frames={ WUPA_FRAME },
.frame_count=1,
.extra_timeout=0,
};
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
iso14a_polling_parameters ECP_POLLING_PARAMETERS = {
.frames={ WUPA_FRAME, ECP_FRAME },
.frame_count=2,
.extra_timeout=100
};
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
};
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;
return wupa_polling_parameters;
}
@ -538,10 +537,14 @@ static int CmdHF14AReader(const char *Cmd) {
cm |= ISO14A_NO_RATS;
}
iso14a_polling_parameters polling_parameters;
if (arg_get_lit(ctx, 5) || arg_get_lit(ctx, 6)) {
bool use_ecp = arg_get_lit(ctx, 5);
bool use_magsafe = arg_get_lit(ctx, 6);
iso14a_polling_parameters * polling_parameters = NULL;
iso14a_polling_parameters parameters = iso14a_get_polling_parameters(use_ecp, use_magsafe);
if (use_ecp || use_magsafe) {
cm |= ISO14A_USE_CUSTOM_POLLING;
polling_parameters = iso14a_get_polling_parameters(arg_get_lit(ctx, 5), arg_get_lit(ctx, 6));
polling_parameters = &parameters;
}
bool continuous = arg_get_lit(ctx, 7);
@ -559,7 +562,7 @@ static int CmdHF14AReader(const char *Cmd) {
clearCommandBuffer();
if (cm & ISO14A_USE_CUSTOM_POLLING) {
SendCommandMIX(CMD_HF_ISO14443A_READER, cm, 0, 0, (uint8_t *)&polling_parameters, sizeof(polling_parameters));
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);
}
@ -900,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) {
uint16_t cmdc = 0;
*dataoutlen = 0;
@ -962,8 +964,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
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_
gs_frame_len = 0;
gs_frames_num = 0;
@ -976,7 +977,12 @@ int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card
// Anticollision + SELECT card
PacketResponseNG resp;
SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0, NULL, 0);
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);
}
if (WaitForResponseTimeout(CMD_ACK, &resp, 1500) == false) {
PrintAndLogEx(WARNING, "Command execute timeout");
return PM3_ETIMEOUT;
@ -1042,6 +1048,10 @@ int SelectCard14443A_4(bool disconnect, bool verbose, iso14a_card_select_t *card
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) {
*chainingout = false;
@ -1423,14 +1433,13 @@ static int CmdHF14ACmdRaw(const char *Cmd) {
flags |= ISO14A_NO_RATS;
}
if (use_ecp) {
flags |= ISO14A_USE_ECP;
// 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;
}
if (use_magsafe) {
flags |= ISO14A_USE_MAGSAFE;
}
// Max buffer is PM3_CMD_DATA_SIZE
datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;

View file

@ -54,6 +54,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav
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_WithParameters(bool disconnect, bool verbose, iso14a_card_select_t *card, iso14a_polling_parameters *polling_parameters);
bool Get_apdu_in_framing(void);
void Set_apdu_in_framing(bool v);

View file

@ -41,7 +41,20 @@
#include "mbedtls/ecc_point_compression.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 getVasUrlOnlyP2 = 0x00;
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) {
clearCommandBuffer();
uint16_t flags = ISO14A_RAW | ISO14A_CONNECT | ISO14A_NO_SELECT | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT;
SendCommandMIX(CMD_HF_ISO14443A_READER, flags, sizeof(ecpData), 0, ecpData, sizeof(ecpData));
iso14a_polling_parameters polling_parameters = {
.frames={ WUPA_FRAME, ECP_VAS_ONLY_FRAME },
.frame_count=2,
.extra_timeout=250
};
msleep(160);
if (SelectCard14443A_4(false, false, NULL) != PM3_SUCCESS) {
if (SelectCard14443A_4_WithParameters(false, false, NULL, &polling_parameters) != PM3_SUCCESS) {
PrintAndLogEx(FAILED, "No card in field");
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;
size_t resLen = 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) {
PrintAndLogEx(FAILED, "Card doesn't support VAS");

View file

@ -155,5 +155,4 @@ typedef struct {
} state;
} PACKED nonces_t;
#endif // _MIFARE_H_