From b54c6c70d57d5c97a006b4b4bc77c66342fb1ca9 Mon Sep 17 00:00:00 2001 From: VerstreuteSeele Date: Mon, 2 Jan 2023 12:34:00 +0100 Subject: [PATCH] Fixed NFC --- applications/main/nfc/nfc.c | 16 ++ applications/main/nfc/nfc_i.h | 3 + .../main/nfc/scenes/nfc_scene_config.h | 13 ++ .../nfc/scenes/nfc_scene_delete_success.c | 11 +- .../main/nfc/scenes/nfc_scene_emulate_nfcv.c | 149 ++++++++++++++ .../main/nfc/scenes/nfc_scene_emulate_uid.c | 11 +- .../main/nfc/scenes/nfc_scene_extra_actions.c | 10 + .../scenes/nfc_scene_mf_classic_dict_attack.c | 6 +- .../nfc/scenes/nfc_scene_mf_classic_emulate.c | 11 +- .../nfc/scenes/nfc_scene_mf_classic_keys.c | 4 +- .../nfc_scene_mf_classic_update_success.c | 11 +- .../nfc_scene_mf_classic_write_success.c | 11 +- .../nfc/scenes/nfc_scene_mf_desfire_app.c | 21 +- .../nfc/scenes/nfc_scene_mf_desfire_data.c | 21 +- .../scenes/nfc_scene_mf_ultralight_emulate.c | 128 ++++++++++-- .../nfc_scene_mf_ultralight_key_input.c | 2 +- .../nfc/scenes/nfc_scene_mf_ultralight_menu.c | 18 +- .../nfc_scene_mf_ultralight_read_auth.c | 9 +- .../nfc_scene_mf_ultralight_unlock_auto.c | 3 +- .../main/nfc/scenes/nfc_scene_nfc_data_info.c | 170 ++++++++++++++- .../nfc/scenes/nfc_scene_nfcv_key_input.c | 48 +++++ .../main/nfc/scenes/nfc_scene_nfcv_menu.c | 63 ++++++ .../main/nfc/scenes/nfc_scene_nfcv_unlock.c | 155 ++++++++++++++ .../nfc/scenes/nfc_scene_nfcv_unlock_menu.c | 60 ++++++ .../main/nfc/scenes/nfc_scene_passport_auth.c | 194 ++++++++++++++++++ .../nfc_scene_passport_auth_save_name.c | 82 ++++++++ .../main/nfc/scenes/nfc_scene_passport_date.c | 126 ++++++++++++ .../nfc/scenes/nfc_scene_passport_docnr.c | 67 ++++++ .../main/nfc/scenes/nfc_scene_passport_menu.c | 57 +++++ .../nfc/scenes/nfc_scene_passport_pace_todo.c | 40 ++++ .../main/nfc/scenes/nfc_scene_passport_read.c | 90 ++++++++ .../nfc/scenes/nfc_scene_passport_read_auth.c | 142 +++++++++++++ applications/main/nfc/scenes/nfc_scene_read.c | 22 +- .../nfc/scenes/nfc_scene_restore_original.c | 11 +- applications/main/nfc/scenes/nfc_scene_rpc.c | 19 +- .../main/nfc/scenes/nfc_scene_save_name.c | 2 +- .../main/nfc/scenes/nfc_scene_save_success.c | 17 +- .../main/nfc/scenes/nfc_scene_saved_menu.c | 2 + applications/main/nfc/views/dict_attack.c | 4 +- 39 files changed, 1685 insertions(+), 144 deletions(-) create mode 100644 applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c create mode 100644 applications/main/nfc/scenes/nfc_scene_nfcv_key_input.c create mode 100644 applications/main/nfc/scenes/nfc_scene_nfcv_menu.c create mode 100644 applications/main/nfc/scenes/nfc_scene_nfcv_unlock.c create mode 100644 applications/main/nfc/scenes/nfc_scene_nfcv_unlock_menu.c create mode 100644 applications/main/nfc/scenes/nfc_scene_passport_auth.c create mode 100644 applications/main/nfc/scenes/nfc_scene_passport_auth_save_name.c create mode 100644 applications/main/nfc/scenes/nfc_scene_passport_date.c create mode 100644 applications/main/nfc/scenes/nfc_scene_passport_docnr.c create mode 100644 applications/main/nfc/scenes/nfc_scene_passport_menu.c create mode 100644 applications/main/nfc/scenes/nfc_scene_passport_pace_todo.c create mode 100644 applications/main/nfc/scenes/nfc_scene_passport_read.c create mode 100644 applications/main/nfc/scenes/nfc_scene_passport_read_auth.c diff --git a/applications/main/nfc/nfc.c b/applications/main/nfc/nfc.c index cf4584d7a..90fcf9f27 100644 --- a/applications/main/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -87,6 +87,13 @@ Nfc* nfc_alloc() { nfc->view_dispatcher, NfcViewTextBox, text_box_get_view(nfc->text_box)); nfc->text_box_store = furi_string_alloc(); + // Variable Item List + nfc->variable_item_list = variable_item_list_alloc(); + view_dispatcher_add_view( + nfc->view_dispatcher, + NfcViewVarItemList, + variable_item_list_get_view(nfc->variable_item_list)); + // Custom Widget nfc->widget = widget_alloc(); view_dispatcher_add_view(nfc->view_dispatcher, NfcViewWidget, widget_get_view(nfc->widget)); @@ -159,6 +166,10 @@ void nfc_free(Nfc* nfc) { text_box_free(nfc->text_box); furi_string_free(nfc->text_box_store); + // Variable Item List + view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewVarItemList); + variable_item_list_free(nfc->variable_item_list); + // Custom Widget view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewWidget); widget_free(nfc->widget); @@ -290,6 +301,11 @@ int32_t nfc_app(void* p) { } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); DOLPHIN_DEED(DolphinDeedNfcEmulate); + } else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateNfcV); + DOLPHIN_DEED(DolphinDeedNfcEmulate); + } else if(nfc->dev->format == NfcDeviceSaveFormatBankCard) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneDeviceInfo); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); DOLPHIN_DEED(DolphinDeedNfcEmulate); diff --git a/applications/main/nfc/nfc_i.h b/applications/main/nfc/nfc_i.h index f7e489902..a3a62972c 100644 --- a/applications/main/nfc/nfc_i.h +++ b/applications/main/nfc/nfc_i.h @@ -21,6 +21,7 @@ #include #include #include +#include #include #include @@ -77,6 +78,7 @@ struct Nfc { TextInput* text_input; ByteInput* byte_input; TextBox* text_box; + VariableItemList* variable_item_list; Widget* widget; DictAttack* dict_attack; DetectReader* detect_reader; @@ -92,6 +94,7 @@ typedef enum { NfcViewTextInput, NfcViewByteInput, NfcViewTextBox, + NfcViewVarItemList, NfcViewWidget, NfcViewDictAttack, NfcViewDetectReader, diff --git a/applications/main/nfc/scenes/nfc_scene_config.h b/applications/main/nfc/scenes/nfc_scene_config.h index ce51d000d..045080fea 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -14,6 +14,11 @@ ADD_SCENE(nfc, file_select, FileSelect) ADD_SCENE(nfc, emulate_uid, EmulateUid) ADD_SCENE(nfc, nfca_read_success, NfcaReadSuccess) ADD_SCENE(nfc, nfca_menu, NfcaMenu) +ADD_SCENE(nfc, nfcv_menu, NfcVMenu) +ADD_SCENE(nfc, nfcv_unlock_menu, NfcVUnlockMenu) +ADD_SCENE(nfc, nfcv_key_input, NfcVKeyInput) +ADD_SCENE(nfc, nfcv_unlock, NfcVUnlock) +ADD_SCENE(nfc, emulate_nfcv, EmulateNfcV) ADD_SCENE(nfc, mf_ultralight_read_success, MfUltralightReadSuccess) ADD_SCENE(nfc, mf_ultralight_data, MfUltralightData) ADD_SCENE(nfc, mf_ultralight_menu, MfUltralightMenu) @@ -45,6 +50,14 @@ ADD_SCENE(nfc, mf_classic_update_success, MfClassicUpdateSuccess) ADD_SCENE(nfc, mf_classic_wrong_card, MfClassicWrongCard) ADD_SCENE(nfc, emv_read_success, EmvReadSuccess) ADD_SCENE(nfc, emv_menu, EmvMenu) +ADD_SCENE(nfc, passport_read, PassportReadSuccess) +ADD_SCENE(nfc, passport_read_auth, PassportReadAuthSuccess) +ADD_SCENE(nfc, passport_menu, PassportMenu) +ADD_SCENE(nfc, passport_auth, PassportAuth) +ADD_SCENE(nfc, passport_auth_save_name, PassportAuthSaveName) +ADD_SCENE(nfc, passport_date, PassportDate) +ADD_SCENE(nfc, passport_docnr, PassportDocNr) +ADD_SCENE(nfc, passport_pace_todo, PassportPaceTodo) ADD_SCENE(nfc, emulate_apdu_sequence, EmulateApduSequence) ADD_SCENE(nfc, device_info, DeviceInfo) ADD_SCENE(nfc, delete, Delete) diff --git a/applications/main/nfc/scenes/nfc_scene_delete_success.c b/applications/main/nfc/scenes/nfc_scene_delete_success.c index faa7fd7bb..1664a9e5b 100644 --- a/applications/main/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/main/nfc/scenes/nfc_scene_delete_success.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_delete_success_popup_callback(void* context) { Nfc* nfc = context; @@ -8,24 +7,16 @@ void nfc_scene_delete_success_popup_callback(void* context) { void nfc_scene_delete_success_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); // Setup view Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62_sfw); - } - else { - popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); - } + popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62); popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); popup_set_callback(popup, nfc_scene_delete_success_popup_callback); popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c b/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c new file mode 100644 index 000000000..e6fc60d86 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c @@ -0,0 +1,149 @@ +#include "../nfc_i.h" + +#define NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX (100) + +enum { + NfcSceneEmulateNfcVStateWidget, + NfcSceneEmulateNfcVStateTextBox, +}; + +bool nfc_emulate_nfcv_worker_callback(NfcWorkerEvent event, void* context) { + UNUSED(event); + furi_assert(context); + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); + return true; +} + +void nfc_scene_emulate_nfcv_widget_callback(GuiButtonType result, InputType type, void* context) { + furi_assert(context); + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_emulate_nfcv_textbox_callback(void* context) { + furi_assert(context); + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +// Add widget with device name or inform that data received +static void nfc_scene_emulate_nfcv_widget_config(Nfc* nfc, bool data_received) { + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; + Widget* widget = nfc->widget; + widget_reset(widget); + FuriString* info_str; + info_str = furi_string_alloc(); + + widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61); + widget_add_string_element( + widget, 89, 32, AlignCenter, AlignTop, FontPrimary, "Emulating NfcV"); + if(strcmp(nfc->dev->dev_name, "")) { + furi_string_printf(info_str, "%s", nfc->dev->dev_name); + } else { + for(uint8_t i = 0; i < data->uid_len; i++) { + furi_string_cat_printf(info_str, "%02X ", data->uid[i]); + } + } + furi_string_trim(info_str); + widget_add_text_box_element( + widget, 56, 43, 70, 21, AlignCenter, AlignTop, furi_string_get_cstr(info_str), true); + furi_string_free(info_str); + if(data_received) { + widget_add_button_element( + widget, GuiButtonTypeCenter, "Log", nfc_scene_emulate_nfcv_widget_callback, nfc); + } +} + +void nfc_scene_emulate_nfcv_on_enter(void* context) { + Nfc* nfc = context; + + // Setup Widget + nfc_scene_emulate_nfcv_widget_config(nfc, false); + // Setup TextBox + TextBox* text_box = nfc->text_box; + text_box_set_font(text_box, TextBoxFontHex); + text_box_set_focus(text_box, TextBoxFocusEnd); + furi_string_reset(nfc->text_box_store); + + // Set Widget state and view + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneEmulateNfcV, NfcSceneEmulateNfcVStateWidget); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + // Start worker + memset(&nfc->dev->dev_data.reader_data, 0, sizeof(NfcReaderRequestData)); + nfc_worker_start( + nfc->worker, + NfcWorkerStateNfcVEmulate, + &nfc->dev->dev_data, + nfc_emulate_nfcv_worker_callback, + nfc); + + nfc_blink_emulate_start(nfc); +} + +bool nfc_scene_emulate_nfcv_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + NfcVData* nfcv_data = &nfc->dev->dev_data.nfcv_data; + uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneEmulateNfcV); + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventWorkerExit) { + // Add data button to widget if data is received for the first time + if(!furi_string_size(nfc->text_box_store)) { + nfc_scene_emulate_nfcv_widget_config(nfc, true); + } + if(strlen(nfcv_data->last_command) > 0) { + /* use the last n bytes from the log so there's enough space for the new log entry */ + size_t maxSize = + NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX - (strlen(nfcv_data->last_command) + 1); + if(furi_string_size(nfc->text_box_store) >= maxSize) { + furi_string_right(nfc->text_box_store, (strlen(nfcv_data->last_command) + 1)); + } + furi_string_cat_printf(nfc->text_box_store, "%s", nfcv_data->last_command); + furi_string_push_back(nfc->text_box_store, '\n'); + text_box_set_text(nfc->text_box, furi_string_get_cstr(nfc->text_box_store)); + + /* clear previously logged command */ + strcpy(nfcv_data->last_command, ""); + } + consumed = true; + } else if(event.event == GuiButtonTypeCenter && state == NfcSceneEmulateNfcVStateWidget) { + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneEmulateNfcV, NfcSceneEmulateNfcVStateTextBox); + consumed = true; + } else if(event.event == NfcCustomEventViewExit && state == NfcSceneEmulateNfcVStateTextBox) { + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneEmulateNfcV, NfcSceneEmulateNfcVStateWidget); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + if(state == NfcSceneEmulateNfcVStateTextBox) { + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneEmulateNfcV, NfcSceneEmulateNfcVStateWidget); + consumed = true; + } + } + + return consumed; +} + +void nfc_scene_emulate_nfcv_on_exit(void* context) { + Nfc* nfc = context; + + // Stop worker + nfc_worker_stop(nfc->worker); + + // Clear view + widget_reset(nfc->widget); + text_box_reset(nfc->text_box); + furi_string_reset(nfc->text_box_store); + + nfc_blink_stop(nfc); +} diff --git a/applications/main/nfc/scenes/nfc_scene_emulate_uid.c b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c index eec43c92c..7316eebe0 100644 --- a/applications/main/nfc/scenes/nfc_scene_emulate_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_emulate_uid.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" #define NFC_SCENE_EMULATE_UID_LOG_SIZE_MAX (200) @@ -37,15 +36,8 @@ static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) { widget_reset(widget); FuriString* info_str; info_str = furi_string_alloc(); - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); - if (settings->sfw_mode) { - widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { - widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61); - } + widget_add_icon_element(widget, 0, 3, &I_NFC_dolphin_emulation_47x61); widget_add_string_element(widget, 57, 13, AlignLeft, AlignTop, FontPrimary, "Emulating UID"); if(strcmp(nfc->dev->dev_name, "") != 0) { furi_string_printf(info_str, "%s", nfc->dev->dev_name); @@ -62,7 +54,6 @@ static void nfc_scene_emulate_uid_widget_config(Nfc* nfc, bool data_received) { widget_add_button_element( widget, GuiButtonTypeCenter, "Log", nfc_scene_emulate_uid_widget_callback, nfc); } - free(settings); } void nfc_scene_emulate_uid_on_enter(void* context) { diff --git a/applications/main/nfc/scenes/nfc_scene_extra_actions.c b/applications/main/nfc/scenes/nfc_scene_extra_actions.c index 717e8efc4..147c89757 100644 --- a/applications/main/nfc/scenes/nfc_scene_extra_actions.c +++ b/applications/main/nfc/scenes/nfc_scene_extra_actions.c @@ -4,6 +4,7 @@ enum SubmenuIndex { SubmenuIndexReadCardType, SubmenuIndexMfClassicKeys, SubmenuIndexMfUltralightUnlock, + SubmenuIndexNfcVUnlock, }; void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) { @@ -34,6 +35,12 @@ void nfc_scene_extra_actions_on_enter(void* context) { SubmenuIndexMfUltralightUnlock, nfc_scene_extra_actions_submenu_callback, nfc); + submenu_add_item( + submenu, + "Unlock SLIX-L", + SubmenuIndexNfcVUnlock, + nfc_scene_extra_actions_submenu_callback, + nfc); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } @@ -56,6 +63,9 @@ bool nfc_scene_extra_actions_on_event(void* context, SceneManagerEvent event) { scene_manager_set_scene_state(nfc->scene_manager, NfcSceneReadCardType, 0); scene_manager_next_scene(nfc->scene_manager, NfcSceneReadCardType); consumed = true; + } else if(event.event == SubmenuIndexNfcVUnlock) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVUnlockMenu); + consumed = true; } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneExtraActions, event.event); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c index b82bf5521..9b477e301 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_dict_attack.c @@ -58,7 +58,7 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt // If failed to load user dictionary - try the system dictionary if(!dict) { - FURI_LOG_E(TAG, "User dictionary not found"); + FURI_LOG_E(TAG, "User Dictionary Not Found"); state = DictAttackStateFlipperDictInProgress; } } @@ -67,8 +67,8 @@ static void nfc_scene_mf_classic_dict_attack_prepare_view(Nfc* nfc, DictAttackSt dict_attack_set_header(nfc->dict_attack, "MF Classic System Dictionary"); dict = mf_classic_dict_alloc(MfClassicDictTypeSystem); if(!dict) { - FURI_LOG_E(TAG, "Flipper dictionary not found"); - // Pass through to let the worker handle the failure + FURI_LOG_E(TAG, "Flipper Dictionary Not Found"); + // Pass through to let worker handle the failure } } // Free previous dictionary diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c index 0fa624ad9..8c0f493e1 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_emulate.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" #define NFC_MF_CLASSIC_DATA_NOT_CHANGED (0UL) #define NFC_MF_CLASSIC_DATA_CHANGED (1UL) @@ -15,8 +14,6 @@ bool nfc_mf_classic_emulate_worker_callback(NfcWorkerEvent event, void* context) void nfc_scene_mf_classic_emulate_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); // Setup view Popup* popup = nfc->popup; @@ -26,12 +23,7 @@ void nfc_scene_mf_classic_emulate_on_enter(void* context) { } else { nfc_text_store_set(nfc, "MIFARE\nClassic"); } - if (settings->sfw_mode) { - popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { - popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); - } + popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); popup_set_text(popup, nfc->text_store, 90, 28, AlignCenter, AlignTop); // Setup and start worker @@ -43,7 +35,6 @@ void nfc_scene_mf_classic_emulate_on_enter(void* context) { nfc_mf_classic_emulate_worker_callback, nfc); nfc_blink_emulate_start(nfc); - free(settings); } bool nfc_scene_mf_classic_emulate_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c index 8a7dc2c18..8b61904b4 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_keys.c @@ -28,9 +28,9 @@ void nfc_scene_mf_classic_keys_on_enter(void* context) { widget_add_string_element( nfc->widget, 0, 0, AlignLeft, AlignTop, FontPrimary, "MIFARE Classic Keys"); char temp_str[32]; - snprintf(temp_str, sizeof(temp_str), "System dict: %lu", flipper_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "System Dict: %ld", flipper_dict_keys_total); widget_add_string_element(nfc->widget, 0, 20, AlignLeft, AlignTop, FontSecondary, temp_str); - snprintf(temp_str, sizeof(temp_str), "User dict: %lu", user_dict_keys_total); + snprintf(temp_str, sizeof(temp_str), "User Dict: %ld", user_dict_keys_total); widget_add_string_element(nfc->widget, 0, 32, AlignLeft, AlignTop, FontSecondary, temp_str); widget_add_button_element( nfc->widget, GuiButtonTypeCenter, "Add", nfc_scene_mf_classic_keys_widget_callback, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c index a76a758b6..fef8fd5e9 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_update_success.c @@ -1,6 +1,5 @@ #include "../nfc_i.h" #include -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_mf_classic_update_success_popup_callback(void* context) { Nfc* nfc = context; @@ -10,18 +9,11 @@ void nfc_scene_mf_classic_update_success_popup_callback(void* context) { void nfc_scene_mf_classic_update_success_on_enter(void* context) { Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcSave); - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); notification_message(nfc->notifications, &sequence_success); Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - } + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_header(popup, "Updated!", 11, 20, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); @@ -29,7 +21,6 @@ void nfc_scene_mf_classic_update_success_on_enter(void* context) { popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_mf_classic_update_success_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c b/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c index e425d8c3a..2f2a3beb1 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_classic_write_success.c @@ -1,6 +1,5 @@ #include "../nfc_i.h" #include -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_mf_classic_write_success_popup_callback(void* context) { Nfc* nfc = context; @@ -10,18 +9,11 @@ void nfc_scene_mf_classic_write_success_popup_callback(void* context) { void nfc_scene_mf_classic_write_success_on_enter(void* context) { Nfc* nfc = context; DOLPHIN_DEED(DolphinDeedNfcSave); - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); notification_message(nfc->notifications, &sequence_success); Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - } + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_header(popup, "Successfully\nwritten", 13, 22, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); @@ -29,7 +21,6 @@ void nfc_scene_mf_classic_write_success_on_enter(void* context) { popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_mf_classic_write_success_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c index 882dc5fea..afc5f0dee 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_app.c @@ -51,18 +51,23 @@ void nfc_scene_mf_desfire_app_on_enter(void* context) { nfc_scene_mf_desfire_app_submenu_callback, nfc); - FuriString* label = furi_string_alloc(); + uint16_t cap = NFC_TEXT_STORE_SIZE; + char* buf = nfc->text_store; int idx = SubmenuIndexDynamic; for(MifareDesfireFile* file = app->file_head; file; file = file->next) { - furi_string_printf(label, "File %d", file->id); + int size = snprintf(buf, cap, "File %d", file->id); + if(size < 0 || size >= cap) { + FURI_LOG_W( + TAG, + "Exceeded NFC_TEXT_STORE_SIZE when preparing file id strings; menu truncated"); + break; + } + char* label = buf; + cap -= size + 1; + buf += size + 1; submenu_add_item( - nfc->submenu, - furi_string_get_cstr(label), - idx++, - nfc_scene_mf_desfire_app_submenu_callback, - nfc); + nfc->submenu, label, idx++, nfc_scene_mf_desfire_app_submenu_callback, nfc); } - furi_string_free(label); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c b/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c index c7caee8dc..e619d0377 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_desfire_data.c @@ -33,18 +33,21 @@ void nfc_scene_mf_desfire_data_on_enter(void* context) { nfc_scene_mf_desfire_data_submenu_callback, nfc); - FuriString* label = furi_string_alloc(); + uint16_t cap = NFC_TEXT_STORE_SIZE; + char* buf = nfc->text_store; int idx = SubmenuIndexDynamic; for(MifareDesfireApplication* app = data->app_head; app; app = app->next) { - furi_string_printf(label, "App %02x%02x%02x", app->id[0], app->id[1], app->id[2]); - submenu_add_item( - submenu, - furi_string_get_cstr(label), - idx++, - nfc_scene_mf_desfire_data_submenu_callback, - nfc); + int size = snprintf(buf, cap, "App %02x%02x%02x", app->id[0], app->id[1], app->id[2]); + if(size < 0 || size >= cap) { + FURI_LOG_W( + TAG, "Exceeded NFC_TEXT_STORE_SIZE when preparing app id strings; menu truncated"); + break; + } + char* label = buf; + cap -= size + 1; + buf += size + 1; + submenu_add_item(submenu, label, idx++, nfc_scene_mf_desfire_data_submenu_callback, nfc); } - furi_string_free(label); if(state >= MifareDesfireDataStateItem) { submenu_set_selected_item( diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c index ca25b48c1..88b6b71d9 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c @@ -1,23 +1,103 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" +#include + +#define NFC_SCENE_MF_ULTRALIGHT_EMULATE_LOG_SIZE_MAX (200) #define NFC_MF_UL_DATA_NOT_CHANGED (0UL) #define NFC_MF_UL_DATA_CHANGED (1UL) -bool nfc_mf_ultralight_emulate_worker_callback(NfcWorkerEvent event, void* context) { - UNUSED(event); - Nfc* nfc = context; +enum { + // View states + NfcSceneMfUltralightEmulateStateWidget, + NfcSceneMfUltralightEmulateStateTextBox, + NfcSceneMfUltralightEmulateStateMax = 0xFF, + // State flags + NfcSceneMfUltralightEmulateStateDataChanged = 1 << 8, + NfcSceneMfUltralightEmulateStateAuthAttempted = 1 << 9, + NfcSceneMfUltralightEmulateStateLogButtonShown = 1 << 10, +}; + +bool nfc_mf_ultralight_emulate_worker_callback(NfcWorkerEvent event, void* context) { + Nfc* nfc = context; + uint32_t state = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate); + + if(event == NfcWorkerEventSuccess) + state |= NfcSceneMfUltralightEmulateStateDataChanged; + else if(event == NfcWorkerEventMfUltralightPwdAuth) { + // Don't update if we're exiting + if(nfc_worker_get_state(nfc->worker) != NfcWorkerStateStop) { + // Event data is only available for the duration of this callback, so we're updating the + // text box right here + MfUltralightAuth* auth = nfc_worker_get_event_data(nfc->worker); + if(auth != NULL && furi_string_size(nfc->text_box_store) < + NFC_SCENE_MF_ULTRALIGHT_EMULATE_LOG_SIZE_MAX) { + furi_string_cat(nfc->text_box_store, "PWD:"); + for(size_t i = 0; i < sizeof(auth->pwd.raw); ++i) { + furi_string_cat_printf(nfc->text_box_store, " %02X", auth->pwd.raw[i]); + } + furi_string_push_back(nfc->text_box_store, '\n'); + text_box_set_text(nfc->text_box, furi_string_get_cstr(nfc->text_box_store)); + } + state |= NfcSceneMfUltralightEmulateStateAuthAttempted; + } + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate, state); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); - scene_manager_set_scene_state( - nfc->scene_manager, NfcSceneMfUltralightEmulate, NFC_MF_UL_DATA_CHANGED); return true; } +void nfc_scene_mf_ultralight_emulate_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + furi_assert(context); + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_mf_ultralight_emulate_widget_config(Nfc* nfc, bool auth_attempted) { + Widget* widget = nfc->widget; + widget_reset(widget); + FuriString* info_str; + info_str = furi_string_alloc(); + + widget_add_icon_element(widget, 0, 3, &I_RFIDDolphinSend_97x61); + if(strcmp(nfc->dev->dev_name, "")) { + furi_string_printf(info_str, "Emulating\n%s", nfc->dev->dev_name); + } else { + furi_string_printf(info_str, "Emulating\nMf Ultralight"); + } + + widget_add_string_multiline_element( + widget, 56, 31, AlignLeft, AlignTop, FontPrimary, furi_string_get_cstr(info_str)); + furi_string_free(info_str); + if(auth_attempted) { + widget_add_button_element( + widget, + GuiButtonTypeCenter, + "Log", + nfc_scene_mf_ultralight_emulate_widget_callback, + nfc); + } +} + void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); + uint32_t state = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate); + // Setup Widget + nfc_scene_mf_ultralight_emulate_widget_config(nfc, false); + state &= ~NfcSceneMfUltralightEmulateStateLogButtonShown; + // Setup TextBox + TextBox* text_box = nfc->text_box; + text_box_set_font(text_box, TextBoxFontHex); + text_box_set_focus(text_box, TextBoxFocusEnd); + furi_string_reset(nfc->text_box_store); // Setup view MfUltralightType type = nfc->dev->dev_data.mf_ul_data.type; bool is_ultralight = (type == MfUltralightTypeUL11) || (type == MfUltralightTypeUL21) || @@ -31,16 +111,15 @@ void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { } else { nfc_text_store_set(nfc, "MIFARE\nNTAG"); } - if (settings->sfw_mode) { - popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { - popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); - } + popup_set_icon(popup, 0, 3, &I_NFC_dolphin_emulation_47x61); popup_set_text(popup, nfc->text_store, 90, 28, AlignCenter, AlignTop); - // Setup and start worker - view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + // Set Widget state and view + state = (state & ~NfcSceneMfUltralightEmulateStateMax) | + NfcSceneMfUltralightEmulateStateWidget; + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate, state); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); + // Start worker nfc_worker_start( nfc->worker, NfcWorkerStateMfUltralightEmulate, @@ -48,7 +127,6 @@ void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { nfc_mf_ultralight_emulate_worker_callback, nfc); nfc_blink_emulate_start(nfc); - free(settings); } bool nfc_scene_mf_ultralight_emulate_on_event(void* context, SceneManagerEvent event) { @@ -68,16 +146,28 @@ bool nfc_scene_mf_ultralight_emulate_on_event(void* context, SceneManagerEvent e nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path)); } } - consumed = false; } return consumed; } void nfc_scene_mf_ultralight_emulate_on_exit(void* context) { Nfc* nfc = context; + uint32_t state = + scene_manager_get_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate); + + // Stop worker + nfc_worker_stop(nfc->worker); + // Check if data changed and save in shadow file + if(state & NfcSceneMfUltralightEmulateStateDataChanged) { + state &= ~NfcSceneMfUltralightEmulateStateDataChanged; + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneMfUltralightEmulate, state); + nfc_device_save_shadow(nfc->dev, nfc->dev->dev_name); + } // Clear view - popup_reset(nfc->popup); + widget_reset(nfc->widget); + text_box_reset(nfc->text_box); + furi_string_reset(nfc->text_box_store); nfc_blink_stop(nfc); } diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_key_input.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_key_input.c index 089187d5b..174d1a406 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_key_input.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_key_input.c @@ -11,7 +11,7 @@ void nfc_scene_mf_ultralight_key_input_on_enter(void* context) { // Setup view ByteInput* byte_input = nfc->byte_input; - byte_input_set_header_text(byte_input, "Enter the password in hex"); + byte_input_set_header_text(byte_input, "Enter The Password In Hex"); byte_input_set_result_callback( byte_input, nfc_scene_mf_ultralight_key_input_byte_input_callback, diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c index c511e9dcb..ddf30c54a 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c @@ -2,7 +2,8 @@ #include enum SubmenuIndex { - SubmenuIndexUnlock, + SubmenuIndexUnlockByReader, + SubmenuIndexUnlockByPassword, SubmenuIndexSave, SubmenuIndexEmulate, SubmenuIndexInfo, @@ -22,8 +23,14 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) { if(!mf_ul_is_full_capture(data)) { submenu_add_item( submenu, - "Unlock", - SubmenuIndexUnlock, + "Unlock With Reader", + SubmenuIndexUnlockByReader, + nfc_scene_mf_ultralight_menu_submenu_callback, + nfc); + submenu_add_item( + submenu, + "Unlock With Password", + SubmenuIndexUnlockByPassword, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); } @@ -63,7 +70,10 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even DOLPHIN_DEED(DolphinDeedNfcEmulate); } consumed = true; - } else if(event.event == SubmenuIndexUnlock) { + } else if(event.event == SubmenuIndexUnlockByReader) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockAuto); + consumed = true; + } else if(event.event == SubmenuIndexUnlockByPassword) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockMenu); consumed = true; } else if(event.event == SubmenuIndexInfo) { diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c index 2ab5e3f3f..8e2dd0c22 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_read_auth.c @@ -24,21 +24,22 @@ void nfc_scene_mf_ultralight_read_auth_set_state(Nfc* nfc, NfcSceneMfUlReadState if(curr_state != state) { if(state == NfcSceneMfUlReadStateDetecting) { popup_reset(nfc->popup); - popup_set_text(nfc->popup, "Apply the\ntarget card", 97, 24, AlignCenter, AlignTop); + popup_set_text( + nfc->popup, "Apply Card To\nFlipper's Back", 97, 24, AlignCenter, AlignTop); popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50); nfc_blink_read_start(nfc); } else if(state == NfcSceneMfUlReadStateReading) { popup_reset(nfc->popup); popup_set_header( - nfc->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop); + nfc->popup, "Reading Card\nDon't Move...", 85, 24, AlignCenter, AlignTop); popup_set_icon(nfc->popup, 12, 23, &A_Loading_24); nfc_blink_detect_start(nfc); } else if(state == NfcSceneMfUlReadStateNotSupportedCard) { popup_reset(nfc->popup); - popup_set_header(nfc->popup, "Wrong type of card!", 64, 3, AlignCenter, AlignTop); + popup_set_header(nfc->popup, "Wrong Type Of Card!", 64, 3, AlignCenter, AlignTop); popup_set_text( nfc->popup, - "Only MIFARE\nUltralight & NTAG\nare supported", + "Only MIFARE\nUltralight & NTAG\n Are Supported", 4, 22, AlignLeft, diff --git a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_auto.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_auto.c index c59fe3a7d..050f6db1e 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_auto.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_auto.c @@ -31,7 +31,7 @@ void nfc_scene_mf_ultralight_unlock_auto_on_enter(void* context) { nfc_scene_mf_ultralight_unlock_auto_worker_callback, nfc); - nfc_blink_read_start(nfc); + nfc_blink_emulate_start(nfc); } bool nfc_scene_mf_ultralight_unlock_auto_on_event(void* context, SceneManagerEvent event) { @@ -58,6 +58,7 @@ void nfc_scene_mf_ultralight_unlock_auto_on_exit(void* context) { // Stop worker nfc_worker_stop(nfc->worker); // Clear view + popup_reset(nfc->popup); widget_reset(nfc->widget); nfc_blink_stop(nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c index b44ab7823..372da8860 100644 --- a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c +++ b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c @@ -7,6 +7,17 @@ void nfc_scene_nfc_data_info_widget_callback(GuiButtonType result, InputType typ } } +uint32_t nfc_scene_nfc_data_info_get_key(uint8_t* data) { + uint32_t value = 0; + + for(uint32_t pos = 0; pos < 4; pos++) { + value <<= 8; + value |= data[pos]; + } + + return value; +} + void nfc_scene_nfc_data_info_on_enter(void* context) { Nfc* nfc = context; Widget* widget = nfc->widget; @@ -14,7 +25,8 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { NfcDeviceData* dev_data = &nfc->dev->dev_data; NfcProtocol protocol = dev_data->protocol; uint8_t text_scroll_height = 0; - if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl)) { + if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl) || + (protocol == NfcDeviceProtocolNfcV)) { widget_add_button_element( widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc); text_scroll_height = 52; @@ -32,6 +44,8 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { // Set tag type if(protocol == NfcDeviceProtocolEMV) { furi_string_cat_printf(temp_str, "\e#EMV Bank Card\n"); + } else if(protocol == NfcDeviceProtocolMRTD) { + furi_string_cat_printf(temp_str, "\e#Passport/ID\n"); } else if(protocol == NfcDeviceProtocolMifareUl) { furi_string_cat_printf( temp_str, "\e#%s\n", nfc_mf_ul_type(dev_data->mf_ul_data.type, true)); @@ -40,19 +54,156 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { temp_str, "\e#%s\n", nfc_mf_classic_type(dev_data->mf_classic_data.type)); } else if(protocol == NfcDeviceProtocolMifareDesfire) { furi_string_cat_printf(temp_str, "\e#MIFARE DESfire\n"); + } else if(protocol == NfcDeviceProtocolNfcV) { + switch(dev_data->nfcv_data.sub_type) { + case NfcVTypePlain: + furi_string_cat_printf(temp_str, "\e#ISO15693\n"); + break; + case NfcVTypeSlix: + furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX\n"); + break; + case NfcVTypeSlixS: + furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX-S\n"); + break; + case NfcVTypeSlixL: + furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX-L\n"); + break; + case NfcVTypeSlix2: + furi_string_cat_printf(temp_str, "\e#ISO15693 SLIX2\n"); + break; + default: + furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n"); + break; + } } else { furi_string_cat_printf(temp_str, "\e#Unknown ISO tag\n"); } // Set tag iso data - char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3'; - furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); - furi_string_cat_printf(temp_str, "UID:"); - for(size_t i = 0; i < nfc_data->uid_len; i++) { - furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + if(protocol == NfcDeviceProtocolNfcV) { + NfcVData* nfcv_data = &nfc->dev->dev_data.nfcv_data; + + furi_string_cat_printf(temp_str, "UID:\n"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + furi_string_cat_printf(temp_str, "\n"); + + furi_string_cat_printf(temp_str, "DSFID: %02X\n", nfcv_data->dsfid); + furi_string_cat_printf(temp_str, "AFI: %02X\n", nfcv_data->afi); + furi_string_cat_printf(temp_str, "IC Ref: %02X\n", nfcv_data->ic_ref); + furi_string_cat_printf(temp_str, "Blocks: %02X\n", nfcv_data->block_num); + furi_string_cat_printf(temp_str, "Blocksize: %02X\n", nfcv_data->block_size); + + furi_string_cat_printf( + temp_str, "Data (%d byte)\n", nfcv_data->block_num * nfcv_data->block_size); + + int maxBlocks = nfcv_data->block_num; + if(maxBlocks > 32) { + maxBlocks = 32; + furi_string_cat_printf(temp_str, "(truncated to %d blocks)\n", maxBlocks); + } + + for(int block = 0; block < maxBlocks; block++) { + for(int pos = 0; pos < nfcv_data->block_size; pos++) { + furi_string_cat_printf( + temp_str, " %02X", nfcv_data->data[block * nfcv_data->block_size + pos]); + } + furi_string_cat_printf(temp_str, "\n"); + } + furi_string_cat_printf(temp_str, "\n"); + + switch(dev_data->nfcv_data.sub_type) { + case NfcVTypePlain: + furi_string_cat_printf(temp_str, "Type: Plain\n"); + break; + case NfcVTypeSlix: + furi_string_cat_printf(temp_str, "Type: SLIX\n"); + furi_string_cat_printf(temp_str, "Keys:\n"); + furi_string_cat_printf( + temp_str, + " EAS %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas)); + break; + case NfcVTypeSlixS: + furi_string_cat_printf(temp_str, "Type: SLIX-S\n"); + furi_string_cat_printf(temp_str, "Keys:\n"); + furi_string_cat_printf( + temp_str, + " Read %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_read)); + furi_string_cat_printf( + temp_str, + " Write %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_write)); + furi_string_cat_printf( + temp_str, + " Privacy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy)); + furi_string_cat_printf( + temp_str, + " Destroy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy)); + furi_string_cat_printf( + temp_str, + " EAS %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas)); + break; + case NfcVTypeSlixL: + furi_string_cat_printf(temp_str, "Type: SLIX-L\n"); + furi_string_cat_printf(temp_str, "Keys:\n"); + furi_string_cat_printf( + temp_str, + " Privacy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy)); + furi_string_cat_printf( + temp_str, + " Destroy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy)); + furi_string_cat_printf( + temp_str, + " EAS %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas)); + break; + case NfcVTypeSlix2: + furi_string_cat_printf(temp_str, "Type: SLIX2\n"); + furi_string_cat_printf(temp_str, "Keys:\n"); + furi_string_cat_printf( + temp_str, + " Read %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_read)); + furi_string_cat_printf( + temp_str, + " Write %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_write)); + furi_string_cat_printf( + temp_str, + " Privacy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_privacy)); + furi_string_cat_printf( + temp_str, + " Destroy %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_destroy)); + furi_string_cat_printf( + temp_str, + " EAS %08lX\n", + nfc_scene_nfc_data_info_get_key(nfcv_data->sub_data.slix.key_eas)); + break; + default: + furi_string_cat_printf(temp_str, "\e#ISO15693 (unknown)\n"); + break; + } + } else { + char iso_type = FURI_BIT(nfc_data->sak, 5) ? '4' : '3'; + furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-A)\n", iso_type); + furi_string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < nfc_data->uid_len; i++) { + furi_string_cat_printf(temp_str, " %02X", nfc_data->uid[i]); + } + furi_string_cat_printf( + temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]); + furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak); } - furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", nfc_data->atqa[1], nfc_data->atqa[0]); - furi_string_cat_printf(temp_str, " SAK: %02X", nfc_data->sak); // Set application specific data if(protocol == NfcDeviceProtocolMifareDesfire) { @@ -136,6 +287,9 @@ bool nfc_scene_nfc_data_info_on_event(void* context, SceneManagerEvent event) { } else if(protocol == NfcDeviceProtocolMifareUl) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightData); consumed = true; + } else if(protocol == NfcDeviceProtocolNfcV) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVMenu); + consumed = true; } } } diff --git a/applications/main/nfc/scenes/nfc_scene_nfcv_key_input.c b/applications/main/nfc/scenes/nfc_scene_nfcv_key_input.c new file mode 100644 index 000000000..cc53c4dcb --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcv_key_input.c @@ -0,0 +1,48 @@ +#include "../nfc_i.h" +#include + +void nfc_scene_nfcv_key_input_byte_input_callback(void* context) { + Nfc* nfc = context; + NfcVSlixData* data = &nfc->dev->dev_data.nfcv_data.sub_data.slix; + + memcpy(data->key_privacy, nfc->byte_input_store, 4); + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventByteInputDone); +} + +void nfc_scene_nfcv_key_input_on_enter(void* context) { + Nfc* nfc = context; + + // Setup view + ByteInput* byte_input = nfc->byte_input; + byte_input_set_header_text(byte_input, "Enter The Password In Hex"); + byte_input_set_result_callback( + byte_input, + nfc_scene_nfcv_key_input_byte_input_callback, + NULL, + nfc, + nfc->byte_input_store, + 4); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewByteInput); +} + +bool nfc_scene_nfcv_key_input_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventByteInputDone) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVUnlock); + DOLPHIN_DEED(DolphinDeedNfcRead); + consumed = true; + } + } + return consumed; +} + +void nfc_scene_nfcv_key_input_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + byte_input_set_result_callback(nfc->byte_input, NULL, NULL, NULL, NULL, 0); + byte_input_set_header_text(nfc->byte_input, ""); +} diff --git a/applications/main/nfc/scenes/nfc_scene_nfcv_menu.c b/applications/main/nfc/scenes/nfc_scene_nfcv_menu.c new file mode 100644 index 000000000..b30495a05 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcv_menu.c @@ -0,0 +1,63 @@ +#include "../nfc_i.h" +#include + +enum SubmenuIndex { + SubmenuIndexSave, + SubmenuIndexEmulate, +}; + +void nfc_scene_nfcv_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_nfcv_menu_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + submenu_add_item(submenu, "Save", SubmenuIndexSave, nfc_scene_nfcv_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Emulate", SubmenuIndexEmulate, nfc_scene_nfcv_menu_submenu_callback, nfc); + + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVMenu)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_nfcv_menu_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexSave) { + nfc->dev->format = NfcDeviceSaveFormatNfcV; + // Clear device name + nfc_device_set_name(nfc->dev, ""); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + consumed = true; + } else if(event.event == SubmenuIndexEmulate) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateNfcV); + if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSetType)) { + DOLPHIN_DEED(DolphinDeedNfcAddEmulate); + } else { + DOLPHIN_DEED(DolphinDeedNfcEmulate); + } + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcVMenu, event.event); + + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_nfcv_menu_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + submenu_reset(nfc->submenu); +} diff --git a/applications/main/nfc/scenes/nfc_scene_nfcv_unlock.c b/applications/main/nfc/scenes/nfc_scene_nfcv_unlock.c new file mode 100644 index 000000000..b52cc0caa --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcv_unlock.c @@ -0,0 +1,155 @@ +#include "../nfc_i.h" +#include + +typedef enum { + NfcSceneNfcVUnlockStateIdle, + NfcSceneNfcVUnlockStateDetecting, + NfcSceneNfcVUnlockStateUnlocked, + NfcSceneNfcVUnlockStateAlreadyUnlocked, + NfcSceneNfcVUnlockStateNotSupportedCard, +} NfcSceneNfcVUnlockState; + +static bool nfc_scene_nfcv_unlock_worker_callback(NfcWorkerEvent event, void* context) { + Nfc* nfc = context; + NfcVSlixData* data = &nfc->dev->dev_data.nfcv_data.sub_data.slix; + + if(event == NfcWorkerEventNfcVPassKey) { + memcpy(data->key_privacy, nfc->byte_input_store, 4); + } else { + view_dispatcher_send_custom_event(nfc->view_dispatcher, event); + } + return true; +} + +void nfc_scene_nfcv_unlock_popup_callback(void* context) { + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +void nfc_scene_nfcv_unlock_set_state(Nfc* nfc, NfcSceneNfcVUnlockState state) { + FuriHalNfcDevData* nfc_data = &(nfc->dev->dev_data.nfc_data); + NfcVData* nfcv_data = &(nfc->dev->dev_data.nfcv_data); + + uint32_t curr_state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVUnlock); + if(curr_state != state) { + Popup* popup = nfc->popup; + if(state == NfcSceneNfcVUnlockStateDetecting) { + popup_reset(popup); + popup_set_text( + popup, "Put figurine on\nFlipper's back", 97, 24, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 8, &I_NFC_manual_60x50); + } else if(state == NfcSceneNfcVUnlockStateUnlocked) { + popup_reset(popup); + + if(nfc_worker_get_state(nfc->worker) == NfcWorkerStateNfcVUnlockAndSave) { + nfc_text_store_set( + nfc, + "%s/SLIX_%02X%02X%02X%02X%02X%02X%02X%02X%s", + NFC_APP_FOLDER, + nfc_data->uid[0], + nfc_data->uid[1], + nfc_data->uid[2], + nfc_data->uid[3], + nfc_data->uid[4], + nfc_data->uid[5], + nfc_data->uid[6], + nfc_data->uid[7], + NFC_APP_EXTENSION); + + nfc->dev->format = NfcDeviceSaveFormatNfcV; + + if(nfc_device_save(nfc->dev, nfc->text_store)) { + popup_set_header(popup, "Successfully\nsaved", 94, 3, AlignCenter, AlignTop); + } else { + popup_set_header( + popup, "Unlocked but\nsave failed!", 94, 3, AlignCenter, AlignTop); + } + } else { + popup_set_header(popup, "Successfully\nunlocked", 94, 3, AlignCenter, AlignTop); + } + + notification_message(nfc->notifications, &sequence_single_vibro); + //notification_message(nfc->notifications, &sequence_success); + + popup_set_icon(popup, 0, 6, &I_RFIDDolphinSuccess_108x57); + popup_set_context(popup, nfc); + popup_set_callback(popup, nfc_scene_nfcv_unlock_popup_callback); + popup_set_timeout(popup, 1500); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + DOLPHIN_DEED(DolphinDeedNfcReadSuccess); + + } else if(state == NfcSceneNfcVUnlockStateAlreadyUnlocked) { + popup_reset(popup); + + popup_set_header(popup, "Already\nUnlocked!", 94, 3, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 6, &I_RFIDDolphinSuccess_108x57); + popup_set_context(popup, nfc); + popup_set_callback(popup, nfc_scene_nfcv_unlock_popup_callback); + popup_set_timeout(popup, 1500); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + } else if(state == NfcSceneNfcVUnlockStateNotSupportedCard) { + popup_reset(popup); + popup_set_header(popup, "Wrong Type Of Card!", 64, 3, AlignCenter, AlignTop); + popup_set_text(popup, nfcv_data->error, 4, 22, AlignLeft, AlignTop); + popup_set_icon(popup, 73, 20, &I_DolphinCommon_56x48); + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcVUnlock, state); + } +} + +void nfc_scene_nfcv_unlock_on_enter(void* context) { + Nfc* nfc = context; + + nfc_device_clear(nfc->dev); + // Setup view + nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateDetecting); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); + + // Start worker + nfc_worker_start( + nfc->worker, + NfcWorkerStateNfcVUnlockAndSave, + &nfc->dev->dev_data, + nfc_scene_nfcv_unlock_worker_callback, + nfc); + + nfc_blink_read_start(nfc); +} + +bool nfc_scene_nfcv_unlock_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcWorkerEventCardDetected) { + nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateUnlocked); + consumed = true; + } else if(event.event == NfcWorkerEventAborted) { + nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateAlreadyUnlocked); + consumed = true; + } else if(event.event == NfcWorkerEventNoCardDetected) { + nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateDetecting); + consumed = true; + } else if(event.event == NfcWorkerEventWrongCardDetected) { + nfc_scene_nfcv_unlock_set_state(nfc, NfcSceneNfcVUnlockStateNotSupportedCard); + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneNfcVUnlockMenu); + } + return consumed; +} + +void nfc_scene_nfcv_unlock_on_exit(void* context) { + Nfc* nfc = context; + + // Stop worker + nfc_worker_stop(nfc->worker); + // Clear view + popup_reset(nfc->popup); + nfc_blink_stop(nfc); + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneNfcVUnlock, NfcSceneNfcVUnlockStateIdle); +} diff --git a/applications/main/nfc/scenes/nfc_scene_nfcv_unlock_menu.c b/applications/main/nfc/scenes/nfc_scene_nfcv_unlock_menu.c new file mode 100644 index 000000000..9c4c81fbd --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_nfcv_unlock_menu.c @@ -0,0 +1,60 @@ +#include "../nfc_i.h" +#include + +enum SubmenuIndex { + SubmenuIndexNfcVUnlockMenuManual, + SubmenuIndexNfcVUnlockMenuTonieBox, +}; + +void nfc_scene_nfcv_unlock_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_nfcv_unlock_menu_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + uint32_t state = scene_manager_get_scene_state(nfc->scene_manager, NfcSceneNfcVUnlockMenu); + submenu_add_item( + submenu, + "Enter PWD Manually", + SubmenuIndexNfcVUnlockMenuManual, + nfc_scene_nfcv_unlock_menu_submenu_callback, + nfc); + submenu_add_item( + submenu, + "Auth As TonieBox", + SubmenuIndexNfcVUnlockMenuTonieBox, + nfc_scene_nfcv_unlock_menu_submenu_callback, + nfc); + submenu_set_selected_item(submenu, state); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_nfcv_unlock_menu_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexNfcVUnlockMenuManual) { + nfc->dev->dev_data.nfcv_data.auth_method = NfcVAuthMethodManual; + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVKeyInput); + consumed = true; + } else if(event.event == SubmenuIndexNfcVUnlockMenuTonieBox) { + nfc->dev->dev_data.nfcv_data.auth_method = NfcVAuthMethodTonieBox; + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcVUnlock); + DOLPHIN_DEED(DolphinDeedNfcRead); + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneNfcVUnlockMenu, event.event); + } + return consumed; +} + +void nfc_scene_nfcv_unlock_menu_on_exit(void* context) { + Nfc* nfc = context; + + submenu_reset(nfc->submenu); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_auth.c b/applications/main/nfc/scenes/nfc_scene_passport_auth.c new file mode 100644 index 000000000..c90c38233 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_auth.c @@ -0,0 +1,194 @@ +#include "../nfc_i.h" + +#define TAG "PassportAuth" + +#define MRTD_AUTH_METHOD_COUNT 4 +// Must match MrtdAuthMethod size (lib/nfc/protocols/mrtd_helpers.h) + +typedef enum { + NfcScenePassportAuthSelectDob, + NfcScenePassportAuthSelectDoe, + NfcScenePassportAuthSelectDocNr, + NfcScenePassportAuthSelectMethod, + NfcScenePassportAuthSelectAuth, + NfcScenePassportAuthSelectSave, + NfcScenePassportAuthSelectLoad, +} NfcScenePassportAuthSelect; + +void nfc_scene_passport_auth_var_list_enter_callback(void* context, uint32_t index) { + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_passport_auth_method_changed(VariableItem* item) { + Nfc* nfc = variable_item_get_context(item); + uint8_t index = variable_item_get_current_value_index(item); + nfc->dev->dev_data.mrtd_data.auth.method = index; + variable_item_set_current_value_text(item, mrtd_auth_method_string(index)); +} + +bool nfc_scene_passport_auth_load(Nfc* nfc) { + const DialogsFileBrowserOptions browser_options = { + .extension = MRTD_APP_EXTENSION, + .skip_assets = true, + .icon = &I_u2f_10px, + .hide_ext = true, + .item_loader_callback = NULL, + .item_loader_context = NULL, + }; + + FuriString* mrtd_app_folder; + mrtd_app_folder = furi_string_alloc_set(MRTD_APP_FOLDER); + + FuriString* file_path; + file_path = furi_string_alloc(); + + bool res = + dialog_file_browser_show(nfc->dev->dialogs, file_path, mrtd_app_folder, &browser_options); + + furi_string_free(mrtd_app_folder); + + if(res) { + mrtd_auth_params_load( + nfc->dev->storage, + nfc->dev->dialogs, + &nfc->dev->dev_data.mrtd_data.auth, + furi_string_get_cstr(file_path), + true); + + nfc_scene_passport_auth_on_enter(nfc); + variable_item_list_set_selected_item( + nfc->variable_item_list, NfcScenePassportAuthSelectAuth); + } + + return res; +} + +void nfc_scene_passport_auth_on_enter(void* context) { + Nfc* nfc = context; + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + + // By entering the Auth menu, we default to Auth: Any + MrtdAuthMethod* auth_method = &mrtd_data->auth.method; + if(*auth_method == MrtdAuthMethodNone) { + *auth_method = MrtdAuthMethodAny; + } + + VariableItemList* variable_item_list = nfc->variable_item_list; + variable_item_list_reset(variable_item_list); + + VariableItem* item; + uint8_t value_index; + + const size_t temp_str_size = 15; + char temp_str[temp_str_size]; + snprintf( + temp_str, + temp_str_size, + "%02u%02u%02u", + mrtd_data->auth.birth_date.year, + mrtd_data->auth.birth_date.month, + mrtd_data->auth.birth_date.day); + + item = variable_item_list_add(variable_item_list, "Birth Date", 1, NULL, NULL); + variable_item_set_current_value_text(item, temp_str); + + snprintf( + temp_str, + temp_str_size, + "%02u%02u%02u", + mrtd_data->auth.expiry_date.year, + mrtd_data->auth.expiry_date.month, + mrtd_data->auth.expiry_date.day); + + item = variable_item_list_add(variable_item_list, "Expiry Date", 1, NULL, NULL); + variable_item_set_current_value_text(item, temp_str); + + item = variable_item_list_add(variable_item_list, "Document Nr.", 1, NULL, NULL); + + strncpy(temp_str, mrtd_data->auth.doc_number, temp_str_size); + temp_str[temp_str_size -1] = '\x00'; + if(strlen(temp_str) > 8) { + temp_str[8] = '.'; + temp_str[9] = '.'; + temp_str[10] = '.'; + temp_str[11] = '\x00'; + } + variable_item_set_current_value_text(item, temp_str); + + item = variable_item_list_add( + variable_item_list, + "Method", + MRTD_AUTH_METHOD_COUNT, + nfc_scene_passport_auth_method_changed, + nfc); + + value_index = *auth_method; + variable_item_set_current_value_index(item, value_index); + variable_item_set_current_value_text(item, mrtd_auth_method_string(value_index)); + + variable_item_list_add(variable_item_list, "Authenticate and read", 1, NULL, NULL); + + variable_item_list_add(variable_item_list, "Save parameters", 1, NULL, NULL); + variable_item_list_add(variable_item_list, "Load parameters", 1, NULL, NULL); + + variable_item_list_set_enter_callback( + variable_item_list, nfc_scene_passport_auth_var_list_enter_callback, nfc); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewVarItemList); +} + +bool nfc_scene_passport_auth_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + FURI_LOG_D(TAG, "event.event: %ld", event.event); + switch(event.event) { + case NfcScenePassportAuthSelectLoad: + nfc_scene_passport_auth_load(nfc); + consumed = true; + break; + case NfcScenePassportAuthSelectDob: + scene_manager_set_scene_state(nfc->scene_manager, NfcScenePassportDate, 0); + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportDate); + consumed = true; + break; + case NfcScenePassportAuthSelectDoe: + scene_manager_set_scene_state(nfc->scene_manager, NfcScenePassportDate, 1); + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportDate); + consumed = true; + break; + case NfcScenePassportAuthSelectDocNr: + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportDocNr); + consumed = true; + break; + case NfcScenePassportAuthSelectMethod: + consumed = true; + break; + case NfcScenePassportAuthSelectAuth: + if(nfc->dev->dev_data.mrtd_data.auth.method == MrtdAuthMethodPace) { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportPaceTodo); + } else { + nfc_device_clear(nfc->dev); + scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); + } + consumed = true; + break; + case NfcScenePassportAuthSelectSave: + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportAuthSaveName); + consumed = true; + break; + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_passport_auth_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + variable_item_list_reset(nfc->variable_item_list); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_auth_save_name.c b/applications/main/nfc/scenes/nfc_scene_passport_auth_save_name.c new file mode 100644 index 000000000..65fee0bcf --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_auth_save_name.c @@ -0,0 +1,82 @@ +#include "../nfc_i.h" +#include +#include +#include + +void nfc_scene_passport_auth_save_name_text_input_callback(void* context) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone); +} + +void nfc_scene_passport_auth_save_name_on_enter(void* context) { + Nfc* nfc = context; + + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + + // Setup view + TextInput* text_input = nfc->text_input; + bool docnr_empty = false; + if(!strcmp(mrtd_data->auth.doc_number, "")) { + set_random_name(nfc->text_store, sizeof(nfc->text_store)); + docnr_empty = true; + } else { + nfc_text_store_set(nfc, mrtd_data->auth.doc_number); + } + text_input_set_header_text(text_input, "Name the parameters"); + text_input_set_result_callback( + text_input, + nfc_scene_passport_auth_save_name_text_input_callback, + nfc, + nfc->text_store, + NFC_DEV_NAME_MAX_LEN, + docnr_empty); + + FuriString* folder_path; + folder_path = furi_string_alloc(); + + if(furi_string_end_with(nfc->dev->load_path, NFC_APP_EXTENSION)) { + path_extract_dirname(furi_string_get_cstr(nfc->dev->load_path), folder_path); + } else { + furi_string_set(folder_path, NFC_APP_FOLDER); + } + + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(furi_string_get_cstr(folder_path), NFC_APP_EXTENSION, NULL); + text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); + + furi_string_free(folder_path); +} + +bool nfc_scene_passport_auth_save_name_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventTextInputDone) { + if(mrtd_auth_params_save( + nfc->dev->storage, nfc->dev->dialogs, &mrtd_data->auth, nfc->text_store)) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveSuccess); + consumed = true; + } else { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneStart); + } + } + } + return consumed; +} + +void nfc_scene_passport_auth_save_name_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + void* validator_context = text_input_get_validator_callback_context(nfc->text_input); + text_input_set_validator(nfc->text_input, NULL, NULL); + validator_is_file_free(validator_context); + + text_input_reset(nfc->text_input); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_date.c b/applications/main/nfc/scenes/nfc_scene_passport_date.c new file mode 100644 index 000000000..6655bdd59 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_date.c @@ -0,0 +1,126 @@ +#include "../nfc_i.h" +#include "m-string.h" +#include + +#define TAG "PassportDate" + +#define DATE_LENGTH 6 + +//TODO: use types in .h file? also in nfc_scene_passport_bac.c +#define NFC_PASSPORT_DATE_BIRTH 0 +#define NFC_PASSPORT_DATE_EXPIRY 1 + +void nfc_scene_passport_date_text_input_callback(void* context) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone); +} + +void nfc_scene_passport_date_on_enter(void* context) { + Nfc* nfc = context; + + MrtdDate date_value; + + uint32_t date_type = scene_manager_get_scene_state(nfc->scene_manager, NfcScenePassportDate); + + //TODO: numbers only + TextInput* text_input = nfc->text_input; + + // TODO: Clean this up because I'm bad + date_value.year = 0; + date_value.month = 0; + date_value.day = 0; + + + switch(date_type) { + case NFC_PASSPORT_DATE_BIRTH: + text_input_set_header_text(text_input, "Birth Date"); + date_value = nfc->dev->dev_data.mrtd_data.auth.birth_date; + break; + case NFC_PASSPORT_DATE_EXPIRY: + text_input_set_header_text(text_input, "Expiry Date"); + date_value = nfc->dev->dev_data.mrtd_data.auth.expiry_date; + break; + } + + bool date_empty = false; + if(date_value.year == 0 || date_value.month == 0 || date_value.day == 0 || + date_value.year > 100 || date_value.month > 13 || date_value.day > 31) { + nfc_text_store_set(nfc, "YYMMDD"); + date_empty = true; + } else { + char temp_str[10]; + snprintf(temp_str, 10, "%02u%02u%02u", date_value.year, date_value.month, date_value.day); + + memcpy(nfc->text_store, temp_str, DATE_LENGTH); + nfc->text_store[DATE_LENGTH] = '\x00'; + } + + text_input_set_result_callback( + text_input, + nfc_scene_passport_date_text_input_callback, + nfc, + nfc->text_store, + DATE_LENGTH + 1, // incl. '\x00' + date_empty); // Use as template + + //TODO: add validator for valid date (YYMMDD) + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); +} + +bool nfc_scene_passport_date_save(Nfc* nfc) { + int year; + int month; + int day; + int ret = sscanf(nfc->text_store, "%02d%02d%02d", &year, &month, &day); + + if(ret != 3) { + FURI_LOG_E(TAG, "Invalid date entered (YYMMDD): %s", nfc->text_store); + return false; + } + + MrtdDate date_value; + date_value.year = year; + date_value.month = month; + date_value.day = day; + + uint32_t date_type = scene_manager_get_scene_state(nfc->scene_manager, NfcScenePassportDate); + + //TODO: use types in .h file? also in nfc_scene_passport_bac.c + switch(date_type) { + case NFC_PASSPORT_DATE_BIRTH: + nfc->dev->dev_data.mrtd_data.auth.birth_date = date_value; + break; + case NFC_PASSPORT_DATE_EXPIRY: + nfc->dev->dev_data.mrtd_data.auth.expiry_date = date_value; + break; + } + + return true; +} + +bool nfc_scene_passport_date_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventTextInputDone) { + nfc_scene_passport_date_save(nfc); + //TODO: handle invalid date (returned false) + + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcScenePassportAuth); + } + } + return consumed; +} + +void nfc_scene_passport_date_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + // TODO: clear validator + + text_input_reset(nfc->text_input); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_docnr.c b/applications/main/nfc/scenes/nfc_scene_passport_docnr.c new file mode 100644 index 000000000..109415759 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_docnr.c @@ -0,0 +1,67 @@ +#include "../nfc_i.h" +#include "m-string.h" +#include + +#define TAG "PassportDocnr" + +void nfc_scene_passport_docnr_text_input_callback(void* context) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventTextInputDone); +} + +void nfc_scene_passport_docnr_on_enter(void* context) { + Nfc* nfc = context; + + TextInput* text_input = nfc->text_input; + text_input_set_header_text(text_input, "Document Nr."); + + char* docnr = nfc->dev->dev_data.mrtd_data.auth.doc_number; + bool docnr_empty = false; + + if(*docnr) { + nfc_text_store_set(nfc, docnr); + docnr_empty = false; + } else { + nfc_text_store_set(nfc, "PA7HJ34M8"); + docnr_empty = true; + } + + text_input_set_result_callback( + text_input, + nfc_scene_passport_docnr_text_input_callback, + nfc, + nfc->text_store, + MRTD_DOCNR_MAX_LENGTH, // incl. '\x00' + docnr_empty); // Use as template + + //TODO: add validator? + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextInput); +} + +bool nfc_scene_passport_docnr_save(Nfc* nfc) { + strncpy(nfc->dev->dev_data.mrtd_data.auth.doc_number, nfc->text_store, MRTD_DOCNR_MAX_LENGTH); + return true; +} + +bool nfc_scene_passport_docnr_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventTextInputDone) { + nfc_scene_passport_docnr_save(nfc); + + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcScenePassportAuth); + } + } + return consumed; +} + +void nfc_scene_passport_docnr_on_exit(void* context) { + Nfc* nfc = context; + + text_input_reset(nfc->text_input); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_menu.c b/applications/main/nfc/scenes/nfc_scene_passport_menu.c new file mode 100644 index 000000000..27febcb18 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_menu.c @@ -0,0 +1,57 @@ +#include "../nfc_i.h" + +enum SubmenuIndex { + SubmenuIndexSave, + SubmenuIndexInfo, +}; + +void nfc_scene_passport_menu_submenu_callback(void* context, uint32_t index) { + Nfc* nfc = context; + + view_dispatcher_send_custom_event(nfc->view_dispatcher, index); +} + +void nfc_scene_passport_menu_on_enter(void* context) { + Nfc* nfc = context; + Submenu* submenu = nfc->submenu; + + submenu_add_item( + submenu, "Save", SubmenuIndexSave, nfc_scene_passport_menu_submenu_callback, nfc); + submenu_add_item( + submenu, "Info", SubmenuIndexInfo, nfc_scene_passport_menu_submenu_callback, nfc); + submenu_set_selected_item( + nfc->submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcScenePassportMenu)); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); +} + +bool nfc_scene_passport_menu_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == SubmenuIndexSave) { + //TODO: save more than just UID + nfc->dev->format = NfcDeviceSaveFormatUid; + // Clear device name + nfc_device_set_name(nfc->dev, ""); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSaveName); + consumed = true; + } else if(event.event == SubmenuIndexInfo) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + consumed = true; + } + scene_manager_set_scene_state(nfc->scene_manager, NfcScenePassportMenu, event.event); + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(nfc->scene_manager); + } + + return consumed; +} + +void nfc_scene_passport_menu_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + submenu_reset(nfc->submenu); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_pace_todo.c b/applications/main/nfc/scenes/nfc_scene_passport_pace_todo.c new file mode 100644 index 000000000..c6d7d7f6c --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_pace_todo.c @@ -0,0 +1,40 @@ +#include "../nfc_i.h" + +void nfc_scene_passport_pace_todo_popup_callback(void* context) { + Nfc* nfc = context; + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); +} + +void nfc_scene_passport_pace_todo_on_enter(void* context) { + Nfc* nfc = context; + + // Setup view + Popup* popup = nfc->popup; + popup_set_icon(popup, 64, 16, &I_DolphinCommon_56x48); + popup_set_header(popup, "PACE not yet implemented", 4, 4, AlignLeft, AlignTop); + popup_set_timeout(popup, 2000); + popup_set_context(popup, nfc); + popup_set_callback(popup, nfc_scene_passport_pace_todo_popup_callback); + popup_enable_timeout(popup); + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); +} + +bool nfc_scene_passport_pace_todo_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == NfcCustomEventViewExit) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcScenePassportAuth); + } + } + return consumed; +} + +void nfc_scene_passport_pace_todo_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + popup_reset(nfc->popup); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_read.c b/applications/main/nfc/scenes/nfc_scene_passport_read.c new file mode 100644 index 000000000..74f173b52 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_read.c @@ -0,0 +1,90 @@ +#include "../nfc_i.h" +#include + +void nfc_scene_passport_read_widget_callback(GuiButtonType result, InputType type, void* context) { + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_passport_read_on_enter(void* context) { + Nfc* nfc = context; + FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + + DOLPHIN_DEED(DolphinDeedNfcReadSuccess); + + Widget* widget = nfc->widget; + + // Setup Custom Widget view + FuriString* temp_str; + temp_str = furi_string_alloc(); + furi_string_set(temp_str, "\e#Passport\n"); + char iso_type = FURI_BIT(data->sak, 5) ? '4' : '3'; + + char nfc_type; + switch(data->type) { + case FuriHalNfcTypeA: + nfc_type = 'A'; + break; + case FuriHalNfcTypeB: + nfc_type = 'B'; + break; + default: + nfc_type = '?'; + break; + } + furi_string_cat_printf(temp_str, "ISO 14443-%c (NFC-%c)\n", iso_type, nfc_type); + furi_string_cat_printf(temp_str, "UID:"); + for(size_t i = 0; i < data->uid_len; i++) { + furi_string_cat_printf(temp_str, " %02X", data->uid[i]); + } + furi_string_cat_printf(temp_str, "\nATQA: %02X %02X ", data->atqa[1], data->atqa[0]); + furi_string_cat_printf(temp_str, " SAK: %02X\n", data->sak); + + if(mrtd_data->auth.method != MrtdAuthMethodNone && !mrtd_data->auth_success) { + furi_string_cat_printf(temp_str, "Auth failed. Wrong params?"); + } + + widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); + + widget_add_button_element( + nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_passport_read_widget_callback, nfc); + widget_add_button_element( + nfc->widget, GuiButtonTypeCenter, "Auth", nfc_scene_passport_read_widget_callback, nfc); + widget_add_button_element( + nfc->widget, GuiButtonTypeRight, "More", nfc_scene_passport_read_widget_callback, nfc); + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_passport_read_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); + consumed = true; + } else if(event.event == GuiButtonTypeCenter) { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportAuth); + consumed = true; + } else if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportMenu); + consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; + } + return consumed; +} + +void nfc_scene_passport_read_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + widget_reset(nfc->widget); +} diff --git a/applications/main/nfc/scenes/nfc_scene_passport_read_auth.c b/applications/main/nfc/scenes/nfc_scene_passport_read_auth.c new file mode 100644 index 000000000..31a9e8ce1 --- /dev/null +++ b/applications/main/nfc/scenes/nfc_scene_passport_read_auth.c @@ -0,0 +1,142 @@ +#include "../nfc_i.h" +#include + +const char months[13][4] = { + "---", + "JAN", + "FEB", + "MAR", + "APR", + "MAY", + "JUN", + "JUL", + "AUG", + "SEP", + "OCT", + "NOV", + "DEC", +}; + +void nfc_scene_passport_read_auth_widget_callback( + GuiButtonType result, + InputType type, + void* context) { + Nfc* nfc = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(nfc->view_dispatcher, result); + } +} + +void nfc_scene_passport_read_auth_on_enter(void* context) { + Nfc* nfc = context; + MrtdData* mrtd_data = &nfc->dev->dev_data.mrtd_data; + + Widget* widget = nfc->widget; + + // Setup Custom Widget view + FuriString* temp_str; + temp_str = furi_string_alloc(); + furi_string_set(temp_str, "\e#Passport\n"); + furi_string_cat_printf( + temp_str, "Auth.method: %s\n", mrtd_auth_method_string(mrtd_data->auth_method_used)); + // TODO: indicate BAC / PACE used + + uint16_t lds_version = mrtd_data->files.EF_COM.lds_version; + furi_string_cat_printf(temp_str, "LDS version: %d.%d\n", lds_version / 100, lds_version % 100); + + uint32_t unicode_version = mrtd_data->files.EF_COM.unicode_version; + furi_string_cat_printf( + temp_str, + "Unicode version: %d.%d.%d\n", + (uint8_t)(unicode_version / 10000), + (uint8_t)(unicode_version / 100 % 100), + (uint8_t)(unicode_version % 100)); + + furi_string_cat_printf(temp_str, "Avail.files: "); + for(size_t i = 0; i < MAX_EFCOM_TAGS; ++i) { + uint8_t tag = mrtd_data->files.EF_COM.tag_list[i]; + const EFFile* file = mrtd_tag_to_file(tag); + if(file->tag) { + if(i > 0) furi_string_cat_printf(temp_str, ", "); + furi_string_cat_printf(temp_str, "%s", file->name); + } + } + furi_string_cat_printf(temp_str, "\n"); + + EF_DIR_contents* EF_DIR = &mrtd_data->files.EF_DIR; + if(EF_DIR->applications_count > 0) { + furi_string_cat_printf(temp_str, "Apps:\n"); + for(uint8_t i = 0; i < EF_DIR->applications_count; ++i) { + for(uint8_t n = 0; n < sizeof(AIDValue); ++n) { + furi_string_cat_printf(temp_str, "%02X ", EF_DIR->applications[i][n]); + } + furi_string_cat_printf(temp_str, "\n"); + } + } + + EF_DG1_contents* DG1 = &mrtd_data->files.DG1; + furi_string_cat_printf(temp_str, "\e#DG1\n"); + furi_string_cat_printf(temp_str, "Doc Type: %s\n", DG1->doctype); + furi_string_cat_printf(temp_str, "Issuing State: %s\n", DG1->issuing_state); + furi_string_cat_printf(temp_str, "Name: %s\n", DG1->name); + furi_string_cat_printf(temp_str, "DocNr: %s\n", DG1->docnr); + furi_string_cat_printf(temp_str, "Nationality: %s\n", DG1->nationality); + furi_string_cat_printf( + temp_str, + "Birth Date: %02d %s %02d\n", + DG1->birth_date.day, + months[DG1->birth_date.month], + DG1->birth_date.year); + furi_string_cat_printf(temp_str, "Sex: %s\n", DG1->sex); + furi_string_cat_printf( + temp_str, + "Expiry Date: %02d %s %02d\n", + DG1->expiry_date.day, + months[DG1->expiry_date.month], + DG1->expiry_date.year); + + widget_add_text_scroll_element(widget, 0, 0, 128, 52, furi_string_get_cstr(temp_str)); + furi_string_free(temp_str); + + widget_add_button_element( + nfc->widget, GuiButtonTypeLeft, "Retry", nfc_scene_passport_read_auth_widget_callback, nfc); + /* + widget_add_button_element( + nfc->widget, GuiButtonTypeCenter, "Auth", nfc_scene_passport_read_auth_widget_callback, nfc); + widget_add_button_element( + nfc->widget, GuiButtonTypeRight, "More", nfc_scene_passport_read_auth_widget_callback, nfc); + */ + + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewWidget); +} + +bool nfc_scene_passport_read_auth_on_event(void* context, SceneManagerEvent event) { + Nfc* nfc = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + if(event.event == GuiButtonTypeLeft) { + nfc->dev->dev_data.mrtd_data.auth_success = false; + nfc->dev->dev_data.mrtd_data.auth.method = MrtdAuthMethodNone; + scene_manager_next_scene(nfc->scene_manager, NfcSceneRetryConfirm); + consumed = true; + } else if(event.event == GuiButtonTypeCenter) { + //scene_manager_next_scene(nfc->scene_manager, NfcScenePassportAuth); + //consumed = true; + } else if(event.event == GuiButtonTypeRight) { + //scene_manager_next_scene(nfc->scene_manager, NfcScenePassportMenu); + //consumed = true; + } + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneExitConfirm); + consumed = true; + } + return consumed; +} + +void nfc_scene_passport_read_auth_on_exit(void* context) { + Nfc* nfc = context; + + // Clear view + widget_reset(nfc->widget); +} diff --git a/applications/main/nfc/scenes/nfc_scene_read.c b/applications/main/nfc/scenes/nfc_scene_read.c index 4252883b2..7164a155f 100644 --- a/applications/main/nfc/scenes/nfc_scene_read.c +++ b/applications/main/nfc/scenes/nfc_scene_read.c @@ -25,12 +25,12 @@ void nfc_scene_read_set_state(Nfc* nfc, NfcSceneReadState state) { if(state == NfcSceneReadStateDetecting) { popup_reset(nfc->popup); popup_set_text( - nfc->popup, "Apply card to\nFlipper's back", 97, 24, AlignCenter, AlignTop); + nfc->popup, "Apply Card To\nFlipper's Back", 97, 24, AlignCenter, AlignTop); popup_set_icon(nfc->popup, 0, 8, &I_NFC_manual_60x50); } else if(state == NfcSceneReadStateReading) { popup_reset(nfc->popup); popup_set_header( - nfc->popup, "Reading card\nDon't move...", 85, 24, AlignCenter, AlignTop); + nfc->popup, "Reading Card\nDon't Move...", 85, 24, AlignCenter, AlignTop); popup_set_icon(nfc->popup, 12, 23, &A_Loading_24); } scene_manager_set_scene_state(nfc->scene_manager, NfcSceneRead, state); @@ -68,6 +68,11 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcaReadSuccess); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); consumed = true; + } else if(event.event == NfcWorkerEventReadNfcV) { + notification_message(nfc->notifications, &sequence_success); + scene_manager_next_scene(nfc->scene_manager, NfcSceneNfcDataInfo); + DOLPHIN_DEED(DolphinDeedNfcReadSuccess); + consumed = true; } else if(event.event == NfcWorkerEventReadMfUltralight) { notification_message(nfc->notifications, &sequence_success); // Set unlock password input to 0xFFFFFFFF only on fresh read @@ -90,6 +95,19 @@ bool nfc_scene_read_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmvReadSuccess); DOLPHIN_DEED(DolphinDeedNfcReadSuccess); consumed = true; + } else if(event.event == NfcWorkerEventReadPassport) { + notification_message(nfc->notifications, &sequence_success); + FURI_LOG_D( + "NFC", + "Read passport, auth: %d, success: %d", + nfc->dev->dev_data.mrtd_data.auth.method, + nfc->dev->dev_data.mrtd_data.auth_success); + if(nfc->dev->dev_data.mrtd_data.auth_success) { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportReadAuthSuccess); + } else { + scene_manager_next_scene(nfc->scene_manager, NfcScenePassportReadSuccess); + } + consumed = true; } else if(event.event == NfcWorkerEventReadMfClassicDictAttackRequired) { if(mf_classic_dict_check_presence(MfClassicDictTypeSystem)) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicDictAttack); diff --git a/applications/main/nfc/scenes/nfc_scene_restore_original.c b/applications/main/nfc/scenes/nfc_scene_restore_original.c index 3709008fd..3ecf5c048 100644 --- a/applications/main/nfc/scenes/nfc_scene_restore_original.c +++ b/applications/main/nfc/scenes/nfc_scene_restore_original.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_restore_original_popup_callback(void* context) { Nfc* nfc = context; @@ -8,24 +7,16 @@ void nfc_scene_restore_original_popup_callback(void* context) { void nfc_scene_restore_original_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); // Setup view Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - } + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_header(popup, "Original file\nrestored", 13, 22, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); popup_set_callback(popup, nfc_scene_restore_original_popup_callback); popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_restore_original_on_event(void* context, SceneManagerEvent event) { diff --git a/applications/main/nfc/scenes/nfc_scene_rpc.c b/applications/main/nfc/scenes/nfc_scene_rpc.c index e0da1317c..d06ee7564 100644 --- a/applications/main/nfc/scenes/nfc_scene_rpc.c +++ b/applications/main/nfc/scenes/nfc_scene_rpc.c @@ -1,25 +1,17 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_rpc_on_enter(void* context) { Nfc* nfc = context; Popup* popup = nfc->popup; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); popup_set_header(popup, "NFC", 89, 42, AlignCenter, AlignBottom); popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop); - if (settings->sfw_mode) { - popup_set_icon(popup, 0, 12, &I_NFC_dolphin_emulation_47x61_sfw); - } - else { - popup_set_icon(popup, 0, 12, &I_NFC_dolphin_emulation_47x61); - } + + popup_set_icon(popup, 0, 12, &I_NFC_dolphin_emulation_47x61); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); notification_message(nfc->notifications, &sequence_display_backlight_on); - free(settings); } static bool nfc_scene_rpc_emulate_callback(NfcWorkerEvent event, void* context) { @@ -63,6 +55,13 @@ bool nfc_scene_rpc_on_event(void* context, SceneManagerEvent event) { &nfc->dev->dev_data, nfc_scene_rpc_emulate_callback, nfc); + } else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) { + nfc_worker_start( + nfc->worker, + NfcWorkerStateNfcVEmulate, + &nfc->dev->dev_data, + nfc_scene_rpc_emulate_callback, + nfc); } else { nfc_worker_start( nfc->worker, NfcWorkerStateUidEmulate, &nfc->dev->dev_data, NULL, nfc); diff --git a/applications/main/nfc/scenes/nfc_scene_save_name.c b/applications/main/nfc/scenes/nfc_scene_save_name.c index 007274226..8f0e889ec 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_name.c +++ b/applications/main/nfc/scenes/nfc_scene_save_name.c @@ -22,7 +22,7 @@ void nfc_scene_save_name_on_enter(void* context) { } else { nfc_text_store_set(nfc, nfc->dev->dev_name); } - text_input_set_header_text(text_input, "Name the card"); + text_input_set_header_text(text_input, "Name The Card"); text_input_set_result_callback( text_input, nfc_scene_save_name_text_input_callback, diff --git a/applications/main/nfc/scenes/nfc_scene_save_success.c b/applications/main/nfc/scenes/nfc_scene_save_success.c index 8e74a55ae..43f2246cd 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_success.c +++ b/applications/main/nfc/scenes/nfc_scene_save_success.c @@ -1,5 +1,4 @@ #include "../nfc_i.h" -#include "../../../settings/desktop_settings/desktop_settings_app.h" void nfc_scene_save_success_popup_callback(void* context) { Nfc* nfc = context; @@ -8,24 +7,16 @@ void nfc_scene_save_success_popup_callback(void* context) { void nfc_scene_save_success_on_enter(void* context) { Nfc* nfc = context; - DesktopSettings* settings = malloc(sizeof(DesktopSettings)); - DESKTOP_SETTINGS_LOAD(settings); // Setup view Popup* popup = nfc->popup; - if (settings->sfw_mode) { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59_sfw); - } - else { - popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); - } + popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59); popup_set_header(popup, "Saved!", 13, 22, AlignLeft, AlignBottom); popup_set_timeout(popup, 1500); popup_set_context(popup, nfc); popup_set_callback(popup, nfc_scene_save_success_popup_callback); popup_enable_timeout(popup); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); - free(settings); } bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { @@ -40,6 +31,12 @@ bool nfc_scene_save_success_on_event(void* context, SceneManagerEvent event) { } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneSavedMenu)) { consumed = scene_manager_search_and_switch_to_previous_scene( nfc->scene_manager, NfcSceneSavedMenu); + } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcScenePassportAuth)) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcScenePassportAuth); + } else if(scene_manager_has_previous_scene(nfc->scene_manager, NfcSceneNfcDataInfo)) { + consumed = scene_manager_search_and_switch_to_previous_scene( + nfc->scene_manager, NfcSceneNfcDataInfo); } else { consumed = scene_manager_search_and_switch_to_another_scene( nfc->scene_manager, NfcSceneFileSelect); diff --git a/applications/main/nfc/scenes/nfc_scene_saved_menu.c b/applications/main/nfc/scenes/nfc_scene_saved_menu.c index c0d3ed5c6..616dc0ef7 100644 --- a/applications/main/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_saved_menu.c @@ -117,6 +117,8 @@ bool nfc_scene_saved_menu_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightEmulate); } else if(nfc->dev->format == NfcDeviceSaveFormatMifareClassic) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicEmulate); + } else if(nfc->dev->format == NfcDeviceSaveFormatNfcV) { + scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateNfcV); } else { scene_manager_next_scene(nfc->scene_manager, NfcSceneEmulateUid); } diff --git a/applications/main/nfc/views/dict_attack.c b/applications/main/nfc/views/dict_attack.c index a539e514b..9ee9b1e15 100644 --- a/applications/main/nfc/views/dict_attack.c +++ b/applications/main/nfc/views/dict_attack.c @@ -32,7 +32,7 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { DictAttackViewModel* m = model; if(m->state == DictAttackStateCardRemoved) { canvas_set_font(canvas, FontPrimary); - canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost the tag!"); + canvas_draw_str_aligned(canvas, 64, 4, AlignCenter, AlignTop, "Lost The Tag!"); canvas_set_font(canvas, FontSecondary); elements_multiline_text_aligned( canvas, 64, 23, AlignCenter, AlignTop, "Make sure the tag is\npositioned correctly."); @@ -69,7 +69,7 @@ static void dict_attack_draw_callback(Canvas* canvas, void* model) { } elements_progress_bar_with_text(canvas, 0, 20, 128, dict_progress, draw_str); canvas_set_font(canvas, FontSecondary); - snprintf(draw_str, sizeof(draw_str), "Keys found: %d/%d", m->keys_found, m->keys_total); + snprintf(draw_str, sizeof(draw_str), "Keys Found: %d/%d", m->keys_found, m->keys_total); canvas_draw_str_aligned(canvas, 0, 33, AlignLeft, AlignTop, draw_str); snprintf( draw_str, sizeof(draw_str), "Sectors Read: %d/%d", m->sectors_read, m->sectors_total);