Skip to content

Commit

Permalink
Replace Mfkey32 with MFKey
Browse files Browse the repository at this point in the history
  • Loading branch information
noproto committed Mar 21, 2024
1 parent 8245889 commit 7b4b27b
Show file tree
Hide file tree
Showing 18 changed files with 1,632 additions and 3,006 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
App(
appid="mfkeynested",
name="MFKey Nested",
appid="mfkey",
name="MFKey",
apptype=FlipperAppType.EXTERNAL,
targets=["f7"],
entry_point="mfkey_main",
Expand All @@ -11,7 +11,17 @@ App(
stack_size=1 * 1024,
fap_icon="mfkey.png",
fap_category="NFC",
fap_author="noproto",
fap_author="@noproto",
fap_icon_assets="images",
fap_weburl="https://github.com/noproto/FlipperMfkey",
fap_description="MIFARE Classic key recovery tool",
fap_version="2.0",
)

App(
appid="mfkey_init_plugin",
apptype=FlipperAppType.PLUGIN,
entry_point="init_plugin_ep",
requires=["mfkey"],
sources=["init_plugin.c"],
)
20 changes: 20 additions & 0 deletions base_pack/mfkey/common.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#ifndef COMMON_H
#define COMMON_H

#include <inttypes.h>

inline uint64_t napi_nfc_util_bytes2num(const uint8_t* src, uint8_t len);

inline uint64_t napi_nfc_util_bytes2num(const uint8_t* src, uint8_t len) {
furi_assert(src);
furi_assert(len <= 8);

uint64_t res = 0;
while(len--) {
res = (res << 8) | (*src);
src++;
}
return res;
}

#endif // COMMON_H
22 changes: 22 additions & 0 deletions base_pack/mfkey/crypto1.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#pragma GCC optimize("O3")
#pragma GCC optimize("-funroll-all-loops")

#include <inttypes.h>
#include "crypto1.h"
#include "mfkey.h"

#define BIT(x, n) ((x) >> (n) & 1)

void crypto1_get_lfsr(struct Crypto1State* state, MfClassicKey* lfsr) {
int i;
uint64_t lfsr_value = 0;
for(i = 23; i >= 0; --i) {
lfsr_value = lfsr_value << 1 | BIT(state->odd, i ^ 3);
lfsr_value = lfsr_value << 1 | BIT(state->even, i ^ 3);
}

// Assign the key value to the MfClassicKey struct
for(i = 0; i < 6; ++i) {
lfsr->data[i] = (lfsr_value >> ((5 - i) * 8)) & 0xFF;
}
}
156 changes: 156 additions & 0 deletions base_pack/mfkey/crypto1.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#ifndef CRYPTO1_H
#define CRYPTO1_H

#include <inttypes.h>
#include "mfkey.h"
#include <nfc/protocols/mf_classic/mf_classic.h>

#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 SWAPENDIAN(x) \
((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);
static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int x);

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};
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};

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);
}

#ifndef __ARM_ARCH_7EM__
static inline uint8_t evenparity32(uint32_t x) {
return __builtin_parity(x);
}
#endif

#ifdef __ARM_ARCH_7EM__
static inline uint8_t evenparity32(uint32_t x) {
uint32_t result;
__asm__ volatile("eor r1, %[x], %[x], lsr #16 \n\t" // r1 = x ^ (x >> 16)
"eor r1, r1, r1, lsr #8 \n\t" // r1 = r1 ^ (r1 >> 8)
"eor r1, r1, r1, lsr #4 \n\t" // r1 = r1 ^ (r1 >> 4)
"eor r1, r1, r1, lsr #2 \n\t" // r1 = r1 ^ (r1 >> 2)
"eor r1, r1, r1, lsr #1 \n\t" // r1 = r1 ^ (r1 >> 1)
"and %[result], r1, #1 \n\t" // result = r1 & 1
: [result] "=r"(result)
: [x] "r"(x)
: "r1");
return result;
}
#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 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 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 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 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
Binary file added base_pack/mfkey/images/mfkey.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 7b4b27b

Please sign in to comment.