Add lf em 4x70 autorecover

Also:
* common.h: Increase safety of some of the macros.
  Parenthesizing the macro parameters ... a best practice.
* firmware: partially-tracked source of "extra bits" messages.
  Add a TODO comment for further study.
* Improve reliability of `lf em 4x70 writekey`
  Authenticate w/new key after it is written.
  Particularly important for glass modules,
  or other tags with weaker coupling.
This commit is contained in:
Henry Gabryjelski 2024-03-11 17:12:45 -07:00
commit 160d61682b
4 changed files with 940 additions and 324 deletions

View file

@ -581,6 +581,11 @@ static bool send_command_and_read(uint8_t command, uint8_t *bytes, size_t length
Dbprintf("Invalid data received length: %d, expected %d", len, out_length_bits); Dbprintf("Invalid data received length: %d, expected %d", len, out_length_bits);
return false; return false;
} }
// TODO: Figure out why getting an extra bit (quite often) here
// e.g., write block and info commands both reach here and output:
// [#] Should have a multiple of 8 bits, was sent 33
// [#] Should have a multiple of 8 bits, was sent 65
// Extra bits are currently just dropped, with no ill effect noticed.
bits2bytes(bits, len, bytes); bits2bytes(bits, len, bytes);
return true; return true;
} }
@ -903,10 +908,12 @@ void em4x70_write_key(const em4x70_data_t *etd, bool ledcontrol) {
break; break;
} }
} }
// TODO: Ideally here we would perform a test authentication // The client now has support for test authentication after
// to ensure the new key was written correctly. This is // writing a new key, thus allowing to verify that the new
// what the datasheet suggests. We can't do that until // key was written correctly. This is what the datasheet
// we have the crypto algorithm implemented. // suggests. Not currently implemented in the firmware,
// although ID48LIB has no dependencies that would prevent
// use within the firmware layer.
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -148,16 +148,16 @@ extern bool g_tearoff_enabled;
// convert 2 bytes to U16 in little endian // convert 2 bytes to U16 in little endian
#ifndef BYTES2UINT16 #ifndef BYTES2UINT16
# define BYTES2UINT16(x) ((x[1] << 8) | (x[0])) # define BYTES2UINT16(x) (((x)[1] << 8) | ((x)[0]))
#endif #endif
// convert 4 bytes to U32 in little endian // convert 4 bytes to U32 in little endian
#ifndef BYTES2UINT32 #ifndef BYTES2UINT32
# define BYTES2UINT32(x) ((x[3] << 24) | (x[2] << 16) | (x[1] << 8) | (x[0])) # define BYTES2UINT32(x) (((x)[3] << 24) | ((x)[2] << 16) | ((x)[1] << 8) | ((x)[0]))
#endif #endif
// convert 4 bytes to U32 in big endian // convert 4 bytes to U32 in big endian
#ifndef BYTES2UINT32_BE #ifndef BYTES2UINT32_BE
# define BYTES2UINT32_BE(x) ((x[0] << 24) | (x[1] << 16) | (x[2] << 8) | (x[3])) # define BYTES2UINT32_BE(x) (((x)[0] << 24) | ((x)[1] << 16) | ((x)[2] << 8) | ((x)[3]))
#endif #endif
@ -174,7 +174,7 @@ extern bool g_tearoff_enabled;
#endif #endif
#ifndef CRUMB #ifndef CRUMB
# define CRUMB(b,p) (((b & (0x3 << p) ) >> p ) & 0xF) # define CRUMB(b,p) ((((b) & (0x3 << (p)) ) >> (p) ) & 0xF)
#endif #endif
#ifndef SWAP_NIBBLE #ifndef SWAP_NIBBLE
@ -183,18 +183,18 @@ extern bool g_tearoff_enabled;
// Binary Encoded Digit // Binary Encoded Digit
#ifndef BCD2DEC #ifndef BCD2DEC
# define BCD2DEC(bcd) HornerScheme(bcd, 0x10, 10) # define BCD2DEC(bcd) HornerScheme((bcd), 0x10, 10)
#endif #endif
#ifndef DEC2BCD #ifndef DEC2BCD
# define DEC2BCD(dec) HornerScheme(dec, 10, 0x10) # define DEC2BCD(dec) HornerScheme((dec), 10, 0x10)
#endif #endif
// bit stream operations // bit stream operations
#define TEST_BIT(data, i) (*(data + (i / 8)) >> (7 - (i % 8))) & 1 #define TEST_BIT(data, i) (*((data) + ((i) / 8)) >> (7 - ((i) % 8))) & 1
#define SET_BIT(data, i) *(data + (i / 8)) |= (1 << (7 - (i % 8))) #define SET_BIT(data, i) *((data) + ((i) / 8)) |= (1 << (7 - ((i) % 8)))
#define CLEAR_BIT(data, i) *(data + (i / 8)) &= ~(1 << (7 - (i % 8))) #define CLEAR_BIT(data, i) *((data) + ((i) / 8)) &= ~(1 << (7 - ((i) % 8)))
#define FLIP_BIT(data, i) *(data + (i / 8)) ^= (1 << (7 - (i % 8))) #define FLIP_BIT(data, i) *((data) + ((i) / 8)) ^= (1 << (7 - ((i) % 8)))
// time for decompressing and loading the image to the FPGA // time for decompressing and loading the image to the FPGA
#define FPGA_LOAD_WAIT_TIME (1500) #define FPGA_LOAD_WAIT_TIME (1500)

View file

@ -39,6 +39,7 @@ typedef struct {
// Used for writing address // Used for writing address
uint8_t address; uint8_t address;
// ISSUE: Presumes target is little-endian
uint16_t word; uint16_t word;
// PIN to unlock // PIN to unlock
@ -53,6 +54,7 @@ typedef struct {
uint8_t crypt_key[12]; uint8_t crypt_key[12];
// used for bruteforce the partial key // used for bruteforce the partial key
// ISSUE: Presumes target is little-endian
uint16_t start_key; uint16_t start_key;
} em4x70_data_t; } em4x70_data_t;