Merge pull request #1109 from cmolson/em4x70-receive

em4x70: Update receive function with expected bits to receive.
This commit is contained in:
Iceman 2020-12-15 15:06:38 +01:00 committed by GitHub
commit 631d6deed3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23

View file

@ -42,7 +42,7 @@ static bool command_parity = true;
#define EM4X70_T_TAG_TIMEOUT (4 * EM4X70_T_TAG_FULL_PERIOD) // Timeout if we ever get a pulse longer than this #define EM4X70_T_TAG_TIMEOUT (4 * EM4X70_T_TAG_FULL_PERIOD) // Timeout if we ever get a pulse longer than this
#define EM4X70_T_WAITING_FOR_LIW 50 // Pulses to wait for listen window #define EM4X70_T_WAITING_FOR_LIW 50 // Pulses to wait for listen window
#define EM4X70_T_READ_HEADER_LEN 16 // Read header length (16 bit periods)
#define EM4X70_COMMAND_RETRIES 5 // Attempts to send/read command #define EM4X70_COMMAND_RETRIES 5 // Attempts to send/read command
#define EM4X70_MAX_RECEIVE_LENGTH 96 // Maximum bits to expect from any command #define EM4X70_MAX_RECEIVE_LENGTH 96 // Maximum bits to expect from any command
@ -73,7 +73,7 @@ static bool command_parity = true;
static uint8_t bits2byte(const uint8_t *bits, int length); static uint8_t bits2byte(const uint8_t *bits, int length);
static void bits2bytes(const uint8_t *bits, int length, uint8_t *out); static void bits2bytes(const uint8_t *bits, int length, uint8_t *out);
static int em4x70_receive(uint8_t *bits); static int em4x70_receive(uint8_t *bits, size_t length);
static bool find_listen_window(bool command); static bool find_listen_window(bool command);
static void init_tag(void) { static void init_tag(void) {
@ -329,8 +329,8 @@ static int authenticate(const uint8_t *rnd, const uint8_t *frnd, uint8_t *respon
// Receive header, 20-bit g(RN), LIW // Receive header, 20-bit g(RN), LIW
uint8_t grnd[EM4X70_MAX_RECEIVE_LENGTH] = {0}; uint8_t grnd[EM4X70_MAX_RECEIVE_LENGTH] = {0};
int num = em4x70_receive(grnd); int num = em4x70_receive(grnd, 20);
if (num < 10) { if (num < 20) {
Dbprintf("Auth failed"); Dbprintf("Auth failed");
return PM3_ESOFT; return PM3_ESOFT;
} }
@ -369,7 +369,7 @@ static int send_pin(const uint32_t pin) {
WaitTicks(EM4X70_T_TAG_WEE); WaitTicks(EM4X70_T_TAG_WEE);
// <-- Receive header + ID // <-- Receive header + ID
uint8_t tag_id[EM4X70_MAX_RECEIVE_LENGTH]; uint8_t tag_id[EM4X70_MAX_RECEIVE_LENGTH];
int num = em4x70_receive(tag_id); int num = em4x70_receive(tag_id, 32);
if (num < 32) { if (num < 32) {
Dbprintf("Invalid ID Received"); Dbprintf("Invalid ID Received");
return PM3_ESOFT; return PM3_ESOFT;
@ -480,7 +480,7 @@ static uint8_t bits2byte(const uint8_t *bits, int length) {
return byte; return byte;
} }
static bool send_command_and_read(uint8_t command, uint8_t resp_len_bits, uint8_t *out_bytes) { static bool send_command_and_read(uint8_t command, uint8_t *bytes, size_t length) {
int retries = EM4X70_COMMAND_RETRIES; int retries = EM4X70_COMMAND_RETRIES;
while (retries) { while (retries) {
@ -488,13 +488,14 @@ static bool send_command_and_read(uint8_t command, uint8_t resp_len_bits, uint8_
if (find_listen_window(true)) { if (find_listen_window(true)) {
uint8_t bits[EM4X70_MAX_RECEIVE_LENGTH] = {0}; uint8_t bits[EM4X70_MAX_RECEIVE_LENGTH] = {0};
size_t out_length_bits = length * 8;
em4x70_send_nibble(command, command_parity); em4x70_send_nibble(command, command_parity);
int len = em4x70_receive(bits); int len = em4x70_receive(bits, out_length_bits);
if (len < resp_len_bits) { if (len < out_length_bits) {
Dbprintf("Invalid data received length: %d", len); Dbprintf("Invalid data received length: %d, expected %d", len, out_length_bits);
return false; return false;
} }
bits2bytes(bits, len, out_bytes); bits2bytes(bits, len, bytes);
return true; return true;
} }
} }
@ -510,7 +511,7 @@ static bool send_command_and_read(uint8_t command, uint8_t resp_len_bits, uint8_
*/ */
static bool em4x70_read_id(void) { static bool em4x70_read_id(void) {
return send_command_and_read(EM4X70_COMMAND_ID, 32, &tag.data[4]); return send_command_and_read(EM4X70_COMMAND_ID, &tag.data[4], 4);
} }
@ -521,7 +522,7 @@ static bool em4x70_read_id(void) {
*/ */
static bool em4x70_read_um1(void) { static bool em4x70_read_um1(void) {
return send_command_and_read(EM4X70_COMMAND_UM1, 32, &tag.data[0]); return send_command_and_read(EM4X70_COMMAND_UM1, &tag.data[0], 4);
} }
@ -533,7 +534,7 @@ static bool em4x70_read_um1(void) {
*/ */
static bool em4x70_read_um2(void) { static bool em4x70_read_um2(void) {
return send_command_and_read(EM4X70_COMMAND_UM2, 64, &tag.data[24]); return send_command_and_read(EM4X70_COMMAND_UM2, &tag.data[24], 8);
} }
@ -543,7 +544,7 @@ static bool find_em4x70_Tag(void) {
return find_listen_window(false); return find_listen_window(false);
} }
static int em4x70_receive(uint8_t *bits) { static int em4x70_receive(uint8_t *bits, size_t length) {
uint32_t pl; uint32_t pl;
int bit_pos = 0; int bit_pos = 0;
@ -558,10 +559,8 @@ static int em4x70_receive(uint8_t *bits) {
WaitTicks(6 * EM4X70_T_TAG_FULL_PERIOD); WaitTicks(6 * EM4X70_T_TAG_FULL_PERIOD);
// wait until we get the transition from 1's to 0's which is 1.5 full windows // wait until we get the transition from 1's to 0's which is 1.5 full windows
int pulse_count = 0; for(int i = 0; i < EM4X70_T_READ_HEADER_LEN; i++) {
while (pulse_count < 12) {
pl = get_pulse_length(edge); pl = get_pulse_length(edge);
pulse_count++;
if (check_pulse_length(pl, 3 * EM4X70_T_TAG_HALF_PERIOD)) { if (check_pulse_length(pl, 3 * EM4X70_T_TAG_HALF_PERIOD)) {
foundheader = true; foundheader = true;
break; break;
@ -575,23 +574,26 @@ static int em4x70_receive(uint8_t *bits) {
// Skip next 3 0's, header check consumes the first 0 // Skip next 3 0's, header check consumes the first 0
for (int i = 0; i < 3; i++) { for (int i = 0; i < 3; i++) {
get_pulse_length(edge); // If pulse length is not 1 bit, then abort early
if(!check_pulse_length(get_pulse_length(edge), EM4X70_T_TAG_FULL_PERIOD)) {
return 0;
}
} }
// identify remaining bits based on pulse lengths // identify remaining bits based on pulse lengths
// between listen windows only pulse lengths of 1, 1.5 and 2 are possible // between listen windows only pulse lengths of 1, 1.5 and 2 are possible
while (bit_pos < EM4X70_MAX_RECEIVE_LENGTH) { while (bit_pos < length) {
pl = get_pulse_length(edge); pl = get_pulse_length(edge);
if (check_pulse_length(pl, EM4X70_T_TAG_FULL_PERIOD)) { if (check_pulse_length(pl, EM4X70_T_TAG_FULL_PERIOD)) {
// pulse length = 1 // pulse length 1 -> assign bit
bits[bit_pos++] = edge == FALLING_EDGE ? 1 : 0; bits[bit_pos++] = edge == FALLING_EDGE ? 1 : 0;
} else if (check_pulse_length(pl, 3 * EM4X70_T_TAG_HALF_PERIOD)) { } else if (check_pulse_length(pl, 3 * EM4X70_T_TAG_HALF_PERIOD)) {
// pulse length = 1.5 -> flip edge detection // pulse length 1.5 -> 2 bits + flip edge detection
if (edge == FALLING_EDGE) { if (edge == FALLING_EDGE) {
bits[bit_pos++] = 0; bits[bit_pos++] = 0;
bits[bit_pos++] = 0; bits[bit_pos++] = 0;
@ -604,7 +606,7 @@ static int em4x70_receive(uint8_t *bits) {
} else if (check_pulse_length(pl, 2 * EM4X70_T_TAG_FULL_PERIOD)) { } else if (check_pulse_length(pl, 2 * EM4X70_T_TAG_FULL_PERIOD)) {
// pulse length of 2 // pulse length of 2 -> two bits
if (edge == FALLING_EDGE) { if (edge == FALLING_EDGE) {
bits[bit_pos++] = 0; bits[bit_pos++] = 0;
bits[bit_pos++] = 1; bits[bit_pos++] = 1;
@ -613,16 +615,13 @@ static int em4x70_receive(uint8_t *bits) {
bits[bit_pos++] = 0; bits[bit_pos++] = 0;
} }
} else if (((edge == FALLING_EDGE) && check_pulse_length(pl, (2*EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_FULL_PERIOD)) || } else {
((edge == RISING_EDGE) && check_pulse_length(pl, (2*EM4X70_T_TAG_FULL_PERIOD) + EM4X70_T_TAG_HALF_PERIOD))) { // Listen Window, or invalid bit
break;
// LIW detected (either invert or normal)
return --bit_pos;
} }
} }
// Should not get here return bit_pos;
return --bit_pos;
} }
void em4x70_info(em4x70_data_t *etd) { void em4x70_info(em4x70_data_t *etd) {