mirror of
https://github.com/DarkFlippers/unleashed-firmware.git
synced 2025-12-12 04:34:43 +04:00
format
This commit is contained in:
@@ -6,202 +6,185 @@
|
||||
#include <nfc/helpers/nfc_util.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
|
||||
#define LF_POLY_ODD (0x29CE5C)
|
||||
#define LF_POLY_ODD (0x29CE5C)
|
||||
#define LF_POLY_EVEN (0x870804)
|
||||
#define BIT(x, n) ((x) >> (n) & 1)
|
||||
#define BEBIT(x, n) BIT(x, (n) ^ 24)
|
||||
#define BIT(x, n) ((x) >> (n) & 1)
|
||||
#define BEBIT(x, n) BIT(x, (n) ^ 24)
|
||||
#define SWAPENDIAN(x) \
|
||||
((x) = ((x) >> 8 & 0xff00ff) | ((x) & 0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16)
|
||||
((x) = ((x) >> 8 & 0xff00ff) | ((x) & 0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16)
|
||||
|
||||
static inline uint32_t prng_successor(uint32_t x, uint32_t n);
|
||||
static inline int filter(uint32_t const x);
|
||||
static inline uint8_t evenparity32(uint32_t x);
|
||||
static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2);
|
||||
void crypto1_get_lfsr(struct Crypto1State *state, MfClassicKey *lfsr);
|
||||
static inline uint32_t crypt_word(struct Crypto1State *s);
|
||||
static inline void crypt_word_noret(struct Crypto1State *s, uint32_t in, int x);
|
||||
static inline uint32_t crypt_word_ret(struct Crypto1State *s, uint32_t in, int x);
|
||||
void crypto1_get_lfsr(struct Crypto1State* state, MfClassicKey* lfsr);
|
||||
static inline uint32_t crypt_word(struct Crypto1State* s);
|
||||
static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x);
|
||||
static inline uint32_t crypt_word_ret(struct Crypto1State* s, uint32_t in, int x);
|
||||
static uint32_t crypt_word_par(
|
||||
struct Crypto1State *s,
|
||||
uint32_t in,
|
||||
int is_encrypted,
|
||||
uint32_t nt_plain,
|
||||
uint8_t *parity_keystream_bits);
|
||||
static inline void rollback_word_noret(struct Crypto1State *s, uint32_t in, int x);
|
||||
static inline uint8_t napi_lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb);
|
||||
static inline uint32_t napi_lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb);
|
||||
struct Crypto1State* s,
|
||||
uint32_t in,
|
||||
int is_encrypted,
|
||||
uint32_t nt_plain,
|
||||
uint8_t* parity_keystream_bits);
|
||||
static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x);
|
||||
static inline uint8_t napi_lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb);
|
||||
static inline uint32_t napi_lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb);
|
||||
|
||||
static const uint8_t lookup1[256] = {
|
||||
0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16,
|
||||
8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8,
|
||||
8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
|
||||
0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
|
||||
0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
|
||||
8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 0, 0, 16, 16, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
|
||||
8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24};
|
||||
0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16,
|
||||
8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8,
|
||||
8, 24, 8, 8, 24, 24, 24, 24, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
|
||||
0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
|
||||
0, 0, 16, 16, 0, 16, 0, 0, 0, 16, 0, 0, 16, 16, 16, 16, 0, 0, 16, 16, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
|
||||
8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24, 0, 0, 16, 16, 0, 16, 0, 0,
|
||||
0, 16, 0, 0, 16, 16, 16, 16, 8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24,
|
||||
8, 8, 24, 24, 8, 24, 8, 8, 8, 24, 8, 8, 24, 24, 24, 24};
|
||||
static const uint8_t lookup2[256] = {
|
||||
0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4,
|
||||
4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6,
|
||||
2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2,
|
||||
2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4,
|
||||
0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2,
|
||||
2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4,
|
||||
4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2,
|
||||
2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2,
|
||||
2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6};
|
||||
0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4,
|
||||
4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6,
|
||||
2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2,
|
||||
2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4,
|
||||
0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2,
|
||||
2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4,
|
||||
4, 4, 0, 0, 4, 4, 0, 4, 0, 0, 0, 4, 0, 0, 4, 4, 4, 4, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2,
|
||||
2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2,
|
||||
2, 6, 2, 2, 6, 6, 6, 6, 2, 2, 6, 6, 2, 6, 2, 2, 2, 6, 2, 2, 6, 6, 6, 6};
|
||||
|
||||
static inline int filter(uint32_t const x)
|
||||
{
|
||||
uint32_t f;
|
||||
f = lookup1[x & 0xff] | lookup2[(x >> 8) & 0xff];
|
||||
f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
|
||||
return BIT(0xEC57E80A, f);
|
||||
static inline int filter(uint32_t const x) {
|
||||
uint32_t f;
|
||||
f = lookup1[x & 0xff] | lookup2[(x >> 8) & 0xff];
|
||||
f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
|
||||
return BIT(0xEC57E80A, f);
|
||||
}
|
||||
|
||||
#ifdef __ARM_ARCH_7EM__
|
||||
static inline uint8_t evenparity32(uint32_t x)
|
||||
{
|
||||
// fold 32 bits -> 16 -> 8 -> 4
|
||||
x ^= x >> 16;
|
||||
x ^= x >> 8;
|
||||
x ^= x >> 4;
|
||||
// magic 0x6996: bit i tells you parity of i (0 ≤ i < 16)
|
||||
return (uint8_t)((0x6996u >> (x & 0xF)) & 1);
|
||||
static inline uint8_t evenparity32(uint32_t x) {
|
||||
// fold 32 bits -> 16 -> 8 -> 4
|
||||
x ^= x >> 16;
|
||||
x ^= x >> 8;
|
||||
x ^= x >> 4;
|
||||
// magic 0x6996: bit i tells you parity of i (0 ≤ i < 16)
|
||||
return (uint8_t)((0x6996u >> (x & 0xF)) & 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2)
|
||||
{
|
||||
int p = data[item] >> 25;
|
||||
p = p << 1 | evenparity32(data[item] & mask1);
|
||||
p = p << 1 | evenparity32(data[item] & mask2);
|
||||
data[item] = p << 24 | (data[item] & 0xffffff);
|
||||
static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2) {
|
||||
int p = data[item] >> 25;
|
||||
p = p << 1 | evenparity32(data[item] & mask1);
|
||||
p = p << 1 | evenparity32(data[item] & mask2);
|
||||
data[item] = p << 24 | (data[item] & 0xffffff);
|
||||
}
|
||||
|
||||
static inline uint32_t crypt_word(struct Crypto1State *s)
|
||||
{
|
||||
// "in" and "x" are always 0 (last iteration)
|
||||
uint32_t res_ret = 0;
|
||||
uint32_t feedin, t;
|
||||
for (int i = 0; i <= 31; i++)
|
||||
{
|
||||
res_ret |= (filter(s->odd) << (24 ^ i)); //-V629
|
||||
feedin = LF_POLY_EVEN & s->even;
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
s->even = s->even << 1 | (evenparity32(feedin));
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
}
|
||||
return res_ret;
|
||||
static inline uint32_t crypt_word(struct Crypto1State* s) {
|
||||
// "in" and "x" are always 0 (last iteration)
|
||||
uint32_t res_ret = 0;
|
||||
uint32_t feedin, t;
|
||||
for(int i = 0; i <= 31; i++) {
|
||||
res_ret |= (filter(s->odd) << (24 ^ i)); //-V629
|
||||
feedin = LF_POLY_EVEN & s->even;
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
s->even = s->even << 1 | (evenparity32(feedin));
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
}
|
||||
return res_ret;
|
||||
}
|
||||
|
||||
static inline void crypt_word_noret(struct Crypto1State *s, uint32_t in, int x)
|
||||
{
|
||||
uint8_t ret;
|
||||
uint32_t feedin, t, next_in;
|
||||
for (int i = 0; i <= 31; i++)
|
||||
{
|
||||
next_in = BEBIT(in, i);
|
||||
ret = filter(s->odd);
|
||||
feedin = ret & (!!x);
|
||||
feedin ^= LF_POLY_EVEN & s->even;
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
feedin ^= !!next_in;
|
||||
s->even = s->even << 1 | (evenparity32(feedin));
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
}
|
||||
return;
|
||||
static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x) {
|
||||
uint8_t ret;
|
||||
uint32_t feedin, t, next_in;
|
||||
for(int i = 0; i <= 31; i++) {
|
||||
next_in = BEBIT(in, i);
|
||||
ret = filter(s->odd);
|
||||
feedin = ret & (!!x);
|
||||
feedin ^= LF_POLY_EVEN & s->even;
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
feedin ^= !!next_in;
|
||||
s->even = s->even << 1 | (evenparity32(feedin));
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static inline uint32_t crypt_word_ret(struct Crypto1State *s, uint32_t in, int x)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
uint32_t feedin, t, next_in;
|
||||
uint8_t next_ret;
|
||||
for (int i = 0; i <= 31; i++)
|
||||
{
|
||||
next_in = BEBIT(in, i);
|
||||
next_ret = filter(s->odd);
|
||||
feedin = next_ret & (!!x);
|
||||
feedin ^= LF_POLY_EVEN & s->even;
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
feedin ^= !!next_in;
|
||||
s->even = s->even << 1 | (evenparity32(feedin));
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
ret |= next_ret << (24 ^ i);
|
||||
}
|
||||
return ret;
|
||||
static inline uint32_t crypt_word_ret(struct Crypto1State* s, uint32_t in, int x) {
|
||||
uint32_t ret = 0;
|
||||
uint32_t feedin, t, next_in;
|
||||
uint8_t next_ret;
|
||||
for(int i = 0; i <= 31; i++) {
|
||||
next_in = BEBIT(in, i);
|
||||
next_ret = filter(s->odd);
|
||||
feedin = next_ret & (!!x);
|
||||
feedin ^= LF_POLY_EVEN & s->even;
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
feedin ^= !!next_in;
|
||||
s->even = s->even << 1 | (evenparity32(feedin));
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
ret |= next_ret << (24 ^ i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint8_t get_nth_byte(uint32_t value, int n)
|
||||
{
|
||||
if (n < 0 || n > 3)
|
||||
{
|
||||
// Handle invalid input
|
||||
return 0;
|
||||
}
|
||||
return (value >> (8 * (3 - n))) & 0xFF;
|
||||
static uint8_t get_nth_byte(uint32_t value, int n) {
|
||||
if(n < 0 || n > 3) {
|
||||
// Handle invalid input
|
||||
return 0;
|
||||
}
|
||||
return (value >> (8 * (3 - n))) & 0xFF;
|
||||
}
|
||||
|
||||
static uint8_t crypt_bit(struct Crypto1State *s, uint8_t in, int is_encrypted)
|
||||
{
|
||||
uint32_t feedin, t;
|
||||
uint8_t ret = filter(s->odd);
|
||||
feedin = ret & !!is_encrypted;
|
||||
feedin ^= !!in;
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
feedin ^= LF_POLY_EVEN & s->even;
|
||||
s->even = s->even << 1 | evenparity32(feedin);
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
return ret;
|
||||
static uint8_t crypt_bit(struct Crypto1State* s, uint8_t in, int is_encrypted) {
|
||||
uint32_t feedin, t;
|
||||
uint8_t ret = filter(s->odd);
|
||||
feedin = ret & !!is_encrypted;
|
||||
feedin ^= !!in;
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
feedin ^= LF_POLY_EVEN & s->even;
|
||||
s->even = s->even << 1 | evenparity32(feedin);
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t crypt_word_par(
|
||||
struct Crypto1State *s,
|
||||
uint32_t in,
|
||||
int is_encrypted,
|
||||
uint32_t nt_plain,
|
||||
uint8_t *parity_keystream_bits)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
*parity_keystream_bits = 0; // Reset parity keystream bits
|
||||
struct Crypto1State* s,
|
||||
uint32_t in,
|
||||
int is_encrypted,
|
||||
uint32_t nt_plain,
|
||||
uint8_t* parity_keystream_bits) {
|
||||
uint32_t ret = 0;
|
||||
*parity_keystream_bits = 0; // Reset parity keystream bits
|
||||
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
uint8_t bit = crypt_bit(s, BEBIT(in, i), is_encrypted);
|
||||
ret |= bit << (24 ^ i);
|
||||
// Save keystream parity bit
|
||||
if ((i + 1) % 8 == 0)
|
||||
{
|
||||
*parity_keystream_bits |=
|
||||
(filter(s->odd) ^ nfc_util_even_parity8(get_nth_byte(nt_plain, i / 8)))
|
||||
<< (3 - (i / 8));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
for(int i = 0; i < 32; i++) {
|
||||
uint8_t bit = crypt_bit(s, BEBIT(in, i), is_encrypted);
|
||||
ret |= bit << (24 ^ i);
|
||||
// Save keystream parity bit
|
||||
if((i + 1) % 8 == 0) {
|
||||
*parity_keystream_bits |=
|
||||
(filter(s->odd) ^ nfc_util_even_parity8(get_nth_byte(nt_plain, i / 8)))
|
||||
<< (3 - (i / 8));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline void rollback_word_noret(struct Crypto1State *s, uint32_t in, int x)
|
||||
{
|
||||
uint8_t ret;
|
||||
uint32_t feedin, t, next_in;
|
||||
for (int i = 31; i >= 0; i--)
|
||||
{
|
||||
next_in = BEBIT(in, i);
|
||||
s->odd &= 0xffffff;
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
ret = filter(s->odd);
|
||||
feedin = ret & (!!x);
|
||||
feedin ^= s->even & 1;
|
||||
feedin ^= LF_POLY_EVEN & (s->even >>= 1);
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
feedin ^= !!next_in;
|
||||
s->even |= (evenparity32(feedin)) << 23;
|
||||
}
|
||||
return;
|
||||
static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x) {
|
||||
uint8_t ret;
|
||||
uint32_t feedin, t, next_in;
|
||||
for(int i = 31; i >= 0; i--) {
|
||||
next_in = BEBIT(in, i);
|
||||
s->odd &= 0xffffff;
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
ret = filter(s->odd);
|
||||
feedin = ret & (!!x);
|
||||
feedin ^= s->even & 1;
|
||||
feedin ^= LF_POLY_EVEN & (s->even >>= 1);
|
||||
feedin ^= LF_POLY_ODD & s->odd;
|
||||
feedin ^= !!next_in;
|
||||
s->even |= (evenparity32(feedin)) << 23;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO:
|
||||
@@ -227,39 +210,36 @@ uint32_t rollback_word(struct Crypto1State *s, uint32_t in, int x) {
|
||||
}
|
||||
*/
|
||||
|
||||
uint8_t napi_lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb)
|
||||
{
|
||||
int out;
|
||||
uint8_t ret;
|
||||
uint32_t t;
|
||||
s->odd &= 0xffffff;
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
uint8_t napi_lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb) {
|
||||
int out;
|
||||
uint8_t ret;
|
||||
uint32_t t;
|
||||
s->odd &= 0xffffff;
|
||||
t = s->odd, s->odd = s->even, s->even = t;
|
||||
|
||||
out = s->even & 1;
|
||||
out ^= LF_POLY_EVEN & (s->even >>= 1);
|
||||
out ^= LF_POLY_ODD & s->odd;
|
||||
out ^= !!in;
|
||||
out ^= (ret = filter(s->odd)) & !!fb;
|
||||
out = s->even & 1;
|
||||
out ^= LF_POLY_EVEN & (s->even >>= 1);
|
||||
out ^= LF_POLY_ODD & s->odd;
|
||||
out ^= !!in;
|
||||
out ^= (ret = filter(s->odd)) & !!fb;
|
||||
|
||||
s->even |= evenparity32(out) << 23;
|
||||
return ret;
|
||||
s->even |= evenparity32(out) << 23;
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t napi_lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb)
|
||||
{
|
||||
int i;
|
||||
uint32_t ret = 0;
|
||||
for (i = 31; i >= 0; --i)
|
||||
ret |= napi_lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24);
|
||||
return ret;
|
||||
uint32_t napi_lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb) {
|
||||
int i;
|
||||
uint32_t ret = 0;
|
||||
for(i = 31; i >= 0; --i)
|
||||
ret |= napi_lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline uint32_t prng_successor(uint32_t x, uint32_t n)
|
||||
{
|
||||
SWAPENDIAN(x);
|
||||
while (n--)
|
||||
x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
|
||||
return SWAPENDIAN(x);
|
||||
static inline uint32_t prng_successor(uint32_t x, uint32_t n) {
|
||||
SWAPENDIAN(x);
|
||||
while(n--)
|
||||
x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;
|
||||
return SWAPENDIAN(x);
|
||||
}
|
||||
|
||||
#endif // CRYPTO1_H
|
||||
File diff suppressed because it is too large
Load Diff
@@ -9,115 +9,103 @@
|
||||
#include <toolbox/stream/buffered_file_stream.h>
|
||||
#include <nfc/protocols/mf_classic/mf_classic.h>
|
||||
|
||||
struct Crypto1State
|
||||
{
|
||||
uint32_t odd, even;
|
||||
struct Crypto1State {
|
||||
uint32_t odd, even;
|
||||
};
|
||||
struct Msb
|
||||
{
|
||||
int tail;
|
||||
uint32_t states[768];
|
||||
struct Msb {
|
||||
int tail;
|
||||
uint32_t states[768];
|
||||
};
|
||||
|
||||
typedef enum
|
||||
{
|
||||
MissingNonces,
|
||||
ZeroNonces,
|
||||
InsufficientRAM,
|
||||
typedef enum {
|
||||
MissingNonces,
|
||||
ZeroNonces,
|
||||
InsufficientRAM,
|
||||
} MFKeyError;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Ready,
|
||||
Initializing,
|
||||
DictionaryAttack,
|
||||
MFKeyAttack,
|
||||
Complete,
|
||||
Error,
|
||||
Help,
|
||||
typedef enum {
|
||||
Ready,
|
||||
Initializing,
|
||||
DictionaryAttack,
|
||||
MFKeyAttack,
|
||||
Complete,
|
||||
Error,
|
||||
Help,
|
||||
} MFKeyState;
|
||||
|
||||
// TODO: Can we eliminate any of the members of this struct?
|
||||
typedef struct
|
||||
{
|
||||
FuriMutex *mutex;
|
||||
MFKeyError err;
|
||||
MFKeyState mfkey_state;
|
||||
int cracked;
|
||||
int unique_cracked;
|
||||
int num_completed;
|
||||
int num_candidates;
|
||||
int total;
|
||||
int dict_count;
|
||||
int search;
|
||||
int eta_timestamp;
|
||||
int eta_total;
|
||||
int eta_round;
|
||||
bool mfkey32_present;
|
||||
bool nested_present;
|
||||
bool close_thread_please;
|
||||
FuriThread *mfkeythread;
|
||||
KeysDict *cuid_dict;
|
||||
MfClassicKey *key_buffer;
|
||||
size_t key_buffer_size;
|
||||
size_t key_buffer_count;
|
||||
typedef struct {
|
||||
FuriMutex* mutex;
|
||||
MFKeyError err;
|
||||
MFKeyState mfkey_state;
|
||||
int cracked;
|
||||
int unique_cracked;
|
||||
int num_completed;
|
||||
int num_candidates;
|
||||
int total;
|
||||
int dict_count;
|
||||
int search;
|
||||
int eta_timestamp;
|
||||
int eta_total;
|
||||
int eta_round;
|
||||
bool mfkey32_present;
|
||||
bool nested_present;
|
||||
bool close_thread_please;
|
||||
FuriThread* mfkeythread;
|
||||
KeysDict* cuid_dict;
|
||||
MfClassicKey* key_buffer;
|
||||
size_t key_buffer_size;
|
||||
size_t key_buffer_count;
|
||||
} ProgramState;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
mfkey32,
|
||||
static_nested,
|
||||
static_encrypted
|
||||
typedef enum {
|
||||
mfkey32,
|
||||
static_nested,
|
||||
static_encrypted
|
||||
} AttackType;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
AttackType attack;
|
||||
MfClassicKey key; // key
|
||||
uint32_t uid; // serial number
|
||||
uint32_t nt0; // tag challenge first
|
||||
uint32_t nt1; // tag challenge second
|
||||
uint32_t uid_xor_nt0; // uid ^ nt0
|
||||
uint32_t uid_xor_nt1; // uid ^ nt1
|
||||
union
|
||||
{
|
||||
// Mfkey32
|
||||
struct
|
||||
{
|
||||
uint32_t p64; // 64th successor of nt0
|
||||
uint32_t p64b; // 64th successor of nt1
|
||||
uint32_t nr0_enc; // first encrypted reader challenge
|
||||
uint32_t ar0_enc; // first encrypted reader response
|
||||
uint32_t nr1_enc; // second encrypted reader challenge
|
||||
uint32_t ar1_enc; // second encrypted reader response
|
||||
};
|
||||
// Nested
|
||||
struct
|
||||
{
|
||||
uint32_t ks1_1_enc; // first encrypted keystream
|
||||
uint32_t ks1_2_enc; // second encrypted keystream
|
||||
char par_1_str[5]; // first parity bits (string representation)
|
||||
char par_2_str[5]; // second parity bits (string representation)
|
||||
uint8_t par_1; // first parity bits
|
||||
uint8_t par_2; // second parity bits
|
||||
};
|
||||
};
|
||||
typedef struct {
|
||||
AttackType attack;
|
||||
MfClassicKey key; // key
|
||||
uint32_t uid; // serial number
|
||||
uint32_t nt0; // tag challenge first
|
||||
uint32_t nt1; // tag challenge second
|
||||
uint32_t uid_xor_nt0; // uid ^ nt0
|
||||
uint32_t uid_xor_nt1; // uid ^ nt1
|
||||
union {
|
||||
// Mfkey32
|
||||
struct {
|
||||
uint32_t p64; // 64th successor of nt0
|
||||
uint32_t p64b; // 64th successor of nt1
|
||||
uint32_t nr0_enc; // first encrypted reader challenge
|
||||
uint32_t ar0_enc; // first encrypted reader response
|
||||
uint32_t nr1_enc; // second encrypted reader challenge
|
||||
uint32_t ar1_enc; // second encrypted reader response
|
||||
};
|
||||
// Nested
|
||||
struct {
|
||||
uint32_t ks1_1_enc; // first encrypted keystream
|
||||
uint32_t ks1_2_enc; // second encrypted keystream
|
||||
char par_1_str[5]; // first parity bits (string representation)
|
||||
char par_2_str[5]; // second parity bits (string representation)
|
||||
uint8_t par_1; // first parity bits
|
||||
uint8_t par_2; // second parity bits
|
||||
};
|
||||
};
|
||||
} MfClassicNonce;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Stream *stream;
|
||||
uint32_t total_nonces;
|
||||
MfClassicNonce *remaining_nonce_array;
|
||||
size_t remaining_nonces;
|
||||
typedef struct {
|
||||
Stream* stream;
|
||||
uint32_t total_nonces;
|
||||
MfClassicNonce* remaining_nonce_array;
|
||||
size_t remaining_nonces;
|
||||
} MfClassicNonceArray;
|
||||
|
||||
struct KeysDict
|
||||
{
|
||||
Stream *stream;
|
||||
size_t key_size;
|
||||
size_t key_size_symbols;
|
||||
size_t total_keys;
|
||||
struct KeysDict {
|
||||
Stream* stream;
|
||||
size_t key_size;
|
||||
size_t key_size_symbols;
|
||||
size_t total_keys;
|
||||
};
|
||||
|
||||
#endif // MFKEY_H
|
||||
Reference in New Issue
Block a user