This commit is contained in:
iceman1001 2024-03-14 11:26:06 +01:00
commit 94c3bdd91c
17 changed files with 355 additions and 297 deletions

View file

@ -31,13 +31,13 @@
#include <string.h>
#include <stdbool.h>
#if defined(NDEBUG)
#define ASSERT(x) ((void)0)
#define ASSERT(x) ((void)0)
#elif defined(ID48_NO_STDIO)
#define ASSERT(x) ((void)0)
#define ASSERT(x) ((void)0)
#else // neither NDEBUG nor ID48_NO_STDIO defined
#include <stdio.h>
#include <assert.h>
#define ASSERT(x) assert((x))
#include <stdio.h>
#include <assert.h>
#define ASSERT(x) assert((x))
#endif
@ -108,7 +108,7 @@ typedef struct _ID48LIB_FRN {
/// Native format if viewed linearly from frn[0..6].
/// Mapping to the indices used in the research paper,
/// where ( O₂₈ .. O₅₅ ) :== output( s₃₅, k₀₄..k₀₀ (15x 0) ) == grn
///
///
/// then:
/// rn[ 0] :== O₂₈ .. O₃₅
/// rn[ 1] :== O₃₆ .. O₄₃
@ -128,15 +128,15 @@ typedef struct _ID48LIB_GRN {
/// Note: In C++, each parameter would be a reference (not pointer).
/// </remarks>
void id48lib_generator(
const ID48LIB_KEY* key_96bit,
const ID48LIB_NONCE* nonce_56bit,
ID48LIB_FRN* frn28_out,
ID48LIB_GRN* grn20_out
);
const ID48LIB_KEY *key_96bit,
const ID48LIB_NONCE *nonce_56bit,
ID48LIB_FRN *frn28_out,
ID48LIB_GRN *grn20_out
);
/// <summary>
/// Initializes to allow iterative recovery
/// of multiple potential keys. After calling
/// of multiple potential keys. After calling
/// this init() function, can repeatedly call
/// the next() function until it returns false
/// to obtain all potential keys.
@ -165,10 +165,10 @@ void id48lib_generator(
/// Note: In C++, each parameter would be a reference (not pointer).
/// </remarks>
void id48lib_key_recovery_init(
const ID48LIB_KEY* input_partial_key,
const ID48LIB_NONCE* input_nonce,
const ID48LIB_FRN* input_frn,
const ID48LIB_GRN* input_grn
const ID48LIB_KEY *input_partial_key,
const ID48LIB_NONCE *input_nonce,
const ID48LIB_FRN *input_frn,
const ID48LIB_GRN *input_grn
);
/// <summary>
/// This can be repeated called (after calling init())
@ -184,7 +184,7 @@ void id48lib_key_recovery_init(
/// <param name="potential_key_output">
/// When the function returns true, this caller-provided
/// value will be filled with the 96-bit key that, when
/// programmed to the tag, should authenticate against
/// programmed to the tag, should authenticate against
/// the nonce+frn values, with tag returning the grn value.
/// </param>
/// <returns>
@ -195,7 +195,7 @@ void id48lib_key_recovery_init(
/// Note: In C++, each parameter would be a reference (not pointer).
/// </remarks>
bool id48lib_key_recovery_next(
ID48LIB_KEY* potential_key_output
ID48LIB_KEY *potential_key_output
);
#if defined(__cplusplus)

View file

@ -50,7 +50,7 @@ static const uint8_t small_lut_group4[4] = { // aka 32 bits
0x8f, 0x34, 0x52, 0xe9,
};
static inline bool get_bit(const uint8_t* table_start, uint32_t bit_idx) {
static inline bool get_bit(const uint8_t *table_start, uint32_t bit_idx) {
const uint32_t byte = bit_idx / 8u;
const uint8_t mask = 1u << (bit_idx % 8u);
return (table_start[byte] & mask) != 0;
@ -72,7 +72,7 @@ static inline bool get_bit(const uint8_t* table_start, uint32_t bit_idx) {
// so long as the lookup tables are adjusted accordingly.
//
// Which bits are used for which small lookup table indixes?
//
//
// Bit: ₆₃ ₆₂ ₆₁ ₆₀ ₅₉ ₅₈ ₅₇ ₅₆ ₅₅ ₅₄ ₅₃ ₅₂ ₅₁ ₅₀ ₄₉ ₄₈ ₄₇ ₄₆ ₄₅ ₄₄ ₄₃ ₄₂ ₄₁ ₄₀ ₃₉ ₃₈ ₃₇ ₃₆ ₃₅ ₃₄ ₃₃ ₃₂
// Reg: i j r₀₆ r₀₅ r₀₄ r₀₃ r₀₂ r₀₁ r₀₀ m₀₆ m₀₅ m₀₄ m₀₃ m₀₂ m₀₁ m₀₀ l₀₆ l₀₅ l₀₄ l₀₃ l₀₂ l₀₁ l₀₀ g₂₂ g₂₁ g₂₀ g₁₉ g₁₈ g₁₇ g₁₆ g₁₅ g₁₄
// i_v i_v i_v i_v i_v i_v i_v i_v
@ -80,8 +80,8 @@ static inline bool get_bit(const uint8_t* table_start, uint32_t bit_idx) {
// BBB BBB BBB BBB
// CCC CCC CCC CCC
// DDD DDD DDD DDD DDD
//
// Bit: ₃₁ ₃₀ ₂₉ ₂₈ ₂₇ ₂₆ ₂₅ ₂₄ ₂₃ ₂₂ ₂₁ ₂₀ ₁₉ ₁₈ ₁₇ ₁₆ ₁₅ ₁₄ ₁₃ ₁₂ ₁₁ ₁₀ ₀₉ ₀₈ ₀₇ ₀₆ ₀₅ ₀₄ ₀₃ ₀₂ ₀₁ ₀₀
//
// Bit: ₃₁ ₃₀ ₂₉ ₂₈ ₂₇ ₂₆ ₂₅ ₂₄ ₂₃ ₂₂ ₂₁ ₂₀ ₁₉ ₁₈ ₁₇ ₁₆ ₁₅ ₁₄ ₁₃ ₁₂ ₁₁ ₁₀ ₀₉ ₀₈ ₀₇ ₀₆ ₀₅ ₀₄ ₀₃ ₀₂ ₀₁ ₀₀
// Reg: g₁₃ g₁₂ g₁₁ g₁₀ g₀₉ g₀₈ g₀₇ g₀₆ g₀₅ g₀₄ g₀₃ g₀₂ g₀₁ g₀₀ h₁₂ h₁₁ h₁₀ h₀₉ h₀₈ h₀₇ h₀₆ h₀₅ h₀₄ h₀₃ h₀₂ h₀₁ h₀₀ _ a b c 0
// AAA BBB CCC
//
@ -105,7 +105,7 @@ static inline bool get_bit(const uint8_t* table_start, uint32_t bit_idx) {
static bool output_lookup_small_lut(uint32_t output_index) {
if (output_index >= COUNT_OF_POTENTIAL_INPUTS) { return false; }
// 1 1 1 1 1 1 1 1 1 1
// 1 1 1 1 1 1 1 1 1 1
// 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
// Fₒ( a b c l₀ l₂ l₃ l₄ l₅ l₆ m₀ m₁ m₃ m₅ r₀ r₁ r₂ r₃ r₄ r₅ r₆ )

View file

@ -91,8 +91,8 @@ static inline uint64_t reverse_bits_64(uint64_t n) {
#pragma region // id48lib state register
// Bit: ₆₃ ₆₂ ₆₁ ₆₀ ₅₉ ₅₈ ₅₇ ₅₆ ₅₅ ₅₄ ₅₃ ₅₂ ₅₁ ₅₀ ₄₉ ₄₈ ₄₇ ₄₆ ₄₅ ₄₄ ₄₃ ₄₂ ₄₁ ₄₀ ₃₉ ₃₈ ₃₇ ₃₆ ₃₅ ₃₄ ₃₃ ₃₂
// Reg: x x x r₀₆ r₀₅ r₀₄ r₀₃ r₀₂ r₀₁ r₀₀ m₀₆ m₀₅ m₀₄ m₀₃ m₀₂ m₀₁ m₀₀ l₀₆ l₀₅ l₀₄ l₀₃ l₀₂ l₀₁ l₀₀ g₂₂ g₂₁ g₂₀ g₁₉ g₁₈ g₁₇ g₁₆ g₁₅
//
// Bit: ₃₁ ₃₀ ₂₉ ₂₈ ₂₇ ₂₆ ₂₅ ₂₄ ₂₃ ₂₂ ₂₁ ₂₀ ₁₉ ₁₈ ₁₇ ₁₆ ₁₅ ₁₄ ₁₃ ₁₂ ₁₁ ₁₀ ₀₉ ₀₈ ₀₇ ₀₆ ₀₅ ₀₄ ₀₃ ₀₂ ₀₁ ₀₀
//
// Bit: ₃₁ ₃₀ ₂₉ ₂₈ ₂₇ ₂₆ ₂₅ ₂₄ ₂₃ ₂₂ ₂₁ ₂₀ ₁₉ ₁₈ ₁₇ ₁₆ ₁₅ ₁₄ ₁₃ ₁₂ ₁₁ ₁₀ ₀₉ ₀₈ ₀₇ ₀₆ ₀₅ ₀₄ ₀₃ ₀₂ ₀₁ ₀₀
// Reg: g₁₄ g₁₃ g₁₂ g₁₁ g₁₀ g₀₉ g₀₈ g₀₇ g₀₆ g₀₅ g₀₄ g₀₃ g₀₂ g₀₁ g₀₀ h₁₂ h₁₁ h₁₀ h₀₉ h₀₈ h₀₇ h₀₆ h₀₅ h₀₄ h₀₃ h₀₂ h₀₁ h₀₀ x x x 1
#pragma endregion // id48lib state register
#pragma region // bit definitions for the (stable) id48lib state register
@ -164,8 +164,8 @@ static inline uint64_t reverse_bits_64(uint64_t n) {
#pragma region // Unstable (during calculations) id48lib state register
// Bit: ₆₃ ₆₂ ₆₁ ₆₀ ₅₉ ₅₈ ₅₇ ₅₆ ₅₅ ₅₄ ₅₃ ₅₂ ₅₁ ₅₀ ₄₉ ₄₈ ₄₇ ₄₆ ₄₅ ₄₄ ₄₃ ₄₂ ₄₁ ₄₀ ₃₉ ₃₈ ₃₇ ₃₆ ₃₅ ₃₄ ₃₃ ₃₂
// Reg: i j r₀₆ r₀₅ r₀₄ r₀₃ r₀₂ r₀₁ r₀₀ m₀₆ m₀₅ m₀₄ m₀₃ m₀₂ m₀₁ m₀₀ l₀₆ l₀₅ l₀₄ l₀₃ l₀₂ l₀₁ l₀₀ g₂₂ g₂₁ g₂₀ g₁₉ g₁₈ g₁₇ g₁₆ g₁₅ g₁₄
//
// Bit: ₃₁ ₃₀ ₂₉ ₂₈ ₂₇ ₂₆ ₂₅ ₂₄ ₂₃ ₂₂ ₂₁ ₂₀ ₁₉ ₁₈ ₁₇ ₁₆ ₁₅ ₁₄ ₁₃ ₁₂ ₁₁ ₁₀ ₀₉ ₀₈ ₀₇ ₀₆ ₀₅ ₀₄ ₀₃ ₀₂ ₀₁ ₀₀
//
// Bit: ₃₁ ₃₀ ₂₉ ₂₈ ₂₇ ₂₆ ₂₅ ₂₄ ₂₃ ₂₂ ₂₁ ₂₀ ₁₉ ₁₈ ₁₇ ₁₆ ₁₅ ₁₄ ₁₃ ₁₂ ₁₁ ₁₀ ₀₉ ₀₈ ₀₇ ₀₆ ₀₅ ₀₄ ₀₃ ₀₂ ₀₁ ₀₀
// Reg: g₁₃ g₁₂ g₁₁ g₁₀ g₀₉ g₀₈ g₀₇ g₀₆ g₀₅ g₀₄ g₀₃ g₀₂ g₀₁ g₀₀ h₁₂ h₁₁ h₁₀ h₀₉ h₀₈ h₀₇ h₀₆ h₀₅ h₀₄ h₀₃ h₀₂ h₀₁ h₀₀ _ a b c 0
#pragma endregion // Unstable (during calculations) id48lib state register
//
@ -242,34 +242,33 @@ static inline uint64_t reverse_bits_64(uint64_t n) {
// 0 // == 0 value defines as unstable state
#pragma endregion // bit definitions for the (stable) id48lib state register
#pragma region // single bit test/set/clear/flip/assign
static inline bool is_ssr_state_stable (const ID48LIBX_STATE_REGISTERS* ssr) { ASSERT(ssr != nullptr); return ((ssr->Raw & 1u) == 1u); }
static inline bool test_single_ssr_bit (const ID48LIBX_STATE_REGISTERS* ssr, size_t bit_index) { ASSERT(ssr != nullptr); ASSERT(bit_index < (sizeof(uint64_t) * 8)); return ((ssr->Raw) >> bit_index) & 1; }
static inline void set_single_ssr_bit ( ID48LIBX_STATE_REGISTERS* ssr, size_t bit_index) { ASSERT(ssr != nullptr); ASSERT(bit_index < (sizeof(uint64_t) * 8)); ssr->Raw |= ((uint64_t)(1ull << bit_index)); }
static inline void clear_single_ssr_bit ( ID48LIBX_STATE_REGISTERS* ssr, size_t bit_index) { ASSERT(ssr != nullptr); ASSERT(bit_index < (sizeof(uint64_t) * 8)); ssr->Raw &= ~((uint64_t)(1ull << bit_index)); }
static inline void flip_single_ssr_bit ( ID48LIBX_STATE_REGISTERS* ssr, size_t bit_index) { ASSERT(ssr != nullptr); ASSERT(bit_index < (sizeof(uint64_t) * 8)); ssr->Raw ^= ((uint64_t)(1ull << bit_index)); }
static inline void assign_single_ssr_bit ( ID48LIBX_STATE_REGISTERS* ssr, size_t bit_index, bool value) {
static inline bool is_ssr_state_stable(const ID48LIBX_STATE_REGISTERS *ssr) { ASSERT(ssr != nullptr); return ((ssr->Raw & 1u) == 1u); }
static inline bool test_single_ssr_bit(const ID48LIBX_STATE_REGISTERS *ssr, size_t bit_index) { ASSERT(ssr != nullptr); ASSERT(bit_index < (sizeof(uint64_t) * 8)); return ((ssr->Raw) >> bit_index) & 1; }
static inline void set_single_ssr_bit(ID48LIBX_STATE_REGISTERS *ssr, size_t bit_index) { ASSERT(ssr != nullptr); ASSERT(bit_index < (sizeof(uint64_t) * 8)); ssr->Raw |= ((uint64_t)(1ull << bit_index)); }
static inline void clear_single_ssr_bit(ID48LIBX_STATE_REGISTERS *ssr, size_t bit_index) { ASSERT(ssr != nullptr); ASSERT(bit_index < (sizeof(uint64_t) * 8)); ssr->Raw &= ~((uint64_t)(1ull << bit_index)); }
static inline void flip_single_ssr_bit(ID48LIBX_STATE_REGISTERS *ssr, size_t bit_index) { ASSERT(ssr != nullptr); ASSERT(bit_index < (sizeof(uint64_t) * 8)); ssr->Raw ^= ((uint64_t)(1ull << bit_index)); }
static inline void assign_single_ssr_bit(ID48LIBX_STATE_REGISTERS *ssr, size_t bit_index, bool value) {
ASSERT(ssr != nullptr);
ASSERT(bit_index < (sizeof(uint64_t) * 8));
if (value) {
set_single_ssr_bit(ssr, bit_index);
}
else {
} else {
clear_single_ssr_bit(ssr, bit_index);
}
}
#pragma endregion // single bit test/set/clear/flip/assign
#pragma region // test/assign of temporaries a/b/c/i/j
static inline void test_temporary_a(ID48LIBX_STATE_REGISTERS* ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_a); }
static inline void test_temporary_b(ID48LIBX_STATE_REGISTERS* ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_b); }
static inline void test_temporary_c(ID48LIBX_STATE_REGISTERS* ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_c); }
static inline void test_temporary_i(ID48LIBX_STATE_REGISTERS* ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_i); }
static inline void test_temporary_j(ID48LIBX_STATE_REGISTERS* ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_j); }
static inline void test_temporary_a(ID48LIBX_STATE_REGISTERS *ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_a); }
static inline void test_temporary_b(ID48LIBX_STATE_REGISTERS *ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_b); }
static inline void test_temporary_c(ID48LIBX_STATE_REGISTERS *ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_c); }
static inline void test_temporary_i(ID48LIBX_STATE_REGISTERS *ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_i); }
static inline void test_temporary_j(ID48LIBX_STATE_REGISTERS *ssr) { ASSERT(!is_ssr_state_stable(ssr)); test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_j); }
static inline void assign_temporary_a(ID48LIBX_STATE_REGISTERS* ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_a, v); }
static inline void assign_temporary_b(ID48LIBX_STATE_REGISTERS* ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_b, v); }
static inline void assign_temporary_c(ID48LIBX_STATE_REGISTERS* ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_c, v); }
static inline void assign_temporary_i(ID48LIBX_STATE_REGISTERS* ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_i, v); }
static inline void assign_temporary_j(ID48LIBX_STATE_REGISTERS* ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_j, v); }
static inline void assign_temporary_a(ID48LIBX_STATE_REGISTERS *ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_a, v); }
static inline void assign_temporary_b(ID48LIBX_STATE_REGISTERS *ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_b, v); }
static inline void assign_temporary_c(ID48LIBX_STATE_REGISTERS *ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_c, v); }
static inline void assign_temporary_i(ID48LIBX_STATE_REGISTERS *ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_i, v); }
static inline void assign_temporary_j(ID48LIBX_STATE_REGISTERS *ssr, bool v) { ASSERT(!is_ssr_state_stable(ssr)); assign_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_j, v); }
#pragma endregion // test/assign of temporaries a/b/c/i/j
#pragma region // Mask & Macro to get registers (in minimal bit form)
@ -301,17 +300,17 @@ static inline void assign_temporary_j(ID48LIBX_STATE_REGISTERS* ssr, bool v) { A
#define SSR_VALUE_MASK_REG_M (0x00007Fu) // 7 bits
#define SSR_VALUE_MASK_REG_R (0x00007Fu) // 7 bits
static inline uint16_t get_register_h(const ID48LIBX_STATE_REGISTERS* ssr) { return ((uint16_t)(ssr->Raw >> SSR_SHIFT_COUNT_REG_H)) & (SSR_VALUE_MASK_REG_H); }
static inline uint32_t get_register_g(const ID48LIBX_STATE_REGISTERS* ssr) { return ((uint32_t)(ssr->Raw >> SSR_SHIFT_COUNT_REG_G)) & (SSR_VALUE_MASK_REG_G); }
static inline uint8_t get_register_l(const ID48LIBX_STATE_REGISTERS* ssr) { return ((uint8_t )(ssr->Raw >> SSR_SHIFT_COUNT_REG_L)) & (SSR_VALUE_MASK_REG_L); }
static inline uint8_t get_register_m(const ID48LIBX_STATE_REGISTERS* ssr) { return ((uint8_t )(ssr->Raw >> SSR_SHIFT_COUNT_REG_M)) & (SSR_VALUE_MASK_REG_M); }
static inline uint8_t get_register_r(const ID48LIBX_STATE_REGISTERS* ssr) { return ((uint8_t )(ssr->Raw >> SSR_SHIFT_COUNT_REG_R)) & (SSR_VALUE_MASK_REG_R); }
static inline uint16_t get_register_h(const ID48LIBX_STATE_REGISTERS *ssr) { return ((uint16_t)(ssr->Raw >> SSR_SHIFT_COUNT_REG_H)) & (SSR_VALUE_MASK_REG_H); }
static inline uint32_t get_register_g(const ID48LIBX_STATE_REGISTERS *ssr) { return ((uint32_t)(ssr->Raw >> SSR_SHIFT_COUNT_REG_G)) & (SSR_VALUE_MASK_REG_G); }
static inline uint8_t get_register_l(const ID48LIBX_STATE_REGISTERS *ssr) { return ((uint8_t)(ssr->Raw >> SSR_SHIFT_COUNT_REG_L)) & (SSR_VALUE_MASK_REG_L); }
static inline uint8_t get_register_m(const ID48LIBX_STATE_REGISTERS *ssr) { return ((uint8_t)(ssr->Raw >> SSR_SHIFT_COUNT_REG_M)) & (SSR_VALUE_MASK_REG_M); }
static inline uint8_t get_register_r(const ID48LIBX_STATE_REGISTERS *ssr) { return ((uint8_t)(ssr->Raw >> SSR_SHIFT_COUNT_REG_R)) & (SSR_VALUE_MASK_REG_R); }
static inline void set_register_h(ID48LIBX_STATE_REGISTERS* ssr, uint16_t v) { ASSERT((v & SSR_VALUE_MASK_REG_H) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_H) | (((uint64_t)(v & SSR_VALUE_MASK_REG_H)) << SSR_SHIFT_COUNT_REG_H); }
static inline void set_register_g(ID48LIBX_STATE_REGISTERS* ssr, uint32_t v) { ASSERT((v & SSR_VALUE_MASK_REG_G) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_G) | (((uint64_t)(v & SSR_VALUE_MASK_REG_G)) << SSR_SHIFT_COUNT_REG_G); }
static inline void set_register_l(ID48LIBX_STATE_REGISTERS* ssr, uint8_t v) { ASSERT((v & SSR_VALUE_MASK_REG_L) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_L) | (((uint64_t)(v & SSR_VALUE_MASK_REG_L)) << SSR_SHIFT_COUNT_REG_L); }
static inline void set_register_m(ID48LIBX_STATE_REGISTERS* ssr, uint8_t v) { ASSERT((v & SSR_VALUE_MASK_REG_M) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_M) | (((uint64_t)(v & SSR_VALUE_MASK_REG_M)) << SSR_SHIFT_COUNT_REG_M); }
static inline void set_register_r(ID48LIBX_STATE_REGISTERS* ssr, uint8_t v) { ASSERT((v & SSR_VALUE_MASK_REG_R) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_R) | (((uint64_t)(v & SSR_VALUE_MASK_REG_R)) << SSR_SHIFT_COUNT_REG_R); }
static inline void set_register_h(ID48LIBX_STATE_REGISTERS *ssr, uint16_t v) { ASSERT((v & SSR_VALUE_MASK_REG_H) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_H) | (((uint64_t)(v & SSR_VALUE_MASK_REG_H)) << SSR_SHIFT_COUNT_REG_H); }
static inline void set_register_g(ID48LIBX_STATE_REGISTERS *ssr, uint32_t v) { ASSERT((v & SSR_VALUE_MASK_REG_G) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_G) | (((uint64_t)(v & SSR_VALUE_MASK_REG_G)) << SSR_SHIFT_COUNT_REG_G); }
static inline void set_register_l(ID48LIBX_STATE_REGISTERS *ssr, uint8_t v) { ASSERT((v & SSR_VALUE_MASK_REG_L) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_L) | (((uint64_t)(v & SSR_VALUE_MASK_REG_L)) << SSR_SHIFT_COUNT_REG_L); }
static inline void set_register_m(ID48LIBX_STATE_REGISTERS *ssr, uint8_t v) { ASSERT((v & SSR_VALUE_MASK_REG_M) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_M) | (((uint64_t)(v & SSR_VALUE_MASK_REG_M)) << SSR_SHIFT_COUNT_REG_M); }
static inline void set_register_r(ID48LIBX_STATE_REGISTERS *ssr, uint8_t v) { ASSERT((v & SSR_VALUE_MASK_REG_R) == v); ssr->Raw = (ssr->Raw & SSR_BITMASK_WITHOUT_REG_R) | (((uint64_t)(v & SSR_VALUE_MASK_REG_R)) << SSR_SHIFT_COUNT_REG_R); }
#pragma endregion // Mask & Macro to get registers (in minimal bit form)
/// <summary>
@ -322,7 +321,7 @@ static inline void set_register_r(ID48LIBX_STATE_REGISTERS* ssr, uint8_t v) { A
/// <param name="k96">key in pm3 order</param>
/// <param name="n56">nonce in pm3 order</param>
/// <returns>56-bit value p₅₅..p₀₀</returns>
static inline uint64_t calculate__p55_p00(const ID48LIB_KEY* k96, const ID48LIB_NONCE* n56) {
static inline uint64_t calculate__p55_p00(const ID48LIB_KEY *k96, const ID48LIB_NONCE *n56) {
// messy ... have to reverse the bits AND shift them into position,
// perform the addition, and then reverse bits again to return to
// native bit order (subscript is same as bit position).
@ -334,7 +333,7 @@ static inline uint64_t calculate__p55_p00(const ID48LIB_KEY* k96, const ID48LIB_
ASSERT(n56 != nullptr);
uint64_t k40_k95 = 0;
uint64_t n00_n55 = 0;
//
//
// k [ 6] :== K₄₇..K₄₀
// ...
// k [ 0] :== K₉₅..K₈₈
@ -367,7 +366,7 @@ static inline uint64_t calculate__p55_p00(const ID48LIB_KEY* k96, const ID48LIB_
/// </summary>
/// <param name="p55_p00">56 bit value: p₅₅..p₀₀</param>
/// <returns>44-bit value: q₄₃..q₀₀</returns>
static inline uint64_t calculate__q43_q00(const uint64_t* p55_p00) {
static inline uint64_t calculate__q43_q00(const uint64_t *p55_p00) {
ASSERT(p55_p00 != nullptr);
static const uint64_t C_BITMASK44 = (1ull << 44) - 1u;
uint64_t result = (*p55_p00 >> 2);
@ -382,7 +381,7 @@ static inline uint64_t calculate__q43_q00(const uint64_t* p55_p00) {
/// Relies on old g22 bit (now in L00).
/// May modify G00, G03, G04, G05, G06, G13, G16
/// </summary>
static inline void g_successor(ID48LIBX_STATE_REGISTERS* ssr) {
static inline void g_successor(ID48LIBX_STATE_REGISTERS *ssr) {
ASSERT(ssr != nullptr);
ASSERT(!is_ssr_state_stable(ssr));
assign_single_ssr_bit(ssr, SSR_BIT_G00, test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_j));
@ -403,25 +402,26 @@ static inline void g_successor(ID48LIBX_STATE_REGISTERS* ssr) {
}
}
static inline ID48LIBX_STATE_REGISTERS init_id48libx_state_register(const ID48LIB_KEY* k96, const ID48LIB_NONCE* n56) {
static inline ID48LIBX_STATE_REGISTERS init_id48libx_state_register(const ID48LIB_KEY *k96, const ID48LIB_NONCE *n56) {
ASSERT(k96 != nullptr);
ASSERT(n56 != nullptr);
ID48LIBX_STATE_REGISTERS result; result.Raw = 0;
ID48LIBX_STATE_REGISTERS* const ssr = &result; // the pointer is constant ... not the value it points to
ID48LIBX_STATE_REGISTERS result;
result.Raw = 0;
ID48LIBX_STATE_REGISTERS *const ssr = &result; // the pointer is constant ... not the value it points to
const uint64_t p55_p00 = calculate__p55_p00(k96, n56);
// p55_p00 is used to set initial value of register l
if (true) {
static const uint8_t C_BITMASK7 = ((1u << 7) - 1u);
const uint8_t l = (
((uint8_t)(p55_p00 >> 55)) ^ // 0 0 0 0 0 0 p55
((uint8_t)(p55_p00 >> 51)) ^ // 0 0 p55 p54 p53 p52 p51
((uint8_t)(p55_p00 >> 45)) // p51 p50 p49 p48 p47 p46 p45
) & C_BITMASK7;
((uint8_t)(p55_p00 >> 55)) ^ // 0 0 0 0 0 0 p55
((uint8_t)(p55_p00 >> 51)) ^ // 0 0 p55 p54 p53 p52 p51
((uint8_t)(p55_p00 >> 45)) // p51 p50 p49 p48 p47 p46 p45
) & C_BITMASK7;
set_register_l(ssr, l);
ASSERT(l == get_register_l(ssr));
}
// p is used to calculate q
const uint64_t q43_q00 = calculate__q43_q00(&p55_p00);
@ -429,7 +429,7 @@ static inline ID48LIBX_STATE_REGISTERS init_id48libx_state_register(const ID48LI
// ===> G(q₂₀..q₄₂, 0, q₀₀..q₁₉)
// ===> g₀₀..g₂₂ :=== q₂₀..q₄₂
// and j₀₀..j₁₉ :=== q₀₀..q₁₉
//
//
// But, since I'm storing the register with g₀₀ as lsb:
// ===> g₂₂..g₀₀ :=== q₄₂..q₂₀
if (true) {
@ -442,13 +442,12 @@ static inline ID48LIBX_STATE_REGISTERS init_id48libx_state_register(const ID48LI
// input bits for `j` during init are q00..q19, with q19 used first
// For ease of use, I'll generate this as q00..q19, so the loop
// can test the lsb (and then shift it right one bit)
uint32_t q00_q19 = reverse_bits_32( ((uint32_t)q43_q00) << 12 );
uint32_t q00_q19 = reverse_bits_32(((uint32_t)q43_q00) << 12);
uint32_t q_lsb_next = q00_q19;
ssr->Raw |= 1u;
// G(g,0,j) twenty times, using q19, q18, ... q00 for `j`
for (uint8_t ix = 0; ix < 20; ++ix)
{
for (uint8_t ix = 0; ix < 20; ++ix) {
ASSERT(is_ssr_state_stable(ssr));
ssr->Raw <<= 1; // starts the process ... it's now an unstable value
ASSERT(!is_ssr_state_stable(ssr));
@ -478,27 +477,27 @@ static inline ID48LIBX_STATE_REGISTERS init_id48libx_state_register(const ID48LI
/// <summary>
/// H(h) matches the research paper, definition 3.3
///
///
/// Reads bits H01, H08, H09, H11, H12.
/// </summary>
/// <remarks>
/// If ssr is in unstable state, caller is responsible for ensuring
/// the values have not changed.
/// </remarks>
static inline bool calculate_feedback_h(const ID48LIBX_STATE_REGISTERS* ssr) {
static inline bool calculate_feedback_h(const ID48LIBX_STATE_REGISTERS *ssr) {
ASSERT(ssr != nullptr);
// ( h₀₁ && h₀₈ ) || ( h₀₉ && h₁₁ ) || (!h₁₂ )
// \____ a1 ____/ \____ a2 ____/ \____ a3 ____/
// result == xor(a1,a2,a3)
bool a1 = is_ssr_state_stable(ssr) ?
test_single_ssr_bit(ssr, SSR_BIT_H01) && test_single_ssr_bit(ssr, SSR_BIT_H08) :
test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H01) && test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H08);
test_single_ssr_bit(ssr, SSR_BIT_H01) && test_single_ssr_bit(ssr, SSR_BIT_H08) :
test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H01) && test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H08);
bool a2 = is_ssr_state_stable(ssr) ?
test_single_ssr_bit(ssr, SSR_BIT_H09) && test_single_ssr_bit(ssr, SSR_BIT_H11) :
test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H09) && test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H11);
test_single_ssr_bit(ssr, SSR_BIT_H09) && test_single_ssr_bit(ssr, SSR_BIT_H11) :
test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H09) && test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H11);
bool a3 = is_ssr_state_stable(ssr) ?
!test_single_ssr_bit(ssr, SSR_BIT_H12) :
!test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H12);
!test_single_ssr_bit(ssr, SSR_BIT_H12) :
!test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_H12);
bool result = false;
if (a1) result = !result;
if (a2) result = !result;
@ -510,7 +509,7 @@ static inline bool calculate_feedback_h(const ID48LIBX_STATE_REGISTERS* ssr) {
/// fₗ(...) matches the research paper, definition 3.4
/// hard-coded to use bits for calculation of 'a'
/// </summary>
static inline bool calculate_feedback_l(const ID48LIBX_STATE_REGISTERS* ssr) {
static inline bool calculate_feedback_l(const ID48LIBX_STATE_REGISTERS *ssr) {
ASSERT(ssr != nullptr);
// a = fₗ( g00 g04 g06 g13 g18 h03 ) ⊕ g22 ⊕ r02 ⊕ r06
// fₗ( x₀ x₁ x₂ x₃ x₄ x₅ )
@ -534,7 +533,7 @@ static inline bool calculate_feedback_l(const ID48LIBX_STATE_REGISTERS* ssr) {
/// fₘ(...) matches the research paper, definition 3.5
/// hard-coded to use bits for calculation of 'b'
/// </summary>
static inline bool calculate_feedback_m(const ID48LIBX_STATE_REGISTERS* ssr) {
static inline bool calculate_feedback_m(const ID48LIBX_STATE_REGISTERS *ssr) {
ASSERT(ssr != nullptr);
// b = fₘ( g01 g05 g10 g15 h00 h07 ) ⊕ l00 ⊕ l03 ⊕ l06
// fₘ( x₀ x₁ x₂ x₃ x₄ x₅ )
@ -558,7 +557,7 @@ static inline bool calculate_feedback_m(const ID48LIBX_STATE_REGISTERS* ssr) {
/// fᵣ(...) matches the research paper, definition 3.6
/// hard-coded to use bits for calculation of 'c'
/// </summary>
static inline bool calculate_feedback_r(const ID48LIBX_STATE_REGISTERS* ssr) {
static inline bool calculate_feedback_r(const ID48LIBX_STATE_REGISTERS *ssr) {
ASSERT(ssr != nullptr);
ASSERT(!is_ssr_state_stable(ssr));
// c = fᵣ( g02 g03⊕i g09 g14 g16 h01 ) ⊕ m00 ⊕ m03 ⊕ m06
@ -583,7 +582,7 @@ static inline bool calculate_feedback_r(const ID48LIBX_STATE_REGISTERS* ssr) {
/// Matches the research paper, definition 3.7
/// See also Definition 3.2, defining that parameter as `j`.
/// </summary>
static inline bool calculate_j(const ID48LIBX_STATE_REGISTERS* ssr) {
static inline bool calculate_j(const ID48LIBX_STATE_REGISTERS *ssr) {
ASSERT(ssr != nullptr);
// g := G(g, i, l₀₁ ⊕ m₀₆ ⊕ h₀₂ ⊕ h₀₈ ⊕ h₁₂)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^------ calculates `j`
@ -602,22 +601,22 @@ static inline bool calculate_j(const ID48LIBX_STATE_REGISTERS* ssr) {
/// Calculates a, b, c, j and new value for H₀₀.
/// These are the only bits changed by this function.
/// </summary>
static inline void calculate_temporaries(ID48LIBX_STATE_REGISTERS* ssr) {
static inline void calculate_temporaries(ID48LIBX_STATE_REGISTERS *ssr) {
ASSERT(ssr != nullptr);
#pragma region // to be removed after all is validated
#pragma region // to be removed after all is validated
static const uint64_t bits_must_remain_same_mask =
~(
(1ull << SSR_UNSTABLE_BIT_a) |
(1ull << SSR_UNSTABLE_BIT_b) |
(1ull << SSR_UNSTABLE_BIT_c) |
(1ull << SSR_UNSTABLE_BIT_j) |
(1ull << SSR_UNSTABLE_NEW_BIT_H00)
~(
(1ull << SSR_UNSTABLE_BIT_a) |
(1ull << SSR_UNSTABLE_BIT_b) |
(1ull << SSR_UNSTABLE_BIT_c) |
(1ull << SSR_UNSTABLE_BIT_j) |
(1ull << SSR_UNSTABLE_NEW_BIT_H00)
);
const uint64_t backup = ssr->Raw & bits_must_remain_same_mask;
(void)backup; // to avoid warning about unused variable
#pragma endregion // to be removed after all is validated
#pragma endregion // to be removed after all is validated
// Only bits that change value: H00, a, b, c, j
ASSERT(!is_ssr_state_stable(ssr)); // assigning temp values directly in ssr, so...
@ -643,29 +642,30 @@ static inline void calculate_temporaries(ID48LIBX_STATE_REGISTERS* ssr) {
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_M03)) flip_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_c);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_M06)) flip_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_c);
#pragma region // to be removed after all is validated
#pragma region // to be removed after all is validated
const uint64_t chk = ssr->Raw & bits_must_remain_same_mask;
(void)chk; // to avoid warning about unused variable
ASSERT(chk == backup);
#pragma endregion // to be removed after all is validated
#pragma endregion // to be removed after all is validated
return;
}
static inline OUTPUT_INDEX2 calculate_output_index(const ID48LIBX_STATE_REGISTERS* ssr) {
static inline OUTPUT_INDEX2 calculate_output_index(const ID48LIBX_STATE_REGISTERS *ssr) {
// Fₒ( abc l₀l₂l₃l₄l₅l₆ m₀m₁m₃m₅ r₀r₁r₂r₃r₄r₅r₆ )
// msb 19 ---^ lsb 00 ---^^
ASSERT(ssr != nullptr);
ASSERT(!is_ssr_state_stable(ssr));
OUTPUT_INDEX2 result; result.Raw = 0;
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_a )) result.Raw |= (1u << 19);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_b )) result.Raw |= (1u << 18);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_c )) result.Raw |= (1u << 17);
OUTPUT_INDEX2 result;
result.Raw = 0;
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_a)) result.Raw |= (1u << 19);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_b)) result.Raw |= (1u << 18);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_c)) result.Raw |= (1u << 17);
//bool bit17 = test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_c);
//if (test_single_ssr_bit(ssr, SSR_UNSTABLE_BIT_i) ) bit17 = !bit17;
//if (bit17 ) result.Raw |= (1u << 17);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_L00)) result.Raw |= (1u << 16);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_L00)) result.Raw |= (1u << 16);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_L02)) result.Raw |= (1u << 15);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_L03)) result.Raw |= (1u << 14);
if (test_single_ssr_bit(ssr, SSR_UNSTABLE_OLD_BIT_L04)) result.Raw |= (1u << 13);
@ -686,7 +686,7 @@ static inline OUTPUT_INDEX2 calculate_output_index(const ID48LIBX_STATE_REGISTER
}
// returns a single bit corresponding to the output bit for this transition
static inline bool calculate_successor_state(ID48LIBX_STATE_REGISTERS* ssr, bool i) {
static inline bool calculate_successor_state(ID48LIBX_STATE_REGISTERS *ssr, bool i) {
ASSERT(ssr != nullptr);
ASSERT(is_ssr_state_stable(ssr));
@ -718,7 +718,7 @@ static inline bool calculate_successor_state(ID48LIBX_STATE_REGISTERS* ssr, bool
// 4. calculate and save output index
OUTPUT_INDEX2 output_index = calculate_output_index(ssr); // note: does *NOT* rely on new H00 value
bool output_result = id48libx_output_lookup(output_index.Raw);
// 5. g --> g', aka G(g, i, j)
g_successor(ssr);
@ -735,7 +735,7 @@ static inline bool calculate_successor_state(ID48LIBX_STATE_REGISTERS* ssr, bool
// Keep only the registers (no temporaries)
ssr->Raw &= SSR_BITMASK_REG_ALL;
// Mark as stable view of the SSR
ssr->Raw |= 1u;
@ -748,14 +748,15 @@ static inline bool calculate_successor_state(ID48LIBX_STATE_REGISTERS* ssr, bool
/// by one bit each iteration (allowing least significant bit
/// to always be the input bit).
/// </summary>
static inline INPUT_BITS2 get_key_input_bits(const ID48LIB_KEY* k) {
static inline INPUT_BITS2 get_key_input_bits(const ID48LIB_KEY *k) {
ASSERT(k != nullptr);
// Per research paper, key bit 39 is used first.
// So, what should end up in result is: 0²⁴ k₀₀..K₃₉
// This allows simply shifting the lsb out each cycle....
INPUT_BITS2 result; result.Raw = 0;
INPUT_BITS2 result;
result.Raw = 0;
// k[ 0] :== K₉₅..K₈₈
// ...
@ -775,19 +776,19 @@ static inline INPUT_BITS2 get_key_input_bits(const ID48LIB_KEY* k) {
return result;
}
static inline bool shift_out_next_input_bit(INPUT_BITS2* inputs) {
static inline bool shift_out_next_input_bit(INPUT_BITS2 *inputs) {
ASSERT(inputs != nullptr);
bool result = inputs->Raw & 1ull;
inputs->Raw >>= 1;
return result;
}
static inline void shift_in_next_output_bit(OUTPUT_BITS2* outputs, bool v) {
static inline void shift_in_next_output_bit(OUTPUT_BITS2 *outputs, bool v) {
ASSERT(outputs != nullptr);
outputs->Raw <<= 1;
if (v) outputs->Raw |= 1ull;
}
static inline void extract_frn(const OUTPUT_BITS2* outputs, ID48LIB_FRN* frn28_out) {
static inline void extract_frn(const OUTPUT_BITS2 *outputs, ID48LIB_FRN *frn28_out) {
ASSERT(outputs != nullptr);
ASSERT(frn28_out != nullptr);
@ -802,7 +803,7 @@ static inline void extract_frn(const OUTPUT_BITS2* outputs, ID48LIB_FRN* frn28_o
frn28_out->frn[2] = (uint8_t)((tmp >> (8 * 1)) & 0xFFu);
frn28_out->frn[3] = (uint8_t)((tmp >> (8 * 0)) & 0xFFu);
}
static inline void extract_grn(const OUTPUT_BITS2* outputs, ID48LIB_GRN* grn20_out) {
static inline void extract_grn(const OUTPUT_BITS2 *outputs, ID48LIB_GRN *grn20_out) {
ASSERT(outputs != nullptr);
ASSERT(grn20_out != nullptr);
memset(grn20_out, 0, sizeof(ID48LIB_GRN));
@ -817,12 +818,11 @@ static inline void extract_grn(const OUTPUT_BITS2* outputs, ID48LIB_GRN* grn20_o
}
static void retro_generator_impl(
const ID48LIB_KEY* k,
const ID48LIB_NONCE* n,
ID48LIB_FRN* frn28_out,
ID48LIB_GRN* grn20_out
)
{
const ID48LIB_KEY *k,
const ID48LIB_NONCE *n,
ID48LIB_FRN *frn28_out,
ID48LIB_GRN *grn20_out
) {
ASSERT(k != nullptr);
ASSERT(n != nullptr);
ASSERT(frn28_out != nullptr);
@ -834,7 +834,8 @@ static void retro_generator_impl(
// get 55-bit successor state input
INPUT_BITS2 inputs = get_key_input_bits(k);
OUTPUT_BITS2 outputs; outputs.Raw = 0ull;
OUTPUT_BITS2 outputs;
outputs.Raw = 0ull;
for (uint8_t ix = 0; ix < 55; ix++) {
ASSERT(is_ssr_state_stable(&ssr));
@ -865,9 +866,10 @@ static void retro_generator_impl(
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// internal function
ID48LIBX_SUCCESSOR_RESULT id48libx_retro003_successor(const ID48LIBX_STATE_REGISTERS* initial_state, uint8_t input_bit) {
ID48LIBX_SUCCESSOR_RESULT id48libx_retro003_successor(const ID48LIBX_STATE_REGISTERS *initial_state, uint8_t input_bit) {
ASSERT(initial_state != nullptr);
ID48LIBX_SUCCESSOR_RESULT r; memset(&r, 0, sizeof(ID48LIBX_SUCCESSOR_RESULT));
ID48LIBX_SUCCESSOR_RESULT r;
memset(&r, 0, sizeof(ID48LIBX_SUCCESSOR_RESULT));
ID48LIBX_STATE_REGISTERS s = *initial_state;
bool output_bit = calculate_successor_state(&s, !!input_bit);
r.state.Raw = s.Raw;
@ -875,23 +877,23 @@ ID48LIBX_SUCCESSOR_RESULT id48libx_retro003_successor(const ID48LIBX_STATE_REGIS
return r;
}
// internal function
ID48LIBX_STATE_REGISTERS id48libx_retro003_init(const ID48LIB_KEY* key, const ID48LIB_NONCE* nonce) {
ID48LIBX_STATE_REGISTERS id48libx_retro003_init(const ID48LIB_KEY *key, const ID48LIB_NONCE *nonce) {
ASSERT(key != nullptr);
ASSERT(nonce != nullptr);
ID48LIBX_STATE_REGISTERS ssr = init_id48libx_state_register(key, nonce);
ID48LIBX_STATE_REGISTERS result; memset(&result, 0, sizeof(ID48LIBX_STATE_REGISTERS));
ID48LIBX_STATE_REGISTERS result;
memset(&result, 0, sizeof(ID48LIBX_STATE_REGISTERS));
result.Raw = ssr.Raw;
return result;
}
// public API
void id48lib_generator(
const ID48LIB_KEY* k,
const ID48LIB_NONCE* n,
ID48LIB_FRN* frn28_out,
ID48LIB_GRN* grn20_out
)
{
const ID48LIB_KEY *k,
const ID48LIB_NONCE *n,
ID48LIB_FRN *frn28_out,
ID48LIB_GRN *grn20_out
) {
retro_generator_impl(k, n, frn28_out, grn20_out);
}

View file

@ -45,8 +45,8 @@ typedef struct _ID48LIBX_SUCCESSOR_RESULT {
} ID48LIBX_SUCCESSOR_RESULT;
// the following are used in key recovery but implemented in id48.c
ID48LIBX_SUCCESSOR_RESULT id48libx_retro003_successor(const ID48LIBX_STATE_REGISTERS* initial_state, uint8_t input_bit);
ID48LIBX_STATE_REGISTERS id48libx_retro003_init (const ID48LIB_KEY* key, const ID48LIB_NONCE* nonce);
ID48LIBX_SUCCESSOR_RESULT id48libx_retro003_successor(const ID48LIBX_STATE_REGISTERS *initial_state, uint8_t input_bit);
ID48LIBX_STATE_REGISTERS id48libx_retro003_init(const ID48LIB_KEY *key, const ID48LIB_NONCE *nonce);
bool id48libx_output_lookup(uint32_t output_index);

View file

@ -116,8 +116,8 @@ typedef struct _RECOVERY_STATE {
} RECOVERY_STATE;
// Need equivalent of the following two function pointers:
typedef ID48LIBX_SUCCESSOR_RESULT (*ID48LIB_SUCCESSOR_FN)(const ID48LIBX_STATE_REGISTERS* initial_state, uint8_t input_bit);
typedef ID48LIBX_STATE_REGISTERS(*ID48LIB_INIT_FN )(const ID48LIB_KEY* key, const ID48LIB_NONCE* nonce);
typedef ID48LIBX_SUCCESSOR_RESULT(*ID48LIB_SUCCESSOR_FN)(const ID48LIBX_STATE_REGISTERS *initial_state, uint8_t input_bit);
typedef ID48LIBX_STATE_REGISTERS(*ID48LIB_INIT_FN)(const ID48LIB_KEY *key, const ID48LIB_NONCE *nonce);
static const ID48LIB_INIT_FN init_fn = id48libx_retro003_init;
static const ID48LIB_SUCCESSOR_FN successor_fn = id48libx_retro003_successor;
@ -129,7 +129,7 @@ static const ID48LIB_SUCCESSOR_FN successor_fn = id48libx_retro003_successor;
/// <param name="input_partial_key">Key with K₉₅..K₄₈, in PM3 compatible layout</param>
/// <param name="more_bits">0 K₃₃..K₄₇ (to support simple incrementing input)</param>
/// <returns>PM3-formatted key: K₉₅..K₃₃ 0³³</returns>
static ID48LIB_KEY create_partial_key56(const ID48LIB_KEY * input_partial_key, uint8_t k47_to_k40) {
static ID48LIB_KEY create_partial_key56(const ID48LIB_KEY *input_partial_key, uint8_t k47_to_k40) {
ID48LIB_KEY result;
result.k[ 0] = input_partial_key->k[0]; // k[ 0] :== K₉₅..K₈₈
result.k[ 1] = input_partial_key->k[1]; // k[ 1] :== K₈₇..K₈₀
@ -153,7 +153,7 @@ static ID48LIB_KEY create_partial_key56(const ID48LIB_KEY * input_partial_key, u
/// <param name="input_frn">PM3 compatible input for frn</param>
/// <param name="input_grn">PM3 compatible input for grn</param>
/// <returns></returns>
static EXPECTED_OUTPUT_BITS create_expected_output_bits(const ID48LIB_FRN* input_frn, const ID48LIB_GRN* input_grn) {
static EXPECTED_OUTPUT_BITS create_expected_output_bits(const ID48LIB_FRN *input_frn, const ID48LIB_GRN *input_grn) {
// inputs:
// frn[ 0] :== O₀₀..O₀₇
// frn[ 1] :== O₀₈..O₁₅
@ -162,15 +162,23 @@ static EXPECTED_OUTPUT_BITS create_expected_output_bits(const ID48LIB_FRN* input
// grn[ 0] :== O₂₈ .. O₃₅
// grn[ 1] :== O₃₆ .. O₄₃
// grn[ 2] :== O₄₄..O₄₇ 0000
EXPECTED_OUTPUT_BITS result; result.Raw = 0u;
result.Raw <<= 4; result.Raw |= reverse_bits_08(input_grn->grn[2] & 0xF0u); // adds grn₁₉..grn₁₆ aka O₄₇..O₄₄
result.Raw <<= 8; result.Raw |= reverse_bits_08(input_grn->grn[1] & 0xFFu); // adds grn₁₅..grn₀₈ aka O₄₃..O₃₆
result.Raw <<= 8; result.Raw |= reverse_bits_08(input_grn->grn[0] & 0xFFu); // adds grn₀₇..grn₀₀ aka O₃₅..O₂₈
EXPECTED_OUTPUT_BITS result;
result.Raw = 0u;
result.Raw <<= 4;
result.Raw |= reverse_bits_08(input_grn->grn[2] & 0xF0u); // adds grn₁₉..grn₁₆ aka O₄₇..O₄₄
result.Raw <<= 8;
result.Raw |= reverse_bits_08(input_grn->grn[1] & 0xFFu); // adds grn₁₅..grn₀₈ aka O₄₃..O₃₆
result.Raw <<= 8;
result.Raw |= reverse_bits_08(input_grn->grn[0] & 0xFFu); // adds grn₀₇..grn₀₀ aka O₃₅..O₂₈
result.Raw <<= 4; result.Raw |= reverse_bits_08(input_frn->frn[3] & 0xF0u); // adds frn₂₇..frn₂₄ aka O₂₇..O₂₄
result.Raw <<= 8; result.Raw |= reverse_bits_08(input_frn->frn[2] & 0xFFu); // adds frn₂₃..frn₁₆ aka O₂₃..O₁₆
result.Raw <<= 8; result.Raw |= reverse_bits_08(input_frn->frn[1] & 0xFFu); // adds frn₁₅..frn₀₈ aka O₁₅..O₀₈
result.Raw <<= 8; result.Raw |= reverse_bits_08(input_frn->frn[0] & 0xFFu); // adds frn₀₇..frn₀₀ aka O₀₇..O₀₀
result.Raw <<= 4;
result.Raw |= reverse_bits_08(input_frn->frn[3] & 0xF0u); // adds frn₂₇..frn₂₄ aka O₂₇..O₂₄
result.Raw <<= 8;
result.Raw |= reverse_bits_08(input_frn->frn[2] & 0xFFu); // adds frn₂₃..frn₁₆ aka O₂₃..O₁₆
result.Raw <<= 8;
result.Raw |= reverse_bits_08(input_frn->frn[1] & 0xFFu); // adds frn₁₅..frn₀₈ aka O₁₅..O₀₈
result.Raw <<= 8;
result.Raw |= reverse_bits_08(input_frn->frn[0] & 0xFFu); // adds frn₀₇..frn₀₀ aka O₀₇..O₀₀
return result;
}
/// <summary>
@ -180,7 +188,7 @@ static EXPECTED_OUTPUT_BITS create_expected_output_bits(const ID48LIB_FRN* input
/// </summary>
/// <param name="recovery_state">A value in the range [0,55]</param>
/// <returns>Zero or non-zero (boolean) corresponding to the expected output.</returns>
static bool get_expected_output_bit(const RECOVERY_STATE* recovery_state, uint8_t current_state_index) {
static bool get_expected_output_bit(const RECOVERY_STATE *recovery_state, uint8_t current_state_index) {
ASSERT(recovery_state != nullptr);
ASSERT(current_state_index >= 7);
ASSERT(current_state_index <= 55);
@ -188,7 +196,7 @@ static bool get_expected_output_bit(const RECOVERY_STATE* recovery_state, uint8_
return !!(shifted & 0x1u); // return the single bit result
}
static void restart_and_calculate_s00(RECOVERY_STATE* s, const KEY_BITS_K47_TO_K00* k_low) {
static void restart_and_calculate_s00(RECOVERY_STATE *s, const KEY_BITS_K47_TO_K00 *k_low) {
ASSERT(s != nullptr);
ASSERT(k_low != nullptr);
memset(&(s->states[0]), 0xAA, sizeof(ID48LIBX_STATE_REGISTERS) * MAXIMUM_STATE_HISTORY);
@ -197,11 +205,11 @@ static void restart_and_calculate_s00(RECOVERY_STATE* s, const KEY_BITS_K47_TO_K
s->states[0] = init_fn(&start_56b_key, &(s->known_nonce));
}
static bool validate_output_from_additional_fifteen_zero_bits(RECOVERY_STATE* s) {
static bool validate_output_from_additional_fifteen_zero_bits(RECOVERY_STATE *s) {
bool all_still_match = true;
for (uint8_t i = 0; all_still_match && i < 15; i++) {
const uint8_t src_idx = 40 + i;
const ID48LIBX_STATE_REGISTERS* state = &(s->states[src_idx]);
const ID48LIBX_STATE_REGISTERS *state = &(s->states[src_idx]);
ID48LIBX_SUCCESSOR_RESULT r = successor_fn(state, 0);
bool expected_result = get_expected_output_bit(s, src_idx);
if (expected_result != (!!r.output)) {
@ -220,12 +228,11 @@ static bool validate_output_from_additional_fifteen_zero_bits(RECOVERY_STATE* s)
RECOVERY_STATE g_S = { 0 };
static void init(
const ID48LIB_KEY * input_partial_key,
const ID48LIB_NONCE * input_nonce,
const ID48LIB_FRN * input_frn,
const ID48LIB_GRN * input_grn
)
{
const ID48LIB_KEY *input_partial_key,
const ID48LIB_NONCE *input_nonce,
const ID48LIB_FRN *input_frn,
const ID48LIB_GRN *input_grn
) {
memset(&g_S, 0, sizeof(RECOVERY_STATE));
memset(&(g_S.states[0]), 0xAA, sizeof(ID48LIBX_STATE_REGISTERS) * MAXIMUM_STATE_HISTORY);
g_S.known_k95_to_k48.k[0] = input_partial_key->k[0];
@ -240,7 +247,7 @@ static void init(
g_S.is_fresh_initialization = true;
}
static bool get_next_potential_key(
ID48LIB_KEY* potential_key_output
ID48LIB_KEY *potential_key_output
) {
memset(potential_key_output, 0, sizeof(ID48LIB_KEY));
@ -271,8 +278,7 @@ static bool get_next_potential_key(
g_S.is_fresh_initialization = false;
k_low.Raw = 0ull;
current_key_bit_shift = 47;
}
else {
} else {
// by definition, a returned potential key had all the bits defined
current_key_bit_shift = 0;
k_low = g_S.last_returned_potential_key;
@ -417,16 +423,15 @@ static bool get_next_potential_key(
void id48lib_key_recovery_init(
const ID48LIB_KEY * input_partial_key,
const ID48LIB_NONCE * input_nonce,
const ID48LIB_FRN * input_frn,
const ID48LIB_GRN * input_grn
)
{
const ID48LIB_KEY *input_partial_key,
const ID48LIB_NONCE *input_nonce,
const ID48LIB_FRN *input_frn,
const ID48LIB_GRN *input_grn
) {
init(input_partial_key, input_nonce, input_frn, input_grn);
}
bool id48lib_key_recovery_next(
ID48LIB_KEY* potential_key_output
ID48LIB_KEY *potential_key_output
) {
return get_next_potential_key(potential_key_output);
}