noproto 1 год назад
Родитель
Сommit
f35ab2bc6a
3 измененных файлов с 73 добавлено и 13 удалено
  1. 5 3
      application.fam
  2. 49 0
      crypto1.h
  3. 19 10
      mfkey.c

+ 5 - 3
application.fam

@@ -10,11 +10,12 @@ App(
     ],
     stack_size=1 * 1024,
     fap_icon="mfkey.png",
-    fap_category="Nfc",
-    fap_author="noproto",
+    fap_category="NFC",
+    fap_author="@noproto",
     fap_icon_assets="images",
     fap_weburl="https://github.com/noproto/FlipperMfkey",
-    fap_version="2.2",
+    fap_description="MIFARE Classic key recovery tool",
+    fap_version="2.7",
 )
 
 App(
@@ -23,4 +24,5 @@ App(
     entry_point="init_plugin_ep",
     requires=["mfkey"],
     sources=["init_plugin.c"],
+    fal_embedded=True,
 )

+ 49 - 0
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;

+ 19 - 10
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
@@ -532,7 +541,7 @@ void mfkey(ProgramState* program_state) {
     //FURI_LOG_I(TAG, "Free heap before alloc(): %zub", memmgr_get_free_heap());
     Storage* storage = furi_record_open(RECORD_STORAGE);
     FlipperApplication* app = flipper_application_alloc(storage, firmware_api_interface);
-    flipper_application_preload(app, APP_DATA_PATH("plugins/mfkey_init_plugin.fal"));
+    flipper_application_preload(app, APP_ASSETS_PATH("plugins/mfkey_init_plugin.fal"));
     flipper_application_map_to_memory(app);
     const FlipperAppPluginDescriptor* app_descriptor =
         flipper_application_plugin_get_descriptor(app);
@@ -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);
@@ -764,11 +773,11 @@ static void render_callback(Canvas* const canvas, void* ctx) {
     furi_mutex_release(program_state->mutex);
 }
 
-static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
+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) {