From a04002ab1b40ef6392bd22bdeb3585da4a8df145 Mon Sep 17 00:00:00 2001 From: tharexde Date: Thu, 22 Oct 2020 00:42:18 +0200 Subject: [PATCH] redesign --- armsrc/appmain.c | 4 +- armsrc/em4x50.c | 299 ++++++++++++++------------------------- armsrc/em4x50.h | 4 +- client/src/cmdlfem4x50.c | 243 +++++++++++++++---------------- include/em4x50.h | 12 +- 5 files changed, 228 insertions(+), 334 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index bcf0a656f..9dc2472c8 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1034,7 +1034,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_EM4X50_WIPE: { - em4x50_wipe((em4x50_data_t *)packet->data.asBytes); + em4x50_wipe((uint32_t *)packet->data.asBytes); break; } case CMD_LF_EM4X50_BRUTE: { @@ -1042,7 +1042,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_EM4X50_LOGIN: { - em4x50_login((em4x50_data_t *)packet->data.asBytes); + em4x50_login((uint32_t *)packet->data.asBytes); break; } case CMD_LF_EM4X50_RESET: { diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index 4fe84eb75..17423caef 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -13,7 +13,6 @@ #include "dbprint.h" #include "lfadc.h" #include "commonutil.h" -#include "BigBuf.h" #include "em4x50.h" // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) @@ -47,45 +46,17 @@ #define EM4X50_COMMAND_WRITE_PASSWORD 0x11 #define EM4X50_COMMAND_SELECTIVE_READ 0x0A -#define EM4X50_COMMAND_TIMEOUT 5000 -#define FPGA_TIMER_0 0 - int gHigh = 0; int gLow = 0; // auxiliary functions -static void msb2lsb_word(uint8_t *word) { - - // reorders given according to EM4x50 datasheet (msb -> lsb) - - uint8_t buff[4]; - buff[0] = reflect8(word[3]); - buff[1] = reflect8(word[2]); - buff[2] = reflect8(word[1]); - buff[3] = reflect8(word[0]); - - word[0] = buff[0]; - word[1] = buff[1]; - word[2] = buff[2]; - word[3] = buff[3]; -} - -static void wait_timer(int timer, uint32_t period) { +static void wait_timer0(uint32_t period) { // do nothing for using timer - if (timer == FPGA_TIMER_0) { - - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV < period); - - } else { - - AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; - while (AT91C_BASE_TC1->TC_CV < period); - - } + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + while (AT91C_BASE_TC0->TC_CV < period); } static void em4x50_setup_read(void) { @@ -160,7 +131,7 @@ static bool get_signalproperties(void) { if (BUTTON_PRESS()) return false; // about 2 samples per bit period - wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_HALF_PERIOD); + wait_timer0(T0 * EM4X50_T_TAG_HALF_PERIOD); if (AT91C_BASE_SSC->SSC_RHR > noise) { signal_found = true; @@ -194,31 +165,31 @@ static bool get_signalproperties(void) { // set global envelope variables gHigh = sample_ref + pct * (sample_max_mean - sample_ref) / 100; gLow = sample_ref - pct * (sample_max_mean - sample_ref) / 100; + + Dbprintf("gHigh = %i, gLow = %i", gHigh, gLow); + return true; } -static int get_next_bit(void) { +static bool unvalid_bit(void) { - // returns bit value (or EM4X50_BIT_OTHER -> no bit pattern) by evaluating - // a single sample within a bit period (given there is no LIW, ACK or NAK) - // This function is not used for decoding, it is only used for identifying - // a listen window (return value = EM4X50_BIT_OTHER) in functions + // returns true if bit is undefined by evaluating a single sample within + // a bit period (given there is no LIW, ACK or NAK) + // This function is used for identifying a listen window in functions // "find_double_listen_window" and "check_ack" // get sample at 3/4 of bit period - wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_THREE_QUARTER_PERIOD); + wait_timer0(T0 * EM4X50_T_TAG_THREE_QUARTER_PERIOD); uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; // wait until end of bit period - wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_QUARTER_PERIOD); + wait_timer0(T0 * EM4X50_T_TAG_QUARTER_PERIOD); - // decide wether "0" or "1" - if (sample > gHigh) - return EM4X50_BIT_0; - else if (sample < gLow) - return EM4X50_BIT_1; + // bit in "undefined" state? + if (sample <= gHigh && sample >= gLow) + return true; - return EM4X50_BIT_OTHER; + return false; } static uint32_t get_pulse_length(void) { @@ -229,9 +200,8 @@ static uint32_t get_pulse_length(void) { volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - while (sample > gLow && (timeout--)) { + while (sample > gLow && (timeout--)) sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - } if (timeout == 0) return 0; @@ -239,17 +209,15 @@ static uint32_t get_pulse_length(void) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD); - while (sample < gHigh && (timeout--)) { + while (sample < gHigh && (timeout--)) sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - } if (timeout == 0) return 0; timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD); - while (sample > gLow && (timeout--)) { + while (sample > gLow && (timeout--)) sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - } if (timeout == 0) return 0; @@ -319,13 +287,18 @@ static void em4x50_reader_send_byte_with_parity(uint8_t byte) { em4x50_reader_send_bit(parity); } -static void em4x50_reader_send_word(const uint8_t bytes[4]) { +static void em4x50_reader_send_word(const uint32_t word) { // send 32 bit word with parity bits according to EM4x50 datasheet + // word hast be sent in msb notation - for (int i = 0; i < 4; i++) + uint8_t bytes[4] = {0x0, 0x0, 0x0, 0x0}; + + for (int i = 0; i < 4; i++) { + bytes[i] = (word >> (24 - (8 * i))) & 0xFF; em4x50_reader_send_byte_with_parity(bytes[i]); - + } + // send column parities em4x50_reader_send_byte(bytes[0] ^ bytes[1] ^ bytes[2] ^ bytes[3]); @@ -387,12 +360,12 @@ static int find_double_listen_window(bool bcommand) { // second window follows - sync on this to issue a command // skip the next bit... - wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_FULL_PERIOD); + wait_timer0(T0 * EM4X50_T_TAG_FULL_PERIOD); // ...and check if the following bit does make sense // (if not it is the correct position within the second // listen window) - if (get_next_bit() == EM4X50_BIT_OTHER) { + if (unvalid_bit()) { // send RM for request mode em4x50_reader_send_bit(0); @@ -606,11 +579,11 @@ static bool check_ack(bool bliw) { // wait for 2 bits (remaining "bit" of ACK signal + first // "bit" of listen window) - wait_timer(FPGA_TIMER_0, T0 * 2 * EM4X50_T_TAG_FULL_PERIOD); + wait_timer0(T0 * 2 * EM4X50_T_TAG_FULL_PERIOD); // check for listen window (if first bit cannot be inerpreted // as a valid bit it must belong to a listen window) - if (get_next_bit() == EM4X50_BIT_OTHER) { + if (unvalid_bit()) { // send RM for request mode em4x50_reader_send_bit(0); @@ -776,7 +749,7 @@ static int get_word_from_bitstream(uint32_t *data) { // login function //============================================================================== -static bool login(uint8_t password[4]) { +static bool login(uint32_t password) { // simple login to EM4x50, // used in operations that require authentication @@ -857,15 +830,14 @@ static bool standard_read(int *now, uint32_t *words) { return false; } -static bool selective_read(uint8_t addresses[4], uint32_t *words) { +static bool selective_read(uint32_t addresses, uint32_t *words) { - // reads from "first word read" (fwr = addresses[3]) to "last word read" - // (lwr = addresses[2]) + // reads from "first word read" (fwr) to "last word read" (lwr) // result is verified by "standard read mode" - int fwr = addresses[3]; // first word read - int lwr = addresses[2]; // last word read - int now = fwr; // number of words + uint8_t fwr = addresses & 0xFF; // first word read (first byte) + uint8_t lwr = (addresses >> 8) & 0xFF; // last word read (second byte) + int now = fwr; // number of words if (request_receive_mode()) { @@ -894,12 +866,10 @@ static bool selective_read(uint8_t addresses[4], uint32_t *words) { void em4x50_info(em4x50_data_t *etd) { // collects as much information as possible via selective read mode - // if no password is given -> try with standard password "0x00000000" - // otherwise continue without login bool bsuccess = false, blogin = false; uint8_t status = 0; - uint8_t addresses[] = {0x00, 0x00, 0x21, 0x00}; // fwr = 0, lwr = 33 + uint32_t addresses = 0x00002100; // read from fwr = 0 to lwr = 33 (0x21) uint32_t words[32] = {0x0}; em4x50_setup_read(); @@ -907,12 +877,9 @@ void em4x50_info(em4x50_data_t *etd) { // set gHigh and gLow if (get_signalproperties() && find_em4x50_tag()) { - if (etd->pwd_given) { - - // try to login with given password - blogin = login(etd->password); - - } + // login with given password + if (etd->pwd_given) + blogin = login(etd->password1); bsuccess = selective_read(addresses, words); } @@ -933,7 +900,6 @@ void em4x50_read(em4x50_data_t *etd) { bool bsuccess = false, blogin = false; int now = 0; uint8_t status = 0; - uint8_t addresses[] = {0x00, 0x00, 0x00, 0x00}; uint32_t words[32] = {0x0}; em4x50_setup_read(); @@ -947,11 +913,10 @@ void em4x50_read(em4x50_data_t *etd) { // try to login with given password if (etd->pwd_given) - blogin = login(etd->password); + blogin = login(etd->password1); // only one word has to be read -> first word read = last word read - addresses[2] = addresses[3] = etd->address; - bsuccess = selective_read(addresses, words); + bsuccess = selective_read(etd->addresses, words); } else { @@ -966,14 +931,13 @@ void em4x50_read(em4x50_data_t *etd) { LOW(GPIO_SSC_DOUT); lf_finalize(); reply_ng(CMD_ACK, status, (uint8_t *)words, 136); - //reply_ng(CMD_ACK, status, (uint8_t *)em4x50_tag, 136); } //============================================================================== // write functions //============================================================================== -static bool write(uint8_t word[4], uint8_t address) { +static bool write(uint32_t word, uint32_t addresses) { // writes to specified
@@ -983,13 +947,13 @@ static bool write(uint8_t word[4], uint8_t address) { em4x50_reader_send_byte_with_parity(EM4X50_COMMAND_WRITE); // send address data - em4x50_reader_send_byte_with_parity(address); + em4x50_reader_send_byte_with_parity(addresses & 0xFF); // send data em4x50_reader_send_word(word); // wait for T0 * EM4X50_T_TAG_TWA (write access time) - wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA); + wait_timer0(T0 * EM4X50_T_TAG_TWA); // look for ACK sequence if (check_ack(false)) { @@ -1009,7 +973,7 @@ static bool write(uint8_t word[4], uint8_t address) { return false; } -static bool write_password(uint8_t password[4], uint8_t new_password[4]) { +static bool write_password(uint32_t password, uint32_t new_password) { // changes password from to @@ -1022,7 +986,7 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) { em4x50_reader_send_word(password); // wait for T0 * EM4x50_T_TAG_TPP (processing pause time) - wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TPP); + wait_timer0(T0 * EM4X50_T_TAG_TPP); // look for ACK sequence and send rm request // during following listen window @@ -1032,7 +996,7 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) { em4x50_reader_send_word(new_password); // wait for T0 * EM4X50_T_TAG_TWA (write access time) - wait_timer(FPGA_TIMER_0, T0 * EM4X50_T_TAG_TWA); + wait_timer0(T0 * EM4X50_T_TAG_TWA); if (check_ack(false)) if (check_ack(false)) @@ -1055,7 +1019,6 @@ void em4x50_write(em4x50_data_t *etd) { bool bsuccess = false, blogin = false; uint8_t status = 0; - uint8_t addresses[4] = {0x00, 0x00, 0x00, 0x00}; uint32_t words[34] = {0x0}; em4x50_setup_read(); @@ -1063,37 +1026,25 @@ void em4x50_write(em4x50_data_t *etd) { // set gHigh and gLow if (get_signalproperties() && find_em4x50_tag()) { - // reorder word according to datasheet - msb2lsb_word(etd->word); - // if password is given try to login first if (etd->pwd_given) - blogin = login(etd->password); + blogin = login(etd->password1); // write word to given address - if (write(etd->word, etd->address)) { + if (write(etd->word, etd->addresses)) { // to verify result reset EM4x50 if (reset()) { // if password is given login if (etd->pwd_given) - blogin &= login(etd->password); + blogin &= login(etd->password1); // call a selective read - addresses[2] = addresses[3] = etd->address; - if (selective_read(addresses, words)) { + if (selective_read(etd->addresses, words)) { // compare with given word - uint32_t tmp = 0x0; - tmp = etd->word[0]; - tmp <<= 8; - tmp |= etd->word[1]; - tmp <<= 8; - tmp |= etd->word[2]; - tmp <<= 8; - tmp |= etd->word[3]; - bsuccess = (words[etd->address] == reflect32(tmp)); + bsuccess = (words[etd->addresses & 0xFF] == reflect32(etd->word)); } } } @@ -1110,43 +1061,29 @@ void em4x50_write_password(em4x50_data_t *etd) { // simple change of password bool bsuccess = false; - uint8_t rpwd[4] = {0x0, 0x0, 0x0, 0x0}; - uint8_t rnewpwd[4] = {0x0, 0x0, 0x0, 0x0}; em4x50_setup_read(); // set gHigh and gLow if (get_signalproperties() && find_em4x50_tag()) { - // lsb -> msb - rpwd[0] = reflect8(etd->password[3]); - rpwd[1] = reflect8(etd->password[2]); - rpwd[2] = reflect8(etd->password[1]); - rpwd[3] = reflect8(etd->password[0]); - - rnewpwd[0] = reflect8(etd->new_password[3]); - rnewpwd[1] = reflect8(etd->new_password[2]); - rnewpwd[2] = reflect8(etd->new_password[1]); - rnewpwd[3] = reflect8(etd->new_password[0]); - // login and change password - if (login(rpwd)) { - bsuccess = write_password(rpwd, rnewpwd); - } + if (login(etd->password1)) + bsuccess = write_password(etd->password1, etd->password2); } lf_finalize(); reply_ng(CMD_ACK, bsuccess, 0, 0); } -void em4x50_wipe(em4x50_data_t *etd) { +void em4x50_wipe(uint32_t *password) { // set all data of EM4x50 tag to 0x0 including password bool bsuccess = false; - uint8_t zero[4] = {0, 0, 0, 0}; - uint8_t addresses[4] = {0, 0, EM4X50_NO_WORDS - 3, 1}; + uint32_t addresses = 0x00001E01; // from fwr = 1 to lwr = 31 (0x1E) uint32_t words[34] = {0x0}; + uint32_t zero = 0x0; em4x50_setup_read(); @@ -1154,15 +1091,14 @@ void em4x50_wipe(em4x50_data_t *etd) { if (get_signalproperties() && find_em4x50_tag()) { // login first - if (login(etd->password)) { + if (login(*password)) { // write 0x0 to each address but ignore addresses // 0 -> password, 32 -> serial, 33 -> uid - // writing 34 words takes about 3.6 seconds -> high timeout needed - for (int i = 1; i <= EM4X50_NO_WORDS - 3; i++) + for (int i = 1; i <= 33; i++) write(zero, i); - // to verify result reset EM4x50 + // to verify result -> reset EM4x50 if (reset()) { // login not necessary because protected word has been set to 0 @@ -1172,7 +1108,7 @@ void em4x50_wipe(em4x50_data_t *etd) { // check if everything is zero bsuccess = true; - for (int i = 1; i <= EM4X50_NO_WORDS - 3; i++) + for (int i = 1; i <= 33; i++) bsuccess &= (words[i] == 0); } @@ -1181,8 +1117,8 @@ void em4x50_wipe(em4x50_data_t *etd) { // so far everything is fine // last task: reset password - if (login(etd->password)) - bsuccess = write_password(etd->password, zero); + if (login(*password)) + bsuccess = write_password(*password, zero); // verify by login with new password if (bsuccess) @@ -1205,37 +1141,24 @@ void em4x50_reset(void) { em4x50_setup_read(); // set gHigh and gLow - if (get_signalproperties() && find_em4x50_tag()) { - + if (get_signalproperties() && find_em4x50_tag()) status = reset(); - } lf_finalize(); reply_ng(CMD_ACK, status, 0, 0); } -void em4x50_login(em4x50_data_t *etd) { +void em4x50_login(uint32_t *password) { // login into EM4x50 uint8_t status = false; - uint8_t bytes[4] = {0x0, 0x0, 0x0, 0x0}; - uint32_t rpwd = 0x0; em4x50_setup_read(); // set gHigh and gLow - if (get_signalproperties() && find_em4x50_tag()) { - - // lsb -> msb - rpwd = reflect32(etd->login_password); - - // convert to "old" data format - for (int i = 0; i < 4; i++) - bytes[i] = (rpwd >> ((3 - i) * 8)) & 0xFF; - - status = login(bytes); - } + if (get_signalproperties() && find_em4x50_tag()) + status = login(*password); lf_finalize(); reply_ng(CMD_ACK, status, 0, 0); @@ -1247,18 +1170,10 @@ static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) { bool pwd_found = false; int cnt = 0; - uint32_t rpwd = 0x0; - uint8_t bytes[4] = {0x0, 0x0, 0x0, 0x0}; for (*pwd = start; *pwd <= stop; (*pwd)++) { - // lsb -> msb - rpwd = reflect32(*pwd); - - for (int i = 0; i < 4; i++) - bytes[i] = (rpwd >> ((3 - i) * 8)) & 0xFF; - - if (login(bytes)) { + if (login(*pwd)) { pwd_found = true; break; } @@ -1274,7 +1189,7 @@ static bool brute(uint32_t start, uint32_t stop, uint32_t *pwd) { } // print data - Dbprintf("|%8i | 0x%08x | 0x%08x |", cnt, rpwd, *pwd); + Dbprintf("|%8i | 0x%08x | 0x%08x |", cnt, reflect32(*pwd), *pwd); } if (BUTTON_PRESS()) @@ -1299,44 +1214,12 @@ void em4x50_brute(em4x50_data_t *etd) { em4x50_setup_read(); if (get_signalproperties() && find_em4x50_tag()) - bsuccess = brute(etd->start_password, etd->stop_password, &pwd); + bsuccess = brute(etd->password1, etd->password2, &pwd); lf_finalize(); reply_ng(CMD_ACK, bsuccess, (uint8_t *)(&pwd), 32); } -int em4x50_standalone_brute(uint32_t start, uint32_t stop, uint32_t *pwd) { - - // envoke password search in standalone mode - - int status = false; - - em4x50_setup_read(); - - if (get_signalproperties() && find_em4x50_tag()) - status = brute(start, stop, pwd); - else - status = PM3_ETIMEOUT; - - lf_finalize(); - - return status; -} - -int em4x50_standalone_read(uint32_t *words) { - - int now = 0; - - em4x50_setup_read(); - - if (get_signalproperties() && find_em4x50_tag()) - if (find_double_listen_window(false)) - while (get_word_from_bitstream(&words[now]) == EM4X50_TAG_WORD) - now++; - - return now; -} - void em4x50_watch() { // read continuously and display standard reads of tag @@ -1373,3 +1256,39 @@ void em4x50_watch() { lf_finalize(); reply_ng(CMD_ACK, 1, 0, 0); } + +//============================================================================== +// standalone mode functions +//============================================================================== + +int em4x50_standalone_brute(uint32_t start, uint32_t stop, uint32_t *pwd) { + + // envoke password search in standalone mode + + int status = false; + + em4x50_setup_read(); + + if (get_signalproperties() && find_em4x50_tag()) + status = brute(start, stop, pwd); + else + status = PM3_ETIMEOUT; + + lf_finalize(); + + return status; +} + +int em4x50_standalone_read(uint32_t *words) { + + int now = 0; + + em4x50_setup_read(); + + if (get_signalproperties() && find_em4x50_tag()) + if (find_double_listen_window(false)) + while (get_word_from_bitstream(&words[now]) == EM4X50_TAG_WORD) + now++; + + return now; +} diff --git a/armsrc/em4x50.h b/armsrc/em4x50.h index 9822d604d..c851f04e4 100644 --- a/armsrc/em4x50.h +++ b/armsrc/em4x50.h @@ -23,9 +23,9 @@ void em4x50_info(em4x50_data_t *etd); void em4x50_write(em4x50_data_t *etd); void em4x50_write_password(em4x50_data_t *etd); void em4x50_read(em4x50_data_t *etd); -void em4x50_wipe(em4x50_data_t *etd); +void em4x50_wipe(uint32_t *password); void em4x50_brute(em4x50_data_t *etd); -void em4x50_login(em4x50_data_t *etd); +void em4x50_login(uint32_t *password); void em4x50_reset(void); void em4x50_watch(void); diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 50602e9fb..83027e4be 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -22,7 +22,7 @@ static int usage_lf_em4x50_info(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " v - verbose output"); - PrintAndLogEx(NORMAL, " p - password (hex) (optional)"); + PrintAndLogEx(NORMAL, " p - password (hex, lsb) (optional)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_info")); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_info p fa225de1")); @@ -37,8 +37,8 @@ static int usage_lf_em4x50_write(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " a - memory address to write to (dec)"); - PrintAndLogEx(NORMAL, " w - word to write (hex, lsb notation)"); - PrintAndLogEx(NORMAL, " p - password (hex, lsb notation) (optional)"); + PrintAndLogEx(NORMAL, " w - word to write (hex, lsb)"); + PrintAndLogEx(NORMAL, " p - password (hex, lsb) (optional)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_write a 3 w deadc0de")); PrintAndLogEx(NORMAL, ""); @@ -50,8 +50,8 @@ static int usage_lf_em4x50_write_password(void) { PrintAndLogEx(NORMAL, "Usage: lf em 4x50_write_password [h] [p ] [n ]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " p - password (hex, lsb notation)"); - PrintAndLogEx(NORMAL, " n - new password (hex, lsb notation)"); + PrintAndLogEx(NORMAL, " p - password (hex, lsb)"); + PrintAndLogEx(NORMAL, " n - new password (hex, lsb)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_write_password p 11223344 n 01020304")); PrintAndLogEx(NORMAL, ""); @@ -64,7 +64,7 @@ static int usage_lf_em4x50_read(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " a - memory address to read (dec) (optional)"); - PrintAndLogEx(NORMAL, " p - password (hex) (optional)"); + PrintAndLogEx(NORMAL, " p - password (hex, lsb) (optional)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_read")); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_read a 2 p 00000000")); @@ -78,7 +78,7 @@ static int usage_lf_em4x50_dump(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " f - overide filename prefix (optional). Default is based on UID"); - PrintAndLogEx(NORMAL, " p - password (hex) (optional)"); + PrintAndLogEx(NORMAL, " p - password (hex, lsb) (optional)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_dump")); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_dump p 11223344")); @@ -91,7 +91,7 @@ static int usage_lf_em4x50_wipe(void) { PrintAndLogEx(NORMAL, "Usage: lf em 4x50_wipe [h] [p ]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " p - password (hex)"); + PrintAndLogEx(NORMAL, " p - password (hex, lsb)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_wipe p 11223344")); PrintAndLogEx(NORMAL, ""); @@ -103,8 +103,8 @@ static int usage_lf_em4x50_brute(void) { PrintAndLogEx(NORMAL, "Usage: lf em 4x50_brute [h] f l "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " f - start password (hex, lsb notation)"); - PrintAndLogEx(NORMAL, " l - stop password (hex, lsb notation)"); + PrintAndLogEx(NORMAL, " f - start password (hex, lsb)"); + PrintAndLogEx(NORMAL, " l - stop password (hex, lsb)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_brute f 11200000 l 11300000")); PrintAndLogEx(NORMAL, ""); @@ -116,7 +116,7 @@ static int usage_lf_em4x50_login(void) { PrintAndLogEx(NORMAL, "Usage: lf em 4x50_login [h] p "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " p - password (hex, lsb notation)"); + PrintAndLogEx(NORMAL, " p - password (hex, lsb)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, _YELLOW_(" lf em 4x50_login p 11200000")); PrintAndLogEx(NORMAL, ""); @@ -251,7 +251,7 @@ bool detect_4x50_block(void) { em4x50_data_t etd = { .pwd_given = false, .addr_given = true, - .address = EM4X50_DEVICE_ID, + .addresses = EM4X50_DEVICE_ID, }; em4x50_word_t words[EM4X50_NO_WORDS]; return (em4x50_read(&etd, words, false) == PM3_SUCCESS); @@ -261,7 +261,7 @@ int read_em4x50_uid(void) { em4x50_data_t etd = { .pwd_given = false, .addr_given = true, - .address = EM4X50_DEVICE_SERIAL, + .addresses = EM4X50_DEVICE_SERIAL, }; em4x50_word_t words[EM4X50_NO_WORDS]; int res = em4x50_read(&etd, words, false); @@ -279,7 +279,7 @@ int CmdEM4x50Info(const char *Cmd) { uint8_t cmdp = 0; em4x50_data_t etd; etd.pwd_given = false; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -287,21 +287,13 @@ int CmdEM4x50Info(const char *Cmd) { return usage_lf_em4x50_info(); case 'p': - if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) { - PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n"); - return PM3_EINVARG; - } + etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16); etd.pwd_given = true; cmdp += 2; break; - case 'v': - verbose = true; - cmdp += 1; - break; - default: - PrintAndLogEx(WARNING, " Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; } @@ -337,48 +329,48 @@ int CmdEM4x50Write(const char *Cmd) { em4x50_data_t etd = { .pwd_given = false }; bool errors = false, bword = false, baddr = false; + uint8_t address = 0x0; uint8_t cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': { + + case 'h': return usage_lf_em4x50_write(); - } - case 'p': { - if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) { - PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n"); - return PM3_EINVARG; - } + + case 'p': + etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16); etd.pwd_given = true; cmdp += 2; break; - } - case 'w': { - if (param_gethex(Cmd, cmdp + 1, etd.word, 8)) { - PrintAndLogEx(FAILED, "\n word has to be 8 hex symbols\n"); - return PM3_EINVARG; - } + + case 'w': + etd.word = param_get32ex(Cmd, cmdp + 1, 0, 16); bword = true; cmdp += 2; break; - } - case 'a': { - param_getdec(Cmd, cmdp + 1, &etd.address); + + case 'a': + param_getdec(Cmd, cmdp + 1, &address); // validation - if (etd.address < 1 || etd.address > 31) { - PrintAndLogEx(FAILED, "\n error, address has to be in range [1-31]\n"); + if (address < 1 || address > 31) { + PrintAndLogEx(FAILED, "error, address has to be in range [1-31]\n"); return PM3_EINVARG; } + etd.addresses = address; // lwr + etd.addresses <<= 8; + etd.addresses |= address; // fwr baddr = true; cmdp += 2; break; - } - default: { - PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; break; - } + } } @@ -405,32 +397,20 @@ int CmdEM4x50Write(const char *Cmd) { PrintAndLogEx(FAILED, "login failed"); return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%s"), sprint_hex_inrow(etd.password, 4)); + PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%08x"), etd.password1); } // display result of writing operation in structured format uint8_t *data = resp.data.asBytes; em4x50_word_t words[EM4X50_NO_WORDS]; - prepare_result(data, etd.address, etd.address, words); - print_result(words, etd.address, etd.address); + prepare_result(data, address, address, words); + print_result(words, address, address); PrintAndLogEx(SUCCESS, "Successfully wrote to tag"); - PrintAndLogEx(HINT, "Try `" _YELLOW_("lf em 4x50_read a %u") "` - to read your data", etd.address); + PrintAndLogEx(HINT, "Try `" _YELLOW_("lf em 4x50_read a %u") "` - to read your data", address); return PM3_SUCCESS; } -static void print_write_password_result(PacketResponseNG *resp, const em4x50_data_t *etd) { - - // display result of password changing operation - - char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0}; - - sprintf(pstring, "\n writing new password " _GREEN_("ok")); - strcat(string, pstring); - - PrintAndLogEx(NORMAL, "%s\n", string); -} - int CmdEM4x50WritePassword(const char *Cmd) { // envokes changing the password of EM4x50 tag @@ -442,7 +422,6 @@ int CmdEM4x50WritePassword(const char *Cmd) { // init etd.pwd_given = false; - etd.newpwd_given = false; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { @@ -451,27 +430,20 @@ int CmdEM4x50WritePassword(const char *Cmd) { return usage_lf_em4x50_write_password(); case 'p': - if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) { - PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n"); - return PM3_EINVARG; - } - bpwd = true; + etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16); etd.pwd_given = true; + bpwd = true; cmdp += 2; break; case 'n': - if (param_gethex(Cmd, cmdp + 1, etd.new_password, 8)) { - PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n"); - return PM3_EINVARG; - } + etd.password2 = param_get32ex(Cmd, cmdp + 1, 0, 16); bnpwd = true; - etd.newpwd_given = true; cmdp += 2; break; default: - PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; break; } @@ -489,11 +461,11 @@ int CmdEM4x50WritePassword(const char *Cmd) { } success = (bool)resp.status; - // get, prepare and print response + // print response if (success) - print_write_password_result(&resp, &etd); + PrintAndLogEx(SUCCESS, "\nwriting new password " _GREEN_("ok") "\n"); else - PrintAndLogEx(NORMAL, "\nwriting password " _RED_("failed") "\n"); + PrintAndLogEx(FAILED, "\nwriting password " _RED_("failed") "\n"); return (success) ? PM3_SUCCESS : PM3_ESOFT; } @@ -534,14 +506,14 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) { PrintAndLogEx(FAILED, "login failed"); return PM3_ESOFT; } - PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%s"), sprint_hex_inrow(etd->password, 4)); + PrintAndLogEx(SUCCESS, "login with password " _YELLOW_("%08x"), etd->password1); } uint8_t *data = resp.data.asBytes; em4x50_word_t words[EM4X50_NO_WORDS]; int now = (resp.status & STATUS_NO_WORDS) >> 2; if (edata.addr_given) { - prepare_result(data, etd->address, etd->address, words); + prepare_result(data, etd->addresses & 0xFF, (etd->addresses >> 8) & 0xFF, words); } else { prepare_result(data, 0, now - 1, words); } @@ -551,7 +523,7 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) { } if (edata.addr_given) - print_result(words, etd->address, etd->address); + print_result(words, etd->addresses & 0xFF, (etd->addresses >> 8) & 0xFF); else print_result(words, 0, now - 1); @@ -560,47 +532,48 @@ int em4x50_read(em4x50_data_t *etd, em4x50_word_t *out, bool verbose) { int CmdEM4x50Read(const char *Cmd) { + uint8_t address = 0x0; em4x50_data_t etd; memset(&etd, 0x00, sizeof(em4x50_data_t)); etd.pwd_given = false; etd.addr_given = false; - etd.newpwd_given = false; bool errors = false; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': { + + case 'h': return usage_lf_em4x50_read(); - } + case 'a': { - param_getdec(Cmd, cmdp + 1, &etd.address); + param_getdec(Cmd, cmdp + 1, &address); + // lsb: byte 1 = fwr, byte 2 = lwr, byte 3 = 0x0, byte 4 = 0x0 + etd.addresses = address; // lwr + etd.addresses <<= 8; + etd.addresses |= address; // fwr // validation - if (etd.address <= 0 || etd.address >= EM4X50_NO_WORDS) { - PrintAndLogEx(FAILED, "\n error, address has to be in range [1-33]\n"); + if (address <= 0 || address >= EM4X50_NO_WORDS) { + PrintAndLogEx(FAILED, "error, address has to be in range [1-33]\n"); return PM3_EINVARG; } etd.addr_given = true; cmdp += 2; break; } - case 'p': { - if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) { - PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n"); - return PM3_EINVARG; - } + case 'p': + etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16); etd.pwd_given = true; cmdp += 2; break; - } - default: { - PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; break; - } } } @@ -616,7 +589,6 @@ int CmdEM4x50Dump(const char *Cmd) { em4x50_data_t etd; etd.pwd_given = false; etd.addr_given = false; - etd.newpwd_given = false; char filename[FILE_PATH_SIZE] = {0x00}; char *fptr = filename; @@ -625,24 +597,24 @@ int CmdEM4x50Dump(const char *Cmd) { uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_lf_em4x50_dump(); break; + case 'f': param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); cmdp += 2; break; - case 'p': { - if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) { - PrintAndLogEx(FAILED, "\n password has to be 8 hex symbols\n"); - return PM3_EINVARG; - } + + case 'p': + etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16); etd.pwd_given = true; cmdp += 2; break; - } + default: - PrintAndLogEx(WARNING, " Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; }; @@ -698,38 +670,36 @@ int CmdEM4x50Wipe(const char *Cmd) { // fills EM4x50 tag with zeros including password - bool errors = false, bpwd = false; + bool errors = false, pwd_given = false; uint8_t cmdp = 0; - em4x50_data_t etd; + uint32_t password = 0x0; PacketResponseNG resp; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_lf_em4x50_wipe(); case 'p': - if (param_gethex(Cmd, cmdp + 1, etd.password, 8)) { - PrintAndLogEx(FAILED, "\npassword has to be 8 hex symbols\n"); - return PM3_EINVARG; - } - bpwd = true; + password = param_get32ex(Cmd, cmdp + 1, 0, 16); + pwd_given = true; cmdp += 2; break; default: - PrintAndLogEx(WARNING, "\nUnknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; break; } } - if (errors || !bpwd) + if (errors || !pwd_given) return usage_lf_em4x50_wipe(); clearCommandBuffer(); - SendCommandNG(CMD_LF_EM4X50_WIPE, (uint8_t *)&etd, sizeof(etd)); + SendCommandNG(CMD_LF_EM4X50_WIPE, (uint8_t *)&password, sizeof(password)); WaitForResponse(CMD_ACK, &resp); // print response @@ -756,20 +726,24 @@ int CmdEM4x50Brute(const char *Cmd) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_lf_em4x50_brute(); + case 'f': - etd.start_password = param_get32ex(Cmd, cmdp + 1, 0, 16); + etd.password1 = param_get32ex(Cmd, cmdp + 1, 0, 16); startpwd = true; cmdp += 2; break; + case 'l': - etd.stop_password = param_get32ex(Cmd, cmdp + 1, 0, 16); + etd.password2 = param_get32ex(Cmd, cmdp + 1, 0, 16); stoppwd = true; cmdp += 2; break; + default: - PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; break; } @@ -779,14 +753,14 @@ int CmdEM4x50Brute(const char *Cmd) { return usage_lf_em4x50_brute(); // print some information - no_iter = etd.stop_password - etd.start_password + 1; + no_iter = etd.password2 - etd.password1 + 1; dur_s = no_iter / speed; dur_h = dur_s / 3600; dur_m = (dur_s - dur_h * 3600) / 60; dur_s -= dur_h * 3600 + dur_m * 60; - PrintAndLogEx(NORMAL, "\ntrying %i passwords in range [0x%08x, 0x%08x]", - no_iter, etd.start_password, etd.stop_password); - PrintAndLogEx(NORMAL, "estimated duration: %ih%im%is\n", dur_h, dur_m, dur_s); + PrintAndLogEx(INFO, "trying %i passwords in range [0x%08x, 0x%08x]", + no_iter, etd.password1, etd.password2); + PrintAndLogEx(INFO, "estimated duration: %ih%im%is", dur_h, dur_m, dur_s); // start clearCommandBuffer(); @@ -795,9 +769,9 @@ int CmdEM4x50Brute(const char *Cmd) { // print response if ((bool)resp.status) - PrintAndLogEx(NORMAL, "\npassword " _GREEN_("found") ": 0x%08x\n", resp.data.asDwords[0]); + PrintAndLogEx(SUCCESS, "\npassword " _GREEN_("found") ": 0x%08x\n", resp.data.asDwords[0]); else - PrintAndLogEx(NORMAL, "\npassword: " _RED_("not found") "\n"); + PrintAndLogEx(FAILED, "\npassword: " _RED_("not found") "\n"); return PM3_SUCCESS; } @@ -806,21 +780,24 @@ int CmdEM4x50Login(const char *Cmd) { bool errors = false, pwd_given = false; uint8_t cmdp = 0; - em4x50_data_t etd; + uint32_t password = 0x0; PacketResponseNG resp; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_lf_em4x50_login(); + case 'p': - etd.login_password = param_get32ex(Cmd, cmdp + 1, 0, 16); + password = param_get32ex(Cmd, cmdp + 1, 0, 16); pwd_given = true; cmdp += 2; break; + default: - PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; break; } @@ -831,14 +808,14 @@ int CmdEM4x50Login(const char *Cmd) { // start clearCommandBuffer(); - SendCommandNG(CMD_LF_EM4X50_LOGIN, (uint8_t *)&etd, sizeof(etd)); + SendCommandNG(CMD_LF_EM4X50_LOGIN, (uint8_t *)&password, sizeof(password)); WaitForResponse(CMD_ACK, &resp); // print response if ((bool)resp.status) - PrintAndLogEx(NORMAL, "\nlogin " _GREEN_("ok") "\n"); + PrintAndLogEx(SUCCESS, "\nlogin " _GREEN_("ok") "\n"); else - PrintAndLogEx(NORMAL, "\nlogin " _RED_("failed") "\n"); + PrintAndLogEx(FAILED, "\nlogin " _RED_("failed") "\n"); return PM3_SUCCESS; } @@ -852,10 +829,12 @@ int CmdEM4x50Reset(const char *Cmd) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_lf_em4x50_reset(); + default: - PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; break; } @@ -871,9 +850,9 @@ int CmdEM4x50Reset(const char *Cmd) { // print response if ((bool)resp.status) - PrintAndLogEx(NORMAL, "\nreset " _GREEN_("ok") "\n"); + PrintAndLogEx(SUCCESS, "\nreset " _GREEN_("ok") "\n"); else - PrintAndLogEx(NORMAL, "\nreset " _RED_("failed") "\n"); + PrintAndLogEx(FAILED, "\nreset " _RED_("failed") "\n"); return PM3_SUCCESS; } @@ -893,7 +872,7 @@ int CmdEM4x50Watch(const char *Cmd) { return usage_lf_em4x50_watch(); default: - PrintAndLogEx(WARNING, " Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; } diff --git a/include/em4x50.h b/include/em4x50.h index ae6a53177..2bb490203 100644 --- a/include/em4x50.h +++ b/include/em4x50.h @@ -43,14 +43,10 @@ typedef struct { bool addr_given; bool pwd_given; - bool newpwd_given; - uint8_t password[4]; - uint8_t new_password[4]; - uint8_t address; - uint8_t word[4]; - uint32_t start_password; - uint32_t stop_password; - uint32_t login_password; + uint32_t password1; + uint32_t password2; + uint32_t word; + uint32_t addresses; } em4x50_data_t; typedef struct {