#include "apps.h"
#include "string.h"
-// The large multi-purpose buffer, typically used to hold A/D samples or traces,
-// may be processed in some way. Also used to hold various smaller buffers.
-static uint8_t BigBuf[BIGBUF_SIZE];
+// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
+// Also used to hold various smaller buffers and the Mifare Emulator Memory.
+
+// declare it as uint32_t to achieve alignment to 4 Byte boundary
+static uint32_t BigBuf[BIGBUF_SIZE/sizeof(uint32_t)];
// High memory mark
static uint16_t BigBuf_hi = BIGBUF_SIZE;
-// trace related global variables. Change to function calls?
-//uint8_t *trace = BigBuf;
-uint16_t traceLen;
+// pointer to the emulator memory.
+static uint8_t *emulator_memory = NULL;
+
+// trace related global variables
+// (only one left). ToDo: make this static as well?
+uint16_t traceLen = 0;
// get the address of BigBuf
uint8_t *BigBuf_get_addr(void)
{
- return BigBuf;
+ return (uint8_t *)BigBuf;
+}
+
+
+// get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done
+uint8_t *BigBuf_get_EM_addr(void)
+{
+ if (emulator_memory == NULL) { // not yet allocated
+ emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE);
+ }
+
+ return emulator_memory;
}
}
-// allocate a chunk of memory from BigBuf. We allocate high memory first. Low memory
-// is always for traces/samples
+// allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory
+// at the beginning of BigBuf is always for traces/samples
uint8_t *BigBuf_malloc(uint16_t chunksize)
{
if (BigBuf_hi - chunksize < 0) {
- return NULL; // no memory left
+ return NULL; // no memory left
} else {
- BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
- return BigBuf + BigBuf_hi;
+ chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4
+ BigBuf_hi -= chunksize; // aligned to 4 Byte boundary
+ return (uint8_t *)BigBuf + BigBuf_hi;
}
}
-// free ALL allocated chunks. The whole BigBuf is available for traces again.
+// free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
void BigBuf_free(void)
{
BigBuf_hi = BIGBUF_SIZE;
+ emulator_memory = NULL;
+}
+
+
+// free allocated chunks EXCEPT the emulator memory
+void BigBuf_free_keep_EM(void)
+{
+ if (emulator_memory != NULL) {
+ BigBuf_hi = emulator_memory - (uint8_t *)BigBuf;
+ } else {
+ BigBuf_hi = BIGBUF_SIZE;
+ }
}
// return the maximum trace length (i.e. the unallocated size of BigBuf)
-uint16_t BigBuf_max_trace_len(void)
+uint16_t BigBuf_max_traceLen(void)
{
return BigBuf_hi;
-}
\ No newline at end of file
+}
#define BIGBUF_SIZE 40000
-#define TRACE_OFFSET 0
-#define TRACE_SIZE 3000
-#define RECV_CMD_OFFSET (TRACE_OFFSET + TRACE_SIZE)
-#define MAX_FRAME_SIZE 256
-#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 1)/ 8)
-#define RECV_CMD_PAR_OFFSET (RECV_CMD_OFFSET + MAX_FRAME_SIZE)
-#define RECV_RESP_OFFSET (RECV_CMD_PAR_OFFSET + MAX_PARITY_SIZE)
-#define RECV_RESP_PAR_OFFSET (RECV_RESP_OFFSET + MAX_FRAME_SIZE)
-#define CARD_MEMORY_OFFSET (RECV_RESP_PAR_OFFSET + MAX_PARITY_SIZE)
+#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame
+#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8)
+#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC
+#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these
#define CARD_MEMORY_SIZE 4096
-#define DMA_BUFFER_OFFSET CARD_MEMORY_OFFSET
-#define DMA_BUFFER_SIZE CARD_MEMORY_SIZE
-#define FREE_BUFFER_OFFSET (CARD_MEMORY_OFFSET + CARD_MEMORY_SIZE)
-#define FREE_BUFFER_SIZE (BIGBUF_SIZE - FREE_BUFFER_OFFSET - 1)
+#define DMA_BUFFER_SIZE 128
extern uint8_t *BigBuf_get_addr(void);
-extern uint16_t BigBuf_max_trace_len(void);
+extern uint8_t *BigBuf_get_EM_addr(void);
+extern uint16_t BigBuf_max_traceLen(void);
void BigBuf_Clear(void);
extern uint8_t *BigBuf_malloc(uint16_t);
extern void BigBuf_free(void);
+extern void BigBuf_free_keep_EM(void);
extern uint16_t traceLen;
void SimulateTagHfListen(void)
{
- uint8_t *dest = BigBuf_get_addr() + FREE_BUFFER_OFFSET;
+ // ToDo: historically this used the free buffer, which was 2744 Bytes long.
+ // There might be a better size to be defined:
+ #define HF_14B_SNOOP_BUFFER_SIZE 2744
+ uint8_t *dest = BigBuf_malloc(HF_14B_SNOOP_BUFFER_SIZE);
uint8_t v = 0;
int i;
int p = 0;
p = 0;
i++;
- if(i >= FREE_BUFFER_SIZE) {
+ if(i >= HF_14B_SNOOP_BUFFER_SIZE) {
break;
}
}
uint8_t *BigBuf = BigBuf_get_addr();
for(size_t i=0; i<c->arg[1]; i += USB_CMD_DATA_SIZE) {
size_t len = MIN((c->arg[1] - i),USB_CMD_DATA_SIZE);
- cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,i,len,0,BigBuf+c->arg[0]+i,len);
+ cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K,i,len,traceLen,BigBuf+c->arg[0]+i,len);
}
// Trigger a finish downloading signal with an ACK frame
- cmd_send(CMD_ACK,0,0,0,0,0);
+ cmd_send(CMD_ACK,0,0,traceLen,0,0);
LED_B_OFF();
break;
static bool bQuiet;
-bool bCrypto;
-bool bAuthenticating;
-bool bPwd;
-bool bSuccessful;
+static bool bCrypto;
+static bool bAuthenticating;
+static bool bPwd;
+static bool bSuccessful;
-int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader)
+static int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader)
{
static uint16_t traceLen = 0;
uint8_t *trace = BigBuf_get_addr();
// Return when trace is full
- if (traceLen >= TRACE_SIZE) return FALSE;
+ if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + nbytes(iBits) > BigBuf_max_traceLen()) return FALSE;
// Trace the random, i'm curious
rsamples += iSamples;
},
};
-//#define TRACE_LENGTH 3000
-//uint8_t *trace = (uint8_t *) BigBuf;
-//int traceLen = 0;
-//int rsamples = 0;
+// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces.
+// Historically it used to be FREE_BUFFER_SIZE, which was 2744.
+#define AUTH_TABLE_LENGTH 2744
+static byte_t* auth_table;
+static size_t auth_table_pos = 0;
+static size_t auth_table_len = AUTH_TABLE_LENGTH;
-#define AUTH_TABLE_OFFSET FREE_BUFFER_OFFSET
-#define AUTH_TABLE_LENGTH FREE_BUFFER_SIZE
-size_t auth_table_pos = 0;
-size_t auth_table_len = AUTH_TABLE_LENGTH;
-
-byte_t password[4];
-byte_t NrAr[8];
-byte_t key[8];
-uint64_t cipher_state;
+static byte_t password[4];
+static byte_t NrAr[8];
+static byte_t key[8];
+static uint64_t cipher_state;
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
return c;
}
-int hitag2_reset(void)
+static int hitag2_reset(void)
{
tag.state = TAG_STATE_RESET;
tag.crypto_active = 0;
return 0;
}
-int hitag2_init(void)
+static int hitag2_init(void)
{
// memcpy(&tag, &resetdata, sizeof(tag));
hitag2_reset();
LOW(GPIO_SSC_DOUT);
}
-void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
+
+static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
{
- byte_t* auth_table;
- auth_table = (byte_t *)BigBuf_get_addr() + AUTH_TABLE_OFFSET;
byte_t rx_air[HITAG_FRAME_LEN];
// Copy the (original) received frame how it is send over the air
LED_A_OFF();
}
+
static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
{
// Send the content of the frame
size_t blocknr;
-bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
+static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
// Reset the transmission frame length
*txlen = 0;
return true;
}
-bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
+static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
// Reset the transmission frame length
*txlen = 0;
}
-bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
+static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
// Reset the transmission frame length
*txlen = 0;
return true;
}
-bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
- byte_t* auth_table;
- auth_table = (byte_t *)BigBuf_get_addr() + AUTH_TABLE_OFFSET;
+static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
// Reset the transmission frame length
*txlen = 0;
if (bCrypto) {
Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]);
- // Removing failed entry from authentiations table
- memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8);
- auth_table_len -= 8;
+ // Removing failed entry from authentiations table
+ memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8);
+ auth_table_len -= 8;
- // Return if we reached the end of the authentiactions table
+ // Return if we reached the end of the authentications table
bCrypto = false;
if (auth_table_pos == auth_table_len) {
return false;
}
-
- // Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
+
+ // Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry)
memcpy(NrAr,auth_table+auth_table_pos,8);
}
*txlen = 5;
return true;
}
+
void SnoopHitag(uint32_t type) {
int frame_count;
int response;
byte_t rx[HITAG_FRAME_LEN];
size_t rxlen=0;
- // Clean up trace and prepare it for storing frames
- iso14a_set_tracing(TRUE);
- iso14a_clear_trace();
-
auth_table_len = 0;
auth_table_pos = 0;
- byte_t* auth_table;
- auth_table = (byte_t *)BigBuf_get_addr() + AUTH_TABLE_OFFSET;
+ BigBuf_free();
+ auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
+
+ // Clean up trace and prepare it for storing frames
+ iso14a_set_tracing(TRUE);
+ iso14a_clear_trace();
DbpString("Starting Hitag2 snoop");
LED_D_ON();
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
- // Disable timer during configuration
+ // Disable timer during configuration
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
bool bQuitTraceFull = false;
bQuiet = false;
- // Clean up trace and prepare it for storing frames
- iso14a_set_tracing(TRUE);
- iso14a_clear_trace();
auth_table_len = 0;
auth_table_pos = 0;
byte_t* auth_table;
- auth_table = (byte_t *)BigBuf_get_addr() + AUTH_TABLE_OFFSET;
+ BigBuf_free();
+ auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
+ // Clean up trace and prepare it for storing frames
+ iso14a_set_tracing(TRUE);
+ iso14a_clear_trace();
+
DbpString("Starting Hitag2 simulation");
LED_D_ON();
hitag2_init();
bool bStop;
bool bQuitTraceFull = false;
- FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- // Reset the return status
- bSuccessful = false;
+ FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+ // Reset the return status
+ bSuccessful = false;
// Clean up trace and prepare it for storing frames
iso14a_set_tracing(TRUE);
iso14a_clear_trace();
- byte_t* auth_table;
- auth_table = (byte_t *)BigBuf_get_addr() + AUTH_TABLE_OFFSET;
DbpString("Starting Hitag reader family");
// Check configuration
switch(htf) {
case RHT2F_PASSWORD: {
- Dbprintf("List identifier in password mode");
+ Dbprintf("List identifier in password mode");
memcpy(password,htd->pwd.password,4);
blocknr = 0;
bQuitTraceFull = false;
Dbhexdump(8,NrAr,false);
bQuiet = false;
bCrypto = false;
- bAuthenticating = false;
+ bAuthenticating = false;
bQuitTraceFull = true;
} break;
DbpString("Authenticating using key:");
memcpy(key,htd->crypto.key,4); //HACK; 4 or 6?? I read both in the code.
Dbhexdump(6,key,false);
- blocknr = 0;
+ blocknr = 0;
bQuiet = false;
bCrypto = false;
- bAuthenticating = false;
+ bAuthenticating = false;
bQuitTraceFull = true;
} break;
case RHT2F_TEST_AUTH_ATTEMPTS: {
Dbprintf("Testing %d authentication attempts",(auth_table_len/8));
auth_table_pos = 0;
- memcpy(NrAr,auth_table,8);
+ memcpy(NrAr, auth_table, 8);
bQuitTraceFull = false;
bQuiet = false;
bCrypto = false;
// The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes.
// So 32 should be enough!
- uint8_t *readerToTagCmd = BigBuf_get_addr() + RECV_CMD_OFFSET;
+ #define ICLASS_BUFFER_SIZE 32
+ uint8_t readerToTagCmd[ICLASS_BUFFER_SIZE];
// The response (tag -> reader) that we're receiving.
- uint8_t *tagToReaderResponse = BigBuf_get_addr() + RECV_RESP_OFFSET;
+ uint8_t tagToReaderResponse[ICLASS_BUFFER_SIZE];
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
- // reset traceLen to 0
+ // free all BigBuf memory
+ BigBuf_free();
+ // The DMA buffer, used to stream samples from the FPGA
+ uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
+
+ // reset traceLen to 0
iso14a_set_tracing(TRUE);
iso14a_clear_trace();
iso14a_set_trigger(FALSE);
- // The DMA buffer, used to stream samples from the FPGA
- uint8_t *dmaBuf = BigBuf_get_addr() + DMA_BUFFER_OFFSET;
- int lastRxCounter;
+ int lastRxCounter;
uint8_t *upTo;
int smpl;
int maxBehindBy = 0;
(DMA_BUFFER_SIZE-1);
if(behindBy > maxBehindBy) {
maxBehindBy = behindBy;
- if(behindBy > 400) {
+ if(behindBy > (9 * DMA_BUFFER_SIZE / 10)) {
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
goto done;
}
int trace_data_size = 0;
//uint8_t sof = 0x0f;
+ // free eventually allocated BigBuf memory
+ BigBuf_free();
// Respond SOF -- takes 1 bytes
- uint8_t *resp1 = (BigBuf_get_addr() + FREE_BUFFER_OFFSET);
+ uint8_t *resp1 = BigBuf_malloc(2);
int resp1Len;
// Anticollision CSN (rotated CSN)
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
- uint8_t *resp2 = (BigBuf_get_addr() + FREE_BUFFER_OFFSET + 2);
+ uint8_t *resp2 = BigBuf_malloc(28);
int resp2Len;
// CSN
// 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte)
- uint8_t *resp3 = (BigBuf_get_addr() + FREE_BUFFER_OFFSET + 30);
+ uint8_t *resp3 = BigBuf_malloc(30);
int resp3Len;
// e-Purse
- // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/byte)
- uint8_t *resp4 = (BigBuf_get_addr() + FREE_BUFFER_OFFSET + 60);
+ // 144: Takes 16 bytes for SOF/EOF and 8 * 16 = 128 bytes (2 bytes/bit)
+ uint8_t *resp4 = BigBuf_malloc(150);
int resp4Len;
- // + 1720..
- uint8_t *receivedCmd = BigBuf_get_addr() + RECV_CMD_OFFSET;
+ uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
memset(receivedCmd, 0x44, MAX_FRAME_SIZE);
int len;
static uint8_t identify[] = { 0x0c };
static uint8_t select[] = { 0x81, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static uint8_t readcheck_cc[]= { 0x88, 0x02 };
- uint8_t *resp = BigBuf_get_addr() + RECV_RESP_OFFSET;
+ uint8_t resp[ICLASS_BUFFER_SIZE];
uint8_t read_status = 0;
while(!BUTTON_PRESS())
{
- if(traceLen > TRACE_SIZE) {
+ if(traceLen > BigBuf_max_traceLen()) {
DbpString("Trace full");
break;
}
int keyaccess;
} memory;
- uint8_t* resp = BigBuf_get_addr() + RECV_RESP_OFFSET;
+ uint8_t resp[ICLASS_BUFFER_SIZE];
setupIclassReader();
WDT_HIT();
- if(traceLen > TRACE_SIZE) {
+ if(traceLen > BigBuf_max_traceLen()) {
DbpString("Trace full");
break;
}
int triggered = TRUE;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
+ BigBuf_free();
// The command (reader -> tag) that we're working on receiving.
- uint8_t *receivedCmd = BigBuf_get_addr() + DEMOD_TRACE_SIZE;
+ uint8_t *receivedCmd = BigBuf_malloc(READER_TAG_BUFFER_SIZE);
// The response (tag -> reader) that we're working on receiving.
- uint8_t *receivedResponse = BigBuf_get_addr() + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE;
+ uint8_t *receivedResponse = BigBuf_malloc(TAG_READER_BUFFER_SIZE);
// As we receive stuff, we copy it from receivedCmd or receivedResponse
// into trace, along with its length and other annotations.
uint8_t *trace = BigBuf_get_addr();
- int traceLen = 0;
+ traceLen = 0;
// The DMA buffer, used to stream samples from the FPGA.
- uint8_t *dmaBuf = BigBuf_get_addr() + DEMOD_TRACE_SIZE + READER_TAG_BUFFER_SIZE + TAG_READER_BUFFER_SIZE;
+ uint8_t *dmaBuf = BigBuf_malloc(DEMOD_DMA_BUFFER_SIZE);
int lastRxCounter;
uint8_t *upTo;
int ci, cq;
int samples = 0;
// Initialize the trace buffer
- memset(trace, 0x44, DEMOD_TRACE_SIZE);
+ memset(trace, 0x44, BigBuf_max_traceLen());
// Set up the demodulator for tag -> reader responses.
Demod.output = receivedResponse;
// Print some debug information about the buffer sizes
Dbprintf("Snooping buffers initialized:");
- Dbprintf(" Trace: %i bytes", DEMOD_TRACE_SIZE);
+ Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen());
Dbprintf(" Reader -> tag: %i bytes", READER_TAG_BUFFER_SIZE);
Dbprintf(" tag -> Reader: %i bytes", TAG_READER_BUFFER_SIZE);
Dbprintf(" DMA: %i bytes", DEMOD_DMA_BUFFER_SIZE);
(DEMOD_DMA_BUFFER_SIZE-1);
if(behindBy > maxBehindBy) {
maxBehindBy = behindBy;
- if(behindBy > (DEMOD_DMA_BUFFER_SIZE-2)) { // TODO: understand whether we can increase/decrease as we want or not?
+ if(behindBy > (9*DEMOD_DMA_BUFFER_SIZE/10)) { // TODO: understand whether we can increase/decrease as we want or not?
Dbprintf("blew circular buffer! behindBy=0x%x", behindBy);
goto done;
}
trace[traceLen++] = Demod.len;
memcpy(trace+traceLen, receivedResponse, Demod.len);
traceLen += Demod.len;
- if(traceLen > DEMOD_TRACE_SIZE) {
+ if(traceLen > BigBuf_max_traceLen()) {
DbpString("Reached trace limit");
goto done;
}
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
- AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
+ AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS;
DbpString("Snoop statistics:");
- Dbprintf(" Max behind by: %i", maxBehindBy);
+ Dbprintf(" Max behind by: %i", maxBehindBy);
Dbprintf(" Uart State: %x", Uart.state);
Dbprintf(" Uart ByteCnt: %i", Uart.byteCnt);
Dbprintf(" Uart ByteCntMax: %i", Uart.byteCntMax);
void iso14a_clear_trace() {
uint8_t *trace = BigBuf_get_addr();
- memset(trace, 0x44, TRACE_SIZE);
+ uint16_t max_traceLen = BigBuf_max_traceLen();
+ memset(trace, 0x44, max_traceLen);
traceLen = 0;
}
uint16_t duration = timestamp_end - timestamp_start;
// Return when trace is full
- if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= TRACE_SIZE) {
+ uint16_t max_traceLen = BigBuf_max_traceLen();
+ if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= max_traceLen) {
tracing = FALSE; // don't trace any more
return FALSE;
}
// bit 1 - trigger from first reader 7-bit request
LEDsoff();
- // init trace buffer
- iso14a_clear_trace();
- iso14a_set_tracing(TRUE);
// We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a
// triggered == FALSE -- to wait first for card
bool triggered = !(param & 0x03);
+ // Allocate memory from BigBuf for some buffers
+ // free all previous allocations first
+ BigBuf_free();
+
// The command (reader -> tag) that we're receiving.
- // The length of a received command will in most cases be no more than 18 bytes.
- // So 32 should be enough!
- uint8_t *receivedCmd = BigBuf_get_addr() + RECV_CMD_OFFSET;
- uint8_t *receivedCmdPar = BigBuf_get_addr() + RECV_CMD_PAR_OFFSET;
+ uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
+ uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
// The response (tag -> reader) that we're receiving.
- uint8_t *receivedResponse = BigBuf_get_addr() + RECV_RESP_OFFSET;
- uint8_t *receivedResponsePar = BigBuf_get_addr() + RECV_RESP_PAR_OFFSET;
-
- // As we receive stuff, we copy it from receivedCmd or receivedResponse
- // into trace, along with its length and other annotations.
- //uint8_t *trace = (uint8_t *)BigBuf;
+ uint8_t *receivedResponse = BigBuf_malloc(MAX_FRAME_SIZE);
+ uint8_t *receivedResponsePar = BigBuf_malloc(MAX_PARITY_SIZE);
// The DMA buffer, used to stream samples from the FPGA
- uint8_t *dmaBuf = BigBuf_get_addr() + DMA_BUFFER_OFFSET;
+ uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
+
+ // init trace buffer
+ iso14a_clear_trace();
+ iso14a_set_tracing(TRUE);
+
uint8_t *data = dmaBuf;
uint8_t previous_data = 0;
int maxDataLen = 0;
// test for length of buffer
if(dataLen > maxDataLen) {
maxDataLen = dataLen;
- if(dataLen > 400) {
+ if(dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
Dbprintf("blew circular buffer! dataLen=%d", dataLen);
break;
}
uint32_t ProxToAirDuration;
} tag_response_info_t;
-void reset_free_buffer() {
- free_buffer_pointer = BigBuf_get_addr() + FREE_BUFFER_OFFSET;
-}
-
bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffer_size) {
// Example response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes
// This will need the following byte array for a modulation sequence
// ----------- +
// 166 bytes, since every bit that needs to be send costs us a byte
//
-
+
+
// Prepare the tag modulation bits from the message
CodeIso14443aAsTag(response_info->response,response_info->response_n);
return true;
}
+
+// "precompile" responses. There are 7 predefined responses with a total of 28 bytes data to transmit.
+// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
+// 28 * 8 data bits, 28 * 1 parity bits, 7 start bits, 7 stop bits, 7 correction bits
+// -> need 273 bytes buffer
+#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 273
+
bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) {
// Retrieve and store the current buffer index
response_info->modulation = free_buffer_pointer;
// Determine the maximum size we can use from our buffer
- size_t max_buffer_size = BigBuf_get_addr() + FREE_BUFFER_OFFSET + FREE_BUFFER_SIZE - free_buffer_pointer;
+ size_t max_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE;
// Forward the prepare tag modulation function to the inner function
- if (prepare_tag_modulation(response_info,max_buffer_size)) {
+ if (prepare_tag_modulation(response_info, max_buffer_size)) {
// Update the free buffer offset
free_buffer_pointer += ToSendMax;
return true;
//-----------------------------------------------------------------------------
void SimulateIso14443aTag(int tagType, int uid_1st, int uid_2nd, byte_t* data)
{
- // Enable and clear the trace
- iso14a_clear_trace();
- iso14a_set_tracing(TRUE);
-
uint8_t sak;
// The first response contains the ATQA (note: bytes are transmitted in reverse order).
.modulation_n = 0
};
- // Reset the offset pointer of the free buffer
- reset_free_buffer();
-
+ BigBuf_free_keep_EM();
+
+ // allocate buffers:
+ uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
+ uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
+ free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
+
+ // clear trace
+ iso14a_clear_trace();
+ iso14a_set_tracing(TRUE);
+
// Prepare the responses of the anticollision phase
// there will be not enough time to do this at the moment the reader sends it REQA
for (size_t i=0; i<TAG_RESPONSE_COUNT; i++) {
// We need to listen to the high-frequency, peak-detected path.
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
- // buffers used on software Uart:
- uint8_t *receivedCmd = BigBuf_get_addr() + RECV_CMD_OFFSET;
- uint8_t *receivedCmdPar = BigBuf_get_addr() + RECV_CMD_PAR_OFFSET;
-
cmdsRecvd = 0;
tag_response_info_t* p_response;
Dbprintf("%x %x %x", happened, happened2, cmdsRecvd);
LED_A_OFF();
+ BigBuf_free_keep_EM();
}
uint8_t sel_all[] = { 0x93,0x20 };
uint8_t sel_uid[] = { 0x93,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
uint8_t rats[] = { 0xE0,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0
- uint8_t *resp = BigBuf_get_addr() + RECV_RESP_OFFSET;
- uint8_t *resp_par = BigBuf_get_addr() + RECV_RESP_PAR_OFFSET;
+ uint8_t resp[MAX_FRAME_SIZE]; // theoretically. A usual RATS will be much smaller
+ uint8_t resp_par[MAX_PARITY_SIZE];
byte_t uid_resp[4];
size_t uid_resp_len;
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };
static uint8_t mf_nr_ar3;
- uint8_t* receivedAnswer = BigBuf_get_addr() + RECV_RESP_OFFSET;
- uint8_t* receivedAnswerPar = BigBuf_get_addr() + RECV_RESP_PAR_OFFSET;
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
+ // free eventually allocated BigBuf memory. We want all for tracing.
+ BigBuf_free();
+
iso14a_clear_trace();
iso14a_set_tracing(TRUE);
struct Crypto1State *pcs;
pcs = &mpcs;
uint32_t numReads = 0;//Counts numer of times reader read a block
- uint8_t* receivedCmd = get_bigbufptr_recvcmdbuf();
- uint8_t* receivedCmd_par = receivedCmd + MAX_FRAME_SIZE;
- uint8_t* response = get_bigbufptr_recvrespbuf();
- uint8_t* response_par = response + MAX_FRAME_SIZE;
+ uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE];
+ uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE];
+ uint8_t response[MAX_MIFARE_FRAME_SIZE];
+ uint8_t response_par[MAX_MIFARE_PARITY_SIZE];
uint8_t rATQA[] = {0x04, 0x00}; // Mifare classic 1k 4BUID
uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
uint32_t ar_nr_responses[] = {0,0,0,0,0,0,0,0};
uint8_t ar_nr_collected = 0;
+ // free eventually allocated BigBuf memory but keep Emulator Memory
+ BigBuf_free_keep_EM();
// clear trace
iso14a_clear_trace();
iso14a_set_tracing(TRUE);
// The command (reader -> tag) that we're receiving.
// The length of a received command will in most cases be no more than 18 bytes.
// So 32 should be enough!
- uint8_t *receivedCmd = BigBuf_get_addr() + RECV_CMD_OFFSET;
- uint8_t *receivedCmdPar = BigBuf_get_addr() + RECV_CMD_PAR_OFFSET;
+ uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE];
+ uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE];
// The response (tag -> reader) that we're receiving.
- uint8_t *receivedResponse = BigBuf_get_addr() + RECV_RESP_OFFSET;
- uint8_t *receivedResponsePar = BigBuf_get_addr() + RECV_RESP_PAR_OFFSET;
+ uint8_t receivedResponse[MAX_MIFARE_FRAME_SIZE];
+ uint8_t receivedResponsePar[MAX_MIFARE_PARITY_SIZE];
// As we receive stuff, we copy it from receivedCmd or receivedResponse
// into trace, along with its length and other annotations.
//uint8_t *trace = (uint8_t *)BigBuf;
- // The DMA buffer, used to stream samples from the FPGA
- uint8_t *dmaBuf = BigBuf_get_addr() + DMA_BUFFER_OFFSET;
+ // free eventually allocated BigBuf memory
+ BigBuf_free();
+ // allocate the DMA buffer, used to stream samples from the FPGA
+ uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
uint8_t *data = dmaBuf;
uint8_t previous_data = 0;
int maxDataLen = 0;
// test for length of buffer
if(dataLen > maxDataLen) { // we are more behind than ever...
maxDataLen = dataLen;
- if(dataLen > 400) {
+ if(dataLen > (9 * DMA_BUFFER_SIZE / 10)) {
Dbprintf("blew circular buffer! dataLen=0x%x", dataLen);
break;
}
void DoAcquisition125k_internal(int trigger_threshold,bool silent)
{
uint8_t *dest = BigBuf_get_addr();
- int n = BigBuf_max_trace_len();
+ int n = BigBuf_max_traceLen();
int i;
memset(dest, 0, n);
#define FREQHI 134200
signed char *dest = (signed char *)BigBuf_get_addr();
- uint16_t n = BigBuf_max_trace_len();
+ uint16_t n = BigBuf_max_traceLen();
// 128 bit shift register [shift3:shift2:shift1:shift0]
uint32_t shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0;
// clear buffer
uint32_t *BigBuf = (uint32_t *)BigBuf_get_addr();
- memset(BigBuf,0,BigBuf_max_trace_len()/sizeof(uint32_t));
+ memset(BigBuf,0,BigBuf_max_traceLen()/sizeof(uint32_t));
// Set up the synchronous serial port
AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN;
{
uint8_t *dest = BigBuf_get_addr();
- size_t size=sizeof(BigBuf);
+ size_t size = BigBuf_max_traceLen();
uint32_t hi2=0, hi=0, lo=0;
int idx=0;
// Configure to go in 125Khz listen mode
DoAcquisition125k_internal(-1,true);
// FSK demodulator
- idx = HIDdemodFSK(dest, BigBuf_max_trace_len(), &hi2, &hi, &lo);
- WDT_HIT();
- size = sizeof(BigBuf);
-
idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo);
if (idx>0 && lo>0){
if (ledcontrol) LED_A_ON();
DoAcquisition125k_internal(-1,true);
- size = BigBuf_max_trace_len();
+ size = BigBuf_max_traceLen();
//Dbprintf("DEBUG: Buffer got");
//askdemod and manchester decode
errCnt = askmandemod(dest, &size, &clk, &invert);
DoAcquisition125k_internal(-1,true);
//fskdemod and get start index
WDT_HIT();
- idx = IOdemodFSK(dest, BigBuf_max_trace_len());
+ idx = IOdemodFSK(dest, BigBuf_max_traceLen());
if (idx>0){
//valid tag found
//int m=0, i=0; //enio adjustment 12/10/14
uint32_t m=0, i=0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- m = BigBuf_max_trace_len();
+ m = BigBuf_max_traceLen();
// Clear destination buffer before sending the command
memset(dest, 128, m);
// Connect the A/D to the peak-detected low-frequency path.
int m=0, i=0;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
- m = BigBuf_max_trace_len();
+ m = BigBuf_max_traceLen();
// Clear destination buffer before sending the command
memset(dest, 128, m);
// Connect the A/D to the peak-detected low-frequency path.
uint8_t BitStream[256];
uint8_t Blocks[8][16];
uint8_t *GraphBuffer = BigBuf_get_addr();
- int GraphTraceLen = BigBuf_max_trace_len();
+ int GraphTraceLen = BigBuf_max_traceLen();
int i, j, lastval, bitidx, half_switch;
int clock = 64;
int tolerance = clock / 8;
fwd_bit_count = Prepare_Cmd( FWD_CMD_READ );
fwd_bit_count += Prepare_Addr( Address );
- m = BigBuf_max_trace_len();
+ m = BigBuf_max_traceLen();
// Clear destination buffer before sending the command
memset(dest, 128, m);
// Connect the A/D to the peak-detected low-frequency path.
struct Crypto1State mpcs = {0, 0};\r
struct Crypto1State *pcs;\r
pcs = &mpcs;\r
- uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
\r
uint32_t auth1_time, auth2_time;\r
static uint16_t delta_time;\r
\r
+ // free eventually allocated BigBuf memory\r
+ BigBuf_free();\r
// clear trace\r
iso14a_clear_trace();\r
iso14a_set_tracing(false);\r
uint8_t d_block[18] = {0x00};\r
uint32_t cuid;\r
\r
- uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
// reset FPGA and LED\r
if (workFlags & 0x08) {\r
uint8_t data[18] = {0x00};\r
uint32_t cuid = 0;\r
\r
- uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
if (workFlags & 0x08) {\r
LED_A_ON();\r
// variables\r
byte_t isOK = 1;\r
\r
- uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
ReaderTransmitBitsPar(wupC1,7,0, NULL);\r
if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {\r
cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout));\r
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);\r
LEDsoff();\r
-}
\ No newline at end of file
+}
while (pckLen > 0) {\r
pckSize = MIN(USB_CMD_DATA_SIZE, pckLen);\r
LED_B_ON();\r
- cmd_send(CMD_ACK, 1, pckSize, pckNum, trace + traceLen - pckLen, pckSize);\r
+ cmd_send(CMD_ACK, 1, traceLen, pckSize, trace + traceLen - pckLen, pckSize);\r
LED_B_OFF();\r
\r
pckLen -= pckSize;\r
\r
int MF_DBGLEVEL = MF_DBG_ALL;\r
\r
-// memory management\r
-uint8_t* get_bigbufptr_recvrespbuf(void) {\r
- return BigBuf_get_addr() + RECV_RESP_OFFSET; \r
-}\r
-uint8_t* get_bigbufptr_recvcmdbuf(void) {\r
- return BigBuf_get_addr() + RECV_CMD_OFFSET; \r
-}\r
-uint8_t* get_bigbufptr_emlcardmem(void) {\r
- return BigBuf_get_addr() + CARD_MEMORY_OFFSET;\r
-}\r
-\r
// crypto1 helpers\r
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){\r
uint8_t bt = 0;\r
uint32_t nt, ntpp; // Supplied tag nonce\r
\r
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 };\r
- uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
// Transmit MIFARE_CLASSIC_AUTH\r
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);\r
int len; \r
uint8_t bt[2];\r
\r
- uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
// command MIFARE_CLASSIC_READBLOCK\r
len = mifare_sendcmd_short(pcs, 1, 0x30, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
int mifare_ultra_auth1(uint32_t uid, uint8_t *blockData){\r
\r
uint16_t len;\r
- uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
len = mifare_sendcmd_short(NULL, 1, 0x1A, 0x00, receivedAnswer,receivedAnswerPar ,NULL);\r
if (len == 1) {\r
int mifare_ultra_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){\r
\r
uint16_t len;\r
- uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
len = mifare_sendcmd_short_mfucauth(NULL, 1, 0xAF, key, receivedAnswer, receivedAnswerPar, NULL);\r
if (len == 1) {\r
{
uint16_t len;
uint8_t bt[2];
- uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
// command MIFARE_CLASSIC_READBLOCK
byte_t res;\r
\r
uint8_t d_block[18], d_block_enc[18];\r
- uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
// command MIFARE_CLASSIC_WRITEBLOCK\r
len = mifare_sendcmd_short(pcs, 1, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);\r
uint16_t len;
uint8_t par[3] = {0}; // enough for 18 parity bits
uint8_t d_block[18] = {0x00};
- uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t* receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
// command MIFARE_CLASSIC_WRITEBLOCK
len = mifare_sendcmd_short(NULL, true, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL);
{
uint16_t len;
uint8_t d_block[8] = {0x00};
- uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
// command MIFARE_CLASSIC_WRITEBLOCK
d_block[0]= blockNo;
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid)
{
uint16_t len; \r
- uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
len = mifare_sendcmd_short(pcs, pcs == NULL ? false:true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);\r
if (len != 0) {\r
int mifare_ultra_halt(uint32_t uid)
{
uint16_t len;
- uint8_t *receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
len = mifare_sendcmd_short(NULL, true, 0x50, 0x00, receivedAnswer, receivedAnswerPar, NULL);
if (len != 0) {
\r
// work with emulator memory
void emlSetMem(uint8_t *data, int blockNum, int blocksCount) {
- uint8_t* emCARD = get_bigbufptr_emlcardmem();
+ uint8_t* emCARD = BigBuf_get_EM_addr();
memcpy(emCARD + blockNum * 16, data, blocksCount * 16);\r
}\r
\r
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {\r
- uint8_t* emCARD = get_bigbufptr_emlcardmem();\r
+ uint8_t* emCARD = BigBuf_get_EM_addr();\r
memcpy(data, emCARD + blockNum * 16, blocksCount * 16);\r
}\r
\r
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) {\r
- uint8_t* emCARD = get_bigbufptr_emlcardmem();\r
+ uint8_t* emCARD = BigBuf_get_EM_addr();\r
memcpy(data, emCARD + bytePtr, byteCount);\r
}\r
\r
int emlCheckValBl(int blockNum) {\r
- uint8_t* emCARD = get_bigbufptr_emlcardmem();\r
+ uint8_t* emCARD = BigBuf_get_EM_addr();\r
uint8_t* data = emCARD + blockNum * 16;\r
\r
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||\r
}\r
\r
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {\r
- uint8_t* emCARD = get_bigbufptr_emlcardmem();\r
+ uint8_t* emCARD = BigBuf_get_EM_addr();\r
uint8_t* data = emCARD + blockNum * 16;\r
\r
if (emlCheckValBl(blockNum)) {\r
}\r
\r
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {\r
- uint8_t* emCARD = get_bigbufptr_emlcardmem();\r
+ uint8_t* emCARD = BigBuf_get_EM_addr();\r
uint8_t* data = emCARD + blockNum * 16;\r
\r
memcpy(data + 0, &blReg, 4);\r
\r
uint64_t emlGetKey(int sectorNum, int keyType) {\r
uint8_t key[6];\r
- uint8_t* emCARD = get_bigbufptr_emlcardmem();\r
+ uint8_t* emCARD = BigBuf_get_EM_addr();\r
\r
memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);\r
return bytes_to_num(key, 6);\r
\r
const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};\r
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};\r
- uint8_t* emCARD = get_bigbufptr_emlcardmem();\r
+ uint8_t* emCARD = BigBuf_get_EM_addr();\r
\r
memset(emCARD, 0, CARD_MEMORY_SIZE);\r
\r
int len;\r
// load key, keynumber\r
uint8_t data[2]={0x0a, 0x00};\r
- uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL);\r
if (len == 1) {\r
data[0] = 0xAF;\r
memcpy(data+1,key,16);\r
\r
- uint8_t* receivedAnswer = get_bigbufptr_recvrespbuf();\r
- uint8_t *receivedAnswerPar = receivedAnswer + MAX_FRAME_SIZE;\r
+ uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];\r
+ uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];\r
\r
len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL);\r
\r
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();\r
\r
//functions
-uint8_t* mifare_get_bigbufptr(void);
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing);
\r
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);\r
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);\r
\r
-// memory management\r
-uint8_t* get_bigbufptr_recvrespbuf(void);\r
-uint8_t* get_bigbufptr_recvcmdbuf(void);\r
-uint8_t* get_bigbufptr_emlcardmem(void);\r
-\r
// Mifare memory structure\r
uint8_t NumBlocksPerSector(uint8_t sectorNo);\r
uint8_t FirstBlockOfSector(uint8_t sectorNo);\r
int offset = 0;
char string_buf[25];
char* string_ptr = string_buf;
- uint8_t got[40000];
+ uint8_t got[BIGBUF_SIZE];
sscanf(Cmd, "%i %i", &requested, &offset);
requested = 8;
}
if (offset + requested > sizeof(got)) {
- PrintAndLog("Tried to read past end of buffer, <bytes> + <offset> > 40000");
+ PrintAndLog("Tried to read past end of buffer, <bytes> + <offset> > %d", BIGBUF_SIZE);
return 0;
}
int CmdSamples(const char *Cmd)
{
- uint8_t got[40000] = {0x00};
+ uint8_t got[BIGBUF_SIZE] = {0x00};
int n = strtol(Cmd, NULL, 0);
if (n == 0)
n = sizeof(got);
PrintAndLog("Reading %d samples from device memory\n", n);
- GetFromBigBuf(got,n,0);
- WaitForResponse(CMD_ACK,NULL);
+ GetFromBigBuf(got,n,0);
+ WaitForResponse(CMD_ACK,NULL);
for (int j = 0; j < n; j++) {
GraphBuffer[j] = ((int)got[j]) - 128;
- }
- GraphTraceLen = n;
- RepaintGraphWindow();
- return 0;
+ }
+ GraphTraceLen = n;
+ RepaintGraphWindow();
+ return 0;
}
int CmdTuneSamples(const char *Cmd)
extern uint8_t DemodBuffer[MAX_DEMOD_BUF_LEN];
extern int DemodBufferLen;
+#define BIGBUF_SIZE 40000
+
#endif
SendCommand(&c);
return 0;
}
-// for the time being. Need better Bigbuf handling.
-#define TRACE_SIZE 3000
//The following data is taken from http://www.proxmark.org/forum/viewtopic.php?pid=13501#p13501
/*
}
}
-uint16_t printTraceLine(uint16_t tracepos, uint8_t* trace, uint8_t protocol, bool showWaitCycles)
+uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, uint8_t protocol, bool showWaitCycles)
{
bool isResponse;
- uint16_t duration, data_len,parity_len;
+ uint16_t duration, data_len, parity_len;
uint32_t timestamp, first_timestamp, EndOfTransmissionTimestamp;
char explanation[30] = {0};
+ if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
+
first_timestamp = *((uint32_t *)(trace));
timestamp = *((uint32_t *)(trace + tracepos));
- // Break and stick with current result if buffer was not completely full
- if (timestamp == 0x44444444) return TRACE_SIZE;
tracepos += 4;
duration = *((uint16_t *)(trace + tracepos));
}
parity_len = (data_len-1)/8 + 1;
- if (tracepos + data_len + parity_len >= TRACE_SIZE) {
- return TRACE_SIZE;
+ if (tracepos + data_len + parity_len > traceLen) {
+ return traceLen;
}
uint8_t *frame = trace + tracepos;
}
}
+ if (tracepos + sizeof(uint32_t) + sizeof(uint16_t) + sizeof(uint16_t) > traceLen) return traceLen;
+
bool next_isResponse = *((uint16_t *)(trace + tracepos + 6)) & 0x8000;
if (showWaitCycles && !isResponse && next_isResponse) {
(next_timestamp - EndOfTransmissionTimestamp));
}
}
+
return tracepos;
}
+
int CmdHFList(const char *Cmd)
{
bool showWaitCycles = false;
}
- uint8_t trace[TRACE_SIZE];
+ uint8_t *trace;
uint16_t tracepos = 0;
- GetFromBigBuf(trace, TRACE_SIZE, 0);
- WaitForResponse(CMD_ACK, NULL);
-
- PrintAndLog("Recorded Activity");
+ trace = malloc(USB_CMD_DATA_SIZE);
+
+ // Query for the size of the trace
+ UsbCommand response;
+ GetFromBigBuf(trace, USB_CMD_DATA_SIZE, 0);
+ WaitForResponse(CMD_ACK, &response);
+ uint16_t traceLen = response.arg[2];
+ if (traceLen > USB_CMD_DATA_SIZE) {
+ uint8_t *p = realloc(trace, traceLen);
+ if (p == NULL) {
+ PrintAndLog("Cannot allocate memory for trace");
+ free(trace);
+ return 2;
+ }
+ trace = p;
+ GetFromBigBuf(trace, traceLen, 0);
+ WaitForResponse(CMD_ACK, NULL);
+ }
+
+ PrintAndLog("Recorded Activity (TraceLen = %d bytes)", traceLen);
PrintAndLog("");
PrintAndLog("Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer");
PrintAndLog("iso14443a - All times are in carrier periods (1/13.56Mhz)");
PrintAndLog(" Start | End | Src | Data (! denotes parity error) | CRC | Annotation |");
PrintAndLog("-----------|-----------|-----|-----------------------------------------------------------------|-----|--------------------|");
- while(tracepos < TRACE_SIZE)
+ while(tracepos < traceLen)
{
- tracepos = printTraceLine(tracepos, trace, protocol, showWaitCycles);
+ tracepos = printTraceLine(tracepos, traceLen, trace, protocol, showWaitCycles);
}
+
+ free(trace);
return 0;
}
int CmdHF14BList(const char *Cmd)
{
- uint8_t got[TRACE_BUFFER_SIZE];
- GetFromBigBuf(got,sizeof(got),0);
- WaitForResponse(CMD_ACK,NULL);
-
- PrintAndLog("recorded activity:");
+ uint8_t *got = malloc(USB_CMD_DATA_SIZE);
+
+ // Query for the actual size of the trace
+ UsbCommand response;
+ GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0);
+ WaitForResponse(CMD_ACK, &response);
+ uint16_t traceLen = response.arg[2];
+ if (traceLen > USB_CMD_DATA_SIZE) {
+ uint8_t *p = realloc(got, traceLen);
+ if (p == NULL) {
+ PrintAndLog("Cannot allocate memory for trace");
+ free(got);
+ return 2;
+ }
+ got = p;
+ GetFromBigBuf(got, traceLen, 0);
+ WaitForResponse(CMD_ACK,NULL);
+ }
+ PrintAndLog("recorded activity: (TraceLen = %d bytes)", traceLen);
PrintAndLog(" time :rssi: who bytes");
PrintAndLog("---------+----+----+-----------");
for(;;) {
- if(i >= TRACE_BUFFER_SIZE) { break; }
+ if(i >= traceLen) { break; }
bool isResponse;
int timestamp = *((uint32_t *)(got+i));
if(len > 100) {
break;
}
- if(i + len >= TRACE_BUFFER_SIZE) {
+ if(i + len >= traceLen) {
break;
}
prev = timestamp;
i += (len + 9);
}
+ free(got);
return 0;
}
int res = 0;\r
int len = 0;\r
int blockLen = 0;\r
- int num = 0;\r
int pckNum = 0;\r
- uint8_t uid[7] = {0x00};\r
+ int num = 0;\r
+ uint8_t uid[7];\r
uint8_t uid_len;\r
uint8_t atqa[2] = {0x00};\r
uint8_t sak;\r
bool isTag;\r
- uint8_t buf[3000] = {0x00};\r
- uint8_t * bufPtr = buf;\r
+ uint8_t *buf = NULL;\r
+ uint16_t bufsize = 0;\r
+ uint8_t *bufPtr = NULL;\r
\r
char ctmp = param_getchar(Cmd, 0);\r
if ( ctmp == 'h' || ctmp == 'H' ) {\r
break;\r
}\r
\r
- UsbCommand resp;\r
- if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {\r
+ UsbCommand resp;\r
+ if (WaitForResponseTimeout(CMD_ACK,&resp,2000)) {\r
res = resp.arg[0] & 0xff;\r
- len = resp.arg[1];\r
- num = resp.arg[2];\r
- \r
- if (res == 0) return 0;\r
- if (res == 1) {\r
- if (num ==0) {\r
+ uint16_t traceLen = resp.arg[1];\r
+ len = resp.arg[2];\r
+\r
+ if (res == 0) return 0; // we are done\r
+\r
+ if (res == 1) { // there is (more) data to be transferred\r
+ if (pckNum == 0) { // first packet, (re)allocate necessary buffer\r
+ if (traceLen > bufsize) {\r
+ uint8_t *p;\r
+ if (buf == NULL) { // not yet allocated\r
+ p = malloc(traceLen);\r
+ } else { // need more memory\r
+ p = realloc(buf, traceLen);\r
+ }\r
+ if (p == NULL) {\r
+ PrintAndLog("Cannot allocate memory for trace");\r
+ free(buf);\r
+ return 2;\r
+ }\r
+ buf = p;\r
+ }\r
bufPtr = buf;\r
- memset(buf, 0x00, 3000);\r
+ bufsize = traceLen;\r
+ memset(buf, 0x00, traceLen);\r
}\r
memcpy(bufPtr, resp.d.asBytes, len);\r
bufPtr += len;\r
pckNum++;\r
}\r
- if (res == 2) {\r
+\r
+ if (res == 2) { // received all data, start displaying\r
blockLen = bufPtr - buf;\r
bufPtr = buf;\r
printf(">\n");\r
PrintAndLog("received trace len: %d packages: %d", blockLen, pckNum);\r
- num = 0;\r
while (bufPtr - buf < blockLen) {\r
- bufPtr += 6;\r
+ bufPtr += 6; // skip (void) timing information\r
len = *((uint16_t *)bufPtr);\r
-\r
if(len & 0x8000) {\r
isTag = true;\r
len &= 0x7fff;\r
}\r
bufPtr += 2;\r
if ((len == 14) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[12] == 0xff) && (bufPtr[13] == 0xff)) {\r
- \r
memcpy(uid, bufPtr + 2, 7);\r
memcpy(atqa, bufPtr + 2 + 7, 2);\r
uid_len = (atqa[0] & 0xC0) == 0x40 ? 7 : 4;\r
sak = bufPtr[11];\r
- \r
PrintAndLog("tag select uid:%s atqa:0x%02x%02x sak:0x%02x", \r
sprint_hex(uid + (7 - uid_len), uid_len),\r
atqa[1], \r
AddLogHex(logHexFileName, isTag ? "TAG: ":"RDR: ", bufPtr, len);\r
if (wantDecrypt) \r
mfTraceDecode(bufPtr, len, wantSaveToEmlFile);\r
+ num++; \r
}\r
bufPtr += len;\r
bufPtr += ((len-1)/8+1); // ignore parity\r
- num++;\r
}\r
+ pckNum = 0;\r
}\r
} // resp not NULL\r
} // while (true)\r
- \r
+\r
+ free(buf);\r
return 0;\r
}\r
\r
+\r
static command_t CommandTable[] =\r
{\r
{"help", CmdHelp, 1, "This help"},\r
int CmdLFHitagList(const char *Cmd)
{
- uint8_t got[TRACE_BUFFER_SIZE];
- GetFromBigBuf(got,sizeof(got),0);
- WaitForResponse(CMD_ACK,NULL);
-
- PrintAndLog("recorded activity:");
- PrintAndLog(" ETU :nbits: who bytes");
- PrintAndLog("---------+-----+----+-----------");
+ uint8_t *got = malloc(USB_CMD_DATA_SIZE);
+
+ // Query for the actual size of the trace
+ UsbCommand response;
+ GetFromBigBuf(got, USB_CMD_DATA_SIZE, 0);
+ WaitForResponse(CMD_ACK, &response);
+ uint16_t traceLen = response.arg[2];
+ if (traceLen > USB_CMD_DATA_SIZE) {
+ uint8_t *p = realloc(got, traceLen);
+ if (p == NULL) {
+ PrintAndLog("Cannot allocate memory for trace");
+ free(got);
+ return 2;
+ }
+ got = p;
+ GetFromBigBuf(got, traceLen, 0);
+ WaitForResponse(CMD_ACK,NULL);
+ }
+
+ PrintAndLog("recorded activity (TraceLen = %d bytes):");
+ PrintAndLog(" ETU :nbits: who bytes");
+ PrintAndLog("---------+-----+----+-----------");
- int i = 0;
- int prev = -1;
- int len = strlen(Cmd);
+ int i = 0;
+ int prev = -1;
+ int len = strlen(Cmd);
- char filename[FILE_PATH_SIZE] = { 0x00 };
- FILE* pf = NULL;
+ char filename[FILE_PATH_SIZE] = { 0x00 };
+ FILE* pf = NULL;
- if (len > FILE_PATH_SIZE)
- len = FILE_PATH_SIZE;
- memcpy(filename, Cmd, len);
+ if (len > FILE_PATH_SIZE)
+ len = FILE_PATH_SIZE;
+ memcpy(filename, Cmd, len);
- if (strlen(filename) > 0) {
- if ((pf = fopen(filename,"wb")) == NULL) {
- PrintAndLog("Error: Could not open file [%s]",filename);
- return 1;
+ if (strlen(filename) > 0) {
+ if ((pf = fopen(filename,"wb")) == NULL) {
+ PrintAndLog("Error: Could not open file [%s]",filename);
+ return 1;
+ }
}
- }
- for (;;) {
+ for (;;) {
- if(i >= TRACE_BUFFER_SIZE) { break; }
-
- bool isResponse;
- int timestamp = *((uint32_t *)(got+i));
- if (timestamp & 0x80000000) {
- timestamp &= 0x7fffffff;
- isResponse = 1;
- } else {
- isResponse = 0;
- }
-
- int parityBits = *((uint32_t *)(got+i+4));
- // 4 bytes of additional information...
- // maximum of 32 additional parity bit information
- //
- // TODO:
- // at each quarter bit period we can send power level (16 levels)
- // or each half bit period in 256 levels.
-
- int bits = got[i+8];
- int len = nbytes(got[i+8]);
-
- if (len > 100) {
- break;
- }
- if (i + len >= TRACE_BUFFER_SIZE) { break;}
-
- uint8_t *frame = (got+i+9);
-
- // Break and stick with current result if buffer was not completely full
- if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
-
- char line[1000] = "";
- int j;
- for (j = 0; j < len; j++) {
- int oddparity = 0x01;
- int k;
+ if(i > traceLen) { break; }
+
+ bool isResponse;
+ int timestamp = *((uint32_t *)(got+i));
+ if (timestamp & 0x80000000) {
+ timestamp &= 0x7fffffff;
+ isResponse = 1;
+ } else {
+ isResponse = 0;
+ }
- for (k=0;k<8;k++) {
- oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
- }
+ int parityBits = *((uint32_t *)(got+i+4));
+ // 4 bytes of additional information...
+ // maximum of 32 additional parity bit information
+ //
+ // TODO:
+ // at each quarter bit period we can send power level (16 levels)
+ // or each half bit period in 256 levels.
- //if((parityBits >> (len - j - 1)) & 0x01) {
- if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
- sprintf(line+(j*4), "%02x! ", frame[j]);
- }
- else {
- sprintf(line+(j*4), "%02x ", frame[j]);
- }
- }
-
- PrintAndLog(" +%7d: %3d: %s %s",
- (prev < 0 ? 0 : (timestamp - prev)),
- bits,
- (isResponse ? "TAG" : " "),
- line);
+ int bits = got[i+8];
+ int len = nbytes(got[i+8]);
+ if (len > 100) {
+ break;
+ }
+ if (i + len > traceLen) { break;}
+
+ uint8_t *frame = (got+i+9);
+
+ // Break and stick with current result if buffer was not completely full
+ if (frame[0] == 0x44 && frame[1] == 0x44 && frame[3] == 0x44) { break; }
+
+ char line[1000] = "";
+ int j;
+ for (j = 0; j < len; j++) {
+ int oddparity = 0x01;
+ int k;
+
+ for (k=0;k<8;k++) {
+ oddparity ^= (((frame[j] & 0xFF) >> k) & 0x01);
+ }
+
+ //if((parityBits >> (len - j - 1)) & 0x01) {
+ if (isResponse && (oddparity != ((parityBits >> (len - j - 1)) & 0x01))) {
+ sprintf(line+(j*4), "%02x! ", frame[j]);
+ }
+ else {
+ sprintf(line+(j*4), "%02x ", frame[j]);
+ }
+ }
- if (pf) {
- fprintf(pf," +%7d: %3d: %s %s\n",
- (prev < 0 ? 0 : (timestamp - prev)),
- bits,
- (isResponse ? "TAG" : " "),
- line);
- }
-
- prev = timestamp;
- i += (len + 9);
- }
+ PrintAndLog(" +%7d: %3d: %s %s",
+ (prev < 0 ? 0 : (timestamp - prev)),
+ bits,
+ (isResponse ? "TAG" : " "),
+ line);
+
+ if (pf) {
+ fprintf(pf," +%7d: %3d: %s %s\n",
+ (prev < 0 ? 0 : (timestamp - prev)),
+ bits,
+ (isResponse ? "TAG" : " "),
+ line);
+ }
+
+ prev = timestamp;
+ i += (len + 9);
+ }
- if (pf) {
- fclose(pf);
- PrintAndLog("Recorded activity succesfully written to file: %s", filename);
- }
+ if (pf) {
+ fclose(pf);
+ PrintAndLog("Recorded activity succesfully written to file: %s", filename);
+ }
- return 0;
+ free(got);
+ return 0;
}
int CmdLFHitagSnoop(const char *Cmd) {
} break;
case CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K: {
- sample_buf_len += UC->arg[1];
memcpy(sample_buf+(UC->arg[0]),UC->d.asBytes,UC->arg[1]);
} break;
#include "cmdmain.h"
uint8_t* sample_buf;
-size_t sample_buf_len;
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index)
{
- sample_buf_len = 0;
sample_buf = dest;
UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}};
SendCommand(&c);
#include <stdint.h>
-//trace buffer size as defined in armsrc/apps.h TRACE_SIZE
-#define TRACE_BUFFER_SIZE 4096
#define FILE_PATH_SIZE 1000
-#define SAMPLE_BUFFER_SIZE 64
extern uint8_t* sample_buf;
-extern size_t sample_buf_len;
#define arraylen(x) (sizeof(x)/sizeof((x)[0]))
void GetFromBigBuf(uint8_t *dest, int bytes, int start_index);
typedef enum {
RHT2F_PASSWORD = 21,
RHT2F_AUTHENTICATE = 22,
- RHT2F_CRYPTO = 23,
- RHT2F_TEST_AUTH_ATTEMPTS = 25,
+ RHT2F_CRYPTO = 23,
+ RHT2F_TEST_AUTH_ATTEMPTS = 25,
} hitag_function;
typedef struct {
typedef union {
rht2d_password pwd;
rht2d_authenticate auth;
- rht2d_crypto crypto;
+ rht2d_crypto crypto;
} hitag_data;
#endif