From 9ce9a8280383af01f7ee36cd8d458e0e9047ddad Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:31:39 +0200 Subject: [PATCH 01/16] defined stop condition for reading processes, otherwise pm 'crashes' if there's no tag on device --- armsrc/em4x50.c | 153 +++++++++++++++++++++++++++--------------------- 1 file changed, 87 insertions(+), 66 deletions(-) diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index cfbfb9fe0..bcf48bd55 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -75,6 +75,7 @@ static em4x50_tag_t tag = { #define EM4X50_T_WAITING_FOR_LIW 500 #define EM4X50_T_TAG_TPP 64 #define EM4X50_T_TAG_TWA 64 +#define EM4X50_T_TAG_INIT 2112 #define EM4X50_TAG_TOLERANCE 8 #define EM4X50_TAG_WORD 45 @@ -237,19 +238,34 @@ static void em4x50_setup_read(void) { // functions for "reader" use case -static void get_signalproperties(void) { +static bool get_signalproperties(void) { // calculate signal properties (mean amplitudes) from measured data: // 32 amplitudes (maximum values) -> mean amplitude value -> gHigh -> gLow + bool signal_found = false; int no_periods = 32, pct = 75, noise = 140; uint8_t sample = 0, sample_ref = 127; uint8_t sample_max_mean = 0; uint8_t sample_max[no_periods]; uint32_t sample_max_sum = 0; + - // wait until signal/noise > 1 - while (AT91C_BASE_SSC->SSC_RHR < noise); + // wait until signal/noise > 1 (max. 32 periods) + for (int i = 0; i < T0 * no_periods; i++) { + + // about 2 samples per bit period + wait_timer(0, T0 * EM4X50_T_TAG_HALF_PERIOD); + + if (AT91C_BASE_SSC->SSC_RHR > noise) { + signal_found = true; + break; + } + + } + + if (!signal_found) + return false; // calculate mean maximum value of 32 periods, each period has a length of // 3 single "full periods" to eliminate the influence of a listen window @@ -274,6 +290,7 @@ static void get_signalproperties(void) { gHigh = sample_ref + pct * (sample_max_mean - sample_ref) / 100; gLow = sample_ref - pct * (sample_max_mean - sample_ref) / 100; + return true; } static int get_next_bit(void) { @@ -736,31 +753,32 @@ void em4x50_info(em4x50_data_t *etd) { init_tag(); em4x50_setup_read(); - + // set gHigh and gLow - get_signalproperties(); - - if (etd->pwd_given) { + if (get_signalproperties()) { - // try to login with given password - blogin = login(etd->password); + if (etd->pwd_given) { - } else { - - // if no password is given, try to login with "0x00000000" - blogin = login(password); + // try to login with given password + blogin = login(etd->password); + } else { + + // if no password is given, try to login with "0x00000000" + blogin = login(password); + + } + + bsuccess = selective_read(addresses); } - - bsuccess = selective_read(addresses); - + status = (bsuccess << 1) + blogin; lf_finalize(); reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238); } -void em4x50_sread(em4x50_data_t *etd) { +void em4x50_read(em4x50_data_t *etd) { // reads in two different ways: // - using "selective read mode" -> bidirectional communication @@ -776,25 +794,26 @@ void em4x50_sread(em4x50_data_t *etd) { em4x50_setup_read(); // set gHigh and gLow - get_signalproperties(); + if (get_signalproperties()) { - if (etd->addr_given) { + if (etd->addr_given) { - // selective read mode - - // try to login with given password - if (etd->pwd_given) - blogin = login(etd->password); - - // only one word has to be read -> first word read = last word read - addresses[2] = addresses[3] = etd->address; - bsuccess = selective_read(addresses); - - } else { - - // standard read mode - bsuccess = standard_read(&now); - + // selective read mode + + // try to login with given password + if (etd->pwd_given) + blogin = login(etd->password); + + // only one word has to be read -> first word read = last word read + addresses[2] = addresses[3] = etd->address; + bsuccess = selective_read(addresses); + + } else { + + // standard read mode + bsuccess = standard_read(&now); + + } } status = (now << 2) + (bsuccess << 1) + blogin; @@ -896,40 +915,41 @@ void em4x50_write(em4x50_data_t *etd) { em4x50_setup_read(); // set gHigh and gLow - get_signalproperties(); + if (get_signalproperties()) { - // 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); - - // write word to given address - if (write(etd->word, etd->address)) { + // 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); + + // write word to given address + if (write(etd->word, etd->address)) { - // to verify result reset EM4x50 - if (reset()) { + // to verify result reset EM4x50 + if (reset()) { - // if password is given login - if (etd->pwd_given) - blogin &= login(etd->password); + // if password is given login + if (etd->pwd_given) + blogin &= login(etd->password); - // call a selective read - addresses[2] = addresses[3] = etd->address; - if (selective_read(addresses)) { + // call a selective read + addresses[2] = addresses[3] = etd->address; + if (selective_read(addresses)) { - // compare with given word - word[0] = tag.sectors[etd->address][0]; - word[1] = tag.sectors[etd->address][1]; - word[2] = tag.sectors[etd->address][2]; - word[3] = tag.sectors[etd->address][3]; - msb2lsb_word(word); - - bsuccess = true; - for (int i = 0; i < 4; i++) - bsuccess &= (word[i] == etd->word[i]) ? true : false; + // compare with given word + word[0] = tag.sectors[etd->address][0]; + word[1] = tag.sectors[etd->address][1]; + word[2] = tag.sectors[etd->address][2]; + word[3] = tag.sectors[etd->address][3]; + msb2lsb_word(word); + + bsuccess = true; + for (int i = 0; i < 4; i++) + bsuccess &= (word[i] == etd->word[i]) ? true : false; + } } } } @@ -950,11 +970,12 @@ void em4x50_write_password(em4x50_data_t *etd) { em4x50_setup_read(); // set gHigh and gLow - get_signalproperties(); + if (get_signalproperties()) { - // login and change password - if (login(etd->password)) { - bsuccess = write_password(etd->password, etd->new_password); + // login and change password + if (login(etd->password)) { + bsuccess = write_password(etd->password, etd->new_password); + } } lf_finalize(); From b6359def47da0c7cfef183fd191f4d4a329044c0 Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:32:52 +0200 Subject: [PATCH 02/16] renamed 'sread" to 'read' --- armsrc/em4x50.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/em4x50.h b/armsrc/em4x50.h index aecaea78e..d786e61c0 100644 --- a/armsrc/em4x50.h +++ b/armsrc/em4x50.h @@ -20,6 +20,6 @@ typedef struct { void em4x50_info(em4x50_data_t *etd); void em4x50_write(em4x50_data_t *etd); void em4x50_write_password(em4x50_data_t *etd); -void em4x50_sread(em4x50_data_t *etd); +void em4x50_read(em4x50_data_t *etd); #endif /* EM4X50_H */ From 955c7a642d0a269fd7caadaf53e05dc2e89df4c9 Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:33:37 +0200 Subject: [PATCH 03/16] renamed 'sread' to 'read' --- client/src/cmdlfem4x50.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/src/cmdlfem4x50.h b/client/src/cmdlfem4x50.h index 8f4b63a4f..7b3fb53a0 100644 --- a/client/src/cmdlfem4x50.h +++ b/client/src/cmdlfem4x50.h @@ -11,14 +11,18 @@ #ifndef CMDLFEM4X50_H__ #define CMDLFEM4X50_H__ +#include"common.h" + int usage_lf_em4x50_info(void); int usage_lf_em4x50_write(void); int usage_lf_em4x50_write_password(void); -int usage_lf_em4x50_sread(void); +int usage_lf_em4x50_read(void); + +int EM4x50Read(const char *Cmd, bool verbose); int CmdEM4x50Info(const char *Cmd); int CmdEM4x50Write(const char *Cmd); int CmdEM4x50WritePassword(const char *Cmd); -int CmdEM4x50SRead(const char *Cmd); +int CmdEM4x50Read(const char *Cmd); #endif From c6435d2f9662f50491e9b17cf741a07e5c4d6f55 Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:35:06 +0200 Subject: [PATCH 04/16] output changes due to integration of 'read' into 'lf search' process --- client/src/cmdlfem4x50.c | 378 ++++++++++++++++++++------------------- 1 file changed, 194 insertions(+), 184 deletions(-) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index cee6ece71..20db97a14 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -54,17 +54,17 @@ int usage_lf_em4x50_write_password(void) { PrintAndLogEx(NORMAL, " lf em 4x50_write_password p 11223344 n 01020304"); return PM3_SUCCESS; } -int usage_lf_em4x50_sread(void) { +int usage_lf_em4x50_read(void) { PrintAndLogEx(NORMAL, "Read EM4x50 word(s). Tag must be on antenna. "); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x50_sread [h] a
p "); + PrintAndLogEx(NORMAL, "Usage: lf em 4x50_read [h] a
p "); 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, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x50_sread"); - PrintAndLogEx(NORMAL, " lf em 4x50_sread a 2 p 00000000"); + PrintAndLogEx(NORMAL, " lf em 4x50_read"); + PrintAndLogEx(NORMAL, " lf em 4x50_read a 2 p 00000000"); return PM3_SUCCESS; } @@ -190,7 +190,7 @@ static void print_bit_table(const em4x50_word_t word) { string[0] = '\0'; } -static void print_result(const em4x50_word_t *words, int fwr, int lwr) { +static void print_result(const em4x50_word_t *words, int fwr, int lwr, bool verbose) { // print available information for given word from fwr to lwr, i.e. // bit table + summary lines with hex notation of word (msb + lsb) @@ -199,28 +199,41 @@ static void print_result(const em4x50_word_t *words, int fwr, int lwr) { for (int i = fwr; i <= lwr; i++) { - // blank line before each bit table - PrintAndLogEx(NORMAL, ""); + if (verbose) { + + // blank line before each bit table + PrintAndLogEx(NORMAL, ""); - // print bit table - print_bit_table(words[i]); - - // final result - string[0] = '\0'; - sprintf(pstring, "\n word[%i] msb: " _GREEN_("0x"), i); - strcat(string, pstring); + // print bit table + print_bit_table(words[i]); - for (int j = 0; j < 4; j++) { - sprintf(pstring, _GREEN_("%02x"), words[i].byte[j]); + // final result + string[0] = '\0'; + sprintf(pstring, "\n word[%i] msb: " _GREEN_("0x"), i); strcat(string, pstring); - } - - sprintf(pstring, "\n word[%i] lsb: 0x", i); - strcat(string, pstring); - for (int j = 0; j < 4; j++) { - sprintf(pstring, "%02x", reflect8(words[i].byte[3-j])); + for (int j = 0; j < 4; j++) { + sprintf(pstring, _GREEN_("%02x"), words[i].byte[j]); + strcat(string, pstring); + } + + sprintf(pstring, "\n word[%i] lsb: 0x", i); strcat(string, pstring); + + for (int j = 0; j < 4; j++) { + sprintf(pstring, "%02x", reflect8(words[i].byte[3-j])); + strcat(string, pstring); + } + } else { + + string[0] = '\0'; + sprintf(pstring, "[" _GREEN_("+") "] word[%i]: " _YELLOW_("0x"), i); + strcat(string, pstring); + + for (int j = 0; j < 4; j++) { + sprintf(pstring, _YELLOW_("%02x"), words[i].byte[j]); + strcat(string, pstring); + } } PrintAndLogEx(NORMAL,string); @@ -236,7 +249,6 @@ static void print_info_result(PacketResponseNG *resp, const em4x50_data_t *etd, char pstring[NO_CHARS_MAX] = {0}, string[NO_CHARS_MAX] = {0}; bool bpwd_given = etd->pwd_given; - bool bsuccess = (resp->status & STATUS_SUCCESS) >> 1; bool blogin = resp->status & STATUS_LOGIN; prepare_result(data, 0, EM4X50_NO_WORDS - 1, words); @@ -256,7 +268,7 @@ static void print_info_result(PacketResponseNG *resp, const em4x50_data_t *etd, if (bverbose) { // detailed data section - print_result(words, 0, EM4X50_NO_WORDS - 1); + print_result(words, 0, EM4X50_NO_WORDS - 1, true); } else { @@ -336,47 +348,38 @@ static void print_info_result(PacketResponseNG *resp, const em4x50_data_t *etd, sprintf(pstring, " reading "); strcat(string, pstring); - if (!bsuccess) { + sprintf(pstring, _GREEN_("ok ")); + strcat(string, pstring); + + if (blogin) { + + if (bpwd_given) { + + sprintf(pstring, "(login with password 0x%02x%02x%02x%02x)", + etd->password[0], etd->password[1], + etd->password[2], etd->password[3]); + strcat(string, pstring); - sprintf(pstring, _RED_("failed")); - strcat(string, pstring); - - } else { - - sprintf(pstring, _GREEN_("ok ")); - strcat(string, pstring); - - if (blogin) { - - if (bpwd_given) { - - sprintf(pstring, "(login with password 0x%02x%02x%02x%02x)", - etd->password[0], etd->password[1], - etd->password[2], etd->password[3]); - strcat(string, pstring); - - } else { - - sprintf(pstring, "(login with default password 0x00000000)"); - strcat(string, pstring); - - } - } else { - if (bpwd_given) { + sprintf(pstring, "(login with default password 0x00000000)"); + strcat(string, pstring); - sprintf(pstring, "(login failed)"); - strcat(string, pstring); - - } else { - - sprintf(pstring, "(no login)"); - strcat(string, pstring); - - } } + } else { + + if (bpwd_given) { + + sprintf(pstring, "(login failed)"); + strcat(string, pstring); + + } else { + + sprintf(pstring, "(no login)"); + strcat(string, pstring); + + } } PrintAndLogEx(NORMAL,"%s\n", string); @@ -432,15 +435,19 @@ int CmdEM4x50Info(const char *Cmd) { // get result - if (!WaitForResponse(CMD_ACK, &resp)) { - PrintAndLogEx(WARNING, " timeout while waiting for reply."); + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } - // print result - print_info_result(&resp, &etd, verbose); - success = (resp.status & STATUS_SUCCESS) >> 1; + + // print result + if (success) + print_info_result(&resp, &etd, verbose); + else + PrintAndLogEx(NORMAL,"\nreading " _RED_("failed") "\n"); + return (success) ? PM3_SUCCESS : PM3_ESOFT; } @@ -449,41 +456,32 @@ static void print_write_result(PacketResponseNG *resp, const em4x50_data_t *etd) // display result of writing operation in structured format bool pwd_given = etd->pwd_given; - bool success = (resp->status & STATUS_SUCCESS) >> 1; bool login = resp->status & STATUS_LOGIN; uint8_t *data = resp->data.asBytes; char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0}; em4x50_word_t word; - if (!success) { - - sprintf(pstring, "\n writing " _RED_("failed")); - strcat(string, pstring); + prepare_result(data, etd->address, etd->address, &word); + print_result(&word, etd->address, etd->address, true); - } else { - - prepare_result(data, etd->address, etd->address, &word); - print_result(&word, etd->address, etd->address); + sprintf(pstring, "\n writing " _GREEN_("ok ")); + strcat(string, pstring); - sprintf(pstring, "\n writing " _GREEN_("ok ")); - strcat(string, pstring); - - if (pwd_given) { - - if (login) { - sprintf(pstring, "(login with password 0x%02x%02x%02x%02x)", - etd->password[0], etd->password[1], - etd->password[2], etd->password[3]); - strcat(string, pstring); - } else { - sprintf(pstring, "(login failed)"); - strcat(string, pstring); - } + if (pwd_given) { + if (login) { + sprintf(pstring, "(login with password 0x%02x%02x%02x%02x)", + etd->password[0], etd->password[1], + etd->password[2], etd->password[3]); + strcat(string, pstring); } else { - sprintf(pstring, "(no login)"); + sprintf(pstring, "(login failed)"); strcat(string, pstring); } + + } else { + sprintf(pstring, "(no login)"); + strcat(string, pstring); } PrintAndLogEx(NORMAL,"%s\n", string); @@ -551,15 +549,19 @@ int CmdEM4x50Write(const char *Cmd) { SendCommandNG(CMD_LF_EM4X50_WRITE, (uint8_t *)&etd, sizeof(etd)); - if (!WaitForResponse(CMD_ACK, &resp)) { - PrintAndLogEx(WARNING, "\n timeout while waiting for reply.\n"); + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } - // get, prepare and print response - print_write_result(&resp, &etd); - success = (resp.status & STATUS_SUCCESS) >> 1; + + // get, prepare and print response + if (success) + print_write_result(&resp, &etd); + else + PrintAndLogEx(NORMAL,"\nwriting " _RED_("failed") "\n"); + return (success) ? PM3_SUCCESS : PM3_ESOFT; } @@ -567,19 +569,10 @@ static void print_write_password_result(PacketResponseNG *resp, const em4x50_dat // display result of password changing operation - bool success = resp->status; char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0}; - if (!success) { - - sprintf(pstring, "\n writing new password " _RED_("failed")); - strcat(string, pstring); - - } else { - - sprintf(pstring, "\n writing new password " _GREEN_("ok")); - strcat(string, pstring); - } + sprintf(pstring, "\n writing new password " _GREEN_("ok")); + strcat(string, pstring); PrintAndLogEx(NORMAL,"%s\n", string); } @@ -588,7 +581,7 @@ int CmdEM4x50WritePassword(const char *Cmd) { // envokes changing the password of EM4x50 tag - bool errors = false, bpwd = false, bnpwd = false; + bool errors = false, bpwd = false, bnpwd = false, success = false; uint8_t cmdp = 0; em4x50_data_t etd; PacketResponseNG resp; @@ -636,71 +629,69 @@ int CmdEM4x50WritePassword(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_LF_EM4X50_WRITE_PASSWORD, (uint8_t *)&etd, sizeof(etd)); - if (!WaitForResponse(CMD_ACK, &resp)) { - PrintAndLogEx(WARNING, "\n timeout while waiting for reply.\n"); + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } + success = (bool)resp.status; // get, prepare and print response - print_write_password_result(&resp, &etd); - - return ((bool)resp.status) ? PM3_SUCCESS : PM3_ESOFT; + if (success) + print_write_password_result(&resp, &etd); + else + PrintAndLogEx(NORMAL,"\nwriting password " _RED_("failed") "\n"); + + return (success) ? PM3_SUCCESS : PM3_ESOFT; } -static void print_sread_result(PacketResponseNG *resp, const em4x50_data_t *etd) { +static void print_read_result(PacketResponseNG *resp, const em4x50_data_t *etd, bool verbose) { // display result of writing operation in structured format bool addr_given = etd->addr_given; bool pwd_given = etd->pwd_given; bool login = resp->status & STATUS_LOGIN; - bool success = (resp->status & STATUS_SUCCESS) >> 1; int now = (resp->status & STATUS_NO_WORDS) >> 2; char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0}; uint8_t *data = resp->data.asBytes; em4x50_word_t word; - if (!success) { + if (addr_given) { - sprintf(pstring, "\n reading " _RED_("failed")); + // selective read mode + + prepare_result(data, etd->address, etd->address, &word); + print_result(&word, etd->address, etd->address, true); + + string[0] = '\0'; + sprintf(pstring, "\n reading " _GREEN_("ok ")); strcat(string, pstring); + + if (pwd_given) { + if (login) { + sprintf(pstring, "(login with password 0x%02x%02x%02x%02x)", + etd->password[0], etd->password[1], + etd->password[2], etd->password[3]); + strcat(string, pstring); + } else { + sprintf(pstring, "(login failed)"); + strcat(string, pstring); + } + } else { + sprintf(pstring, "(no login)"); + strcat(string, pstring); + } PrintAndLogEx(NORMAL,"%s\n", string); } else { + + //standard read mode - if (addr_given) { - - // selective read mode + prepare_result(data, 0, now - 1, &word); + print_result(&word, 0, now - 1, verbose); - prepare_result(data, etd->address, etd->address, &word); - print_result(&word, etd->address, etd->address); - - string[0] = '\0'; - sprintf(pstring, "\n reading " _GREEN_("ok ")); - strcat(string, pstring); - - if (pwd_given) { - if (login) { - sprintf(pstring, "(login with password 0x%02x%02x%02x%02x)", - etd->password[0], etd->password[1], - etd->password[2], etd->password[3]); - strcat(string, pstring); - } else { - sprintf(pstring, "(login failed)"); - strcat(string, pstring); - } - } else { - sprintf(pstring, "(no login)"); - strcat(string, pstring); - } - - } else { - - //standard read mode - - prepare_result(data, 0, now - 1, &word); - print_result(&word, 0, now - 1); + if (verbose) { string[0] = '\0'; sprintf(pstring, "\n reading " _GREEN_("ok ")); @@ -713,14 +704,14 @@ static void print_sread_result(PacketResponseNG *resp, const em4x50_data_t *etd) sprintf(pstring, "(standard read mode)"); strcat(string, pstring); } - } - PrintAndLogEx(NORMAL,"%s\n", string); + PrintAndLogEx(NORMAL,"%s\n", string); + } } } -int CmdEM4x50SRead(const char *Cmd) { - +int EM4x50Read(const char *Cmd, bool verbose) { + // envoke reading // - without option -> standard read mode // - with given address (option a) (and optional password if address is @@ -735,55 +726,74 @@ int CmdEM4x50SRead(const char *Cmd) { etd.pwd_given = false; etd.addr_given = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + if (verbose) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_lf_em4x50_sread(); + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_em4x50_read(); - 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.pwd_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; + } + etd.pwd_given = true; + cmdp += 2; + break; - case 'a': - param_getdec(Cmd, cmdp + 1, &etd.address); + case 'a': + param_getdec(Cmd, cmdp + 1, &etd.address); - // validation - if (etd.address <= 0 || etd.address >= EM4X50_NO_WORDS) { - PrintAndLogEx(FAILED, "\n error, address has to be in range [1-33]\n"); - return PM3_EINVARG; - } - etd.addr_given = true; - cmdp += 2; - break; + // validation + if (etd.address <= 0 || etd.address >= EM4X50_NO_WORDS) { + PrintAndLogEx(FAILED, "\n error, address has to be in range [1-33]\n"); + return PM3_EINVARG; + } + etd.addr_given = true; + cmdp += 2; + break; - default: - PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; + default: + PrintAndLogEx(WARNING, "\n Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } + + if (errors) + return usage_lf_em4x50_read(); + } - if (errors) - return usage_lf_em4x50_sread(); - clearCommandBuffer(); - SendCommandNG(CMD_LF_EM4X50_SREAD, (uint8_t *)&etd, sizeof(etd)); + SendCommandNG(CMD_LF_EM4X50_READ, (uint8_t *)&etd, sizeof(etd)); - if (!WaitForResponse(CMD_ACK, &resp)) { - PrintAndLogEx(WARNING, "\n timeout while waiting for reply.\n"); + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } - // get, prepare and print response - print_sread_result(&resp, &etd); - success = (resp.status & STATUS_SUCCESS) >> 1; + + // get, prepare and print response + if (success) + print_read_result(&resp, &etd, verbose); + else if (verbose) + PrintAndLogEx(NORMAL,"\nreading " _RED_("failed") "\n"); + return (success) ? PM3_SUCCESS : PM3_ESOFT; + +} + +int CmdEM4x50Read(const char *Cmd) { + + // envoke reading function + // verbose = true for manual call + // verbose = false for automatic call (e.g. lf search) + + bool verbose = true; + + return EM4x50Read(Cmd, verbose); } From eddaf70ef90fb0acdeccce1432d638d6ed021b7a Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:35:49 +0200 Subject: [PATCH 05/16] added timeout value if there's no tag on device --- include/em4x50.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/em4x50.h b/include/em4x50.h index ddda32f7f..b70072c32 100644 --- a/include/em4x50.h +++ b/include/em4x50.h @@ -38,6 +38,7 @@ #define STATUS_SUCCESS 0x2 #define STATUS_LOGIN 0x1 #define NO_CHARS_MAX 400 +#define TIMEOUT 2000 typedef struct { bool addr_given; From a01c5aff0e64f301f348fb81f73262644269e1de Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:37:12 +0200 Subject: [PATCH 06/16] deleted EM4x50 functions due to switch to new 'read' function for EM4x50 tag (device side) --- client/src/cmdlfem4x.h | 1 - 1 file changed, 1 deletion(-) diff --git a/client/src/cmdlfem4x.h b/client/src/cmdlfem4x.h index d727cb551..62ecafa23 100644 --- a/client/src/cmdlfem4x.h +++ b/client/src/cmdlfem4x.h @@ -16,7 +16,6 @@ int CmdLFEM4X(const char *Cmd); int demodEM410x(void); -int EM4x50Read(const char *Cmd, bool verbose); bool EM4x05IsBlock0(uint32_t *word); void printEM410x(uint32_t hi, uint64_t id); From 1cf51410f406fb37ebf5de9c0035fd62206fd9ca Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:37:53 +0200 Subject: [PATCH 07/16] renamed 'lread' to 'read' --- armsrc/appmain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 604d44c34..95b42982a 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1019,8 +1019,8 @@ static void PacketReceived(PacketCommandNG *packet) { em4x50_write_password((em4x50_data_t *)packet->data.asBytes); break; } - case CMD_LF_EM4X50_SREAD: { - em4x50_sread((em4x50_data_t *)packet->data.asBytes); + case CMD_LF_EM4X50_READ: { + em4x50_read((em4x50_data_t *)packet->data.asBytes); break; } From 942493970e69b7c6bb85f62965db85245244eec6 Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:38:19 +0200 Subject: [PATCH 08/16] renamed 'sread' to 'read' --- include/pm3_cmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 05c42dfd8..117eea672 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -405,7 +405,7 @@ typedef struct { #define CMD_LF_EM4X50_INFO 0x0240 #define CMD_LF_EM4X50_WRITE 0x0241 #define CMD_LF_EM4X50_WRITE_PASSWORD 0x0242 -#define CMD_LF_EM4X50_SREAD 0x0243 +#define CMD_LF_EM4X50_READ 0x0243 // Sampling configuration for LF reader/sniffer #define CMD_LF_SAMPLING_SET_CONFIG 0x021D #define CMD_LF_FSK_SIMULATE 0x021E From c572a2bab8926a140292ebd46a74275e7ea7ca0b Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:39:27 +0200 Subject: [PATCH 09/16] introduced 'IfPm3EM4x50' function --- client/src/cmdparser.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/src/cmdparser.c b/client/src/cmdparser.c index 529a3d553..dee76a8fe 100644 --- a/client/src/cmdparser.c +++ b/client/src/cmdparser.c @@ -89,6 +89,12 @@ bool IfPm3Hitag(void) { return pm3_capabilities.compiled_with_hitag; } +bool IfPm3EM4x50(void) { + if (!IfPm3Present()) + return false; + return pm3_capabilities.compiled_with_em4x50; +} + bool IfPm3Hfsniff(void) { if (!IfPm3Present()) return false; From 91ff0350df909b9b2b319f1e3422a8b6db9d808a Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:39:59 +0200 Subject: [PATCH 10/16] introduced 'IfPm3EM4x50' function --- client/src/cmdparser.h | 1 + 1 file changed, 1 insertion(+) diff --git a/client/src/cmdparser.h b/client/src/cmdparser.h index 1105f63ae..baade0bcb 100644 --- a/client/src/cmdparser.h +++ b/client/src/cmdparser.h @@ -33,6 +33,7 @@ bool IfPm3FpcUsartDevFromUsb(void); bool IfPm3FpcUsartFromUsb(void); bool IfPm3Lf(void); bool IfPm3Hitag(void); +bool IfPm3EM4x50(void); bool IfPm3Hfsniff(void); bool IfPm3Hfplot(void); bool IfPm3Iso14443a(void); From 78511df9f28dd7b067176ed9a0052f302adf489e Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:41:21 +0200 Subject: [PATCH 11/16] integrated 'lread' into 'lf search' process and renamed 'lread' to 'read' --- client/src/cmdlf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/src/cmdlf.c b/client/src/cmdlf.c index 748c9557a..35ce4c1b7 100644 --- a/client/src/cmdlf.c +++ b/client/src/cmdlf.c @@ -30,6 +30,7 @@ #include "cmddata.h" // for `lf search` #include "cmdlfawid.h" // for awid menu #include "cmdlfem4x.h" // for em4x menu +#include "cmdlfem4x50.h" // for em4x50 #include "cmdlfhid.h" // for hid menu #include "cmdlfhitag.h" // for hitag menu #include "cmdlfio.h" // for ioprox menu @@ -1250,6 +1251,13 @@ int CmdLFfind(const char *Cmd) { } } + if (IfPm3EM4x50()) { + if (EM4x50Read("", false) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!"); + return PM3_SUCCESS; + } + } + // only run if graphbuffer is just noise as it should be for hitag // The improved noise detection will find Cotag. if (getSignalProperties()->isnoise) { @@ -1270,8 +1278,6 @@ int CmdLFfind(const char *Cmd) { } } - if (EM4x50Read("", false) == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!"); return PM3_SUCCESS;} - if (demodHID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;} if (demodAWID() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;} if (demodIOProx() == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;} From 9aafc094b6426b7e590037727147a0ba0f348476 Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 21:43:13 +0200 Subject: [PATCH 12/16] deleted nearly all EM4x50 code; new EM4x50 code is in 'cmdlfem4x50.c' (device side instead GraphBuffer) --- client/src/cmdlfem4x.c | 369 +---------------------------------------- 1 file changed, 4 insertions(+), 365 deletions(-) diff --git a/client/src/cmdlfem4x.c b/client/src/cmdlfem4x.c index ef8cbdc13..27de68519 100644 --- a/client/src/cmdlfem4x.c +++ b/client/src/cmdlfem4x.c @@ -116,41 +116,6 @@ static int usage_lf_em410x_brute(void) { return PM3_SUCCESS; } -//////////////// 4050 / 4450 commands -static int usage_lf_em4x50_demod(void) { - PrintAndLogEx(NORMAL, "Usage: lf em 4x50_demod [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x50_demod"); - return PM3_SUCCESS; -} -static int usage_lf_em4x50_dump(void) { - PrintAndLogEx(NORMAL, "Dump EM4x50/EM4x69. Tag must be on antenna. "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x50_dump [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x50_dump"); - PrintAndLogEx(NORMAL, " lf em 4x50_dump 11223344"); - return PM3_SUCCESS; -} -static int usage_lf_em4x50_read(void) { - PrintAndLogEx(NORMAL, "Read EM 4x50/EM4x69. Tag must be on antenna. "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf em 4x50_read [h]
"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " address - memory address to read. (0-15)"); - PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 4x50_read 1"); - PrintAndLogEx(NORMAL, " lf em 4x50_read 1 11223344"); - return PM3_SUCCESS; -} - //////////////// 4205 / 4305 commands static int usage_lf_em4x05_dump(void) { PrintAndLogEx(NORMAL, "Dump EM4x05/EM4x69. Tag must be on antenna. "); @@ -723,329 +688,6 @@ static bool EM_ColParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t col return true; } -// even parity ROW -static bool EM_RowParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) { - if (rows * cols > size) return false; - uint8_t rowP = 0; - - for (uint8_t r = 0; r < rows - 1; r++) { - for (uint8_t c = 0; c < cols; c++) { - rowP ^= bs[(r * cols) + c]; - } - if (rowP != pType) return false; - rowP = 0; - } - return true; -} - -// EM word parity test. -// 9*5 = 45 bits in total -// 012345678|r0 -// 012345678|r1 -// 012345678|r2 -// 012345678|r3 -// ------------ -//c012345678| 0 -// |- must be zero - -/* -static int EMwordparitytest(uint8_t *bits) { - - // last row/col parity must be 0 - if (bits[44] != 0) return PM3_ESOFT; - - // col parity check - uint8_t c1 = bytebits_to_byte(bits, 8) ^ bytebits_to_byte(bits + 9, 8) ^ bytebits_to_byte(bits + 18, 8) ^ bytebits_to_byte(bits + 27, 8); - uint8_t c2 = bytebits_to_byte(bits + 36, 8); - if (c1 != c2) return PM3_ESOFT; - - // row parity check - uint8_t rowP = 0; - for (uint8_t i = 0; i < 36; ++i) { - - rowP ^= bits[i]; - if (i > 0 && (i % 9) == 0) { - - if (rowP != EVEN) - return PM3_ESOFT; - - rowP = 0; - } - } - // all checks ok. - return PM3_SUCCESS; -} -*/ - -//////////////// 4050 / 4450 commands - -static uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest) { - if (size < 45) return 0; - - uint32_t code = bytebits_to_byte(BitStream, 8); - code = code << 8 | bytebits_to_byte(BitStream + 9, 8); - code = code << 8 | bytebits_to_byte(BitStream + 18, 8); - code = code << 8 | bytebits_to_byte(BitStream + 27, 8); - - if (verbose || g_debugMode) { - for (uint8_t i = 0; i < 5; i++) { - if (i == 4) PrintAndLogEx(NORMAL, ""); //parity byte spacer - PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d -> 0x%02x", - BitStream[i * 9], - BitStream[i * 9 + 1], - BitStream[i * 9 + 2], - BitStream[i * 9 + 3], - BitStream[i * 9 + 4], - BitStream[i * 9 + 5], - BitStream[i * 9 + 6], - BitStream[i * 9 + 7], - BitStream[i * 9 + 8], - bytebits_to_byte(BitStream + i * 9, 8) - ); - } - - PrintAndLogEx(SUCCESS, "Parity checks | %s", (pTest) ? _GREEN_("Passed") : _RED_("Fail")); - } - return code; -} - -/* Read the transmitted data of an EM4x50 tag from the graphbuffer - * Format: - * - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * XXXXXXXX [row parity bit (even)] <- 8 bits plus parity - * CCCCCCC0 <- column parity bits - * 0 <- stop bit - * LW <- Listen Window - * - * This pattern repeats for every block of data being transmitted. - * Transmission starts with two Listen Windows (LW - a modulated - * pattern of 320 cycles each (32/32/128/64/64)). - * - * Note that this data may or may not be the UID. It is whatever data - * is stored in the blocks defined in the control word First and Last - * Word Read values. UID is stored in block 32. - */ -//completed by Marshmellow -int EM4x50Read(const char *Cmd, bool verbose) { - int clk = 0, invert = 0, tol = 0, phaseoff; - int i = 0, j = 0, startblock, skip, block, start, end, low = 0, high = 0; - uint32_t Code[6]; - char tmp[6]; - char tmp2[20]; - bool complete = false; - - int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; - memset(tmpbuff, 0, sizeof(tmpbuff)); - - // get user entry if any - sscanf(Cmd, "%i %i", &clk, &invert); - - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; - size_t size = getFromGraphBuf(bits); - - if (size < 4000) { - if (verbose || g_debugMode) PrintAndLogEx(ERR, "Error: EM4x50 - Too little data in Graphbuffer"); - return PM3_ESOFT; - } - - computeSignalProperties(bits, size); - - // get fuzzed HI / LOW limits in signal - getHiLo(&high, &low, 75, 75); - - // get to first full low to prime loop and skip incomplete first pulse - size_t offset = 0; - getNextHigh(bits, size, high, &offset); - getNextLow(bits, size, low, &offset); - - i = (int)offset; - skip = offset; - - // set clock - if (clk == 0) { - DetectASKClock(bits, size, &clk, 0); - if (clk == 0) { - if (verbose || g_debugMode) PrintAndLogEx(ERR, "Error: EM4x50 - didn't find a clock"); - return PM3_ESOFT; - } - } - // tolerance - tol = clk / 8; - - // populate tmpbuff buffer with pulse lengths - while (i < size) { - // measure from low to low - while ((i < size) && (bits[i] > low)) - ++i; - start = i; - - while ((i < size) && (bits[i] < high)) - ++i; - - while ((i < size) && (bits[i] > low)) - ++i; - - if (j >= (MAX_GRAPH_TRACE_LEN / 64)) { - break; - } - tmpbuff[j++] = i - start; - } - - // look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2) - start = -1; - for (i = 0; i < j - 4 ; ++i) { - skip += tmpbuff[i]; - if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) //3 clocks - if (tmpbuff[i + 1] >= clk * 2 - tol && tmpbuff[i + 1] <= clk * 2 + tol) //2 clocks - if (tmpbuff[i + 2] >= clk * 3 - tol && tmpbuff[i + 2] <= clk * 3 + tol) //3 clocks - if (tmpbuff[i + 3] >= clk - tol) { //1.5 to 2 clocks - depends on bit following - start = i + 4; - break; - } - } - startblock = i + 4; - - // skip over the remainder of LW - skip += (tmpbuff[i + 1] + tmpbuff[i + 2] + clk); - - if (tmpbuff[i + 3] > clk) - phaseoff = tmpbuff[i + 3] - clk; - else - phaseoff = 0; - - // now do it again to find the end - for (i += 3; i < j - 4 ; ++i) { - if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) //3 clocks - if (tmpbuff[i + 1] >= clk * 2 - tol && tmpbuff[i + 1] <= clk * 2 + tol) //2 clocks - if (tmpbuff[i + 2] >= clk * 3 - tol && tmpbuff[i + 2] <= clk * 3 + tol) //3 clocks - if (tmpbuff[i + 3] >= clk - tol) { //1.5 to 2 clocks - depends on bit following - complete = true; - break; - } - } - end = i; - - // report back - if (verbose || g_debugMode) { - if (start >= 0) { - PrintAndLogEx(INFO, "\nNote: one block = 50 bits (32 data, 12 parity, 6 marker)"); - } else { - PrintAndLogEx(INFO, "No data found!, clock tried: " _YELLOW_("%d"), clk); - PrintAndLogEx(HINT, "Try again with more samples"); - PrintAndLogEx(HINT, " or after a " _YELLOW_("'data askedge'") " command to clean up the read"); - return PM3_ESOFT; - } - } else if (start < 0) { - return PM3_ESOFT; - } - - start = skip; - - snprintf(tmp2, sizeof(tmp2), "%d %d 1000 %d", clk, invert, clk * 47); - - // save GraphBuffer - to restore it later - save_restoreGB(GRAPH_SAVE); - - // get rid of leading crap - snprintf(tmp, sizeof(tmp), "%i", skip); - CmdLtrim(tmp); - - bool AllPTest = true; - - // now work through remaining buffer printing out data blocks - block = 0; - i = startblock; - while (block < 6) { - if (verbose || g_debugMode) PrintAndLogEx(NORMAL, "\nBlock %i:", block); - skip = phaseoff; - - // look for LW before start of next block - for (; i < j - 4 ; ++i) { - skip += tmpbuff[i]; - if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) - if (tmpbuff[i + 1] >= clk - tol) - break; - } - if (i >= j - 4) break; //next LW not found - skip += clk; - if (tmpbuff[i + 1] > clk) - phaseoff = tmpbuff[i + 1] - clk; - else - phaseoff = 0; - - i += 2; - - if (ASKDemod(tmp2, false, false, 1) != PM3_SUCCESS) { - save_restoreGB(GRAPH_RESTORE); - return PM3_ESOFT; - } - - //set DemodBufferLen to just one block - DemodBufferLen = skip / clk; - //test parities - bool pTest = EM_RowParityTest(DemodBuffer, DemodBufferLen, 5, 9, 0); - pTest &= EM_ColParityTest(DemodBuffer, DemodBufferLen, 5, 9, 0); - AllPTest &= pTest; - //get output - Code[block] = OutputEM4x50_Block(DemodBuffer, DemodBufferLen, verbose, pTest); - PrintAndLogEx(DEBUG, "\nskipping %d samples, bits:%d", skip, skip / clk); - //skip to start of next block - snprintf(tmp, sizeof(tmp), "%i", skip); - CmdLtrim(tmp); - block++; - if (i >= end) break; //in case chip doesn't output 6 blocks - } - - //print full code: - if (verbose || g_debugMode || AllPTest) { - if (!complete) { - PrintAndLogEx(WARNING, _RED_("* **Warning!")); - PrintAndLogEx(INFO, "Partial data - no end found!"); - PrintAndLogEx(HINT, "Try again with more samples."); - } - PrintAndLogEx(INFO, "Found data at sample: %i - using clock: %i", start, clk); - end = block; - PrintAndLogEx(INFO, "blk | data"); - PrintAndLogEx(INFO, "----+--------------"); - for (block = 0; block < end; block++) { - PrintAndLogEx(INFO, "%03d | %08x", block, Code[block]); - } - PrintAndLogEx(INFO, "----+--------------"); - PrintAndLogEx((AllPTest) ? SUCCESS : WARNING, "Parities checks | %s", (AllPTest) ? _GREEN_("Passed") : _RED_("Fail")); - - if (AllPTest == false) { - PrintAndLogEx(HINT, "Try cleaning the read samples with " _YELLOW_("'data askedge'")); - } - } - - //restore GraphBuffer - save_restoreGB(GRAPH_RESTORE); - return AllPTest ? PM3_SUCCESS : PM3_ESOFT; -} - -static int CmdEM4x50Demod(const char *Cmd) { - uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_lf_em4x50_demod(); - return EM4x50Read(Cmd, true); -} - -static int CmdEM4x50Read(const char *Cmd) { - uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_lf_em4x50_read(); - lf_read(false, 24000); - return EM4x50Read(Cmd, true); -} - -static int CmdEM4x50Dump(const char *Cmd) { - uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_lf_em4x50_dump(); - PrintAndLogEx(NORMAL, "no implemented yet"); - return PM3_SUCCESS; -} - #define EM_PREAMBLE_LEN 6 // download samples from device and copy to Graphbuffer static bool downloadSamplesEM(void) { @@ -1753,13 +1395,10 @@ static command_t CommandTable[] = { {"4x05_read", CmdEM4x05Read, IfPm3Lf, "read word data from EM4x05/EM4x69"}, {"4x05_write", CmdEM4x05Write, IfPm3Lf, "write word data to EM4x05/EM4x69"}, {"----------", CmdHelp, AlwaysAvailable, "----------------------- " _CYAN_("EM 4x50") " -----------------------"}, - {"4x50_demod", CmdEM4x50Demod, AlwaysAvailable, "demodulate a EM4x50 tag from the GraphBuffer"}, - {"4x50_dump", CmdEM4x50Dump, IfPm3Lf, "dump EM4x50 tag"}, - {"4x50_read", CmdEM4x50Read, IfPm3Lf, "read word data from EM4x50"}, - {"4x50_info", CmdEM4x50Info, IfPm3Lf, "read complete data from EM4x50"}, - {"4x50_write", CmdEM4x50Write, IfPm3Lf, "write word data to EM4x50"}, - {"4x50_write_password", CmdEM4x50WritePassword, IfPm3Lf, "change passwword of EM4x50 tag"}, - {"4x50_sread", CmdEM4x50SRead, IfPm3Lf, "read word data from EM4x50 on device"}, + {"4x50_info", CmdEM4x50Info, IfPm3EM4x50, "read complete data from EM4x50"}, + {"4x50_write", CmdEM4x50Write, IfPm3EM4x50, "write word data to EM4x50"}, + {"4x50_write_password", CmdEM4x50WritePassword, IfPm3EM4x50, "change passwword of EM4x50 tag"}, + {"4x50_read", CmdEM4x50Read, IfPm3EM4x50, "read word data from EM4x50"}, {NULL, NULL, NULL, NULL} }; From 8854c7b688a12d2512fc2ac2c978e4470cc7112b Mon Sep 17 00:00:00 2001 From: tharexde Date: Sun, 28 Jun 2020 23:33:01 +0200 Subject: [PATCH 13/16] - changed termination condition in "listen window detection" (old one didn't work) - decreased debug sensitivity --- armsrc/em4x50.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index bcf48bd55..639342c2c 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -72,10 +72,9 @@ static em4x50_tag_t tag = { #define EM4X50_T_TAG_HALF_PERIOD 32 #define EM4X50_T_TAG_THREE_QUARTER_PERIOD 48 #define EM4X50_T_TAG_FULL_PERIOD 64 -#define EM4X50_T_WAITING_FOR_LIW 500 #define EM4X50_T_TAG_TPP 64 #define EM4X50_T_TAG_TWA 64 -#define EM4X50_T_TAG_INIT 2112 +#define EM4X50_T_WAITING_FOR_LIW 8 // determined empiracally #define EM4X50_TAG_TOLERANCE 8 #define EM4X50_TAG_WORD 45 @@ -425,10 +424,13 @@ static bool find_double_listen_window(bool bcommand) { // find two successive listen windows that indicate the beginning of // data transmission + // listen windows should be detected within T0 * EM4X50_T_WAITING_FOR_LIW + // pulses (empirically determined) + + int cnt_pulses = 0; + + while (cnt_pulses < T0 * EM4X50_T_WAITING_FOR_LIW) { - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV < T0 * EM4X50_T_WAITING_FOR_LIW) { - // identification of listen window is done via evaluation of // pulse lengths if (check_pulse_length(get_pulse_length(), 3 * EM4X50_T_TAG_FULL_PERIOD)) { @@ -471,6 +473,8 @@ static bool find_double_listen_window(bool bcommand) { return true; } } + } else { + cnt_pulses++; } } @@ -643,7 +647,7 @@ static bool login(uint8_t password[4]) { return true; } else { - if (DBGLEVEL >= DBG_ERROR) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("error in command request"); } @@ -667,7 +671,7 @@ static bool reset(void) { return true; } else { - if (DBGLEVEL >= DBG_ERROR) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("error in command request"); } @@ -699,7 +703,7 @@ static bool standard_read(int *now) { return true; } else { - if (DBGLEVEL >= DBG_ERROR) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("didn't find a listen window"); } @@ -733,7 +737,7 @@ static bool selective_read(uint8_t addresses[4]) { return true; } else { - if (DBGLEVEL >= DBG_ERROR) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("error in command request"); } @@ -855,7 +859,7 @@ static bool write(uint8_t word[4], uint8_t address) { } } else { - if (DBGLEVEL >= DBG_ERROR) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("error in command request"); } @@ -894,7 +898,7 @@ static bool write_password(uint8_t password[4], uint8_t new_password[4]) { } } else { - if (DBGLEVEL >= DBG_ERROR) + if (DBGLEVEL >= DBG_DEBUG) Dbprintf("error in command request"); } From 3f70f1154bce8dbfb352f437e94a21501711fc8d Mon Sep 17 00:00:00 2001 From: tharexde Date: Mon, 29 Jun 2020 00:01:19 +0200 Subject: [PATCH 14/16] updated conditions for stopping the detection of a double listen window --- armsrc/em4x50.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index 639342c2c..5644962b8 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -74,7 +74,7 @@ static em4x50_tag_t tag = { #define EM4X50_T_TAG_FULL_PERIOD 64 #define EM4X50_T_TAG_TPP 64 #define EM4X50_T_TAG_TWA 64 -#define EM4X50_T_WAITING_FOR_LIW 8 // determined empiracally +#define EM4X50_T_WAITING_FOR_DBLLIW 1600 #define EM4X50_TAG_TOLERANCE 8 #define EM4X50_TAG_WORD 45 @@ -424,12 +424,13 @@ static bool find_double_listen_window(bool bcommand) { // find two successive listen windows that indicate the beginning of // data transmission - // listen windows should be detected within T0 * EM4X50_T_WAITING_FOR_LIW - // pulses (empirically determined) + // double listen window to be detected within 1600 pulses -> worst case + // reason: first detectable double listen window after 34 words + // -> 34 words + 34 single listen windows -> about 1600 pulses int cnt_pulses = 0; - while (cnt_pulses < T0 * EM4X50_T_WAITING_FOR_LIW) { + while (cnt_pulses < EM4X50_T_WAITING_FOR_DBLLIW) { // identification of listen window is done via evaluation of // pulse lengths From a1f760259254c6d729e4fe6dbfba01b2d8d15803 Mon Sep 17 00:00:00 2001 From: tharexde Date: Tue, 30 Jun 2020 01:50:31 +0200 Subject: [PATCH 15/16] fixed: if tag status = NAK -> following detection of double listen window took too long --- armsrc/em4x50.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/armsrc/em4x50.c b/armsrc/em4x50.c index 5644962b8..0132ff2fd 100644 --- a/armsrc/em4x50.c +++ b/armsrc/em4x50.c @@ -74,7 +74,7 @@ static em4x50_tag_t tag = { #define EM4X50_T_TAG_FULL_PERIOD 64 #define EM4X50_T_TAG_TPP 64 #define EM4X50_T_TAG_TWA 64 -#define EM4X50_T_WAITING_FOR_DBLLIW 1600 +#define EM4X50_T_WAITING_FOR_DBLLIW 1550 #define EM4X50_TAG_TOLERANCE 8 #define EM4X50_TAG_WORD 45 @@ -535,6 +535,10 @@ static bool check_ack(bool bliw) { return true; } } + } else { + + // It's NAK -> stop searching + break; } } } From 9c263b3fb8792cd9ef0a01a22f9154a115d72e78 Mon Sep 17 00:00:00 2001 From: tharexde Date: Tue, 30 Jun 2020 01:51:24 +0200 Subject: [PATCH 16/16] fixed simple compilation errors --- client/src/cmdlfem4x50.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/src/cmdlfem4x50.c b/client/src/cmdlfem4x50.c index 62d8c143f..b38a2cc56 100644 --- a/client/src/cmdlfem4x50.c +++ b/client/src/cmdlfem4x50.c @@ -461,8 +461,8 @@ static void print_write_result(PacketResponseNG *resp, const em4x50_data_t *etd) char string[NO_CHARS_MAX] = {0}, pstring[NO_CHARS_MAX] = {0}; em4x50_word_t words[EM4X50_NO_WORDS]; - prepare_result(data, etd->address, etd->address, &word); - print_result(&word, etd->address, etd->address, true); + prepare_result(data, etd->address, etd->address, words); + print_result(words, etd->address, etd->address, true); sprintf(pstring, "\n writing " _GREEN_("ok ")); strcat(string, pstring); @@ -660,8 +660,8 @@ static void print_read_result(PacketResponseNG *resp, const em4x50_data_t *etd, // selective read mode - prepare_result(data, etd->address, etd->address, &word); - print_result(&word, etd->address, etd->address, true); + prepare_result(data, etd->address, etd->address, words); + print_result(words, etd->address, etd->address, true); string[0] = '\0'; sprintf(pstring, "\n reading " _GREEN_("ok ")); @@ -688,8 +688,8 @@ static void print_read_result(PacketResponseNG *resp, const em4x50_data_t *etd, //standard read mode - prepare_result(data, 0, now - 1, &word); - print_result(&word, 0, now - 1, verbose); + prepare_result(data, 0, now - 1, words); + print_result(words, 0, now - 1, verbose); if (verbose) {