From 560be3005301b94e5918d7766ea7a6c2a283335b Mon Sep 17 00:00:00 2001 From: tharexde Date: Tue, 5 Jan 2021 01:12:21 +0100 Subject: [PATCH] next version of half duplex simulation --- armsrc/em4x50.c | 212 ++++++++++++++++++------------------------------ 1 file changed, 78 insertions(+), 134 deletions(-) diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index 6c6091a8b..e0b93ce0f 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -57,12 +57,17 @@ int gHigh = 190; int gLow = 60; + +// a global parameter is needed to indicate whether a previous login was +// successful, so operations that require authentication may be performed +bool gLogin = 0; + int gcount = 0; int gcycles = 0; int rm = 0; -static bool em4x50_sim_send_listen_window(void); -static void em4x50_sim_handle_command(uint8_t command); +static bool em4x50_sim_send_listen_window(uint32_t *tag); +static void em4x50_sim_handle_command(uint8_t command, uint32_t *tag); void catch_samples(void); @@ -170,22 +175,19 @@ static void em4x50_setup_read(void) { // Enable Peripheral Clock for // TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0);// | (1 << AT91C_ID_TC1); 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; - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers // Enable and reset counters 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 TC1 returned to zero @@ -289,13 +291,11 @@ static bool invalid_bit(void) { // get sample at 3/4 of bit period wait_timer(T0 * EM4X50_T_TAG_THREE_QUARTER_PERIOD); - //wait_timer(T0 * EM4X50_T_TAG_HALF_PERIOD); uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // wait until end of bit period wait_timer(T0 * EM4X50_T_TAG_QUARTER_PERIOD); - //wait_timer(T0 * EM4X50_T_TAG_HALF_PERIOD); // bit in "undefined" state? if (sample <= gHigh && sample >= gLow) @@ -522,18 +522,14 @@ static int request_receive_mode(void) { // If is true then within the single listen window right after the // ack signal a RM request has to be sent. static bool check_ack(bool bliw) { - int cnt_pulses = 0; - - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - //while (cnt_pulses < EM4X50_T_WAITING_FOR_ACK) { - while (AT91C_BASE_TC0->TC_CV < T0 * 4 * EM4X50_T_TAG_FULL_PERIOD) { - + int count_cycles = 0; + while (count_cycles < EM4X50_T_WAITING_FOR_ACK) { if (BUTTON_PRESS()) return false; if (check_pulse_length(get_pulse_length(), 2 * EM4X50_T_TAG_FULL_PERIOD)) { - catch_samples(); + //catch_samples(); // The received signal is either ACK or NAK. @@ -570,7 +566,7 @@ static bool check_ack(bool bliw) { break; } } - cnt_pulses++; + count_cycles++; } return false; @@ -919,6 +915,8 @@ static void em4x50_sim_send_nak(void) { SHORT_COIL(); wait_cycles(EM4X50_T_TAG_HALF_PERIOD); + + OPEN_COIL(); } /* @@ -969,68 +967,57 @@ static bool em4x50_sim_send_listen_window(void) { } */ -static void em4x50_sim_handle_login_command(void) { +static void em4x50_sim_handle_login_command(uint32_t *tag) { - //uint8_t *em4x50_mem = BigBuf_get_EM_addr(); uint32_t password = 0; - //uint32_t tag[EM4X50_NO_WORDS] = {0x0}; // read password password = em4x50_sim_read_word(); - //for (int i = 0; i < EM4X50_NO_WORDS; i++) - // tag[i] = reflect32(bytes_to_num(em4x50_mem + (i * 4), 4)); - // processing pause time (corresponds to a "1" bit) em4x50_sim_send_bit(1); - em4x50_sim_send_ack(); - - /* + // empirically determined delay (to be examined seperately) + wait_cycles(1); + if (password == tag[0]) { em4x50_sim_send_ack(); + gLogin = true; } else { - em4x50_sim_send_ack(); + em4x50_sim_send_nak(); + gLogin = false; } - */ // continue with standard read mode - em4x50_sim_handle_command(0); - Dbprintf("password = %08x", password); - BigBuf_free(); + em4x50_sim_handle_command(0, tag); } -static void em4x50_sim_handle_reset_command(void) { +static void em4x50_sim_handle_reset_command(uint32_t *tag) { // processing pause time (corresponds to a "1" bit) em4x50_sim_send_bit(1); // send ACK em4x50_sim_send_ack(); + gLogin = false; // wait for tinit - wait_timer(T0 * EM4X50_T_TAG_TINIT); - + wait_cycles(EM4X50_T_TAG_TINIT); + // continue with standard read mode - em4x50_sim_handle_command(0); + em4x50_sim_handle_command(0, tag); } -static void em4x50_sim_handle_write_command(void) { +static void em4x50_sim_handle_write_command(uint32_t *tag) { - uint8_t *em4x50_mem = BigBuf_get_EM_addr(); uint8_t address = 0; uint32_t data = 0; - uint32_t tag[EM4X50_NO_WORDS] = {0x0}; // read address address = em4x50_sim_read_byte_with_parity_check(); // read data data = em4x50_sim_read_word(); - for (int i = 0; i < EM4X50_NO_WORDS; i++) { - tag[i] = reflect32(bytes_to_num(em4x50_mem + (i * 4), 4)); - } - // extract necessary control data bool raw = (tag[EM4X50_CONTROL] >> CONFIG_BLOCK) & READ_AFTER_WRITE; // extract protection data @@ -1041,7 +1028,7 @@ static void em4x50_sim_handle_write_command(void) { tag[address] = data; // write access time - wait_timer(T0 * EM4X50_T_TAG_TWA); + wait_cycles(EM4X50_T_TAG_TWA); if ((address >= fwrp) && (address <= lwrp)) { em4x50_sim_send_nak(); @@ -1055,28 +1042,24 @@ static void em4x50_sim_handle_write_command(void) { } // EEPROM write time - //wait_timer(T0 * EM4X50_T_TAG_TWEE); + wait_cycles(EM4X50_T_TAG_TWEE); em4x50_sim_send_ack(); // if "read after write" (raw) bit is set, repeat written data once if (raw) { - em4x50_sim_send_listen_window(); - em4x50_sim_send_listen_window(); + em4x50_sim_send_listen_window(tag); + em4x50_sim_send_listen_window(tag); em4x50_sim_send_word(tag[address]); } - BigBuf_free(); - // continue with standard read mode - em4x50_sim_handle_command(0); + em4x50_sim_handle_command(0, tag); } -static void em4x50_sim_handle_selective_read_command(void) { +static void em4x50_sim_handle_selective_read_command(uint32_t *tag) { - uint8_t *em4x50_mem = BigBuf_get_EM_addr(); uint32_t address = 0; - uint32_t tag[EM4X50_NO_WORDS] = {0x0}; // read password address = em4x50_sim_read_word(); @@ -1085,10 +1068,6 @@ static void em4x50_sim_handle_selective_read_command(void) { int fwr = address & 0xFF; // first word read int lwr = (address >> 8) & 0xFF; // last word read - for (int i = 0; i < EM4X50_NO_WORDS; i++) { - tag[i] = reflect32(bytes_to_num(em4x50_mem + (i * 4), 4)); - } - // extract protection data int fwrp = tag[EM4X50_PROTECTION] & 0xFF; // first word read protected int lwrp = (tag[EM4X50_PROTECTION] >> 8) & 0xFF; // last word read protected @@ -1098,34 +1077,27 @@ static void em4x50_sim_handle_selective_read_command(void) { em4x50_sim_send_ack(); + // iceman, will need a usb cmd check to break as well while (BUTTON_PRESS() == false) { WDT_HIT(); - em4x50_sim_send_listen_window(); + em4x50_sim_send_listen_window(tag); for (int i = fwr; i <= lwr; i++) { - em4x50_sim_send_listen_window(); + em4x50_sim_send_listen_window(tag); - if ((i >= fwrp) && (i <= lwrp)) { + // if not authenticated do not send read protected words + if ((gLogin == false) && (i >= fwrp) && (i <= lwrp)) { em4x50_sim_send_word(0x00); } else { em4x50_sim_send_word(tag[i]); } } } - - BigBuf_free(); } -static void em4x50_sim_handle_standard_read_command(void) { +static void em4x50_sim_handle_standard_read_command(uint32_t *tag) { - uint8_t *em4x50_mem = BigBuf_get_EM_addr(); - uint32_t tag[EM4X50_NO_WORDS] = {0x0}; - - for (int i = 0; i < EM4X50_NO_WORDS; i++) { - tag[i] = reflect32(bytes_to_num(em4x50_mem + (i * 4), 4)); - } - // extract control data int fwr = tag[CONFIG_BLOCK] & 0xFF; // first word read int lwr = (tag[CONFIG_BLOCK] >> 8) & 0xFF; // last word read @@ -1133,13 +1105,14 @@ static void em4x50_sim_handle_standard_read_command(void) { int fwrp = tag[EM4X50_PROTECTION] & 0xFF; // first word read protected int lwrp = (tag[EM4X50_PROTECTION] >> 8) & 0xFF; // last word read protected + // iceman, will need a usb cmd check to break as well while (BUTTON_PRESS() == false) { WDT_HIT(); - em4x50_sim_send_listen_window(); + em4x50_sim_send_listen_window(tag); for (int i = fwr; i <= lwr; i++) { - em4x50_sim_send_listen_window(); + em4x50_sim_send_listen_window(tag); if ((i >= fwrp) && (i <= lwrp)) { em4x50_sim_send_word(0x00); @@ -1148,23 +1121,22 @@ static void em4x50_sim_handle_standard_read_command(void) { } } } - BigBuf_free(); } -static void em4x50_sim_handle_command(uint8_t command) { +static void em4x50_sim_handle_command(uint8_t command, uint32_t *tag) { switch (command) { case EM4X50_COMMAND_LOGIN: - em4x50_sim_handle_login_command(); + em4x50_sim_handle_login_command(tag); break; case EM4X50_COMMAND_RESET: - em4x50_sim_handle_reset_command(); + em4x50_sim_handle_reset_command(tag); break; case EM4X50_COMMAND_WRITE: - em4x50_sim_handle_write_command(); + em4x50_sim_handle_write_command(tag); break; case EM4X50_COMMAND_WRITE_PASSWORD: @@ -1172,17 +1144,17 @@ static void em4x50_sim_handle_command(uint8_t command) { break; case EM4X50_COMMAND_SELECTIVE_READ: - em4x50_sim_handle_selective_read_command(); + em4x50_sim_handle_selective_read_command(tag); break; default: - em4x50_sim_handle_standard_read_command(); + em4x50_sim_handle_standard_read_command(tag); break; } } // reader requests receive mode (rm) by sending two zeros -static void check_rm_request(void) { +static void check_rm_request(uint32_t *tag) { int cond = EM4X50_T_TAG_FULL_PERIOD - EM4X50_TAG_TOLERANCE; @@ -1194,12 +1166,12 @@ static void check_rm_request(void) { // read mode request detected, get command from reader uint8_t command = em4x50_sim_read_byte_with_parity_check(); - em4x50_sim_handle_command(command); + em4x50_sim_handle_command(command, tag); } } } -static bool em4x50_sim_send_listen_window(void) { +static bool em4x50_sim_send_listen_window(uint32_t *tag) { SHORT_COIL(); wait_cycles(EM4X50_T_TAG_HALF_PERIOD); @@ -1211,7 +1183,7 @@ static bool em4x50_sim_send_listen_window(void) { wait_cycles(2 * EM4X50_T_TAG_FULL_PERIOD); OPEN_COIL(); - check_rm_request(); + check_rm_request(tag); SHORT_COIL(); wait_cycles(EM4X50_T_TAG_FULL_PERIOD); @@ -1230,7 +1202,7 @@ static bool login(uint32_t password) { // send password em4x50_reader_send_word(password); - wait_timer(T0 * EM4X50_T_TAG_TPP); + wait_timer(T0 * (EM4X50_T_TAG_TPP)); // check if ACK is returned if (check_ack(false)) { @@ -1377,7 +1349,7 @@ static int reset(void) { // send reset command em4x50_reader_send_byte_with_parity(EM4X50_COMMAND_RESET); - + if (check_ack(false)) return PM3_SUCCESS; @@ -1674,60 +1646,36 @@ void em4x50_writepwd(em4x50_data_t *etd) { } // simulate uploaded data in emulator memory -// (currently simulation allows only a one-way communication) void em4x50_sim() { int status = PM3_SUCCESS; uint8_t *em4x50_mem = BigBuf_get_EM_addr(); - uint32_t words[EM4X50_NO_WORDS] = {0x0}; + uint32_t tag[EM4X50_NO_WORDS] = {0x0}; for (int i = 0; i < EM4X50_NO_WORDS; i++) - words[i] = reflect32(bytes_to_num(em4x50_mem + (i * 4), 4)); + tag[i] = reflect32(bytes_to_num(em4x50_mem + (i * 4), 4)); // only if valid em4x50 data (e.g. uid == serial) - if (words[EM4X50_DEVICE_SERIAL] != words[EM4X50_DEVICE_ID]) { + if (tag[EM4X50_DEVICE_SERIAL] != tag[EM4X50_DEVICE_ID]) { + // init em4x50_setup_sim(); + gLogin = false; - em4x50_sim_handle_command(0); + // start with inital command = standard read mode (= 0) + em4x50_sim_handle_command(0, tag); - /* - // extract control data - int fwr = words[CONFIG_BLOCK] & 0xFF; // first word read - int lwr = (words[CONFIG_BLOCK] >> 8) & 0xFF; // last word read - // extract protection data - int fwrp = words[EM4X50_PROTECTION] & 0xFF; // first word read protected - int lwrp = (words[EM4X50_PROTECTION] >> 8) & 0xFF; // last word read protected - - // iceman, will need a usb cmd check to break as well - while (BUTTON_PRESS() == false) { - - rm = 0; - WDT_HIT(); - em4x50_sim_send_listen_window(); - for (int i = fwr; i <= lwr; i++) { - - em4x50_sim_send_listen_window(); - - if ((i >= fwrp) && (i <= lwrp)) - em4x50_sim_send_word(0x00); - else - em4x50_sim_send_word(words[i]); - } - } - */ } else { status = PM3_ENODATA; } BigBuf_free(); lf_finalize(); - reply_ng(CMD_LF_EM4X50_SIM, status, NULL, 0); } void em4x50_test(em4x50_test_t *ett) { - int status = PM3_EFAILED; + int status = 0; // set field on or off if (ett->field != -1) { @@ -1791,25 +1739,21 @@ void em4x50_test(em4x50_test_t *ett) { } } - - em4x50_setup_sim(); - for (;;) { - em4x50_sim_send_listen_window(); - em4x50_sim_send_listen_window(); - em4x50_sim_send_bit(0); - em4x50_sim_send_bit(0); - em4x50_sim_send_bit(0); - em4x50_sim_send_ack(); - em4x50_sim_send_ack(); - em4x50_sim_send_bit(0); - em4x50_sim_send_bit(0); - em4x50_sim_send_bit(0); - em4x50_sim_send_nak(); - em4x50_sim_send_nak(); - em4x50_sim_send_bit(0); - em4x50_sim_send_bit(0); - em4x50_sim_send_bit(0); + + // perform reset + if (ett->reset) { + em4x50_setup_read(); + + status = PM3_EFAILED; + if (get_signalproperties() && find_em4x50_tag()) { + + if (reset() == PM3_SUCCESS) { + status = 1; + } + } + + lf_finalize(); } - + reply_ng(CMD_LF_EM4X50_TEST, status, NULL, 0); }