Update TOTP

This commit is contained in:
MX 2022-12-26 23:31:38 +03:00
parent 1243dad8fd
commit 4f05c1816b
No known key found for this signature in database
GPG key ID: 6C4C311DFD4B4AB5
19 changed files with 620 additions and 257 deletions

View file

@ -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.

View file

@ -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);
}

View file

@ -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");
}

View file

@ -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);
}

View file

@ -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);

View file

@ -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) {

View file

@ -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);

View file

@ -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;
}

View file

@ -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);
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);

View file

@ -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) {

View file

@ -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

View file

@ -18,8 +18,6 @@
/* Written by Simon Josefsson. The interface was inspired by memxor
in Niels Möller's Nettle. */
/* #include <config.h> */
#include "memxor.h"
void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n) {

View file

@ -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);

View file

@ -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");
}

View file

@ -0,0 +1,7 @@
#pragma once
#include <dialogs/dialogs.h>
#include "../types/plugin_state.h"
DialogMessageButton totp_dialogs_config_loading_error(PluginState* plugin_state);
DialogMessageButton totp_dialogs_config_updating_error(PluginState* plugin_state);

View file

@ -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};

View file

@ -2,6 +2,7 @@
#include <math.h>
#include <totp_icons.h>
#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 = {

View file

@ -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) {

View file

@ -2,6 +2,7 @@
#include <gui/gui.h>
#include <dialogs/dialogs.h>
#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;