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>
This commit is contained in:
		@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -29,9 +29,14 @@ 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) {
 | 
			
		||||
            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;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -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
									
								
								applications/main/nfc/scenes/nfc_scene_read_card_type.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								applications/main/nfc/scenes/nfc_scene_read_card_type.c
									
									
									
									
									
										Normal file
									
								
							@@ -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);
 | 
			
		||||
}
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -90,7 +90,11 @@ int32_t nfc_worker_task(void* context) {
 | 
			
		||||
    furi_hal_nfc_exit_sleep();
 | 
			
		||||
 | 
			
		||||
    if(nfc_worker->state == NfcWorkerStateRead) {
 | 
			
		||||
        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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user