From f491d0bb5a79ed45eaa068ad062e4912bc6a2c11 Mon Sep 17 00:00:00 2001 From: Chris van Marle Date: Wed, 20 Aug 2025 13:34:00 +0200 Subject: [PATCH 1/2] Add initial auth menu This commit adds an initial version of the Authentication menu. This menu currently contains: - Document Number - Date of Birth - Date of Expiry - Authentication Method (Any, BAC only, PACE only) The idea is to also implement options to save and load authentication details to/from files. --- passy.c | 11 ++ passy_i.h | 3 + scenes/passy_scene_auth_menu.c | 147 +++++++++++++++++++++ scenes/passy_scene_config.h | 1 + scenes/passy_scene_dob_input.c | 2 +- scenes/passy_scene_doe_input.c | 2 +- scenes/passy_scene_main_menu.c | 2 +- scenes/passy_scene_passport_number_input.c | 2 +- 8 files changed, 166 insertions(+), 4 deletions(-) create mode 100644 scenes/passy_scene_auth_menu.c diff --git a/passy.c b/passy.c index 826c9a4..435a79a 100644 --- a/passy.c +++ b/passy.c @@ -157,6 +157,13 @@ Passy* passy_alloc() { view_dispatcher_add_view( passy->view_dispatcher, PassyViewMenu, submenu_get_view(passy->submenu)); + // Variable Item List + passy->variable_item_list = variable_item_list_alloc(); + view_dispatcher_add_view( + passy->view_dispatcher, + PassyViewVariableItemList, + variable_item_list_get_view(passy->variable_item_list)); + // Popup passy->popup = popup_alloc(); view_dispatcher_add_view(passy->view_dispatcher, PassyViewPopup, popup_get_view(passy->popup)); @@ -210,6 +217,10 @@ void passy_free(Passy* passy) { view_dispatcher_remove_view(passy->view_dispatcher, PassyViewMenu); submenu_free(passy->submenu); + // Variable Item List + view_dispatcher_remove_view(passy->view_dispatcher, PassyViewVariableItemList); + variable_item_list_free(passy->variable_item_list); + // Popup view_dispatcher_remove_view(passy->view_dispatcher, PassyViewPopup); popup_free(passy->popup); diff --git a/passy_i.h b/passy_i.h index 4e80039..b1f4320 100644 --- a/passy_i.h +++ b/passy_i.h @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -69,6 +70,7 @@ struct Passy { // Common Views Submenu* submenu; + VariableItemList* variable_item_list; Popup* popup; Loading* loading; TextInput* text_input; @@ -105,6 +107,7 @@ struct Passy { typedef enum { PassyViewMenu, + PassyViewVariableItemList, PassyViewPopup, PassyViewLoading, PassyViewTextInput, diff --git a/scenes/passy_scene_auth_menu.c b/scenes/passy_scene_auth_menu.c new file mode 100644 index 0000000..3d48adf --- /dev/null +++ b/scenes/passy_scene_auth_menu.c @@ -0,0 +1,147 @@ +#include "../passy_i.h" + +#define TAG "PassySceneAuthMenu" + +enum SubmenuIndex { + SubmenuIndexDocNr, + SubmenuIndexDob, + SubmenuIndexDoe, + SubmenuIndexMethod, + // SubmenuIndexSave, + // SubmenuIndexLoad, +}; + +typedef enum { + MrtdAuthMethodNone, + MrtdAuthMethodAny, + MrtdAuthMethodBac, + MrtdAuthMethodPace, + MRTD_AUTH_METHOD_COUNT, +} MrtdAuthMethod; + +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"; + } +} + +void passy_scene_auth_menu_auth_method_changed(VariableItem* item) { + Passy* passy = variable_item_get_context(item); + UNUSED(passy); // TODO: use to save selected method + uint8_t index = variable_item_get_current_value_index(item); + // TODO: store selected auth method in passy + // nfc->dev->dev_data.mrtd_data.auth.method = index; + variable_item_set_current_value_text(item, mrtd_auth_method_string(index)); +} + +void passy_scene_auth_menu_var_list_enter_callback(void* context, uint32_t index) { + Passy* passy = context; + view_dispatcher_send_custom_event(passy->view_dispatcher, index); +} + +void passy_scene_auth_menu_on_enter(void* context) { + Passy* passy = context; + VariableItemList* variable_item_list = passy->variable_item_list; + + // By entering the Auth menu, we default to Auth: Any + //TODO: read from passy, before: &mrtd_data->auth.method; + MrtdAuthMethod temp_method = MrtdAuthMethodNone; + MrtdAuthMethod* auth_method = &temp_method; + if(*auth_method == MrtdAuthMethodNone) { + *auth_method = MrtdAuthMethodAny; + } + + VariableItem* item; + uint8_t value_index; + + const size_t temp_str_size = 15; + char temp_str[temp_str_size]; + + item = variable_item_list_add(variable_item_list, "Document Nr.", 1, NULL, NULL); + strlcpy(temp_str, passy->passport_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, "Birth Date", 1, NULL, NULL); + variable_item_set_current_value_text(item, passy->date_of_birth); + + item = variable_item_list_add(variable_item_list, "Expiry Date", 1, NULL, NULL); + variable_item_set_current_value_text(item, passy->date_of_expiry); + + item = variable_item_list_add( + variable_item_list, + "Method", + MRTD_AUTH_METHOD_COUNT, + passy_scene_auth_menu_auth_method_changed, + passy); + + 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)); + + //TODO: save/load + //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, passy_scene_auth_menu_var_list_enter_callback, passy); + view_dispatcher_switch_to_view(passy->view_dispatcher, PassyViewVariableItemList); +} + +bool passy_scene_auth_menu_on_event(void* context, SceneManagerEvent event) { + Passy* passy = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + switch(event.event) { + case SubmenuIndexDob: + scene_manager_next_scene(passy->scene_manager, PassySceneDoBInput); + consumed = true; + break; + case SubmenuIndexDoe: + scene_manager_next_scene(passy->scene_manager, PassySceneDoEInput); + consumed = true; + break; + case SubmenuIndexDocNr: + scene_manager_next_scene(passy->scene_manager, PassyScenePassportNumberInput); + consumed = true; + break; + case SubmenuIndexMethod: + consumed = true; + break; + // case SubmenuIndexSave: + // scene_manager_next_scene(nfc->scene_manager, PassySceneAuthMenuSaveName); + // consumed = true; + // break; + // case SubmenuIndexLoad: + // nfc_scene_passport_auth_load(nfc); + // consumed = true; + // break; + } + } else if(event.type == SceneManagerEventTypeBack) { + consumed = scene_manager_previous_scene(passy->scene_manager); + } + return consumed; +} + +void passy_scene_auth_menu_on_exit(void* context) { + Passy* passy = context; + + // Clear view + variable_item_list_reset(passy->variable_item_list); +} diff --git a/scenes/passy_scene_config.h b/scenes/passy_scene_config.h index a564972..a1a27b4 100644 --- a/scenes/passy_scene_config.h +++ b/scenes/passy_scene_config.h @@ -1,4 +1,5 @@ ADD_SCENE(passy, main_menu, MainMenu) +ADD_SCENE(passy, auth_menu, AuthMenu) ADD_SCENE(passy, read, Read) ADD_SCENE(passy, read_error, ReadError) ADD_SCENE(passy, read_success, ReadSuccess) diff --git a/scenes/passy_scene_dob_input.c b/scenes/passy_scene_dob_input.c index c32d1b6..c5c912a 100644 --- a/scenes/passy_scene_dob_input.c +++ b/scenes/passy_scene_dob_input.c @@ -39,7 +39,7 @@ bool passy_scene_dob_input_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { if(event.event == PassyCustomEventTextInputDone) { strlcpy(passy->date_of_birth, passy->text_store, strlen(passy->text_store) + 1); - scene_manager_next_scene(passy->scene_manager, PassySceneDoEInput); + scene_manager_previous_scene(passy->scene_manager); consumed = true; } } diff --git a/scenes/passy_scene_doe_input.c b/scenes/passy_scene_doe_input.c index bc447ca..5ac79b1 100644 --- a/scenes/passy_scene_doe_input.c +++ b/scenes/passy_scene_doe_input.c @@ -39,7 +39,7 @@ bool passy_scene_doe_input_on_event(void* context, SceneManagerEvent event) { if(event.event == PassyCustomEventTextInputDone) { strlcpy(passy->date_of_expiry, passy->text_store, strlen(passy->text_store) + 1); passy_save_mrz_info(passy); - scene_manager_next_scene(passy->scene_manager, PassySceneMainMenu); + scene_manager_previous_scene(passy->scene_manager); consumed = true; } } diff --git a/scenes/passy_scene_main_menu.c b/scenes/passy_scene_main_menu.c index 749abd7..eb335ad 100644 --- a/scenes/passy_scene_main_menu.c +++ b/scenes/passy_scene_main_menu.c @@ -78,7 +78,7 @@ bool passy_scene_main_menu_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { scene_manager_set_scene_state(passy->scene_manager, PassySceneMainMenu, event.event); if(event.event == SubmenuIndexEnterMRZInfo) { - scene_manager_next_scene(passy->scene_manager, PassyScenePassportNumberInput); + scene_manager_next_scene(passy->scene_manager, PassySceneAuthMenu); consumed = true; } else if(event.event == SubmenuIndexDeleteMRZInfo) { scene_manager_next_scene(passy->scene_manager, PassySceneDelete); diff --git a/scenes/passy_scene_passport_number_input.c b/scenes/passy_scene_passport_number_input.c index 1942842..cbade91 100644 --- a/scenes/passy_scene_passport_number_input.c +++ b/scenes/passy_scene_passport_number_input.c @@ -49,7 +49,7 @@ bool passy_scene_passport_number_input_on_event(void* context, SceneManagerEvent } strlcpy(passy->passport_number, passy->text_store, strlen(passy->text_store) + 1); - scene_manager_next_scene(passy->scene_manager, PassySceneDoBInput); + scene_manager_previous_scene(passy->scene_manager); consumed = true; } } From 9c05b3cb5a9161fc76f4f9125363858eaa6f0870 Mon Sep 17 00:00:00 2001 From: Chris van Marle Date: Wed, 20 Aug 2025 13:34:06 +0200 Subject: [PATCH 2/2] Move AuthMethod consts+helper to passy_common. Store/use auth method in passy. Log selected method in state machine --- passy_common.c | 15 +++++++++++++ passy_common.h | 9 ++++++++ passy_i.h | 1 + scenes/passy_scene_auth_menu.c | 41 +++++++--------------------------- 4 files changed, 33 insertions(+), 33 deletions(-) diff --git a/passy_common.c b/passy_common.c index 60d1608..e133490 100644 --- a/passy_common.c +++ b/passy_common.c @@ -4,6 +4,21 @@ #define TAG "PassyCommon" +const char* passy_auth_method_string(PassyAuthMethod method) { + switch(method) { + case PassyAuthMethodBac: + return "BAC"; + case PassyAuthMethodPace: + return "PACE"; + case PassyAuthMethodNone: + return "None"; + case PassyAuthMethodAny: + return "Any"; + default: + return "Unknown"; + } +} + static char asn1_log[PASSY_WORKER_MAX_BUFFER_SIZE]; int print_struct_callback(const void* buffer, size_t size, void* app_key) { if(app_key) { diff --git a/passy_common.h b/passy_common.h index f398561..fd3f78b 100644 --- a/passy_common.h +++ b/passy_common.h @@ -24,6 +24,15 @@ typedef enum { PassyReadDG15 = 0x010F, } PassyReadType; +typedef enum { + PassyAuthMethodNone, + PassyAuthMethodAny, + PassyAuthMethodBac, + PassyAuthMethodPace, + PASSY_AUTH_METHOD_COUNT, +} PassyAuthMethod; + +const char* passy_auth_method_string(PassyAuthMethod method); void passy_log_bitbuffer(char* tag, char* prefix, BitBuffer* buffer); void passy_log_buffer(char* tag, char* prefix, uint8_t* buffer, size_t buffer_len); void passy_mac(uint8_t* key, uint8_t* data, size_t data_length, uint8_t* mac, bool prepadded); diff --git a/passy_i.h b/passy_i.h index b1f4320..fbacf34 100644 --- a/passy_i.h +++ b/passy_i.h @@ -97,6 +97,7 @@ struct Passy { BitBuffer* dg_header; PassyReadType read_type; + PassyAuthMethod auth_mehod; size_t offset; size_t bytes_total; diff --git a/scenes/passy_scene_auth_menu.c b/scenes/passy_scene_auth_menu.c index 3d48adf..127b390 100644 --- a/scenes/passy_scene_auth_menu.c +++ b/scenes/passy_scene_auth_menu.c @@ -11,36 +11,13 @@ enum SubmenuIndex { // SubmenuIndexLoad, }; -typedef enum { - MrtdAuthMethodNone, - MrtdAuthMethodAny, - MrtdAuthMethodBac, - MrtdAuthMethodPace, - MRTD_AUTH_METHOD_COUNT, -} MrtdAuthMethod; - -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"; - } -} - void passy_scene_auth_menu_auth_method_changed(VariableItem* item) { Passy* passy = variable_item_get_context(item); UNUSED(passy); // TODO: use to save selected method uint8_t index = variable_item_get_current_value_index(item); - // TODO: store selected auth method in passy - // nfc->dev->dev_data.mrtd_data.auth.method = index; - variable_item_set_current_value_text(item, mrtd_auth_method_string(index)); + // store selected auth method in passy + passy->auth_mehod = index; + variable_item_set_current_value_text(item, passy_auth_method_string(index)); } void passy_scene_auth_menu_var_list_enter_callback(void* context, uint32_t index) { @@ -53,11 +30,9 @@ void passy_scene_auth_menu_on_enter(void* context) { VariableItemList* variable_item_list = passy->variable_item_list; // By entering the Auth menu, we default to Auth: Any - //TODO: read from passy, before: &mrtd_data->auth.method; - MrtdAuthMethod temp_method = MrtdAuthMethodNone; - MrtdAuthMethod* auth_method = &temp_method; - if(*auth_method == MrtdAuthMethodNone) { - *auth_method = MrtdAuthMethodAny; + PassyAuthMethod* auth_method = &passy->auth_mehod; + if(*auth_method == PassyAuthMethodNone) { + *auth_method = PassyAuthMethodAny; } VariableItem* item; @@ -86,13 +61,13 @@ void passy_scene_auth_menu_on_enter(void* context) { item = variable_item_list_add( variable_item_list, "Method", - MRTD_AUTH_METHOD_COUNT, + PASSY_AUTH_METHOD_COUNT, passy_scene_auth_menu_auth_method_changed, passy); 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_set_current_value_text(item, passy_auth_method_string(value_index)); //TODO: save/load //variable_item_list_add(variable_item_list, "Save parameters", 1, NULL, NULL);