Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update MFKey to v2.7 #231

Merged
merged 4 commits into from
Jul 24, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions mfkey/.catalog/changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
## 2.7
- Mfkey32 recovery is 30% faster, fix UI and slowdown bugs
## 2.6
- Version bump for catalog build system
## 2.5
Expand Down
2 changes: 1 addition & 1 deletion mfkey/application.fam
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ App(
fap_icon_assets="images",
fap_weburl="https://github.com/noproto/FlipperMfkey",
fap_description="MIFARE Classic key recovery tool",
fap_version="2.6",
fap_version="2.7",
)

App(
Expand Down
49 changes: 49 additions & 0 deletions mfkey/crypto1.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ 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 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,
Expand Down Expand Up @@ -147,6 +149,53 @@ static inline void rollback_word_noret(struct Crypto1State* s, uint32_t in, int
return;
}

// TODO:
/*
uint32_t rollback_word(struct Crypto1State *s, uint32_t in, int x) {
uint32_t res_ret = 0;
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;
res_ret |= (ret << (24 ^ i));
}
return res_ret;
}
*/

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;

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

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;
Expand Down
23 changes: 16 additions & 7 deletions mfkey/mfkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -52,15 +52,18 @@
((x) = ((x) >> 8 & 0xff00ff) | ((x) & 0xff00ff) << 8, (x) = (x) >> 16 | (x) << 16)
//#define SIZEOF(arr) sizeof(arr) / sizeof(*arr)

static int eta_round_time = 56;
static int eta_total_time = 900;
static int eta_round_time = 44;
static int eta_total_time = 705;
// MSB_LIMIT: Chunk size (out of 256)
static int MSB_LIMIT = 16;

int check_state(struct Crypto1State* t, MfClassicNonce* n) {
if(!(t->odd | t->even)) return 0;
if(n->attack == mfkey32) {
rollback_word_noret(t, 0, 0);
uint32_t rb = (napi_lfsr_rollback_word(t, 0, 0) ^ n->p64);
if(rb != n->ar0_enc) {
return 0;
}
rollback_word_noret(t, n->nr0_enc, 1);
rollback_word_noret(t, n->uid_xor_nt0, 0);
struct Crypto1State temp = {t->odd, t->even};
Expand Down Expand Up @@ -419,6 +422,10 @@ void** allocate_blocks(const size_t* block_sizes, int num_blocks) {
return block_pointers;
}

bool is_full_speed() {
return MSB_LIMIT == 16;
}

bool recover(MfClassicNonce* n, int ks2, unsigned int in, ProgramState* program_state) {
bool found = false;
const size_t block_sizes[] = {49216, 49216, 5120, 5120, 4096};
Expand All @@ -427,9 +434,11 @@ bool recover(MfClassicNonce* n, int ks2, unsigned int in, ProgramState* program_
void** block_pointers = allocate_blocks(block_sizes, num_blocks);
if(block_pointers == NULL) {
// System has less than the guaranteed amount of RAM (140 KB) - adjust some parameters to run anyway at half speed
eta_round_time *= 2;
eta_total_time *= 2;
MSB_LIMIT /= 2;
if(is_full_speed()) {
//eta_round_time *= 2;
eta_total_time *= 2;
MSB_LIMIT /= 2;
}
block_pointers = allocate_blocks(reduced_block_sizes, num_blocks);
if(block_pointers == NULL) {
// System has less than 70 KB of RAM - should never happen so we don't reduce speed further
Expand Down Expand Up @@ -725,7 +734,7 @@ static void render_callback(Canvas* const canvas, void* ctx) {
canvas_draw_str_aligned(canvas, 26, 28, AlignLeft, AlignTop, draw_str);
} else if(program_state->mfkey_state == Complete) {
// TODO: Scrollable list view to see cracked keys if user presses down
elements_progress_bar_with_text(canvas, 5, 18, 118, 1, draw_str);
elements_progress_bar(canvas, 5, 18, 118, 1);
canvas_set_font(canvas, FontSecondary);
snprintf(draw_str, sizeof(draw_str), "Complete");
canvas_draw_str_aligned(canvas, 40, 31, AlignLeft, AlignTop, draw_str);
Expand Down