瀏覽代碼

Merge mfkey from https://github.com/noproto/FlipperMfkey

# Conflicts:
#	mfkey/application.fam
#	mfkey/mfkey.c
Willy-JL 1 年之前
父節點
當前提交
2f3a0e252f
共有 3 個文件被更改,包括 71 次插入12 次删除
  1. 1 1
      mfkey/application.fam
  2. 49 0
      mfkey/crypto1.h
  3. 21 11
      mfkey/mfkey.c

+ 1 - 1
mfkey/application.fam

@@ -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(

+ 49 - 0
mfkey/crypto1.h

@@ -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,
@@ -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;

+ 21 - 11
mfkey/mfkey.c

@@ -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};
@@ -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};
@@ -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
@@ -721,7 +730,9 @@ static void render_callback(Canvas* const canvas, void* ctx) {
     } else if(program_state->mfkey_state == Complete) {
         // TODO: Scrollable list view to see cracked keys if user presses down
         elements_progress_bar(canvas, 5, 18, 118, 1);
-        canvas_draw_str_aligned(canvas, 40, 31, AlignLeft, AlignTop, "Complete");
+        canvas_set_font(canvas, FontSecondary);
+        snprintf(draw_str, sizeof(draw_str), "Complete");
+        canvas_draw_str_aligned(canvas, 40, 31, AlignLeft, AlignTop, draw_str);
         snprintf(
             draw_str,
             sizeof(draw_str),
@@ -756,12 +767,11 @@ static void render_callback(Canvas* const canvas, void* ctx) {
     furi_mutex_release(program_state->mutex);
 }
 
-static void input_callback(InputEvent* input_event, void* ctx) {
-    furi_assert(ctx);
-    FuriMessageQueue* event_queue = ctx;
+static void input_callback(InputEvent* input_event, void* event_queue) {
+    furi_assert(event_queue);
 
     PluginEvent event = {.type = EventTypeKey, .input = *input_event};
-    furi_message_queue_put(event_queue, &event, FuriWaitForever);
+    furi_message_queue_put((FuriMessageQueue*)event_queue, &event, FuriWaitForever);
 }
 
 static void mfkey_state_init(ProgramState* program_state) {