From 2dac83abef8a80a80f0e0587f6e07c7eca220674 Mon Sep 17 00:00:00 2001 From: Alexander Kopachov Date: Wed, 21 Dec 2022 14:50:01 +0100 Subject: [PATCH] Implemented #49 (#50) --- flipperzero-firmware_official_dev | 2 +- flipperzero-firmware_official_stable | 2 +- totp/cli/cli_helpers.h | 3 + totp/cli/commands/add/add.c | 8 +- totp/cli/commands/delete/delete.c | 11 +- totp/cli/commands/move/move.c | 14 +- totp/cli/commands/notification/notification.c | 13 +- totp/cli/commands/pin/pin.c | 25 +- totp/cli/commands/timezone/timezone.c | 7 +- totp/services/config/config.c | 562 +++++++++++++----- totp/services/config/config.h | 67 ++- totp/services/crypto/crypto.c | 21 +- totp/services/crypto/crypto.h | 3 +- totp/services/hmac/memxor.c | 2 - totp/totp_app.c | 50 +- totp/ui/common_dialogs.c | 20 + 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 +- 21 files changed, 593 insertions(+), 249 deletions(-) create mode 100644 totp/ui/common_dialogs.c create mode 100644 totp/ui/common_dialogs.h diff --git a/flipperzero-firmware_official_dev b/flipperzero-firmware_official_dev index 2a6a3a1bf7b..7ff9414656c 160000 --- a/flipperzero-firmware_official_dev +++ b/flipperzero-firmware_official_dev @@ -1 +1 @@ -Subproject commit 2a6a3a1bf7ba1ecb42b8cbfc1b1856a54f2878b7 +Subproject commit 7ff9414656c11da3164d97a15f670d8865ce77d5 diff --git a/flipperzero-firmware_official_stable b/flipperzero-firmware_official_stable index 3c1d59f152e..09f3dc74bcf 160000 --- a/flipperzero-firmware_official_stable +++ b/flipperzero-firmware_official_stable @@ -1 +1 @@ -Subproject commit 3c1d59f152ebc06c9a42a21528ed61337470d0c5 +Subproject commit 09f3dc74bcfe815ed3ee6370c7144beacb7e8cd6 diff --git a/totp/cli/cli_helpers.h b/totp/cli/cli_helpers.h index 075822cd678..ae6fe6e0cbb 100644 --- a/totp/cli/cli_helpers.h +++ b/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/totp/cli/commands/add/add.c b/totp/cli/commands/add/add.c index 90cc0f4204c..e037546e277 100644 --- a/totp/cli/commands/add/add.c +++ b/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/totp/cli/commands/delete/delete.c b/totp/cli/commands/delete/delete.c index 7eddb96bd72..0463416931c 100644 --- a/totp/cli/commands/delete/delete.c +++ b/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/totp/cli/commands/move/move.c b/totp/cli/commands/move/move.c index 95cb8dcac27..9d47134e54a 100644 --- a/totp/cli/commands/move/move.c +++ b/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/totp/cli/commands/notification/notification.c b/totp/cli/commands/notification/notification.c index 91dd44d4ff1..5b98a857b08 100644 --- a/totp/cli/commands/notification/notification.c +++ b/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/totp/cli/commands/pin/pin.c b/totp/cli/commands/pin/pin.c index 045976eef3b..198324e2734 100644 --- a/totp/cli/commands/pin/pin.c +++ b/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/totp/cli/commands/timezone/timezone.c b/totp/cli/commands/timezone/timezone.c index 7a17c1ae23b..537cf8a4aa5 100644 --- a/totp/cli/commands/timezone/timezone.c +++ b/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/totp/services/config/config.c b/totp/services/config/config.c index 7a7d3bb3a93..b9f0e9d50b7 100644 --- a/totp/services/config/config.c +++ b/totp/services/config/config.c @@ -9,6 +9,8 @@ #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) { @@ -36,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) { @@ -52,7 +77,7 @@ 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); @@ -63,15 +88,17 @@ 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; + 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); - return NULL; + 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); + 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) { @@ -81,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( @@ -153,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 !!!"); - } - 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 !!!"); - } - 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); +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; } -void totp_config_file_save_new_token(const TokenInfo* token_info) { +TotpConfigFileUpdateResult totp_config_file_save_new_token(const TokenInfo* token_info) { 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(totp_config_file_save_new_token_i(file, token_info) != + TotpConfigFileUpdateSuccess) { + update_result = TotpConfigFileUpdateError; + break; + } - totp_config_file_save_new_token_i(file, token_info); + 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_timezone_offset(float new_timezone_offset) { +TotpConfigFileUpdateResult totp_config_file_update_timezone_offset(float new_timezone_offset) { 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, &new_timezone_offset, 1)) { + update_result = TotpConfigFileUpdateError; + break; + } - flipper_format_insert_or_update_float(file, TOTP_CONFIG_KEY_TIMEZONE, &new_timezone_offset, 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_notification_method(NotificationMethod new_notification_method) { +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; + + 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); - uint32_t tmp_uint32 = new_notification_method; - flipper_format_insert_or_update_uint32( - file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1); + 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) { +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; + } + + update_result = TotpConfigFileUpdateSuccess; + } while(false); - 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); + } else { + update_result = TotpConfigFileUpdateError; + } - totp_close_config_file(file); totp_close_storage(); + return update_result; } -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); - - 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); - }); + do { + if(!flipper_format_file_open_always(fff_data_file, CONFIG_FILE_TEMP_PATH)) { + result = TotpConfigFileUpdateError; + break; + } + + 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; - } + 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(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 < 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); - } + if(storage_common_stat(storage, CONFIG_FILE_BACKUP_PATH, NULL) == FSE_OK) { + storage_simply_remove(storage, 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); - 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(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; + } - 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"); + 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; } - } - 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(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"); - } + 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); + 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); + 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; } @@ -478,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/totp/services/config/config.h b/totp/services/config/config.h index 1eabe33650b..bb48105f754 100644 --- a/totp/services/config/config.h +++ b/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 Closes storage record - */ -void totp_close_storage(); + /** + * @brief An error has occurred during opening config file + */ + TotpConfigFileOpenError = 1 +}; /** - * @brief Opens or creates TOTP application standard config file - * @param storage storage record to use - * @return Config file reference + * @brief Config file updating result */ -FlipperFormat* totp_open_config_file(Storage* storage); +enum TotpConfigFileUpdateResults { + /** + * @brief Config file updated successfully + */ + TotpConfigFileUpdateSuccess, -/** - * @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 + */ +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 */ -void totp_config_file_update_user_settings(const PluginState* plugin_state); \ No newline at end of file +TotpConfigFileUpdateResult + totp_config_file_update_crypto_signatures(const PluginState* plugin_state); \ No newline at end of file diff --git a/totp/services/crypto/crypto.c b/totp/services/crypto/crypto.c index 794d0b0be0c..ed4775dfb25 100644 --- a/totp/services/crypto/crypto.c +++ b/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/totp/services/crypto/crypto.h b/totp/services/crypto/crypto.h index d39fe013bee..3442b9a6e91 100644 --- a/totp/services/crypto/crypto.h +++ b/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/totp/services/hmac/memxor.c b/totp/services/hmac/memxor.c index 6824ea33bb0..ab6026aa321 100644 --- a/totp/services/hmac/memxor.c +++ b/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/totp/totp_app.c b/totp/totp_app.c index 5a551c4f132..93acf8e4d17 100644 --- a/totp/totp_app.c +++ b/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 void totp_plugin_state_free(PluginState* plugin_state) { - totp_cli_unregister_command_handler(); +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_scene_director_deactivate_active_scene(plugin_state); + if(totp_config_file_load_base(plugin_state) != TotpConfigFileOpenSuccess) { + totp_dialogs_config_loading_error(plugin_state); + return false; + } - totp_scene_director_dispose(plugin_state); + return true; +} +static void totp_plugin_state_free(PluginState* 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/totp/ui/common_dialogs.c b/totp/ui/common_dialogs.c new file mode 100644 index 00000000000..0a10389e17d --- /dev/null +++ b/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/totp/ui/common_dialogs.h b/totp/ui/common_dialogs.h new file mode 100644 index 00000000000..187d0e95c96 --- /dev/null +++ b/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/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c b/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c index e6351010ec4..592a12d0f4a 100644 --- a/totp/ui/scenes/add_new_token/totp_scene_add_new_token.c +++ b/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/totp/ui/scenes/app_settings/totp_app_settings.c b/totp/ui/scenes/app_settings/totp_app_settings.c index 5f68c67728c..b8936f39554 100644 --- a/totp/ui/scenes/app_settings/totp_app_settings.c +++ b/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/totp/ui/scenes/generate_token/totp_scene_generate_token.c b/totp/ui/scenes/generate_token/totp_scene_generate_token.c index c90cc6b2345..157a7192fae 100644 --- a/totp/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/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/totp/ui/scenes/token_menu/totp_scene_token_menu.c b/totp/ui/scenes/token_menu/totp_scene_token_menu.c index dc713f0a822..16776260202 100644 --- a/totp/ui/scenes/token_menu/totp_scene_token_menu.c +++ b/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;