1
mirror of https://github.com/DarkFlippers/unleashed-firmware.git synced 2025-12-12 20:49:49 +04:00
This commit is contained in:
MX
2025-09-09 15:34:19 +03:00
parent ffb8eb7cff
commit 40c6c8b59c
3 changed files with 1269 additions and 1512 deletions

View File

@@ -54,8 +54,7 @@ static const uint8_t lookup2[256] = {
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, 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}; 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) static inline int filter(uint32_t const x) {
{
uint32_t f; uint32_t f;
f = lookup1[x & 0xff] | lookup2[(x >> 8) & 0xff]; f = lookup1[x & 0xff] | lookup2[(x >> 8) & 0xff];
f |= 0x0d938 >> (x >> 16 & 0xf) & 1; f |= 0x0d938 >> (x >> 16 & 0xf) & 1;
@@ -63,8 +62,7 @@ static inline int filter(uint32_t const x)
} }
#ifdef __ARM_ARCH_7EM__ #ifdef __ARM_ARCH_7EM__
static inline uint8_t evenparity32(uint32_t x) static inline uint8_t evenparity32(uint32_t x) {
{
// fold 32 bits -> 16 -> 8 -> 4 // fold 32 bits -> 16 -> 8 -> 4
x ^= x >> 16; x ^= x >> 16;
x ^= x >> 8; x ^= x >> 8;
@@ -74,21 +72,18 @@ static inline uint8_t evenparity32(uint32_t x)
} }
#endif #endif
static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2) static inline void update_contribution(unsigned int data[], int item, int mask1, int mask2) {
{
int p = data[item] >> 25; int p = data[item] >> 25;
p = p << 1 | evenparity32(data[item] & mask1); p = p << 1 | evenparity32(data[item] & mask1);
p = p << 1 | evenparity32(data[item] & mask2); p = p << 1 | evenparity32(data[item] & mask2);
data[item] = p << 24 | (data[item] & 0xffffff); data[item] = p << 24 | (data[item] & 0xffffff);
} }
static inline uint32_t crypt_word(struct Crypto1State *s) static inline uint32_t crypt_word(struct Crypto1State* s) {
{
// "in" and "x" are always 0 (last iteration) // "in" and "x" are always 0 (last iteration)
uint32_t res_ret = 0; uint32_t res_ret = 0;
uint32_t feedin, t; uint32_t feedin, t;
for (int i = 0; i <= 31; i++) for(int i = 0; i <= 31; i++) {
{
res_ret |= (filter(s->odd) << (24 ^ i)); //-V629 res_ret |= (filter(s->odd) << (24 ^ i)); //-V629
feedin = LF_POLY_EVEN & s->even; feedin = LF_POLY_EVEN & s->even;
feedin ^= LF_POLY_ODD & s->odd; feedin ^= LF_POLY_ODD & s->odd;
@@ -98,12 +93,10 @@ static inline uint32_t crypt_word(struct Crypto1State *s)
return res_ret; return res_ret;
} }
static inline void crypt_word_noret(struct Crypto1State *s, uint32_t in, int x) static inline void crypt_word_noret(struct Crypto1State* s, uint32_t in, int x) {
{
uint8_t ret; uint8_t ret;
uint32_t feedin, t, next_in; uint32_t feedin, t, next_in;
for (int i = 0; i <= 31; i++) for(int i = 0; i <= 31; i++) {
{
next_in = BEBIT(in, i); next_in = BEBIT(in, i);
ret = filter(s->odd); ret = filter(s->odd);
feedin = ret & (!!x); feedin = ret & (!!x);
@@ -116,13 +109,11 @@ static inline void crypt_word_noret(struct Crypto1State *s, uint32_t in, int x)
return; return;
} }
static inline uint32_t crypt_word_ret(struct Crypto1State *s, uint32_t in, int x) static inline uint32_t crypt_word_ret(struct Crypto1State* s, uint32_t in, int x) {
{
uint32_t ret = 0; uint32_t ret = 0;
uint32_t feedin, t, next_in; uint32_t feedin, t, next_in;
uint8_t next_ret; uint8_t next_ret;
for (int i = 0; i <= 31; i++) for(int i = 0; i <= 31; i++) {
{
next_in = BEBIT(in, i); next_in = BEBIT(in, i);
next_ret = filter(s->odd); next_ret = filter(s->odd);
feedin = next_ret & (!!x); feedin = next_ret & (!!x);
@@ -136,18 +127,15 @@ static inline uint32_t crypt_word_ret(struct Crypto1State *s, uint32_t in, int x
return ret; return ret;
} }
static uint8_t get_nth_byte(uint32_t value, int n) static uint8_t get_nth_byte(uint32_t value, int n) {
{ if(n < 0 || n > 3) {
if (n < 0 || n > 3)
{
// Handle invalid input // Handle invalid input
return 0; return 0;
} }
return (value >> (8 * (3 - n))) & 0xFF; return (value >> (8 * (3 - n))) & 0xFF;
} }
static uint8_t crypt_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) static uint8_t crypt_bit(struct Crypto1State* s, uint8_t in, int is_encrypted) {
{
uint32_t feedin, t; uint32_t feedin, t;
uint8_t ret = filter(s->odd); uint8_t ret = filter(s->odd);
feedin = ret & !!is_encrypted; feedin = ret & !!is_encrypted;
@@ -164,18 +152,15 @@ static inline uint32_t crypt_word_par(
uint32_t in, uint32_t in,
int is_encrypted, int is_encrypted,
uint32_t nt_plain, uint32_t nt_plain,
uint8_t *parity_keystream_bits) uint8_t* parity_keystream_bits) {
{
uint32_t ret = 0; uint32_t ret = 0;
*parity_keystream_bits = 0; // Reset parity keystream bits *parity_keystream_bits = 0; // Reset parity keystream bits
for (int i = 0; i < 32; i++) for(int i = 0; i < 32; i++) {
{
uint8_t bit = crypt_bit(s, BEBIT(in, i), is_encrypted); uint8_t bit = crypt_bit(s, BEBIT(in, i), is_encrypted);
ret |= bit << (24 ^ i); ret |= bit << (24 ^ i);
// Save keystream parity bit // Save keystream parity bit
if ((i + 1) % 8 == 0) if((i + 1) % 8 == 0) {
{
*parity_keystream_bits |= *parity_keystream_bits |=
(filter(s->odd) ^ nfc_util_even_parity8(get_nth_byte(nt_plain, i / 8))) (filter(s->odd) ^ nfc_util_even_parity8(get_nth_byte(nt_plain, i / 8)))
<< (3 - (i / 8)); << (3 - (i / 8));
@@ -184,12 +169,10 @@ static inline uint32_t crypt_word_par(
return ret; return ret;
} }
static inline void rollback_word_noret(struct Crypto1State *s, uint32_t in, int x) static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x) {
{
uint8_t ret; uint8_t ret;
uint32_t feedin, t, next_in; uint32_t feedin, t, next_in;
for (int i = 31; i >= 0; i--) for(int i = 31; i >= 0; i--) {
{
next_in = BEBIT(in, i); next_in = BEBIT(in, i);
s->odd &= 0xffffff; s->odd &= 0xffffff;
t = s->odd, s->odd = s->even, s->even = t; t = s->odd, s->odd = s->even, s->even = t;
@@ -227,8 +210,7 @@ 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) uint8_t napi_lfsr_rollback_bit(struct Crypto1State* s, uint32_t in, int fb) {
{
int out; int out;
uint8_t ret; uint8_t ret;
uint32_t t; uint32_t t;
@@ -245,8 +227,7 @@ uint8_t napi_lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb)
return ret; return ret;
} }
uint32_t napi_lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) uint32_t napi_lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb) {
{
int i; int i;
uint32_t ret = 0; uint32_t ret = 0;
for(i = 31; i >= 0; --i) for(i = 31; i >= 0; --i)
@@ -254,8 +235,7 @@ uint32_t napi_lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb)
return ret; return ret;
} }
static inline uint32_t prng_successor(uint32_t x, uint32_t n) static inline uint32_t prng_successor(uint32_t x, uint32_t n) {
{
SWAPENDIAN(x); SWAPENDIAN(x);
while(n--) while(n--)
x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31;

File diff suppressed because it is too large Load Diff

View File

@@ -9,25 +9,21 @@
#include <toolbox/stream/buffered_file_stream.h> #include <toolbox/stream/buffered_file_stream.h>
#include <nfc/protocols/mf_classic/mf_classic.h> #include <nfc/protocols/mf_classic/mf_classic.h>
struct Crypto1State struct Crypto1State {
{
uint32_t odd, even; uint32_t odd, even;
}; };
struct Msb struct Msb {
{
int tail; int tail;
uint32_t states[768]; uint32_t states[768];
}; };
typedef enum typedef enum {
{
MissingNonces, MissingNonces,
ZeroNonces, ZeroNonces,
InsufficientRAM, InsufficientRAM,
} MFKeyError; } MFKeyError;
typedef enum typedef enum {
{
Ready, Ready,
Initializing, Initializing,
DictionaryAttack, DictionaryAttack,
@@ -38,8 +34,7 @@ typedef enum
} MFKeyState; } MFKeyState;
// TODO: Can we eliminate any of the members of this struct? // TODO: Can we eliminate any of the members of this struct?
typedef struct typedef struct {
{
FuriMutex* mutex; FuriMutex* mutex;
MFKeyError err; MFKeyError err;
MFKeyState mfkey_state; MFKeyState mfkey_state;
@@ -63,15 +58,13 @@ typedef struct
size_t key_buffer_count; size_t key_buffer_count;
} ProgramState; } ProgramState;
typedef enum typedef enum {
{
mfkey32, mfkey32,
static_nested, static_nested,
static_encrypted static_encrypted
} AttackType; } AttackType;
typedef struct typedef struct {
{
AttackType attack; AttackType attack;
MfClassicKey key; // key MfClassicKey key; // key
uint32_t uid; // serial number uint32_t uid; // serial number
@@ -79,11 +72,9 @@ typedef struct
uint32_t nt1; // tag challenge second uint32_t nt1; // tag challenge second
uint32_t uid_xor_nt0; // uid ^ nt0 uint32_t uid_xor_nt0; // uid ^ nt0
uint32_t uid_xor_nt1; // uid ^ nt1 uint32_t uid_xor_nt1; // uid ^ nt1
union union {
{
// Mfkey32 // Mfkey32
struct struct {
{
uint32_t p64; // 64th successor of nt0 uint32_t p64; // 64th successor of nt0
uint32_t p64b; // 64th successor of nt1 uint32_t p64b; // 64th successor of nt1
uint32_t nr0_enc; // first encrypted reader challenge uint32_t nr0_enc; // first encrypted reader challenge
@@ -92,8 +83,7 @@ typedef struct
uint32_t ar1_enc; // second encrypted reader response uint32_t ar1_enc; // second encrypted reader response
}; };
// Nested // Nested
struct struct {
{
uint32_t ks1_1_enc; // first encrypted keystream uint32_t ks1_1_enc; // first encrypted keystream
uint32_t ks1_2_enc; // second encrypted keystream uint32_t ks1_2_enc; // second encrypted keystream
char par_1_str[5]; // first parity bits (string representation) char par_1_str[5]; // first parity bits (string representation)
@@ -104,16 +94,14 @@ typedef struct
}; };
} MfClassicNonce; } MfClassicNonce;
typedef struct typedef struct {
{
Stream* stream; Stream* stream;
uint32_t total_nonces; uint32_t total_nonces;
MfClassicNonce* remaining_nonce_array; MfClassicNonce* remaining_nonce_array;
size_t remaining_nonces; size_t remaining_nonces;
} MfClassicNonceArray; } MfClassicNonceArray;
struct KeysDict struct KeysDict {
{
Stream* stream; Stream* stream;
size_t key_size; size_t key_size;
size_t key_size_symbols; size_t key_size_symbols;