This commit is contained in:
tharexde 2021-01-17 00:27:08 +01:00
commit 03d56596cb

View file

@ -40,7 +40,8 @@
#define EM4X50_T_TAG_WAITING_FOR_SIGNAL 75 #define EM4X50_T_TAG_WAITING_FOR_SIGNAL 75
#define EM4X50_T_WAITING_FOR_DBLLIW 1550 #define EM4X50_T_WAITING_FOR_DBLLIW 1550
#define EM4X50_T_WAITING_FOR_ACK 4 #define EM4X50_T_WAITING_FOR_ACK 4
//#define EM4X50_T_SIMULATION_TIMEOUT 100 #define EM4X50_T_SIMULATION_TIMEOUT_READ 400
#define EM4X50_T_SIMULATION_TIMEOUT_WAIT 50
// the following value seems to be critical; if it's too low (e.g. < 120) // the following value seems to be critical; if it's too low (e.g. < 120)
// some cards are no longer readable although they're ok // some cards are no longer readable although they're ok
@ -221,6 +222,8 @@ static void em4x50_setup_sim(void) {
// Watchdog hit // Watchdog hit
WDT_HIT(); WDT_HIT();
LEDsoff();
} }
// calculate signal properties (mean amplitudes) from measured data: // calculate signal properties (mean amplitudes) from measured data:
@ -670,7 +673,7 @@ static int get_word_from_bitstream(uint32_t *data) {
return PM3_EOPABORTED; return PM3_EOPABORTED;
} }
static int em4x50_sim_send_bit(uint8_t bit) { static void em4x50_sim_send_bit(uint8_t bit) {
uint16_t timeout = EM4X50_T_TAG_FULL_PERIOD; uint16_t timeout = EM4X50_T_TAG_FULL_PERIOD;
@ -681,7 +684,7 @@ static int em4x50_sim_send_bit(uint8_t bit) {
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) && (timeout--)); while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) && (timeout--));
if (timeout == 0) { if (timeout == 0) {
return PM3_ETIMEOUT; return;
} }
timeout = EM4X50_T_TAG_FULL_PERIOD; timeout = EM4X50_T_TAG_FULL_PERIOD;
@ -693,7 +696,7 @@ static int em4x50_sim_send_bit(uint8_t bit) {
//wait until SSC_CLK goes LOW //wait until SSC_CLK goes LOW
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK && (timeout--)); while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK && (timeout--));
if (timeout == 0) { if (timeout == 0) {
return PM3_ETIMEOUT; return;
} }
timeout = EM4X50_T_TAG_FULL_PERIOD; timeout = EM4X50_T_TAG_FULL_PERIOD;
@ -701,36 +704,28 @@ static int em4x50_sim_send_bit(uint8_t bit) {
bit ^= 1; bit ^= 1;
} }
return PM3_SUCCESS;
} }
static int em4x50_sim_send_byte(uint8_t byte) { static void em4x50_sim_send_byte(uint8_t byte, bool paritycheck) {
// send byte // send byte
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
em4x50_sim_send_bit((byte >> (7 - i)) & 1); em4x50_sim_send_bit((byte >> (7 - i)) & 1);
} }
return PM3_SUCCESS; if (paritycheck) {
uint8_t parity = 0x0;
for (int i = 0; i < 8; i++) {
parity ^= (byte >> i) & 1;
}
em4x50_sim_send_bit(parity);
}
} }
static int em4x50_sim_send_byte_with_parity(uint8_t byte) { static void em4x50_sim_send_word(uint32_t word) {
uint8_t parity = 0x0;
// send byte with parity (even)
for (int i = 0; i < 8; i++)
parity ^= (byte >> i) & 1;
em4x50_sim_send_byte(byte);
em4x50_sim_send_bit(parity);
return PM3_SUCCESS;
}
static int em4x50_sim_send_word(uint32_t word) {
uint8_t cparity = 0x00; uint8_t cparity = 0x00;
@ -739,7 +734,7 @@ static int em4x50_sim_send_word(uint32_t word) {
// 4 bytes each with even row parity bit // 4 bytes each with even row parity bit
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
em4x50_sim_send_byte_with_parity((word >> ((3 - i) * 8)) & 0xFF); em4x50_sim_send_byte((word >> ((3 - i) * 8)) & 0xFF, true);
} }
// column parity // column parity
@ -749,56 +744,44 @@ static int em4x50_sim_send_word(uint32_t word) {
cparity ^= (((word >> ((3 - j) * 8)) & 0xFF) >> (7 - i)) & 1; cparity ^= (((word >> ((3 - j) * 8)) & 0xFF) >> (7 - i)) & 1;
} }
} }
em4x50_sim_send_byte(cparity); em4x50_sim_send_byte(cparity, false);
// stop bit // stop bit
em4x50_sim_send_bit(0); em4x50_sim_send_bit(0);
return PM3_SUCCESS;
} }
static int wait_cycles(int maxperiods) { static void wait_cycles(int maxperiods) {
int EM4X50_T_SIMULATION_TIMEOUT = 500; int period = 0, timeout = EM4X50_T_SIMULATION_TIMEOUT_WAIT;
int period = 0, timeout = EM4X50_T_SIMULATION_TIMEOUT;
while (period < maxperiods) { while (period < maxperiods) {
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) && (timeout--)); while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) && (timeout--));
if (timeout <= 0) { if (timeout <= 0) {
return PM3_ETIMEOUT; return;
} }
timeout = EM4X50_T_SIMULATION_TIMEOUT; timeout = EM4X50_T_SIMULATION_TIMEOUT_WAIT;
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK && (timeout--)); while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK && (timeout--));
if (timeout <= 0) { if (timeout <= 0) {
return PM3_ETIMEOUT; return;
} }
timeout = EM4X50_T_SIMULATION_TIMEOUT; timeout = EM4X50_T_SIMULATION_TIMEOUT_WAIT;
period++; period++;
} }
return PM3_SUCCESS;
} }
static int em4x50_sim_read_bit(void) { static int em4x50_sim_read_bit(void) {
int EM4X50_T_SIMULATION_TIMEOUT = 500;
int cycles = 0; int cycles = 0;
int timeout1 = EM4X50_T_SIMULATION_TIMEOUT; int timeout = EM4X50_T_SIMULATION_TIMEOUT_READ;
int timeout2 = EM4X50_T_SIMULATION_TIMEOUT;
while (cycles < EM4X50_T_TAG_FULL_PERIOD) { while (cycles < EM4X50_T_TAG_FULL_PERIOD) {
// wait until reader field disappears // wait until reader field disappears
while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) && (timeout1--)); while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK));
if (timeout1 <= 0) {
return PM3_ETIMEOUT;
}
timeout1 = EM4X50_T_SIMULATION_TIMEOUT;
// reader field is off, reset timer TC0
AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG;
// now check until reader switches on carrier field // now check until reader switches on carrier field
@ -808,15 +791,15 @@ static int em4x50_sim_read_bit(void) {
if (AT91C_BASE_TC0->TC_CV > T0 * EM4X50_ZERO_DETECTION) { if (AT91C_BASE_TC0->TC_CV > T0 * EM4X50_ZERO_DETECTION) {
// gap detected; wait until reader field is switched on again // gap detected; wait until reader field is switched on again
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK && (timeout2--)); while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK && (timeout--));
if (timeout2 <= 0) { if (timeout <= 0) {
return PM3_ETIMEOUT; return PM3_ETIMEOUT;
} }
timeout2 = EM4X50_T_SIMULATION_TIMEOUT; timeout = EM4X50_T_SIMULATION_TIMEOUT_READ;
// now we have a reference "position", from here it will take // now we have a reference "position", from here it will take
// slightly less 32 cycles until the end of the bit period // slightly less than 32 cycles until the end of the bit period
wait_cycles(28); wait_cycles(28);
// end of bit period is reached; return with bit value "0" // end of bit period is reached; return with bit value "0"
@ -835,47 +818,44 @@ static int em4x50_sim_read_bit(void) {
return 1; return 1;
} }
static int em4x50_sim_read_byte(void) { static bool em4x50_sim_read_byte(uint8_t *byte, bool paritycheck) {
int byte = 0;
for (int i = 0; i < 8; i++) {
byte <<= 1;
byte |= em4x50_sim_read_bit();
}
return byte;
}
static int em4x50_sim_read_byte_with_parity_check(uint8_t *byte) {
int pval = 0;
uint8_t parity = 0;
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
*byte <<= 1; *byte <<= 1;
*byte |= em4x50_sim_read_bit(); *byte |= em4x50_sim_read_bit();
parity ^= ((*byte) & 1);
} }
pval = em4x50_sim_read_bit(); if (paritycheck) {
int pval = em4x50_sim_read_bit();
uint8_t parity = 0;
for (int i = 0; i < 8; i++) {
parity ^= ((*byte) >> i) & 1;
}
if (parity != pval) {
return false;
}
}
return true;
return (parity == pval) ? PM3_SUCCESS : PM3_EFAILED;
} }
static int em4x50_sim_read_word(uint32_t *word) { static bool em4x50_sim_read_word(uint32_t *word) {
int stop_bit = 0; uint8_t stop_bit = 0;
int parities = 0, parities_calculated = 0; uint8_t parities = 0, parities_calculated = 0;
uint8_t bytes[4] = {0}; uint8_t bytes[4] = {0};
// read plain data // read plain data
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
em4x50_sim_read_byte_with_parity_check(&bytes[i]); em4x50_sim_read_byte(&bytes[i], true);
} }
// read column parities and stop bit // read column parities and stop bit
parities = em4x50_sim_read_byte(); em4x50_sim_read_byte(&parities, false);
stop_bit = em4x50_sim_read_bit(); stop_bit = em4x50_sim_read_bit();
// calculate column parities from data // calculate column parities from data
@ -890,10 +870,10 @@ static int em4x50_sim_read_word(uint32_t *word) {
// check parities // check parities
if ((parities == parities_calculated) && (stop_bit == 0)) { if ((parities == parities_calculated) && (stop_bit == 0)) {
return PM3_SUCCESS; return true;
} }
return PM3_EFAILED; return false;
} }
static void em4x50_sim_send_ack(void) { static void em4x50_sim_send_ack(void) {
@ -949,9 +929,11 @@ static int em4x50_sim_handle_login_command(uint32_t *tag) {
// read password // read password
uint32_t password = 0; uint32_t password = 0;
int pwd = em4x50_sim_read_word(&password); bool pwd = em4x50_sim_read_word(&password);
// signal that reader sent the password
LED_D_ON();
em4x50_sim_read_word(&password);
//wait_cycles(15); //wait_cycles(15);
// processing pause time (corresponds to a "1" bit) // processing pause time (corresponds to a "1" bit)
@ -960,12 +942,14 @@ static int em4x50_sim_handle_login_command(uint32_t *tag) {
// empirically determined delay (to be examined seperately) // empirically determined delay (to be examined seperately)
wait_cycles(1); wait_cycles(1);
if ((pwd == PM3_SUCCESS) && (password == reflect32(tag[EM4X50_DEVICE_PASSWORD]))) { if (pwd && (password == reflect32(tag[EM4X50_DEVICE_PASSWORD]))) {
em4x50_sim_send_ack(); em4x50_sim_send_ack();
gLogin = true; gLogin = true;
LED_A_ON();
} else { } else {
em4x50_sim_send_nak(); em4x50_sim_send_nak();
gLogin = false; gLogin = false;
LED_A_OFF();
} }
// continue with standard read mode // continue with standard read mode
return EM4X50_COMMAND_STANDARD_READ; return EM4X50_COMMAND_STANDARD_READ;
@ -991,15 +975,15 @@ static int em4x50_sim_handle_write_command(uint32_t *tag) {
// read address // read address
uint8_t address = 0; uint8_t address = 0;
int addr = em4x50_sim_read_byte_with_parity_check(&address); bool addr = em4x50_sim_read_byte(&address, true);
// read data // read data
uint32_t data = 0; uint32_t data = 0;
int word = em4x50_sim_read_word(&data); bool word = em4x50_sim_read_word(&data);
// write access time // write access time
wait_cycles(EM4X50_T_TAG_TWA); wait_cycles(EM4X50_T_TAG_TWA);
if ((addr != PM3_SUCCESS) || (word != PM3_SUCCESS)) { if ((addr == false) || (word == false)) {
em4x50_sim_send_nak(); em4x50_sim_send_nak();
return EM4X50_COMMAND_STANDARD_READ; return EM4X50_COMMAND_STANDARD_READ;
} }
@ -1051,8 +1035,13 @@ static int em4x50_sim_handle_write_command(uint32_t *tag) {
default: default:
if ((address >= fwwp) && (address <= lwwp) && (gLogin == false)) { if ((address >= fwwp) && (address <= lwwp) && (gLogin == false)) {
em4x50_sim_send_nak(); if (gLogin) {
return EM4X50_COMMAND_STANDARD_READ; tag[address] = reflect32(data);
em4x50_sim_send_ack();
} else {
em4x50_sim_send_nak();
return EM4X50_COMMAND_STANDARD_READ;
}
} else { } else {
tag[address] = reflect32(data); tag[address] = reflect32(data);
em4x50_sim_send_ack(); em4x50_sim_send_ack();
@ -1090,7 +1079,7 @@ static int em4x50_sim_handle_write_command(uint32_t *tag) {
static int em4x50_sim_handle_writepwd_command(uint32_t *tag) { static int em4x50_sim_handle_writepwd_command(uint32_t *tag) {
int pwd = 0; bool pwd = false;
if (gWritePasswordProcess == false) { if (gWritePasswordProcess == false) {
@ -1105,7 +1094,7 @@ static int em4x50_sim_handle_writepwd_command(uint32_t *tag) {
// processing pause time (corresponds to a "1" bit) // processing pause time (corresponds to a "1" bit)
em4x50_sim_send_bit(1); em4x50_sim_send_bit(1);
if ((pwd == PM3_SUCCESS) && (act_password == reflect32(tag[EM4X50_DEVICE_PASSWORD]))) { if (pwd && (act_password == reflect32(tag[EM4X50_DEVICE_PASSWORD]))) {
em4x50_sim_send_ack(); em4x50_sim_send_ack();
gLogin = true; gLogin = true;
} else { } else {
@ -1130,7 +1119,7 @@ static int em4x50_sim_handle_writepwd_command(uint32_t *tag) {
// write access time // write access time
wait_cycles(EM4X50_T_TAG_TWA); wait_cycles(EM4X50_T_TAG_TWA);
if (pwd == PM3_SUCCESS) { if (pwd) {
em4x50_sim_send_ack(); em4x50_sim_send_ack();
tag[EM4X50_DEVICE_PASSWORD] = reflect32(new_password); tag[EM4X50_DEVICE_PASSWORD] = reflect32(new_password);
} else { } else {
@ -1163,13 +1152,13 @@ static int em4x50_sim_handle_selective_read_command(uint32_t *tag) {
// read password // read password
uint32_t address = 0; uint32_t address = 0;
int addr = em4x50_sim_read_word(&address); bool addr = em4x50_sim_read_word(&address);
//wait_cycles(15); //wait_cycles(15);
// processing pause time (corresponds to a "1" bit) // processing pause time (corresponds to a "1" bit)
em4x50_sim_send_bit(1); em4x50_sim_send_bit(1);
if (addr == PM3_SUCCESS) { if (addr) {
em4x50_sim_send_ack(); em4x50_sim_send_ack();
} else { } else {
em4x50_sim_send_nak(); em4x50_sim_send_nak();
@ -1244,7 +1233,7 @@ static int em4x50_sim_handle_standard_read_command(uint32_t *tag) {
return command; return command;
} }
if ((i >= fwrp) && (i <= lwrp)) { if ((gLogin == false) && (i >= fwrp) && (i <= lwrp)) {
em4x50_sim_send_word(0x00); em4x50_sim_send_word(0x00);
} else { } else {
em4x50_sim_send_word(reflect32(tag[i])); em4x50_sim_send_word(reflect32(tag[i]));
@ -1273,7 +1262,7 @@ static int check_rm_request(uint32_t *tag) {
} else { } else {
// read mode request detected, get command from reader // read mode request detected, get command from reader
uint8_t command = 0; uint8_t command = 0;
em4x50_sim_read_byte_with_parity_check(&command); em4x50_sim_read_byte(&command, true);
return command; return command;
} }
} }
@ -1773,6 +1762,10 @@ void em4x50_writepwd(em4x50_data_t *etd) {
} }
// simulate uploaded data in emulator memory // simulate uploaded data in emulator memory
// LED A -> operations that require authentication are possible
// LED B -> standard read mode is active
// LED C -> command has been transmitted by reader
// LED D -> password has been caught from reader
void em4x50_sim(uint32_t *password) { void em4x50_sim(uint32_t *password) {
int command = PM3_ENODATA; int command = PM3_ENODATA;
@ -1803,26 +1796,38 @@ void em4x50_sim(uint32_t *password) {
switch (command) { switch (command) {
case EM4X50_COMMAND_LOGIN: case EM4X50_COMMAND_LOGIN:
LED_B_OFF();
LED_C_OFF();
command = em4x50_sim_handle_login_command(tag); command = em4x50_sim_handle_login_command(tag);
break; break;
case EM4X50_COMMAND_RESET: case EM4X50_COMMAND_RESET:
LED_B_OFF();
LED_C_OFF();
command = em4x50_sim_handle_reset_command(tag); command = em4x50_sim_handle_reset_command(tag);
break; break;
case EM4X50_COMMAND_WRITE: case EM4X50_COMMAND_WRITE:
LED_B_OFF();
LED_C_OFF();
command = em4x50_sim_handle_write_command(tag); command = em4x50_sim_handle_write_command(tag);
break; break;
case EM4X50_COMMAND_WRITE_PASSWORD: case EM4X50_COMMAND_WRITE_PASSWORD:
LED_B_OFF();
LED_C_OFF();
command = em4x50_sim_handle_writepwd_command(tag); command = em4x50_sim_handle_writepwd_command(tag);
break; break;
case EM4X50_COMMAND_SELECTIVE_READ: case EM4X50_COMMAND_SELECTIVE_READ:
LED_B_OFF();
LED_C_ON();
command = em4x50_sim_handle_selective_read_command(tag); command = em4x50_sim_handle_selective_read_command(tag);
break; break;
case EM4X50_COMMAND_STANDARD_READ: case EM4X50_COMMAND_STANDARD_READ:
LED_B_ON();
LED_C_OFF();
command = em4x50_sim_handle_standard_read_command(tag); command = em4x50_sim_handle_standard_read_command(tag);
break; break;
} }
@ -1832,7 +1837,7 @@ void em4x50_sim(uint32_t *password) {
break; break;
} }
// if timeout (e.g. no reader field) go on with standard read mode // if timeout (e.g. no reader field) continue with standard read mode
if (command == PM3_ETIMEOUT) { if (command == PM3_ETIMEOUT) {
command = EM4X50_COMMAND_STANDARD_READ; command = EM4X50_COMMAND_STANDARD_READ;
} }