mirror of
https://github.com/DarkFlippers/unleashed-firmware
synced 2024-11-23 13:03:13 +00:00
Update TOTP
This commit is contained in:
parent
1243dad8fd
commit
4f05c1816b
19 changed files with 620 additions and 257 deletions
|
@ -38,6 +38,9 @@
|
||||||
TOTP_CLI_PRINTF( \
|
TOTP_CLI_PRINTF( \
|
||||||
"Invalid command arguments. use \"help\" command to get list of available commands")
|
"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.
|
* @brief Checks whether user is authenticated and entered correct PIN.
|
||||||
* If user is not authenticated it prompts user to enter correct PIN to authenticate.
|
* If user is not authenticated it prompts user to enter correct PIN to authenticate.
|
||||||
|
|
|
@ -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);
|
TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, token_info, furi_check);
|
||||||
plugin_state->tokens_count++;
|
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) {
|
if(load_generate_token_scene) {
|
||||||
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name);
|
|
||||||
}
|
}
|
|
@ -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_list = list_remove(plugin_state->tokens_list, list_node);
|
||||||
plugin_state->tokens_count--;
|
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) {
|
if(activate_generate_token_scene) {
|
||||||
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
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 {
|
} else {
|
||||||
TOTP_CLI_PRINTF("User not confirmed\r\n");
|
TOTP_CLI_PRINTF("User not confirmed\r\n");
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,18 +147,18 @@ void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, C
|
||||||
}
|
}
|
||||||
|
|
||||||
if(token_updated) {
|
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) {
|
if(activate_generate_token_scene) {
|
||||||
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
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);
|
furi_string_free(temp_str);
|
||||||
}
|
}
|
|
@ -86,15 +86,18 @@ void totp_cli_command_notification_handle(PluginState* plugin_state, FuriString*
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin_state->notification_method = new_method;
|
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) {
|
if(previous_scene != TotpSceneNone) {
|
||||||
totp_scene_director_activate_scene(plugin_state, previous_scene, NULL);
|
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 {
|
} else {
|
||||||
TOTP_CLI_PRINTF("Current notification method is ");
|
TOTP_CLI_PRINTF("Current notification method is ");
|
||||||
totp_cli_command_notification_print_method(plugin_state->notification_method);
|
totp_cli_command_notification_print_method(plugin_state->notification_method);
|
||||||
|
|
|
@ -134,8 +134,14 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl
|
||||||
plugin_state->crypto_verify_data = NULL;
|
plugin_state->crypto_verify_data = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
totp_crypto_seed_iv(
|
if(!totp_crypto_seed_iv(
|
||||||
plugin_state, new_pin_length > 0 ? &new_pin[0] : NULL, new_pin_length);
|
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, {
|
TOTP_LIST_FOREACH(plugin_state->tokens_list, node, {
|
||||||
TokenInfo* token_info = node->data;
|
TokenInfo* token_info = node->data;
|
||||||
|
@ -152,15 +158,18 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl
|
||||||
free(plain_token);
|
free(plain_token);
|
||||||
});
|
});
|
||||||
|
|
||||||
totp_full_save_config_file(plugin_state);
|
|
||||||
|
|
||||||
TOTP_CLI_DELETE_LAST_LINE();
|
TOTP_CLI_DELETE_LAST_LINE();
|
||||||
|
|
||||||
if(do_change) {
|
if(totp_full_save_config_file(plugin_state) == TotpConfigFileUpdateSuccess) {
|
||||||
TOTP_CLI_PRINTF("PIN has been successfully changed\r\n");
|
if(do_change) {
|
||||||
} else if(do_remove) {
|
TOTP_CLI_PRINTF("PIN has been successfully changed\r\n");
|
||||||
TOTP_CLI_PRINTF("PIN has been successfully removed\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);
|
} while(false);
|
||||||
|
|
||||||
if(load_generate_token_scene) {
|
if(load_generate_token_scene) {
|
||||||
|
|
|
@ -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);
|
float tz = strtof(furi_string_get_cstr(temp_str), NULL);
|
||||||
if(tz >= -12.75f && tz <= 12.75f) {
|
if(tz >= -12.75f && tz <= 12.75f) {
|
||||||
plugin_state->timezone_offset = tz;
|
plugin_state->timezone_offset = tz;
|
||||||
totp_config_file_update_timezone_offset(tz);
|
if(totp_config_file_update_timezone_offset(tz) == TotpConfigFileUpdateSuccess) {
|
||||||
TOTP_CLI_PRINTF("Timezone is set to %f\r\n", tz);
|
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) {
|
if(plugin_state->current_scene == TotpSceneGenerateToken) {
|
||||||
totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);
|
totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL);
|
||||||
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
||||||
|
|
|
@ -6,9 +6,12 @@
|
||||||
#include "../../types/token_info.h"
|
#include "../../types/token_info.h"
|
||||||
#include "migrations/config_migration_v1_to_v2.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_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf"
|
||||||
#define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup"
|
#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) {
|
static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) {
|
||||||
switch(token_info->algo) {
|
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);
|
return furi_record_open(RECORD_STORAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void totp_close_storage() {
|
/**
|
||||||
|
* @brief Closes storage record
|
||||||
|
*/
|
||||||
|
static void totp_close_storage() {
|
||||||
furi_record_close(RECORD_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);
|
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||||
|
|
||||||
if(storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK) {
|
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)) {
|
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);
|
FURI_LOG_E(LOGGING_TAG, "Error opening existing file %s", CONFIG_FILE_PATH);
|
||||||
totp_close_config_file(fff_data_file);
|
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 {
|
} else {
|
||||||
FURI_LOG_D(LOGGING_TAG, "Config file %s is not found. Will create new.", CONFIG_FILE_PATH);
|
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) {
|
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);
|
CONFIG_FILE_DIRECTORY_PATH);
|
||||||
if(!storage_simply_mkdir(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);
|
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)) {
|
if(!flipper_format_file_open_new(fff_data_file, CONFIG_FILE_PATH)) {
|
||||||
totp_close_config_file(fff_data_file);
|
totp_close_config_file(fff_data_file);
|
||||||
FURI_LOG_E(LOGGING_TAG, "Error creating new file %s", CONFIG_FILE_PATH);
|
FURI_LOG_E(LOGGING_TAG, "Error creating new file %s", CONFIG_FILE_PATH);
|
||||||
return NULL;
|
return TotpConfigFileOpenError;
|
||||||
}
|
}
|
||||||
|
|
||||||
flipper_format_write_header_cstr(
|
flipper_format_write_header_cstr(
|
||||||
|
@ -134,228 +180,415 @@ FlipperFormat* totp_open_config_file(Storage* storage) {
|
||||||
if(!flipper_format_rewind(fff_data_file)) {
|
if(!flipper_format_rewind(fff_data_file)) {
|
||||||
totp_close_config_file(fff_data_file);
|
totp_close_config_file(fff_data_file);
|
||||||
FURI_LOG_E(LOGGING_TAG, "Rewind error");
|
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) {
|
TotpConfigFileUpdateResult
|
||||||
flipper_format_seek_to_end(file);
|
totp_config_file_save_new_token_i(FlipperFormat* file, const TokenInfo* token_info) {
|
||||||
flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name);
|
TotpConfigFileUpdateResult update_result;
|
||||||
bool token_is_valid = token_info->token != NULL && token_info->token_length > 0;
|
do {
|
||||||
if(!token_is_valid) {
|
if(!flipper_format_seek_to_end(file)) {
|
||||||
flipper_format_write_comment_cstr(file, "!!! WARNING BEGIN: INVALID TOKEN !!!");
|
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);
|
totp_close_storage();
|
||||||
if(!token_is_valid) {
|
return update_result;
|
||||||
flipper_format_write_comment_cstr(file, "!!! WARNING END !!!");
|
}
|
||||||
|
|
||||||
|
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();
|
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();
|
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();
|
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();
|
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;
|
update_result = TotpConfigFileUpdateSuccess;
|
||||||
flipper_format_insert_or_update_uint32(
|
} while(false);
|
||||||
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();
|
totp_close_storage();
|
||||||
|
return update_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void totp_config_file_update_user_settings(const PluginState* plugin_state) {
|
TotpConfigFileUpdateResult totp_full_save_config_file(const PluginState* const 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) {
|
|
||||||
Storage* storage = totp_open_storage();
|
Storage* storage = totp_open_storage();
|
||||||
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
||||||
|
TotpConfigFileUpdateResult result = TotpConfigFileUpdateSuccess;
|
||||||
|
|
||||||
flipper_format_file_open_always(fff_data_file, CONFIG_FILE_PATH);
|
do {
|
||||||
flipper_format_write_header_cstr(
|
if(!flipper_format_file_open_always(fff_data_file, CONFIG_FILE_TEMP_PATH)) {
|
||||||
fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION);
|
result = TotpConfigFileUpdateError;
|
||||||
flipper_format_write_hex(
|
break;
|
||||||
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, {
|
if(!flipper_format_write_header_cstr(
|
||||||
const TokenInfo* token_info = node->data;
|
fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION)) {
|
||||||
totp_config_file_save_new_token_i(fff_data_file, token_info);
|
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);
|
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();
|
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();
|
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;
|
plugin_state->timezone_offset = 0;
|
||||||
|
|
||||||
FuriString* temp_str = furi_string_alloc();
|
FuriString* temp_str = furi_string_alloc();
|
||||||
|
|
||||||
uint32_t file_version;
|
do {
|
||||||
if(!flipper_format_read_header(fff_data_file, temp_str, &file_version)) {
|
uint32_t file_version;
|
||||||
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
|
if(!flipper_format_read_header(fff_data_file, temp_str, &file_version)) {
|
||||||
furi_string_free(temp_str);
|
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
|
||||||
return;
|
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(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) {
|
if(file_version < CONFIG_FILE_ACTUAL_VERSION) {
|
||||||
FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", CONFIG_FILE_BACKUP_PATH);
|
FURI_LOG_I(
|
||||||
fff_data_file = totp_open_config_file(storage);
|
LOGGING_TAG,
|
||||||
FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage);
|
"Obsolete config file version detected. Current version: %" PRIu32
|
||||||
flipper_format_file_open_existing(fff_backup_data_file, CONFIG_FILE_BACKUP_PATH);
|
"; Actual version: %" PRId16,
|
||||||
|
file_version,
|
||||||
|
CONFIG_FILE_ACTUAL_VERSION);
|
||||||
|
totp_close_config_file(fff_data_file);
|
||||||
|
|
||||||
if(file_version == 1) {
|
if(storage_common_stat(storage, CONFIG_FILE_BACKUP_PATH, NULL) == FSE_OK) {
|
||||||
if(totp_config_migrate_v1_to_v2(fff_data_file, fff_backup_data_file)) {
|
storage_simply_remove(storage, CONFIG_FILE_BACKUP_PATH);
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
flipper_format_file_close(fff_backup_data_file);
|
if(storage_common_copy(storage, CONFIG_FILE_PATH, CONFIG_FILE_BACKUP_PATH) == FSE_OK) {
|
||||||
flipper_format_free(fff_backup_data_file);
|
FURI_LOG_I(LOGGING_TAG, "Took config file backup to %s", CONFIG_FILE_BACKUP_PATH);
|
||||||
flipper_format_rewind(fff_data_file);
|
if(totp_open_config_file(storage, &fff_data_file) != TotpConfigFileOpenSuccess) {
|
||||||
} else {
|
result = TotpConfigFileOpenError;
|
||||||
FURI_LOG_E(
|
break;
|
||||||
LOGGING_TAG,
|
}
|
||||||
"An error occurred during taking backup of %s into %s before migration",
|
|
||||||
CONFIG_FILE_PATH,
|
FlipperFormat* fff_backup_data_file = flipper_format_file_alloc(storage);
|
||||||
CONFIG_FILE_BACKUP_PATH);
|
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(
|
if(!flipper_format_read_hex(
|
||||||
fff_data_file,
|
fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) {
|
||||||
TOTP_CONFIG_KEY_CRYPTO_VERIFY,
|
FURI_LOG_D(LOGGING_TAG, "Missing base IV");
|
||||||
plugin_state->crypto_verify_data,
|
}
|
||||||
crypto_size)) {
|
|
||||||
FURI_LOG_D(LOGGING_TAG, "Missing crypto verify token");
|
if(!flipper_format_rewind(fff_data_file)) {
|
||||||
free(plugin_state->crypto_verify_data);
|
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 = NULL;
|
||||||
plugin_state->crypto_verify_data_length = 0;
|
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(
|
if(!flipper_format_read_float(
|
||||||
fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) {
|
fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1)) {
|
||||||
plugin_state->timezone_offset = 0;
|
plugin_state->timezone_offset = 0;
|
||||||
FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 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(
|
if(!flipper_format_read_bool(
|
||||||
fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
|
fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
|
||||||
plugin_state->pin_set = true;
|
plugin_state->pin_set = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
flipper_format_rewind(fff_data_file);
|
flipper_format_rewind(fff_data_file);
|
||||||
|
|
||||||
uint32_t tmp_uint32;
|
uint32_t tmp_uint32;
|
||||||
if(!flipper_format_read_uint32(
|
if(!flipper_format_read_uint32(
|
||||||
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) {
|
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) {
|
||||||
tmp_uint32 = NotificationMethodSound | NotificationMethodVibro;
|
tmp_uint32 = NotificationMethodSound | NotificationMethodVibro;
|
||||||
}
|
}
|
||||||
|
|
||||||
plugin_state->notification_method = tmp_uint32;
|
plugin_state->notification_method = tmp_uint32;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
furi_string_free(temp_str);
|
furi_string_free(temp_str);
|
||||||
totp_close_config_file(fff_data_file);
|
totp_close_config_file(fff_data_file);
|
||||||
totp_close_storage();
|
totp_close_storage();
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) {
|
TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) {
|
||||||
Storage* storage = totp_open_storage();
|
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();
|
FuriString* temp_str = furi_string_alloc();
|
||||||
uint32_t temp_data32;
|
uint32_t temp_data32;
|
||||||
|
|
||||||
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
||||||
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
|
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
|
||||||
|
totp_close_storage();
|
||||||
furi_string_free(temp_str);
|
furi_string_free(temp_str);
|
||||||
return TokenLoadingResultError;
|
return TokenLoadingResultError;
|
||||||
}
|
}
|
||||||
|
@ -459,8 +692,42 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void totp_close_config_file(FlipperFormat* file) {
|
TotpConfigFileUpdateResult
|
||||||
if(file == NULL) return;
|
totp_config_file_update_crypto_signatures(const PluginState* plugin_state) {
|
||||||
flipper_format_file_close(file);
|
Storage* storage = totp_open_storage();
|
||||||
flipper_format_free(file);
|
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;
|
||||||
|
}
|
|
@ -7,6 +7,8 @@
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
|
|
||||||
typedef uint8_t TokenLoadingResult;
|
typedef uint8_t TokenLoadingResult;
|
||||||
|
typedef uint8_t TotpConfigFileOpenResult;
|
||||||
|
typedef uint8_t TotpConfigFileUpdateResult;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Token loading results
|
* @brief Token loading results
|
||||||
|
@ -29,40 +31,48 @@ enum TokenLoadingResults {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Opens storage record
|
* @brief Config file opening result
|
||||||
* @return Storage record
|
|
||||||
*/
|
*/
|
||||||
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
|
* @brief An error has occurred during updating config file
|
||||||
* @param storage storage record to use
|
*/
|
||||||
* @return Config file reference
|
TotpConfigFileUpdateError
|
||||||
*/
|
};
|
||||||
FlipperFormat* totp_open_config_file(Storage* storage);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Closes config file
|
|
||||||
* @param file config file reference
|
|
||||||
*/
|
|
||||||
void totp_close_config_file(FlipperFormat* file);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Saves all the settings and tokens to an application config file
|
* @brief Saves all the settings and tokens to an application config file
|
||||||
* @param plugin_state application state
|
* @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
|
* @brief Loads basic information from an application config file into application state without loading all the tokens
|
||||||
* @param plugin_state application state
|
* @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
|
* @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
|
* @brief Add new token to the end of the application config file
|
||||||
* @param token_info token information to be saved
|
* @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
|
* @brief Updates timezone offset in an application config file
|
||||||
* @param new_timezone_offset new timezone offset to be set
|
* @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
|
* @brief Updates notification method in an application config file
|
||||||
* @param new_notification_method new notification method to be set
|
* @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
|
* @brief Updates application user settings
|
||||||
* @param plugin_state application state
|
* @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);
|
|
@ -61,7 +61,7 @@ uint8_t* totp_crypto_decrypt(
|
||||||
return decrypted_data;
|
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) {
|
if(plugin_state->crypto_verify_data == NULL) {
|
||||||
FURI_LOG_D(LOGGING_TAG, "Generating new IV");
|
FURI_LOG_D(LOGGING_TAG, "Generating new IV");
|
||||||
furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE);
|
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) {
|
if(plugin_state->crypto_verify_data == NULL) {
|
||||||
FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data");
|
FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data");
|
||||||
plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH);
|
plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH);
|
||||||
furi_check(plugin_state->crypto_verify_data != NULL);
|
furi_check(plugin_state->crypto_verify_data != NULL);
|
||||||
plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH;
|
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(
|
plugin_state->crypto_verify_data = totp_crypto_encrypt(
|
||||||
(uint8_t*)CRYPTO_VERIFY_KEY,
|
(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->iv[0],
|
||||||
&plugin_state->crypto_verify_data_length);
|
&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;
|
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);
|
result = totp_config_file_update_crypto_signatures(plugin_state) ==
|
||||||
totp_close_config_file(config_file);
|
TotpConfigFileUpdateSuccess;
|
||||||
totp_close_storage();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool totp_crypto_verify_key(const PluginState* plugin_state) {
|
bool totp_crypto_verify_key(const PluginState* plugin_state) {
|
||||||
|
|
|
@ -35,8 +35,9 @@ uint8_t* totp_crypto_decrypt(
|
||||||
* @param plugin_state application state
|
* @param plugin_state application state
|
||||||
* @param pin user's PIN
|
* @param pin user's PIN
|
||||||
* @param pin_length user's PIN length
|
* @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
|
* @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
/* Written by Simon Josefsson. The interface was inspired by memxor
|
/* Written by Simon Josefsson. The interface was inspired by memxor
|
||||||
in Niels Möller's Nettle. */
|
in Niels Möller's Nettle. */
|
||||||
|
|
||||||
/* #include <config.h> */
|
|
||||||
|
|
||||||
#include "memxor.h"
|
#include "memxor.h"
|
||||||
|
|
||||||
void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n) {
|
void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n) {
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "types/common.h"
|
#include "types/common.h"
|
||||||
#include "ui/scene_director.h"
|
#include "ui/scene_director.h"
|
||||||
#include "ui/constants.h"
|
#include "ui/constants.h"
|
||||||
|
#include "ui/common_dialogs.h"
|
||||||
#include "services/crypto/crypto.h"
|
#include "services/crypto/crypto.h"
|
||||||
#include "cli/cli.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);
|
furi_message_queue_put(event_queue, &event, FuriWaitForever);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool totp_plugin_state_init(PluginState* const plugin_state) {
|
static bool totp_activate_initial_scene(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);
|
|
||||||
|
|
||||||
if(plugin_state->crypto_verify_data == NULL) {
|
if(plugin_state->crypto_verify_data == NULL) {
|
||||||
DialogMessage* message = dialog_message_alloc();
|
DialogMessage* message = dialog_message_alloc();
|
||||||
dialog_message_set_buttons(message, "No", NULL, "Yes");
|
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) {
|
if(dialog_result == DialogMessageButtonRight) {
|
||||||
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
|
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
|
||||||
} else {
|
} 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);
|
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
||||||
}
|
}
|
||||||
} else if(plugin_state->pin_set) {
|
} else if(plugin_state->pin_set) {
|
||||||
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
|
totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
|
||||||
} else {
|
} 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)) {
|
if(totp_crypto_verify_key(plugin_state)) {
|
||||||
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
||||||
} else {
|
} else {
|
||||||
|
@ -94,13 +91,20 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) {
|
||||||
return true;
|
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) {
|
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_GUI);
|
||||||
furi_record_close(RECORD_NOTIFICATION);
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
furi_record_close(RECORD_DIALOGS);
|
furi_record_close(RECORD_DIALOGS);
|
||||||
|
@ -139,6 +143,14 @@ int32_t totp_app() {
|
||||||
return 255;
|
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
|
// Set system callbacks
|
||||||
ViewPort* view_port = view_port_alloc();
|
ViewPort* view_port = view_port_alloc();
|
||||||
view_port_draw_callback_set(view_port, render_callback, &state_mutex);
|
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);
|
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);
|
view_port_enabled_set(view_port, false);
|
||||||
gui_remove_view_port(plugin_state->gui, view_port);
|
gui_remove_view_port(plugin_state->gui, view_port);
|
||||||
view_port_free(view_port);
|
view_port_free(view_port);
|
||||||
|
|
20
applications/plugins/totp/ui/common_dialogs.c
Normal file
20
applications/plugins/totp/ui/common_dialogs.c
Normal 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");
|
||||||
|
}
|
7
applications/plugins/totp/ui/common_dialogs.h
Normal file
7
applications/plugins/totp/ui/common_dialogs.h
Normal 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);
|
|
@ -7,6 +7,7 @@
|
||||||
#include "../../../lib/list/list.h"
|
#include "../../../lib/list/list.h"
|
||||||
#include "../../../services/config/config.h"
|
#include "../../../services/config/config.h"
|
||||||
#include "../../ui_controls.h"
|
#include "../../ui_controls.h"
|
||||||
|
#include "../../common_dialogs.h"
|
||||||
#include "../../../lib/roll_value/roll_value.h"
|
#include "../../../lib/roll_value/roll_value.h"
|
||||||
#include "../../../types/nullable.h"
|
#include "../../../types/nullable.h"
|
||||||
#include "../generate_token/totp_scene_generate_token.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);
|
TOTP_LIST_INIT_OR_ADD(plugin_state->tokens_list, tokenInfo, furi_check);
|
||||||
plugin_state->tokens_count++;
|
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 = {
|
GenerateTokenSceneContext generate_scene_context = {
|
||||||
.current_token_index = plugin_state->tokens_count - 1};
|
.current_token_index = plugin_state->tokens_count - 1};
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <totp_icons.h>
|
#include <totp_icons.h>
|
||||||
#include "../../ui_controls.h"
|
#include "../../ui_controls.h"
|
||||||
|
#include "../../common_dialogs.h"
|
||||||
#include "../../scene_director.h"
|
#include "../../scene_director.h"
|
||||||
#include "../token_menu/totp_scene_token_menu.h"
|
#include "../token_menu/totp_scene_token_menu.h"
|
||||||
#include "../../constants.h"
|
#include "../../constants.h"
|
||||||
|
@ -202,7 +203,12 @@ bool totp_scene_app_settings_handle_event(
|
||||||
NotificationMethodNone) |
|
NotificationMethodNone) |
|
||||||
(scene_state->notification_vibro ? NotificationMethodVibro :
|
(scene_state->notification_vibro ? NotificationMethodVibro :
|
||||||
NotificationMethodNone);
|
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) {
|
if(!scene_state->current_token_index.is_null) {
|
||||||
TokenMenuSceneContext generate_scene_context = {
|
TokenMenuSceneContext generate_scene_context = {
|
||||||
|
|
|
@ -128,7 +128,7 @@ static void int_token_to_str(uint32_t i_token_code, char* str, TokenDigitsCount
|
||||||
str[len] = '\0';
|
str[len] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
|
static TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
|
||||||
switch(algo) {
|
switch(algo) {
|
||||||
case SHA1:
|
case SHA1:
|
||||||
return TOTP_ALGO_SHA1;
|
return TOTP_ALGO_SHA1;
|
||||||
|
@ -143,7 +143,7 @@ TOTP_ALGO get_totp_algo_impl(TokenHashAlgo algo) {
|
||||||
return NULL;
|
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;
|
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
|
||||||
|
|
||||||
if(scene_state->current_token_index < plugin_state->tokens_count) {
|
if(scene_state->current_token_index < plugin_state->tokens_count) {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <dialogs/dialogs.h>
|
#include <dialogs/dialogs.h>
|
||||||
#include "../../ui_controls.h"
|
#include "../../ui_controls.h"
|
||||||
|
#include "../../common_dialogs.h"
|
||||||
#include "../../constants.h"
|
#include "../../constants.h"
|
||||||
#include "../../scene_director.h"
|
#include "../../scene_director.h"
|
||||||
#include "../../../services/config/config.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);
|
furi_check(tokenInfo != NULL);
|
||||||
token_info_free(tokenInfo);
|
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);
|
totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
Loading…
Reference in a new issue