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

Force card types in extra actions (#1961)

* Mifare Classic forced read
* Add all the needed card types
* nfc: remove unused scene
* nfc: remove unused worker state
* nfc: fix read card type scene state usage
* nfc: move NfcReadMode to NfcDevData struct
* nfc: fix bank card reading and scene navigation
* nfc magic: fix magic deactifate function

Co-authored-by: gornekich <n.gorbadey@gmail.com>
Co-authored-by: あく <alleteam@gmail.com>
Astra 3 лет назад
Родитель
Сommit
e7c4b40dbe

+ 1 - 0
applications/main/nfc/scenes/nfc_scene_config.h

@@ -60,3 +60,4 @@ ADD_SCENE(nfc, detect_reader, DetectReader)
 ADD_SCENE(nfc, mfkey_nonces_info, MfkeyNoncesInfo)
 ADD_SCENE(nfc, mfkey_complete, MfkeyComplete)
 ADD_SCENE(nfc, nfc_data_info, NfcDataInfo)
+ADD_SCENE(nfc, read_card_type, ReadCardType)

+ 7 - 2
applications/main/nfc/scenes/nfc_scene_exit_confirm.c

@@ -29,8 +29,13 @@ bool nfc_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) {
         if(event.event == DialogExResultRight) {
             consumed = scene_manager_previous_scene(nfc->scene_manager);
         } else if(event.event == DialogExResultLeft) {
-            consumed = scene_manager_search_and_switch_to_previous_scene(
-                nfc->scene_manager, NfcSceneStart);
+            if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneReadCardType)) {
+                consumed = scene_manager_search_and_switch_to_previous_scene(
+                    nfc->scene_manager, NfcSceneReadCardType);
+            } else {
+                consumed = scene_manager_search_and_switch_to_previous_scene(
+                    nfc->scene_manager, NfcSceneStart);
+            }
         }
     } else if(event.type == SceneManagerEventTypeBack) {
         consumed = true;

+ 13 - 0
applications/main/nfc/scenes/nfc_scene_extra_actions.c

@@ -1,6 +1,7 @@
 #include "../nfc_i.h"
 
 enum SubmenuIndex {
+    SubmenuIndexReadCardType,
     SubmenuIndexMfClassicKeys,
     SubmenuIndexMfUltralightUnlock,
 };
@@ -15,6 +16,12 @@ void nfc_scene_extra_actions_on_enter(void* context) {
     Nfc* nfc = context;
     Submenu* submenu = nfc->submenu;
 
+    submenu_add_item(
+        submenu,
+        "Read Specific Card Type",
+        SubmenuIndexReadCardType,
+        nfc_scene_extra_actions_submenu_callback,
+        nfc);
     submenu_add_item(
         submenu,
         "Mifare Classic Keys",
@@ -44,9 +51,15 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
             consumed = true;
         } else if(event.event == SubmenuIndexMfUltralightUnlock) {
             scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu);
+            consumed = true;
+        } else if(event.event == SubmenuIndexReadCardType) {
+            scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, 0);
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardType);
+            consumed = true;
         }
         scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event);
     }
+
     return consumed;
 }
 

+ 97 - 0
applications/main/nfc/scenes/nfc_scene_read_card_type.c

@@ -0,0 +1,97 @@
+#include "../nfc_i.h"
+#include "nfc_worker_i.h"
+
+enum SubmenuIndex {
+    SubmenuIndexReadMifareClassic,
+    SubmenuIndexReadMifareDesfire,
+    SubmenuIndexReadMfUltralight,
+    SubmenuIndexReadEMV,
+    SubmenuIndexReadNFCA,
+};
+
+void nfc_scene_read_card_type_submenu_callback(void* context, uint32_t index) {
+    Nfc* nfc = context;
+
+    view_dispatcher_send_custom_event(nfc->view_dispatcher, index);
+}
+
+void nfc_scene_read_card_type_on_enter(void* context) {
+    Nfc* nfc = context;
+    Submenu* submenu = nfc->submenu;
+
+    submenu_add_item(
+        submenu,
+        "Read Mifare Classic",
+        SubmenuIndexReadMifareClassic,
+        nfc_scene_read_card_type_submenu_callback,
+        nfc);
+    submenu_add_item(
+        submenu,
+        "Read Mifare DESFire",
+        SubmenuIndexReadMifareDesfire,
+        nfc_scene_read_card_type_submenu_callback,
+        nfc);
+    submenu_add_item(
+        submenu,
+        "Read NTAG/Ultralight",
+        SubmenuIndexReadMfUltralight,
+        nfc_scene_read_card_type_submenu_callback,
+        nfc);
+    submenu_add_item(
+        submenu,
+        "Read EMV card",
+        SubmenuIndexReadEMV,
+        nfc_scene_read_card_type_submenu_callback,
+        nfc);
+    submenu_add_item(
+        submenu,
+        "Read NFC-A data",
+        SubmenuIndexReadNFCA,
+        nfc_scene_read_card_type_submenu_callback,
+        nfc);
+    uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneReadCardType);
+    submenu_set_selected_item(submenu, state);
+
+    view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
+}
+
+bool nfc_scene_read_card_type_on_event(void* context, SceneManagerEvent event) {
+    Nfc* nfc = context;
+    bool consumed = false;
+
+    if(event.type == SceneManagerEventTypeCustom) {
+        if(event.event == SubmenuIndexReadMifareClassic) {
+            nfc->dev->dev_data.read_mode = NfcReadModeMfClassic;
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
+            consumed = true;
+        }
+        if(event.event == SubmenuIndexReadMifareDesfire) {
+            nfc->dev->dev_data.read_mode = NfcReadModeMfDesfire;
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
+            consumed = true;
+        }
+        if(event.event == SubmenuIndexReadMfUltralight) {
+            nfc->dev->dev_data.read_mode = NfcReadModeMfUltralight;
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
+            consumed = true;
+        }
+        if(event.event == SubmenuIndexReadEMV) {
+            nfc->dev->dev_data.read_mode = NfcReadModeEMV;
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
+            consumed = true;
+        }
+        if(event.event == SubmenuIndexReadNFCA) {
+            nfc->dev->dev_data.read_mode = NfcReadModeNFCA;
+            scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
+            consumed = true;
+        }
+        scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, event.event);
+    }
+    return consumed;
+}
+
+void nfc_scene_read_card_type_on_exit(void* context) {
+    Nfc* nfc = context;
+
+    submenu_reset(nfc->submenu);
+}

+ 2 - 0
applications/main/nfc/scenes/nfc_scene_start.c

@@ -1,4 +1,5 @@
 #include "../nfc_i.h"
+#include "nfc_worker_i.h"
 #include <dolphin/dolphin.h>
 
 enum SubmenuIndex {
@@ -47,6 +48,7 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) {
 
     if(event.type == SceneManagerEventTypeCustom) {
         if(event.event == SubmenuIndexRead) {
+            nfc->dev->dev_data.read_mode = NfcReadModeAuto;
             scene_manager_next_scene(nfc->scene_manager, NfcSceneRead);
             DOLPHIN_DEED(DolphinDeedNfcRead);
             consumed = true;

+ 1 - 1
applications/plugins/nfc_magic/lib/magic/magic.c

@@ -210,5 +210,5 @@ bool magic_wipe() {
 
 void magic_deactivate() {
     furi_hal_nfc_ll_txrx_off();
-    furi_hal_nfc_start_sleep();
+    furi_hal_nfc_sleep();
 }

+ 0 - 1
applications/plugins/nfc_magic/nfc_magic_worker.c

@@ -167,7 +167,6 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) {
         if(!magic_data_access_cmd()) continue;
         if(!magic_write_blk(0, &block)) continue;
         nfc_magic_worker->callback(NfcMagicWorkerEventSuccess, nfc_magic_worker->context);
-        magic_deactivate();
         break;
     }
     magic_deactivate();

+ 10 - 0
lib/nfc/nfc_device.h

@@ -51,9 +51,19 @@ typedef struct {
     MfClassicDict* dict;
 } NfcMfClassicDictAttackData;
 
+typedef enum {
+    NfcReadModeAuto,
+    NfcReadModeMfClassic,
+    NfcReadModeMfUltralight,
+    NfcReadModeMfDesfire,
+    NfcReadModeEMV,
+    NfcReadModeNFCA,
+} NfcReadMode;
+
 typedef struct {
     FuriHalNfcDevData nfc_data;
     NfcProtocol protocol;
+    NfcReadMode read_mode;
     union {
         NfcReaderRequestData reader_data;
         NfcMfClassicDictAttackData mf_classic_dict_attack_data;

+ 80 - 1
lib/nfc/nfc_worker.c

@@ -90,7 +90,11 @@ int32_t nfc_worker_task(void* context) {
     furi_hal_nfc_exit_sleep();
 
     if(nfc_worker->state == NfcWorkerStateRead) {
-        nfc_worker_read(nfc_worker);
+        if(nfc_worker->dev_data->read_mode == NfcReadModeAuto) {
+            nfc_worker_read(nfc_worker);
+        } else {
+            nfc_worker_read_type(nfc_worker);
+        }
     } else if(nfc_worker->state == NfcWorkerStateUidEmulate) {
         nfc_worker_emulate_uid(nfc_worker);
     } else if(nfc_worker->state == NfcWorkerStateEmulateApdu) {
@@ -394,6 +398,81 @@ void nfc_worker_read(NfcWorker* nfc_worker) {
     }
 }
 
+void nfc_worker_read_type(NfcWorker* nfc_worker) {
+    furi_assert(nfc_worker);
+    furi_assert(nfc_worker->callback);
+
+    NfcReadMode read_mode = nfc_worker->dev_data->read_mode;
+    nfc_device_data_clear(nfc_worker->dev_data);
+    NfcDeviceData* dev_data = nfc_worker->dev_data;
+    FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data;
+    FuriHalNfcTxRxContext tx_rx = {};
+    NfcWorkerEvent event = 0;
+    bool card_not_detected_notified = false;
+
+    while(nfc_worker->state == NfcWorkerStateRead) {
+        if(furi_hal_nfc_detect(nfc_data, 300)) {
+            FURI_LOG_D(TAG, "Card detected");
+            furi_hal_nfc_sleep();
+            // Process first found device
+            nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context);
+            card_not_detected_notified = false;
+            if(nfc_data->type == FuriHalNfcTypeA) {
+                if(read_mode == NfcReadModeMfClassic) {
+                    nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareClassic;
+                    nfc_worker->dev_data->mf_classic_data.type = mf_classic_get_classic_type(
+                        nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak);
+                    if(nfc_worker_read_mf_classic(nfc_worker, &tx_rx)) {
+                        FURI_LOG_D(TAG, "Card read");
+                        dev_data->protocol = NfcDeviceProtocolMifareClassic;
+                        event = NfcWorkerEventReadMfClassicDone;
+                        break;
+                    } else {
+                        FURI_LOG_D(TAG, "Card read failed");
+                        dev_data->protocol = NfcDeviceProtocolMifareClassic;
+                        event = NfcWorkerEventReadMfClassicDictAttackRequired;
+                        break;
+                    }
+                } else if(read_mode == NfcReadModeMfUltralight) {
+                    FURI_LOG_I(TAG, "Mifare Ultralight / NTAG");
+                    nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareUl;
+                    if(nfc_worker_read_mf_ultralight(nfc_worker, &tx_rx)) {
+                        event = NfcWorkerEventReadMfUltralight;
+                        break;
+                    }
+                } else if(read_mode == NfcReadModeMfDesfire) {
+                    nfc_worker->dev_data->protocol = NfcDeviceProtocolMifareDesfire;
+                    if(nfc_worker_read_mf_desfire(nfc_worker, &tx_rx)) {
+                        event = NfcWorkerEventReadMfDesfire;
+                        break;
+                    }
+                } else if(read_mode == NfcReadModeEMV) {
+                    nfc_worker->dev_data->protocol = NfcDeviceProtocolEMV;
+                    if(nfc_worker_read_bank_card(nfc_worker, &tx_rx)) {
+                        event = NfcWorkerEventReadBankCard;
+                        break;
+                    }
+                } else if(read_mode == NfcReadModeNFCA) {
+                    nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown;
+                    event = NfcWorkerEventReadUidNfcA;
+                    break;
+                }
+            } else {
+                if(!card_not_detected_notified) {
+                    nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context);
+                    card_not_detected_notified = true;
+                }
+            }
+        }
+        furi_hal_nfc_sleep();
+        furi_delay_ms(100);
+    }
+    // Notify caller and exit
+    if(event > NfcWorkerEventReserved) {
+        nfc_worker->callback(event, nfc_worker->context);
+    }
+}
+
 void nfc_worker_emulate_uid(NfcWorker* nfc_worker) {
     FuriHalNfcTxRxContext tx_rx = {};
     FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data;

+ 2 - 0
lib/nfc/nfc_worker_i.h

@@ -35,6 +35,8 @@ int32_t nfc_worker_task(void* context);
 
 void nfc_worker_read(NfcWorker* nfc_worker);
 
+void nfc_worker_read_type(NfcWorker* nfc_worker);
+
 void nfc_worker_emulate_uid(NfcWorker* nfc_worker);
 
 void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker);