mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-20 20:18:17 +08:00
hitag sim changes
This commit is contained in:
parent
a9a57e4a92
commit
ebc04ea27e
1 changed files with 234 additions and 188 deletions
422
armsrc/hitag2.c
422
armsrc/hitag2.c
|
@ -18,7 +18,7 @@
|
|||
// Piwi, 2019
|
||||
// Iceman, 2019
|
||||
// Anon, 2019
|
||||
// Doegos, 2020
|
||||
// Doegox, 2020
|
||||
|
||||
#include "hitag2.h"
|
||||
#include "hitag2_crypto.h"
|
||||
|
@ -96,7 +96,6 @@ size_t blocknr;
|
|||
size_t flipped_bit = 0;
|
||||
uint32_t byte_value = 0;
|
||||
|
||||
|
||||
static int hitag2_reset(void) {
|
||||
tag.state = TAG_STATE_RESET;
|
||||
tag.crypto_active = 0;
|
||||
|
@ -143,6 +142,8 @@ static int hitag2_init(void) {
|
|||
#define HITAG_T_TAG_CAPTURE_THREE_HALF 41
|
||||
#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57
|
||||
|
||||
/*
|
||||
// sim
|
||||
static void hitag_send_bit(int bit) {
|
||||
LED_A_ON();
|
||||
|
||||
|
@ -167,6 +168,7 @@ static void hitag_send_bit(int bit) {
|
|||
LED_A_OFF();
|
||||
}
|
||||
|
||||
// sim
|
||||
static void hitag_send_frame(const uint8_t *frame, size_t frame_len) {
|
||||
// SOF - send start of frame
|
||||
hitag_send_bit(1);
|
||||
|
@ -183,6 +185,7 @@ static void hitag_send_frame(const uint8_t *frame, size_t frame_len) {
|
|||
// Drop the modulation
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
}
|
||||
*/
|
||||
|
||||
// sim
|
||||
static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) {
|
||||
|
@ -215,42 +218,43 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
|
||||
// Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number
|
||||
case 10: {
|
||||
unsigned int sector = (~(((rx[0] << 2) & 0x04) | ((rx[1] >> 6) & 0x03)) & 0x07);
|
||||
uint16_t sector = (~(((rx[0] << 2) & 0x04) | ((rx[1] >> 6) & 0x03)) & 0x07);
|
||||
|
||||
// Verify complement of sector index
|
||||
if (sector != ((rx[0] >> 3) & 0x07)) {
|
||||
//DbpString("Transmission error (read/write)");
|
||||
DbpString("Transmission error (read/write)");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (rx[0] & 0xC6) {
|
||||
// Read command: 11xx x00y
|
||||
case 0xC0:
|
||||
case 0xC0: {
|
||||
memcpy(tx, tag.sectors[sector], 4);
|
||||
*txlen = 32;
|
||||
break;
|
||||
|
||||
}
|
||||
// Inverted Read command: 01xx x10y
|
||||
case 0x44:
|
||||
case 0x44: {
|
||||
for (size_t i = 0; i < 4; i++) {
|
||||
tx[i] = tag.sectors[sector][i] ^ 0xff;
|
||||
}
|
||||
*txlen = 32;
|
||||
break;
|
||||
|
||||
}
|
||||
// Write command: 10xx x01y
|
||||
case 0x82:
|
||||
case 0x82: {
|
||||
// Prepare write, acknowledge by repeating command
|
||||
memcpy(tx, rx, nbytes(rxlen));
|
||||
*txlen = rxlen;
|
||||
tag.active_sector = sector;
|
||||
tag.state = TAG_STATE_WRITING;
|
||||
break;
|
||||
|
||||
}
|
||||
// Unknown command
|
||||
default:
|
||||
default: {
|
||||
Dbprintf("Unknown command: %02x %02x", rx[0], rx[1]);
|
||||
return;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -284,15 +288,13 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
|
||||
// Reset the cipher state
|
||||
hitag2_cipher_reset(&tag, rx);
|
||||
|
||||
// Check if the authentication was correct
|
||||
if (!hitag2_cipher_authenticate(&(tag.cs), rx + 4)) {
|
||||
// The reader failed to authenticate, do nothing
|
||||
Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!", rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]);
|
||||
return;
|
||||
}
|
||||
// Succesful, but commented out reporting back to the Host, this may delay to much.
|
||||
// Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]);
|
||||
|
||||
// Activate encryption algorithm for all further communication
|
||||
tag.crypto_active = 1;
|
||||
|
||||
|
@ -303,15 +305,13 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_
|
|||
break;
|
||||
}
|
||||
|
||||
// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false);
|
||||
// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true);
|
||||
|
||||
if (tag.crypto_active) {
|
||||
hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8);
|
||||
}
|
||||
}
|
||||
|
||||
// sim
|
||||
// reader/writer
|
||||
// returns how long it took
|
||||
static uint32_t hitag_reader_send_bit(int bit) {
|
||||
uint32_t wait = 0;
|
||||
LED_A_ON();
|
||||
|
@ -330,36 +330,41 @@ static uint32_t hitag_reader_send_bit(int bit) {
|
|||
|
||||
if (bit == 0) {
|
||||
// Zero bit: |_-|
|
||||
lf_wait_periods(HITAG_T_0-HITAG_T_LOW); // wait for 18-22 times the carrier period
|
||||
wait += HITAG_T_0-HITAG_T_LOW;
|
||||
lf_wait_periods(HITAG_T_0 - HITAG_T_LOW); // wait for 18-22 times the carrier period
|
||||
wait += HITAG_T_0 - HITAG_T_LOW;
|
||||
} else {
|
||||
// One bit: |_--|
|
||||
lf_wait_periods(HITAG_T_1-HITAG_T_LOW); // wait for 26-32 times the carrier period
|
||||
wait += HITAG_T_1-HITAG_T_LOW;
|
||||
lf_wait_periods(HITAG_T_1 - HITAG_T_LOW); // wait for 26-32 times the carrier period
|
||||
wait += HITAG_T_1 - HITAG_T_LOW;
|
||||
}
|
||||
/*lf_wait_periods(10);*/
|
||||
LED_A_OFF();
|
||||
return wait;
|
||||
}
|
||||
|
||||
// sim
|
||||
// reader/writer
|
||||
static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) {
|
||||
|
||||
uint32_t wait = 0;
|
||||
// Send the content of the frame
|
||||
for (size_t i = 0; i < frame_len; i++) {
|
||||
wait += hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1);
|
||||
}
|
||||
|
||||
// Enable modulation, which means, drop the field
|
||||
lf_modulation(true);
|
||||
|
||||
// Wait for 4-10 times the carrier period
|
||||
lf_wait_periods(HITAG_T_LOW);
|
||||
wait += HITAG_T_LOW;
|
||||
|
||||
// Disable modulation, just activates the field again
|
||||
lf_modulation(false);
|
||||
|
||||
// t_stop, high field for stop condition (> 36)
|
||||
lf_wait_periods(HITAG_T_STOP);
|
||||
wait += HITAG_T_STOP;
|
||||
|
||||
return wait;
|
||||
}
|
||||
|
||||
|
@ -688,10 +693,10 @@ static bool hitag2_password(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
|
|||
}
|
||||
|
||||
if (blocknr > 7) {
|
||||
DbpString("Read successful!");
|
||||
bSuccessful = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
*txlen = 10;
|
||||
tx[0] = 0xC0 | (blocknr << 3) | ((blocknr ^ 7) >> 2);
|
||||
tx[1] = ((blocknr ^ 7) << 6);
|
||||
|
@ -951,7 +956,6 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
|
|||
Dbhexdump(4, rx, false);
|
||||
}
|
||||
if (blocknr > 0) {
|
||||
DbpString("Read successful!");
|
||||
bSuccessful = true;
|
||||
return false;
|
||||
}
|
||||
|
@ -970,10 +974,6 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t
|
|||
// Hitag2 Sniffing
|
||||
void SniffHitag2(void) {
|
||||
|
||||
LEDsoff();
|
||||
StopTicks();
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
clear_trace();
|
||||
|
@ -988,19 +988,34 @@ void SniffHitag2(void) {
|
|||
DbpString("Starting Hitag2 sniffing");
|
||||
LED_D_ON();
|
||||
|
||||
lf_init(false);
|
||||
lf_init(false, false);
|
||||
|
||||
logging = false;
|
||||
|
||||
size_t periods = 0;
|
||||
uint8_t periods_bytes[4];
|
||||
|
||||
int16_t checked = 0;
|
||||
|
||||
/*bool waiting_for_first_edge = true;*/
|
||||
LED_C_ON();
|
||||
|
||||
while (!BUTTON_PRESS() && !data_available()) {
|
||||
while (!BUTTON_PRESS()) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// only every 1000th times, in order to save time when collecting samples.
|
||||
if (checked == 1000) {
|
||||
if (data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
|
||||
|
||||
// Receive frame, watch for at most T0*EOF periods
|
||||
lf_reset_counter();
|
||||
|
||||
|
@ -1021,69 +1036,57 @@ void SniffHitag2(void) {
|
|||
LogTrace(periods_bytes, 4, 0, 0, NULL, true);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
// Check if frame was captured
|
||||
if (rxlen > 0) {
|
||||
// frame_count++;
|
||||
LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame);
|
||||
|
||||
// Check if we recognize a valid authentication attempt
|
||||
if (nbytes(rxlen) == 8) {
|
||||
// Store the authentication attempt
|
||||
if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) {
|
||||
memcpy(auth_table + auth_table_len, rx, 8);
|
||||
auth_table_len += 8;
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
lf_finalize();
|
||||
|
||||
StartTicks();
|
||||
|
||||
DbpString("Hitag2 sniffing finish. Use `lf hitag list` for annotations");
|
||||
}
|
||||
|
||||
// Hitag2 simulation
|
||||
void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
||||
|
||||
StopTicks();
|
||||
|
||||
// int frame_count = 0;
|
||||
int response = 0, overflow = 0;
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen = 0;
|
||||
uint8_t tx[HITAG_FRAME_LEN];
|
||||
size_t txlen = 0;
|
||||
|
||||
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
|
||||
BigBuf_free();
|
||||
BigBuf_Clear_ext(false);
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
|
||||
// empties bigbuff etc
|
||||
lf_init(false, true);
|
||||
|
||||
int response = 0;
|
||||
uint8_t rx[HITAG_FRAME_LEN];
|
||||
size_t rxlen = 0;
|
||||
uint8_t tx[HITAG_FRAME_LEN];
|
||||
size_t txlen = 0;
|
||||
|
||||
auth_table_len = 0;
|
||||
auth_table_pos = 0;
|
||||
auth_table = BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||
memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||
// auth_table = BigBuf_malloc(AUTH_TABLE_LENGTH);
|
||||
// memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
|
||||
|
||||
// Reset the received frame, frame count and timing info
|
||||
memset(rx, 0x00, sizeof(rx));
|
||||
// memset(rx, 0x00, sizeof(rx));
|
||||
// memset(tx, 0x00, sizeof(tx));
|
||||
|
||||
DbpString("Starting Hitag2 simulation");
|
||||
|
||||
LED_D_ON();
|
||||
|
||||
// hitag2 state machine?
|
||||
hitag2_init();
|
||||
|
||||
// copy user supplied emulation data
|
||||
if (tag_mem_supplied) {
|
||||
DbpString("Loading hitag2 memory...");
|
||||
memcpy((uint8_t *)tag.sectors, data, 48);
|
||||
}
|
||||
|
||||
// printing
|
||||
uint32_t block = 0;
|
||||
for (size_t i = 0; i < 12; i++) {
|
||||
|
||||
// num2bytes?
|
||||
for (size_t j = 0; j < 4; j++) {
|
||||
block <<= 8;
|
||||
block |= tag.sectors[i][j];
|
||||
|
@ -1091,89 +1094,137 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
|||
Dbprintf("| %d | %08x |", i, block);
|
||||
}
|
||||
|
||||
// Set up simulator mode, frequency divisor which will drive the FPGA
|
||||
// and analog mux selection.
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
|
||||
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125); //125kHz
|
||||
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
|
||||
uint8_t tag_modulation;
|
||||
size_t max_nrzs = 8 * HITAG_FRAME_LEN + 5;
|
||||
uint8_t nrz_samples[max_nrzs];
|
||||
size_t nrzs = 0, periods = 0;
|
||||
|
||||
// Configure output pin that is connected to the FPGA (for modulating)
|
||||
AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT;
|
||||
AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT;
|
||||
// uint32_t command_start = 0, command_duration = 0;
|
||||
|
||||
// Disable modulation at default, which means release resistance
|
||||
LOW(GPIO_SSC_DOUT);
|
||||
int16_t checked = 0;
|
||||
|
||||
// Enable Peripheral Clock for
|
||||
// TIMER_CLOCK0, used to measure exact timing before answering
|
||||
// TIMER_CLOCK1, used to capture edges of the tag frames
|
||||
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
|
||||
while (!BUTTON_PRESS()) {
|
||||
|
||||
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
|
||||
|
||||
// Disable timer during configuration
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
|
||||
// TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers
|
||||
AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK;
|
||||
|
||||
// TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger,
|
||||
// external trigger rising edge, load RA on rising edge of TIOA.
|
||||
AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING;
|
||||
|
||||
// Enable and reset counter
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
|
||||
// synchronized startup procedure
|
||||
while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC0 returned to zero
|
||||
|
||||
while (!BUTTON_PRESS() && !data_available()) {
|
||||
// Watchdog hit
|
||||
loop1:
|
||||
LED_A_OFF();
|
||||
WDT_HIT();
|
||||
|
||||
// Receive frame, watch for at most T0*EOF periods
|
||||
while (AT91C_BASE_TC1->TC_CV < HITAG_T0 * HITAG_T_EOF) {
|
||||
// Check if rising edge in modulation is detected
|
||||
if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) {
|
||||
// Retrieve the new timing values
|
||||
int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0) + overflow;
|
||||
overflow = 0;
|
||||
// only every 1000th times, in order to save time when collecting samples.
|
||||
if (checked == 100) {
|
||||
if (data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
|
||||
// Reset timer every frame, we have to capture the last edge for timing
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
rxlen = 0;
|
||||
|
||||
LED_B_ON();
|
||||
// Keep administration of the first edge detection
|
||||
bool waiting_for_first_edge = true;
|
||||
|
||||
// Capture reader frame
|
||||
if (ra >= HITAG_T_STOP) {
|
||||
if (rxlen != 0) {
|
||||
//DbpString("wierd0?");
|
||||
}
|
||||
// Capture the T0 periods that have passed since last communication or field drop (reset)
|
||||
response = (ra - HITAG_T_LOW);
|
||||
} else if (ra >= HITAG_T_1_MIN) {
|
||||
// '1' bit
|
||||
rx[rxlen / 8] |= 1 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
} else if (ra >= HITAG_T_0_MIN) {
|
||||
// '0' bit
|
||||
rx[rxlen / 8] |= 0 << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
} else {
|
||||
// Ignore wierd value, is to small to mean anything
|
||||
// Did we detected any modulaiton at all
|
||||
bool detected_tag_modulation = false;
|
||||
|
||||
// Use the current modulation state as starting point
|
||||
tag_modulation = lf_get_tag_modulation();
|
||||
|
||||
// Receive frame, watch for at most max_nrzs periods
|
||||
// Reset the number of NRZ samples and use edge detection to detect them
|
||||
nrzs = 0;
|
||||
while (nrzs < max_nrzs) {
|
||||
// Get the timing of the next edge in number of wave periods
|
||||
periods = lf_count_edge_periods(128);
|
||||
|
||||
// Just break out of loop after an initial time-out (tag is probably not available)
|
||||
// The function lf_count_edge_periods() returns 0 when a time-out occurs
|
||||
if (periods == 0) {
|
||||
goto loop1; //break;
|
||||
}
|
||||
|
||||
LED_A_ON();
|
||||
|
||||
// Are we dealing with the first incoming edge
|
||||
if (waiting_for_first_edge) {
|
||||
|
||||
// Register the number of periods that have passed
|
||||
response = periods;
|
||||
|
||||
// Indicate that we have dealt with the first edge
|
||||
waiting_for_first_edge = false;
|
||||
|
||||
// The first edge is always a single NRZ bit, force periods on 16
|
||||
periods = 16;
|
||||
|
||||
// We have received more than 0 periods, so we have detected a tag response
|
||||
detected_tag_modulation = true;
|
||||
}
|
||||
|
||||
// Evaluate the number of periods before the next edge
|
||||
if (periods > 24 && periods <= 64) {
|
||||
// Detected two sequential equal bits and a modulation switch
|
||||
// NRZ modulation: (11 => --|) or (11 __|)
|
||||
nrz_samples[nrzs++] = tag_modulation;
|
||||
nrz_samples[nrzs++] = tag_modulation;
|
||||
// Invert tag modulation state
|
||||
tag_modulation ^= 1;
|
||||
} else if (periods > 0 && periods <= 24) {
|
||||
// Detected one bit and a modulation switch
|
||||
// NRZ modulation: (1 => -|) or (0 _|)
|
||||
nrz_samples[nrzs++] = tag_modulation;
|
||||
tag_modulation ^= 1;
|
||||
} else {
|
||||
tag_modulation ^= 1;
|
||||
// The function lf_count_edge_periods() returns > 64 periods, this is not a valid number periods
|
||||
Dbprintf("Detected unexpected period count: %d", periods);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If there is no response, just repeat the loop
|
||||
if (!detected_tag_modulation) continue;
|
||||
|
||||
// Make sure we always have an even number of samples. This fixes the problem
|
||||
// of ending the manchester decoding with a zero. See the example below where
|
||||
// the '|' character is end of modulation
|
||||
// One at the end: ..._-|_____...
|
||||
// Zero at the end: ...-_|_____...
|
||||
// The last modulation change of a zero is not detected, but we should take
|
||||
// the half period in account, otherwise the demodulator will fail.
|
||||
if ((nrzs % 2) != 0) {
|
||||
nrz_samples[nrzs++] = tag_modulation;
|
||||
}
|
||||
|
||||
LED_B_ON();
|
||||
|
||||
// decode bitstream
|
||||
manrawdecode((uint8_t *)nrz_samples, &nrzs, true, 0);
|
||||
|
||||
// Verify if the header consists of five consecutive ones
|
||||
if (nrzs < 5) {
|
||||
Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs);
|
||||
continue;
|
||||
} else {
|
||||
for (size_t i = 0; i < 5; i++){
|
||||
if (nrz_samples[i] != 1) {
|
||||
Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pack the response into a byte array
|
||||
for (size_t i = 5; i < 37; i++){
|
||||
uint8_t bit = nrz_samples[i];
|
||||
rx[rxlen / 8] |= bit << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
|
||||
// Check if frame was captured
|
||||
if (rxlen > 4) {
|
||||
// frame_count++;
|
||||
LogTrace(rx, nbytes(rxlen), response, response, NULL, true);
|
||||
|
||||
// Disable timer 1 with external trigger to avoid triggers during our own modulation
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
LogTrace(rx, nbytes(rxlen), response, 0, NULL, true);
|
||||
|
||||
// Process the incoming frame (rx) and prepare the outgoing frame (tx)
|
||||
hitag2_handle_reader_command(rx, rxlen, tx, &txlen);
|
||||
|
@ -1183,11 +1234,15 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
|||
// with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low)
|
||||
// periods. The gap time T_Low varies (4..10). All timer values are in
|
||||
// terms of T0 units
|
||||
while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * (HITAG_T_WAIT_1_MIN - HITAG_T_LOW));
|
||||
lf_wait_periods(200);
|
||||
|
||||
// Send and store the tag answer (if there is any)
|
||||
if (txlen) {
|
||||
hitag_send_frame(tx, txlen);
|
||||
// Transmit the tag frame
|
||||
//hitag_send_frame(tx, txlen);
|
||||
lf_manchester_send_bytes(tx, txlen);
|
||||
|
||||
// Store the frame in the trace
|
||||
LogTrace(tx, nbytes(txlen), 0, 0, NULL, false);
|
||||
}
|
||||
|
||||
|
@ -1195,37 +1250,22 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) {
|
|||
memset(rx, 0x00, sizeof(rx));
|
||||
response = 0;
|
||||
|
||||
// Enable and reset external trigger in timer for capturing future frames
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
|
||||
LED_B_OFF();
|
||||
}
|
||||
// Reset the frame length
|
||||
rxlen = 0;
|
||||
// Save the timer overflow, will be 0 when frame was received
|
||||
overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0);
|
||||
// Reset the timer to restart while-loop that receives frames
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
|
||||
}
|
||||
|
||||
LEDsoff();
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
set_tracing(false);
|
||||
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
|
||||
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
|
||||
lf_finalize();
|
||||
|
||||
// release allocated memory from BigBuff.
|
||||
BigBuf_free();
|
||||
|
||||
StartTicks();
|
||||
DbpString("Sim stopped");
|
||||
|
||||
DbpString("Sim Stopped");
|
||||
// reply_ng(CMD_LF_HITAG_SIMULATE, (checked == -1) ? PM3_EOPABORTED : PM3_SUCCESS, (uint8_t *)tag.sectors, tag_size);
|
||||
}
|
||||
|
||||
void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
||||
|
||||
StopTicks();
|
||||
|
||||
int frame_count = 0;
|
||||
uint32_t command_start = 0;
|
||||
uint32_t command_duration = 0;
|
||||
uint32_t response_start = 0;
|
||||
|
@ -1261,9 +1301,8 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
|||
// this part will be unreadable
|
||||
memset(tag.sectors + 2, 0x0, 30);
|
||||
blocknr = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case RHT1F_AUTHENTICATE: {
|
||||
Dbprintf("Read all blocks in authed mode");
|
||||
memcpy(nonce, htd->ht1auth.nonce, 4);
|
||||
|
@ -1284,8 +1323,8 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
|||
DbpString("Logdata_1:");
|
||||
Dbhexdump(4, logdata_1, false);
|
||||
blocknr = 0;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case RHT2F_PASSWORD: {
|
||||
Dbprintf("List identifier in password mode");
|
||||
if (memcmp(htd->pwd.password, "\x00\x00\x00\x00", 4) == 0)
|
||||
|
@ -1334,17 +1373,17 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
|||
default: {
|
||||
Dbprintf("Error, unknown function: %d", htf);
|
||||
set_tracing(false);
|
||||
StartTicks();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
LED_D_ON();
|
||||
|
||||
// hitag2 state machine?
|
||||
hitag2_init();
|
||||
|
||||
// init as reader
|
||||
lf_init(true);
|
||||
lf_init(true, false);
|
||||
|
||||
uint8_t attempt_count = 0;
|
||||
|
||||
|
@ -1379,24 +1418,34 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
|||
size_t max_nrzs = (8 * HITAG_FRAME_LEN + 5) * 2; // up to 2 nrzs per bit
|
||||
uint8_t nrz_samples[max_nrzs];
|
||||
size_t nrzs = 0;
|
||||
int16_t checked = 0;
|
||||
|
||||
while (!bStop && !BUTTON_PRESS() && !data_available()) {
|
||||
while (!bStop) {
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
// only every 1000th times, in order to save time when collecting samples.
|
||||
if (checked == 1000) {
|
||||
if (BUTTON_PRESS() || data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
|
||||
// By default reset the transmission buffer
|
||||
tx = txbuf;
|
||||
switch (htf) {
|
||||
case RHT1F_PLAIN: {
|
||||
bStop = !hitag_plain(rx, rxlen, tx, &txlen, false);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case RHT1F_AUTHENTICATE: {
|
||||
bStop = !hitag1_authenticate(rx, rxlen, tx, &txlen);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case RHT2F_PASSWORD: {
|
||||
bStop = !hitag2_password(rx, rxlen, tx, &txlen, false);
|
||||
break;
|
||||
|
@ -1512,7 +1561,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
|||
// and to be able to overwrite the first samples with the trace (since they currently
|
||||
// still use the same memory space)
|
||||
if (txlen > 0) {
|
||||
frame_count++;
|
||||
LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true);
|
||||
}
|
||||
|
||||
|
@ -1543,7 +1591,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
|||
|
||||
// Verify if the header consists of five consecutive ones
|
||||
if (nrzs < 5) {
|
||||
//Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs);
|
||||
Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs);
|
||||
break;
|
||||
} else {
|
||||
size_t i;
|
||||
|
@ -1560,51 +1608,43 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) {
|
|||
for (size_t i = 5; i < nrzs; i++) {
|
||||
uint8_t bit = nrz_samples[i];
|
||||
if (bit > 1) { // When Manchester detects impossible symbol it writes "7"
|
||||
//Dbprintf("Error in Manchester decoding, abort");
|
||||
Dbprintf("Error in Manchester decoding, abort");
|
||||
break;
|
||||
}
|
||||
rx[rxlen / 8] |= bit << (7 - (rxlen % 8));
|
||||
rxlen++;
|
||||
}
|
||||
|
||||
if (rxlen % 8 == 1) // skip spurious bit
|
||||
rxlen--;
|
||||
|
||||
// Check if frame was captured and store it
|
||||
if (rxlen > 0) {
|
||||
frame_count++;
|
||||
// if (bCollision){
|
||||
// // AC decoding hack
|
||||
// fix_ac_decoding(rx, 64);
|
||||
// rxlen = 32;
|
||||
// }
|
||||
|
||||
LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false);
|
||||
|
||||
// TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag read 23 4F4E4D494B52
|
||||
command_start = response_start + response_duration;
|
||||
// command_start = 0;
|
||||
// Dbhexdump(nbytes(rxlen), rx, false);
|
||||
// Use delta time?
|
||||
// command_start = response_start + response_duration;
|
||||
command_start = 0;
|
||||
nrzs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
lf_finalize();
|
||||
Dbprintf("TX/RX frames recorded: %u", frame_count);
|
||||
|
||||
// release allocated memory from BigBuff.
|
||||
BigBuf_free();
|
||||
StartTicks();
|
||||
|
||||
if (bSuccessful)
|
||||
reply_old(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size);
|
||||
reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size);
|
||||
else
|
||||
reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
||||
|
||||
StopTicks();
|
||||
|
||||
int frame_count = 0;
|
||||
uint32_t command_start = 0;
|
||||
uint32_t command_duration = 0;
|
||||
uint32_t response_start = 0;
|
||||
|
@ -1659,7 +1699,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
break;
|
||||
default: {
|
||||
Dbprintf("Error, unknown function: %d", htf);
|
||||
StartTicks();
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
@ -1670,7 +1709,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
hitag2_init();
|
||||
|
||||
// init as reader
|
||||
lf_init(true);
|
||||
lf_init(true, false);
|
||||
|
||||
// Tag specific configuration settings (sof, timings, etc.)
|
||||
if (htf < 10) {
|
||||
|
@ -1704,7 +1743,19 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
uint8_t nrz_samples[max_nrzs];
|
||||
size_t nrzs = 0;
|
||||
|
||||
while (!bStop && !BUTTON_PRESS() && !data_available()) {
|
||||
int16_t checked = 0;
|
||||
while (!bStop) {
|
||||
|
||||
// only every 1000th times, in order to save time when collecting samples.
|
||||
if (checked == 1000) {
|
||||
if (BUTTON_PRESS() || data_available()) {
|
||||
checked = -1;
|
||||
break;
|
||||
} else {
|
||||
checked = 0;
|
||||
}
|
||||
}
|
||||
++checked;
|
||||
|
||||
WDT_HIT();
|
||||
|
||||
|
@ -1731,7 +1782,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
|
||||
// Transmit the reader frame
|
||||
command_duration = hitag_reader_send_frame(tx, txlen);
|
||||
|
||||
|
||||
response_start = command_start + command_duration;
|
||||
|
||||
// Let the antenna and ADC values settle
|
||||
|
@ -1814,7 +1865,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
// and to be able to overwrite the first samples with the trace (since they currently
|
||||
// still use the same memory space)
|
||||
if (txlen > 0) {
|
||||
frame_count++;
|
||||
LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true);
|
||||
}
|
||||
|
||||
|
@ -1872,8 +1922,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
|
||||
// Check if frame was captured and store it
|
||||
if (rxlen > 0) {
|
||||
frame_count++;
|
||||
|
||||
LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false);
|
||||
command_start = 0;
|
||||
}
|
||||
|
@ -1882,11 +1930,9 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) {
|
|||
|
||||
out:
|
||||
lf_finalize();
|
||||
Dbprintf("TX/RX frames recorded: %u", frame_count);
|
||||
|
||||
// release allocated memory from BigBuff.
|
||||
BigBuf_free();
|
||||
StartTicks();
|
||||
|
||||
|
||||
reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue