Skip to content

Commit

Permalink
speedup 'hf mf chk' (#901)
Browse files Browse the repository at this point in the history
* add separate timeout for tag response to nr_ar
* measure response time and use it for response timeout
* don't drop field between keyblocks
* some reformatting
* some whitespace fixes
* fishing for microseconds in TransmitFor14443a()
* allow arbitrary number of keys in MifareChkKeys()
* and move progress printing to MifareChkKeys()

Co-authored-by: uzlonewolf <[email protected]>
  • Loading branch information
pwpiwi and uzlonewolf authored Jan 9, 2020
1 parent f0c4855 commit a749b1e
Show file tree
Hide file tree
Showing 9 changed files with 284 additions and 319 deletions.
96 changes: 37 additions & 59 deletions armsrc/iso14443a.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,8 +270,7 @@ const bool Mod_Miller_LUT[] = {
#define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4])
#define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)])

static void UartReset()
{
static void UartReset() {
Uart.state = STATE_UNSYNCD;
Uart.bitCount = 0;
Uart.len = 0; // number of decoded data bytes
Expand All @@ -280,8 +279,7 @@ static void UartReset()
Uart.parityBits = 0; // holds 8 parity bits
}

static void UartInit(uint8_t *data, uint8_t *parity)
{
static void UartInit(uint8_t *data, uint8_t *parity) {
Uart.output = data;
Uart.parity = parity;
Uart.fourBits = 0x00000000; // clear the buffer for 4 Bits
Expand All @@ -291,8 +289,7 @@ static void UartInit(uint8_t *data, uint8_t *parity)
}

// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time)
{
static RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) {

Uart.fourBits = (Uart.fourBits << 8) | bit;

Expand Down Expand Up @@ -447,8 +444,7 @@ const bool Mod_Manchester_LUT[] = {
#define IsManchesterModulationNibble2(b) (Mod_Manchester_LUT[(b & 0x000F)])


static void DemodReset()
{
static void DemodReset() {
Demod.state = DEMOD_UNSYNCD;
Demod.len = 0; // number of decoded data bytes
Demod.parityLen = 0;
Expand All @@ -461,16 +457,14 @@ static void DemodReset()
Demod.endTime = 0;
}

static void DemodInit(uint8_t *data, uint8_t *parity)
{
static void DemodInit(uint8_t *data, uint8_t *parity) {
Demod.output = data;
Demod.parity = parity;
DemodReset();
}

// use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time
static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time)
{
static RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time) {

Demod.twoBits = (Demod.twoBits << 8) | bit;

Expand Down Expand Up @@ -729,8 +723,7 @@ void RAMFUNC SnoopIso14443a(uint8_t param) {
//-----------------------------------------------------------------------------
// Prepare tag messages
//-----------------------------------------------------------------------------
static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity)
{
static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity) {
ToSendReset();

// Correction bit, might be removed when not needed
Expand Down Expand Up @@ -778,8 +771,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par
}


static void Code4bitAnswerAsTag(uint8_t cmd)
{
static void Code4bitAnswerAsTag(uint8_t cmd) {
int i;

ToSendReset();
Expand Down Expand Up @@ -853,8 +845,7 @@ static void EmLogTraceTag(uint8_t *tag_data, uint16_t tag_len, uint8_t *tag_Pari
// Stop when button is pressed
// Or return true when command is captured
//-----------------------------------------------------------------------------
static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len)
{
static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) {
// Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
// only, since we are receiving, not transmitting).
// Signal field is off with the appropriate LED
Expand Down Expand Up @@ -951,8 +942,8 @@ bool prepare_allocated_tag_modulation(tag_response_info_t* response_info, uint8_
// Main loop of simulated tag: receive commands from reader, decide what
// response to send, and send it.
//-----------------------------------------------------------------------------
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
{
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data) {

uint8_t sak;

// The first response contains the ATQA (note: bytes are transmitted in reverse order).
Expand Down Expand Up @@ -1231,8 +1222,7 @@ void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)

// prepare a delayed transfer. This simply shifts ToSend[] by a number
// of bits specified in the delay parameter.
static void PrepareDelayedTransfer(uint16_t delay)
{
static void PrepareDelayedTransfer(uint16_t delay) {
uint8_t bitmask = 0;
uint8_t bits_to_shift = 0;
uint8_t bits_shifted = 0;
Expand Down Expand Up @@ -1261,21 +1251,20 @@ static void PrepareDelayedTransfer(uint16_t delay)
// if == 0: transfer immediately and return time of transfer
// if != 0: delay transfer until time specified
//-------------------------------------------------------------------------------------
static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing)
{
static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) {
LED_B_ON();
LED_D_ON();
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);

uint32_t ThisTransferTime = 0;

if (timing) {
if(*timing == 0) { // Measure time
if (*timing == 0) { // Measure time
*timing = (GetCountSspClk() + 8) & 0xfffffff8;
} else {
PrepareDelayedTransfer(*timing & 0x00000007); // Delay transfer (fine tuning - up to 7 MF clock ticks)
}
if(MF_DBGLEVEL >= 4 && GetCountSspClk() >= (*timing & 0xfffffff8)) Dbprintf("TransmitFor14443a: Missed timing");
if (MF_DBGLEVEL >= 4 && GetCountSspClk() >= (*timing & 0xfffffff8)) Dbprintf("TransmitFor14443a: Missed timing");
while (GetCountSspClk() < (*timing & 0xfffffff8)); // Delay transfer (multiple of 8 MF clock ticks)
LastTimeProxToAirStart = *timing;
} else {
Expand All @@ -1284,12 +1273,9 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing
LastTimeProxToAirStart = ThisTransferTime;
}

// clear TXRDY
AT91C_BASE_SSC->SSC_THR = SEC_Y;

uint16_t c = 0;
for (;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = cmd[c];
c++;
if(c >= len) {
Expand All @@ -1306,8 +1292,7 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing
//-----------------------------------------------------------------------------
// Prepare reader command (in bits, support short frames) to send to FPGA
//-----------------------------------------------------------------------------
static void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity)
{
static void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity) {
int i, j;
int last;
uint8_t b;
Expand Down Expand Up @@ -1390,8 +1375,7 @@ static void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, cons
// Stop when button is pressed (return 1) or field was gone (return 2)
// Or return 0 when command is captured
//-----------------------------------------------------------------------------
int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity)
{
int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) {
uint32_t field_off_time = -1;
uint32_t samples = 0;
int ret = 0;
Expand Down Expand Up @@ -1475,8 +1459,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity)
}


static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen)
{
static int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
LED_C_ON();

uint8_t b;
Expand Down Expand Up @@ -1578,8 +1561,7 @@ int EmSendPrecompiledCmd(tag_response_info_t *response_info) {
// If a response is captured return true
// If it takes too long return false
//-----------------------------------------------------------------------------
static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset)
{
static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) {
uint32_t c;

// Set FPGA mode to "reader listen mode", no modulation (listen
Expand All @@ -1598,9 +1580,9 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
for (;;) {
WDT_HIT();

if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
if(ManchesterDecoding(b, offset, 0)) {
if (ManchesterDecoding(b, offset, 0)) {
NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FRAME_DELAY_TIME_PICC_TO_PCD);
return true;
} else if (c++ > iso14a_timeout && Demod.state == DEMOD_UNSYNCD) {
Expand All @@ -1611,55 +1593,51 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive
}


void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing)
{
void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing) {

CodeIso14443aBitsAsReaderPar(frame, bits, par);

// Send command to tag
TransmitFor14443a(ToSend, ToSendMax, timing);
if(trigger)
if (trigger)
LED_A_ON();

// Log reader command in trace buffer
LogTrace(frame, nbytes(bits), LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_READER, (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_READER, par, true);
}


void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing)
{
ReaderTransmitBitsPar(frame, len*8, par, timing);
void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing) {
ReaderTransmitBitsPar(frame, len*8, par, timing);
}


static void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing)
{
static void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) {
// Generate parity and redirect
uint8_t par[MAX_PARITY_SIZE];
GetParity(frame, len/8, par);
ReaderTransmitBitsPar(frame, len, par, timing);
}


void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing)
{
void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing) {
// Generate parity and redirect
uint8_t par[MAX_PARITY_SIZE];
GetParity(frame, len, par);
ReaderTransmitBitsPar(frame, len*8, par, timing);
}


static int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity)
{
static int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity) {
if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) return false;
LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false);
return Demod.len;
}


int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity)
{
int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) {
if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, 0)) return false;

LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false);
return Demod.len;
}
Expand Down Expand Up @@ -1696,7 +1674,7 @@ static void iso14a_set_ATS_times(uint8_t *ats) {
static int GetATQA(uint8_t *resp, uint8_t *resp_par) {

#define WUPA_RETRY_TIMEOUT 10 // 10ms
uint8_t wupa[] = { 0x52 }; // 0x26 - REQA 0x52 - WAKE-UP
uint8_t wupa[] = {ISO14443A_CMD_WUPA}; // 0x26 - REQA 0x52 - WAKE-UP

uint32_t save_iso14a_timeout = iso14a_get_timeout();
iso14a_set_timeout(1236/(16*8)+1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer.
Expand Down Expand Up @@ -1737,7 +1715,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
int len;

// init card struct
if(p_hi14a_card) {
if (p_hi14a_card) {
p_hi14a_card->uidlen = 0;
memset(p_hi14a_card->uid, 0, 10);
p_hi14a_card->ats_len = 0;
Expand All @@ -1747,7 +1725,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_hi14a_card, u
return 0;
}

if(p_hi14a_card) {
if (p_hi14a_card) {
memcpy(p_hi14a_card->atqa, resp, 2);
}

Expand Down Expand Up @@ -2034,8 +2012,8 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u
// Read an ISO 14443a tag. Send out commands and store answers.
//
//-----------------------------------------------------------------------------
void ReaderIso14443a(UsbCommand *c)
{
void ReaderIso14443a(UsbCommand *c) {

iso14a_command_t param = c->arg[0];
uint8_t *cmd = c->d.asBytes;
size_t len = c->arg[1] & 0xffff;
Expand Down
1 change: 1 addition & 0 deletions armsrc/iso14443a.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,5 @@ extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *
extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
extern void iso14a_set_trigger(bool enable);
extern void iso14a_set_timeout(uint32_t timeout);
extern uint32_t iso14a_get_timeout(void);
#endif /* __ISO14443A_H */
Loading

0 comments on commit a749b1e

Please sign in to comment.