mirror of
https://github.com/Proxmark/proxmark3.git
synced 2025-08-20 13:23:25 -07:00
fix 'hf iclass sim':
* add simulation of block 3 and 4 reads * add simulation of READ4 (4 blocks read) * fixing TransmitTo15693Reader() (again) * FPGA change (hi_simulate.v): avoid spp_clk phase changes * some whitespace fixes
This commit is contained in:
parent
3d2c9c9b06
commit
a66f26da18
5 changed files with 198 additions and 159 deletions
|
@ -860,6 +860,12 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
uint8_t *resp_cc = BigBuf_malloc(18);
|
uint8_t *resp_cc = BigBuf_malloc(18);
|
||||||
int resp_cc_len;
|
int resp_cc_len;
|
||||||
|
|
||||||
|
// Kd, Kc (blocks 3 and 4). Cannot be read. Always respond with 0xff bytes only
|
||||||
|
uint8_t *resp_ff = BigBuf_malloc(22);
|
||||||
|
int resp_ff_len;
|
||||||
|
uint8_t ff_data[10] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00};
|
||||||
|
AppendCrc(ff_data, 8);
|
||||||
|
|
||||||
// Application Issuer Area (block 5)
|
// Application Issuer Area (block 5)
|
||||||
uint8_t *resp_aia = BigBuf_malloc(22);
|
uint8_t *resp_aia = BigBuf_malloc(22);
|
||||||
int resp_aia_len;
|
int resp_aia_len;
|
||||||
|
@ -897,14 +903,19 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
memcpy(resp_cc, ToSend, ToSendMax);
|
memcpy(resp_cc, ToSend, ToSendMax);
|
||||||
resp_cc_len = ToSendMax;
|
resp_cc_len = ToSendMax;
|
||||||
|
|
||||||
|
// Kd, Kc (blocks 3 and 4)
|
||||||
|
CodeIso15693AsTag(ff_data, sizeof(ff_data));
|
||||||
|
memcpy(resp_ff, ToSend, ToSendMax);
|
||||||
|
resp_ff_len = ToSendMax;
|
||||||
|
|
||||||
// Application Issuer Area (block 5)
|
// Application Issuer Area (block 5)
|
||||||
CodeIso15693AsTag(aia_data, sizeof(aia_data));
|
CodeIso15693AsTag(aia_data, sizeof(aia_data));
|
||||||
memcpy(resp_aia, ToSend, ToSendMax);
|
memcpy(resp_aia, ToSend, ToSendMax);
|
||||||
resp_aia_len = ToSendMax;
|
resp_aia_len = ToSendMax;
|
||||||
|
|
||||||
//This is used for responding to READ-block commands or other data which is dynamically generated
|
//This is used for responding to READ-block commands or other data which is dynamically generated
|
||||||
uint8_t *data_generic_trace = BigBuf_malloc(8 + 2); // 8 bytes data + 2byte CRC is max tag answer
|
uint8_t *data_generic_trace = BigBuf_malloc(32 + 2); // 32 bytes data + 2byte CRC is max tag answer
|
||||||
uint8_t *data_response = BigBuf_malloc( (8 + 2) * 2 + 2);
|
uint8_t *data_response = BigBuf_malloc( (32 + 2) * 2 + 2);
|
||||||
|
|
||||||
LED_A_ON();
|
LED_A_ON();
|
||||||
bool buttonPressed = false;
|
bool buttonPressed = false;
|
||||||
|
@ -931,6 +942,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
modulated_response_size = 0;
|
modulated_response_size = 0;
|
||||||
trace_data = NULL;
|
trace_data = NULL;
|
||||||
trace_data_size = 0;
|
trace_data_size = 0;
|
||||||
|
|
||||||
if (receivedCmd[0] == ICLASS_CMD_ACTALL) {
|
if (receivedCmd[0] == ICLASS_CMD_ACTALL) {
|
||||||
// Reader in anticollission phase
|
// Reader in anticollission phase
|
||||||
modulated_response = resp_sof;
|
modulated_response = resp_sof;
|
||||||
|
@ -944,12 +956,11 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
modulated_response_size = resp_anticoll_len;
|
modulated_response_size = resp_anticoll_len;
|
||||||
trace_data = anticoll_data;
|
trace_data = anticoll_data;
|
||||||
trace_data_size = sizeof(anticoll_data);
|
trace_data_size = sizeof(anticoll_data);
|
||||||
//DbpString("Reader requests anticollission CSN:");
|
|
||||||
|
|
||||||
} else if (receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY && len == 4) { // read block
|
} else if (receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY && len == 4) { // read block
|
||||||
uint16_t blockNo = receivedCmd[1];
|
uint16_t blockNo = receivedCmd[1];
|
||||||
if (simulationMode != ICLASS_SIM_MODE_FULL) {
|
if (simulationMode == ICLASS_SIM_MODE_EXIT_AFTER_MAC) {
|
||||||
// provide defaults for blocks 0, 1, 2, 5
|
// provide defaults for blocks 0 ... 5
|
||||||
switch (blockNo) {
|
switch (blockNo) {
|
||||||
case 0: // csn (block 00)
|
case 0: // csn (block 00)
|
||||||
modulated_response = resp_csn;
|
modulated_response = resp_csn;
|
||||||
|
@ -973,6 +984,13 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
memcpy(reader_mac_buf, card_challenge_data, 8);
|
memcpy(reader_mac_buf, card_challenge_data, 8);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 3:
|
||||||
|
case 4: // Kd, Kd, always respond with 0xff bytes
|
||||||
|
modulated_response = resp_ff;
|
||||||
|
modulated_response_size = resp_ff_len;
|
||||||
|
trace_data = ff_data;
|
||||||
|
trace_data_size = sizeof(ff_data);
|
||||||
|
break;
|
||||||
case 5: // Application Issuer Area (block 05)
|
case 5: // Application Issuer Area (block 05)
|
||||||
modulated_response = resp_aia;
|
modulated_response = resp_aia;
|
||||||
modulated_response_size = resp_aia_len;
|
modulated_response_size = resp_aia_len;
|
||||||
|
@ -981,6 +999,12 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
break;
|
break;
|
||||||
// default: don't respond
|
// default: don't respond
|
||||||
}
|
}
|
||||||
|
} else if (simulationMode == ICLASS_SIM_MODE_FULL) {
|
||||||
|
if (blockNo == 3 || blockNo == 4) { // Kd, Kc, always respond with 0xff bytes
|
||||||
|
modulated_response = resp_ff;
|
||||||
|
modulated_response_size = resp_ff_len;
|
||||||
|
trace_data = ff_data;
|
||||||
|
trace_data_size = sizeof(ff_data);
|
||||||
} else { // use data from emulator memory
|
} else { // use data from emulator memory
|
||||||
memcpy(data_generic_trace, emulator + (receivedCmd[1] << 3), 8);
|
memcpy(data_generic_trace, emulator + (receivedCmd[1] << 3), 8);
|
||||||
AppendCrc(data_generic_trace, 8);
|
AppendCrc(data_generic_trace, 8);
|
||||||
|
@ -991,6 +1015,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
modulated_response = data_response;
|
modulated_response = data_response;
|
||||||
modulated_response_size = ToSendMax;
|
modulated_response_size = ToSendMax;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if (receivedCmd[0] == ICLASS_CMD_SELECT) {
|
} else if (receivedCmd[0] == ICLASS_CMD_SELECT) {
|
||||||
// Reader selects anticollission CSN.
|
// Reader selects anticollission CSN.
|
||||||
|
@ -1039,6 +1064,18 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
trace_data = NULL;
|
trace_data = NULL;
|
||||||
trace_data_size = 0;
|
trace_data_size = 0;
|
||||||
|
|
||||||
|
} else if (simulationMode == ICLASS_SIM_MODE_FULL && receivedCmd[0] == ICLASS_CMD_READ4 && len == 4) { // 0x06
|
||||||
|
//Read block
|
||||||
|
//Take the data...
|
||||||
|
memcpy(data_generic_trace, emulator + (receivedCmd[1] << 3), 8 * 4);
|
||||||
|
AppendCrc(data_generic_trace, 8 * 4);
|
||||||
|
trace_data = data_generic_trace;
|
||||||
|
trace_data_size = 8 * 4 + 2;
|
||||||
|
CodeIso15693AsTag(trace_data, trace_data_size);
|
||||||
|
memcpy(data_response, ToSend, ToSendMax);
|
||||||
|
modulated_response = data_response;
|
||||||
|
modulated_response_size = ToSendMax;
|
||||||
|
|
||||||
} else if (receivedCmd[0] == ICLASS_CMD_UPDATE && simulationMode == ICLASS_SIM_MODE_FULL) {
|
} else if (receivedCmd[0] == ICLASS_CMD_UPDATE && simulationMode == ICLASS_SIM_MODE_FULL) {
|
||||||
// Probably the reader wants to update the nonce. Let's just ignore that for now.
|
// Probably the reader wants to update the nonce. Let's just ignore that for now.
|
||||||
// OBS! If this is implemented, don't forget to regenerate the cipher_state
|
// OBS! If this is implemented, don't forget to regenerate the cipher_state
|
||||||
|
@ -1072,7 +1109,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
A legit tag has about 330us delay between reader EOT and tag SOF.
|
A legit tag has about 311,5us delay between reader EOT and tag SOF.
|
||||||
**/
|
**/
|
||||||
if (modulated_response_size > 0) {
|
if (modulated_response_size > 0) {
|
||||||
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM - DELAY_ARM_TO_READER_SIM;
|
uint32_t response_time = reader_eof_time + DELAY_ISO15693_VCD_TO_VICC_SIM - DELAY_ARM_TO_READER_SIM;
|
||||||
|
|
|
@ -342,10 +342,10 @@ void TransmitTo15693Reader(const uint8_t *cmd, size_t len, uint32_t start_time,
|
||||||
for (int i = 7; i >= 0; i--) {
|
for (int i = 7; i >= 0; i--) {
|
||||||
uint8_t cmd_bits = ((cmd[c] >> i) & 0x01) ? 0xff : 0x00;
|
uint8_t cmd_bits = ((cmd[c] >> i) & 0x01) ? 0xff : 0x00;
|
||||||
for (int j = 0; j < (slow?4:1); ) {
|
for (int j = 0; j < (slow?4:1); ) {
|
||||||
bits_to_send = bits_to_shift << (8 - shift_delay) | cmd_bits >> shift_delay;
|
|
||||||
bits_to_shift = cmd_bits;
|
|
||||||
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
|
||||||
|
bits_to_send = bits_to_shift << (8 - shift_delay) | cmd_bits >> shift_delay;
|
||||||
AT91C_BASE_SSC->SSC_THR = bits_to_send;
|
AT91C_BASE_SSC->SSC_THR = bits_to_send;
|
||||||
|
bits_to_shift = cmd_bits;
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
// Delays in SSP_CLK ticks.
|
// Delays in SSP_CLK ticks.
|
||||||
// SSP_CLK runs at 13,56MHz / 32 = 423.75kHz when simulating a tag
|
// SSP_CLK runs at 13,56MHz / 32 = 423.75kHz when simulating a tag
|
||||||
#define DELAY_READER_TO_ARM_SIM 8
|
#define DELAY_READER_TO_ARM_SIM 8
|
||||||
#define DELAY_ARM_TO_READER_SIM 1
|
#define DELAY_ARM_TO_READER_SIM 0
|
||||||
#define DELAY_ISO15693_VCD_TO_VICC_SIM 132 // 132/423.75kHz = 311.5us from end of command EOF to start of tag response
|
#define DELAY_ISO15693_VCD_TO_VICC_SIM 132 // 132/423.75kHz = 311.5us from end of command EOF to start of tag response
|
||||||
//SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when acting as reader
|
//SSP_CLK runs at 13.56MHz / 4 = 3,39MHz when acting as reader
|
||||||
#define DELAY_ISO15693_VCD_TO_VICC_READER 1056 // 1056/3,39MHz = 311.5us from end of command EOF to start of tag response
|
#define DELAY_ISO15693_VCD_TO_VICC_READER 1056 // 1056/3,39MHz = 311.5us from end of command EOF to start of tag response
|
||||||
|
|
BIN
fpga/fpga_hf.bit
BIN
fpga/fpga_hf.bit
Binary file not shown.
|
@ -47,9 +47,9 @@ end
|
||||||
|
|
||||||
// Divide 13.56 MHz to produce various frequencies for SSP_CLK
|
// Divide 13.56 MHz to produce various frequencies for SSP_CLK
|
||||||
// and modulation.
|
// and modulation.
|
||||||
reg [7:0] ssp_clk_divider;
|
reg [8:0] ssp_clk_divider;
|
||||||
|
|
||||||
always @(posedge adc_clk)
|
always @(negedge adc_clk)
|
||||||
ssp_clk_divider <= (ssp_clk_divider + 1);
|
ssp_clk_divider <= (ssp_clk_divider + 1);
|
||||||
|
|
||||||
reg ssp_clk;
|
reg ssp_clk;
|
||||||
|
@ -58,35 +58,37 @@ always @(negedge adc_clk)
|
||||||
begin
|
begin
|
||||||
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT)
|
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_424K_8BIT)
|
||||||
// Get bit every at 53KHz (every 8th carrier bit of 424kHz)
|
// Get bit every at 53KHz (every 8th carrier bit of 424kHz)
|
||||||
ssp_clk <= ssp_clk_divider[7];
|
ssp_clk <= ~ssp_clk_divider[7];
|
||||||
else if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
|
else if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
|
||||||
// Get next bit at 212kHz
|
// Get next bit at 212kHz
|
||||||
ssp_clk <= ssp_clk_divider[5];
|
ssp_clk <= ~ssp_clk_divider[5];
|
||||||
else
|
else
|
||||||
// Get next bit at 424Khz
|
// Get next bit at 424Khz
|
||||||
ssp_clk <= ssp_clk_divider[4];
|
ssp_clk <= ~ssp_clk_divider[4];
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
// Divide SSP_CLK by 8 to produce the byte framing signal; the phase of
|
// Produce the byte framing signal; the phase of this signal
|
||||||
// this is arbitrary, because it's just a bitstream.
|
// is arbitrary, because it's just a bit stream in this module.
|
||||||
// One nasty issue, though: I can't make it work with both rx and tx at
|
|
||||||
// once. The phase wrt ssp_clk must be changed. TODO to find out why
|
|
||||||
// that is and make a better fix.
|
|
||||||
reg [2:0] ssp_frame_divider_to_arm;
|
|
||||||
always @(posedge ssp_clk)
|
|
||||||
ssp_frame_divider_to_arm <= (ssp_frame_divider_to_arm + 1);
|
|
||||||
reg [2:0] ssp_frame_divider_from_arm;
|
|
||||||
always @(negedge ssp_clk)
|
|
||||||
ssp_frame_divider_from_arm <= (ssp_frame_divider_from_arm + 1);
|
|
||||||
|
|
||||||
|
|
||||||
reg ssp_frame;
|
reg ssp_frame;
|
||||||
always @(ssp_frame_divider_to_arm or ssp_frame_divider_from_arm or mod_type)
|
always @(negedge adc_clk)
|
||||||
if(mod_type == `FPGA_HF_SIMULATOR_NO_MODULATION) // not modulating, so listening, to ARM
|
begin
|
||||||
ssp_frame = (ssp_frame_divider_to_arm == 3'b000);
|
if (mod_type == `FPGA_HF_SIMULATOR_MODULATE_212K)
|
||||||
|
begin
|
||||||
|
if (ssp_clk_divider[8:5] == 4'd1)
|
||||||
|
ssp_frame <= 1'b1;
|
||||||
|
if (ssp_clk_divider[8:5] == 4'd5)
|
||||||
|
ssp_frame <= 1'b0;
|
||||||
|
end
|
||||||
else
|
else
|
||||||
ssp_frame = (ssp_frame_divider_from_arm == 3'b000);
|
begin
|
||||||
|
if (ssp_clk_divider[7:4] == 4'd1)
|
||||||
|
ssp_frame <= 1'b1;
|
||||||
|
if (ssp_clk_divider[7:4] == 4'd5)
|
||||||
|
ssp_frame <= 1'b0;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
// Synchronize up the after-hysteresis signal, to produce DIN.
|
// Synchronize up the after-hysteresis signal, to produce DIN.
|
||||||
reg ssp_din;
|
reg ssp_din;
|
||||||
|
@ -120,6 +122,6 @@ assign pwr_lo = 1'b0;
|
||||||
assign pwr_oe2 = 1'b0;
|
assign pwr_oe2 = 1'b0;
|
||||||
|
|
||||||
|
|
||||||
assign dbg = ssp_din;
|
assign dbg = ssp_frame;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue