From 4f05c1816bf9f2e915e00e48150a8b9305392480 Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Mon, 26 Dec 2022 23:31:38 +0300 Subject: [PATCH] Update TOTP --- applications/plugins/totp/cli/cli_helpers.h | 3 + .../plugins/totp/cli/commands/add/add.c | 8 +- .../plugins/totp/cli/commands/delete/delete.c | 11 +- .../plugins/totp/cli/commands/move/move.c | 14 +- .../cli/commands/notification/notification.c | 13 +- .../plugins/totp/cli/commands/pin/pin.c | 25 +- .../totp/cli/commands/timezone/timezone.c | 7 +- .../plugins/totp/services/config/config.c | 595 +++++++++++++----- .../plugins/totp/services/config/config.h | 69 +- .../plugins/totp/services/crypto/crypto.c | 21 +- .../plugins/totp/services/crypto/crypto.h | 3 +- .../plugins/totp/services/hmac/memxor.c | 2 - applications/plugins/totp/totp_app.c | 54 +- applications/plugins/totp/ui/common_dialogs.c | 20 + applications/plugins/totp/ui/common_dialogs.h | 7 + .../add_new_token/totp_scene_add_new_token.c | 7 +- .../scenes/app_settings/totp_app_settings.c | 8 +- .../totp_scene_generate_token.c | 4 +- .../scenes/token_menu/totp_scene_token_menu.c | 6 +- 19 files changed, 620 insertions(+), 257 deletions(-) create mode 100644 applications/plugins/totp/ui/common_dialogs.c create mode 100644 applications/plugins/totp/ui/common_dialogs.h diff --git a/applications/plugins/totp/cli/cli_helpers.h b/applications/plugins/totp/cli/cli_helpers.h index 075822cd6..ae6fe6e0c 100644 --- a/applications/plugins/totp/cli/cli_helpers.h +++ b/applications/plugins/totp/cli/cli_helpers.h @@ -38,6 +38,9 @@ TOTP_CLI_PRINTF( \ "Invalid command arguments. use \"help\" command to get list of available commands") +#define TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE() \ + TOTP_CLI_PRINTF("An error has occurred during updating config file\r\n") + /** * @brief Checks whether user is authenticated and entered correct PIN. * If user is not authenticated it prompts user to enter correct PIN to authenticate. diff --git a/applications/plugins/totp/cli/commands/add/add.c b/applications/plugins/totp/cli/commands/add/add.c index 90cc0f420..e037546e2 100644 --- a/applications/plugins/totp/cli/commands/add/add.c +++ b/applications/plugins/totp/cli/commands/add/add.c @@ -206,11 +206,13 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, token_info, furi_check); plugin_state->tokens_count++; - totp_config_file_save_new_token(token_info); + if(totp_config_file_save_new_token(token_info) == TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } if(load_generate_token_scene) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } - - TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name); } \ No newline at end of file diff --git a/applications/plugins/totp/cli/commands/delete/delete.c b/applications/plugins/totp/cli/commands/delete/delete.c index 7eddb96bd..046341693 100644 --- a/applications/plugins/totp/cli/commands/delete/delete.c +++ b/applications/plugins/totp/cli/commands/delete/delete.c @@ -93,14 +93,17 @@ void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, plugin_state->tokens_list = list_remove(plugin_state->tokens_list, list_node); plugin_state->tokens_count--; - totp_full_save_config_file(plugin_state); + if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Token \"%s\" has been successfully deleted\r\n", token_info->name); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } + + token_info_free(token_info); if(activate_generate_token_scene) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } - - TOTP_CLI_PRINTF("Token \"%s\" has been successfully deleted\r\n", token_info->name); - token_info_free(token_info); } else { TOTP_CLI_PRINTF("User not confirmed\r\n"); } diff --git a/applications/plugins/totp/cli/commands/move/move.c b/applications/plugins/totp/cli/commands/move/move.c index 95cb8dcac..9d47134e5 100644 --- a/applications/plugins/totp/cli/commands/move/move.c +++ b/applications/plugins/totp/cli/commands/move/move.c @@ -147,18 +147,18 @@ void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, C } if(token_updated) { - totp_full_save_config_file(plugin_state); + if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Token \"%s\" has been successfully updated\r\n", token_info->name); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } + } else { + TOTP_CLI_PRINT_INVALID_ARGUMENTS(); } if(activate_generate_token_scene) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } - if(token_updated) { - TOTP_CLI_PRINTF("Token \"%s\" has been successfully updated\r\n", token_info->name); - } else { - TOTP_CLI_PRINT_INVALID_ARGUMENTS(); - } - furi_string_free(temp_str); } \ No newline at end of file diff --git a/applications/plugins/totp/cli/commands/notification/notification.c b/applications/plugins/totp/cli/commands/notification/notification.c index 91dd44d4f..5b98a857b 100644 --- a/applications/plugins/totp/cli/commands/notification/notification.c +++ b/applications/plugins/totp/cli/commands/notification/notification.c @@ -86,15 +86,18 @@ void totp_cli_command_notification_handle(PluginState* plugin_state, FuriString* } plugin_state->notification_method = new_method; - totp_config_file_update_notification_method(new_method); + if(totp_config_file_update_notification_method(new_method) == + TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Notification method is set to "); + totp_cli_command_notification_print_method(new_method); + cli_nl(); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } if(previous_scene != TotpSceneNone) { totp_scene_director_activate_scene(plugin_state, previous_scene, NULL); } - - TOTP_CLI_PRINTF("Notification method is set to "); - totp_cli_command_notification_print_method(new_method); - cli_nl(); } else { TOTP_CLI_PRINTF("Current notification method is "); totp_cli_command_notification_print_method(plugin_state->notification_method); diff --git a/applications/plugins/totp/cli/commands/pin/pin.c b/applications/plugins/totp/cli/commands/pin/pin.c index 045976eef..198324e27 100644 --- a/applications/plugins/totp/cli/commands/pin/pin.c +++ b/applications/plugins/totp/cli/commands/pin/pin.c @@ -134,8 +134,14 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl plugin_state->crypto_verify_data = NULL; } - totp_crypto_seed_iv( - plugin_state, new_pin_length > 0 ? &new_pin[0] : NULL, new_pin_length); + if(!totp_crypto_seed_iv( + plugin_state, new_pin_length > 0 ? &new_pin[0] : NULL, new_pin_length)) { + memset_s(&new_pin[0], TOTP_IV_SIZE, 0, TOTP_IV_SIZE); + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + break; + } + + memset_s(&new_pin[0], TOTP_IV_SIZE, 0, TOTP_IV_SIZE); TOTP_LIST_FOREACH(plugin_state->tokens_list, node, { TokenInfo* token_info = node->data; @@ -152,15 +158,18 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl free(plain_token); }); - totp_full_save_config_file(plugin_state); - TOTP_CLI_DELETE_LAST_LINE(); - if(do_change) { - TOTP_CLI_PRINTF("PIN has been successfully changed\r\n"); - } else if(do_remove) { - TOTP_CLI_PRINTF("PIN has been successfully removed\r\n"); + if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) { + if(do_change) { + TOTP_CLI_PRINTF("PIN has been successfully changed\r\n"); + } else if(do_remove) { + TOTP_CLI_PRINTF("PIN has been successfully removed\r\n"); + } + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); } + } while(false); if(load_generate_token_scene) { diff --git a/applications/plugins/totp/cli/commands/timezone/timezone.c b/applications/plugins/totp/cli/commands/timezone/timezone.c index 7a17c1ae2..537cf8a4a 100644 --- a/applications/plugins/totp/cli/commands/timezone/timezone.c +++ b/applications/plugins/totp/cli/commands/timezone/timezone.c @@ -33,8 +33,11 @@ void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* arg float tz = strtof(furi_string_get_cstr(temp_str), NULL); if(tz >= -12.75f && tz <= 12.75f) { plugin_state->timezone_offset = tz; - totp_config_file_update_timezone_offset(tz); - TOTP_CLI_PRINTF("Timezone is set to %f\r\n", tz); + if(totp_config_file_update_timezone_offset(tz) == TotpConfigFileUpdateSuccess) { + TOTP_CLI_PRINTF("Timezone is set to %f\r\n", tz); + } else { + TOTP_CLI_PRINT_ERROR_UPDATING_CONFIG_FILE(); + } if(plugin_state->current_scene == TotpSceneGenerateToken) { totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL); totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); diff --git a/applications/plugins/totp/services/config/config.c b/applications/plugins/totp/services/config/config.c index ff7e4eb2d..b9f0e9d50 100644 --- a/applications/plugins/totp/services/config/config.c +++ b/applications/plugins/totp/services/config/config.c @@ -6,9 +6,12 @@ #include "../../types/token_info.h" #include "migrations/config_migration_v1_to_v2.h" -#define CONFIG_FILE_DIRECTORY_PATH "/ext/apps/Misc" +#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("authenticator") #define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf" #define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup" +#define CONFIG_FILE_TEMP_PATH CONFIG_FILE_PATH ".tmp" +#define CONFIG_FILE_ORIG_PATH CONFIG_FILE_PATH ".orig" +#define CONFIG_FILE_PATH_PREVIOUS EXT_PATH("apps/Misc") "/totp.conf" static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) { switch(token_info->algo) { @@ -35,15 +38,38 @@ static void token_info_set_algo_from_str(TokenInfo* token_info, const FuriString } } -Storage* totp_open_storage() { +/** + * @brief Opens storage record + * @return Storage record + */ +static Storage* totp_open_storage() { return furi_record_open(RECORD_STORAGE); } -void totp_close_storage() { +/** + * @brief Closes storage record + */ +static void totp_close_storage() { furi_record_close(RECORD_STORAGE); } -FlipperFormat* totp_open_config_file(Storage* storage) { +/** + * @brief Closes config file + * @param file config file reference + */ +static void totp_close_config_file(FlipperFormat* file) { + if(file == NULL) return; + flipper_format_file_close(file); + flipper_format_free(file); +} + +/** + * @brief Opens or creates TOTP application standard config file + * @param storage storage record to use + * @param[out] file opened config file + * @return Config file open result + */ +static TotpConfigFileOpenResult totp_open_config_file(Storage* storage, FlipperFormat** file) { FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); if(storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK) { @@ -51,8 +77,28 @@ FlipperFormat* totp_open_config_file(Storage* storage) { if(!flipper_format_file_open_existing(fff_data_file, CONFIG_FILE_PATH)) { FURI_LOG_E(LOGGING_TAG, "Error opening existing file %s", CONFIG_FILE_PATH); totp_close_config_file(fff_data_file); - return NULL; + return TotpConfigFileOpenError; } + } else if(storage_common_stat(storage, CONFIG_FILE_PATH_PREVIOUS, NULL) == FSE_OK) { + FURI_LOG_D(LOGGING_TAG, "Old config file %s found", CONFIG_FILE_PATH_PREVIOUS); + if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) { + FURI_LOG_D( + LOGGING_TAG, + "Directory %s doesn't exist. Will create new.", + CONFIG_FILE_DIRECTORY_PATH); + if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) { + FURI_LOG_E(LOGGING_TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH); + totp_close_config_file(fff_data_file); + return TotpConfigFileOpenError; + } + } + if(storage_common_rename(storage, CONFIG_FILE_PATH_PREVIOUS, CONFIG_FILE_PATH) != FSE_OK) { + FURI_LOG_E(LOGGING_TAG, "Error moving config to %s", CONFIG_FILE_PATH); + totp_close_config_file(fff_data_file); + return TotpConfigFileOpenError; + } + FURI_LOG_I(LOGGING_TAG, "Applied config file path migration"); + return totp_open_config_file(storage, file); } else { FURI_LOG_D(LOGGING_TAG, "Config file %s is not found. Will create new.", CONFIG_FILE_PATH); if(storage_common_stat(storage, CONFIG_FILE_DIRECTORY_PATH, NULL) == FSE_NOT_EXIST) { @@ -62,14 +108,14 @@ FlipperFormat* totp_open_config_file(Storage* storage) { CONFIG_FILE_DIRECTORY_PATH); if(!storage_simply_mkdir(storage, CONFIG_FILE_DIRECTORY_PATH)) { FURI_LOG_E(LOGGING_TAG, "Error creating directory %s", CONFIG_FILE_DIRECTORY_PATH); - return NULL; + return TotpConfigFileOpenError; } } if(!flipper_format_file_open_new(fff_data_file, CONFIG_FILE_PATH)) { totp_close_config_file(fff_data_file); FURI_LOG_E(LOGGING_TAG, "Error creating new file %s", CONFIG_FILE_PATH); - return NULL; + return TotpConfigFileOpenError; } flipper_format_write_header_cstr( @@ -134,228 +180,415 @@ FlipperFormat* totp_open_config_file(Storage* storage) { if(!flipper_format_rewind(fff_data_file)) { totp_close_config_file(fff_data_file); FURI_LOG_E(LOGGING_TAG, "Rewind error"); - return NULL; + return TotpConfigFileOpenError; } } - return fff_data_file; + *file = fff_data_file; + return TotpConfigFileOpenSuccess; } -void totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) { - flipper_format_seek_to_end(file); - flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name); - bool token_is_valid = token_info->token != NULL && token_info->token_length > 0; - if(!token_is_valid) { - flipper_format_write_comment_cstr(file, "!!! WARNING BEGIN: INVALID TOKEN !!!"); +TotpConfigFileUpdateResult + totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) { + TotpConfigFileUpdateResult update_result; + do { + if(!flipper_format_seek_to_end(file)) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name)) { + update_result = TotpConfigFileUpdateError; + break; + } + + bool token_is_valid = token_info->token != NULL && token_info->token_length > 0; + if(!token_is_valid && + !flipper_format_write_comment_cstr(file, "!!! WARNING BEGIN: INVALID TOKEN !!!")) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_hex( + file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length)) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!token_is_valid && !flipper_format_write_comment_cstr(file, "!!! WARNING END !!!")) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_string_cstr( + file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info))) { + update_result = TotpConfigFileUpdateError; + break; + } + + uint32_t tmp_uint32 = token_info->digits; + if(!flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &tmp_uint32, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + return update_result; +} + +TotpConfigFileUpdateResult totp_config_file_save_new_token(const TokenInfo* token_info) { + Storage* cfg_storage = totp_open_storage(); + FlipperFormat* file; + TotpConfigFileUpdateResult update_result; + + if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) { + do { + if(totp_config_file_save_new_token_i(file, token_info) != + TotpConfigFileUpdateSuccess) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(file); + } else { + update_result = TotpConfigFileUpdateError; } - flipper_format_write_hex( - file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length); - if(!token_is_valid) { - flipper_format_write_comment_cstr(file, "!!! WARNING END !!!"); + + totp_close_storage(); + return update_result; +} + +TotpConfigFileUpdateResult totp_config_file_update_timezone_offset(float new_timezone_offset) { + Storage* cfg_storage = totp_open_storage(); + FlipperFormat* file; + TotpConfigFileUpdateResult update_result; + + if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) { + do { + if(!flipper_format_insert_or_update_float( + file, TOTP_CONFIG_KEY_TIMEZONE, &new_timezone_offset, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(file); + } else { + update_result = TotpConfigFileUpdateError; } - flipper_format_write_string_cstr( - file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info)); - uint32_t tmp_uint32 = token_info->digits; - flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &tmp_uint32, 1); -} -void totp_config_file_save_new_token(const TokenInfo* token_info) { - Storage* cfg_storage = totp_open_storage(); - FlipperFormat* file = totp_open_config_file(cfg_storage); - - totp_config_file_save_new_token_i(file, token_info); - - totp_close_config_file(file); totp_close_storage(); + return update_result; } -void totp_config_file_update_timezone_offset(float new_timezone_offset) { +TotpConfigFileUpdateResult + totp_config_file_update_notification_method(NotificationMethod new_notification_method) { Storage* cfg_storage = totp_open_storage(); - FlipperFormat* file = totp_open_config_file(cfg_storage); + FlipperFormat* file; + TotpConfigFileUpdateResult update_result; - flipper_format_insert_or_update_float(file, TOTP_CONFIG_KEY_TIMEZONE, &new_timezone_offset, 1); + if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) { + do { + uint32_t tmp_uint32 = new_notification_method; + if(!flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(file); + } else { + update_result = TotpConfigFileUpdateError; + } - totp_close_config_file(file); totp_close_storage(); + return update_result; } -void totp_config_file_update_notification_method(NotificationMethod new_notification_method) { +TotpConfigFileUpdateResult totp_config_file_update_user_settings(const PluginState* plugin_state) { Storage* cfg_storage = totp_open_storage(); - FlipperFormat* file = totp_open_config_file(cfg_storage); + FlipperFormat* file; + TotpConfigFileUpdateResult update_result; + if(totp_open_config_file(cfg_storage, &file) == TotpConfigFileOpenSuccess) { + do { + if(!flipper_format_insert_or_update_float( + file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + uint32_t tmp_uint32 = plugin_state->notification_method; + if(!flipper_format_insert_or_update_uint32( + file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } - uint32_t tmp_uint32 = new_notification_method; - flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(file); + } else { + update_result = TotpConfigFileUpdateError; + } - totp_close_config_file(file); totp_close_storage(); + return update_result; } -void totp_config_file_update_user_settings(const PluginState* plugin_state) { - Storage* cfg_storage = totp_open_storage(); - FlipperFormat* file = totp_open_config_file(cfg_storage); - - flipper_format_insert_or_update_float( - file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1); - uint32_t tmp_uint32 = plugin_state->notification_method; - flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); - - totp_close_config_file(file); - totp_close_storage(); -} - -void totp_full_save_config_file(const PluginState* const plugin_state) { +TotpConfigFileUpdateResult totp_full_save_config_file(const PluginState* const plugin_state) { Storage* storage = totp_open_storage(); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); + TotpConfigFileUpdateResult result = TotpConfigFileUpdateSuccess; - flipper_format_file_open_always(fff_data_file, CONFIG_FILE_PATH); - flipper_format_write_header_cstr( - fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION); - flipper_format_write_hex( - fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE); - flipper_format_write_hex( - fff_data_file, - TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_verify_data, - plugin_state->crypto_verify_data_length); - flipper_format_write_float( - fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1); - flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1); - uint32_t tmp_uint32 = plugin_state->notification_method; - flipper_format_write_uint32( - fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); + do { + if(!flipper_format_file_open_always(fff_data_file, CONFIG_FILE_TEMP_PATH)) { + result = TotpConfigFileUpdateError; + break; + } - TOTP_LIST_FOREACH(plugin_state->tokens_list, node, { - const TokenInfo* token_info = node->data; - totp_config_file_save_new_token_i(fff_data_file, token_info); - }); + if(!flipper_format_write_header_cstr( + fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION)) { + result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_hex( + fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) { + result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_hex( + fff_data_file, + TOTP_CONFIG_KEY_CRYPTO_VERIFY, + plugin_state->crypto_verify_data, + plugin_state->crypto_verify_data_length)) { + result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_float( + fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { + result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_write_bool( + fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { + result = TotpConfigFileUpdateError; + break; + } + uint32_t tmp_uint32 = plugin_state->notification_method; + if(!flipper_format_write_uint32( + fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { + result = TotpConfigFileUpdateError; + break; + } + + bool tokens_written = true; + TOTP_LIST_FOREACH(plugin_state->tokens_list, node, { + const TokenInfo* token_info = node->data; + tokens_written = tokens_written && + totp_config_file_save_new_token_i(fff_data_file, token_info) == + TotpConfigFileUpdateSuccess; + }); + + if(!tokens_written) { + result = TotpConfigFileUpdateError; + break; + } + } while(false); totp_close_config_file(fff_data_file); + + if(result == TotpConfigFileUpdateSuccess) { + if(storage_file_exists(storage, CONFIG_FILE_ORIG_PATH)) { + storage_simply_remove(storage, CONFIG_FILE_ORIG_PATH); + } + + if(storage_common_rename(storage, CONFIG_FILE_PATH, CONFIG_FILE_ORIG_PATH) != FSE_OK) { + result = TotpConfigFileUpdateError; + } else if(storage_common_rename(storage, CONFIG_FILE_TEMP_PATH, CONFIG_FILE_PATH) != FSE_OK) { + result = TotpConfigFileUpdateError; + } else if(!storage_simply_remove(storage, CONFIG_FILE_ORIG_PATH)) { + result = TotpConfigFileUpdateError; + } + } + totp_close_storage(); + return result; } -void totp_config_file_load_base(PluginState* const plugin_state) { +TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_state) { Storage* storage = totp_open_storage(); - FlipperFormat* fff_data_file = totp_open_config_file(storage); + FlipperFormat* fff_data_file; + + TotpConfigFileOpenResult result; + if((result = totp_open_config_file(storage, &fff_data_file)) != TotpConfigFileOpenSuccess) { + totp_close_storage(); + return result; + } plugin_state->timezone_offset = 0; FuriString* temp_str = furi_string_alloc(); - uint32_t file_version; - if(!flipper_format_read_header(fff_data_file, temp_str, &file_version)) { - FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header"); - furi_string_free(temp_str); - return; - } - - if(file_version < CONFIG_FILE_ACTUAL_VERSION) { - FURI_LOG_I( - LOGGING_TAG, - "Obsolete config file version detected. Current version: %" PRIu32 - "; Actual version: %" PRId16, - file_version, - CONFIG_FILE_ACTUAL_VERSION); - totp_close_config_file(fff_data_file); - - if(storage_common_stat(storage, CONFIG_FILE_BACKUP_PATH, NULL) == FSE_OK) { - storage_simply_remove(storage, CONFIG_FILE_BACKUP_PATH); + do { + uint32_t file_version; + if(!flipper_format_read_header(fff_data_file, temp_str, &file_version)) { + FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header"); + result = TotpConfigFileOpenError; + break; } - if(storage_common_copy(storage, CONFIG_FILE_PATH, CONFIG_FILE_BACKUP_PATH) == FSE_OK) { - FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", CONFIG_FILE_BACKUP_PATH); - fff_data_file = totp_open_config_file(storage); - FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage); - flipper_format_file_open_existing(fff_backup_data_file, CONFIG_FILE_BACKUP_PATH); + if(file_version < CONFIG_FILE_ACTUAL_VERSION) { + FURI_LOG_I( + LOGGING_TAG, + "Obsolete config file version detected. Current version: %" PRIu32 + "; Actual version: %" PRId16, + file_version, + CONFIG_FILE_ACTUAL_VERSION); + totp_close_config_file(fff_data_file); - if(file_version == 1) { - if(totp_config_migrate_v1_to_v2(fff_data_file, fff_backup_data_file)) { - FURI_LOG_I(LOGGING_TAG, "Applied migration from v1 to v2"); - } else { - FURI_LOG_W(LOGGING_TAG, "An error occurred during migration from v1 to v2"); - } + if(storage_common_stat(storage, CONFIG_FILE_BACKUP_PATH, NULL) == FSE_OK) { + storage_simply_remove(storage, CONFIG_FILE_BACKUP_PATH); } - flipper_format_file_close(fff_backup_data_file); - flipper_format_free(fff_backup_data_file); - flipper_format_rewind(fff_data_file); - } else { - FURI_LOG_E( - LOGGING_TAG, - "An error occurred during taking backup of %s into %s before migration", - CONFIG_FILE_PATH, - CONFIG_FILE_BACKUP_PATH); + if(storage_common_copy(storage, CONFIG_FILE_PATH, CONFIG_FILE_BACKUP_PATH) == FSE_OK) { + FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", CONFIG_FILE_BACKUP_PATH); + if(totp_open_config_file(storage, &fff_data_file) != TotpConfigFileOpenSuccess) { + result = TotpConfigFileOpenError; + break; + } + + FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage); + if(!flipper_format_file_open_existing( + fff_backup_data_file, CONFIG_FILE_BACKUP_PATH)) { + flipper_format_file_close(fff_backup_data_file); + flipper_format_free(fff_backup_data_file); + result = TotpConfigFileOpenError; + break; + } + + if(file_version == 1) { + if(totp_config_migrate_v1_to_v2(fff_data_file, fff_backup_data_file)) { + FURI_LOG_I(LOGGING_TAG, "Applied migration from v1 to v2"); + } else { + FURI_LOG_W( + LOGGING_TAG, "An error occurred during migration from v1 to v2"); + result = TotpConfigFileOpenError; + break; + } + } + + flipper_format_file_close(fff_backup_data_file); + flipper_format_free(fff_backup_data_file); + flipper_format_rewind(fff_data_file); + } else { + FURI_LOG_E( + LOGGING_TAG, + "An error occurred during taking backup of %s into %s before migration", + CONFIG_FILE_PATH, + CONFIG_FILE_BACKUP_PATH); + result = TotpConfigFileOpenError; + break; + } } - } - if(!flipper_format_read_hex( - fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) { - FURI_LOG_D(LOGGING_TAG, "Missing base IV"); - } - - flipper_format_rewind(fff_data_file); - - uint32_t crypto_size; - if(flipper_format_get_value_count(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, &crypto_size) && - crypto_size > 0) { - plugin_state->crypto_verify_data = malloc(sizeof(uint8_t) * crypto_size); - furi_check(plugin_state->crypto_verify_data != NULL); - plugin_state->crypto_verify_data_length = crypto_size; if(!flipper_format_read_hex( - fff_data_file, - TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_verify_data, - crypto_size)) { - FURI_LOG_D(LOGGING_TAG, "Missing crypto verify token"); - free(plugin_state->crypto_verify_data); + fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) { + FURI_LOG_D(LOGGING_TAG, "Missing base IV"); + } + + if(!flipper_format_rewind(fff_data_file)) { + result = TotpConfigFileOpenError; + break; + } + + uint32_t crypto_size; + if(flipper_format_get_value_count( + fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, &crypto_size) && + crypto_size > 0) { + plugin_state->crypto_verify_data = malloc(sizeof(uint8_t) * crypto_size); + furi_check(plugin_state->crypto_verify_data != NULL); + plugin_state->crypto_verify_data_length = crypto_size; + if(!flipper_format_read_hex( + fff_data_file, + TOTP_CONFIG_KEY_CRYPTO_VERIFY, + plugin_state->crypto_verify_data, + crypto_size)) { + FURI_LOG_D(LOGGING_TAG, "Missing crypto verify token"); + free(plugin_state->crypto_verify_data); + plugin_state->crypto_verify_data = NULL; + plugin_state->crypto_verify_data_length = 0; + } + } else { plugin_state->crypto_verify_data = NULL; plugin_state->crypto_verify_data_length = 0; } - } else { - plugin_state->crypto_verify_data = NULL; - plugin_state->crypto_verify_data_length = 0; - } - flipper_format_rewind(fff_data_file); + if(!flipper_format_rewind(fff_data_file)) { + result = TotpConfigFileOpenError; + break; + } - if(!flipper_format_read_float( - fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { - plugin_state->timezone_offset = 0; - FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0"); - } + if(!flipper_format_read_float( + fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) { + plugin_state->timezone_offset = 0; + FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0"); + } - flipper_format_rewind(fff_data_file); + if(!flipper_format_rewind(fff_data_file)) { + result = TotpConfigFileOpenError; + break; + } - if(!flipper_format_read_bool( - fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { - plugin_state->pin_set = true; - } + if(!flipper_format_read_bool( + fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { + plugin_state->pin_set = true; + } - flipper_format_rewind(fff_data_file); + flipper_format_rewind(fff_data_file); - uint32_t tmp_uint32; - if(!flipper_format_read_uint32( - fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { - tmp_uint32 = NotificationMethodSound | NotificationMethodVibro; - } + uint32_t tmp_uint32; + if(!flipper_format_read_uint32( + fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) { + tmp_uint32 = NotificationMethodSound | NotificationMethodVibro; + } - plugin_state->notification_method = tmp_uint32; + plugin_state->notification_method = tmp_uint32; + } while(false); furi_string_free(temp_str); totp_close_config_file(fff_data_file); totp_close_storage(); + return result; } TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) { Storage* storage = totp_open_storage(); - FlipperFormat* fff_data_file = totp_open_config_file(storage); + FlipperFormat* fff_data_file; + if(totp_open_config_file(storage, &fff_data_file) != TotpConfigFileOpenSuccess) { + totp_close_storage(); + return TokenLoadingResultError; + } FuriString* temp_str = furi_string_alloc(); uint32_t temp_data32; if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) { FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header"); + totp_close_storage(); furi_string_free(temp_str); return TokenLoadingResultError; } @@ -459,8 +692,42 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) return result; } -void totp_close_config_file(FlipperFormat* file) { - if(file == NULL) return; - flipper_format_file_close(file); - flipper_format_free(file); -} +TotpConfigFileUpdateResult + totp_config_file_update_crypto_signatures(const PluginState* plugin_state) { + Storage* storage = totp_open_storage(); + FlipperFormat* config_file; + TotpConfigFileUpdateResult update_result; + if(totp_open_config_file(storage, &config_file) == TotpConfigFileOpenSuccess) { + do { + if(!flipper_format_insert_or_update_hex( + config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE)) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_insert_or_update_hex( + config_file, + TOTP_CONFIG_KEY_CRYPTO_VERIFY, + plugin_state->crypto_verify_data, + plugin_state->crypto_verify_data_length)) { + update_result = TotpConfigFileUpdateError; + break; + } + + if(!flipper_format_insert_or_update_bool( + config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); + + totp_close_config_file(config_file); + } else { + update_result = TotpConfigFileUpdateError; + } + + totp_close_storage(); + return update_result; +} \ No newline at end of file diff --git a/applications/plugins/totp/services/config/config.h b/applications/plugins/totp/services/config/config.h index 1eabe3365..bb48105f7 100644 --- a/applications/plugins/totp/services/config/config.h +++ b/applications/plugins/totp/services/config/config.h @@ -7,6 +7,8 @@ #include "constants.h" typedef uint8_t TokenLoadingResult; +typedef uint8_t TotpConfigFileOpenResult; +typedef uint8_t TotpConfigFileUpdateResult; /** * @brief Token loading results @@ -29,40 +31,48 @@ enum TokenLoadingResults { }; /** - * @brief Opens storage record - * @return Storage record + * @brief Config file opening result */ -Storage* totp_open_storage(); +enum TotpConfigFileOpenResults { + /** + * @brief Config file opened successfully + */ + TotpConfigFileOpenSuccess = 0, + + /** + * @brief An error has occurred during opening config file + */ + TotpConfigFileOpenError = 1 +}; /** - * @brief Closes storage record + * @brief Config file updating result */ -void totp_close_storage(); +enum TotpConfigFileUpdateResults { + /** + * @brief Config file updated successfully + */ + TotpConfigFileUpdateSuccess, -/** - * @brief Opens or creates TOTP application standard config file - * @param storage storage record to use - * @return Config file reference - */ -FlipperFormat* totp_open_config_file(Storage* storage); - -/** - * @brief Closes config file - * @param file config file reference - */ -void totp_close_config_file(FlipperFormat* file); + /** + * @brief An error has occurred during updating config file + */ + TotpConfigFileUpdateError +}; /** * @brief Saves all the settings and tokens to an application config file * @param plugin_state application state + * @return Config file update result */ -void totp_full_save_config_file(const PluginState* const plugin_state); +TotpConfigFileUpdateResult totp_full_save_config_file(const PluginState* const plugin_state); /** * @brief Loads basic information from an application config file into application state without loading all the tokens * @param plugin_state application state + * @return Config file open result */ -void totp_config_file_load_base(PluginState* const plugin_state); +TotpConfigFileOpenResult totp_config_file_load_base(PluginState* const plugin_state); /** * @brief Loads tokens from an application config file into application state @@ -74,23 +84,36 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) /** * @brief Add new token to the end of the application config file * @param token_info token information to be saved + * @return Config file update result */ -void totp_config_file_save_new_token(const TokenInfo* token_info); +TotpConfigFileUpdateResult totp_config_file_save_new_token(const TokenInfo* token_info); /** * @brief Updates timezone offset in an application config file * @param new_timezone_offset new timezone offset to be set + * @return Config file update result */ -void totp_config_file_update_timezone_offset(float new_timezone_offset); +TotpConfigFileUpdateResult totp_config_file_update_timezone_offset(float new_timezone_offset); /** * @brief Updates notification method in an application config file * @param new_notification_method new notification method to be set + * @return Config file update result */ -void totp_config_file_update_notification_method(NotificationMethod new_notification_method); +TotpConfigFileUpdateResult + totp_config_file_update_notification_method(NotificationMethod new_notification_method); /** * @brief Updates application user settings * @param plugin_state application state + * @return Config file update result */ -void totp_config_file_update_user_settings(const PluginState* plugin_state); \ No newline at end of file +TotpConfigFileUpdateResult totp_config_file_update_user_settings(const PluginState* plugin_state); + +/** + * @brief Updates crypto signatures information + * @param plugin_state application state + * @return Config file update result + */ +TotpConfigFileUpdateResult + totp_config_file_update_crypto_signatures(const PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/services/crypto/crypto.c b/applications/plugins/totp/services/crypto/crypto.c index 794d0b0be..ed4775dfb 100644 --- a/applications/plugins/totp/services/crypto/crypto.c +++ b/applications/plugins/totp/services/crypto/crypto.c @@ -61,7 +61,7 @@ uint8_t* totp_crypto_decrypt( return decrypted_data; } -void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { +bool totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { if(plugin_state->crypto_verify_data == NULL) { FURI_LOG_D(LOGGING_TAG, "Generating new IV"); furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE); @@ -94,13 +94,12 @@ void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t } } + bool result = true; if(plugin_state->crypto_verify_data == NULL) { FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data"); plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH); furi_check(plugin_state->crypto_verify_data != NULL); plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH; - Storage* storage = totp_open_storage(); - FlipperFormat* config_file = totp_open_config_file(storage); plugin_state->crypto_verify_data = totp_crypto_encrypt( (uint8_t*)CRYPTO_VERIFY_KEY, @@ -108,19 +107,13 @@ void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t &plugin_state->iv[0], &plugin_state->crypto_verify_data_length); - flipper_format_insert_or_update_hex( - config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE); - flipper_format_insert_or_update_hex( - config_file, - TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_verify_data, - CRYPTO_VERIFY_KEY_LENGTH); plugin_state->pin_set = pin != NULL && pin_length > 0; - flipper_format_insert_or_update_bool( - config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1); - totp_close_config_file(config_file); - totp_close_storage(); + + result = totp_config_file_update_crypto_signatures(plugin_state) == + TotpConfigFileUpdateSuccess; } + + return result; } bool totp_crypto_verify_key(const PluginState* plugin_state) { diff --git a/applications/plugins/totp/services/crypto/crypto.h b/applications/plugins/totp/services/crypto/crypto.h index d39fe013b..3442b9a6e 100644 --- a/applications/plugins/totp/services/crypto/crypto.h +++ b/applications/plugins/totp/services/crypto/crypto.h @@ -35,8 +35,9 @@ uint8_t* totp_crypto_decrypt( * @param plugin_state application state * @param pin user's PIN * @param pin_length user's PIN length + * @return \c true on success; \c false otherwise */ -void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); +bool totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); /** * @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption diff --git a/applications/plugins/totp/services/hmac/memxor.c b/applications/plugins/totp/services/hmac/memxor.c index 6824ea33b..ab6026aa3 100644 --- a/applications/plugins/totp/services/hmac/memxor.c +++ b/applications/plugins/totp/services/hmac/memxor.c @@ -18,8 +18,6 @@ /* Written by Simon Josefsson. The interface was inspired by memxor in Niels Möller's Nettle. */ -/* #include */ - #include "memxor.h" void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n) { diff --git a/applications/plugins/totp/totp_app.c b/applications/plugins/totp/totp_app.c index 5a551c4f1..93acf8e4d 100644 --- a/applications/plugins/totp/totp_app.c +++ b/applications/plugins/totp/totp_app.c @@ -15,6 +15,7 @@ #include "types/common.h" #include "ui/scene_director.h" #include "ui/constants.h" +#include "ui/common_dialogs.h" #include "services/crypto/crypto.h" #include "cli/cli.h" @@ -36,17 +37,7 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu furi_message_queue_put(event_queue, &event, FuriWaitForever); } -static bool totp_plugin_state_init(PluginState* const plugin_state) { - plugin_state->gui = furi_record_open(RECORD_GUI); - plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION); - plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); - - totp_config_file_load_base(plugin_state); - - totp_cli_register_command_handler(plugin_state); - - totp_scene_director_init_scenes(plugin_state); - +static bool totp_activate_initial_scene(PluginState* const plugin_state) { if(plugin_state->crypto_verify_data == NULL) { DialogMessage* message = dialog_message_alloc(); dialog_message_set_buttons(message, "No", NULL, "Yes"); @@ -63,13 +54,19 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { if(dialog_result == DialogMessageButtonRight) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); } else { - totp_crypto_seed_iv(plugin_state, NULL, 0); + if(!totp_crypto_seed_iv(plugin_state, NULL, 0)) { + totp_dialogs_config_loading_error(plugin_state); + return false; + } totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } } else if(plugin_state->pin_set) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); } else { - totp_crypto_seed_iv(plugin_state, NULL, 0); + if(!totp_crypto_seed_iv(plugin_state, NULL, 0)) { + totp_dialogs_config_loading_error(plugin_state); + return false; + } if(totp_crypto_verify_key(plugin_state)) { totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } else { @@ -94,13 +91,20 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { return true; } +static bool totp_plugin_state_init(PluginState* const plugin_state) { + plugin_state->gui = furi_record_open(RECORD_GUI); + plugin_state->notification_app = furi_record_open(RECORD_NOTIFICATION); + plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); + + if(totp_config_file_load_base(plugin_state) != TotpConfigFileOpenSuccess) { + totp_dialogs_config_loading_error(plugin_state); + return false; + } + + return true; +} + static void totp_plugin_state_free(PluginState* plugin_state) { - totp_cli_unregister_command_handler(); - - totp_scene_director_deactivate_active_scene(plugin_state); - - totp_scene_director_dispose(plugin_state); - furi_record_close(RECORD_GUI); furi_record_close(RECORD_NOTIFICATION); furi_record_close(RECORD_DIALOGS); @@ -139,6 +143,14 @@ int32_t totp_app() { return 255; } + totp_cli_register_command_handler(plugin_state); + totp_scene_director_init_scenes(plugin_state); + if(!totp_activate_initial_scene(plugin_state)) { + FURI_LOG_E(LOGGING_TAG, "An error ocurred during activating initial scene\r\n"); + totp_plugin_state_free(plugin_state); + return 253; + } + // Set system callbacks ViewPort* view_port = view_port_alloc(); view_port_draw_callback_set(view_port, render_callback, &state_mutex); @@ -171,6 +183,10 @@ int32_t totp_app() { release_mutex(&state_mutex, plugin_state_m); } + totp_cli_unregister_command_handler(); + totp_scene_director_deactivate_active_scene(plugin_state); + totp_scene_director_dispose(plugin_state); + view_port_enabled_set(view_port, false); gui_remove_view_port(plugin_state->gui, view_port); view_port_free(view_port); diff --git a/applications/plugins/totp/ui/common_dialogs.c b/applications/plugins/totp/ui/common_dialogs.c new file mode 100644 index 000000000..0a10389e1 --- /dev/null +++ b/applications/plugins/totp/ui/common_dialogs.c @@ -0,0 +1,20 @@ +#include "common_dialogs.h" +#include "constants.h" + +static DialogMessageButton totp_dialogs_common(PluginState* plugin_state, const char* text) { + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, "Exit", NULL, NULL); + dialog_message_set_text( + message, text, SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter); + DialogMessageButton result = dialog_message_show(plugin_state->dialogs_app, message); + dialog_message_free(message); + return result; +} + +DialogMessageButton totp_dialogs_config_loading_error(PluginState* plugin_state) { + return totp_dialogs_common(plugin_state, "An error has occurred\nduring loading config file"); +} + +DialogMessageButton totp_dialogs_config_updating_error(PluginState* plugin_state) { + return totp_dialogs_common(plugin_state, "An error has occurred\nduring updating config file"); +} \ No newline at end of file diff --git a/applications/plugins/totp/ui/common_dialogs.h b/applications/plugins/totp/ui/common_dialogs.h new file mode 100644 index 000000000..187d0e95c --- /dev/null +++ b/applications/plugins/totp/ui/common_dialogs.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include "../types/plugin_state.h" + +DialogMessageButton totp_dialogs_config_loading_error(PluginState* plugin_state); +DialogMessageButton totp_dialogs_config_updating_error(PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c b/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c index e6351010e..592a12d0f 100644 --- a/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c +++ b/applications/plugins/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c @@ -7,6 +7,7 @@ #include "../../../lib/list/list.h" #include "../../../services/config/config.h" #include "../../ui_controls.h" +#include "../../common_dialogs.h" #include "../../../lib/roll_value/roll_value.h" #include "../../../types/nullable.h" #include "../generate_token/totp_scene_generate_token.h" @@ -248,7 +249,11 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo, furi_check); plugin_state->tokens_count++; - totp_config_file_save_new_token(tokenInfo); + if(totp_config_file_save_new_token(tokenInfo) != TotpConfigFileUpdateSuccess) { + token_info_free(tokenInfo); + totp_dialogs_config_updating_error(plugin_state); + return false; + } GenerateTokenSceneContext generate_scene_context = { .current_token_index = plugin_state->tokens_count - 1}; diff --git a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c index 5f68c6772..b8936f395 100644 --- a/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/applications/plugins/totp/ui/scenes/app_settings/totp_app_settings.c @@ -2,6 +2,7 @@ #include #include #include "../../ui_controls.h" +#include "../../common_dialogs.h" #include "../../scene_director.h" #include "../token_menu/totp_scene_token_menu.h" #include "../../constants.h" @@ -202,7 +203,12 @@ bool totp_scene_app_settings_handle_event( NotificationMethodNone) | (scene_state->notification_vibro ? NotificationMethodVibro : NotificationMethodNone); - totp_config_file_update_user_settings(plugin_state); + + if(totp_config_file_update_user_settings(plugin_state) != + TotpConfigFileUpdateSuccess) { + totp_dialogs_config_updating_error(plugin_state); + return false; + } if(!scene_state->current_token_index.is_null) { TokenMenuSceneContext generate_scene_context = { diff --git a/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c index c90cc6b23..157a7192f 100644 --- a/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/plugins/totp/ui/scenes/generate_token/totp_scene_generate_token.c @@ -128,7 +128,7 @@ static void int_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount str[len] = '\0'; } -TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { +static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { switch(algo) { case SHA1: return TOTP_ALGO_SHA1; @@ -143,7 +143,7 @@ TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) { return NULL; } -void update_totp_params(PluginState* const plugin_state) { +static void update_totp_params(PluginState* const plugin_state) { SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; if(scene_state->current_token_index < plugin_state->tokens_count) { diff --git a/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c b/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c index dc713f0a8..167762602 100644 --- a/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c +++ b/applications/plugins/totp/ui/scenes/token_menu/totp_scene_token_menu.c @@ -2,6 +2,7 @@ #include #include #include "../../ui_controls.h" +#include "../../common_dialogs.h" #include "../../constants.h" #include "../../scene_director.h" #include "../../../services/config/config.h" @@ -156,7 +157,10 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt furi_check(tokenInfo != NULL); token_info_free(tokenInfo); - totp_full_save_config_file(plugin_state); + if(totp_full_save_config_file(plugin_state) != TotpConfigFileUpdateSuccess) { + totp_dialogs_config_updating_error(plugin_state); + return false; + } totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); } break;