Research, development and trades concerning the powerful Proxmark3 device.
Remember; sharing is caring. Bring something back to the community.
"Learn the tools of the trade the hard way." +Fravia
You are not logged in.
Time changes and with it the technology
Proxmark3 @ discord
Users of this forum, please be aware that information stored on this site is not private.
Pages: 1
Hi
I would like to try to implement one of the feature in the feature list of the next proxmark3 (See the "REQUESTS - What would you like to see next on proxmark3?" thread).
I would like to implement the "EM4x50 full read/write/password". I have some questions and some ideas as how to approach this task.
First of all if anyone is already on this task please let me know.
The EM4x50 has 1K bit of EEPROM organized in 32 words of 32 bits.
Word 0 - Password Control Word
Word 1 - Protection word - Defines the protected and write inhinited words
Word 2 - Control word - Defines the public words
Word 3 - 31 - User Data
The EM4x50 contains additinal 2 words (read only)
Word 32 Device Serial Number
Word 33 Device Identification Word
When a reader approaches the EM4x50, it will start transmitting its public words one by one separated by a listen window (320/160 clocks). During the listen window the EM4450 may receive commands from the reader. The first task is to implement a loop sending the public words in a timely manner and listening for a command in the listen window.
Please let me know if you have any idea as how to design the solution. I think the hitag2 code addresses similar issues (frame and timing).
Is there a description of the FPGA registers?
Thanks,
Ari
Offline
The good hardware folks around here are often very busy so it might be a while before a good answer comes. I'd help if I could but I know little about the FPGA. The hitag code would be a good start to attempt to understand.
Offline
The em4x50 continuously transmits a frame in the following format
listen_window listen_window first_data_word listen_window second_data_word........listen_window last_data_word
The range of data words is defined by the control register.
The em4x50 should listen to the transceiver commands during the listen windows. In case a command is received the em4x50 stops the frame transmission and perform the command. To signal it wants to send a command, the transceiver should send two 0's starting 1 to 7 RF clocks into the listen window.
Do you have any ideas how can I identify two consecutive 0's during the listen window?
Please see below the code of the listen window and the main loop of the em4x50 simulator.
static int em4x50_listen()
{
int period;
// Reset clock
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
// The listen window is composed of
// 32 RF periods - high
// 32 RF periods - low
// 128 RF periods - high
// 64 RF periods - low
// 64 RF periods - high
// 32 RF periods - high
period = T0*EM4x50_T_HALF_PERIOD;
HIGH(GPIO_SSC_DOUT);
while (AT91C_BASE_TC0->TC_CV < period);
// 32 RF periods - low
period += T0*EM4x50_T_HALF_PERIOD;
LOW(GPIO_SSC_DOUT);
while (AT91C_BASE_TC0->TC_CV < period);
// 128 RF periods - high
period += T0 * 2 * EM4x50_T_FULL_PERIOD;
HIGH(GPIO_SSC_DOUT);
while (AT91C_BASE_TC0->TC_CV < period);
// 64 RF periods - low
period += T0 * EM4x50_T_FULL_PERIOD;
LOW(GPIO_SSC_DOUT);
while (AT91C_BASE_TC0->TC_CV < period);
// 64 RF periods - high
period += T0 * EM4x50_T_FULL_PERIOD;
HIGH(GPIO_SSC_DOUT);
while (AT91C_BASE_TC0->TC_CV < period);
return EM4x50_COMMAND_NONE;
}
void SimulateEM4x50Tag(bool tag_mem_supplied, byte_t* data)
{
int command;
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// Clean up trace and prepare it for storing frames
set_tracing(TRUE);
clear_trace();
DbpString("Starting EM4x50 simulation");
LED_D_ON();
if (tag_mem_supplied)
{
DbpString("Loading EM4x50 memory...");
memcpy((byte_t*)tag.data, data, sizeof(tag.data));
em4x50_init();
}
// Set up simulator mode, frequency divisor which will drive the FPGA
// and analog mux selection.
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
RELAY_OFF();
// 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;
// Disable modulation at default, which means release resistance
LOW(GPIO_SSC_DOUT);
// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0);
// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1);
AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME;
// Disable timer during configuration
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
// 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_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
while (!BUTTON_PRESS())
{
// Watchdog hit
WDT_HIT();
// The structure for each frame is
// LISTEN_WINDOW LISTEN_WINDOW FIRST_WORD LISTEN_WINDOW SECOND_WORD ...... LISTEN_WINDOW LAST_WORD
// i.e. it starts with a listen windows and then pairs of (listen window, data word).
// In read mode the range of transmitted words is defined by the control register.
// During the listen window the transceiver can send commands to the em4x50 . The em4x50 will stop the frame transmission
// and will perform the command.
// Start a frame with a listen window.
command = em4x50_listen();
// If no command was received during the listen window, continue with the frame transmission.
if (command == EM4x50_COMMAND_NONE)
{
// Loop thought the [first_word..last_word] and transmit pairs of (listen window, data word).
for (int i = tag.first_word; i <= tag.last_word; i++)
{
// // Start a pair with a listen window.
command = em4x50_listen();
// If no command was received during the listen window, continue with the data word transmission.
if (command == EM4x50_COMMAND_NONE)
{
em4x50_send_word(i);
}
// If a command was received during the listen window, break the frame transmission.
else
{
break;
}
}
}
// The transceiver can send a selective mode command and provide the first and last word to be transmitted. The em4x50 will send
// those words in the followoing frame once and will return to read mode.
// If the current frame was transmitted in selective read state then the em4x50 should return to read mode.
if (tag.state == EM4X50_STATE_SELECTIVE_READ)
{
// Set the state to read mode.
tag.state = EM4X50_STATE_READ;
// Set the transmitted words range according to the control register.
tag.first_word = tag.data[EM4x50_CONTROL][EM4x50_FIRST_WORD_READ_BYTE];
tag.last_word = tag.data[EM4x50_CONTROL][EM4x50_LAST_WORD_READ_BYTE];
}
// If a command was received during the frame
if (command != EM4x50_COMMAND_NONE)
{
switch (command)
{
case EM4x50_COMMAND_LOGIN:
{
// Handle login command.
em4x50_handle_login_command();
}
break;
case EM4x50_COMMAND_WRITE_PASSWORD:
{
// Handle write password command.
em4x50_handle_write_password_command();
}
break;
case EM4x50_COMMAND_WRITE:
{
// Handle write command.
em4x50_handle_write_command();
}
break;
case EM4x50_COMMAND_SELECTIVE_READ:
{
// Handle selective command.
em4x50_handle_selective_read_command();
}
break;
case EM4x50_COMMAND_RESET:
{
// Handle reset command.
em4x50_handle_reset_command();
}
break;
};
}
// Reset the timer to restart while-loop that receives frames
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
}
LED_D_OFF();
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
DbpString("Sim Stopped");
}
Offline
@Shanti Wishing you all the best. pls don't stop Shanti.
Offline
Hard to look at code here like this, make a fork of the pm3 on github and discuss it there.
However, just looking at your code, makes me wonder if it works.
You seem to add periods all the time when I'm guessing you just want a period.
like
"period += T0*EM4x50_T_HALF_PERIOD;" I'm guessing you want it to be
"period = T0*EM4x50_T_HALF_PERIOD;"
// 32 RF periods - high
period = T0*EM4x50_T_HALF_PERIOD;
HIGH(GPIO_SSC_DOUT);
while (AT91C_BASE_TC0->TC_CV < period);
// 32 RF periods - low
period += T0*EM4x50_T_HALF_PERIOD;
LOW(GPIO_SSC_DOUT);
while (AT91C_BASE_TC0->TC_CV < period);
// 128 RF periods - high
period += T0 * 2 * EM4x50_T_FULL_PERIOD;
Offline
Since he's not resetting the timer he would correctly need to continue to add them.. The real question is how can he listen for an answer while modulating. (Sending). And I do not know the answer.
Offline
According to the EM4450 datasheet
Receive Mode
To activate the Receive Mode, the Transceiver sends to the chip the RM pattern (while in the modulated phase of a Listen Window LIW). The EM4450 will stop sending data upon reception of a valid RM. The chip then expects a command. The RM pattern consists of 2 bits "0" sent by the transceiver. The first bit "0" transmitted is to be detected during the 64 (32 opt 32) periods where the modulation is "ON" in LIW.
Fig. 21 in the datasheet describes the signal on the transponder coil.
I'm currently configuring the FPGA to detect the falling edge and uses TC1 to measure the time from the start of the LIW till the falling edge. If that falls into the spec (around 7 FR clocks) then its a valid "0". If I get two valid "0" I'm stopping the modulation and start looking for the transceiver command which follows the double "0".
Offline
I'm currently configuring the FPGA to detect the falling edge and uses TC1 to measure the time from the start of the LIW till the falling edge. If that falls into the spec (around 7 FR clocks) then its a valid "0". If I get two valid "0" I'm stopping the modulation and start looking for the transceiver command which follows the double "0".
i assume you have updated code then? i look forward to seeing it. good work.
Offline
yeah, I saw your fork on GitHub, nice work!
Offline
Pages: 1