mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-19 21:03:48 -07:00
clean up
This commit is contained in:
parent
68db54028c
commit
b4a8409349
5 changed files with 136 additions and 298 deletions
|
@ -80,53 +80,6 @@ static void DownloadLogInstructions(const char *logfile) {
|
||||||
Dbprintf(_YELLOW_("3.") " cat %s", logfile);
|
Dbprintf(_YELLOW_("3.") " cat %s", logfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool strip_check_parities(uint64_t data, uint32_t *word) {
|
|
||||||
|
|
||||||
uint8_t rparity = 0, cparity = 0;
|
|
||||||
uint8_t rparity_m = 0, cparity_m = 0, stop_bit_m = 0;
|
|
||||||
|
|
||||||
// strip parities
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
*word <<= 1;
|
|
||||||
*word += (data >> (EM4X50_TAG_WORD - 1 - 9 * i - j)) & 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate row parities
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
rparity <<= 1;
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
rparity ^= (*word >> (31 - 8 * i - j)) & 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// calculate column parities
|
|
||||||
for (int i = 0; i < 8; i++) {
|
|
||||||
cparity <<= 1;
|
|
||||||
for (int j = 0; j < 4; j++) {
|
|
||||||
cparity ^= (*word >> (31 - 8 * j - i)) & 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// measured row parities
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
rparity_m <<= 1;
|
|
||||||
rparity_m += (data >> (EM4X50_TAG_WORD - 9 * (i + 1))) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// measured column parities
|
|
||||||
cparity_m = (data >> 1) & 0xFF;
|
|
||||||
|
|
||||||
// measured stop bit
|
|
||||||
stop_bit_m = data & 1;
|
|
||||||
|
|
||||||
if ((cparity_m == cparity) && (rparity_m == rparity) && (stop_bit_m == 0))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int get_input_data_from_file(uint32_t *words, char *inputfile) {
|
static int get_input_data_from_file(uint32_t *words, char *inputfile) {
|
||||||
|
|
||||||
size_t now = 0;
|
size_t now = 0;
|
||||||
|
@ -173,8 +126,6 @@ void RunMod(void) {
|
||||||
|
|
||||||
bool state_change = true;//, password_found = false;
|
bool state_change = true;//, password_found = false;
|
||||||
int pwd_found = false;
|
int pwd_found = false;
|
||||||
//int cnt = 0;
|
|
||||||
//int iterprint = 0;
|
|
||||||
uint8_t state = STATE_SIM;
|
uint8_t state = STATE_SIM;
|
||||||
// declarations for simulating
|
// declarations for simulating
|
||||||
uint32_t words[33] = {0x0};
|
uint32_t words[33] = {0x0};
|
||||||
|
@ -183,8 +134,7 @@ void RunMod(void) {
|
||||||
size_t now = 0;
|
size_t now = 0;
|
||||||
// declarations for reading
|
// declarations for reading
|
||||||
int no_words = 0;
|
int no_words = 0;
|
||||||
uint64_t data[EM4X50_TAG_WORD];
|
//uint32_t words[EM4X50_TAG_WORD];
|
||||||
uint32_t word = 0;//, pwd = 0x0, rpwd = 0x0;
|
|
||||||
uint8_t entry[81];
|
uint8_t entry[81];
|
||||||
|
|
||||||
rdv40_spiffs_lazy_mount();
|
rdv40_spiffs_lazy_mount();
|
||||||
|
@ -273,14 +223,14 @@ void RunMod(void) {
|
||||||
Dbprintf(_YELLOW_("switched to EM4x50 reading mode"));
|
Dbprintf(_YELLOW_("switched to EM4x50 reading mode"));
|
||||||
|
|
||||||
memset(entry, 0, sizeof(entry));
|
memset(entry, 0, sizeof(entry));
|
||||||
memset(data, 0, sizeof(data));
|
memset(words, 0, sizeof(words));
|
||||||
|
|
||||||
log_exists = exists_in_spiffs(LF_EM4X50COLLECT_LOGFILE);
|
log_exists = exists_in_spiffs(LF_EM4X50COLLECT_LOGFILE);
|
||||||
|
|
||||||
state_change = false;
|
state_change = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
no_words = em4x50_standalone_read(data);
|
no_words = em4x50_standalone_read(words);
|
||||||
|
|
||||||
if (no_words > 0) {
|
if (no_words > 0) {
|
||||||
|
|
||||||
|
@ -293,11 +243,7 @@ void RunMod(void) {
|
||||||
|
|
||||||
for (int i = 0; i < no_words; i++) {
|
for (int i = 0; i < no_words; i++) {
|
||||||
|
|
||||||
if (strip_check_parities(data[i], &word))
|
sprintf((char *)entry, " %2i -> 0x%08"PRIx32"", i + 1, words[i]);
|
||||||
sprintf((char *)entry, " %2i -> 0x%08"PRIx32" (parity check ok)", i + 1, word);
|
|
||||||
else
|
|
||||||
sprintf((char *)entry, " %2i -> 0x%08"PRIx32" (parity check failed)", i + 1, word);
|
|
||||||
|
|
||||||
Dbprintf("%s", entry);
|
Dbprintf("%s", entry);
|
||||||
strcat((char *)entry, "\n");
|
strcat((char *)entry, "\n");
|
||||||
append(LF_EM4X50COLLECT_LOGFILE, entry, strlen((char *)entry));
|
append(LF_EM4X50COLLECT_LOGFILE, entry, strlen((char *)entry));
|
||||||
|
|
301
armsrc/em4x50.c
301
armsrc/em4x50.c
|
@ -15,50 +15,6 @@
|
||||||
#include "commonutil.h"
|
#include "commonutil.h"
|
||||||
#include "em4x50.h"
|
#include "em4x50.h"
|
||||||
|
|
||||||
// 4 data bytes
|
|
||||||
// + byte with row parities
|
|
||||||
// + column parity byte
|
|
||||||
// + byte with stop bit
|
|
||||||
|
|
||||||
static em4x50_tag_t tag = {
|
|
||||||
.sectors = {
|
|
||||||
[0] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // password
|
|
||||||
[1] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // protection word
|
|
||||||
[2] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // control word
|
|
||||||
[3] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[4] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[5] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[7] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[9] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[10] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[11] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[12] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[13] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[14] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[15] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[17] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[18] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[19] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[20] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[21] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[22] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[23] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[24] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[25] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[26] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[27] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[28] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[29] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[30] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[31] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // user
|
|
||||||
[32] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // device serial number
|
|
||||||
[33] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, // device identification
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK)
|
||||||
// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
|
// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz
|
||||||
// EM4x50 units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
|
// EM4x50 units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier)
|
||||||
|
@ -93,6 +49,7 @@ static em4x50_tag_t tag = {
|
||||||
#define EM4X50_COMMAND_TIMEOUT 5000
|
#define EM4X50_COMMAND_TIMEOUT 5000
|
||||||
#define FPGA_TIMER_0 0
|
#define FPGA_TIMER_0 0
|
||||||
|
|
||||||
|
static uint32_t em4x50_tag[34] = {0x0};
|
||||||
int gHigh = 0;
|
int gHigh = 0;
|
||||||
int gLow = 0;
|
int gLow = 0;
|
||||||
|
|
||||||
|
@ -100,27 +57,7 @@ int gLow = 0;
|
||||||
|
|
||||||
static void init_tag(void) {
|
static void init_tag(void) {
|
||||||
|
|
||||||
// iceman: memset(tag.sectors, 0x00, sizeof));
|
memset(em4x50_tag, 0x00, sizeof(em4x50_tag));
|
||||||
|
|
||||||
// initialize global tag structure
|
|
||||||
for (int i = 0; i < 34; i++)
|
|
||||||
for (int j = 0; j < 7; j++)
|
|
||||||
tag.sectors[i][j] = 0x00;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t bits2byte(uint8_t *bits, int length) {
|
|
||||||
|
|
||||||
// converts <length> separate bits into a single "byte"
|
|
||||||
uint8_t byte = 0;
|
|
||||||
for (int i = 0; i < length; i++) {
|
|
||||||
|
|
||||||
byte |= bits[i];
|
|
||||||
|
|
||||||
if (i != length - 1)
|
|
||||||
byte <<= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return byte;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void msb2lsb_word(uint8_t *word) {
|
static void msb2lsb_word(uint8_t *word) {
|
||||||
|
@ -139,31 +76,6 @@ static void msb2lsb_word(uint8_t *word) {
|
||||||
word[3] = buff[3];
|
word[3] = buff[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void save_word(int pos, uint8_t bits[EM4X50_TAG_WORD]) {
|
|
||||||
|
|
||||||
// split "raw" word into data, row and column parity bits and stop bit and
|
|
||||||
// save them in global tag structure
|
|
||||||
uint8_t row_parity[4];
|
|
||||||
uint8_t col_parity[8];
|
|
||||||
|
|
||||||
// data and row parities
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
tag.sectors[pos][i] = bits2byte(&bits[9 * i], 8);
|
|
||||||
row_parity[i] = bits[9 * i + 8];
|
|
||||||
}
|
|
||||||
|
|
||||||
tag.sectors[pos][4] = bits2byte(row_parity, 4);
|
|
||||||
|
|
||||||
// column parities
|
|
||||||
for (int i = 0; i < 8; i++)
|
|
||||||
col_parity[i] = bits[36 + i];
|
|
||||||
|
|
||||||
tag.sectors[pos][5] = bits2byte(col_parity, 8);
|
|
||||||
|
|
||||||
// stop bit
|
|
||||||
tag.sectors[pos][6] = bits[44];
|
|
||||||
}
|
|
||||||
|
|
||||||
static void wait_timer(int timer, uint32_t period) {
|
static void wait_timer(int timer, uint32_t period) {
|
||||||
|
|
||||||
// do nothing for <period> using timer <timer>
|
// do nothing for <period> using timer <timer>
|
||||||
|
@ -316,8 +228,6 @@ static int get_next_bit(void) {
|
||||||
|
|
||||||
static uint32_t get_pulse_length(void) {
|
static uint32_t get_pulse_length(void) {
|
||||||
|
|
||||||
// Dbprintf( _CYAN_("4x50 get_pulse_length A") );
|
|
||||||
|
|
||||||
int32_t timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
|
int32_t timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
|
||||||
|
|
||||||
// iterates pulse length (low -> high -> low)
|
// iterates pulse length (low -> high -> low)
|
||||||
|
@ -354,6 +264,7 @@ static uint32_t get_pulse_length(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_pulse_length(uint32_t pl, int length) {
|
static bool check_pulse_length(uint32_t pl, int length) {
|
||||||
|
|
||||||
// check if pulse length <pl> corresponds to given length <length>
|
// check if pulse length <pl> corresponds to given length <length>
|
||||||
return ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) && (pl <= T0 * (length + EM4X50_TAG_TOLERANCE)));
|
return ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) && (pl <= T0 * (length + EM4X50_TAG_TOLERANCE)));
|
||||||
}
|
}
|
||||||
|
@ -612,9 +523,7 @@ bool em4x50_sim_send_word(uint32_t word) {
|
||||||
|
|
||||||
bool em4x50_sim_send_listen_window(void) {
|
bool em4x50_sim_send_listen_window(void) {
|
||||||
|
|
||||||
//int i = 0;
|
|
||||||
uint16_t check = 0;
|
uint16_t check = 0;
|
||||||
//uint8_t test[100] = {0};
|
|
||||||
|
|
||||||
for (int t = 0; t < 5 * EM4X50_T_TAG_FULL_PERIOD; t++) {
|
for (int t = 0; t < 5 * EM4X50_T_TAG_FULL_PERIOD; t++) {
|
||||||
|
|
||||||
|
@ -643,7 +552,7 @@ bool em4x50_sim_send_listen_window(void) {
|
||||||
|
|
||||||
check = 0;
|
check = 0;
|
||||||
|
|
||||||
//wait until SSC_CLK goes LOW
|
// wait until SSC_CLK goes LOW
|
||||||
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
|
while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) {
|
||||||
WDT_HIT();
|
WDT_HIT();
|
||||||
if (check == 1000) {
|
if (check == 1000) {
|
||||||
|
@ -671,8 +580,7 @@ static int request_receive_mode(void) {
|
||||||
// To issue a command we have to find a listen window first.
|
// To issue a command we have to find a listen window first.
|
||||||
// Because identification and sychronization at the same time is not
|
// Because identification and sychronization at the same time is not
|
||||||
// possible when using pulse lengths a double listen window is used.
|
// possible when using pulse lengths a double listen window is used.
|
||||||
bool bcommand = true;
|
return find_double_listen_window(true);
|
||||||
return find_double_listen_window(bcommand);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool check_ack(bool bliw) {
|
static bool check_ack(bool bliw) {
|
||||||
|
@ -728,90 +636,146 @@ static bool check_ack(bool bliw) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get_word_from_bitstream(uint8_t bits[EM4X50_TAG_WORD]) {
|
static bool extract_parities(uint64_t word, uint32_t *data) {
|
||||||
|
|
||||||
|
// extract and check parities
|
||||||
|
// return result of parity check and extracted plain data
|
||||||
|
|
||||||
|
uint8_t row_parities = 0x0, col_parities = 0x0;
|
||||||
|
uint8_t row_parities_calculated = 0x0, col_parities_calculated = 0x0;
|
||||||
|
|
||||||
|
*data = 0x0;
|
||||||
|
|
||||||
|
// extract plain data (32 bits) from raw word (45 bits)
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
*data <<= 8;
|
||||||
|
*data |= (word >> ((4 - i) * 9 + 1)) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract row parities (4 bits + stop bit) from raw word (45 bits)
|
||||||
|
for (int i = 0; i < 5; i++) {
|
||||||
|
row_parities <<= 1;
|
||||||
|
row_parities |= (word >> ((4 - i) * 9)) & 0x1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract col_parities (8 bits, no stop bit) from raw word (45 bits)
|
||||||
|
col_parities = (word >> 1) & 0xFF;
|
||||||
|
|
||||||
|
// check extracted parities against extracted data
|
||||||
|
|
||||||
|
// calculate row parities from data
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
row_parities_calculated <<= 1;
|
||||||
|
for (int j = 0; j < 8; j++) {
|
||||||
|
row_parities_calculated ^= (*data >> ((3 - i) * 8 + (7 - j))) & 0x1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// add stop bit (always zero)
|
||||||
|
row_parities_calculated <<= 1;
|
||||||
|
|
||||||
|
// calculate column parities from data
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
col_parities_calculated <<= 1;
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
col_parities_calculated ^= (*data >> ((3 - j) * 8 + (7 - i))) & 0x1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((row_parities == row_parities_calculated) && (col_parities == col_parities_calculated))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_word_from_bitstream(uint32_t *data) {
|
||||||
|
|
||||||
// decodes one word by evaluating pulse lengths and previous bit;
|
// decodes one word by evaluating pulse lengths and previous bit;
|
||||||
// word must have 45 bits in total:
|
// word must have 45 bits in total:
|
||||||
// 32 data bits + 4 row parity bits + 8 column parity bits + 1 stop bit
|
// 32 data bits + 4 row parity bits + 8 column parity bits + 1 stop bit
|
||||||
|
|
||||||
bool bbitchange = false;
|
bool bitchange = false;
|
||||||
int i = 0;
|
int cnt = 0;
|
||||||
uint32_t pl = 0;
|
uint32_t pl = 0;
|
||||||
|
uint64_t word = 0x0;
|
||||||
|
|
||||||
|
*data = 0x0;
|
||||||
|
|
||||||
// initial bit value depends on last pulse length of listen window
|
// initial bit value depends on last pulse length of listen window
|
||||||
pl = get_pulse_length();
|
pl = get_pulse_length();
|
||||||
if (check_pulse_length(pl, 3 * EM4X50_T_TAG_HALF_PERIOD)) {
|
if (check_pulse_length(pl, 3 * EM4X50_T_TAG_HALF_PERIOD)) {
|
||||||
|
|
||||||
// pulse length = 1.5
|
// pulse length = 1.5
|
||||||
bits[0] = 1;
|
word = 0x1;
|
||||||
|
|
||||||
} else if (check_pulse_length(pl, 2 * EM4X50_T_TAG_FULL_PERIOD)) {
|
} else if (check_pulse_length(pl, 2 * EM4X50_T_TAG_FULL_PERIOD)) {
|
||||||
|
|
||||||
// pulse length = 2
|
// pulse length = 2
|
||||||
bits[0] = 0;
|
bitchange = true;
|
||||||
bbitchange = true;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// pulse length = 2.5
|
// pulse length = 2.5
|
||||||
bits[0] = 0;
|
word = 0x1;
|
||||||
bits[1] = 1;
|
cnt++;
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// identify remaining bits based on pulse lengths
|
// identify remaining bits based on pulse lengths
|
||||||
// between two listen windows only pulse lengths of 1, 1.5 and 2 are possible
|
// between two listen windows only pulse lengths of 1, 1.5 and 2 are possible
|
||||||
while (BUTTON_PRESS() == false) {
|
while (true) {
|
||||||
|
|
||||||
i++;
|
cnt++;
|
||||||
|
word <<= 1;
|
||||||
|
|
||||||
pl = get_pulse_length();
|
pl = get_pulse_length();
|
||||||
|
|
||||||
if (check_pulse_length(pl, EM4X50_T_TAG_FULL_PERIOD)) {
|
if (check_pulse_length(pl, EM4X50_T_TAG_FULL_PERIOD)) {
|
||||||
|
|
||||||
// pulse length = 1 -> keep former bit value
|
// pulse length = 1 -> keep former bit value
|
||||||
bits[i] = bits[i - 1];
|
word |= (word >> 1) & 0x1;
|
||||||
|
|
||||||
} else if (check_pulse_length(pl, 3 * EM4X50_T_TAG_HALF_PERIOD)) {
|
} else if (check_pulse_length(pl, 3 * EM4X50_T_TAG_HALF_PERIOD)) {
|
||||||
|
|
||||||
// pulse length = 1.5 -> decision on bit change
|
// pulse length = 1.5 -> decision on bit change
|
||||||
|
|
||||||
if (bbitchange) {
|
if (bitchange) {
|
||||||
|
|
||||||
// if number of pulse lengths with 1.5 periods is even -> add bit
|
// if number of pulse lengths with 1.5 periods is even -> add bit
|
||||||
bits[i] = (bits[i - 1] == 1) ? 1 : 0;
|
word |= (word >> 1) & 0x1;
|
||||||
|
word <<= 1;
|
||||||
|
|
||||||
// pulse length of 1.5 changes bit value
|
// pulse length of 1.5 changes bit value
|
||||||
bits[i + 1] = (bits[i] == 1) ? 0 : 1;
|
word |= ((word >> 1) & 0x1) ^ 0x1;
|
||||||
i++;
|
cnt++;
|
||||||
|
|
||||||
// next time add only one bit
|
// next time add only one bit
|
||||||
bbitchange = false;
|
bitchange = false;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
bits[i] = (bits[i - 1] == 1) ? 0 : 1;
|
word |= ((word >> 1) & 0x1) ^ 0x1;
|
||||||
|
|
||||||
// next time two bits have to be added
|
// next time two bits have to be added
|
||||||
bbitchange = true;
|
bitchange = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (check_pulse_length(pl, 2 * EM4X50_T_TAG_FULL_PERIOD)) {
|
} else if (check_pulse_length(pl, 2 * EM4X50_T_TAG_FULL_PERIOD)) {
|
||||||
|
|
||||||
// pulse length of 2 means: adding 2 bits "01"
|
// pulse length of 2 means: adding 2 bits "01"
|
||||||
bits[i] = 0;
|
cnt++;
|
||||||
bits[i + 1] = 1;
|
|
||||||
i++;
|
word <<= 1;
|
||||||
|
word |= 0x1;
|
||||||
|
|
||||||
} else if (check_pulse_length(pl, 3 * EM4X50_T_TAG_FULL_PERIOD)) {
|
} else if (check_pulse_length(pl, 3 * EM4X50_T_TAG_FULL_PERIOD)) {
|
||||||
|
|
||||||
// pulse length of 3 indicates listen window -> clear last
|
// pulse length of 3 indicates listen window -> clear last
|
||||||
// bit (= 0) and return
|
// bit (= 0) and return (without parities)
|
||||||
return --i;
|
word >>= 2;
|
||||||
|
return (extract_parities(word, data)) ? --cnt : 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
@ -877,14 +841,14 @@ static bool standard_read(int *now) {
|
||||||
// (standard read mode); number of read words is saved in <now>
|
// (standard read mode); number of read words is saved in <now>
|
||||||
|
|
||||||
int fwr = *now;
|
int fwr = *now;
|
||||||
uint8_t bits[EM4X50_TAG_WORD] = {0};
|
uint32_t data = 0x0;
|
||||||
|
|
||||||
// start with the identification of two succsessive listening windows
|
// start with the identification of two succsessive listening windows
|
||||||
if (find_double_listen_window(false)) {
|
if (find_double_listen_window(false)) {
|
||||||
|
|
||||||
// read and save words until following double listen window is detected
|
// read and save words until following double listen window is detected
|
||||||
while (get_word_from_bitstream(bits) == EM4X50_TAG_WORD)
|
while (get_word_from_bitstream(&data) == EM4X50_TAG_WORD)
|
||||||
save_word((*now)++, bits);
|
em4x50_tag[(*now)++] = data;
|
||||||
|
|
||||||
// number of detected words
|
// number of detected words
|
||||||
*now -= fwr;
|
*now -= fwr;
|
||||||
|
@ -942,7 +906,6 @@ void em4x50_info(em4x50_data_t *etd) {
|
||||||
bool bsuccess = false, blogin = false;
|
bool bsuccess = false, blogin = false;
|
||||||
uint8_t status = 0;
|
uint8_t status = 0;
|
||||||
uint8_t addresses[] = {0x00, 0x00, 0x21, 0x00}; // fwr = 0, lwr = 33
|
uint8_t addresses[] = {0x00, 0x00, 0x21, 0x00}; // fwr = 0, lwr = 33
|
||||||
uint8_t password[] = {0x00, 0x00, 0x00, 0x00}; // default password
|
|
||||||
|
|
||||||
init_tag();
|
init_tag();
|
||||||
em4x50_setup_read();
|
em4x50_setup_read();
|
||||||
|
@ -955,11 +918,6 @@ void em4x50_info(em4x50_data_t *etd) {
|
||||||
// try to login with given password
|
// try to login with given password
|
||||||
blogin = login(etd->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);
|
||||||
|
@ -967,8 +925,11 @@ void em4x50_info(em4x50_data_t *etd) {
|
||||||
|
|
||||||
status = (bsuccess << 1) + blogin;
|
status = (bsuccess << 1) + blogin;
|
||||||
|
|
||||||
|
for (int i = 0; i < 34; i++)
|
||||||
|
Dbprintf("em4x5_tag[%i] = %08x", i, em4x50_tag[i]);
|
||||||
|
|
||||||
lf_finalize();
|
lf_finalize();
|
||||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
reply_ng(CMD_ACK, status, (uint8_t *)em4x50_tag, 136);
|
||||||
}
|
}
|
||||||
|
|
||||||
void em4x50_read(em4x50_data_t *etd) {
|
void em4x50_read(em4x50_data_t *etd) {
|
||||||
|
@ -1013,7 +974,7 @@ void em4x50_read(em4x50_data_t *etd) {
|
||||||
|
|
||||||
LOW(GPIO_SSC_DOUT);
|
LOW(GPIO_SSC_DOUT);
|
||||||
lf_finalize();
|
lf_finalize();
|
||||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
reply_ng(CMD_ACK, status, (uint8_t *)em4x50_tag, 136);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
@ -1102,7 +1063,8 @@ void em4x50_write(em4x50_data_t *etd) {
|
||||||
|
|
||||||
bool bsuccess = false, blogin = false;
|
bool bsuccess = false, blogin = false;
|
||||||
uint8_t status = 0;
|
uint8_t status = 0;
|
||||||
uint8_t word[4] = {0x00, 0x00, 0x00, 0x00};
|
//uint8_t word[4] = {0x00, 0x00, 0x00, 0x00};
|
||||||
|
uint32_t word = 0x0;
|
||||||
uint8_t addresses[4] = {0x00, 0x00, 0x00, 0x00};
|
uint8_t addresses[4] = {0x00, 0x00, 0x00, 0x00};
|
||||||
|
|
||||||
init_tag();
|
init_tag();
|
||||||
|
@ -1133,15 +1095,27 @@ void em4x50_write(em4x50_data_t *etd) {
|
||||||
if (selective_read(addresses)) {
|
if (selective_read(addresses)) {
|
||||||
|
|
||||||
// compare with given word
|
// compare with given word
|
||||||
|
word = em4x50_tag[etd->address];
|
||||||
|
/*
|
||||||
word[0] = tag.sectors[etd->address][0];
|
word[0] = tag.sectors[etd->address][0];
|
||||||
word[1] = tag.sectors[etd->address][1];
|
word[1] = tag.sectors[etd->address][1];
|
||||||
word[2] = tag.sectors[etd->address][2];
|
word[2] = tag.sectors[etd->address][2];
|
||||||
word[3] = tag.sectors[etd->address][3];
|
word[3] = tag.sectors[etd->address][3];
|
||||||
msb2lsb_word(word);
|
*/
|
||||||
|
reflect32(word);
|
||||||
|
|
||||||
bsuccess = true;
|
//bsuccess = true;
|
||||||
for (int i = 0; i < 4; i++)
|
//for (int i = 0; i < 4; i++)
|
||||||
bsuccess &= (word[i] == etd->word[i]) ? true : false;
|
// bsuccess &= (word[i] == etd->word[i]) ? true : false;
|
||||||
|
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 = (word == tmp);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1151,7 +1125,7 @@ void em4x50_write(em4x50_data_t *etd) {
|
||||||
status = (bsuccess << 1) + blogin;
|
status = (bsuccess << 1) + blogin;
|
||||||
|
|
||||||
lf_finalize();
|
lf_finalize();
|
||||||
reply_ng(CMD_ACK, status, (uint8_t *)tag.sectors, 238);
|
reply_ng(CMD_ACK, status, (uint8_t *)em4x50_tag, 136);
|
||||||
}
|
}
|
||||||
|
|
||||||
void em4x50_write_password(em4x50_data_t *etd) {
|
void em4x50_write_password(em4x50_data_t *etd) {
|
||||||
|
@ -1223,8 +1197,7 @@ void em4x50_wipe(em4x50_data_t *etd) {
|
||||||
// check if everything is zero
|
// check if everything is zero
|
||||||
bsuccess = true;
|
bsuccess = true;
|
||||||
for (int i = 1; i <= EM4X50_NO_WORDS - 3; i++)
|
for (int i = 1; i <= EM4X50_NO_WORDS - 3; i++)
|
||||||
for (int j = 0; j < 4; j++)
|
bsuccess &= (em4x50_tag[i] == 0) ? true : false;
|
||||||
bsuccess &= (tag.sectors[i][j] == 0) ? true : false;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1244,7 +1217,7 @@ void em4x50_wipe(em4x50_data_t *etd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
lf_finalize();
|
lf_finalize();
|
||||||
reply_ng(CMD_ACK, bsuccess, (uint8_t *)tag.sectors, 238);
|
reply_ng(CMD_ACK, bsuccess, (uint8_t *)em4x50_tag, 136);
|
||||||
}
|
}
|
||||||
|
|
||||||
void em4x50_reset(void) {
|
void em4x50_reset(void) {
|
||||||
|
@ -1364,49 +1337,33 @@ int em4x50_standalone_brute(uint32_t start, uint32_t stop, uint32_t *pwd) {
|
||||||
|
|
||||||
em4x50_setup_read();
|
em4x50_setup_read();
|
||||||
|
|
||||||
if (get_signalproperties() && find_em4x50_tag()) {
|
if (get_signalproperties() && find_em4x50_tag())
|
||||||
status = brute(start, stop, pwd);
|
status = brute(start, stop, pwd);
|
||||||
} else {
|
else
|
||||||
status = PM3_ETIMEOUT;
|
status = PM3_ETIMEOUT;
|
||||||
}
|
|
||||||
|
|
||||||
lf_finalize();
|
lf_finalize();
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
int em4x50_standalone_read(uint64_t *words) {
|
int em4x50_standalone_read(uint32_t *words) {
|
||||||
|
|
||||||
int now = 0;
|
int now = 0;
|
||||||
uint8_t bits[EM4X50_TAG_WORD];
|
|
||||||
|
|
||||||
em4x50_setup_read();
|
em4x50_setup_read();
|
||||||
|
|
||||||
if (get_signalproperties() && find_em4x50_tag()) {
|
if (get_signalproperties() && find_em4x50_tag())
|
||||||
|
if (find_double_listen_window(false))
|
||||||
if (find_double_listen_window(false)) {
|
while (get_word_from_bitstream(&words[now]) == EM4X50_TAG_WORD)
|
||||||
|
|
||||||
memset(bits, 0, sizeof(bits));
|
|
||||||
|
|
||||||
while (get_word_from_bitstream(bits) == EM4X50_TAG_WORD) {
|
|
||||||
words[now] = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < EM4X50_TAG_WORD; i++) {
|
|
||||||
words[now] <<= 1;
|
|
||||||
words[now] += bits[i] & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
now++;
|
now++;
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return now;
|
return now;
|
||||||
}
|
}
|
||||||
|
|
||||||
void em4x50_watch() {
|
void em4x50_watch() {
|
||||||
|
|
||||||
// reads continuously and displays standard reads of tag
|
// read continuously and display standard reads of tag
|
||||||
|
|
||||||
int now = 0;
|
int now = 0;
|
||||||
|
|
||||||
|
@ -1429,16 +1386,8 @@ void em4x50_watch() {
|
||||||
for (int i = 0; i < now; i++) {
|
for (int i = 0; i < now; i++) {
|
||||||
|
|
||||||
Dbprintf("EM4x50 TAG ID: "
|
Dbprintf("EM4x50 TAG ID: "
|
||||||
_GREEN_("%02x%02x%02x%02x") " (msb) - "
|
_GREEN_("%08x") " (msb) - " _GREEN_("%08x") " (lsb)",
|
||||||
_GREEN_("%02x%02x%02x%02x") " (lsb)",
|
em4x50_tag[i], reflect32(em4x50_tag[i]));
|
||||||
tag.sectors[i][0],
|
|
||||||
tag.sectors[i][1],
|
|
||||||
tag.sectors[i][2],
|
|
||||||
tag.sectors[i][3],
|
|
||||||
reflect8(tag.sectors[i][3]),
|
|
||||||
reflect8(tag.sectors[i][2]),
|
|
||||||
reflect8(tag.sectors[i][1]),
|
|
||||||
reflect8(tag.sectors[i][0]));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
#include "../include/em4x50.h"
|
#include "../include/em4x50.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t sectors[34][7];
|
uint8_t sectors[34][4];
|
||||||
} em4x50_tag_t;
|
} em4x50_tag_t;
|
||||||
|
|
||||||
int em4x50_standalone_read(uint64_t *words);
|
int em4x50_standalone_read(uint32_t *words);
|
||||||
int em4x50_standalone_brute(uint32_t start, uint32_t stop, uint32_t *pwd);
|
int em4x50_standalone_brute(uint32_t start, uint32_t stop, uint32_t *pwd);
|
||||||
bool em4x50_sim_send_listen_window(void);
|
bool em4x50_sim_send_listen_window(void);
|
||||||
bool em4x50_sim_send_word(uint32_t word);
|
bool em4x50_sim_send_word(uint32_t word);
|
||||||
|
|
|
@ -145,60 +145,13 @@ static int usage_lf_em4x50_watch(void) {
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void prepare_result(const uint8_t *byte, int fwr, int lwr, em4x50_word_t *words) {
|
static void prepare_result(const uint8_t *data, int fwr, int lwr, em4x50_word_t *words) {
|
||||||
|
|
||||||
// restructure received result in "em4x50_word_t" structure and check all
|
// restructure received result in "em4x50_word_t" structure
|
||||||
// parities including stop bit; result of each check is stored in structure
|
|
||||||
|
|
||||||
int p = 0, c[8] = {0, 0, 0, 0, 0, 0, 0, 0};
|
for (int i = fwr; i <= lwr; i++)
|
||||||
|
for (int j = 0; j < 4; j++)
|
||||||
for (int i = fwr; i <= lwr; i++) {
|
words[i].byte[j] = data[i * 4 + (3 - j)];
|
||||||
|
|
||||||
words[i].stopparity = true;
|
|
||||||
words[i].parity = true;
|
|
||||||
|
|
||||||
for (int j = 0; j < 8; j++)
|
|
||||||
c[j] = 0;
|
|
||||||
|
|
||||||
for (int j = 0; j < 4; j++) {
|
|
||||||
words[i].byte[j] = byte[i * 7 + j];
|
|
||||||
words[i].row_parity[j] = (byte[i * 7 + 4] >> (3 - j)) & 1;
|
|
||||||
|
|
||||||
// collect parities
|
|
||||||
p = 0;
|
|
||||||
|
|
||||||
for (int k = 0; k < 8; k++) {
|
|
||||||
|
|
||||||
// row parity
|
|
||||||
p ^= (words[i].byte[j] >> k) & 1;
|
|
||||||
|
|
||||||
// column parity
|
|
||||||
c[k] ^= (words[i].byte[j] >> (7 - k)) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check row parities
|
|
||||||
words[i].rparity[j] = (words[i].row_parity[j] == p) ? true : false;
|
|
||||||
|
|
||||||
if (!words[i].rparity[j])
|
|
||||||
words[i].parity = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check column parities
|
|
||||||
words[i].col_parity = byte[i * 7 + 5];
|
|
||||||
|
|
||||||
for (int j = 0; j < 8; j++) {
|
|
||||||
words[i].cparity[j] = (((words[i].col_parity >> (7 - j)) & 1) == c[j]) ? true : false;
|
|
||||||
|
|
||||||
if (!words[i].cparity[j])
|
|
||||||
words[i].parity = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// check stop bit
|
|
||||||
words[i].stopbit = byte[i * 7 + 6] & 1;
|
|
||||||
|
|
||||||
if (words[i].stopbit == 1)
|
|
||||||
words[i].stopparity = false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -44,11 +44,8 @@ typedef struct {
|
||||||
bool addr_given;
|
bool addr_given;
|
||||||
bool pwd_given;
|
bool pwd_given;
|
||||||
bool newpwd_given;
|
bool newpwd_given;
|
||||||
uint8_t carrier;
|
|
||||||
uint8_t byte;
|
|
||||||
uint8_t password[4];
|
uint8_t password[4];
|
||||||
uint8_t new_password[4];
|
uint8_t new_password[4];
|
||||||
uint8_t addresses[4];
|
|
||||||
uint8_t address;
|
uint8_t address;
|
||||||
uint8_t word[4];
|
uint8_t word[4];
|
||||||
uint32_t start_password;
|
uint32_t start_password;
|
||||||
|
@ -58,13 +55,6 @@ typedef struct {
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint8_t byte[4];
|
uint8_t byte[4];
|
||||||
uint8_t row_parity[4];
|
|
||||||
uint8_t col_parity;
|
|
||||||
uint8_t stopbit;
|
|
||||||
bool rparity[4];
|
|
||||||
bool cparity[8];
|
|
||||||
bool stopparity;
|
|
||||||
bool parity;
|
|
||||||
} em4x50_word_t;
|
} em4x50_word_t;
|
||||||
|
|
||||||
#endif /* EM4X50_H__ */
|
#endif /* EM4X50_H__ */
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue