|
|
@@ -32,35 +32,38 @@
|
|
|
#include <storage/storage.h>
|
|
|
|
|
|
// TODO: Remove defines that are not needed
|
|
|
-#define KEYS_DICT_SYSTEM_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc")
|
|
|
-#define KEYS_DICT_USER_PATH EXT_PATH("nfc/assets/mf_classic_dict_user.nfc")
|
|
|
-#define MF_CLASSIC_NONCE_PATH EXT_PATH("nfc/.mfkey32.log")
|
|
|
+#define KEYS_DICT_SYSTEM_PATH EXT_PATH("nfc/assets/mf_classic_dict.nfc")
|
|
|
+#define KEYS_DICT_USER_PATH EXT_PATH("nfc/assets/mf_classic_dict_user.nfc")
|
|
|
+#define MF_CLASSIC_NONCE_PATH EXT_PATH("nfc/.mfkey32.log")
|
|
|
#define MF_CLASSIC_NESTED_NONCE_PATH EXT_PATH("nfc/.nested")
|
|
|
-#define TAG "MFKey"
|
|
|
-#define MAX_NAME_LEN 32
|
|
|
-#define MAX_PATH_LEN 64
|
|
|
+#define TAG "MFKey"
|
|
|
+#define MAX_NAME_LEN 32
|
|
|
+#define MAX_PATH_LEN 64
|
|
|
|
|
|
-#define LF_POLY_ODD (0x29CE5C)
|
|
|
+#define LF_POLY_ODD (0x29CE5C)
|
|
|
#define LF_POLY_EVEN (0x870804)
|
|
|
-#define CONST_M1_1 (LF_POLY_EVEN << 1 | 1)
|
|
|
-#define CONST_M2_1 (LF_POLY_ODD << 1)
|
|
|
-#define CONST_M1_2 (LF_POLY_ODD)
|
|
|
-#define CONST_M2_2 (LF_POLY_EVEN << 1 | 1)
|
|
|
-#define BIT(x, n) ((x) >> (n) & 1)
|
|
|
-#define BEBIT(x, n) BIT(x, (n) ^ 24)
|
|
|
+#define CONST_M1_1 (LF_POLY_EVEN << 1 | 1)
|
|
|
+#define CONST_M2_1 (LF_POLY_ODD << 1)
|
|
|
+#define CONST_M1_2 (LF_POLY_ODD)
|
|
|
+#define CONST_M2_2 (LF_POLY_EVEN << 1 | 1)
|
|
|
+#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)
|
|
|
//#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};
|
|
|
@@ -391,9 +394,6 @@ int calculate_msb_tables(
|
|
|
|
|
|
void** allocate_blocks(const size_t* block_sizes, int num_blocks) {
|
|
|
void** block_pointers = malloc(num_blocks * sizeof(void*));
|
|
|
- if(block_pointers == NULL) {
|
|
|
- return NULL;
|
|
|
- }
|
|
|
|
|
|
for(int i = 0; i < num_blocks; i++) {
|
|
|
if(memmgr_heap_get_max_free_block() < block_sizes[i]) {
|
|
|
@@ -406,19 +406,15 @@ void** allocate_blocks(const size_t* block_sizes, int num_blocks) {
|
|
|
}
|
|
|
|
|
|
block_pointers[i] = malloc(block_sizes[i]);
|
|
|
- if(block_pointers[i] == NULL) {
|
|
|
- // Allocation failed, free previously allocated blocks
|
|
|
- for(int j = 0; j < i; j++) {
|
|
|
- free(block_pointers[j]);
|
|
|
- }
|
|
|
- free(block_pointers);
|
|
|
- return NULL;
|
|
|
- }
|
|
|
}
|
|
|
|
|
|
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 +423,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
|
|
|
@@ -675,9 +673,10 @@ static void render_callback(Canvas* const canvas, void* ctx) {
|
|
|
ProgramState* program_state = ctx;
|
|
|
furi_mutex_acquire(program_state->mutex, FuriWaitForever);
|
|
|
char draw_str[44] = {};
|
|
|
- canvas_clear(canvas);
|
|
|
+
|
|
|
canvas_draw_frame(canvas, 0, 0, 128, 64);
|
|
|
canvas_draw_frame(canvas, 0, 15, 128, 64);
|
|
|
+
|
|
|
canvas_set_font(canvas, FontPrimary);
|
|
|
canvas_draw_str_aligned(canvas, 5, 4, AlignLeft, AlignTop, "MFKey");
|
|
|
snprintf(draw_str, sizeof(draw_str), "RAM: %zub", memmgr_get_free_heap());
|
|
|
@@ -725,7 +724,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);
|
|
|
@@ -766,9 +765,7 @@ static void render_callback(Canvas* const canvas, void* 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((FuriMessageQueue*)event_queue, &event, FuriWaitForever);
|
|
|
+ furi_message_queue_put((FuriMessageQueue*)event_queue, input_event, FuriWaitForever);
|
|
|
}
|
|
|
|
|
|
static void mfkey_state_init(ProgramState* program_state) {
|
|
|
@@ -792,25 +789,14 @@ static int32_t mfkey_worker_thread(void* ctx) {
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-void start_mfkey_thread(ProgramState* program_state) {
|
|
|
- if(!program_state->is_thread_running) {
|
|
|
- furi_thread_start(program_state->mfkeythread);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
int32_t mfkey_main() {
|
|
|
- FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent));
|
|
|
+ FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
|
|
|
|
|
|
ProgramState* program_state = malloc(sizeof(ProgramState));
|
|
|
|
|
|
mfkey_state_init(program_state);
|
|
|
|
|
|
program_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
|
|
- if(!program_state->mutex) {
|
|
|
- //FURI_LOG_E(TAG, "cannot create mutex\r\n");
|
|
|
- free(program_state);
|
|
|
- return 255;
|
|
|
- }
|
|
|
|
|
|
// Set system callbacks
|
|
|
ViewPort* view_port = view_port_alloc();
|
|
|
@@ -822,72 +808,57 @@ int32_t mfkey_main() {
|
|
|
gui_add_view_port(gui, view_port, GuiLayerFullscreen);
|
|
|
|
|
|
program_state->mfkeythread = furi_thread_alloc();
|
|
|
- furi_thread_set_name(program_state->mfkeythread, "MFKey Worker");
|
|
|
+ furi_thread_set_name(program_state->mfkeythread, "MFKeyWorker");
|
|
|
furi_thread_set_stack_size(program_state->mfkeythread, 2048);
|
|
|
furi_thread_set_context(program_state->mfkeythread, program_state);
|
|
|
furi_thread_set_callback(program_state->mfkeythread, mfkey_worker_thread);
|
|
|
|
|
|
- PluginEvent event;
|
|
|
+ InputEvent input_event;
|
|
|
for(bool main_loop = true; main_loop;) {
|
|
|
- FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100);
|
|
|
+ FuriStatus event_status = furi_message_queue_get(event_queue, &input_event, 100);
|
|
|
|
|
|
furi_mutex_acquire(program_state->mutex, FuriWaitForever);
|
|
|
|
|
|
if(event_status == FuriStatusOk) {
|
|
|
- // press events
|
|
|
- if(event.type == EventTypeKey) {
|
|
|
- if(event.input.type == InputTypePress) {
|
|
|
- switch(event.input.key) {
|
|
|
- case InputKeyUp:
|
|
|
- break;
|
|
|
- case InputKeyDown:
|
|
|
- break;
|
|
|
- case InputKeyRight:
|
|
|
- if(!program_state->is_thread_running &&
|
|
|
- program_state->mfkey_state == Ready) {
|
|
|
- program_state->mfkey_state = Help;
|
|
|
- view_port_update(view_port);
|
|
|
- }
|
|
|
- break;
|
|
|
- case InputKeyLeft:
|
|
|
- break;
|
|
|
- case InputKeyOk:
|
|
|
- if(!program_state->is_thread_running &&
|
|
|
- program_state->mfkey_state == Ready) {
|
|
|
- start_mfkey_thread(program_state);
|
|
|
- view_port_update(view_port);
|
|
|
- }
|
|
|
- break;
|
|
|
- case InputKeyBack:
|
|
|
- if(!program_state->is_thread_running &&
|
|
|
- program_state->mfkey_state == Help) {
|
|
|
- program_state->mfkey_state = Ready;
|
|
|
- view_port_update(view_port);
|
|
|
- } else {
|
|
|
- program_state->close_thread_please = true;
|
|
|
- if(program_state->is_thread_running && program_state->mfkeythread) {
|
|
|
- // Wait until thread is finished
|
|
|
- furi_thread_join(program_state->mfkeythread);
|
|
|
- }
|
|
|
- program_state->close_thread_please = false;
|
|
|
- main_loop = false;
|
|
|
+ if(input_event.type == InputTypePress) {
|
|
|
+ switch(input_event.key) {
|
|
|
+ case InputKeyRight:
|
|
|
+ if(!program_state->is_thread_running && program_state->mfkey_state == Ready) {
|
|
|
+ program_state->mfkey_state = Help;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case InputKeyOk:
|
|
|
+ if(!program_state->is_thread_running && program_state->mfkey_state == Ready) {
|
|
|
+ furi_thread_start(program_state->mfkeythread);
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case InputKeyBack:
|
|
|
+ if(!program_state->is_thread_running && program_state->mfkey_state == Help) {
|
|
|
+ program_state->mfkey_state = Ready;
|
|
|
+ } else {
|
|
|
+ program_state->close_thread_please = true;
|
|
|
+ if(program_state->is_thread_running) {
|
|
|
+ // Wait until thread is finished
|
|
|
+ furi_thread_join(program_state->mfkeythread);
|
|
|
}
|
|
|
- break;
|
|
|
- default:
|
|
|
- break;
|
|
|
+ program_state->close_thread_please = false;
|
|
|
+ main_loop = false;
|
|
|
}
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ break;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- view_port_update(view_port);
|
|
|
furi_mutex_release(program_state->mutex);
|
|
|
+ view_port_update(view_port);
|
|
|
}
|
|
|
|
|
|
furi_thread_free(program_state->mfkeythread);
|
|
|
view_port_enabled_set(view_port, false);
|
|
|
gui_remove_view_port(gui, view_port);
|
|
|
- furi_record_close("gui");
|
|
|
+ furi_record_close(RECORD_GUI);
|
|
|
view_port_free(view_port);
|
|
|
furi_message_queue_free(event_queue);
|
|
|
furi_mutex_free(program_state->mutex);
|
|
|
@@ -895,4 +866,4 @@ int32_t mfkey_main() {
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
-#pragma GCC pop_options
|
|
|
+#pragma GCC pop_options
|