Просмотр исходного кода

pre-functional stuff for mfc data loading

Luu 11 месяцев назад
Родитель
Сommit
e0d70441aa
5 измененных файлов с 254 добавлено и 114 удалено
  1. 1 1
      metroflip_i.h
  2. 157 95
      scenes/keys.c
  3. 4 1
      scenes/metroflip_scene_auto.c
  4. 53 2
      scenes/metroflip_scene_load.c
  5. 39 15
      scenes/plugins/bip.c

+ 1 - 1
metroflip_i.h

@@ -149,7 +149,7 @@ typedef enum {
     MISSING_KEYFILE
 } KeyfileManager;
 
-CardType determine_card_type(Nfc* nfc);
+CardType determine_card_type(Nfc* nfc, MfClassicData* mfc_data, bool data_loaded);
 
 #ifdef FW_ORIGIN_Official
 #define submenu_add_lockable_item(                                             \

+ 157 - 95
scenes/keys.c

@@ -9,11 +9,11 @@
 
 #define TAG "keys_check"
 
-const MfClassicKeyPair troika_1k_key[1] = {
+const MfClassicKeyPair troika_1k_key[] = {
     {.a = 0x08b386463229},
 };
 
-const MfClassicKeyPair troika_4k_key[1] = {
+const MfClassicKeyPair troika_4k_key[] = {
     {.a = 0xA73F5DC1D333},
 };
 
@@ -25,111 +25,157 @@ const MfClassicKeyPair charliecard_1k_verify_key[] = {
     {.a = 0x5EC39B022F2B},
 };
 
-const MfClassicKeyPair bip_1k_verify_key[1] = {
+const MfClassicKeyPair bip_1k_verify_key[] = {
     {.a = 0x3a42f33af429},
 };
 
-const MfClassicKeyPair metromoney_1k_verify_key[1] = {
+const MfClassicKeyPair metromoney_1k_verify_key[] = {
     {.a = 0x9C616585E26D},
 };
 
-static bool charliecard_verify(Nfc* nfc) {
+static bool charliecard_verify(Nfc* nfc, MfClassicData* mfc_data, bool data_loaded) {
     bool verified = false;
     FURI_LOG_I(TAG, "verifying charliecard..");
-
+    const uint8_t verify_sector = 1;
     do {
-        const uint8_t verify_sector = 1;
-        const uint8_t verify_block = mf_classic_get_first_block_num_of_sector(verify_sector) + 1;
-        FURI_LOG_I(TAG, "Verifying sector %u", verify_sector);
-
-        MfClassicKey key = {0};
-        bit_lib_num_to_bytes_be(charliecard_1k_verify_key[0].a, COUNT_OF(key.data), key.data);
-
-        MfClassicAuthContext auth_context;
-        MfClassicError error =
-            mf_classic_poller_sync_auth(nfc, verify_block, &key, MfClassicKeyTypeA, &auth_context);
-        if(error != MfClassicErrorNone) {
-            FURI_LOG_I(TAG, "Failed to read block %u: %d", verify_block, error);
-            break;
+        if(!data_loaded) {
+            const uint8_t verify_block =
+                mf_classic_get_first_block_num_of_sector(verify_sector) + 1;
+            FURI_LOG_I(TAG, "Verifying sector %u", verify_sector);
+
+            MfClassicKey key = {0};
+            bit_lib_num_to_bytes_be(charliecard_1k_verify_key[0].a, COUNT_OF(key.data), key.data);
+
+            MfClassicAuthContext auth_context;
+            MfClassicError error = mf_classic_poller_sync_auth(
+                nfc, verify_block, &key, MfClassicKeyTypeA, &auth_context);
+            if(error != MfClassicErrorNone) {
+                FURI_LOG_I(TAG, "Failed to read block %u: %d", verify_block, error);
+                break;
+            }
+
+            verified = true;
+        } else {
+            MfClassicSectorTrailer* sec_tr =
+                mf_classic_get_sector_trailer_by_sector(mfc_data, verify_sector);
+            FURI_LOG_I(TAG, "%2x", sec_tr->key_a.data[1]);
+            uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
+            if(key != charliecard_1k_verify_key[0].a) {
+                FURI_LOG_I(TAG, "not equall");
+                break;
+            }
+
+            verified = true;
         }
-
-        verified = true;
     } while(false);
 
     return verified;
 }
 
-bool bip_verify(Nfc* nfc) {
+bool bip_verify(Nfc* nfc, MfClassicData* mfc_data, bool data_loaded) {
     bool verified = false;
 
     do {
-        const uint8_t verify_sector = 0;
-        uint8_t block_num = mf_classic_get_first_block_num_of_sector(verify_sector);
-        FURI_LOG_I(TAG, "Verifying sector %u", verify_sector);
+        if(!data_loaded) {
+            const uint8_t verify_sector = 0;
+            uint8_t block_num = mf_classic_get_first_block_num_of_sector(verify_sector);
+            FURI_LOG_I(TAG, "Verifying sector %u", verify_sector);
 
-        MfClassicKey key = {};
-        bit_lib_num_to_bytes_be(bip_1k_verify_key[0].a, COUNT_OF(key.data), key.data);
+            MfClassicKey key = {};
+            bit_lib_num_to_bytes_be(bip_1k_verify_key[0].a, COUNT_OF(key.data), key.data);
 
-        MfClassicAuthContext auth_ctx = {};
-        MfClassicError error =
-            mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_ctx);
+            MfClassicAuthContext auth_ctx = {};
+            MfClassicError error =
+                mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_ctx);
 
-        if(error != MfClassicErrorNone) {
-            FURI_LOG_I(TAG, "Failed to read block %u: %d", block_num, error);
-            break;
-        }
+            if(error != MfClassicErrorNone) {
+                FURI_LOG_I(TAG, "Failed to read block %u: %d", block_num, error);
+                break;
+            }
+
+            verified = true;
+        } else {
+            MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(mfc_data, 0);
 
-        verified = true;
+            uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
+            if(key != bip_1k_verify_key[0].a) {
+                break;
+            }
+
+            verified = true;
+        }
     } while(false);
 
     return verified;
 }
 
-static bool metromoney_verify(Nfc* nfc) {
+static bool metromoney_verify(Nfc* nfc, MfClassicData* mfc_data, bool data_loaded) {
     bool verified = false;
-
+    const uint8_t ticket_sector_number = 1;
     do {
-        const uint8_t ticket_sector_number = 1;
-        const uint8_t ticket_block_number =
-            mf_classic_get_first_block_num_of_sector(ticket_sector_number) + 1;
-        FURI_LOG_D(TAG, "Verifying sector %u", ticket_sector_number);
-
-        MfClassicKey key = {0};
-        bit_lib_num_to_bytes_be(metromoney_1k_verify_key[0].a, COUNT_OF(key.data), key.data);
-
-        MfClassicAuthContext auth_context;
-        MfClassicError error = mf_classic_poller_sync_auth(
-            nfc, ticket_block_number, &key, MfClassicKeyTypeA, &auth_context);
-        if(error != MfClassicErrorNone) {
-            FURI_LOG_D(TAG, "Failed to read block %u: %d", ticket_block_number, error);
-            break;
+        if(!data_loaded) {
+            const uint8_t ticket_block_number =
+                mf_classic_get_first_block_num_of_sector(ticket_sector_number) + 1;
+            FURI_LOG_D(TAG, "Verifying sector %u", ticket_sector_number);
+
+            MfClassicKey key = {0};
+            bit_lib_num_to_bytes_be(metromoney_1k_verify_key[0].a, COUNT_OF(key.data), key.data);
+
+            MfClassicAuthContext auth_context;
+            MfClassicError error = mf_classic_poller_sync_auth(
+                nfc, ticket_block_number, &key, MfClassicKeyTypeA, &auth_context);
+            if(error != MfClassicErrorNone) {
+                FURI_LOG_D(TAG, "Failed to read block %u: %d", ticket_block_number, error);
+                break;
+            }
+
+            verified = true;
+        } else {
+            MfClassicSectorTrailer* sec_tr =
+                mf_classic_get_sector_trailer_by_sector(mfc_data, ticket_sector_number);
+
+            uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
+            if(key != metromoney_1k_verify_key[0].a) {
+                break;
+            }
+
+            verified = true;
         }
-
-        verified = true;
     } while(false);
 
     return verified;
 }
 
-static bool smartrider_verify(Nfc* nfc) {
+static bool smartrider_verify(Nfc* nfc, MfClassicData* mfc_data, bool data_loaded) {
     bool verified = false;
 
     do {
-        const uint8_t block_number = mf_classic_get_first_block_num_of_sector(0) + 1;
-        FURI_LOG_D(TAG, "Verifying sector 0");
-
-        MfClassicKey key = {0};
-        bit_lib_num_to_bytes_be(smartrider_verify_key[0].a, COUNT_OF(key.data), key.data);
-
-        MfClassicAuthContext auth_context;
-        MfClassicError error =
-            mf_classic_poller_sync_auth(nfc, block_number, &key, MfClassicKeyTypeA, &auth_context);
-        if(error != MfClassicErrorNone) {
-            FURI_LOG_D(TAG, "Failed to read block %u: %d", block_number, error);
-            break;
+        if(!data_loaded) {
+            const uint8_t block_number = mf_classic_get_first_block_num_of_sector(0) + 1;
+            FURI_LOG_D(TAG, "Verifying sector 0");
+
+            MfClassicKey key = {0};
+            bit_lib_num_to_bytes_be(smartrider_verify_key[0].a, COUNT_OF(key.data), key.data);
+
+            MfClassicAuthContext auth_context;
+            MfClassicError error = mf_classic_poller_sync_auth(
+                nfc, block_number, &key, MfClassicKeyTypeA, &auth_context);
+            if(error != MfClassicErrorNone) {
+                FURI_LOG_D(TAG, "Failed to read block %u: %d", block_number, error);
+                break;
+            }
+
+            verified = true;
+        } else {
+            MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(mfc_data, 0);
+
+            uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
+            if(key != smartrider_verify_key[0].a) {
+                break;
+            }
+
+            verified = true;
         }
-
-        verified = true;
     } while(false);
 
     return verified;
@@ -151,50 +197,66 @@ static bool troika_get_card_config(TroikaCardConfig* config, MfClassicType type)
     return success;
 }
 
-static bool troika_verify_type(Nfc* nfc, MfClassicType type) {
+static bool
+    troika_verify_type(Nfc* nfc, MfClassicData* mfc_data, bool data_loaded, MfClassicType type) {
     bool verified = false;
 
     do {
-        TroikaCardConfig cfg = {};
-        if(!troika_get_card_config(&cfg, type)) break;
-
-        const uint8_t block_num = mf_classic_get_first_block_num_of_sector(cfg.data_sector);
-        FURI_LOG_D(TAG, "Verifying sector %lu", cfg.data_sector);
-
-        MfClassicKey key = {0};
-        bit_lib_num_to_bytes_be(cfg.keys[0].a, COUNT_OF(key.data), key.data);
-
-        MfClassicAuthContext auth_context;
-        MfClassicError error =
-            mf_classic_poller_sync_auth(nfc, block_num, &key, MfClassicKeyTypeA, &auth_context);
-        if(error != MfClassicErrorNone) {
-            FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
-            break;
+        if(!data_loaded) {
+            TroikaCardConfig cfg = {};
+            if(!troika_get_card_config(&cfg, type)) break;
+
+            const uint8_t block_num = mf_classic_get_first_block_num_of_sector(cfg.data_sector);
+            FURI_LOG_D(TAG, "Verifying sector %lu", cfg.data_sector);
+
+            MfClassicKey key = {0};
+            bit_lib_num_to_bytes_be(cfg.keys[0].a, COUNT_OF(key.data), key.data);
+
+            MfClassicAuthContext auth_context;
+            MfClassicError error = mf_classic_poller_sync_auth(
+                nfc, block_num, &key, MfClassicKeyTypeA, &auth_context);
+            if(error != MfClassicErrorNone) {
+                FURI_LOG_D(TAG, "Failed to read block %u: %d", block_num, error);
+                break;
+            }
+            FURI_LOG_D(TAG, "Verify success!");
+            verified = true;
+        } else {
+            TroikaCardConfig cfg = {};
+            if(!troika_get_card_config(&cfg, type)) break;
+            MfClassicSectorTrailer* sec_tr =
+                mf_classic_get_sector_trailer_by_sector(mfc_data, cfg.data_sector);
+
+            uint64_t key = bit_lib_bytes_to_num_be(sec_tr->key_a.data, 6);
+            if(key != cfg.keys[0].a) {
+                break;
+            }
+
+            verified = true;
         }
-        FURI_LOG_D(TAG, "Verify success!");
-        verified = true;
     } while(false);
 
     return verified;
 }
 
-static bool troika_verify(Nfc* nfc) {
-    return troika_verify_type(nfc, MfClassicType1k) || troika_verify_type(nfc, MfClassicType4k);
+static bool troika_verify(Nfc* nfc, MfClassicData* mfc_data, bool data_loaded) {
+    return troika_verify_type(nfc, mfc_data, data_loaded, MfClassicType1k) ||
+           troika_verify_type(nfc, mfc_data, data_loaded, MfClassicType4k);
 }
 
-CardType determine_card_type(Nfc* nfc) {
+CardType determine_card_type(Nfc* nfc, MfClassicData* mfc_data, bool data_loaded) {
     FURI_LOG_I(TAG, "checking keys..");
     UNUSED(bip_verify);
 
-    if(bip_verify(nfc)) {
-        return CARD_TYPE_METROMONEY;
-    } else if(metromoney_verify(nfc)) {
+    if(bip_verify(nfc, mfc_data, data_loaded)) {
+        return CARD_TYPE_BIP;
+    } else if(metromoney_verify(nfc, mfc_data, data_loaded)) {
         return CARD_TYPE_METROMONEY;
-    } else if(smartrider_verify(nfc)) {
+    } else if(smartrider_verify(nfc, mfc_data, data_loaded)) {
         return CARD_TYPE_SMARTRIDER;
-    } else if(troika_verify(nfc)) {
+    } else if(troika_verify(nfc, mfc_data, data_loaded)) {
         return CARD_TYPE_TROIKA;
-    } else if(charliecard_verify(nfc)) {
+    } else if(charliecard_verify(nfc, mfc_data, data_loaded)) {
         return CARD_TYPE_CHARLIECARD;
     } else {
         FURI_LOG_I(TAG, "its unknown");

+ 4 - 1
scenes/metroflip_scene_auto.c

@@ -160,7 +160,10 @@ bool metroflip_scene_auto_on_event(void* context, SceneManagerEvent event) {
             app->auto_mode = true;
             if(nfc_detected_protocols_get_protocol(app->detected_protocols, 0) ==
                NfcProtocolMfClassic) {
-                CardType card_type = determine_card_type(app->nfc);
+                MfClassicData* mfc_data = mf_classic_alloc();
+                app->data_loaded = false;
+                CardType card_type = determine_card_type(app->nfc, mfc_data, app->data_loaded);
+                mf_classic_free(mfc_data);
                 app->mfc_card_type = card_type;
                 Popup* popup = app->popup;
                 UNUSED(popup);

+ 53 - 2
scenes/metroflip_scene_load.c

@@ -5,11 +5,14 @@
 #include <lib/nfc/protocols/nfc_protocol.h>
 #include "../api/metroflip/metroflip_api.h"
 #define TAG "Metroflip:Scene:Load"
+#include "keys.h"
+#include <nfc/protocols/mf_classic/mf_classic.h>
 
 void metroflip_scene_load_on_enter(void* context) {
     Metroflip* app = (Metroflip*)context;
     // We initialized this to be false every time we enter
     app->data_loaded = false;
+    bool has_card_type = false;
     // The same string we will use to direct parse scene which plugin to call
     // Extracted from the file
     FuriString* card_type = furi_string_alloc();
@@ -26,7 +29,52 @@ void metroflip_scene_load_on_enter(void* context) {
         FlipperFormat* format = flipper_format_file_alloc(storage);
         do {
             if(!flipper_format_file_open_existing(format, furi_string_get_cstr(file_path))) break;
-            if(!flipper_format_read_string(format, "Card Type", card_type)) break;
+            if(!flipper_format_read_string(format, "Card Type", card_type)) {
+                flipper_format_file_close(format);
+                flipper_format_file_open_existing(format, furi_string_get_cstr(file_path));
+                FURI_LOG_I(TAG, "dont have card type in file, detecting..");
+                MfClassicData* mfc_data = mf_classic_alloc();
+                if(!mf_classic_load(mfc_data, format, 2)) {
+                    FURI_LOG_I(TAG, "failed");
+                } else {
+                    FURI_LOG_I(TAG, "success");
+                }
+                FURI_LOG_I(TAG, "%d", mfc_data->block[3].data[1]);
+                app->data_loaded = true;
+                CardType card_type = determine_card_type(app->nfc, mfc_data, app->data_loaded);
+                app->mfc_card_type = card_type;
+                switch(card_type) {
+                case CARD_TYPE_METROMONEY:
+                    app->card_type = "metromoney";
+                    FURI_LOG_I(TAG, "Detected: Metromoney\n");
+                    break;
+                case CARD_TYPE_CHARLIECARD:
+                    app->card_type = "charliecard";
+                    FURI_LOG_I(TAG, "Detected: CharlieCard\n");
+                    break;
+                case CARD_TYPE_SMARTRIDER:
+                    app->card_type = "smartrider";
+                    FURI_LOG_I(TAG, "Detected: SmartRider\n");
+                    break;
+                case CARD_TYPE_TROIKA:
+                    app->card_type = "troika";
+                    FURI_LOG_I(TAG, "Detected: Troika\n");
+                    break;
+                case CARD_TYPE_UNKNOWN:
+                    app->card_type = "unknown";
+                    FURI_LOG_I(TAG, "Detected: Unknown card type\n");
+
+                    //popup_set_header(popup, "Unsupported\n card", 58, 31, AlignLeft, AlignTop);
+                    break;
+                default:
+                    app->card_type = "unknown";
+                    FURI_LOG_I(TAG, "Detected: Unknown card type\n");
+                    //popup_set_header(popup, "Unsupported\n card", 58, 31, AlignLeft, AlignTop);
+                    break;
+                }
+                mf_classic_free(mfc_data);
+                has_card_type = true;
+            }
             app->file_path = furi_string_get_cstr(file_path);
             app->data_loaded = true;
         } while(0);
@@ -35,7 +83,10 @@ void metroflip_scene_load_on_enter(void* context) {
 
     if(app->data_loaded) {
         // Direct to the parsing screen just like the auto scene does
-        app->card_type = furi_string_get_cstr(card_type);
+        if(!has_card_type) {
+            app->card_type = furi_string_get_cstr(card_type);
+            has_card_type = false;
+        }
         scene_manager_next_scene(app->scene_manager, MetroflipSceneParse);
     } else {
         scene_manager_next_scene(app->scene_manager, MetroflipSceneStart);

+ 39 - 15
scenes/plugins/bip.c

@@ -133,9 +133,7 @@ static bool is_bip_block_empty(const MfClassicBlock* block) {
     return true;
 }
 
-static bool
-    bip_parse(const NfcDevice* device, FuriString* parsed_data, const MfClassicData* data) {
-    furi_assert(device);
+static bool bip_parse(FuriString* parsed_data, const MfClassicData* data) {
     furi_assert(parsed_data);
 
     struct {
@@ -311,7 +309,7 @@ static NfcCommand bip_poller_callback(NfcGenericEvent event, void* context) {
 
         dolphin_deed(DolphinDeedNfcReadSuccess);
         furi_string_reset(app->text_box_store);
-        if(!bip_parse(app->nfc_device, parsed_data, mfc_data)) {
+        if(!bip_parse(parsed_data, mfc_data)) {
             furi_string_reset(app->text_box_store);
             FURI_LOG_I(TAG, "Unknown card type");
             furi_string_printf(parsed_data, "\e#Unknown card\n");
@@ -339,18 +337,44 @@ static void bip_on_enter(Metroflip* app) {
 
     app->sec_num = 0;
 
-    // Setup view
-    Popup* popup = app->popup;
-    popup_set_header(popup, "Apply\n card to\nthe back", 68, 30, AlignLeft, AlignTop);
-    popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
+    if(app->data_loaded) {
+        Storage* storage = furi_record_open(RECORD_STORAGE);
+        FlipperFormat* ff = flipper_format_file_alloc(storage);
+        if(flipper_format_file_open_existing(ff, app->file_path)) {
+            MfClassicData* mfc_data = mf_classic_alloc();
+            mf_classic_load(mfc_data, ff, 2);
+            FuriString* parsed_data = furi_string_alloc();
+            Widget* widget = app->widget;
 
-    // Start worker
-    view_dispatcher_switch_to_view(app->view_dispatcher, MetroflipViewPopup);
-    nfc_scanner_alloc(app->nfc);
-    app->poller = nfc_poller_alloc(app->nfc, NfcProtocolMfClassic);
-    nfc_poller_start(app->poller, bip_poller_callback, app);
-
-    metroflip_app_blink_start(app);
+            furi_string_reset(app->text_box_store);
+            if(!bip_parse(parsed_data, mfc_data)) {
+                furi_string_reset(app->text_box_store);
+                FURI_LOG_I(TAG, "Unknown card type");
+                furi_string_printf(parsed_data, "\e#Unknown card\n");
+            }
+            widget_add_text_scroll_element(
+                widget, 0, 0, 128, 64, furi_string_get_cstr(parsed_data));
+
+            widget_add_button_element(
+                widget, GuiButtonTypeRight, "Exit", metroflip_exit_widget_callback, app);
+            mf_classic_free(mfc_data);
+            furi_string_free(parsed_data);
+            view_dispatcher_switch_to_view(app->view_dispatcher, MetroflipViewWidget);
+        }
+        flipper_format_free(ff);
+    } else {
+        // Setup view
+        Popup* popup = app->popup;
+        popup_set_header(popup, "Apply\n card to\nthe back", 68, 30, AlignLeft, AlignTop);
+        popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
+
+        // Start worker
+        view_dispatcher_switch_to_view(app->view_dispatcher, MetroflipViewPopup);
+        app->poller = nfc_poller_alloc(app->nfc, NfcProtocolMfClassic);
+        nfc_poller_start(app->poller, bip_poller_callback, app);
+
+        metroflip_app_blink_start(app);
+    }
 }
 
 static bool bip_on_event(Metroflip* app, SceneManagerEvent event) {