diff --git a/applications/main/nfc/nfc.c b/applications/main/nfc/nfc.c index b6ea9cfb8..16d5837ea 100644 --- a/applications/main/nfc/nfc.c +++ b/applications/main/nfc/nfc.c @@ -87,13 +87,6 @@ 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)); @@ -166,10 +159,6 @@ 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); @@ -301,11 +290,6 @@ 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, NfcSceneEmulateUid); } 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 a3a62972c..f7e489902 100644 --- a/applications/main/nfc/nfc_i.h +++ b/applications/main/nfc/nfc_i.h @@ -21,7 +21,6 @@ #include #include #include -#include #include #include @@ -78,7 +77,6 @@ struct Nfc { TextInput* text_input; ByteInput* byte_input; TextBox* text_box; - VariableItemList* variable_item_list; Widget* widget; DictAttack* dict_attack; DetectReader* detect_reader; @@ -94,7 +92,6 @@ 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 ef257b76e..a9da07dfd 100644 --- a/applications/main/nfc/scenes/nfc_scene_config.h +++ b/applications/main/nfc/scenes/nfc_scene_config.h @@ -4,7 +4,7 @@ ADD_SCENE(nfc, saved_menu, SavedMenu) ADD_SCENE(nfc, extra_actions, ExtraActions) ADD_SCENE(nfc, set_type, SetType) ADD_SCENE(nfc, set_sak, SetSak) -ADD_SCENE(nfc, set_atqa, SetAtqua) +ADD_SCENE(nfc, set_atqa, SetAtqa) ADD_SCENE(nfc, set_uid, SetUid) ADD_SCENE(nfc, generate_info, GenerateInfo) ADD_SCENE(nfc, read_card_success, ReadCardSuccess) @@ -14,11 +14,6 @@ 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) @@ -51,14 +46,6 @@ 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 4994dd8d4..d8e2652a9 100644 --- a/applications/main/nfc/scenes/nfc_scene_delete_success.c +++ b/applications/main/nfc/scenes/nfc_scene_delete_success.c @@ -31,7 +31,7 @@ bool nfc_scene_delete_success_on_event(void* context, SceneManagerEvent event) { nfc->scene_manager, NfcSceneMfClassicKeys); } else { consumed = scene_manager_search_and_switch_to_previous_scene( - nfc->scene_manager, NfcSceneStart); + nfc->scene_manager, NfcSceneFileSelect); } } } diff --git a/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c b/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c deleted file mode 100644 index 0e9f6b428..000000000 --- a/applications/main/nfc/scenes/nfc_scene_emulate_nfcv.c +++ /dev/null @@ -1,151 +0,0 @@ -#include "../nfc_i.h" -#include "xtreme/assets.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, XTREME_ASSETS()->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_extra_actions.c b/applications/main/nfc/scenes/nfc_scene_extra_actions.c index 147c89757..66aaf5a26 100644 --- a/applications/main/nfc/scenes/nfc_scene_extra_actions.c +++ b/applications/main/nfc/scenes/nfc_scene_extra_actions.c @@ -4,7 +4,6 @@ enum SubmenuIndex { SubmenuIndexReadCardType, SubmenuIndexMfClassicKeys, SubmenuIndexMfUltralightUnlock, - SubmenuIndexNfcVUnlock, }; void nfc_scene_extra_actions_submenu_callback(void* context, uint32_t index) { @@ -35,12 +34,8 @@ 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); + submenu_set_selected_item( + submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneExtraActions)); view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu); } @@ -63,9 +58,6 @@ 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_ultralight_emulate.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c index 77d831cf8..f90d177e2 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_emulate.c @@ -1,105 +1,21 @@ #include "../nfc_i.h" -#include #include "xtreme/assets.h" -#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) -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) { + UNUSED(event); 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, XTREME_ASSETS()->I_NFC_dolphin_emulation_47x61); - - 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; - 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) || @@ -116,12 +32,8 @@ void nfc_scene_mf_ultralight_emulate_on_enter(void* context) { popup_set_icon(popup, 0, 3, XTREME_ASSETS()->I_NFC_dolphin_emulation_47x61); popup_set_text(popup, nfc->text_store, 90, 28, AlignCenter, AlignTop); - // 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 + // Setup and start worker + view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewPopup); nfc_worker_start( nfc->worker, NfcWorkerStateMfUltralightEmulate, @@ -148,28 +60,16 @@ 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 - widget_reset(nfc->widget); - text_box_reset(nfc->text_box); - furi_string_reset(nfc->text_box_store); + popup_reset(nfc->popup); nfc_blink_stop(nfc); } 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 ddf30c54a..c511e9dcb 100644 --- a/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_menu.c @@ -2,8 +2,7 @@ #include enum SubmenuIndex { - SubmenuIndexUnlockByReader, - SubmenuIndexUnlockByPassword, + SubmenuIndexUnlock, SubmenuIndexSave, SubmenuIndexEmulate, SubmenuIndexInfo, @@ -23,14 +22,8 @@ void nfc_scene_mf_ultralight_menu_on_enter(void* context) { if(!mf_ul_is_full_capture(data)) { submenu_add_item( submenu, - "Unlock With Reader", - SubmenuIndexUnlockByReader, - nfc_scene_mf_ultralight_menu_submenu_callback, - nfc); - submenu_add_item( - submenu, - "Unlock With Password", - SubmenuIndexUnlockByPassword, + "Unlock", + SubmenuIndexUnlock, nfc_scene_mf_ultralight_menu_submenu_callback, nfc); } @@ -70,10 +63,7 @@ bool nfc_scene_mf_ultralight_menu_on_event(void* context, SceneManagerEvent even DOLPHIN_DEED(DolphinDeedNfcEmulate); } consumed = true; - } else if(event.event == SubmenuIndexUnlockByReader) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneMfUltralightUnlockAuto); - consumed = true; - } else if(event.event == SubmenuIndexUnlockByPassword) { + } else if(event.event == SubmenuIndexUnlock) { 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_unlock_auto.c b/applications/main/nfc/scenes/nfc_scene_mf_ultralight_unlock_auto.c index 050f6db1e..c59fe3a7d 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_emulate_start(nfc); + nfc_blink_read_start(nfc); } bool nfc_scene_mf_ultralight_unlock_auto_on_event(void* context, SceneManagerEvent event) { @@ -58,7 +58,6 @@ 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 d6cb48047..92ad7b56e 100644 --- a/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c +++ b/applications/main/nfc/scenes/nfc_scene_nfc_data_info.c @@ -7,17 +7,6 @@ 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; @@ -26,7 +15,7 @@ void nfc_scene_nfc_data_info_on_enter(void* context) { NfcProtocol protocol = dev_data->protocol; uint8_t text_scroll_height = 0; if((protocol == NfcDeviceProtocolMifareDesfire) || (protocol == NfcDeviceProtocolMifareUl) || - (protocol == NfcDeviceProtocolNfcV) || (protocol == NfcDeviceProtocolMifareClassic)) { + (protocol == NfcDeviceProtocolMifareClassic)) { widget_add_button_element( widget, GuiButtonTypeRight, "More", nfc_scene_nfc_data_info_widget_callback, nfc); text_scroll_height = 52; @@ -44,8 +33,6 @@ 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)); @@ -54,156 +41,19 @@ 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 - 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); + 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); // Set application specific data if(protocol == NfcDeviceProtocolMifareDesfire) { @@ -287,9 +137,6 @@ 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; } else if(protocol == NfcDeviceProtocolMifareClassic) { scene_manager_next_scene(nfc->scene_manager, NfcSceneMfClassicData); 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 deleted file mode 100644 index cc53c4dcb..000000000 --- a/applications/main/nfc/scenes/nfc_scene_nfcv_key_input.c +++ /dev/null @@ -1,48 +0,0 @@ -#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 deleted file mode 100644 index b30495a05..000000000 --- a/applications/main/nfc/scenes/nfc_scene_nfcv_menu.c +++ /dev/null @@ -1,63 +0,0 @@ -#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 deleted file mode 100644 index b52cc0caa..000000000 --- a/applications/main/nfc/scenes/nfc_scene_nfcv_unlock.c +++ /dev/null @@ -1,155 +0,0 @@ -#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 deleted file mode 100644 index 9c4c81fbd..000000000 --- a/applications/main/nfc/scenes/nfc_scene_nfcv_unlock_menu.c +++ /dev/null @@ -1,60 +0,0 @@ -#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 deleted file mode 100644 index 7bb13e1a1..000000000 --- a/applications/main/nfc/scenes/nfc_scene_passport_auth.c +++ /dev/null @@ -1,194 +0,0 @@ -#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 deleted file mode 100644 index 65fee0bcf..000000000 --- a/applications/main/nfc/scenes/nfc_scene_passport_auth_save_name.c +++ /dev/null @@ -1,82 +0,0 @@ -#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 deleted file mode 100644 index 4594721df..000000000 --- a/applications/main/nfc/scenes/nfc_scene_passport_date.c +++ /dev/null @@ -1,125 +0,0 @@ -#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 deleted file mode 100644 index 109415759..000000000 --- a/applications/main/nfc/scenes/nfc_scene_passport_docnr.c +++ /dev/null @@ -1,67 +0,0 @@ -#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 deleted file mode 100644 index 27febcb18..000000000 --- a/applications/main/nfc/scenes/nfc_scene_passport_menu.c +++ /dev/null @@ -1,57 +0,0 @@ -#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 deleted file mode 100644 index c6d7d7f6c..000000000 --- a/applications/main/nfc/scenes/nfc_scene_passport_pace_todo.c +++ /dev/null @@ -1,40 +0,0 @@ -#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 deleted file mode 100644 index 74f173b52..000000000 --- a/applications/main/nfc/scenes/nfc_scene_passport_read.c +++ /dev/null @@ -1,90 +0,0 @@ -#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 deleted file mode 100644 index 31a9e8ce1..000000000 --- a/applications/main/nfc/scenes/nfc_scene_passport_read_auth.c +++ /dev/null @@ -1,142 +0,0 @@ -#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 7164a155f..4252883b2 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,11 +68,6 @@ 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 @@ -95,19 +90,6 @@ 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_rpc.c b/applications/main/nfc/scenes/nfc_scene_rpc.c index 6adacfda5..c7fd4995f 100644 --- a/applications/main/nfc/scenes/nfc_scene_rpc.c +++ b/applications/main/nfc/scenes/nfc_scene_rpc.c @@ -56,13 +56,6 @@ 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_success.c b/applications/main/nfc/scenes/nfc_scene_save_success.c index c5d8a6872..d3e31fdc3 100644 --- a/applications/main/nfc/scenes/nfc_scene_save_success.c +++ b/applications/main/nfc/scenes/nfc_scene_save_success.c @@ -32,12 +32,6 @@ 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 dddaa47b3..e52493f2a 100644 --- a/applications/main/nfc/scenes/nfc_scene_saved_menu.c +++ b/applications/main/nfc/scenes/nfc_scene_saved_menu.c @@ -117,8 +117,6 @@ 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/scenes/nfc_scene_set_atqa.c b/applications/main/nfc/scenes/nfc_scene_set_atqa.c index f2100aa19..d079b3804 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_atqa.c +++ b/applications/main/nfc/scenes/nfc_scene_set_atqa.c @@ -11,7 +11,7 @@ void nfc_scene_set_atqa_on_enter(void* context) { // Setup view ByteInput* byte_input = nfc->byte_input; - byte_input_set_header_text(byte_input, "Enter atqa in hex"); + byte_input_set_header_text(byte_input, "Enter ATQA in hex"); byte_input_set_result_callback( byte_input, nfc_scene_set_atqa_byte_input_callback, diff --git a/applications/main/nfc/scenes/nfc_scene_set_sak.c b/applications/main/nfc/scenes/nfc_scene_set_sak.c index 3c88f3504..60a1e1494 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_sak.c +++ b/applications/main/nfc/scenes/nfc_scene_set_sak.c @@ -28,7 +28,7 @@ bool nfc_scene_set_sak_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == NfcCustomEventByteInputDone) { - scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqua); + scene_manager_next_scene(nfc->scene_manager, NfcSceneSetAtqa); consumed = true; } } diff --git a/applications/main/nfc/scenes/nfc_scene_set_uid.c b/applications/main/nfc/scenes/nfc_scene_set_uid.c index 5f0f52f6e..54606b68e 100644 --- a/applications/main/nfc/scenes/nfc_scene_set_uid.c +++ b/applications/main/nfc/scenes/nfc_scene_set_uid.c @@ -11,7 +11,7 @@ void nfc_scene_set_uid_on_enter(void* context) { // Setup view ByteInput* byte_input = nfc->byte_input; - byte_input_set_header_text(byte_input, "Enter uid in hex"); + byte_input_set_header_text(byte_input, "Enter UID in hex"); nfc->dev_edit_data = nfc->dev->dev_data.nfc_data; byte_input_set_result_callback( byte_input, diff --git a/applications/main/nfc/scenes/nfc_scene_start.c b/applications/main/nfc/scenes/nfc_scene_start.c index 67f25e5a7..a01f871ab 100644 --- a/applications/main/nfc/scenes/nfc_scene_start.c +++ b/applications/main/nfc/scenes/nfc_scene_start.c @@ -30,14 +30,10 @@ void nfc_scene_start_on_enter(void* context) { submenu_add_item( submenu, "Add Manually", SubmenuIndexAddManually, nfc_scene_start_submenu_callback, nfc); - submenu_add_lockable_item( - submenu, - "Debug", - SubmenuIndexDebug, - nfc_scene_start_submenu_callback, - nfc, - !furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug), - "Enable\nDebug!"); + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + submenu_add_item( + submenu, "Debug", SubmenuIndexDebug, nfc_scene_start_submenu_callback, nfc); + } submenu_set_selected_item( submenu, scene_manager_get_scene_state(nfc->scene_manager, NfcSceneStart)); @@ -52,11 +48,14 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == SubmenuIndexRead) { + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexRead); nfc->dev->dev_data.read_mode = NfcReadModeAuto; scene_manager_next_scene(nfc->scene_manager, NfcSceneRead); DOLPHIN_DEED(DolphinDeedNfcRead); consumed = true; } else if(event.event == SubmenuIndexDetectReader) { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneStart, SubmenuIndexDetectReader); bool sd_exist = storage_sd_status(nfc->dev->storage) == FSE_OK; if(sd_exist) { nfc_device_data_clear(&nfc->dev->dev_data); @@ -67,19 +66,27 @@ bool nfc_scene_start_on_event(void* context, SceneManagerEvent event) { } consumed = true; } else if(event.event == SubmenuIndexSaved) { + // Save the scene state explicitly in each branch, so that + // if the user cancels loading a file, the Saved menu item + // is properly reselected. + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexSaved); scene_manager_next_scene(nfc->scene_manager, NfcSceneFileSelect); consumed = true; } else if(event.event == SubmenuIndexExtraAction) { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneStart, SubmenuIndexExtraAction); scene_manager_next_scene(nfc->scene_manager, NfcSceneExtraActions); consumed = true; } else if(event.event == SubmenuIndexAddManually) { + scene_manager_set_scene_state( + nfc->scene_manager, NfcSceneStart, SubmenuIndexAddManually); scene_manager_next_scene(nfc->scene_manager, NfcSceneSetType); consumed = true; } else if(event.event == SubmenuIndexDebug) { + scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, SubmenuIndexDebug); scene_manager_next_scene(nfc->scene_manager, NfcSceneDebug); consumed = true; } - scene_manager_set_scene_state(nfc->scene_manager, NfcSceneStart, event.event); } return consumed; } diff --git a/lib/nfc/helpers/iso7816.c b/lib/nfc/helpers/iso7816.c deleted file mode 100644 index 03e695e4b..000000000 --- a/lib/nfc/helpers/iso7816.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "iso7816.h" - -// ISO7816-5 -// Simple-TLV (§5.2.1) -// BER-TLV (§5.2.2) -TlvInfo iso7816_tlv_parse(const uint8_t* data) { - TlvInfo tlv; - - // Simple-TLV: tag can be any value from 1 to 254 (not '00' or 'FF') - // BER-TLV: TODO describe - // 00000 - 11110 => 0 - 30 (single byte) - // 11111 00011111 - 11111 01111111 => 31 - 127 (2 byte) - // 11111 10000001 00000001 - 11111 11111111 01111111 => 128 - 16383 (3 byte) - - tlv.tag = *(data++); - tlv.ber.constructed = ((tlv.tag & 0x20) != 0); - tlv.ber.classVar = (tlv.tag >> 6) & 0x03; - if((tlv.tag & 0x1f) == 0x1f) { - // BER-TLV, multi byte tag - tlv.tag <<= 8; - tlv.tag |= *(data++); - tlv.ber.tag = tlv.tag & 0x7f; - if(tlv.tag & 0x80) { - // BER-TLV, 3 byte tag - tlv.tag &= ~0x80; - tlv.tag <<= 7; - tlv.tag |= *(data++) & 0x7f; - tlv.ber.tag = tlv.tag & 0x3fff; - } - } else { - tlv.ber.tag = tlv.tag & 0x1f; - } - - //TODO: check for invalid 'indefinite length' - tlv.length = *(data++); - if(tlv.length == 0xff) { - // Simple-TLV 2 byte length - tlv.length = *(data++) << 8; - tlv.length += *(data++); - } else if(tlv.length > 0x7f) { - uint8_t length_bytes = tlv.length & 0x7f; - //printf("BER length of %d bytes\n", length_bytes); - if(length_bytes < 1 || length_bytes > 4) { - //TODO: error: ISO7816 doesn't support more than 4 length bytes - return (TlvInfo){.tag = 0}; - } - tlv.length = 0; - for(uint8_t i = 0; i < length_bytes; ++i) { - //printf("byte %d: %02x\n", i, *data); - tlv.length <<= 8; - tlv.length |= *(data++); - } - } - tlv.value = data; - tlv.next = data + tlv.length; - - return tlv; -} - -TlvInfo - iso7816_tlv_select(const uint8_t* data, size_t length, const uint16_t tags[], size_t num_tags) { - TlvInfo tlv; - size_t offset = 0; - - if(num_tags == 0) { - return (TlvInfo){.tag = 0x0000}; - } - - while(offset < length) { - tlv = iso7816_tlv_parse(data + offset); - - if(tlv.tag == tags[0]) { - if(num_tags == 1) { - return tlv; - } else { - return iso7816_tlv_select(tlv.value, tlv.length, tags + 1, num_tags - 1); - } - } - - offset = - tlv.next - data; // TODO: use some length value of TlvInfo instead of this monstrosity - } - - return (TlvInfo){.tag = 0x0000}; -} diff --git a/lib/nfc/helpers/iso7816.h b/lib/nfc/helpers/iso7816.h deleted file mode 100644 index ae3c85871..000000000 --- a/lib/nfc/helpers/iso7816.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#define BER_CLASS_UNIVERSAL 0x0 -#define BER_CLASS_APPLICATION 0x1 -#define BER_CLASS_CONTEXT 0x2 -#define BER_CLASS_PRIVATE 0x3 - -typedef struct { - uint16_t tag; // TODO: use define/typedef for this data format? - struct { - uint16_t tag; - uint8_t constructed : 1; - uint8_t classVar : 2; - } ber; - size_t length; - const uint8_t* value; - - const uint8_t* next; -} TlvInfo; - -// ISO7816-5 §5.2 -// Simple-TLV and BER-TLV parsing -TlvInfo iso7816_tlv_parse(const uint8_t* data); - -TlvInfo - iso7816_tlv_select(const uint8_t* data, size_t length, const uint16_t tags[], size_t num_tags); diff --git a/lib/nfc/helpers/mrtd_helpers.c b/lib/nfc/helpers/mrtd_helpers.c deleted file mode 100644 index 26eda51ef..000000000 --- a/lib/nfc/helpers/mrtd_helpers.c +++ /dev/null @@ -1,658 +0,0 @@ -#include "mrtd_helpers.h" -#include "../helpers/iso7816.h" - -#include //TODO: remove -#include - -#include -#include - -static inline unsigned char* ucstr(const char* str) { - return (unsigned char*)str; -} - -const char* mrtd_auth_method_string(MrtdAuthMethod method) { - switch(method) { - case MrtdAuthMethodBac: - return "BAC"; - case MrtdAuthMethodPace: - return "PACE"; - case MrtdAuthMethodNone: - return "None"; - case MrtdAuthMethodAny: - return "Any"; - default: - return "Unknown"; - } -} - -bool mrtd_auth_method_parse_string(MrtdAuthMethod* method, const char* str) { - if(!strcmp(str, "BAC")) { - *method = MrtdAuthMethodBac; - return true; - } - if(!strcmp(str, "PACE")) { - *method = MrtdAuthMethodPace; - return true; - } - if(!strcmp(str, "None")) { - *method = MrtdAuthMethodNone; - return true; - } - if(!strcmp(str, "Any")) { - *method = MrtdAuthMethodAny; - return true; - } - return false; -} - -uint8_t mrtd_bac_check_digit(const char* input, const uint8_t length) { - const uint8_t num_weights = 3; - uint8_t weights[] = {7, 3, 1}; - uint8_t check_digit = 0; - uint8_t idx; - - for(uint8_t i = 0; i < length; ++i) { - char c = input[i]; - if(c >= 'A' && c <= 'Z') { - idx = c - 'A' + 10; - } else if(c >= 'a' && c <= 'z') { - idx = c - 'a' + 10; - } else if(c >= '0' && c <= '9') { - idx = c - '0'; - } else { - idx = 0; - } - check_digit = (check_digit + idx * weights[i % num_weights]) % 10; - } - return check_digit; -} - -void mrtd_print_date(char* output, MrtdDate* date) { - output[0] = (date->year / 10) + '0'; - output[1] = (date->year % 10) + '0'; - output[2] = (date->month / 10) + '0'; - output[3] = (date->month % 10) + '0'; - output[4] = (date->day / 10) + '0'; - output[5] = (date->day % 10) + '0'; -} - -uint8_t charval(char c) { - if(c >= '0' && c <= '9') { - return c - '0'; - } - return 0; -} - -void mrtd_parse_date(MrtdDate* date, const unsigned char* input) { - date->year = charval(input[0]) * 10 + charval(input[1]); - date->month = charval(input[2]) * 10 + charval(input[3]); - date->day = charval(input[4]) * 10 + charval(input[5]); -} - -bool mrtd_bac_get_kmrz(MrtdAuthData* auth, char* output, uint8_t output_size) { - uint8_t idx = 0; - uint8_t docnr_length = strlen(auth->doc_number); - uint8_t cd_idx = 0; - if(output_size < docnr_length + 16) { - return false; - } - - cd_idx = idx; - for(uint8_t i = 0; i < docnr_length; ++i) { - char c = auth->doc_number[i]; - if(c >= 'a' && c <= 'z') { - c = c - 'a' + 'A'; - } - output[idx++] = c; - } - - if(docnr_length < 9) { - memset(output + idx, '<', 9 - docnr_length); - idx += 9 - docnr_length; - } - - output[idx++] = mrtd_bac_check_digit(output + cd_idx, docnr_length) + '0'; - - cd_idx = idx; - mrtd_print_date(output + idx, &auth->birth_date); - idx += 6; - output[idx++] = mrtd_bac_check_digit(output + cd_idx, 6) + '0'; - - cd_idx = idx; - mrtd_print_date(output + idx, &auth->expiry_date); - idx += 6; - output[idx++] = mrtd_bac_check_digit(output + cd_idx, 6) + '0'; - - output[idx++] = '\x00'; - return true; -} - -bool mrtd_bac_keys_from_seed(const uint8_t kseed[16], uint8_t ksenc[16], uint8_t ksmac[16]) { - uint8_t hash[20]; - mbedtls_sha1_context ctx; - mbedtls_sha1_init(&ctx); - - do { - for(uint8_t i = 1; i <= 2; ++i) { - if(mbedtls_sha1_starts(&ctx)) break; - if(mbedtls_sha1_update(&ctx, kseed, 16)) break; - if(mbedtls_sha1_update(&ctx, ucstr("\x00\x00\x00"), 3)) break; - if(mbedtls_sha1_update(&ctx, &i, 1)) break; - if(mbedtls_sha1_finish(&ctx, hash)) break; - - switch(i) { - case 1: - memcpy(ksenc, hash, 16); - mbedtls_des_key_set_parity(ksenc); - mbedtls_des_key_set_parity(ksenc + 8); - break; - case 2: - memcpy(ksmac, hash, 16); - mbedtls_des_key_set_parity(ksmac); - mbedtls_des_key_set_parity(ksmac + 8); - break; - } - } - } while(false); - - mbedtls_sha1_free(&ctx); - return true; -} - -bool mrtd_bac_keys(MrtdAuthData* auth, uint8_t ksenc[16], uint8_t ksmac[16]) { - uint8_t kmrz_max_length = MRTD_DOCNR_MAX_LENGTH + 16; - char kmrz[kmrz_max_length]; - if(!mrtd_bac_get_kmrz(auth, kmrz, kmrz_max_length)) { - return false; - } - - printf("kmrz: %s\r\n", kmrz); //TODO: remove - - uint8_t hash[20]; - mbedtls_sha1((uint8_t*)kmrz, strlen(kmrz), hash); - - if(!mrtd_bac_keys_from_seed(hash, ksenc, ksmac)) { - return false; - } - - return true; -} - -//NOTE: output size will be ((data_length+8)/8)*8 -bool mrtd_bac_encrypt(const uint8_t* data, size_t data_length, const uint8_t* key, uint8_t* output) { - uint8_t IV[8] = "\x00\x00\x00\x00\x00\x00\x00\x00"; - - mbedtls_des3_context ctx; - mbedtls_des3_init(&ctx); - mbedtls_des3_set2key_enc(&ctx, key); - if(mbedtls_des3_crypt_cbc(&ctx, MBEDTLS_DES_ENCRYPT, data_length, IV, data, output)) { - return false; - } - mbedtls_des3_free(&ctx); - - return true; -} - -bool mrtd_bac_decrypt(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output) { - uint8_t IV[8] = "\x00\x00\x00\x00\x00\x00\x00\x00"; - - mbedtls_des3_context ctx; - mbedtls_des3_init(&ctx); - mbedtls_des3_set2key_dec(&ctx, key); - if(mbedtls_des3_crypt_cbc(&ctx, MBEDTLS_DES_DECRYPT, data_length, IV, data, output)) { - return false; - } - mbedtls_des3_free(&ctx); - - return true; -} - -bool mrtd_bac_decrypt_verify( - const uint8_t* data, - size_t data_length, - uint8_t* key_enc, - uint8_t* key_mac, - uint8_t* output) { - mrtd_bac_decrypt(data, data_length - 8, key_enc, output); - - uint8_t mac_calc[8]; - mrtd_bac_padded_mac(data, data_length - 8, key_mac, mac_calc); - - if(memcmp(mac_calc, data + data_length - 8, 8)) { - printf("MAC failed\r\n"); - for(uint8_t i = 0; i < 8; ++i) { - printf("%02X <=> %02X\r\n", mac_calc[i], data[data_length - 8 + i]); - } - return false; - } - return true; -} - -// If output or output_written are NULL-pointers, no output is written -// Otherwise, and if DO'87 is present, data is written to *output -// output should have enough room for additional padding (rounded up by 8 bytes) -// output_written will be the length without padding -uint16_t mrtd_bac_decrypt_verify_sm( - const uint8_t* data, - size_t data_length, - uint8_t* key_enc, - uint8_t* key_mac, - uint64_t ssc, - uint8_t* output, - size_t* output_written) { - // Message: [DO'85 or DO'87] || [DO'99] || DO'8E - // Lengths: Var 1+1+2=4 1+1+8=10 - - //TODO: check for DO'99 presence, instead of assuming - uint16_t ret_code = data[data_length - 10 - 2] << 8 | data[data_length - 10 - 1]; - //ntohs(data + data_length - 10 - 2); - - TlvInfo do87 = iso7816_tlv_select(data, data_length, (uint16_t[]){0x87}, 1); - //printf("DO87.Tag: %X\n", do87.tag); - //printf("DO87.Length: %ld\n", do87.length); - //printf("DO87.Value: "); - //for(uint8_t i=1; i= 0; --padidx) { - if(output[padidx] == 0x00) { - continue; - } else if(output[padidx] == 0x80) { - break; - } else { - printf("Invalid padding\r\n"); - return 0xff01; - } - } - printf(" "); - for(int i = 0; i < padidx; ++i) { - printf(" "); - } - printf("^^\r\n"); - printf("Pad starts at: %d\r\n", padidx); - - *output_written = padidx - 1; - } - } else { - if(output_written != NULL) { - *output_written = 0; - } - } - - mrtd_bac_mac_ctx ctx; - mrtd_bac_mac_init(&ctx, key_mac); - uint64_t ssc_n = htonll(ssc); - mrtd_bac_mac_update(&ctx, (uint8_t*)&ssc_n, 8); - mrtd_bac_mac_update( - &ctx, data, data_length - 10); // 10 = len(DO'8E) = len(header + length + MAC) = 1 + 1 + 8 - uint8_t mac_calc[8]; - mrtd_bac_mac_finalize(&ctx, mac_calc); - - if(memcmp(mac_calc, data + data_length - 8, 8)) { - printf("SM MAC failed\r\n"); - for(uint8_t i = 0; i < 8; ++i) { - printf("%02X <=> %02X\r\n", mac_calc[i], data[data_length - 8 + i]); - } - return 0xff02; - } - return ret_code; -} - -bool mrtd_bac_mac_init(mrtd_bac_mac_ctx* ctx, const uint8_t key[16]) { - mbedtls_des_init(&ctx->des); - mbedtls_des_setkey_enc(&ctx->des, key); - memset(ctx->mac, 0, 8); - ctx->idx_in = 0; - memcpy(ctx->key, key, 16); - return true; -} - -bool mrtd_bac_mac_update(mrtd_bac_mac_ctx* ctx, const uint8_t* data, size_t data_length) { - //printf("MAC add %d: ", data_length); print_hex(data, data_length); printf("\n"); - size_t data_idx = 0; - //uint8_t* xormac = ctx->xormac; - - if(ctx->idx_in != 0) { - uint8_t buff_add = 8 - ctx->idx_in; - if(data_length < buff_add) { - buff_add = data_length; - } - memcpy(ctx->buffer_in + ctx->idx_in, data, buff_add); - ctx->idx_in = (ctx->idx_in + buff_add) % 8; - data_idx += buff_add; - - if(ctx->idx_in == 0) { // buffer_in filled - for(uint8_t j = 0; j < 8; ++j) { - ctx->xormac[j] = ctx->mac[j] ^ ctx->buffer_in[j]; - } - mbedtls_des_crypt_ecb(&ctx->des, ctx->xormac, ctx->mac); - - printf( - "DES buf: %02X %02X %02X %02X %02X %02X %02X %02X\r\n", - ctx->buffer_in[0], - ctx->buffer_in[1], - ctx->buffer_in[2], - ctx->buffer_in[3], - ctx->buffer_in[4], - ctx->buffer_in[5], - ctx->buffer_in[6], - ctx->buffer_in[7]); - - //printf("DES1: %02X %02X %02X %02X %02X %02X %02X %02X\n", - //xormac[0], xormac[1], xormac[2], xormac[3], - //xormac[4], xormac[5], xormac[6], xormac[7]); - } - } - - while(true) { - if(data_idx + 8 > data_length) { - // Not a full block - break; - } - for(uint8_t j = 0; j < 8; ++j) { - ctx->xormac[j] = ctx->mac[j] ^ data[data_idx++]; - } - - mbedtls_des_crypt_ecb(&ctx->des, ctx->xormac, ctx->mac); - printf( - "DES add: %02X %02X %02X %02X %02X %02X %02X %02X\r\n", - data[data_idx - 8 + 0], - data[data_idx - 8 + 1], - data[data_idx - 8 + 2], - data[data_idx - 8 + 3], - data[data_idx - 8 + 4], - data[data_idx - 8 + 5], - data[data_idx - 8 + 6], - data[data_idx - 8 + 7]); - - //printf("DES1: %02X %02X %02X %02X %02X %02X %02X %02X\n", - //xormac[0], xormac[1], xormac[2], xormac[3], - //xormac[4], xormac[5], xormac[6], xormac[7]); - } - - if(data_idx < data_length) { - ctx->idx_in = data_length - data_idx; - memcpy(ctx->buffer_in, data + data_idx, ctx->idx_in); - } - - return true; -} - -bool mrtd_bac_mac_pad(mrtd_bac_mac_ctx* ctx) { - memset(ctx->buffer_in + ctx->idx_in, 0x00, 8 - ctx->idx_in); - ctx->buffer_in[ctx->idx_in] = 0x80; - ctx->idx_in = 8; - - mrtd_bac_mac_update(ctx, NULL, 0); // Force processing the buffer_in - return true; -} - -bool mrtd_bac_mac_finalize(mrtd_bac_mac_ctx* ctx, uint8_t output[8]) { - mrtd_bac_mac_pad(ctx); - - uint8_t tmp[8]; - mbedtls_des_init(&ctx->des); - mbedtls_des_setkey_dec(&ctx->des, ctx->key + 8); - mbedtls_des_crypt_ecb(&ctx->des, ctx->mac, tmp); - - mbedtls_des_init(&ctx->des); - mbedtls_des_setkey_enc(&ctx->des, ctx->key); - mbedtls_des_crypt_ecb(&ctx->des, tmp, output); - - mbedtls_des_free(&ctx->des); - return true; -} - -bool mrtd_bac_mac(const uint8_t* data, size_t data_length, const uint8_t* key, uint8_t* output) { - // MAC - uint8_t mac[8]; - uint8_t xormac[8]; - uint8_t tmp[8]; - mbedtls_des_context ctx; - - mbedtls_des_init(&ctx); - mbedtls_des_setkey_enc(&ctx, key); - - memset(mac, 0, 8); - for(size_t i = 0; i < data_length / 8; ++i) { - for(uint8_t j = 0; j < 8; ++j) { - xormac[j] = mac[j] ^ data[i * 8 + j]; - } - - mbedtls_des_crypt_ecb(&ctx, xormac, mac); - printf( - "DES1: %02X %02X %02X %02X %02X %02X %02X %02X\r\n", - xormac[0], - xormac[1], - xormac[2], - xormac[3], - xormac[4], - xormac[5], - xormac[6], - xormac[7]); - } - - mbedtls_des_init(&ctx); - mbedtls_des_setkey_dec(&ctx, key + 8); - mbedtls_des_crypt_ecb(&ctx, mac, tmp); - - mbedtls_des_init(&ctx); - mbedtls_des_setkey_enc(&ctx, key); - mbedtls_des_crypt_ecb(&ctx, tmp, output); - - mbedtls_des_free(&ctx); - - return true; -} - -bool mrtd_bac_padded_mac(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output) { - //TODO: bufferless padding should be possible with 3DES - size_t newlength = ((data_length + 8) / 8) * 8; // TODO: return this value too? - uint8_t padded[newlength]; //TODO: input parameter - memset(padded, 0, newlength); - memcpy(padded, data, data_length); - padded[data_length] = 0x80; - - if(!mrtd_bac_mac(padded, newlength, key, output)) { - return false; - } - - return true; -} - -size_t mrtd_protect_apdu( - uint8_t cla, - uint8_t ins, - uint8_t p1, - uint8_t p2, - uint8_t lc, - const void* data, - int16_t le, - const uint8_t* key_enc, - const uint8_t* key_mac, - uint64_t ssc, - uint8_t* output) { - //TODO: max size on output? - size_t idx = 0; - - // CC = MAC( SSC || CmdHeader || DO'87 ) - mrtd_bac_mac_ctx mac_ctx; - mrtd_bac_mac_init(&mac_ctx, key_mac); - uint64_t ssc_n = htonll(ssc); - //printf("ssc: %016llx\r\n", ssc); - //printf("ssc_n: "); print_hex(ssc_n, 8); printf("\n"); - mrtd_bac_mac_update(&mac_ctx, (uint8_t*)&ssc_n, 8); - - // Mask cla - output[idx++] = cla | 0x0c; - output[idx++] = ins; - output[idx++] = p1; - output[idx++] = p2; - - // Pad Header - mrtd_bac_mac_update(&mac_ctx, output, idx); - mrtd_bac_mac_pad(&mac_ctx); - - size_t idx_lc = idx; - output[idx++] = 0xff; // place holder for Lc - - // Build DO'87 - // TODO: condition on data presence - // TODO: if ins is odd, use 0x85 - if(lc > 0) { - size_t newlength = ((lc + 8) / 8) * 8; - uint8_t padded[newlength]; - - output[idx++] = 0x87; // Header - output[idx++] = newlength + 1; // Length - output[idx++] = 0x01; //TODO: check this value - - memset(padded, 0, newlength); - memcpy(padded, data, lc); - padded[lc] = 0x80; - - mrtd_bac_encrypt(padded, newlength, key_enc, output + idx); - idx += newlength; - } - - // Build DO'97 - if(le >= 0) { - output[idx++] = 0x97; // Header - output[idx++] = 0x01; // Length - output[idx++] = le; - } - - mrtd_bac_mac_update(&mac_ctx, output + idx_lc + 1, idx - idx_lc - 1); - - // Build DO'8E - // TODO: conditions? - { - output[idx++] = 0x8E; // Header - output[idx++] = 0x08; // Length - - mrtd_bac_mac_finalize(&mac_ctx, output + idx); - idx += 8; - - printf("MAC: "); - for(uint8_t i = 0; i < 8; ++i) { - printf("%02X ", output[idx - 8 + i]); - } - printf("\r\n"); - } - - output[idx_lc] = idx - idx_lc - 1; // Set Lc - - output[idx++] = 0x00; - - return idx; -} - -EFFile EFNone = {.name = NULL, .file_id = 0x0000, .short_id = 0x00, .tag = 0x00}; - -const struct EFFormat EF = { - .ATR = {.name = "ATR", .file_id = 0x2F01, .short_id = 0x01}, - .DIR = {.name = "DIR", .file_id = 0x2F00, .short_id = 0x1E}, - .CardAccess = {.name = "CardAccess", .file_id = 0x011C, .short_id = 0x1C}, - .CardSecurity = {.name = "CardSecurity", .file_id = 0x011D, .short_id = 0x1D}, - .COM = {.name = "COM", .file_id = 0x011E, .short_id = 0x1E, .tag = 0x60}, - .SOD = {.name = "SOD", .file_id = 0X011D, .short_id = 0X1D, .tag = 0x77}, - .DG1 = {.name = "DG1", .file_id = 0X0101, .short_id = 0X01, .tag = 0x61}, - .DG2 = {.name = "DG2", .file_id = 0X0102, .short_id = 0X02, .tag = 0x75}, - .DG3 = {.name = "DG3", .file_id = 0X0103, .short_id = 0X03, .tag = 0x63}, - .DG4 = {.name = "DG4", .file_id = 0X0104, .short_id = 0X04, .tag = 0x76}, - .DG5 = {.name = "DG5", .file_id = 0X0105, .short_id = 0X05, .tag = 0x65}, - .DG6 = {.name = "DG6", .file_id = 0X0106, .short_id = 0X06, .tag = 0x66}, - .DG7 = {.name = "DG7", .file_id = 0X0107, .short_id = 0X07, .tag = 0x67}, - .DG8 = {.name = "DG8", .file_id = 0X0108, .short_id = 0X08, .tag = 0x68}, - .DG9 = {.name = "DG9", .file_id = 0X0109, .short_id = 0X09, .tag = 0x69}, - .DG10 = {.name = "DG10", .file_id = 0X010A, .short_id = 0X0A, .tag = 0x6a}, - .DG11 = {.name = "DG11", .file_id = 0X010B, .short_id = 0X0B, .tag = 0x6b}, - .DG12 = {.name = "DG12", .file_id = 0X010C, .short_id = 0X0C, .tag = 0x6c}, - .DG13 = {.name = "DG13", .file_id = 0X010D, .short_id = 0X0D, .tag = 0x6d}, - .DG14 = {.name = "DG14", .file_id = 0X010E, .short_id = 0X0E, .tag = 0x6e}, - .DG15 = {.name = "DG15", .file_id = 0X010F, .short_id = 0X0F, .tag = 0x6f}, - .DG16 = {.name = "DG16", .file_id = 0X0110, .short_id = 0X10, .tag = 0x70}, -}; - -struct AIDSet AID = { - .eMRTDApplication = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01}, - .TravelRecords = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x01}, - .VisaRecords = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x02}, - .AdditionalBiometrics = {0xA0, 0x00, 0x00, 0x02, 0x47, 0x20, 0x03}, -}; - -const EFFile* mrtd_tag_to_file(uint8_t tag) { - //TODO: generate this code with macros? - switch(tag) { - case 0x60: - return &EF.COM; - case 0x77: - return &EF.SOD; - case 0x61: - return &EF.DG1; - case 0x75: - return &EF.DG2; - case 0x63: - return &EF.DG3; - case 0x76: - return &EF.DG4; - case 0x65: - return &EF.DG5; - case 0x66: - return &EF.DG6; - case 0x67: - return &EF.DG7; - case 0x68: - return &EF.DG8; - case 0x69: - return &EF.DG9; - case 0x6a: - return &EF.DG10; - case 0x6b: - return &EF.DG11; - case 0x6c: - return &EF.DG12; - case 0x6d: - return &EF.DG13; - case 0x6e: - return &EF.DG14; - case 0x6f: - return &EF.DG15; - case 0x70: - return &EF.DG16; - default: - return &EFNone; - } -}; - -int tlv_number(TlvInfo tlv) { - //TODO: negative numbers? - const uint8_t* str = tlv.value; - size_t length = tlv.length; - - int value = 0; - while(length--) { - char c = *(str++); - - if(c >= '0' && c <= '9') { - value = value * 10 + (c - '0'); - } else { - //TODO: warning? return? crash? - } - } - return value; -} diff --git a/lib/nfc/helpers/mrtd_helpers.h b/lib/nfc/helpers/mrtd_helpers.h deleted file mode 100644 index 994e66974..000000000 --- a/lib/nfc/helpers/mrtd_helpers.h +++ /dev/null @@ -1,228 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#include - -#include "../helpers/iso7816.h" - -typedef struct { - uint8_t year; - uint8_t month; - uint8_t day; -} MrtdDate; - -// NULL terminated document ID -#define MRTD_DOCNR_MAX_LENGTH 21 - -typedef enum { - MrtdAuthMethodNone, - MrtdAuthMethodAny, - MrtdAuthMethodBac, - MrtdAuthMethodPace, -} MrtdAuthMethod; - -typedef enum { - MrtdTypeUnknown, - MrtdTypeTD1, - MrtdTypeTD2, - MrtdTypeTD3, -} MrtdType; - -typedef struct { - MrtdAuthMethod method; - - // BAC input fields - MrtdDate birth_date; - MrtdDate expiry_date; - char doc_number[MRTD_DOCNR_MAX_LENGTH]; - - //TODO: PACE -} MrtdAuthData; - -typedef struct { - mbedtls_des_context des; - uint8_t key[16]; - uint8_t mac[8]; - uint8_t xormac[8]; - - uint8_t buffer_in[8]; - uint8_t idx_in; -} mrtd_bac_mac_ctx; - -typedef struct { - const char* name; - const uint8_t short_id; - const uint16_t file_id; - const uint8_t tag; -} EFFile; - -struct EFFormat { - // Under Master File (MF) - const EFFile ATR; - const EFFile DIR; - const EFFile CardAccess; - const EFFile CardSecurity; - - // Under LDS1 eMRTD Application - const EFFile COM; - const EFFile SOD; - const EFFile DG1; - const EFFile DG2; - const EFFile DG3; - const EFFile DG4; - const EFFile DG5; - const EFFile DG6; - const EFFile DG7; - const EFFile DG8; - const EFFile DG9; - const EFFile DG10; - const EFFile DG11; - const EFFile DG12; - const EFFile DG13; - const EFFile DG14; - const EFFile DG15; - const EFFile DG16; -}; - -extern const struct EFFormat EF; - -typedef uint8_t AIDValue[7]; - -struct AIDSet { - AIDValue eMRTDApplication; - AIDValue TravelRecords; - AIDValue VisaRecords; - AIDValue AdditionalBiometrics; -}; - -extern struct AIDSet AID; - -#define MAX_EFDIR_APPS 4 - -typedef struct { - AIDValue applications[MAX_EFDIR_APPS]; - uint8_t applications_count; -} EF_DIR_contents; - -#define MAX_EFCOM_TAGS 18 - -typedef struct { - uint16_t lds_version; // xxyy => xx.yy (major.minor) - uint32_t unicode_version; // aabbcc => aa.bb.cc (major.minor.release) - uint8_t tag_list[MAX_EFCOM_TAGS]; -} EF_COM_contents; - -typedef struct { - MrtdType type; - // ICAO9303 max sizes + 1 for 0-byte - uint8_t doctype[3]; - uint8_t issuing_state[4]; - uint8_t name[40]; - MrtdDate birth_date; - uint8_t docnr[10]; - uint8_t nationality[4]; - uint8_t sex[2]; - MrtdDate expiry_date; -} EF_DG1_contents; - -typedef struct { - MrtdAuthData auth; - bool auth_success; - MrtdAuthMethod auth_method_used; - - struct { - EF_DIR_contents EF_DIR; - EF_COM_contents EF_COM; - EF_DG1_contents DG1; - } files; -} MrtdData; - -const char* mrtd_auth_method_string(MrtdAuthMethod method); - -bool mrtd_auth_method_parse_string(MrtdAuthMethod* method, const char* str); - -uint8_t mrtd_bac_check_digit(const char* input, const uint8_t length); - -//TODO: swap order, all other functions have output last -void mrtd_print_date(char* output, MrtdDate* date); - -void mrtd_parse_date(MrtdDate* date, const unsigned char* input); - -bool mrtd_bac_get_kmrz(MrtdAuthData* auth, char* output, uint8_t output_size); - -bool mrtd_bac_keys_from_seed(const uint8_t* kseed, uint8_t* ksenc, uint8_t* ksmac); - -bool mrtd_bac_keys(MrtdAuthData* auth, uint8_t ksenc[16], uint8_t ksmac[16]); - -bool mrtd_bac_encrypt(const uint8_t* data, size_t data_length, const uint8_t* key, uint8_t* output); - -bool mrtd_bac_mac(const uint8_t* data, size_t data_length, const uint8_t* key, uint8_t* output); - -bool mrtd_bac_mac_init(mrtd_bac_mac_ctx* ctx, const uint8_t key[16]); - -bool mrtd_bac_mac_update(mrtd_bac_mac_ctx* ctx, const uint8_t* data, size_t data_length); - -bool mrtd_bac_mac_finalize(mrtd_bac_mac_ctx* ctx, uint8_t output[8]); - -bool mrtd_bac_mac_pad(mrtd_bac_mac_ctx* ctx); // TODO: internal only, remove from .h? - -bool mrtd_bac_padded_mac(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output); - -bool mrtd_bac_decrypt(const uint8_t* data, size_t data_length, uint8_t* key, uint8_t* output); - -bool mrtd_bac_decrypt_verify( - const uint8_t* data, - size_t data_length, - uint8_t* key_enc, - uint8_t* key_mac, - uint8_t* output); - -//TODO: add some consts -uint16_t mrtd_bac_decrypt_verify_sm( - const uint8_t* data, - size_t data_length, - uint8_t* key_enc, - uint8_t* key_mac, - uint64_t ssc, - uint8_t* output, - size_t* output_written); - -#include -#define htonll(x) ((((uint64_t)__htonl(x)) << 32) + __htonl((x) >> 32)) - -static __inline uint64_t mrtd_ssc_from_data(const uint8_t* rnd_ic, const uint8_t* rnd_ifd) { -#if _BYTE_ORDER == _LITTLE_ENDIAN - return (((uint64_t)rnd_ic[4] << 56) & 0xff00000000000000) | - (((uint64_t)rnd_ic[5] << 48) & 0x00ff000000000000) | - (((uint64_t)rnd_ic[6] << 40) & 0x0000ff0000000000) | - (((uint64_t)rnd_ic[7] << 32) & 0x000000ff00000000) | - (((uint64_t)rnd_ifd[4] << 24) & 0x00000000ff000000) | - (((uint64_t)rnd_ifd[5] << 16) & 0x0000000000ff0000) | - (((uint64_t)rnd_ifd[6] << 8) & 0x000000000000ff00) | - (((uint64_t)rnd_ifd[7]) & 0x00000000000000ff); -#else -#error Using untested code, please verify first! - return (*((uint64_t*)(rnd_ic + 4)) & 0xffffffff) + (*((uint64_t*)(rnd_ifd + 4)) * 0x100000000); -#endif -} - -size_t mrtd_protect_apdu( - uint8_t cla, - uint8_t ins, - uint8_t p1, - uint8_t p2, - uint8_t lc, - const void* data, - int16_t le, - const uint8_t* key_enc, - const uint8_t* key_mac, - uint64_t ssc, - uint8_t* output); - -int tlv_number(TlvInfo tlv); - -const EFFile* mrtd_tag_to_file(uint8_t tag); diff --git a/lib/nfc/nfc_device.c b/lib/nfc/nfc_device.c index df7688ed1..3c9cf408a 100644 --- a/lib/nfc/nfc_device.c +++ b/lib/nfc/nfc_device.c @@ -58,8 +58,6 @@ static void nfc_device_prepare_format_string(NfcDevice* dev, FuriString* format_ furi_string_set(format_string, "Mifare Classic"); } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { furi_string_set(format_string, "Mifare DESFire"); - } else if(dev->format == NfcDeviceSaveFormatNfcV) { - furi_string_set(format_string, "ISO15693"); } else { furi_string_set(format_string, "Unknown"); } @@ -95,11 +93,6 @@ static bool nfc_device_parse_format_string(NfcDevice* dev, FuriString* format_st dev->dev_data.protocol = NfcDeviceProtocolMifareDesfire; return true; } - if(furi_string_start_with_str(format_string, "ISO15693")) { - dev->format = NfcDeviceSaveFormatNfcV; - dev->dev_data.protocol = NfcDeviceProtocolNfcV; - return true; - } return false; } @@ -657,281 +650,6 @@ bool nfc_device_load_mifare_df_data(FlipperFormat* file, NfcDevice* dev) { return parsed; } -static bool nfc_device_save_slix_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - - do { - if(!flipper_format_write_comment_cstr(file, "SLIX specific data")) break; - if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - saved = true; - } while(false); - - return saved; -} - -bool nfc_device_load_slix_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - memset(data, 0, sizeof(NfcVData)); - - do { - if(!flipper_format_read_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - - parsed = true; - } while(false); - - return parsed; -} - -static bool nfc_device_save_slix_s_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - - do { - if(!flipper_format_write_comment_cstr(file, "SLIX-S specific data")) break; - if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) - break; - if(!flipper_format_write_hex( - file, "Password Write", data->key_write, sizeof(data->key_write))) - break; - if(!flipper_format_write_hex( - file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) - break; - if(!flipper_format_write_hex( - file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) - break; - if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break; - saved = true; - } while(false); - - return saved; -} - -bool nfc_device_load_slix_s_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - memset(data, 0, sizeof(NfcVData)); - - do { - if(!flipper_format_read_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) - break; - if(!flipper_format_read_hex( - file, "Password Write", data->key_write, sizeof(data->key_write))) - break; - if(!flipper_format_read_hex( - file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) - break; - if(!flipper_format_read_hex( - file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) - break; - if(!flipper_format_read_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break; - - parsed = true; - } while(false); - - return parsed; -} - -static bool nfc_device_save_slix_l_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - - do { - if(!flipper_format_write_comment_cstr(file, "SLIX-L specific data")) break; - if(!flipper_format_write_hex( - file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) - break; - if(!flipper_format_write_hex( - file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) - break; - if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break; - saved = true; - } while(false); - - return saved; -} - -bool nfc_device_load_slix_l_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - memset(data, 0, sizeof(NfcVData)); - - do { - if(!flipper_format_read_hex( - file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) - break; - if(!flipper_format_read_hex( - file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) - break; - if(!flipper_format_read_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break; - - parsed = true; - } while(false); - - return parsed; -} - -static bool nfc_device_save_slix2_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - - do { - if(!flipper_format_write_comment_cstr(file, "SLIX2 specific data")) break; - if(!flipper_format_write_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) - break; - if(!flipper_format_write_hex( - file, "Password Write", data->key_write, sizeof(data->key_write))) - break; - if(!flipper_format_write_hex( - file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) - break; - if(!flipper_format_write_hex( - file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) - break; - if(!flipper_format_write_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - if(!flipper_format_write_bool(file, "Privacy Mode", &data->privacy, 1)) break; - saved = true; - } while(false); - - return saved; -} - -bool nfc_device_load_slix2_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVSlixData* data = &dev->dev_data.nfcv_data.sub_data.slix; - memset(data, 0, sizeof(NfcVData)); - - do { - if(!flipper_format_read_hex(file, "Password Read", data->key_read, sizeof(data->key_read))) - break; - if(!flipper_format_read_hex( - file, "Password Write", data->key_write, sizeof(data->key_write))) - break; - if(!flipper_format_read_hex( - file, "Password Privacy", data->key_privacy, sizeof(data->key_privacy))) - break; - if(!flipper_format_read_hex( - file, "Password Destroy", data->key_destroy, sizeof(data->key_destroy))) - break; - if(!flipper_format_read_hex(file, "Password EAS", data->key_eas, sizeof(data->key_eas))) - break; - if(!flipper_format_read_bool(file, "Privacy Mode", &data->privacy, 1)) break; - - parsed = true; - } while(false); - - return parsed; -} - -static bool nfc_device_save_nfcv_data(FlipperFormat* file, NfcDevice* dev) { - bool saved = false; - NfcVData* data = &dev->dev_data.nfcv_data; - - do { - uint32_t temp_uint32 = 0; - uint8_t temp_uint8 = 0; - - if(!flipper_format_write_comment_cstr(file, "Data Storage Format Identifier")) break; - if(!flipper_format_write_hex(file, "DSFID", &(data->dsfid), 1)) break; - if(!flipper_format_write_comment_cstr(file, "Application Family Identifier")) break; - if(!flipper_format_write_hex(file, "AFI", &(data->afi), 1)) break; - if(!flipper_format_write_hex(file, "IC Reference", &(data->ic_ref), 1)) break; - temp_uint32 = data->block_num; - if(!flipper_format_write_comment_cstr(file, "Number of memory blocks, usually 0 to 256")) - break; - if(!flipper_format_write_uint32(file, "Block Count", &temp_uint32, 1)) break; - if(!flipper_format_write_comment_cstr(file, "Size of a single memory block, usually 4")) - break; - if(!flipper_format_write_hex(file, "Block Size", &(data->block_size), 1)) break; - if(!flipper_format_write_hex( - file, "Data Content", data->data, data->block_num * data->block_size)) - break; - if(!flipper_format_write_comment_cstr( - file, - "Subtype of this card (0 = ISO15693, 1 = SLIX, 2 = SLIX-S, 3 = SLIX-L, 4 = SLIX2)")) - break; - temp_uint8 = (uint8_t)data->sub_type; - if(!flipper_format_write_hex(file, "Subtype", &temp_uint8, 1)) break; - - switch(data->sub_type) { - case NfcVTypePlain: - if(!flipper_format_write_comment_cstr(file, "End of ISO15693 parameters")) break; - saved = true; - break; - case NfcVTypeSlix: - saved = nfc_device_save_slix_data(file, dev); - break; - case NfcVTypeSlixS: - saved = nfc_device_save_slix_s_data(file, dev); - break; - case NfcVTypeSlixL: - saved = nfc_device_save_slix_l_data(file, dev); - break; - case NfcVTypeSlix2: - saved = nfc_device_save_slix2_data(file, dev); - break; - } - } while(false); - - return saved; -} - -bool nfc_device_load_nfcv_data(FlipperFormat* file, NfcDevice* dev) { - bool parsed = false; - NfcVData* data = &dev->dev_data.nfcv_data; - - memset(data, 0, sizeof(NfcVData)); - - do { - uint32_t temp_uint32 = 0; - uint8_t temp_value = 0; - - if(!flipper_format_read_hex(file, "DSFID", &(data->dsfid), 1)) break; - if(!flipper_format_read_hex(file, "AFI", &(data->afi), 1)) break; - if(!flipper_format_read_hex(file, "IC Reference", &(data->ic_ref), 1)) break; - if(!flipper_format_read_uint32(file, "Block Count", &temp_uint32, 1)) break; - data->block_num = temp_uint32; - if(!flipper_format_read_hex(file, "Block Size", &(data->block_size), 1)) break; - if(!flipper_format_read_hex( - file, "Data Content", data->data, data->block_num * data->block_size)) - break; - if(!flipper_format_read_hex(file, "Subtype", &temp_value, 1)) break; - data->sub_type = temp_value; - - switch(data->sub_type) { - case NfcVTypePlain: - parsed = true; - break; - case NfcVTypeSlix: - parsed = nfc_device_load_slix_data(file, dev); - break; - case NfcVTypeSlixS: - parsed = nfc_device_load_slix_s_data(file, dev); - break; - case NfcVTypeSlixL: - parsed = nfc_device_load_slix_l_data(file, dev); - break; - case NfcVTypeSlix2: - parsed = nfc_device_load_slix2_data(file, dev); - break; - } - } while(false); - - return parsed; -} - static bool nfc_device_save_bank_card_data(FlipperFormat* file, NfcDevice* dev) { bool saved = false; EmvData* data = &dev->dev_data.emv_data; @@ -1379,28 +1097,23 @@ bool nfc_device_save(NfcDevice* dev, const char* dev_name) { if(!flipper_format_write_header_cstr(file, nfc_file_header, nfc_file_version)) break; // Write nfc device type if(!flipper_format_write_comment_cstr( - file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic or ISO15693")) + file, "Nfc device type can be UID, Mifare Ultralight, Mifare Classic, Bank card")) break; nfc_device_prepare_format_string(dev, temp_str); if(!flipper_format_write_string(file, "Device type", temp_str)) break; - // Write UID - if(!flipper_format_write_comment_cstr(file, "UID is common for all formats")) break; + // Write UID, ATQA, SAK + if(!flipper_format_write_comment_cstr(file, "UID, ATQA and SAK are common for all formats")) + break; if(!flipper_format_write_hex(file, "UID", data->uid, data->uid_len)) break; - - if(dev->format != NfcDeviceSaveFormatNfcV) { - // Save ATQA in MSB order for correct companion apps display - uint8_t atqa[2] = {data->atqa[1], data->atqa[0]}; - if(!flipper_format_write_hex(file, "ATQA", atqa, 2)) break; - if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break; - } - + // Save ATQA in MSB order for correct companion apps display + uint8_t atqa[2] = {data->atqa[1], data->atqa[0]}; + if(!flipper_format_write_hex(file, "ATQA", atqa, 2)) break; + if(!flipper_format_write_hex(file, "SAK", &data->sak, 1)) break; // Save more data if necessary if(dev->format == NfcDeviceSaveFormatMifareUl) { if(!nfc_device_save_mifare_ul_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { if(!nfc_device_save_mifare_df_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatNfcV) { - if(!nfc_device_save_nfcv_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatBankCard) { if(!nfc_device_save_bank_card_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatMifareClassic) { @@ -1477,20 +1190,18 @@ static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dia if(!nfc_device_parse_format_string(dev, temp_str)) break; // Read and parse UID, ATQA and SAK if(!flipper_format_get_value_count(file, "UID", &data_cnt)) break; - if(!(data_cnt == 4 || data_cnt == 7 || data_cnt == 8)) break; + if(!(data_cnt == 4 || data_cnt == 7)) break; data->uid_len = data_cnt; if(!flipper_format_read_hex(file, "UID", data->uid, data->uid_len)) break; - if(dev->format != NfcDeviceSaveFormatNfcV) { - if(version == version_with_lsb_atqa) { - if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break; - } else { - uint8_t atqa[2] = {}; - if(!flipper_format_read_hex(file, "ATQA", atqa, 2)) break; - data->atqa[0] = atqa[1]; - data->atqa[1] = atqa[0]; - } - if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break; + if(version == version_with_lsb_atqa) { + if(!flipper_format_read_hex(file, "ATQA", data->atqa, 2)) break; + } else { + uint8_t atqa[2] = {}; + if(!flipper_format_read_hex(file, "ATQA", atqa, 2)) break; + data->atqa[0] = atqa[1]; + data->atqa[1] = atqa[0]; } + if(!flipper_format_read_hex(file, "SAK", &data->sak, 1)) break; // Load CUID uint8_t* cuid_start = data->uid; if(data->uid_len == 7) { @@ -1505,8 +1216,6 @@ static bool nfc_device_load_data(NfcDevice* dev, FuriString* path, bool show_dia if(!nfc_device_load_mifare_classic_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatMifareDesfire) { if(!nfc_device_load_mifare_df_data(file, dev)) break; - } else if(dev->format == NfcDeviceSaveFormatNfcV) { - if(!nfc_device_load_nfcv_data(file, dev)) break; } else if(dev->format == NfcDeviceSaveFormatBankCard) { if(!nfc_device_load_bank_card_data(file, dev)) break; } diff --git a/lib/nfc/nfc_device.h b/lib/nfc/nfc_device.h index 10530e317..8b2e6e5ba 100644 --- a/lib/nfc/nfc_device.h +++ b/lib/nfc/nfc_device.h @@ -8,11 +8,9 @@ #include #include #include -#include #include #include #include -#include #ifdef __cplusplus extern "C" { @@ -30,11 +28,9 @@ typedef void (*NfcLoadingCallback)(void* context, bool state); typedef enum { NfcDeviceProtocolUnknown, NfcDeviceProtocolEMV, - NfcDeviceProtocolMRTD, NfcDeviceProtocolMifareUl, NfcDeviceProtocolMifareClassic, NfcDeviceProtocolMifareDesfire, - NfcDeviceProtocolNfcV } NfcProtocol; typedef enum { @@ -43,7 +39,6 @@ typedef enum { NfcDeviceSaveFormatMifareUl, NfcDeviceSaveFormatMifareClassic, NfcDeviceSaveFormatMifareDesfire, - NfcDeviceSaveFormatNfcV, } NfcDeviceSaveFormat; typedef struct { @@ -76,11 +71,9 @@ typedef struct { }; union { EmvData emv_data; - MrtdData mrtd_data; MfUltralightData mf_ul_data; MfClassicData mf_classic_data; MifareDesfireData mf_df_data; - NfcVData nfcv_data; }; FuriString* parsed_data; } NfcDeviceData; diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index b4a45efdb..c2b89c71a 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -16,7 +16,6 @@ NfcWorker* nfc_worker_alloc() { nfc_worker->callback = NULL; nfc_worker->context = NULL; - nfc_worker->event_data = NULL; nfc_worker->storage = furi_record_open(RECORD_STORAGE); // Initialize rfal @@ -46,10 +45,6 @@ NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker) { return nfc_worker->state; } -void* nfc_worker_get_event_data(NfcWorker* nfc_worker) { - return nfc_worker->event_data; -} - void nfc_worker_start( NfcWorker* nfc_worker, NfcWorkerState state, @@ -116,12 +111,6 @@ int32_t nfc_worker_task(void* context) { nfc_worker_mf_classic_dict_attack(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateAnalyzeReader) { nfc_worker_analyze_reader(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) { - nfc_worker_emulate_nfcv(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) { - nfc_worker_nfcv_unlock(nfc_worker); - } else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) { - nfc_worker_nfcv_unlock(nfc_worker); } furi_hal_nfc_sleep(); nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); @@ -129,179 +118,6 @@ int32_t nfc_worker_task(void* context) { return 0; } -static bool nfc_worker_read_nfcv_content(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { - bool read_success = false; - NfcVReader reader = {}; - - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data; - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, tx_rx, false); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); - } - - do { - if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 200)) break; - if(!nfcv_read_card(&reader, nfc_data, nfcv_data)) break; - - read_success = true; - } while(false); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } - - return read_success; -} - -void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) { - furi_assert(nfc_worker); - furi_assert(nfc_worker->callback); - - NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data; - FuriHalNfcTxRxContext tx_rx = {}; - uint8_t* key_data = nfcv_data->sub_data.slix.key_privacy; - uint32_t key = 0; - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, &tx_rx, true); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); - } - - furi_hal_nfc_sleep(); - - while((nfc_worker->state == NfcWorkerStateNfcVUnlock) || - (nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave)) { - furi_hal_nfc_exit_sleep(); - furi_hal_nfc_ll_txrx_on(); - furi_hal_nfc_ll_poll(); - if(furi_hal_nfc_ll_set_mode( - FuriHalNfcModePollNfcv, FuriHalNfcBitrate26p48, FuriHalNfcBitrate26p48) != - FuriHalNfcReturnOk) { - break; - } - - furi_hal_nfc_ll_set_fdt_listen(FURI_HAL_NFC_LL_FDT_LISTEN_NFCV_POLLER); - furi_hal_nfc_ll_set_fdt_poll(FURI_HAL_NFC_LL_FDT_POLL_NFCV_POLLER); - furi_hal_nfc_ll_set_error_handling(FuriHalNfcErrorHandlingNfc); - furi_hal_nfc_ll_set_guard_time(FURI_HAL_NFC_LL_GT_NFCV); - - furi_hal_console_printf("Detect presence\r\n"); - ReturnCode ret = slix_get_random(nfcv_data); - - if(ret == ERR_NONE) { - /* there is some chip, responding with a RAND */ - nfc_worker->dev_data->protocol = NfcDeviceProtocolNfcV; - furi_hal_console_printf(" Chip detected. In privacy?\r\n"); - ret = nfcv_inventory(NULL); - - if(ret == ERR_NONE) { - /* chip is also visible, so no action required, just save */ - if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) { - NfcVReader reader = {}; - - if(!nfcv_read_card(&reader, &nfc_worker->dev_data->nfc_data, nfcv_data)) { - furi_hal_console_printf(" => failed, wait for chip to disappear.\r\n"); - snprintf(nfcv_data->error, sizeof(nfcv_data->error), "Read card\nfailed"); - nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context); - } else { - furi_hal_console_printf(" => success, wait for chip to disappear.\r\n"); - nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); - } - } else { - furi_hal_console_printf(" => success, wait for chip to disappear.\r\n"); - nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); - } - - while(slix_get_random(NULL) == ERR_NONE) { - furi_delay_ms(100); - } - - furi_hal_console_printf( - " => chip is already visible, wait for chip to disappear.\r\n"); - nfc_worker->callback(NfcWorkerEventAborted, nfc_worker->context); - while(slix_get_random(NULL) == ERR_NONE) { - furi_delay_ms(100); - } - - key_data[0] = 0; - key_data[1] = 0; - key_data[2] = 0; - key_data[3] = 0; - - } else { - /* chip is invisible, try to unlock */ - furi_hal_console_printf(" chip is invisible, unlocking\r\n"); - - if(nfcv_data->auth_method == NfcVAuthMethodManual) { - key |= key_data[0] << 24; - key |= key_data[1] << 16; - key |= key_data[2] << 8; - key |= key_data[3] << 0; - - ret = slix_unlock(nfcv_data, 4); - } else { - key = 0x7FFD6E5B; - key_data[0] = key >> 24; - key_data[1] = key >> 16; - key_data[2] = key >> 8; - key_data[3] = key >> 0; - ret = slix_unlock(nfcv_data, 4); - - if(ret != ERR_NONE) { - /* main key failed, trying second one */ - furi_hal_console_printf(" trying second key after resetting\r\n"); - - /* reset chip */ - furi_hal_nfc_ll_txrx_off(); - furi_delay_ms(20); - furi_hal_nfc_ll_txrx_on(); - - if(slix_get_random(nfcv_data) != ERR_NONE) { - furi_hal_console_printf(" reset failed\r\n"); - } - - key = 0x0F0F0F0F; - key_data[0] = key >> 24; - key_data[1] = key >> 16; - key_data[2] = key >> 8; - key_data[3] = key >> 0; - ret = slix_unlock(nfcv_data, 4); - } - } - if(ret != ERR_NONE) { - /* unlock failed */ - furi_hal_console_printf(" => failed, wait for chip to disappear.\r\n"); - snprintf( - nfcv_data->error, sizeof(nfcv_data->error), "Passwords not\naccepted"); - nfc_worker->callback(NfcWorkerEventWrongCardDetected, nfc_worker->context); - - /* reset chip */ - furi_hal_nfc_ll_txrx_off(); - furi_delay_ms(20); - furi_hal_nfc_ll_txrx_on(); - - /* wait for disappearing */ - while(slix_get_random(NULL) == ERR_NONE) { - furi_delay_ms(100); - } - } - } - } else { - nfc_worker->callback(NfcWorkerEventNoCardDetected, nfc_worker->context); - } - - furi_hal_nfc_ll_txrx_off(); - furi_hal_nfc_sleep(); - furi_delay_ms(100); - } - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } -} - static bool nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { bool read_success = false; MfUltralightReader reader = {}; @@ -476,49 +292,6 @@ static bool nfc_worker_read_bank_card(NfcWorker* nfc_worker, FuriHalNfcTxRxConte return read_success; } -static bool nfc_worker_read_mrtd(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { - bool read_success = false; - MrtdData* mrtd_data = &nfc_worker->dev_data->mrtd_data; - MrtdApplication* mrtd_app = mrtd_alloc_init(tx_rx, mrtd_data); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, tx_rx, false); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); - } - - do { - // Read passport - if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 300)) break; - - //TODO: try select eMRTDApp first, but when PACE, read CardAccess first! - if(!mrtd_select_app(mrtd_app, AID.eMRTDApplication)) break; // Passport app not selected - - if(mrtd_data->auth.method == MrtdAuthMethodNone) { - // Selected the passport app, but auth. not selected - // Successfully read what we could - read_success = true; - break; - } - - if(!mrtd_authenticate(mrtd_app)) { - // At least we're reading an MRTD and should the app switch to the NFC scenes - read_success = true; - break; // Authentication failed - } - - mrtd_read_parse_file(mrtd_app, EF.COM); - mrtd_read_parse_file(mrtd_app, EF.DG1); - - read_success = true; - } while(false); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } - - return read_success; -} - static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; @@ -544,24 +317,11 @@ static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* t card_read = true; } else if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { FURI_LOG_I(TAG, "ISO14443-4 card detected"); - //TODO: thoughts on improving logic/readability here? - do { - FURI_LOG_D(TAG, "Try reading EMV"); - if(nfc_worker_read_bank_card(nfc_worker, tx_rx)) { - nfc_worker->dev_data->protocol = NfcDeviceProtocolEMV; - break; - } - - furi_hal_nfc_sleep(); // Needed between checks - FURI_LOG_D(TAG, "Try reading MRTD"); - if(nfc_worker_read_mrtd(nfc_worker, tx_rx)) { - nfc_worker->dev_data->protocol = NfcDeviceProtocolMRTD; - break; - } - + nfc_worker->dev_data->protocol = NfcDeviceProtocolEMV; + if(!nfc_worker_read_bank_card(nfc_worker, tx_rx)) { FURI_LOG_I(TAG, "Unknown card. Save UID"); nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; - } while(false); + } card_read = true; } else { nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; @@ -571,47 +331,6 @@ static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* t return card_read; } -static bool nfc_worker_read_nfcb(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - - bool card_read = false; - furi_hal_nfc_sleep(); - if(nfc_data->interface == FuriHalNfcInterfaceIsoDep) { - FURI_LOG_I(TAG, "ISO14443-4B card detected"); - //TODO: thoughts on improving logic/readability here? - do { - FURI_LOG_D(TAG, "Try reading MRTD"); - if(nfc_worker_read_mrtd(nfc_worker, tx_rx)) { - nfc_worker->dev_data->protocol = NfcDeviceProtocolMRTD; - break; - } - - FURI_LOG_I(TAG, "Unknown card. Save UID"); - nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; - } while(false); - card_read = true; - } else { - nfc_worker->dev_data->protocol = NfcDeviceProtocolUnknown; - card_read = true; - } - - return card_read; -} - -static bool nfc_worker_read_nfcv(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { - furi_assert(nfc_worker); - furi_assert(tx_rx); - - bool card_read = false; - furi_hal_nfc_sleep(); - - /* until here the UID field is reversed from the reader IC. - we will read it here again and it will get placed in the right order. */ - card_read = nfc_worker_read_nfcv_content(nfc_worker, tx_rx); - - return card_read; -} - void nfc_worker_read(NfcWorker* nfc_worker) { furi_assert(nfc_worker); furi_assert(nfc_worker->callback); @@ -642,9 +361,6 @@ void nfc_worker_read(NfcWorker* nfc_worker) { } else if(dev_data->protocol == NfcDeviceProtocolEMV) { event = NfcWorkerEventReadBankCard; break; - } else if(dev_data->protocol == NfcDeviceProtocolMRTD) { - event = NfcWorkerEventReadPassport; - break; } else if(dev_data->protocol == NfcDeviceProtocolUnknown) { event = NfcWorkerEventReadUidNfcA; break; @@ -656,27 +372,13 @@ void nfc_worker_read(NfcWorker* nfc_worker) { } } } else if(nfc_data->type == FuriHalNfcTypeB) { - if(nfc_worker_read_nfcb(nfc_worker, &tx_rx)) { - if(dev_data->protocol == NfcDeviceProtocolMRTD) { - event = NfcWorkerEventReadPassport; - break; - } - } - event = NfcWorkerEventReadUidNfcB; break; } else if(nfc_data->type == FuriHalNfcTypeF) { event = NfcWorkerEventReadUidNfcF; break; } else if(nfc_data->type == FuriHalNfcTypeV) { - FURI_LOG_I(TAG, "NfcV detected"); - nfc_worker->dev_data->protocol = NfcDeviceProtocolNfcV; - if(nfc_worker_read_nfcv(nfc_worker, &tx_rx)) { - FURI_LOG_I(TAG, "nfc_worker_read_nfcv success"); - //event = NfcWorkerEventReadNfcV; - //break; - } - event = NfcWorkerEventReadNfcV; + event = NfcWorkerEventReadUidNfcV; break; } } else { @@ -794,32 +496,6 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { } } -void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data; - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, &tx_rx, true); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); - } - - nfcv_emu_init(nfc_data, nfcv_data); - while(nfc_worker->state == NfcWorkerStateNfcVEmulate) { - if(nfcv_emu_loop(&tx_rx, nfc_data, nfcv_data, 50)) { - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - } - furi_delay_ms(0); - } - nfcv_emu_deinit(nfcv_data); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } -} - void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; FuriHalNfcDevData params = { @@ -882,15 +558,6 @@ void nfc_worker_emulate_mf_ultralight(NfcWorker* nfc_worker) { mf_ul_prepare_emulation_response, &emulator, 5000); - // Check if there was an auth attempt - if(emulator.auth_attempted) { - nfc_worker->event_data = &emulator.auth_attempt; - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventMfUltralightPwdAuth, nfc_worker->context); - } - emulator.auth_attempted = false; - nfc_worker->event_data = NULL; - } // Check if data was modified if(emulator.data_changed) { nfc_worker->dev_data->mf_ul_data = emulator.data; @@ -1091,7 +758,6 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { break; } nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); - deactivated = true; } furi_hal_nfc_sleep(); deactivated = true; @@ -1112,7 +778,6 @@ void nfc_worker_mf_classic_dict_attack(NfcWorker* nfc_worker) { mf_classic_set_key_found(data, i, MfClassicKeyB, key); nfc_worker->callback(NfcWorkerEventFoundKeyB, nfc_worker->context); nfc_worker_mf_classic_key_attack(nfc_worker, key, &tx_rx, i + 1); - deactivated = true; } deactivated = true; } else { diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index 5df40f1aa..ce542828a 100644 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -18,9 +18,6 @@ typedef enum { NfcWorkerStateReadMfUltralightReadAuth, NfcWorkerStateMfClassicDictAttack, NfcWorkerStateAnalyzeReader, - NfcWorkerStateNfcVEmulate, - NfcWorkerStateNfcVUnlock, - NfcWorkerStateNfcVUnlockAndSave, // Debug NfcWorkerStateEmulateApdu, NfcWorkerStateField, @@ -42,9 +39,7 @@ typedef enum { NfcWorkerEventReadMfClassicDone, NfcWorkerEventReadMfClassicLoadKeyCache, NfcWorkerEventReadMfClassicDictAttackRequired, - NfcWorkerEventReadNfcV, NfcWorkerEventReadBankCard, - NfcWorkerEventReadPassport, // Nfc worker common events NfcWorkerEventSuccess, @@ -75,8 +70,6 @@ typedef enum { // Mifare Ultralight events NfcWorkerEventMfUltralightPassKey, // NFC worker requesting manual key NfcWorkerEventMfUltralightPwdAuth, // Reader sent auth command - NfcWorkerEventNfcVPassKey, // NFC worker requesting manual key - } NfcWorkerEvent; typedef bool (*NfcWorkerCallback)(NfcWorkerEvent event, void* context); @@ -85,8 +78,6 @@ NfcWorker* nfc_worker_alloc(); NfcWorkerState nfc_worker_get_state(NfcWorker* nfc_worker); -void* nfc_worker_get_event_data(NfcWorker* nfc_worker); - void nfc_worker_free(NfcWorker* nfc_worker); void nfc_worker_start( @@ -97,5 +88,3 @@ void nfc_worker_start( void* context); void nfc_worker_stop(NfcWorker* nfc_worker); -void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker); -void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker); diff --git a/lib/nfc/nfc_worker_i.h b/lib/nfc/nfc_worker_i.h index 95c66c2ab..9733426ab 100644 --- a/lib/nfc/nfc_worker_i.h +++ b/lib/nfc/nfc_worker_i.h @@ -7,14 +7,11 @@ #include #include -#include #include #include #include #include #include -#include -#include #include struct NfcWorker { @@ -26,7 +23,6 @@ struct NfcWorker { NfcWorkerCallback callback; void* context; - void* event_data; NfcWorkerState state; diff --git a/lib/nfc/protocols/mifare_classic.c b/lib/nfc/protocols/mifare_classic.c index 8c7603767..d2d7467dc 100644 --- a/lib/nfc/protocols/mifare_classic.c +++ b/lib/nfc/protocols/mifare_classic.c @@ -659,7 +659,6 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u for(size_t i = start_block; i < start_block + total_blocks; i++) { if(!mf_classic_is_block_read(data, i)) { - if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyA, &crypto, false, 0)) continue; if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { mf_classic_set_block_read(data, i, &block_tmp); blocks_read++; @@ -676,7 +675,6 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u blocks_read++; } } - furi_hal_nfc_sleep(); } else { blocks_read++; } @@ -699,7 +697,6 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u for(size_t i = start_block; i < start_block + total_blocks; i++) { if(!mf_classic_is_block_read(data, i)) { - if(!mf_classic_auth(tx_rx, i, key, MfClassicKeyB, &crypto, false, 0)) continue; if(mf_classic_read_block(tx_rx, &crypto, i, &block_tmp)) { mf_classic_set_block_read(data, i, &block_tmp); blocks_read++; @@ -716,7 +713,6 @@ void mf_classic_read_sector(FuriHalNfcTxRxContext* tx_rx, MfClassicData* data, u blocks_read++; } } - furi_hal_nfc_sleep(); } else { blocks_read++; } diff --git a/lib/nfc/protocols/mifare_classic.h b/lib/nfc/protocols/mifare_classic.h index f2623d16e..c03350f2e 100644 --- a/lib/nfc/protocols/mifare_classic.h +++ b/lib/nfc/protocols/mifare_classic.h @@ -9,7 +9,6 @@ #define MF_MINI_TOTAL_SECTORS_NUM (5) #define MF_CLASSIC_1K_TOTAL_SECTORS_NUM (16) #define MF_CLASSIC_4K_TOTAL_SECTORS_NUM (40) -#define MF_MINI_TOTAL_SECTORS_NUM (5) #define MF_CLASSIC_SECTORS_MAX (40) #define MF_CLASSIC_BLOCKS_IN_SECTOR_MAX (16) @@ -20,9 +19,9 @@ #define MF_CLASSIC_ACCESS_BYTES_SIZE (4) typedef enum { - MfClassicTypeMini, MfClassicType1k, MfClassicType4k, + MfClassicTypeMini, } MfClassicType; typedef enum { diff --git a/lib/nfc/protocols/mrtd.c b/lib/nfc/protocols/mrtd.c deleted file mode 100644 index e2b3cc4ba..000000000 --- a/lib/nfc/protocols/mrtd.c +++ /dev/null @@ -1,758 +0,0 @@ -#include -#include -#include -#include - -#include "../helpers/iso7816.h" - -#include "mrtd.h" - -#define TAG "Mrtd" - -//TODO: Check EF.DIR first? Before LDS1 -//TODO: ICAO 9303 p11 §4.2 steps -//- Read EF.CardAccess (REQUIRED) -// If not available or does not contain PACE params, try BAC -//- Read EF.DIR (OPTIONAL) -// Check list of applications present -//- PACE (CONDITIONAL) -//- BAC (CONDITIONAL) - -//TODO: idea - generalize ISO7816 reading. List available apps - -#define num_elements(A) (sizeof(A) / sizeof(A[0])) - -static const char* mrtd_auth_file_header = "Flipper MRTD params"; -static const uint32_t mrtd_auth_file_version = 1; - -static void hexdump(FuriLogLevel level, char* prefix, void* data, size_t length) { - if(furi_log_get_level() >= level) { - printf("%s ", prefix); - for(size_t i = 0; i < length; i++) { - printf("%02X ", ((uint8_t*)data)[i]); - } - printf("\r\n"); - } -} - -static void mrtd_trace(MrtdApplication* app) { - FuriHalNfcTxRxContext* tx_rx = app->tx_rx; - if(furi_log_get_level() == FuriLogLevelTrace) { - printf("TX: "); - for(size_t i = 0; i < tx_rx->tx_bits / 8; i++) { - printf("%02X ", tx_rx->tx_data[i]); - } - printf("\r\nRX: "); - for(size_t i = 0; i < tx_rx->rx_bits / 8; i++) { - printf("%02X ", tx_rx->rx_data[i]); - } - printf("\r\n"); - } -} - -uint16_t mrtd_decode_response(uint8_t* buffer, size_t len) { - // Last two bytes are return code - return (buffer[len - 2] << 8) | buffer[len - 1]; -} - -//TODO: rename to transceive? -//TODO: PRIO output and output written writing seems to crash flipper, sometimes -bool mrtd_send_apdu( - MrtdApplication* app, - uint8_t cla, - uint8_t ins, - uint8_t p1, - uint8_t p2, - uint8_t lc, - const void* data, - int16_t le, - uint8_t* output, - size_t* output_written) { - FuriHalNfcTxRxContext* tx_rx = app->tx_rx; - size_t idx = 0; - - FURI_LOG_T(TAG, "Send APDU, lc: %d, le: %d", lc, le); - - if(app->secure_messaging) { - app->ssc_long++; - idx = mrtd_protect_apdu( - cla, ins, p1, p2, lc, data, le, app->ksenc, app->ksmac, app->ssc_long, tx_rx->tx_data); - } else { - tx_rx->tx_data[idx++] = cla; - tx_rx->tx_data[idx++] = ins; - tx_rx->tx_data[idx++] = p1; - tx_rx->tx_data[idx++] = p2; - if(lc > 0) { - tx_rx->tx_data[idx++] = lc; - memcpy(tx_rx->tx_data + idx, data, lc); - idx += lc; - } - if(le >= 0) { - tx_rx->tx_data[idx++] = le & 0xff; - } - } - - tx_rx->tx_bits = idx * 8; - tx_rx->tx_rx_type = FuriHalNfcTxRxTypeDefault; - - //TODO: timeout as param? - if(furi_hal_nfc_tx_rx(tx_rx, 300)) { - mrtd_trace(app); - uint16_t ret_code = mrtd_decode_response(tx_rx->rx_data, tx_rx->rx_bits / 8); - - if(app->secure_messaging && ret_code == 0x9000) { - app->ssc_long++; - ret_code = mrtd_bac_decrypt_verify_sm( - tx_rx->rx_data, - tx_rx->rx_bits / 8 - 2, - app->ksenc, - app->ksmac, - app->ssc_long, - output, - output_written); - //ret_code = 0x1337; //TODO: remove PRIO - } - - //TODO: handle other return codes? - if(ret_code == 0x9000) { - if(!app->secure_messaging && le > 0) { - // Secure Messaging sets output while decrypting - output_written = memcpy(output, tx_rx->rx_data, le); - } - return true; - } else { - FURI_LOG_I(TAG, "APDU answer is not 0x9000, but 0x%04X", ret_code); - - switch(ret_code) { - case 0x6987: - FURI_LOG_I(TAG, "'expected secure messaging data objects are missing'"); - app->secure_messaging = false; - break; - case 0x6988: - FURI_LOG_I(TAG, "'secure messaging data objects are incorrect'"); - app->secure_messaging = false; - break; - case 0xff01: - //CUSTOM ERROR CODE from mrtd_helpers.c - FURI_LOG_I(TAG, "'invalid padding'"); - break; - case 0xff02: - //CUSTOM ERROR CODE from mrtd_helpers.c - FURI_LOG_I(TAG, "'verify failed'"); - break; - } - - return false; - } - } else { - FURI_LOG_D(TAG, "Sending - failed"); - } - return false; -} - -//TODO: rename commands to "mrtd_cmd_..." -bool mrtd_select_app(MrtdApplication* app, AIDValue aid) { - FURI_LOG_D( - TAG, - "Send select App: %02X %02X %02X %02X %02X %02X %02X", - aid[0], - aid[1], - aid[2], - aid[3], - aid[4], - aid[5], - aid[6]); - if(!mrtd_send_apdu(app, 0x00, 0xA4, 0x04, 0x0C, 0x07, aid, -1, NULL, NULL)) { - FURI_LOG_W(TAG, "Failed select App"); - return false; - } - return true; -} - -bool mrtd_get_challenge(MrtdApplication* app, uint8_t challenge[8]) { - FURI_LOG_D(TAG, "Send Get Challenge"); - size_t chal_size; - if(!mrtd_send_apdu(app, 0x00, 0x84, 0x00, 0x00, 0x00, NULL, 0x08, challenge, &chal_size)) { - FURI_LOG_W(TAG, "Failed get challenge"); - return false; - } - - return true; -} - -bool mrtd_external_authenticate( - MrtdApplication* app, - uint8_t* cmd_data, - size_t cmd_size, - uint8_t* out_data, - size_t out_size) { - furi_assert(cmd_size == 0x28); - furi_assert(out_size >= 0x28); - - FURI_LOG_D(TAG, "Send External Authenticate"); - if(!mrtd_send_apdu( - app, 0x00, 0x82, 0x00, 0x00, cmd_size, cmd_data, 0x28, out_data, &out_size)) { - FURI_LOG_W(TAG, "Failed External Authenticate"); - return false; - } - - return true; -} - -bool mrtd_select_file(MrtdApplication* app, EFFile file) { - uint8_t data[] = {file.file_id >> 8, file.file_id & 0xff}; - FURI_LOG_D(TAG, "Send select EF: %s (0x%04X)", file.name, file.file_id); - if(!mrtd_send_apdu(app, 0x00, 0xA4, 0x02, 0x0C, 0x02, data, -1, NULL, NULL)) { - FURI_LOG_E(TAG, "Failed select EF 0x%04X", file.file_id); - return false; - } - - return true; -} - -size_t mrtd_read_binary(MrtdApplication* app, uint8_t* buffer, size_t bufsize, size_t offset) { - UNUSED(buffer); - UNUSED(bufsize); - // 00 B0 offst - - FURI_LOG_D(TAG, "Read binary, offset: %d", offset); - //TODO: read first 4 bytes, determine length, iterate through file - //TODO: limit reading/buffer fill to max bufsize - - //TODO: test with max_read = bufsize (value !0, > file size) - int16_t max_read = 0; // 0 = 'everything', -1 = 'nothing', >0 = amount of bytes - size_t buf_written = 0; - if(!mrtd_send_apdu( - app, 0x00, 0xB0, offset >> 8, offset & 0xff, 0x00, NULL, max_read, buffer, &buf_written)) { - FURI_LOG_E(TAG, "Failed to read"); - return 0; - } - FURI_LOG_D(TAG, "buf_written: %d\n", buf_written); - - return buf_written; -} - -//TODO: use short id to read, because it's mandatory for eMRTD -//TODO: check for support of extended length in EF.ATR/INFO, see ISO7816-4 - -void mrtd_read_dump(MrtdApplication* app, EFFile file) { - FURI_LOG_D(TAG, "Read and dump %s:", file.name); - - if(!mrtd_select_file(app, file)) { - return; - } - - uint8_t data[2048]; - size_t read = 0; - size_t offset = 0; - do { - read = mrtd_read_binary(app, data, sizeof(data), offset); - offset += read; - - hexdump(FuriLogLevelDebug, "Data:", data, read); - } while(read > 0); -} - -bool parse_ef_dir(EF_DIR_contents* EF_DIR, const uint8_t* data, size_t length) { - size_t offset = 0; - uint8_t app_idx = 0; - - memset(EF_DIR->applications, 0x00, sizeof(EF_DIR->applications)); - EF_DIR->applications_count = 0; - - while(offset < length) { - TlvInfo tlv = iso7816_tlv_parse(data + offset); - - if(tlv.tag != 0x61 || tlv.length != 0x09) { - FURI_LOG_E( - TAG, - "Invalid EF.DIR, tag at offset %d must be '61' and length 9. Got '%02X' and %d", - offset, - tlv.tag, - tlv.length); - return false; - } - - tlv = iso7816_tlv_parse(tlv.value); - if(tlv.tag != 0x4F || tlv.length != 0x07) { - FURI_LOG_E( - TAG, "Invalid EF.DIR, subtag at offset %d must be '4F' and length 7", offset); - return false; - } - - memcpy(EF_DIR->applications[app_idx], tlv.value, tlv.length); - EF_DIR->applications_count = ++app_idx; - - offset = tlv.next - data; - } - - //TODO: remove testing block: - FURI_LOG_D(TAG, "EF.DIR applications: %d", EF_DIR->applications_count); - if(furi_log_get_level() >= FuriLogLevelDebug) { - for(uint8_t i = 0; i < EF_DIR->applications_count; ++i) { - printf("- "); - for(uint8_t n = 0; n < sizeof(AIDValue); ++n) { - printf("%02X ", EF_DIR->applications[i][n]); - } - printf("\r\n"); - } - } - - return true; -} - -bool parse_ef_com(EF_COM_contents* EF_COM, const uint8_t* data, size_t length) { - uint16_t lds_tag_path[] = {0x60, 0x5f01}; - uint16_t unicode_tag_path[] = {0x60, 0x5f36}; - uint16_t tags_tag_path[] = {0x60, 0x5c}; - - TlvInfo tlv_lds_version = - iso7816_tlv_select(data, length, lds_tag_path, num_elements(lds_tag_path)); - if(!tlv_lds_version.tag) { - FURI_LOG_W(TAG, "EF.COM LDS version not found"); - return false; - } - - EF_COM->lds_version = tlv_number(tlv_lds_version); - - TlvInfo tlv_unicode_version = - iso7816_tlv_select(data, length, unicode_tag_path, num_elements(unicode_tag_path)); - if(!tlv_unicode_version.tag) { - FURI_LOG_W(TAG, "EF.COM Unicode info not found!"); - return false; - } - - EF_COM->unicode_version = tlv_number(tlv_unicode_version); - - TlvInfo tlv_tag_list = - iso7816_tlv_select(data, length, tags_tag_path, num_elements(tags_tag_path)); - if(!tlv_tag_list.tag) { - FURI_LOG_W(TAG, "EF.CO Tag List not found!"); - return false; - } - - for(size_t i = 0; i < MAX_EFCOM_TAGS; ++i) { - EF_COM->tag_list[i] = (i < tlv_tag_list.length) ? tlv_tag_list.value[i] : 0x00; - } - - return true; -} - -void mrzcpy(uint8_t* dest, const uint8_t* src, size_t* idx, size_t n) { - //FURI_LOG_D(TAG, "mrzcpy %d: %.*s", n, n, src + *idx); - //memcpy(dest, src + *idx, n); - for(size_t i = 0; i < n; ++i) { - uint8_t c = src[i + *idx]; - if(c == '<') { - c = ' '; - } - dest[i] = c; - } - dest[n] = 0x00; - *idx += n; -} - -bool parse_ef_dg1(EF_DG1_contents* DG1, const uint8_t* data, size_t length) { - TlvInfo tlv_mrz = iso7816_tlv_select(data, length, (uint16_t[]){0x61, 0x5f1f}, 2); - - if(!tlv_mrz.tag) { - FURI_LOG_W(TAG, "DG1, unexpected content. Could not find tag 0x61, 0x5f1f"); - return false; - } - - const uint8_t* mrz = tlv_mrz.value; - size_t idx = 0; - - switch(tlv_mrz.length) { - case 90: - DG1->type = MrtdTypeTD1; - mrzcpy(DG1->doctype, mrz, &idx, 2); - mrzcpy(DG1->issuing_state, mrz, &idx, 3); - mrzcpy(DG1->docnr, mrz, &idx, 9); - idx += 1; // docnr check digit - idx += 15; // optional data - mrtd_parse_date(&DG1->birth_date, mrz + idx); - idx += 6; // birth_date - idx += 1; // birth date check digit - mrzcpy(DG1->sex, mrz, &idx, 1); - mrtd_parse_date(&DG1->expiry_date, mrz + idx); - idx += 6; // expiry_date - idx += 1; // expiry date check digit - mrzcpy(DG1->nationality, mrz, &idx, 3); - idx += 11; // optional data - idx += 1; // check digit - mrzcpy(DG1->name, mrz, &idx, 30); - // 30 + 30 + 30 - break; - case 72: - DG1->type = MrtdTypeTD2; - mrzcpy(DG1->doctype, mrz, &idx, 2); - mrzcpy(DG1->issuing_state, mrz, &idx, 3); - mrzcpy(DG1->name, mrz, &idx, 31); - mrzcpy(DG1->docnr, mrz, &idx, 9); - idx += 1; // docnr check digit - mrzcpy(DG1->nationality, mrz, &idx, 3); - mrtd_parse_date(&DG1->birth_date, mrz + idx); - idx += 6; // birth_date - idx += 1; // birth date check digit - mrzcpy(DG1->sex, mrz, &idx, 1); - mrtd_parse_date(&DG1->expiry_date, mrz + idx); - idx += 6; // expiry_date - idx += 1; // expiry date check digit - idx += 7; // optional data - idx += 1; // check digit - // 36 + 36 - break; - case 88: - DG1->type = MrtdTypeTD3; - mrzcpy(DG1->doctype, mrz, &idx, 2); - mrzcpy(DG1->issuing_state, mrz, &idx, 3); - mrzcpy(DG1->name, mrz, &idx, 39); - mrzcpy(DG1->docnr, mrz, &idx, 9); - idx += 1; // docnr check digit - mrzcpy(DG1->nationality, mrz, &idx, 3); - mrtd_parse_date(&DG1->birth_date, mrz + idx); - idx += 1; // birth date check digit - idx += 6; // birth_date - mrzcpy(DG1->sex, mrz, &idx, 1); - mrtd_parse_date(&DG1->expiry_date, mrz + idx); - idx += 6; // expiry_date - idx += 1; // expiry date check digit - idx += 14; // optional data - idx += 1; // check digit - idx += 1; // check digit - // 44 + 44 - break; - default: - FURI_LOG_W( - TAG, "Unexpected MRZ length in DG1: %d. TD1=90, TD2=72, TD3=88.", tlv_mrz.length); - return false; - } - - return true; -} - -bool mrtd_read_parse_file(MrtdApplication* app, EFFile file) { - uint8_t buffer[100]; - size_t buf_len; - - FURI_LOG_D(TAG, "Read and parse %s (%04X)", file.name, file.file_id); - - if(!mrtd_select_file(app, file)) { - FURI_LOG_E(TAG, "Could not select %s", file.name); - return false; - } - - FURI_LOG_D(TAG, "Selected %s", file.name); - - buf_len = mrtd_read_binary(app, buffer, num_elements(buffer), 0); - - if(!buf_len) { - FURI_LOG_E(TAG, "Could not read %s", file.name); - return false; - } - - FURI_LOG_D(TAG, "Read %s", file.name); - - bool result = false; - - if(file.file_id == EF.COM.file_id) { - result = parse_ef_com(&app->mrtd_data->files.EF_COM, buffer, buf_len); - FURI_LOG_D(TAG, "Parsed EF.COM"); - } else if(file.file_id == EF.DIR.file_id) { - result = parse_ef_dir(&app->mrtd_data->files.EF_DIR, buffer, buf_len); - FURI_LOG_D(TAG, "Parsed EF.DIR"); - } else if(file.file_id == EF.DG1.file_id) { - result = parse_ef_dg1(&app->mrtd_data->files.DG1, buffer, buf_len); - } else { - FURI_LOG_W(TAG, "Don't know how to parse file with id 0x%04X", file.file_id); - } - - return result; -} - -MrtdApplication* mrtd_alloc_init(FuriHalNfcTxRxContext* tx_rx, MrtdData* mrtd_data) { - MrtdApplication* app = malloc(sizeof(MrtdApplication)); - - app->tx_rx = tx_rx; - app->mrtd_data = mrtd_data; - - return app; -} - -void mrtd_free(MrtdApplication* app) { - furi_assert(app); - free(app); -} - -bool mrtd_bac(MrtdApplication* app, MrtdAuthData* auth) { - UNUSED(app); - - static bool rand_generator_inited = false; - uint8_t rnd_ic[8]; - uint8_t rnd_ifd[8]; - uint8_t k_ifd[16]; - - if(!rand_generator_inited) { - // TODO: should random initialization maybe be system wide? - srand(DWT->CYCCNT); - rand_generator_inited = true; - } - - mrtd_get_challenge(app, rnd_ic); - //TODO: remove memcpy rnd_ic - //memcpy(rnd_ic, "\x46\x08\xF9\x19\x88\x70\x22\x12", 8); - - furi_hal_random_fill_buf(rnd_ifd, 8); - furi_hal_random_fill_buf(k_ifd, 16); - //TODO: remove testing code: - //memcpy(rnd_ifd, "\x78\x17\x23\x86\x0C\x06\xC2\x26", 8); - //memcpy(k_ifd, "\x0B\x79\x52\x40\xCB\x70\x49\xB0\x1C\x19\xB3\x3E\x32\x80\x4F\x0B", 16); - - hexdump(FuriLogLevelDebug, "rnd_ifd:", rnd_ifd, 8); - hexdump(FuriLogLevelDebug, "k_ifd:", k_ifd, 16); - - uint8_t kenc[16]; - uint8_t kmac[16]; - - if(!mrtd_bac_keys(auth, kenc, kmac)) { - FURI_LOG_E(TAG, "Failed to calculate BAC keys"); - return false; - } - - uint8_t S[32]; - memcpy(S, rnd_ifd, 8); - memcpy(S + 8, rnd_ic, 8); - memcpy(S + 16, k_ifd, 16); - - hexdump(FuriLogLevelDebug, "S:", S, 32); - - uint8_t cmd_data[40]; - uint8_t* eifd = cmd_data; - uint8_t* mifd = cmd_data + 32; - mrtd_bac_encrypt(S, 32, kenc, eifd); - mrtd_bac_padded_mac(eifd, 32, kmac, mifd); - - uint8_t response[40]; - if(!mrtd_external_authenticate(app, cmd_data, 40, response, 40)) { - FURI_LOG_E(TAG, "BAC External Authenticate failed"); - return false; - } - - uint8_t buffer[32]; // Received R = RND.IC (8) || RND.IFD (8) || KIC (16) - if(!mrtd_bac_decrypt_verify(response, 40, kenc, kmac, buffer)) { - FURI_LOG_W(TAG, "BAC DecryptVerify failed"); - } - - uint8_t* rnd_ifd_recv = buffer + 8; - uint8_t* kic = buffer + 16; - - hexdump(FuriLogLevelDebug, "kic:", kic, 16); - - if(memcmp(rnd_ifd, rnd_ifd_recv, 8)) { - FURI_LOG_W(TAG, "BAC RND.IFD sent and received mismatch."); - } - - uint8_t kseed[16]; - for(uint8_t i = 0; i < 16; ++i) { - kseed[i] = k_ifd[i] ^ kic[i]; - //printf("seed %2d = %02X ^ %02X = %02X\r\n", i, k_ifd[i], kic[i], kseed[i]); - } - - hexdump(FuriLogLevelDebug, "kseed:", kseed, 16); - - if(!mrtd_bac_keys_from_seed(kseed, app->ksenc, app->ksmac)) { - FURI_LOG_E(TAG, "BAC error, could not derive KSenc and KSmac"); - return false; - } - hexdump(FuriLogLevelDebug, "ksenc:", app->ksenc, 16); - hexdump(FuriLogLevelDebug, "ksmac:", app->ksmac, 16); - - hexdump(FuriLogLevelTrace, "RND.IC:", rnd_ic, 8); - hexdump(FuriLogLevelTrace, "RND.IFS:", rnd_ifd, 8); - - app->ssc_long = mrtd_ssc_from_data(rnd_ic, rnd_ifd); - FURI_LOG_D(TAG, "SSC: %01llX", app->ssc_long); - - app->secure_messaging = true; - - return true; -} - -bool mrtd_authenticate(MrtdApplication* app) { - MrtdAuthMethod method = app->mrtd_data->auth.method; - app->mrtd_data->auth_success = false; - app->mrtd_data->auth_method_used = MrtdAuthMethodNone; - FURI_LOG_D(TAG, "Auth method: %d", method); - switch(method) { - case MrtdAuthMethodAny: - //TODO: try PACE, then BAC. For now, fall through to just BAC - case MrtdAuthMethodBac: - app->mrtd_data->auth_success = mrtd_bac(app, &app->mrtd_data->auth); - app->mrtd_data->auth_method_used = MrtdAuthMethodBac; - break; - case MrtdAuthMethodPace: - FURI_LOG_E(TAG, "Auth method PACE not implemented"); - break; - case MrtdAuthMethodNone: - default: - break; - } - - if(!app->mrtd_data->auth_success) { - return false; - } - - return true; -} - -bool mrtd_auth_params_save( - Storage* storage, - DialogsApp* dialogs, - MrtdAuthData* auth_data, - const char* file_name) { - return mrtd_auth_params_save_file( - storage, dialogs, auth_data, file_name, MRTD_APP_FOLDER, MRTD_APP_EXTENSION); -} - -void mrtd_date_prepare_format_string(MrtdDate date, FuriString* format_string) { - furi_string_printf(format_string, "%02u%02u%02u", date.year, date.month, date.day); -} - -bool mrtd_date_parse_format_string(MrtdDate* date, FuriString* format_string) { - int year; - int month; - int day; - - int ret = sscanf(furi_string_get_cstr(format_string), "%02d%02d%02d", &year, &month, &day); - if(ret != 3) { - return false; - } - - date->year = year; - date->month = month; - date->day = day; - return true; -} - -bool mrtd_auth_params_save_file( - Storage* storage, - DialogsApp* dialogs, - MrtdAuthData* auth_data, - const char* file_name, - const char* folder, - const char* extension) { - furi_assert(auth_data); - - bool saved = false; - FlipperFormat* file = flipper_format_file_alloc(storage); - FuriString* temp_str; - temp_str = furi_string_alloc(); - - do { - // Create mrtd directory if necessary - if(!storage_simply_mkdir(storage, MRTD_APP_FOLDER)) break; - - furi_string_printf(temp_str, "%s/%s%s", folder, file_name, extension); - - // Open file - if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break; - // Write header - if(!flipper_format_write_header_cstr(file, mrtd_auth_file_header, mrtd_auth_file_version)) - break; - - // Write auth method - furi_string_set(temp_str, mrtd_auth_method_string(auth_data->method)); - if(!flipper_format_write_string(file, "Method", temp_str)) break; - - // Write birth date - mrtd_date_prepare_format_string(auth_data->birth_date, temp_str); - if(!flipper_format_write_string(file, "BirthDate", temp_str)) break; - - // Write expiry date - mrtd_date_prepare_format_string(auth_data->expiry_date, temp_str); - if(!flipper_format_write_string(file, "ExpiryDate", temp_str)) break; - - // Write docnr - furi_string_set(temp_str, auth_data->doc_number); - if(!flipper_format_write_string(file, "DocNr", temp_str)) break; - - saved = true; - } while(false); - - if(!saved) { - dialog_message_show_storage_error(dialogs, "Can not save\nparams file"); - } - furi_string_free(temp_str); - flipper_format_free(file); - return saved; -} - -bool mrtd_auth_params_load( - Storage* storage, - DialogsApp* dialogs, - MrtdAuthData* auth_data, - const char* file_path, - bool show_dialog) { - furi_assert(storage); - furi_assert(dialogs); - furi_assert(auth_data); - furi_assert(file_path); - - bool parsed = false; - FlipperFormat* file = flipper_format_file_alloc(storage); - bool deprecated_version = false; - - FuriString* temp_str; - temp_str = furi_string_alloc(); - - MrtdAuthData copy; - - FURI_LOG_D(TAG, "Load auth params"); - - do { - if(!flipper_format_file_open_existing(file, file_path)) break; - - uint32_t version = 0; - if(!flipper_format_read_header(file, temp_str, &version)) break; - FURI_LOG_D(TAG, "Version: %s", furi_string_get_cstr(temp_str)); - if(furi_string_cmp_str(temp_str, mrtd_auth_file_header) || - (version != mrtd_auth_file_version)) { - deprecated_version = true; - break; - } - - if(!flipper_format_read_string(file, "Method", temp_str)) break; - FURI_LOG_D(TAG, "Method: %s", furi_string_get_cstr(temp_str)); - if(!mrtd_auth_method_parse_string(©.method, furi_string_get_cstr(temp_str))) break; - - if(!flipper_format_read_string(file, "BirthDate", temp_str)) break; - FURI_LOG_D(TAG, "BirthDate: %s", furi_string_get_cstr(temp_str)); - if(!mrtd_date_parse_format_string(©.birth_date, temp_str)) break; - - if(!flipper_format_read_string(file, "ExpiryDate", temp_str)) break; - FURI_LOG_D(TAG, "ExpiryDate: %s", furi_string_get_cstr(temp_str)); - if(!mrtd_date_parse_format_string(©.expiry_date, temp_str)) break; - - if(!flipper_format_read_string(file, "DocNr", temp_str)) break; - FURI_LOG_D(TAG, "DocNr: %s", furi_string_get_cstr(temp_str)); - strlcpy(copy.doc_number, furi_string_get_cstr(temp_str), MRTD_DOCNR_MAX_LENGTH); - - // Everything went fine. Save copy to pointed auth data - *auth_data = copy; - parsed = true; - } while(false); - - FURI_LOG_D(TAG, "Load done, success: %d", parsed); - - if(!parsed && show_dialog) { - if(deprecated_version) { - dialog_message_show_storage_error(dialogs, "File format deprecated"); - } else { - dialog_message_show_storage_error(dialogs, "Can not parse\nfile"); - } - } - - furi_string_free(temp_str); - flipper_format_free(file); - return parsed; -} diff --git a/lib/nfc/protocols/mrtd.h b/lib/nfc/protocols/mrtd.h deleted file mode 100644 index 2d43ed450..000000000 --- a/lib/nfc/protocols/mrtd.h +++ /dev/null @@ -1,44 +0,0 @@ -#pragma once - -#include -#include - -#define MRTD_APP_FOLDER "/any/nfc/mrtd" -#define MRTD_APP_EXTENSION ".mrtd" - -typedef struct { - FuriHalNfcTxRxContext* tx_rx; - MrtdData* mrtd_data; - uint16_t file_offset; - uint8_t ksenc[16]; - uint8_t ksmac[16]; - uint64_t ssc_long; // TODO: rename without _long - - bool secure_messaging; -} MrtdApplication; - -//TODO: description -MrtdApplication* mrtd_alloc_init(FuriHalNfcTxRxContext* tx_rx, MrtdData* mrtd_data); -bool mrtd_select_app(MrtdApplication* app, AIDValue aid); -bool mrtd_authenticate(MrtdApplication* app); -bool mrtd_read_parse_file(MrtdApplication* app, EFFile file); - -bool mrtd_auth_params_save( - Storage* storage, - DialogsApp* dialogs, - MrtdAuthData* auth_data, - const char* file_name); -bool mrtd_auth_params_save_file( - Storage* storage, - DialogsApp* dialogs, - MrtdAuthData* auth_data, - const char* file_name, - const char* folder, - const char* extension); - -bool mrtd_auth_params_load( - Storage* storage, - DialogsApp* dialogs, - MrtdAuthData* auth_data, - const char* file_path, - bool show_dialog); diff --git a/lib/nfc/protocols/nfca_trans_rx.c b/lib/nfc/protocols/nfca_trans_rx.c deleted file mode 100644 index 28737fa2d..000000000 --- a/lib/nfc/protocols/nfca_trans_rx.c +++ /dev/null @@ -1,169 +0,0 @@ -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nfca_trans_rx.h" - -#define TAG "NfcA-trans-rx" - -void nfca_trans_rx_init(NfcaTransRxState* state) { - FURI_LOG_D(TAG, "Starting NfcA transparent rx"); - - st25r3916ExecuteCommand(ST25R3916_CMD_STOP); - st25r3916WriteRegister(ST25R3916_REG_OP_CONTROL, 0xC3); - st25r3916WriteRegister(ST25R3916_REG_MODE, 0x88); - st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE); - - furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc); - - /* allocate a 512 edge buffer, more than enough */ - state->reader_signal = pulse_reader_alloc(&gpio_spi_r_miso, 512); - /* timebase shall be 1 ns */ - pulse_reader_set_timebase(state->reader_signal, PulseReaderUnitNanosecond); - - pulse_reader_start(state->reader_signal); - - /* set start values */ - state->bits_received = 0; - state->have_sof = false; - state->valid_frame = false; -} - -void nfca_trans_rx_deinit(NfcaTransRxState* state) { - furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); - pulse_reader_free(state->reader_signal); -} - -void nfca_trans_rx_pause(NfcaTransRxState* state) { - pulse_reader_stop(state->reader_signal); -} - -void nfca_trans_rx_continue(NfcaTransRxState* state) { - pulse_reader_start(state->reader_signal); -} - -static void nfca_bit_received(NfcaTransRxState* state, uint8_t bit) { - /* According to ISO14443-3 short frames have 7 bits and standard 9 bits per byte, - where the 9th bit is odd parity. Data is transmitted LSB first. */ - uint32_t byte_num = (state->bits_received / 9); - uint32_t bit_num = (state->bits_received % 9); - - if(byte_num >= NFCA_FRAME_LENGTH) { - return; - } - - if(bit_num == 8) { - uint32_t parity_value = 1 << (state->bits_received / 9); - state->parity_bits &= ~parity_value; - state->parity_bits |= bit ? parity_value : 0; - } else { - uint32_t bit_value = 1 << bit_num; - state->frame_data[byte_num] &= ~bit_value; - state->frame_data[byte_num] |= bit ? bit_value : 0; - } - - state->bits_received++; -} - -bool nfca_trans_rx_loop(NfcaTransRxState* state, uint32_t timeout_ms) { - furi_assert(state); - - state->valid_frame = false; - state->have_sof = false; - state->bits_received = 0; - - bool done = false; - - uint32_t timeout_us = timeout_ms * 1000; - - while(!done) { - uint32_t nsec = pulse_reader_receive(state->reader_signal, timeout_us); - - bool eof = state->have_sof && (nsec >= (2 * NFCA_TB)); - bool lost_pulse = false; - - if(state->have_sof && nsec == PULSE_READER_LOST_EDGE) { - nsec = NFCA_T1; - lost_pulse = true; - } else if(nsec == PULSE_READER_NO_EDGE) { - done = true; - } - - if(IS_T1(nsec) || eof) { - timeout_us = (3 * NFCA_TB) / 1000; - if(!state->have_sof) { - state->frame_time = -(NFCA_TB - nsec); - state->have_sof = true; - state->valid_frame = false; - state->bits_received = 0; - state->debug_pos = 0; - if(lost_pulse) { - state->frame_time -= nsec; - } - continue; - } - - if(state->frame_time > NFCA_TB_MIN) { - state->frame_time -= NFCA_TB; - nfca_bit_received(state, 0); - } - - if(IS_ZERO(state->frame_time)) { - state->frame_time = -(NFCA_TB - nsec); - nfca_bit_received(state, 0); - } else if(IS_TX(state->frame_time)) { - state->frame_time = -(NFCA_TX - nsec); - nfca_bit_received(state, 1); - } else { - if(eof) { - state->have_sof = false; - state->valid_frame = true; - done = true; - } else { - } - } - } else { - if(!state->have_sof) { - if(IS_TB(nsec)) { - state->frame_time = 0; - state->have_sof = true; - state->valid_frame = false; - state->bits_received = 0; - state->debug_pos = 0; - if(lost_pulse) { - state->frame_time -= nsec; - } - continue; - } else { - state->frame_time = 0; - } - } else { - state->frame_time += nsec; - } - } - - if(lost_pulse) { - state->frame_time -= nsec; - } - } - - if(state->valid_frame) { - if(state->bits_received > 7) { - /* a last 0-bit will look like a missing bit */ - if((state->bits_received % 9) == 8) { - nfca_bit_received(state, 0); - state->bits_received++; - } - } - } - - return state->valid_frame; -} diff --git a/lib/nfc/protocols/nfca_trans_rx.h b/lib/nfc/protocols/nfca_trans_rx.h deleted file mode 100644 index cf6d428ec..000000000 --- a/lib/nfc/protocols/nfca_trans_rx.h +++ /dev/null @@ -1,53 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include - -#include "nfc_util.h" - -/* assume fc/128 */ -#define NFCA_FC (13560000.0f) /* MHz */ -#define NFCA_FC_K ((uint32_t)(NFCA_FC / 1000)) /* kHz */ -#define NFCA_T1 (28.0f / NFCA_FC * 1000000000) -#define NFCA_T1_MIN (24.0f / NFCA_FC * 1000000000) -#define NFCA_T1_MAX (41.0f / NFCA_FC * 1000000000) -#define NFCA_TX (64.0f / NFCA_FC * 1000000000) /* 4.7198 µs */ -#define NFCA_TX_MIN (0.90f * NFCA_TX) -#define NFCA_TX_MAX (1.10f * NFCA_TX) -#define NFCA_TB (128.0f / NFCA_FC * 1000000000) /* 9.4395 µs */ -#define NFCA_TB_MIN (0.80f * NFCA_TB) -#define NFCA_TB_MAX (1.20f * NFCA_TB) - -#define IS_T1(x) ((x) >= NFCA_T1_MIN && (x) <= NFCA_T1_MAX) -#define IS_TX(x) ((x) >= NFCA_TX_MIN && (x) <= NFCA_TX_MAX) -#define IS_TB(x) ((x) >= NFCA_TB_MIN && (x) <= NFCA_TB_MAX) -#define IS_ZERO(x) ((x) >= -NFCA_T1_MIN / 2 && (x) <= NFCA_T1_MIN / 2) - -#define DIGITAL_SIGNAL_UNIT_S (100000000000.0f) -#define DIGITAL_SIGNAL_UNIT_US (100000.0f) - -#define NFCA_FRAME_LENGTH 32 -#define NFCA_DEBUG_LENGTH 128 - -typedef struct { - bool have_sof; - bool valid_frame; - int32_t frame_time; - size_t bits_received; - uint8_t frame_data[NFCA_FRAME_LENGTH]; - uint32_t debug_buffer[NFCA_DEBUG_LENGTH]; - size_t debug_pos; - uint32_t parity_bits; - PulseReader* reader_signal; -} NfcaTransRxState; - -bool nfca_trans_rx_loop(NfcaTransRxState* state, uint32_t timeout_ms); -void nfca_trans_rx_deinit(NfcaTransRxState* state); -void nfca_trans_rx_init(NfcaTransRxState* state); - -void nfca_trans_rx_pause(NfcaTransRxState* state); -void nfca_trans_rx_continue(NfcaTransRxState* state); \ No newline at end of file diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c deleted file mode 100644 index 435a368f5..000000000 --- a/lib/nfc/protocols/nfcv.c +++ /dev/null @@ -1,827 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "nfcv.h" -#include "nfc_util.h" -#include "slix.h" - -#define TAG "NfcV" - -ReturnCode nfcv_inventory(uint8_t* uid) { - uint16_t received = 0; - rfalNfcvInventoryRes res; - ReturnCode ret = ERR_NONE; - - for(int tries = 0; tries < 5; tries++) { - /* TODO: needs proper abstraction via fury_hal(_ll)_* */ - ret = rfalNfcvPollerInventory(RFAL_NFCV_NUM_SLOTS_1, 0, NULL, &res, &received); - - if(ret == ERR_NONE) { - break; - } - } - - if(ret == ERR_NONE) { - if(uid != NULL) { - memcpy(uid, res.UID, 8); - } - } - - return ret; -} - -ReturnCode nfcv_read_blocks(NfcVReader* reader, NfcVData* nfcv_data) { - UNUSED(reader); - - uint16_t received = 0; - for(size_t block = 0; block < nfcv_data->block_num; block++) { - uint8_t rxBuf[32]; - FURI_LOG_D(TAG, "Reading block %d/%d", block, (nfcv_data->block_num - 1)); - - ReturnCode ret = ERR_NONE; - for(int tries = 0; tries < 5; tries++) { - ret = rfalNfcvPollerReadSingleBlock( - RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, block, rxBuf, sizeof(rxBuf), &received); - - if(ret == ERR_NONE) { - break; - } - } - if(ret != ERR_NONE) { - FURI_LOG_D(TAG, "failed to read: %d", ret); - return ret; - } - memcpy( - &(nfcv_data->data[block * nfcv_data->block_size]), &rxBuf[1], nfcv_data->block_size); - FURI_LOG_D( - TAG, - " %02X %02X %02X %02X", - nfcv_data->data[block * nfcv_data->block_size + 0], - nfcv_data->data[block * nfcv_data->block_size + 1], - nfcv_data->data[block * nfcv_data->block_size + 2], - nfcv_data->data[block * nfcv_data->block_size + 3]); - } - - return ERR_NONE; -} - -ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) { - uint8_t rxBuf[32]; - uint16_t received = 0; - ReturnCode ret = ERR_NONE; - - FURI_LOG_D(TAG, "Read SYSTEM INFORMATION..."); - - for(int tries = 0; tries < 5; tries++) { - /* TODO: needs proper abstraction via fury_hal(_ll)_* */ - ret = rfalNfcvPollerGetSystemInformation( - RFAL_NFCV_REQ_FLAG_DEFAULT, NULL, rxBuf, sizeof(rxBuf), &received); - - if(ret == ERR_NONE) { - break; - } - } - - if(ret == ERR_NONE) { - nfc_data->type = FuriHalNfcTypeV; - nfc_data->uid_len = 8; - /* UID is stored reversed in this response */ - for(int pos = 0; pos < nfc_data->uid_len; pos++) { - nfc_data->uid[pos] = rxBuf[2 + (7 - pos)]; - } - nfcv_data->dsfid = rxBuf[10]; - nfcv_data->afi = rxBuf[11]; - nfcv_data->block_num = rxBuf[12] + 1; - nfcv_data->block_size = rxBuf[13] + 1; - nfcv_data->ic_ref = rxBuf[14]; - FURI_LOG_D( - TAG, - " UID: %02X %02X %02X %02X %02X %02X %02X %02X", - 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]); - FURI_LOG_D( - TAG, - " DSFID %d, AFI %d, Blocks %d, Size %d, IC Ref %d", - nfcv_data->dsfid, - nfcv_data->afi, - nfcv_data->block_num, - nfcv_data->block_size, - nfcv_data->ic_ref); - return ret; - } - FURI_LOG_D(TAG, "Failed: %d", ret); - - return ret; -} - -bool nfcv_read_card(NfcVReader* reader, FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) { - furi_assert(reader); - furi_assert(nfc_data); - furi_assert(nfcv_data); - - if(nfcv_read_sysinfo(nfc_data, nfcv_data) != ERR_NONE) { - return false; - } - - if(nfcv_read_blocks(reader, nfcv_data) != ERR_NONE) { - return false; - } - - if(slix_check_card_type(nfc_data)) { - FURI_LOG_I(TAG, "NXP SLIX detected"); - nfcv_data->sub_type = NfcVTypeSlix; - } else if(slix2_check_card_type(nfc_data)) { - FURI_LOG_I(TAG, "NXP SLIX2 detected"); - nfcv_data->sub_type = NfcVTypeSlix2; - } else if(slix_s_check_card_type(nfc_data)) { - FURI_LOG_I(TAG, "NXP SLIX-S detected"); - nfcv_data->sub_type = NfcVTypeSlixS; - } else if(slix_l_check_card_type(nfc_data)) { - FURI_LOG_I(TAG, "NXP SLIX-L detected"); - nfcv_data->sub_type = NfcVTypeSlixL; - } else { - nfcv_data->sub_type = NfcVTypePlain; - } - - return true; -} - -void nfcv_crc(uint8_t* data, uint32_t length) { - uint32_t reg = 0xFFFF; - - for(size_t i = 0; i < length; i++) { - reg = reg ^ ((uint32_t)data[i]); - for(size_t j = 0; j < 8; j++) { - if(reg & 0x0001) { - reg = (reg >> 1) ^ 0x8408; - } else { - reg = (reg >> 1); - } - } - } - - uint16_t crc = ~(uint16_t)(reg & 0xffff); - - data[length + 0] = crc & 0xFF; - data[length + 1] = crc >> 8; -} - -void nfcv_emu_free(NfcVData* nfcv_data) { - if(nfcv_data->emu_air.nfcv_signal) { - digital_sequence_free(nfcv_data->emu_air.nfcv_signal); - } - if(nfcv_data->emu_air.nfcv_resp_unmod_256) { - digital_signal_free(nfcv_data->emu_air.nfcv_resp_unmod_256); - } - if(nfcv_data->emu_air.nfcv_resp_pulse_32) { - digital_signal_free(nfcv_data->emu_air.nfcv_resp_pulse_32); - } - if(nfcv_data->emu_air.nfcv_resp_one) { - digital_signal_free(nfcv_data->emu_air.nfcv_resp_one); - } - if(nfcv_data->emu_air.nfcv_resp_zero) { - digital_signal_free(nfcv_data->emu_air.nfcv_resp_zero); - } - if(nfcv_data->emu_air.nfcv_resp_sof) { - digital_signal_free(nfcv_data->emu_air.nfcv_resp_sof); - } - if(nfcv_data->emu_air.nfcv_resp_eof) { - digital_signal_free(nfcv_data->emu_air.nfcv_resp_eof); - } - if(nfcv_data->emu_air.reader_signal) { - pulse_reader_free(nfcv_data->emu_air.reader_signal); - } - - nfcv_data->emu_air.nfcv_signal = NULL; - nfcv_data->emu_air.nfcv_resp_unmod_256 = NULL; - nfcv_data->emu_air.nfcv_resp_pulse_32 = NULL; - nfcv_data->emu_air.nfcv_resp_one = NULL; - nfcv_data->emu_air.nfcv_resp_zero = NULL; - nfcv_data->emu_air.nfcv_resp_sof = NULL; - nfcv_data->emu_air.nfcv_resp_eof = NULL; - nfcv_data->emu_air.reader_signal = NULL; -} - -void nfcv_emu_alloc(NfcVData* nfcv_data) { - if(!nfcv_data->emu_air.nfcv_signal) { - /* assuming max frame length is 255 bytes */ - nfcv_data->emu_air.nfcv_signal = digital_sequence_alloc(8 * 255 + 2, &gpio_spi_r_mosi); - } - - if(!nfcv_data->emu_air.nfcv_resp_unmod_256) { - /* unmodulated 256/fc signal as building block */ - nfcv_data->emu_air.nfcv_resp_unmod_256 = digital_signal_alloc(4); - nfcv_data->emu_air.nfcv_resp_unmod_256->start_level = false; - nfcv_data->emu_air.nfcv_resp_unmod_256->edge_timings[0] = - (uint32_t)(NFCV_RESP_SUBC1_UNMOD_256 * DIGITAL_SIGNAL_UNIT_S); - nfcv_data->emu_air.nfcv_resp_unmod_256->edge_cnt = 1; - } - if(!nfcv_data->emu_air.nfcv_resp_pulse_32) { - /* modulated fc/32 pulse as building block */ - nfcv_data->emu_air.nfcv_resp_pulse_32 = digital_signal_alloc(4); - nfcv_data->emu_air.nfcv_resp_pulse_32->start_level = true; - nfcv_data->emu_air.nfcv_resp_pulse_32->edge_timings[0] = - (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S); - nfcv_data->emu_air.nfcv_resp_pulse_32->edge_timings[1] = - (uint32_t)(NFCV_RESP_SUBC1_PULSE_32 * DIGITAL_SIGNAL_UNIT_S); - nfcv_data->emu_air.nfcv_resp_pulse_32->edge_cnt = 2; - } - if(!nfcv_data->emu_air.nfcv_resp_one) { - /* logical one: 256/fc unmodulated then 8 pulses fc/32 */ - nfcv_data->emu_air.nfcv_resp_one = digital_signal_alloc(24); - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_one, nfcv_data->emu_air.nfcv_resp_unmod_256); - for(size_t i = 0; i < 8; i++) { - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_one, nfcv_data->emu_air.nfcv_resp_pulse_32); - } - } - if(!nfcv_data->emu_air.nfcv_resp_zero) { - /* logical zero: 8 pulses fc/32 then 256/fc unmodulated */ - nfcv_data->emu_air.nfcv_resp_zero = digital_signal_alloc(24); - for(size_t i = 0; i < 8; i++) { - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_zero, nfcv_data->emu_air.nfcv_resp_pulse_32); - } - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_zero, nfcv_data->emu_air.nfcv_resp_unmod_256); - } - if(!nfcv_data->emu_air.nfcv_resp_sof) { - /* SOF: unmodulated 768/fc, 24 pulses fc/32, logic 1 */ - nfcv_data->emu_air.nfcv_resp_sof = digital_signal_alloc(128); - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_sof, nfcv_data->emu_air.nfcv_resp_unmod_256); - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_sof, nfcv_data->emu_air.nfcv_resp_unmod_256); - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_sof, nfcv_data->emu_air.nfcv_resp_unmod_256); - for(size_t i = 0; i < 24; i++) { - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_sof, nfcv_data->emu_air.nfcv_resp_pulse_32); - } - digital_signal_append(nfcv_data->emu_air.nfcv_resp_sof, nfcv_data->emu_air.nfcv_resp_one); - } - if(!nfcv_data->emu_air.nfcv_resp_eof) { - /* EOF: logic 0, 24 pulses fc/32, unmodulated 768/fc */ - nfcv_data->emu_air.nfcv_resp_eof = digital_signal_alloc(128); - digital_signal_append(nfcv_data->emu_air.nfcv_resp_eof, nfcv_data->emu_air.nfcv_resp_zero); - for(size_t i = 0; i < 24; i++) { - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_eof, nfcv_data->emu_air.nfcv_resp_pulse_32); - } - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_eof, nfcv_data->emu_air.nfcv_resp_unmod_256); - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_eof, nfcv_data->emu_air.nfcv_resp_unmod_256); - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_eof, nfcv_data->emu_air.nfcv_resp_unmod_256); - /* add extra silence */ - digital_signal_append( - nfcv_data->emu_air.nfcv_resp_eof, nfcv_data->emu_air.nfcv_resp_unmod_256); - } - - digital_sequence_set_signal( - nfcv_data->emu_air.nfcv_signal, NFCV_SIG_SOF, nfcv_data->emu_air.nfcv_resp_sof); - digital_sequence_set_signal( - nfcv_data->emu_air.nfcv_signal, NFCV_SIG_BIT0, nfcv_data->emu_air.nfcv_resp_zero); - digital_sequence_set_signal( - nfcv_data->emu_air.nfcv_signal, NFCV_SIG_BIT1, nfcv_data->emu_air.nfcv_resp_one); - digital_sequence_set_signal( - nfcv_data->emu_air.nfcv_signal, NFCV_SIG_EOF, nfcv_data->emu_air.nfcv_resp_eof); -} - -void nfcv_emu_send( - FuriHalNfcTxRxContext* tx_rx, - NfcVData* nfcv, - uint8_t* data, - uint8_t length, - NfcVSendFlags flags, - uint32_t send_time) { - /* picked default value (0) to match the most common format */ - if(!flags) { - flags = NfcVSendFlagsSof | NfcVSendFlagsCrc | NfcVSendFlagsEof | - NfcVSendFlagsOneSubcarrier | NfcVSendFlagsHighRate; - } - - if(flags & NfcVSendFlagsCrc) { - nfcv_crc(data, length); - length += 2; - } - - digital_sequence_clear(nfcv->emu_air.nfcv_signal); - - if(flags & NfcVSendFlagsSof) { - digital_sequence_add(nfcv->emu_air.nfcv_signal, NFCV_SIG_SOF); - } - - for(int bit_total = 0; bit_total < length * 8; bit_total++) { - uint32_t byte_pos = bit_total / 8; - uint32_t bit_pos = bit_total % 8; - uint8_t bit_val = 0x01 << bit_pos; - - digital_sequence_add( - nfcv->emu_air.nfcv_signal, (data[byte_pos] & bit_val) ? NFCV_SIG_BIT1 : NFCV_SIG_BIT0); - } - - if(flags & NfcVSendFlagsEof) { - digital_sequence_add(nfcv->emu_air.nfcv_signal, NFCV_SIG_EOF); - } - - FURI_CRITICAL_ENTER(); - digital_sequence_set_sendtime(nfcv->emu_air.nfcv_signal, send_time); - digital_sequence_send(nfcv->emu_air.nfcv_signal); - FURI_CRITICAL_EXIT(); - furi_hal_gpio_write(&gpio_spi_r_mosi, false); - - if(tx_rx->sniff_tx) { - tx_rx->sniff_tx(data, length * 8, false, tx_rx->sniff_context); - } -} - -static void nfcv_revuidcpy(uint8_t* dst, uint8_t* src) { - for(int pos = 0; pos < 8; pos++) { - dst[pos] = src[7 - pos]; - } -} - -static int nfcv_revuidcmp(uint8_t* dst, uint8_t* src) { - for(int pos = 0; pos < 8; pos++) { - if(dst[pos] != src[7 - pos]) { - return 1; - } - } - return 0; -} - -void nfcv_emu_handle_packet( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - void* nfcv_data_in) { - NfcVData* nfcv_data = (NfcVData*)nfcv_data_in; - NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx; - - if(nfcv_data->frame_length < 2) { - return; - } - - /* parse the frame data for the upcoming part 3 handling */ - ctx->flags = nfcv_data->frame[0]; - ctx->command = nfcv_data->frame[1]; - ctx->addressed = !(ctx->flags & RFAL_NFCV_REQ_FLAG_INVENTORY) && - (ctx->flags & RFAL_NFCV_REQ_FLAG_ADDRESS); - ctx->advanced = (ctx->command >= 0xA0); - ctx->address_offset = 2 + (ctx->advanced ? 1 : 0); - ctx->payload_offset = ctx->address_offset + (ctx->addressed ? 8 : 0); - ctx->response_flags = NfcVSendFlagsNormal; - ctx->send_time = nfcv_data->eof_timestamp + NFCV_FDT_FC(4130); - - /* standard behavior is implemented */ - if(ctx->addressed) { - uint8_t* address = &nfcv_data->frame[ctx->address_offset]; - if(nfcv_revuidcmp(address, nfc_data->uid)) { - FURI_LOG_D(TAG, "addressed command 0x%02X, but not for us:", ctx->command); - FURI_LOG_D( - TAG, - " dest: %02X%02X%02X%02X%02X%02X%02X%02X", - address[7], - address[6], - address[5], - address[4], - address[3], - address[2], - address[1], - address[0]); - FURI_LOG_D( - TAG, - " our UID: %02X%02X%02X%02X%02X%02X%02X%02X", - 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]); - return; - } - } - - /* then give control to the card subtype specific protocol filter */ - if(ctx->emu_protocol_filter != NULL) { - if(ctx->emu_protocol_filter(tx_rx, nfc_data, nfcv_data)) { - if(strlen(nfcv_data->last_command) > 0) { - FURI_LOG_D( - TAG, "Received command %s (handled by filter)", nfcv_data->last_command); - } - return; - } - } - - switch(ctx->command) { - case ISO15693_INVENTORY: { - ctx->response_buffer[0] = ISO15693_NOERROR; - ctx->response_buffer[1] = nfcv_data->dsfid; - nfcv_revuidcpy(&ctx->response_buffer[2], nfc_data->uid); - - nfcv_emu_send( - tx_rx, nfcv_data, ctx->response_buffer, 10, ctx->response_flags, ctx->send_time); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "INVENTORY"); - break; - } - - case ISO15693_STAYQUIET: { - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "STAYQUIET"); - break; - } - - case ISO15693_LOCKBLOCK: { - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "LOCKBLOCK"); - break; - } - - case ISO15693_SELECT: { - ctx->response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send( - tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SELECT"); - break; - } - - case ISO15693_READ_MULTI_BLOCK: - case ISO15693_READBLOCK: { - uint8_t block = nfcv_data->frame[ctx->payload_offset]; - uint8_t blocks = 1; - - if(ctx->command == ISO15693_READ_MULTI_BLOCK) { - blocks = nfcv_data->frame[ctx->payload_offset + 1] + 1; - } - - if(block + blocks > nfcv_data->block_num) { - ctx->response_buffer[0] = ISO15693_ERROR_CMD_NOT_REC; - nfcv_emu_send( - tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time); - } else { - ctx->response_buffer[0] = ISO15693_NOERROR; - memcpy( - &ctx->response_buffer[1], - &nfcv_data->data[nfcv_data->block_size * block], - nfcv_data->block_size * blocks); - nfcv_emu_send( - tx_rx, - nfcv_data, - ctx->response_buffer, - 1 + nfcv_data->block_size * blocks, - ctx->response_flags, - ctx->send_time); - } - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "READ BLOCK %d", block); - break; - } - - case ISO15693_WRITE_MULTI_BLOCK: - case ISO15693_WRITEBLOCK: { - uint8_t block = nfcv_data->frame[ctx->payload_offset]; - uint8_t blocks = 1; - uint8_t data_pos = 1; - - if(ctx->command == ISO15693_WRITE_MULTI_BLOCK) { - blocks = nfcv_data->frame[ctx->payload_offset + 1] + 1; - data_pos++; - } - - uint8_t* data = &nfcv_data->frame[ctx->payload_offset + data_pos]; - uint32_t data_len = nfcv_data->block_size * blocks; - - if(block + blocks > nfcv_data->block_num || - ctx->payload_offset + data_len + 2 > nfcv_data->frame_length) { - ctx->response_buffer[0] = ISO15693_ERROR_CMD_NOT_REC; - } else { - ctx->response_buffer[0] = ISO15693_NOERROR; - memcpy( - &nfcv_data->data[nfcv_data->block_size * block], - &nfcv_data->frame[ctx->payload_offset + data_pos], - data_len); - } - nfcv_emu_send( - tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time); - - if(ctx->command == ISO15693_WRITE_MULTI_BLOCK) { - snprintf( - nfcv_data->last_command, - sizeof(nfcv_data->last_command), - "WRITE MULTI BLOCK %d, %d blocks", - block, - blocks); - } else { - snprintf( - nfcv_data->last_command, - sizeof(nfcv_data->last_command), - "WRITE BLOCK %d <- %02X %02X %02X %02X", - block, - data[0], - data[1], - data[2], - data[3]); - } - break; - } - - case ISO15693_GET_SYSTEM_INFO: { - ctx->response_buffer[0] = ISO15693_NOERROR; - ctx->response_buffer[1] = 0x0F; - nfcv_revuidcpy(&ctx->response_buffer[2], nfc_data->uid); - ctx->response_buffer[10] = nfcv_data->dsfid; /* DSFID */ - ctx->response_buffer[11] = nfcv_data->afi; /* AFI */ - ctx->response_buffer[12] = nfcv_data->block_num - 1; /* number of blocks */ - ctx->response_buffer[13] = nfcv_data->block_size - 1; /* block size */ - ctx->response_buffer[14] = nfcv_data->ic_ref; /* IC reference */ - - nfcv_emu_send( - tx_rx, nfcv_data, ctx->response_buffer, 15, ctx->response_flags, ctx->send_time); - snprintf(nfcv_data->last_command, sizeof(nfcv_data->last_command), "SYSTEMINFO"); - break; - } - - default: - snprintf( - nfcv_data->last_command, - sizeof(nfcv_data->last_command), - "unsupported: %02X", - ctx->command); - break; - } - - if(strlen(nfcv_data->last_command) > 0) { - FURI_LOG_D(TAG, "Received command %s", nfcv_data->last_command); - } -} - -void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data) { - nfcv_emu_alloc(nfcv_data); - rfal_platform_spi_acquire(); - /* configure for transparent and passive mode */ - st25r3916ExecuteCommand(ST25R3916_CMD_STOP); - /* set enable, rx_enable and field detector enable */ - st25r3916WriteRegister(ST25R3916_REG_OP_CONTROL, 0xC3); - /* target mode: ISO14443 passive mode */ - st25r3916WriteRegister(ST25R3916_REG_MODE, 0x88); - /* let us modulate the field using MOSI, read modulation using MISO */ - st25r3916ExecuteCommand(ST25R3916_CMD_TRANSPARENT_MODE); - - furi_hal_spi_bus_handle_deinit(&furi_hal_spi_bus_handle_nfc); - - /* if not set already, initialize the default protocol handler */ - if(!nfcv_data->emu_protocol_ctx) { - nfcv_data->emu_protocol_ctx = malloc(sizeof(NfcVEmuProtocolCtx)); - nfcv_data->emu_protocol_handler = &nfcv_emu_handle_packet; - } - - FURI_LOG_D(TAG, "Starting NfcV emulation"); - FURI_LOG_D( - TAG, - " UID: %02X %02X %02X %02X %02X %02X %02X %02X", - 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]); - - switch(nfcv_data->sub_type) { - case NfcVTypeSlixL: - FURI_LOG_D(TAG, " Card type: SLIX-L"); - slix_l_prepare(nfcv_data); - break; - case NfcVTypeSlixS: - FURI_LOG_D(TAG, " Card type: SLIX-S"); - slix_s_prepare(nfcv_data); - break; - case NfcVTypeSlix2: - FURI_LOG_D(TAG, " Card type: SLIX2"); - slix2_prepare(nfcv_data); - break; - case NfcVTypeSlix: - FURI_LOG_D(TAG, " Card type: SLIX"); - slix_prepare(nfcv_data); - break; - case NfcVTypePlain: - FURI_LOG_D(TAG, " Card type: Plain"); - break; - } - - /* allocate a 512 edge buffer, more than enough */ - nfcv_data->emu_air.reader_signal = pulse_reader_alloc(&gpio_spi_r_miso, 512); - /* timebase shall be 1 ns */ - pulse_reader_set_timebase(nfcv_data->emu_air.reader_signal, PulseReaderUnitNanosecond); - /* and configure to already calculate the number of bits */ - pulse_reader_set_bittime(nfcv_data->emu_air.reader_signal, PULSE_DURATION_NS); - pulse_reader_start(nfcv_data->emu_air.reader_signal); -} - -void nfcv_emu_deinit(NfcVData* nfcv_data) { - furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); - rfal_platform_spi_release(); - nfcv_emu_free(nfcv_data); - - if(nfcv_data->emu_protocol_ctx) { - free(nfcv_data->emu_protocol_ctx); - nfcv_data->emu_protocol_ctx = NULL; - } -} - -bool nfcv_emu_loop( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - NfcVData* nfcv_data, - uint32_t timeout_ms) { - bool ret = false; - uint32_t frame_state = NFCV_FRAME_STATE_SOF1; - uint32_t periods_previous = 0; - uint8_t frame_payload[128]; - uint32_t frame_pos = 0; - uint32_t byte_value = 0; - uint32_t bits_received = 0; - char reset_reason[128]; - bool wait_for_pulse = false; - - while(true) { - uint32_t periods = - pulse_reader_receive(nfcv_data->emu_air.reader_signal, timeout_ms * 1000); - uint32_t timestamp = DWT->CYCCNT; - - if(periods == PULSE_READER_NO_EDGE) { - break; - } - - if(wait_for_pulse) { - wait_for_pulse = false; - if(periods != 1) { - snprintf( - reset_reason, - sizeof(reset_reason), - "SOF: Expected a single low pulse in state %lu, but got %lu", - frame_state, - periods); - frame_state = NFCV_FRAME_STATE_RESET; - } - continue; - } - - switch(frame_state) { - case NFCV_FRAME_STATE_SOF1: - if(periods == 1) { - frame_state = NFCV_FRAME_STATE_SOF2; - } else { - frame_state = NFCV_FRAME_STATE_SOF1; - break; - } - break; - - case NFCV_FRAME_STATE_SOF2: - /* waiting for the second low period, telling us about coding */ - if(periods == 6) { - frame_state = NFCV_FRAME_STATE_CODING_256; - periods_previous = 0; - wait_for_pulse = true; - } else if(periods == 4) { - frame_state = NFCV_FRAME_STATE_CODING_4; - periods_previous = 2; - wait_for_pulse = true; - } else { - snprintf( - reset_reason, - sizeof(reset_reason), - "SOF: Expected 4/6 periods, got %lu", - periods); - frame_state = NFCV_FRAME_STATE_SOF1; - } - break; - - case NFCV_FRAME_STATE_CODING_256: - if(periods_previous > periods) { - snprintf( - reset_reason, - sizeof(reset_reason), - "1oo256: Missing %lu periods from previous symbol, got %lu", - periods_previous, - periods); - frame_state = NFCV_FRAME_STATE_RESET; - break; - } - /* previous symbol left us with some pulse periods */ - periods -= periods_previous; - - if(periods > 512) { - snprintf( - reset_reason, sizeof(reset_reason), "1oo256: %lu periods is too much", periods); - frame_state = NFCV_FRAME_STATE_RESET; - break; - } - - if(periods == 2) { - frame_state = NFCV_FRAME_STATE_EOF; - break; - } - - periods_previous = 512 - (periods + 1); - byte_value = (periods - 1) / 2; - frame_payload[frame_pos++] = (uint8_t)byte_value; - - wait_for_pulse = true; - - break; - - case NFCV_FRAME_STATE_CODING_4: - if(periods_previous > periods) { - snprintf( - reset_reason, - sizeof(reset_reason), - "1oo4: Missing %lu periods from previous symbol, got %lu", - periods_previous, - periods); - frame_state = NFCV_FRAME_STATE_RESET; - break; - } - - /* previous symbol left us with some pulse periods */ - periods -= periods_previous; - periods_previous = 0; - - byte_value >>= 2; - bits_received += 2; - - if(periods == 1) { - byte_value |= 0x00 << 6; - periods_previous = 6; - } else if(periods == 3) { - byte_value |= 0x01 << 6; - periods_previous = 4; - } else if(periods == 5) { - byte_value |= 0x02 << 6; - periods_previous = 2; - } else if(periods == 7) { - byte_value |= 0x03 << 6; - periods_previous = 0; - } else if(periods == 2) { - frame_state = NFCV_FRAME_STATE_EOF; - break; - } else { - snprintf( - reset_reason, - sizeof(reset_reason), - "1oo4: Expected 1/3/5/7 low pulses, but got %lu", - periods); - frame_state = NFCV_FRAME_STATE_RESET; - break; - } - - if(bits_received >= 8) { - frame_payload[frame_pos++] = (uint8_t)byte_value; - bits_received = 0; - } - wait_for_pulse = true; - break; - } - - /* post-state-machine cleanup and reset */ - if(frame_state == NFCV_FRAME_STATE_RESET) { - frame_state = NFCV_FRAME_STATE_SOF1; - - FURI_LOG_D(TAG, "Resetting state machine, reason: '%s'", reset_reason); - } else if(frame_state == NFCV_FRAME_STATE_EOF) { - nfcv_data->frame = frame_payload; - nfcv_data->frame_length = frame_pos; - nfcv_data->eof_timestamp = timestamp; - break; - } - } - - if(frame_state == NFCV_FRAME_STATE_EOF) { - /* we know that this code uses TIM2, so stop pulse reader */ - pulse_reader_stop(nfcv_data->emu_air.reader_signal); - if(tx_rx->sniff_rx) { - tx_rx->sniff_rx(frame_payload, frame_pos * 8, false, tx_rx->sniff_context); - } - nfcv_data->emu_protocol_handler(tx_rx, nfc_data, nfcv_data); - pulse_reader_start(nfcv_data->emu_air.reader_signal); - ret = true; - } - - return ret; -} diff --git a/lib/nfc/protocols/nfcv.h b/lib/nfc/protocols/nfcv.h deleted file mode 100644 index cc0aac18c..000000000 --- a/lib/nfc/protocols/nfcv.h +++ /dev/null @@ -1,205 +0,0 @@ -#pragma once - -#include -#include - -#include -#include -#include "nfc_util.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define NFCV_FC (13560000.0f) /* MHz */ -#define NFCV_RESP_SUBC1_PULSE_32 (1.0f / (NFCV_FC / 32) / 2.0f) /* 1.1799 µs */ -#define NFCV_RESP_SUBC1_UNMOD_256 (256.0f / NFCV_FC) /* 18.8791 µs */ - -#define PULSE_DURATION_NS (128.0f * 1000000000.0f / NFCV_FC) /* ns */ - -#define DIGITAL_SIGNAL_UNIT_S (100000000000.0f) -#define DIGITAL_SIGNAL_UNIT_US (100000.0f) - -#define NFCV_TOTAL_BLOCKS_MAX 256 -#define NFCV_BLOCK_SIZE 4 -#define NFCV_MAX_DUMP_SIZE (NFCV_BLOCK_SIZE * NFCV_TOTAL_BLOCKS_MAX) - -/* helpers to calculate the send time based on DWT->CYCCNT */ -#define NFCV_FDT_USEC(usec) (usec * 64) -#define NFCV_FDT_FC(ticks) (ticks * 6400 / 1356) - -#define NFCV_FRAME_STATE_SOF1 0 -#define NFCV_FRAME_STATE_SOF2 1 -#define NFCV_FRAME_STATE_CODING_4 2 -#define NFCV_FRAME_STATE_CODING_256 3 -#define NFCV_FRAME_STATE_EOF 4 -#define NFCV_FRAME_STATE_RESET 5 - -#define NFCV_SIG_SOF 0 -#define NFCV_SIG_BIT0 1 -#define NFCV_SIG_BIT1 2 -#define NFCV_SIG_EOF 3 - -/* ISO15693 command codes */ -#define ISO15693_INVENTORY 0x01 -#define ISO15693_STAYQUIET 0x02 -#define ISO15693_READBLOCK 0x20 -#define ISO15693_WRITEBLOCK 0x21 -#define ISO15693_LOCKBLOCK 0x22 -#define ISO15693_READ_MULTI_BLOCK 0x23 -#define ISO15693_WRITE_MULTI_BLOCK 0x24 -#define ISO15693_SELECT 0x25 -#define ISO15693_RESET_TO_READY 0x26 -#define ISO15693_WRITE_AFI 0x27 -#define ISO15693_LOCK_AFI 0x28 -#define ISO15693_WRITE_DSFID 0x29 -#define ISO15693_LOCK_DSFID 0x2A -#define ISO15693_GET_SYSTEM_INFO 0x2B -#define ISO15693_READ_MULTI_SECSTATUS 0x2C - -/* ISO15693 RESPONSE ERROR CODES */ -#define ISO15693_NOERROR 0x00 -#define ISO15693_ERROR_CMD_NOT_SUP 0x01 // Command not supported -#define ISO15693_ERROR_CMD_NOT_REC 0x02 // Command not recognized (eg. parameter error) -#define ISO15693_ERROR_CMD_OPTION 0x03 // Command option not supported -#define ISO15693_ERROR_GENERIC 0x0F // No additional Info about this error -#define ISO15693_ERROR_BLOCK_UNAVAILABLE 0x10 -#define ISO15693_ERROR_BLOCK_LOCKED_ALREADY 0x11 // cannot lock again -#define ISO15693_ERROR_BLOCK_LOCKED 0x12 // cannot be changed -#define ISO15693_ERROR_BLOCK_WRITE 0x13 // Writing was unsuccessful -#define ISO15693_ERROR_BLOCL_WRITELOCK 0x14 // Locking was unsuccessful - -typedef enum { - NfcVAuthMethodManual, - NfcVAuthMethodTonieBox, -} NfcVAuthMethod; - -typedef enum { - NfcVTypePlain = 0, - NfcVTypeSlix = 1, - NfcVTypeSlixS = 2, - NfcVTypeSlixL = 3, - NfcVTypeSlix2 = 4, -} NfcVSubtype; - -typedef enum { - NfcVSendFlagsNormal = 0, - NfcVSendFlagsSof = 1 << 0, - NfcVSendFlagsCrc = 1 << 1, - NfcVSendFlagsEof = 1 << 2, - NfcVSendFlagsOneSubcarrier = 0, - NfcVSendFlagsTwoSubcarrier = 1 << 3, - NfcVSendFlagsLowRate = 0, - NfcVSendFlagsHighRate = 1 << 4 -} NfcVSendFlags; - -typedef struct { - uint8_t key_read[4]; - uint8_t key_write[4]; - uint8_t key_privacy[4]; - uint8_t key_destroy[4]; - uint8_t key_eas[4]; - uint8_t rand[2]; - bool privacy; -} NfcVSlixData; - -typedef union { - NfcVSlixData slix; -} NfcVSubtypeData; - -typedef struct { - PulseReader* reader_signal; - DigitalSignal* nfcv_resp_pulse_32; - DigitalSignal* nfcv_resp_unmod; - DigitalSignal* nfcv_resp_one; - DigitalSignal* nfcv_resp_zero; - DigitalSignal* nfcv_resp_sof; - DigitalSignal* nfcv_resp_eof; - DigitalSignal* nfcv_resp_unmod_256; - DigitalSignal* nfcv_resp_unmod_768; - DigitalSequence* nfcv_signal; -} NfcVEmuAir; - -typedef void (*NfcVEmuProtocolHandler)( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - void* nfcv_data); -typedef bool (*NfcVEmuProtocolFilter)( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - void* nfcv_data); - -typedef struct { - uint8_t flags; /* ISO15693-3 flags of the header as specified */ - uint8_t command; /* ISO15693-3 command at offset 1 as specified */ - bool addressed; /* ISO15693-3 flags: addressed frame */ - bool advanced; /* ISO15693-3 command: advanced command */ - uint8_t address_offset; /* ISO15693-3 offset of the address in frame, if addressed is set */ - uint8_t payload_offset; /* ISO15693-3 offset of the payload in frame */ - - uint8_t response_buffer[128]; /* pre-allocated response buffer */ - NfcVSendFlags response_flags; /* flags to use when sending response */ - uint32_t send_time; /* timestamp when to send the response */ - - NfcVEmuProtocolFilter emu_protocol_filter; -} NfcVEmuProtocolCtx; - -typedef struct { - /* common ISO15693 fields, being specified in ISO15693-3 */ - uint8_t dsfid; - uint8_t afi; - uint8_t ic_ref; - uint16_t block_num; - uint8_t block_size; - uint8_t data[NFCV_MAX_DUMP_SIZE]; - - /* specfic variant infos */ - NfcVSubtype sub_type; - NfcVSubtypeData sub_data; - NfcVAuthMethod auth_method; - - /* precalced air level data */ - NfcVEmuAir emu_air; - - uint8_t* frame; /* ISO15693-2 incoming raw data from air layer */ - uint8_t frame_length; /* ISO15693-2 length of incoming data */ - uint32_t eof_timestamp; /* ISO15693-2 EOF timestamp, read from DWT->CYCCNT */ - - /* handler for the protocol layer as specified in ISO15693-3 */ - NfcVEmuProtocolHandler emu_protocol_handler; - void* emu_protocol_ctx; - - /* runtime data */ - char last_command[128]; - char error[32]; -} NfcVData; - -typedef struct { - uint16_t blocks_to_read; - int16_t blocks_read; -} NfcVReader; - -ReturnCode nfcv_read_blocks(NfcVReader* reader, NfcVData* data); -ReturnCode nfcv_read_sysinfo(FuriHalNfcDevData* nfc_data, NfcVData* data); -ReturnCode nfcv_inventory(uint8_t* uid); -bool nfcv_read_card(NfcVReader* reader, FuriHalNfcDevData* nfc_data, NfcVData* data); - -void nfcv_emu_init(FuriHalNfcDevData* nfc_data, NfcVData* nfcv_data); -void nfcv_emu_deinit(NfcVData* nfcv_data); -bool nfcv_emu_loop( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - NfcVData* nfcv_data, - uint32_t timeout_ms); -void nfcv_emu_send( - FuriHalNfcTxRxContext* tx_rx, - NfcVData* nfcv, - uint8_t* data, - uint8_t length, - NfcVSendFlags flags, - uint32_t send_time); - -#ifdef __cplusplus -} -#endif diff --git a/lib/nfc/protocols/slix.c b/lib/nfc/protocols/slix.c deleted file mode 100644 index e61c70919..000000000 --- a/lib/nfc/protocols/slix.c +++ /dev/null @@ -1,407 +0,0 @@ - -#include -#include "nfcv.h" -#include "slix.h" -#include "nfc_util.h" -#include -#include "furi_hal_nfc.h" -#include - -#define TAG "SLIX" - -static uint32_t slix_read_be(uint8_t* data, uint32_t length) { - uint32_t value = 0; - - for(uint32_t pos = 0; pos < length; pos++) { - value <<= 8; - value |= data[pos]; - } - - return value; -} - -uint8_t slix_get_ti(FuriHalNfcDevData* nfc_data) { - return (nfc_data->uid[3] >> 3) & 3; -} - -bool slix_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x01) && - slix_get_ti(nfc_data) == 2) { - return true; - } - return false; -} - -bool slix2_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x01) && - slix_get_ti(nfc_data) == 1) { - return true; - } - return false; -} - -bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x02)) { - return true; - } - return false; -} - -bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data) { - if((nfc_data->uid[0] == 0xE0) && (nfc_data->uid[1] == 0x04) && (nfc_data->uid[2] == 0x03)) { - return true; - } - return false; -} - -ReturnCode slix_get_random(NfcVData* data) { - uint16_t received = 0; - uint8_t rxBuf[32]; - - ReturnCode ret = rfalNfcvPollerTransceiveReq( - ISO15693_CMD_NXP_GET_RANDOM_NUMBER, - RFAL_NFCV_REQ_FLAG_DEFAULT, - ISO15693_MANUFACTURER_NXP, - NULL, - NULL, - 0, - rxBuf, - sizeof(rxBuf), - &received); - - if(ret == ERR_NONE) { - if(received != 3) { - return ERR_PROTO; - } - if(data != NULL) { - data->sub_data.slix.rand[0] = rxBuf[2]; - data->sub_data.slix.rand[1] = rxBuf[1]; - } - } - - return ret; -} - -ReturnCode slix_unlock(NfcVData* data, uint32_t password_id) { - furi_assert(rand); - - uint16_t received = 0; - uint8_t rxBuf[32]; - uint8_t cmd_set_pass[] = { - password_id, - data->sub_data.slix.rand[1], - data->sub_data.slix.rand[0], - data->sub_data.slix.rand[1], - data->sub_data.slix.rand[0]}; - uint8_t* password = NULL; - - switch(password_id) { - case SLIX_PASS_READ: - password = data->sub_data.slix.key_read; - break; - case SLIX_PASS_WRITE: - password = data->sub_data.slix.key_write; - break; - case SLIX_PASS_PRIVACY: - password = data->sub_data.slix.key_privacy; - break; - case SLIX_PASS_DESTROY: - password = data->sub_data.slix.key_destroy; - break; - case SLIX_PASS_EASAFI: - password = data->sub_data.slix.key_eas; - break; - default: - break; - } - - if(!password) { - return ERR_NOTSUPP; - } - - for(int pos = 0; pos < 4; pos++) { - cmd_set_pass[1 + pos] ^= password[3 - pos]; - } - - ReturnCode ret = rfalNfcvPollerTransceiveReq( - ISO15693_CMD_NXP_SET_PASSWORD, - RFAL_NFCV_REQ_FLAG_DATA_RATE, - ISO15693_MANUFACTURER_NXP, - NULL, - cmd_set_pass, - sizeof(cmd_set_pass), - rxBuf, - sizeof(rxBuf), - &received); - - return ret; -} - -bool slix_generic_protocol_filter( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - void* nfcv_data_in, - uint32_t password_supported) { - furi_assert(tx_rx); - furi_assert(nfc_data); - furi_assert(nfcv_data_in); - - NfcVData* nfcv_data = (NfcVData*)nfcv_data_in; - NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx; - NfcVSlixData* slix = &nfcv_data->sub_data.slix; - - if(slix->privacy && ctx->command != ISO15693_CMD_NXP_GET_RANDOM_NUMBER && - ctx->command != ISO15693_CMD_NXP_SET_PASSWORD) { - snprintf( - nfcv_data->last_command, - sizeof(nfcv_data->last_command), - "command 0x%02X ignored, privacy mode", - ctx->command); - FURI_LOG_D(TAG, "%s", nfcv_data->last_command); - return true; - } - - bool handled = false; - - switch(ctx->command) { - case ISO15693_CMD_NXP_GET_RANDOM_NUMBER: { - slix->rand[0] = furi_hal_random_get(); - slix->rand[1] = furi_hal_random_get(); - - ctx->response_buffer[0] = ISO15693_NOERROR; - ctx->response_buffer[1] = slix->rand[1]; - ctx->response_buffer[2] = slix->rand[0]; - - nfcv_emu_send( - tx_rx, nfcv_data, ctx->response_buffer, 3, ctx->response_flags, ctx->send_time); - snprintf( - nfcv_data->last_command, - sizeof(nfcv_data->last_command), - "GET_RANDOM_NUMBER -> 0x%02X%02X", - slix->rand[0], - slix->rand[1]); - - handled = true; - break; - } - - case ISO15693_CMD_NXP_SET_PASSWORD: { - uint8_t password_id = nfcv_data->frame[ctx->payload_offset]; - - if(!(password_id & password_supported)) { - break; - } - - uint8_t* password_xored = &nfcv_data->frame[ctx->payload_offset + 1]; - uint8_t* rand = slix->rand; - uint8_t* password = NULL; - uint8_t password_rcv[4]; - - switch(password_id) { - case SLIX_PASS_READ: - password = slix->key_read; - break; - case SLIX_PASS_WRITE: - password = slix->key_write; - break; - case SLIX_PASS_PRIVACY: - password = slix->key_privacy; - break; - case SLIX_PASS_DESTROY: - password = slix->key_destroy; - break; - case SLIX_PASS_EASAFI: - password = slix->key_eas; - break; - default: - break; - } - - for(int pos = 0; pos < 4; pos++) { - password_rcv[pos] = password_xored[3 - pos] ^ rand[pos % 2]; - } - uint32_t pass_expect = slix_read_be(password, 4); - uint32_t pass_received = slix_read_be(password_rcv, 4); - - /* if the password is all-zeroes, just accept any password*/ - if(!pass_expect || pass_expect == pass_received) { - switch(password_id) { - case SLIX_PASS_READ: - break; - case SLIX_PASS_WRITE: - break; - case SLIX_PASS_PRIVACY: - slix->privacy = false; - break; - case SLIX_PASS_DESTROY: - FURI_LOG_D(TAG, "Pooof! Got destroyed"); - break; - case SLIX_PASS_EASAFI: - break; - default: - break; - } - ctx->response_buffer[0] = ISO15693_NOERROR; - nfcv_emu_send( - tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time); - snprintf( - nfcv_data->last_command, - sizeof(nfcv_data->last_command), - "SET_PASSWORD #%02X 0x%08lX OK", - password_id, - pass_received); - } else { - snprintf( - nfcv_data->last_command, - sizeof(nfcv_data->last_command), - "SET_PASSWORD #%02X 0x%08lX/%08lX FAIL", - password_id, - pass_received, - pass_expect); - } - handled = true; - break; - } - - case ISO15693_CMD_NXP_ENABLE_PRIVACY: { - ctx->response_buffer[0] = ISO15693_NOERROR; - - nfcv_emu_send( - tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time); - snprintf( - nfcv_data->last_command, - sizeof(nfcv_data->last_command), - "ISO15693_CMD_NXP_ENABLE_PRIVACY"); - - slix->privacy = true; - handled = true; - break; - } - } - - return handled; -} - -bool slix_l_protocol_filter( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - void* nfcv_data_in) { - furi_assert(tx_rx); - furi_assert(nfc_data); - furi_assert(nfcv_data_in); - - bool handled = false; - - /* many SLIX share some of the functions, place that in a generic handler */ - if(slix_generic_protocol_filter( - tx_rx, - nfc_data, - nfcv_data_in, - SLIX_PASS_PRIVACY | SLIX_PASS_DESTROY | SLIX_PASS_EASAFI)) { - return true; - } - - return handled; -} - -void slix_l_prepare(NfcVData* nfcv_data) { - FURI_LOG_D( - TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4)); - FURI_LOG_D( - TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4)); - FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4)); - FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF"); - - NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx; - ctx->emu_protocol_filter = &slix_l_protocol_filter; -} - -bool slix_s_protocol_filter( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - void* nfcv_data_in) { - furi_assert(tx_rx); - furi_assert(nfc_data); - furi_assert(nfcv_data_in); - - bool handled = false; - - /* many SLIX share some of the functions, place that in a generic handler */ - if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_ALL)) { - return true; - } - - return handled; -} - -void slix_s_prepare(NfcVData* nfcv_data) { - FURI_LOG_D( - TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4)); - FURI_LOG_D( - TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4)); - FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4)); - FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF"); - - NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx; - ctx->emu_protocol_filter = &slix_s_protocol_filter; -} - -bool slix_protocol_filter( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - void* nfcv_data_in) { - furi_assert(tx_rx); - furi_assert(nfc_data); - furi_assert(nfcv_data_in); - - bool handled = false; - - /* many SLIX share some of the functions, place that in a generic handler */ - if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_EASAFI)) { - return true; - } - - return handled; -} - -void slix_prepare(NfcVData* nfcv_data) { - FURI_LOG_D( - TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4)); - FURI_LOG_D( - TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4)); - FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4)); - FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF"); - - NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx; - ctx->emu_protocol_filter = &slix_protocol_filter; -} - -bool slix2_protocol_filter( - FuriHalNfcTxRxContext* tx_rx, - FuriHalNfcDevData* nfc_data, - void* nfcv_data_in) { - furi_assert(tx_rx); - furi_assert(nfc_data); - furi_assert(nfcv_data_in); - - bool handled = false; - - /* many SLIX share some of the functions, place that in a generic handler */ - if(slix_generic_protocol_filter(tx_rx, nfc_data, nfcv_data_in, SLIX_PASS_ALL)) { - return true; - } - - return handled; -} - -void slix2_prepare(NfcVData* nfcv_data) { - FURI_LOG_D( - TAG, " Privacy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_privacy, 4)); - FURI_LOG_D( - TAG, " Destroy pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_destroy, 4)); - FURI_LOG_D(TAG, " EAS pass: 0x%08lX", slix_read_be(nfcv_data->sub_data.slix.key_eas, 4)); - FURI_LOG_D(TAG, " Privacy mode: %s", nfcv_data->sub_data.slix.privacy ? "ON" : "OFF"); - - NfcVEmuProtocolCtx* ctx = nfcv_data->emu_protocol_ctx; - ctx->emu_protocol_filter = &slix2_protocol_filter; -} diff --git a/lib/nfc/protocols/slix.h b/lib/nfc/protocols/slix.h deleted file mode 100644 index 719fe6f43..000000000 --- a/lib/nfc/protocols/slix.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#include -#include -#include "nfc_util.h" -#include - -#define ISO15693_MANUFACTURER_NXP 0x04 - -/* ISO15693-3 CUSTOM NXP COMMANDS */ -#define ISO15693_CMD_NXP_SET_EAS 0xA2 -#define ISO15693_CMD_NXP_RESET_EAS 0xA3 -#define ISO15693_CMD_NXP_LOCK_EAS 0xA4 -#define ISO15693_CMD_NXP_EAS_ALARM 0xA5 -#define ISO15693_CMD_NXP_PASSWORD_PROTECT_EAS_AFI 0xA6 -#define ISO15693_CMD_NXP_WRITE_EAS_ID 0xA7 -#define ISO15693_CMD_NXP_INVENTORY_PAGE_READ 0xB0 -#define ISO15693_CMD_NXP_INVENTORY_PAGE_READ_FAST 0xB1 -#define ISO15693_CMD_NXP_GET_RANDOM_NUMBER 0xB2 -#define ISO15693_CMD_NXP_SET_PASSWORD 0xB3 -#define ISO15693_CMD_NXP_WRITE_PASSWORD 0xB4 -#define ISO15693_CMD_NXP_DESTROY 0xB9 -#define ISO15693_CMD_NXP_ENABLE_PRIVACY 0xBA - -/* available passwords */ -#define SLIX_PASS_READ 0x01 -#define SLIX_PASS_WRITE 0x02 -#define SLIX_PASS_PRIVACY 0x04 -#define SLIX_PASS_DESTROY 0x08 -#define SLIX_PASS_EASAFI 0x10 - -#define SLIX_PASS_ALL \ - (SLIX_PASS_READ | SLIX_PASS_WRITE | SLIX_PASS_PRIVACY | SLIX_PASS_DESTROY | SLIX_PASS_EASAFI) - -bool slix_check_card_type(FuriHalNfcDevData* nfc_data); -bool slix2_check_card_type(FuriHalNfcDevData* nfc_data); -bool slix_s_check_card_type(FuriHalNfcDevData* nfc_data); -bool slix_l_check_card_type(FuriHalNfcDevData* nfc_data); - -ReturnCode slix_get_random(NfcVData* data); -ReturnCode slix_unlock(NfcVData* data, uint32_t password_id); - -void slix_prepare(NfcVData* nfcv_data); -void slix_s_prepare(NfcVData* nfcv_data); -void slix_l_prepare(NfcVData* nfcv_data); -void slix2_prepare(NfcVData* nfcv_data); diff --git a/lib/pulse_reader/pulse_reader.c b/lib/pulse_reader/pulse_reader.c deleted file mode 100644 index 20f993844..000000000 --- a/lib/pulse_reader/pulse_reader.c +++ /dev/null @@ -1,202 +0,0 @@ -#include -#include -#include -#include - -#include "pulse_reader.h" - -#define GPIO_PIN_MAP(pin, prefix) \ - (((pin) == (LL_GPIO_PIN_0)) ? prefix##0 : \ - ((pin) == (LL_GPIO_PIN_1)) ? prefix##1 : \ - ((pin) == (LL_GPIO_PIN_2)) ? prefix##2 : \ - ((pin) == (LL_GPIO_PIN_3)) ? prefix##3 : \ - ((pin) == (LL_GPIO_PIN_4)) ? prefix##4 : \ - ((pin) == (LL_GPIO_PIN_5)) ? prefix##5 : \ - ((pin) == (LL_GPIO_PIN_6)) ? prefix##6 : \ - ((pin) == (LL_GPIO_PIN_7)) ? prefix##7 : \ - ((pin) == (LL_GPIO_PIN_8)) ? prefix##8 : \ - ((pin) == (LL_GPIO_PIN_9)) ? prefix##9 : \ - ((pin) == (LL_GPIO_PIN_10)) ? prefix##10 : \ - ((pin) == (LL_GPIO_PIN_11)) ? prefix##11 : \ - ((pin) == (LL_GPIO_PIN_12)) ? prefix##12 : \ - ((pin) == (LL_GPIO_PIN_13)) ? prefix##13 : \ - ((pin) == (LL_GPIO_PIN_14)) ? prefix##14 : \ - prefix##15) - -#define GET_DMAMUX_EXTI_LINE(pin) GPIO_PIN_MAP(pin, LL_DMAMUX_REQ_GEN_EXTI_LINE) - -PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size) { - PulseReader* signal = malloc(sizeof(PulseReader)); - signal->timer_buffer = malloc(size * sizeof(uint32_t)); - signal->gpio_buffer = malloc(size * sizeof(uint32_t)); - signal->dma_channel = LL_DMA_CHANNEL_4; - signal->gpio = gpio; - signal->size = size; - signal->timer_value = 0; - signal->pos = 0; - - pulse_reader_set_timebase(signal, PulseReaderUnit64MHz); - pulse_reader_set_bittime(signal, 1); - - signal->dma_config_timer.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; - signal->dma_config_timer.PeriphOrM2MSrcAddress = (uint32_t) & (TIM2->CNT); - signal->dma_config_timer.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - signal->dma_config_timer.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; - signal->dma_config_timer.MemoryOrM2MDstAddress = (uint32_t)signal->timer_buffer; - signal->dma_config_timer.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - signal->dma_config_timer.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; - signal->dma_config_timer.Mode = LL_DMA_MODE_CIRCULAR; - signal->dma_config_timer.PeriphRequest = - LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */ - signal->dma_config_timer.Priority = LL_DMA_PRIORITY_VERYHIGH; - - signal->dma_config_gpio.Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY; - signal->dma_config_gpio.PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT; - signal->dma_config_gpio.PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_WORD; - signal->dma_config_gpio.MemoryOrM2MDstIncMode = LL_DMA_MEMORY_INCREMENT; - signal->dma_config_gpio.MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_WORD; - signal->dma_config_gpio.Mode = LL_DMA_MODE_CIRCULAR; - signal->dma_config_gpio.PeriphRequest = - LL_DMAMUX_REQ_GENERATOR0; /* executes LL_DMA_SetPeriphRequest */ - signal->dma_config_gpio.Priority = LL_DMA_PRIORITY_VERYHIGH; - - return signal; -} - -void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit) { - switch(unit) { - case PulseReaderUnit64MHz: - signal->unit_multiplier = 1; - signal->unit_divider = 1; - break; - case PulseReaderUnitPicosecond: - signal->unit_multiplier = 15625; - signal->unit_divider = 1; - break; - case PulseReaderUnitNanosecond: - signal->unit_multiplier = 15625; - signal->unit_divider = 1000; - break; - case PulseReaderUnitMicrosecond: - signal->unit_multiplier = 15625; - signal->unit_divider = 1000000; - break; - } -} - -void pulse_reader_set_bittime(PulseReader* signal, uint32_t bit_time) { - signal->bit_time = bit_time; -} - -void pulse_reader_free(PulseReader* signal) { - free(signal->timer_buffer); - free(signal->gpio_buffer); - free(signal); -} - -uint32_t pulse_reader_samples(PulseReader* signal) { - uint32_t dma_pos = signal->size - (uint32_t)LL_DMA_GetDataLength(DMA1, signal->dma_channel); - - return ((signal->pos + signal->size) - dma_pos) % signal->size; -} - -void pulse_reader_stop(PulseReader* signal) { - LL_DMA_DisableChannel(DMA1, signal->dma_channel); - LL_DMA_DisableChannel(DMA1, signal->dma_channel + 1); - LL_DMAMUX_DisableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0); - LL_TIM_DisableCounter(TIM2); -} - -void pulse_reader_start(PulseReader* signal) { - /* configure DMA to read from a timer peripheral */ - signal->dma_config_timer.NbData = signal->size; - - signal->dma_config_gpio.PeriphOrM2MSrcAddress = (uint32_t) & (signal->gpio->port->IDR); - signal->dma_config_gpio.MemoryOrM2MDstAddress = (uint32_t)signal->gpio_buffer; - signal->dma_config_gpio.NbData = signal->size; - - /* start counter */ - LL_TIM_SetCounterMode(TIM2, LL_TIM_COUNTERMODE_UP); - LL_TIM_SetClockDivision(TIM2, LL_TIM_CLOCKDIVISION_DIV1); - LL_TIM_SetPrescaler(TIM2, 0); - LL_TIM_SetAutoReload(TIM2, 0xFFFFFFFF); - LL_TIM_SetCounter(TIM2, 0); - LL_TIM_EnableCounter(TIM2); - - /* generator 0 gets fed by EXTI_LINEn */ - LL_DMAMUX_SetRequestSignalID( - NULL, LL_DMAMUX_REQ_GEN_0, GET_DMAMUX_EXTI_LINE(signal->gpio->pin)); - /* trigger on rising edge of the interrupt */ - LL_DMAMUX_SetRequestGenPolarity(NULL, LL_DMAMUX_REQ_GEN_0, LL_DMAMUX_REQ_GEN_POL_RISING); - /* now enable request generation again */ - LL_DMAMUX_EnableRequestGen(NULL, LL_DMAMUX_REQ_GEN_0); - - /* we need the EXTI to be configured as interrupt generating line, but no ISR registered */ - furi_hal_gpio_init_ex( - signal->gpio, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedVeryHigh, GpioAltFnUnused); - - /* capture current timer */ - signal->pos = 0; - signal->start_level = furi_hal_gpio_read(signal->gpio); - signal->timer_value = TIM2->CNT; - signal->gpio_mask = signal->gpio->pin; - - /* now set up DMA with these settings */ - LL_DMA_Init(DMA1, signal->dma_channel, &signal->dma_config_timer); - LL_DMA_Init(DMA1, signal->dma_channel + 1, &signal->dma_config_gpio); - LL_DMA_EnableChannel(DMA1, signal->dma_channel); - LL_DMA_EnableChannel(DMA1, signal->dma_channel + 1); -} - -uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us) { - uint32_t start_time = DWT->CYCCNT; - uint32_t timeout_ticks = timeout_us * (F_TIM2 / 1000000); - - do { - /* get the DMA's next write position by reading "remaining length" register */ - uint32_t dma_pos = - signal->size - (uint32_t)LL_DMA_GetDataLength(DMA1, signal->dma_channel); - - /* the DMA has advanced in the ringbuffer */ - if(dma_pos != signal->pos) { - uint32_t delta = signal->timer_buffer[signal->pos] - signal->timer_value; - uint32_t last_gpio_value = signal->gpio_value; - - signal->gpio_value = signal->gpio_buffer[signal->pos]; - - /* check if the GPIO really toggled. if not, we lost an edge :( */ - if(((last_gpio_value ^ signal->gpio_value) & signal->gpio_mask) != signal->gpio_mask) { - signal->gpio_value ^= signal->gpio_mask; - return PULSE_READER_LOST_EDGE; - } - signal->timer_value = signal->timer_buffer[signal->pos]; - - signal->pos++; - signal->pos %= signal->size; - - uint32_t delta_unit = 0; - - /* probably larger values, so choose a wider data type */ - if(signal->unit_divider > 1) { - delta_unit = - (uint32_t)((uint64_t)delta * (uint64_t)signal->unit_multiplier / signal->unit_divider); - } else { - delta_unit = delta * signal->unit_multiplier; - } - - /* if to be scaled to bit times, save a few instructions. should be faster */ - if(signal->bit_time > 1) { - return (delta_unit + signal->bit_time / 2) / signal->bit_time; - } - - return delta_unit; - } - - /* check for timeout */ - uint32_t elapsed = DWT->CYCCNT - start_time; - - if(elapsed > timeout_ticks) { - return PULSE_READER_NO_EDGE; - } - } while(true); -} diff --git a/lib/pulse_reader/pulse_reader.h b/lib/pulse_reader/pulse_reader.h deleted file mode 100644 index fb65f62bc..000000000 --- a/lib/pulse_reader/pulse_reader.h +++ /dev/null @@ -1,130 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define PULSE_READER_NO_EDGE 0xFFFFFFFFUL -#define PULSE_READER_LOST_EDGE 0xFFFFFFFEUL -#define F_TIM2 64000000UL - -/** - * unit of the edge durations to return - */ -typedef enum { - PulseReaderUnit64MHz, - PulseReaderUnitPicosecond, - PulseReaderUnitNanosecond, - PulseReaderUnitMicrosecond, -} PulseReaderUnit; - -typedef struct { - bool start_level; - uint32_t* timer_buffer; - uint32_t* gpio_buffer; - uint32_t size; - uint32_t pos; - uint32_t timer_value; - uint32_t gpio_value; - uint32_t gpio_mask; - uint32_t unit_multiplier; - uint32_t unit_divider; - uint32_t bit_time; - uint32_t dma_channel; - const GpioPin* gpio; - LL_DMA_InitTypeDef dma_config_timer; - LL_DMA_InitTypeDef dma_config_gpio; -} PulseReader; - -/** Allocate a PulseReader object - * - * Allocates memory for a ringbuffer and initalizes the object - * - * @param[in] gpio the GPIO to use. will get configured as input. - * @param[in] size number of edges to buffer - */ -PulseReader* pulse_reader_alloc(const GpioPin* gpio, uint32_t size); - -/** Free a PulseReader object - * - * Frees all memory of the given object - * - * @param[in] signal previously allocated PulseReader object. - */ -void pulse_reader_free(PulseReader* signal); - -/** Start signal capturing - * - * Initializes DMA1, TIM2 and DMAMUX_REQ_GEN_0 to automatically capture timer values - * - * @param[in] signal previously allocated PulseReader object. - */ -void pulse_reader_start(PulseReader* signal); - -/** Stop signal capturing - * - * Frees DMA1, TIM2 and DMAMUX_REQ_GEN_0 - * - * @param[in] signal previously allocated PulseReader object. - */ -void pulse_reader_stop(PulseReader* signal); - -/** Recevie a sample from ringbuffer - * - * Waits for the specified time until a new edge gets detected. - * If not configured otherwise, the pulse duration will be in picosecond resolution. - * If a bittime was configured, the return value will contain the properly rounded - * number of bit times measured. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] timeout_us time to wait for a signal [µs] - * - * @returns the scaled value of the pulse duration - */ -uint32_t pulse_reader_receive(PulseReader* signal, int timeout_us); - -/** Get available samples - * - * Get the number of available samples in the ringbuffer - * - * @param[in] signal previously allocated PulseReader object. - * - * @returns the number of samples in buffer - */ -uint32_t pulse_reader_samples(PulseReader* signal); - -/** Set timebase - * - * Set the timebase to be used when returning pulse duration. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] unit PulseReaderUnit64MHz or PulseReaderUnitPicosecond - */ -void pulse_reader_set_timebase(PulseReader* signal, PulseReaderUnit unit); - -/** Set bit time - * - * Set the number of timebase units per bit. - * When set, the pulse_reader_receive() will return an already rounded - * bit count value instead of the raw duration. - * - * Set to 1 to return duration again. - * - * @param[in] signal previously allocated PulseReader object. - * @param[in] bit_time - */ -void pulse_reader_set_bittime(PulseReader* signal, uint32_t bit_time); - -#ifdef __cplusplus -} -#endif