mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
hf felica dump: vastly improve speed; fix traces being empty after command execution
This commit is contained in:
+39
-26
@@ -47,6 +47,7 @@
|
||||
static uint32_t felica_timeout;
|
||||
static uint32_t felica_nexttransfertime;
|
||||
static uint32_t felica_lasttime_prox2air_start;
|
||||
static bool felica_field_active;
|
||||
|
||||
static void iso18092_setup(uint8_t fpga_minor_mode);
|
||||
static uint8_t felica_select_card(felica_card_select_t *card);
|
||||
@@ -62,16 +63,13 @@ static uint32_t iso18092_get_timeout(void) {
|
||||
}
|
||||
|
||||
#ifndef FELICA_MAX_FRAME_SIZE
|
||||
// 255 base length (max 254 data + 1 len byte) + 2 sync + 2 crc + 1 extra for safety
|
||||
#define FELICA_MAX_FRAME_SIZE 260
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//structure to hold outgoing NFC frame
|
||||
static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE + 4];
|
||||
static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE];
|
||||
|
||||
//structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames
|
||||
static struct {
|
||||
@@ -494,10 +492,6 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
||||
#endif
|
||||
// allocate command receive buffer
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
|
||||
// Initialize Demod and Uart structs
|
||||
// DemodInit(BigBuf_calloc(MAX_FRAME_SIZE));
|
||||
FelicaFrameinit(BigBuf_calloc(FELICA_MAX_FRAME_SIZE));
|
||||
|
||||
felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; // 418
|
||||
@@ -525,10 +519,12 @@ static void iso18092_setup(uint8_t fpga_minor_mode) {
|
||||
StartCountSspClk();
|
||||
|
||||
LED_D_ON();
|
||||
felica_field_active = true;
|
||||
}
|
||||
|
||||
static void felica_reset_frame_mode(void) {
|
||||
switch_off();
|
||||
felica_field_active = false;
|
||||
//Resetting Frame mode (First set in fpgaloader.c)
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
}
|
||||
@@ -545,35 +541,47 @@ void felica_sendraw(const PacketCommandNG *c) {
|
||||
felica_command_t param = c->oldarg[0];
|
||||
size_t len = c->oldarg[1] & 0xffff;
|
||||
uint32_t arg0;
|
||||
bool do_connect = ((param & FELICA_CONNECT) == FELICA_CONNECT);
|
||||
bool no_disconnect = ((param & FELICA_NO_DISCONNECT) == FELICA_NO_DISCONNECT);
|
||||
|
||||
if ((param & FELICA_CONNECT) == FELICA_CONNECT) {
|
||||
if (do_connect) {
|
||||
clear_trace();
|
||||
}
|
||||
|
||||
set_tracing(true);
|
||||
|
||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
// Preserve compatibility with existing commands that do not send CONNECT:
|
||||
// set up reader path when starting from field-off state.
|
||||
if (do_connect || !felica_field_active) {
|
||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
}
|
||||
|
||||
if ((param & FELICA_CONNECT) == FELICA_CONNECT) {
|
||||
if (do_connect && ((param & FELICA_NO_SELECT) != FELICA_NO_SELECT)) {
|
||||
|
||||
// notify client selecting status.
|
||||
// if failed selecting, turn off antenna and quite.
|
||||
if ((param & FELICA_NO_SELECT) != FELICA_NO_SELECT) {
|
||||
|
||||
felica_card_select_t card;
|
||||
arg0 = felica_select_card(&card);
|
||||
reply_mix(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
|
||||
if (arg0) {
|
||||
felica_reset_frame_mode();
|
||||
return;
|
||||
}
|
||||
// if failed selecting, turn off antenna and quit.
|
||||
felica_card_select_t card;
|
||||
arg0 = felica_select_card(&card);
|
||||
reply_mix(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
|
||||
if (arg0) {
|
||||
felica_reset_frame_mode();
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ((param & FELICA_RAW) == FELICA_RAW) {
|
||||
if (len > FELICA_MAX_FRAME_SIZE) {
|
||||
Dbprintf("FeliCa raw payload too long: %u (max %u)", len, FELICA_MAX_FRAME_SIZE);
|
||||
reply_mix(CMD_ACK, 0, PM3_ELENGTH, 0, NULL, 0);
|
||||
if (!no_disconnect) {
|
||||
felica_reset_frame_mode();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t buf[FELICA_MAX_FRAME_SIZE];
|
||||
memset(buf, 0, sizeof(buf));
|
||||
|
||||
// 2 sync, 1 len, 2 crc == 5
|
||||
uint8_t *buf = BigBuf_calloc(len + 5);
|
||||
// add sync bits
|
||||
buf[0] = 0xb2;
|
||||
buf[1] = 0x4d;
|
||||
@@ -614,7 +622,7 @@ void felica_sendraw(const PacketCommandNG *c) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((param & FELICA_NO_DISCONNECT) == FELICA_NO_DISCONNECT) {
|
||||
if (no_disconnect) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -695,6 +703,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
|
||||
}
|
||||
}
|
||||
switch_off();
|
||||
felica_field_active = false;
|
||||
//reset framing
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
|
||||
@@ -733,6 +742,7 @@ void felica_sim_lite(const uint8_t *uid) {
|
||||
AddCrc(&resp_poll1[2], resp_poll1[2]);
|
||||
AddCrc(&resp_readblk[2], resp_readblk[2]);
|
||||
|
||||
clear_trace();
|
||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
int retval = PM3_SUCCESS;
|
||||
@@ -840,6 +850,7 @@ void felica_sim_lite(const uint8_t *uid) {
|
||||
}
|
||||
|
||||
switch_off();
|
||||
felica_field_active = false;
|
||||
|
||||
// reset framing
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
@@ -856,6 +867,7 @@ void felica_dump_lite_s(void) {
|
||||
uint16_t liteblks[28] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x90, 0x91, 0x92, 0xa0};
|
||||
|
||||
// setup device.
|
||||
clear_trace();
|
||||
iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
|
||||
|
||||
uint8_t blknum;
|
||||
@@ -917,6 +929,7 @@ void felica_dump_lite_s(void) {
|
||||
}
|
||||
}
|
||||
switch_off();
|
||||
felica_field_active = false;
|
||||
|
||||
// Resetting Frame mode (First set in fpgaloader.c)
|
||||
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
|
||||
|
||||
+49
-14
@@ -1717,8 +1717,11 @@ static int CmdHFFelicaDump(const char *Cmd) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
uint8_t flags = FELICA_APPEND_CRC | FELICA_RAW;
|
||||
// Set up field once and keep it up for the entire dump sequence.
|
||||
// First command connects (with NO_SELECT since we already have IDm).
|
||||
uint8_t flags = FELICA_CONNECT | FELICA_NO_SELECT | FELICA_NO_DISCONNECT | FELICA_APPEND_CRC | FELICA_RAW;
|
||||
|
||||
int ret = PM3_SUCCESS;
|
||||
uint16_t cursor = 0x0000;
|
||||
|
||||
felica_service_dump_response_t resp;
|
||||
@@ -1731,14 +1734,20 @@ static int CmdHFFelicaDump(const char *Cmd) {
|
||||
if (send_dump_sv_plain(flags, service_datalen, data_service_dump, 0,
|
||||
&resp, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(FAILED, "No response at cursor 0x%04X", cursor);
|
||||
return PM3_ERFTRANS;
|
||||
ret = PM3_ERFTRANS;
|
||||
break;
|
||||
}
|
||||
|
||||
// After first command, drop CONNECT flag — field is already up
|
||||
flags = FELICA_NO_DISCONNECT | FELICA_APPEND_CRC | FELICA_RAW;
|
||||
|
||||
if (resp.frame_response.cmd_code[0] != 0x0B) {
|
||||
PrintAndLogEx(FAILED, "Bad response cmd 0x%02X @ 0x%04X.",
|
||||
resp.frame_response.cmd_code[0], cursor);
|
||||
PrintAndLogEx(INFO, "This is a normal signal issue. Please try again.");
|
||||
PrintAndLogEx(INFO, "If the issue persists, move the card around and check signal strength. FeliCa can be hard to keep in field.");
|
||||
return PM3_ERFTRANS;
|
||||
ret = PM3_ERFTRANS;
|
||||
break;
|
||||
}
|
||||
uint8_t len = resp.frame_response.length[0];
|
||||
uint16_t node_code = resp.payload[0] | (resp.payload[1] << 8);
|
||||
@@ -1811,14 +1820,20 @@ static int CmdHFFelicaDump(const char *Cmd) {
|
||||
default:
|
||||
PrintAndLogEx(FAILED, "Unexpected length 0x%02X @ 0x%04X",
|
||||
len, cursor);
|
||||
return PM3_ERFTRANS;
|
||||
ret = PM3_ERFTRANS;
|
||||
break;
|
||||
}
|
||||
if (ret != PM3_SUCCESS) break;
|
||||
cursor++;
|
||||
if (cursor == 0) break;
|
||||
}
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Unauth service dump complete.");
|
||||
return PM3_SUCCESS;
|
||||
DropField();
|
||||
|
||||
if (ret == PM3_SUCCESS)
|
||||
PrintAndLogEx(SUCCESS, "Unauth service dump complete.");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -1956,11 +1971,15 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) {
|
||||
PrintAndLogEx(HINT, "Area and service codes are printed in network order.");
|
||||
PrintAndLogEx(INFO, "┌───────────────────────────────────────────────");
|
||||
|
||||
uint8_t flags = FELICA_APPEND_CRC | FELICA_RAW;
|
||||
// Set up field once and keep it up for the entire traversal.
|
||||
// First command connects (with NO_SELECT since we already have IDm).
|
||||
uint8_t flags = FELICA_CONNECT | FELICA_NO_SELECT | FELICA_NO_DISCONNECT | FELICA_APPEND_CRC | FELICA_RAW;
|
||||
|
||||
int ret = PM3_SUCCESS;
|
||||
|
||||
/* -- traversal state ------------------------------------------ */
|
||||
uint16_t cursor = 0x0000;
|
||||
uint16_t area_end_stack[8] = {0xFFFF}; /* root “end” = 0xFFFF */
|
||||
uint16_t area_end_stack[8] = {0xFFFF}; /* root "end" = 0xFFFF */
|
||||
int depth = 0; /* current stack depth */
|
||||
|
||||
felica_service_dump_response_t resp;
|
||||
@@ -1974,14 +1993,20 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) {
|
||||
if (send_dump_sv_plain(flags, datalen, data, 0,
|
||||
&resp, false) != PM3_SUCCESS) {
|
||||
PrintAndLogEx(FAILED, "No response at cursor 0x%04X", cursor);
|
||||
return PM3_ERFTRANS;
|
||||
ret = PM3_ERFTRANS;
|
||||
break;
|
||||
}
|
||||
|
||||
// After first command, drop CONNECT flag — field is already up
|
||||
flags = FELICA_NO_DISCONNECT | FELICA_APPEND_CRC | FELICA_RAW;
|
||||
|
||||
if (resp.frame_response.cmd_code[0] != 0x0B) {
|
||||
PrintAndLogEx(FAILED, "Bad response cmd 0x%02X @ 0x%04X.",
|
||||
resp.frame_response.cmd_code[0], cursor);
|
||||
PrintAndLogEx(INFO, "This is a normal signal issue. Please try again.");
|
||||
PrintAndLogEx(INFO, "If the issue persists, move the card around and check signal strength. FeliCa can be hard to keep in field.");
|
||||
return PM3_ERFTRANS;
|
||||
ret = PM3_ERFTRANS;
|
||||
break;
|
||||
}
|
||||
|
||||
uint8_t len = resp.frame_response.length[0];
|
||||
@@ -2021,12 +2046,15 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) {
|
||||
} else {
|
||||
PrintAndLogEx(FAILED, "Unexpected length 0x%02X @ 0x%04X",
|
||||
len, cursor);
|
||||
return PM3_ERFTRANS;
|
||||
ret = PM3_ERFTRANS;
|
||||
break;
|
||||
}
|
||||
cursor++;
|
||||
if (cursor == 0) break; /* overflow safety */
|
||||
}
|
||||
|
||||
DropField();
|
||||
|
||||
/* draw closing bar └─┴─... based on final depth */
|
||||
char bar[128]; /* large enough for depth ≤ 7 */
|
||||
size_t pos = 0;
|
||||
@@ -2043,9 +2071,10 @@ static int CmdHFFelicaDumpServiceArea(const char *Cmd) {
|
||||
|
||||
PrintAndLogEx(INFO, "%s", bar);
|
||||
|
||||
if (ret == PM3_SUCCESS)
|
||||
PrintAndLogEx(SUCCESS, "Service code and area dump complete.");
|
||||
|
||||
PrintAndLogEx(SUCCESS, "Service code and area dump complete.");
|
||||
return PM3_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int CmdHFFelicaSniff(const char *Cmd) {
|
||||
@@ -3107,7 +3136,13 @@ static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||
flags |= FELICA_RAW;
|
||||
}
|
||||
|
||||
// Max buffer is PM3_CMD_DATA_SIZE
|
||||
// FeliCa length byte includes itself, so raw payload must be <= 254 bytes.
|
||||
if (datalen > 254) {
|
||||
PrintAndLogEx(FAILED, "FeliCa raw payload too long (%d). Max is 254 bytes.", datalen);
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
// Max transport buffer is PM3_CMD_DATA_SIZE
|
||||
datalen = (datalen > PM3_CMD_DATA_SIZE) ? PM3_CMD_DATA_SIZE : datalen;
|
||||
|
||||
clearCommandBuffer();
|
||||
|
||||
Reference in New Issue
Block a user