2022-10-12 02:01:37 +00:00
# include "config.h"
# include <stdlib.h>
# include <string.h>
2023-04-26 20:50:37 +00:00
# include <flipper_format/flipper_format.h>
# include <furi_hal_rtc.h>
# include <flipper_format/flipper_format_i.h>
# include <flipper_format/flipper_format_stream.h>
# include <memset_s.h>
2022-10-12 02:01:37 +00:00
# include "../../types/common.h"
# include "../../types/token_info.h"
2023-03-21 16:03:53 +00:00
# include "../../features_config.h"
2023-04-26 20:50:37 +00:00
# include "../crypto/crypto.h"
2023-04-01 14:45:52 +00:00
# include "migrations/common_migration.h"
2022-10-12 02:01:37 +00:00
# define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH " / totp.conf"
2023-04-26 20:50:37 +00:00
# define CONFIG_FILE_BACKUP_DIR CONFIG_FILE_DIRECTORY_PATH " / backups"
# define CONFIG_FILE_BACKUP_BASE_PATH CONFIG_FILE_BACKUP_DIR " / totp.conf"
2022-12-26 20:31:38 +00:00
# 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"
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
struct ConfigFileContext {
/**
* @ brief Config file reference
*/
FlipperFormat * config_file ;
/**
* @ brief Storage reference
*/
Storage * storage ;
/**
* @ brief Token list iterator context
*/
TokenInfoIteratorContext * token_info_iterator_context ;
} ;
2022-12-26 20:31:38 +00:00
/**
* @ brief Opens storage record
* @ return Storage record
*/
static Storage * totp_open_storage ( ) {
2022-10-12 02:01:37 +00:00
return furi_record_open ( RECORD_STORAGE ) ;
}
2022-12-26 20:31:38 +00:00
/**
* @ brief Closes storage record
*/
static void totp_close_storage ( ) {
2022-10-12 02:01:37 +00:00
furi_record_close ( RECORD_STORAGE ) ;
}
2022-12-26 20:31:38 +00:00
/**
* @ 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 ) ;
}
2023-04-13 18:20:29 +00:00
/**
* @ brief Tries to take a config file backup
* @ param storage storage record
* @ return backup path if backup successfully taken ; \ c NULL otherwise
*/
static char * totp_config_file_backup_i ( Storage * storage ) {
2023-04-26 20:50:37 +00:00
if ( ! storage_dir_exists ( storage , CONFIG_FILE_BACKUP_DIR ) & &
! storage_simply_mkdir ( storage , CONFIG_FILE_BACKUP_DIR ) ) {
return NULL ;
}
FuriHalRtcDateTime current_datetime ;
furi_hal_rtc_get_datetime ( & current_datetime ) ;
uint8_t backup_path_size = sizeof ( CONFIG_FILE_BACKUP_BASE_PATH ) + 14 ;
2023-04-13 18:20:29 +00:00
char * backup_path = malloc ( backup_path_size ) ;
furi_check ( backup_path ! = NULL ) ;
memcpy ( backup_path , CONFIG_FILE_BACKUP_BASE_PATH , sizeof ( CONFIG_FILE_BACKUP_BASE_PATH ) ) ;
uint16_t i = 1 ;
bool backup_file_exists ;
2023-04-26 20:50:37 +00:00
do {
snprintf (
backup_path ,
backup_path_size ,
CONFIG_FILE_BACKUP_BASE_PATH " .%4 " PRIu16 " %02 " PRIu8 " %02 " PRIu8 " -% " PRIu16 ,
current_datetime . year ,
current_datetime . month ,
current_datetime . day ,
i ) ;
2023-04-13 18:20:29 +00:00
i + + ;
2023-04-26 20:50:37 +00:00
} while ( ( backup_file_exists = storage_common_exists ( storage , backup_path ) ) & & i < = 9999 ) ;
2023-04-13 18:20:29 +00:00
if ( backup_file_exists | |
storage_common_copy ( storage , CONFIG_FILE_PATH , backup_path ) ! = FSE_OK ) {
FURI_LOG_E ( LOGGING_TAG , " Unable to take a backup " ) ;
free ( backup_path ) ;
return NULL ;
}
FURI_LOG_I ( LOGGING_TAG , " Took config file backup to %s " , backup_path ) ;
return backup_path ;
}
2022-12-26 20:31:38 +00:00
/**
* @ 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
*/
2023-04-26 20:50:37 +00:00
static bool totp_open_config_file ( Storage * storage , FlipperFormat * * file ) {
2022-10-12 02:01:37 +00:00
FlipperFormat * fff_data_file = flipper_format_file_alloc ( storage ) ;
2022-10-13 14:00:20 +00:00
if ( storage_common_stat ( storage , CONFIG_FILE_PATH , NULL ) = = FSE_OK ) {
2022-10-12 02:01:37 +00:00
FURI_LOG_D ( LOGGING_TAG , " Config file %s found " , 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 ) ;
totp_close_config_file ( fff_data_file ) ;
2023-04-26 20:50:37 +00:00
return false ;
2022-12-26 20:31:38 +00:00
}
} 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 ) ;
2023-04-26 20:50:37 +00:00
return false ;
2022-12-26 20:31:38 +00:00
}
}
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 ) ;
2023-04-26 20:50:37 +00:00
return false ;
2022-10-12 02:01:37 +00:00
}
2022-12-26 20:31:38 +00:00
FURI_LOG_I ( LOGGING_TAG , " Applied config file path migration " ) ;
return totp_open_config_file ( storage , file ) ;
2022-10-12 02:01:37 +00:00
} else {
FURI_LOG_D ( LOGGING_TAG , " Config file %s is not found. Will create new. " , CONFIG_FILE_PATH ) ;
2022-10-13 14:00:20 +00:00
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 ) ) {
2022-10-12 02:01:37 +00:00
FURI_LOG_E ( LOGGING_TAG , " Error creating directory %s " , CONFIG_FILE_DIRECTORY_PATH ) ;
2023-04-26 20:50:37 +00:00
return false ;
2022-10-12 02:01:37 +00:00
}
}
2022-10-13 14:00:20 +00:00
if ( ! flipper_format_file_open_new ( fff_data_file , CONFIG_FILE_PATH ) ) {
2022-10-12 02:01:37 +00:00
totp_close_config_file ( fff_data_file ) ;
FURI_LOG_E ( LOGGING_TAG , " Error creating new file %s " , CONFIG_FILE_PATH ) ;
2023-04-26 20:50:37 +00:00
return false ;
2022-10-12 02:01:37 +00:00
}
2022-10-13 14:00:20 +00:00
flipper_format_write_header_cstr (
fff_data_file , CONFIG_FILE_HEADER , CONFIG_FILE_ACTUAL_VERSION ) ;
2023-04-26 20:50:37 +00:00
2022-10-13 14:00:20 +00:00
flipper_format_write_comment_cstr (
fff_data_file ,
2023-04-26 20:50:37 +00:00
" Config file format specification can be found here: https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md " ) ;
float tmp_tz = 0 ;
2022-10-12 02:01:37 +00:00
flipper_format_write_float ( fff_data_file , TOTP_CONFIG_KEY_TIMEZONE , & tmp_tz , 1 ) ;
2022-11-23 22:19:19 +00:00
uint32_t tmp_uint32 = NotificationMethodSound | NotificationMethodVibro ;
flipper_format_write_uint32 (
fff_data_file , TOTP_CONFIG_KEY_NOTIFICATION_METHOD , & tmp_uint32 , 1 ) ;
2023-03-21 16:03:53 +00:00
tmp_uint32 = AutomationMethodBadUsb ;
flipper_format_write_uint32 (
fff_data_file , TOTP_CONFIG_KEY_AUTOMATION_METHOD , & tmp_uint32 , 1 ) ;
2022-10-12 02:01:37 +00:00
if ( ! flipper_format_rewind ( fff_data_file ) ) {
totp_close_config_file ( fff_data_file ) ;
FURI_LOG_E ( LOGGING_TAG , " Rewind error " ) ;
2023-04-26 20:50:37 +00:00
return false ;
2022-10-12 02:01:37 +00:00
}
}
2022-10-13 14:00:20 +00:00
2022-12-26 20:31:38 +00:00
* file = fff_data_file ;
2023-04-26 20:50:37 +00:00
return true ;
2022-10-12 02:01:37 +00:00
}
2023-04-26 20:50:37 +00:00
char * totp_config_file_backup ( const PluginState * plugin_state ) {
if ( plugin_state - > config_file_context = = NULL ) return NULL ;
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
totp_close_config_file ( plugin_state - > config_file_context - > config_file ) ;
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
char * result = totp_config_file_backup_i ( plugin_state - > config_file_context - > storage ) ;
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
totp_open_config_file (
plugin_state - > config_file_context - > storage ,
& plugin_state - > config_file_context - > config_file ) ;
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
totp_token_info_iterator_attach_to_config_file (
plugin_state - > config_file_context - > token_info_iterator_context ,
plugin_state - > config_file_context - > config_file ) ;
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
return result ;
}
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
bool totp_config_file_update_timezone_offset ( const PluginState * plugin_state ) {
FlipperFormat * file = plugin_state - > config_file_context - > config_file ;
flipper_format_rewind ( file ) ;
bool update_result = false ;
2023-01-18 16:52:33 +00:00
2023-04-26 20:50:37 +00:00
do {
if ( ! flipper_format_insert_or_update_float (
file , TOTP_CONFIG_KEY_TIMEZONE , & plugin_state - > timezone_offset , 1 ) ) {
2023-04-01 14:45:52 +00:00
break ;
}
2023-04-26 20:50:37 +00:00
update_result = true ;
2022-12-26 20:31:38 +00:00
} while ( false ) ;
return update_result ;
2022-10-12 02:01:37 +00:00
}
2023-04-26 20:50:37 +00:00
bool totp_config_file_update_notification_method ( const PluginState * plugin_state ) {
FlipperFormat * file = plugin_state - > config_file_context - > config_file ;
flipper_format_rewind ( file ) ;
bool update_result = false ;
2022-11-23 22:19:19 +00:00
2023-04-26 20:50:37 +00:00
do {
uint32_t tmp_uint32 = plugin_state - > notification_method ;
if ( ! flipper_format_insert_or_update_uint32 (
file , TOTP_CONFIG_KEY_NOTIFICATION_METHOD , & tmp_uint32 , 1 ) ) {
break ;
}
2022-11-23 22:19:19 +00:00
2023-04-26 20:50:37 +00:00
update_result = true ;
} while ( false ) ;
2022-11-23 22:19:19 +00:00
2022-12-26 20:31:38 +00:00
return update_result ;
2022-11-23 22:19:19 +00:00
}
2023-04-26 20:50:37 +00:00
bool totp_config_file_update_automation_method ( const PluginState * plugin_state ) {
FlipperFormat * file = plugin_state - > config_file_context - > config_file ;
flipper_format_rewind ( file ) ;
bool update_result = false ;
2022-12-26 20:31:38 +00:00
do {
2023-04-26 20:50:37 +00:00
uint32_t tmp_uint32 = plugin_state - > automation_method ;
if ( ! flipper_format_insert_or_update_uint32 (
file , TOTP_CONFIG_KEY_AUTOMATION_METHOD , & tmp_uint32 , 1 ) ) {
2022-12-26 20:31:38 +00:00
break ;
}
2023-04-26 20:50:37 +00:00
update_result = true ;
} while ( false ) ;
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
return update_result ;
}
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
bool totp_config_file_update_user_settings ( const PluginState * plugin_state ) {
FlipperFormat * file = plugin_state - > config_file_context - > config_file ;
flipper_format_rewind ( file ) ;
bool update_result = false ;
do {
if ( ! flipper_format_insert_or_update_float (
file , TOTP_CONFIG_KEY_TIMEZONE , & plugin_state - > timezone_offset , 1 ) ) {
2022-12-26 20:31:38 +00:00
break ;
}
uint32_t tmp_uint32 = plugin_state - > notification_method ;
2023-04-26 20:50:37 +00:00
if ( ! flipper_format_insert_or_update_uint32 (
file , TOTP_CONFIG_KEY_NOTIFICATION_METHOD , & tmp_uint32 , 1 ) ) {
2022-12-26 20:31:38 +00:00
break ;
}
2023-03-21 16:03:53 +00:00
tmp_uint32 = plugin_state - > automation_method ;
2023-04-26 20:50:37 +00:00
if ( ! flipper_format_insert_or_update_uint32 (
file , TOTP_CONFIG_KEY_AUTOMATION_METHOD , & tmp_uint32 , 1 ) ) {
2023-03-21 16:03:53 +00:00
break ;
}
2023-04-26 20:50:37 +00:00
update_result = true ;
2022-12-26 20:31:38 +00:00
} while ( false ) ;
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
return update_result ;
2022-10-12 02:01:37 +00:00
}
2023-04-26 20:50:37 +00:00
bool totp_config_file_load ( PluginState * const plugin_state ) {
2022-10-12 02:01:37 +00:00
Storage * storage = totp_open_storage ( ) ;
2022-12-26 20:31:38 +00:00
FlipperFormat * fff_data_file ;
2023-04-26 20:50:37 +00:00
if ( ! totp_open_config_file ( storage , & fff_data_file ) ) {
2022-12-26 20:31:38 +00:00
totp_close_storage ( ) ;
2023-04-26 20:50:37 +00:00
return false ;
2022-12-26 20:31:38 +00:00
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
flipper_format_rewind ( fff_data_file ) ;
bool result = false ;
2022-10-12 02:01:37 +00:00
plugin_state - > timezone_offset = 0 ;
FuriString * temp_str = furi_string_alloc ( ) ;
2022-12-26 20:31:38 +00:00
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 " ) ;
break ;
}
2022-10-12 02:01:37 +00:00
2022-12-26 20:31:38 +00:00
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 ) ;
2022-10-12 02:01:37 +00:00
2023-04-13 18:20:29 +00:00
char * backup_path = totp_config_file_backup_i ( storage ) ;
2022-10-13 14:00:20 +00:00
2023-04-13 18:20:29 +00:00
if ( backup_path ! = NULL ) {
2023-04-26 20:50:37 +00:00
if ( totp_open_config_file ( storage , & fff_data_file ) ! = true ) {
2022-12-26 20:31:38 +00:00
break ;
}
2022-10-13 14:00:20 +00:00
2022-12-26 20:31:38 +00:00
FlipperFormat * fff_backup_data_file = flipper_format_file_alloc ( storage ) ;
2023-04-13 18:20:29 +00:00
if ( ! flipper_format_file_open_existing ( fff_backup_data_file , backup_path ) ) {
2022-12-26 20:31:38 +00:00
flipper_format_file_close ( fff_backup_data_file ) ;
flipper_format_free ( fff_backup_data_file ) ;
break ;
2022-10-12 02:01:37 +00:00
}
2023-04-01 14:45:52 +00:00
if ( totp_config_migrate_to_latest ( fff_data_file , fff_backup_data_file ) ) {
FURI_LOG_I (
LOGGING_TAG ,
" Applied migration to version % " PRId16 ,
CONFIG_FILE_ACTUAL_VERSION ) ;
file_version = CONFIG_FILE_ACTUAL_VERSION ;
} else {
FURI_LOG_W (
LOGGING_TAG ,
" An error occurred during migration to version % " PRId16 ,
CONFIG_FILE_ACTUAL_VERSION ) ;
break ;
2023-01-18 16:52:33 +00:00
}
2022-12-26 20:31:38 +00:00
flipper_format_file_close ( fff_backup_data_file ) ;
flipper_format_free ( fff_backup_data_file ) ;
flipper_format_rewind ( fff_data_file ) ;
2023-04-13 18:20:29 +00:00
free ( backup_path ) ;
2022-12-26 20:31:38 +00:00
} else {
FURI_LOG_E (
LOGGING_TAG ,
2023-04-13 18:20:29 +00:00
" An error occurred during taking backup of %s before migration " ,
CONFIG_FILE_PATH ) ;
2022-12-26 20:31:38 +00:00
break ;
}
2022-10-12 02:01:37 +00:00
}
2022-12-26 20:31:38 +00:00
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 " ) ;
}
2022-10-12 02:01:37 +00:00
2022-12-26 20:31:38 +00:00
if ( ! flipper_format_rewind ( fff_data_file ) ) {
break ;
}
2022-10-12 02:01:37 +00:00
2022-12-26 20:31:38 +00:00
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 {
2022-10-12 02:01:37 +00:00
plugin_state - > crypto_verify_data = NULL ;
2022-10-17 18:22:34 +00:00
plugin_state - > crypto_verify_data_length = 0 ;
2022-10-12 02:01:37 +00:00
}
2022-12-26 20:31:38 +00:00
if ( ! flipper_format_rewind ( fff_data_file ) ) {
break ;
}
2022-10-12 02:01:37 +00:00
2022-12-26 20:31:38 +00:00
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 " ) ;
}
2022-10-12 02:01:37 +00:00
2022-12-26 20:31:38 +00:00
if ( ! flipper_format_rewind ( fff_data_file ) ) {
break ;
}
2022-10-17 18:22:34 +00:00
2022-12-26 20:31:38 +00:00
if ( ! flipper_format_read_bool (
fff_data_file , TOTP_CONFIG_KEY_PINSET , & plugin_state - > pin_set , 1 ) ) {
plugin_state - > pin_set = true ;
}
2022-10-17 18:22:34 +00:00
2022-12-26 20:31:38 +00:00
flipper_format_rewind ( fff_data_file ) ;
2022-11-23 22:19:19 +00:00
2022-12-26 20:31:38 +00:00
uint32_t tmp_uint32 ;
if ( ! flipper_format_read_uint32 (
fff_data_file , TOTP_CONFIG_KEY_NOTIFICATION_METHOD , & tmp_uint32 , 1 ) ) {
tmp_uint32 = NotificationMethodSound | NotificationMethodVibro ;
}
2022-11-23 22:19:19 +00:00
2022-12-26 20:31:38 +00:00
plugin_state - > notification_method = tmp_uint32 ;
2023-03-21 16:03:53 +00:00
flipper_format_rewind ( fff_data_file ) ;
if ( ! flipper_format_read_uint32 (
fff_data_file , TOTP_CONFIG_KEY_AUTOMATION_METHOD , & tmp_uint32 , 1 ) ) {
tmp_uint32 = AutomationMethodBadUsb ;
}
plugin_state - > automation_method = tmp_uint32 ;
2023-04-26 20:50:37 +00:00
plugin_state - > config_file_context = malloc ( sizeof ( ConfigFileContext ) ) ;
furi_check ( plugin_state - > config_file_context ! = NULL ) ;
plugin_state - > config_file_context - > storage = storage ;
plugin_state - > config_file_context - > config_file = fff_data_file ;
plugin_state - > config_file_context - > token_info_iterator_context =
totp_token_info_iterator_alloc (
storage , plugin_state - > config_file_context - > config_file , plugin_state - > iv ) ;
result = true ;
2022-12-26 20:31:38 +00:00
} while ( false ) ;
2022-11-23 22:19:19 +00:00
2022-10-12 02:01:37 +00:00
furi_string_free ( temp_str ) ;
2022-12-26 20:31:38 +00:00
return result ;
2022-10-12 02:01:37 +00:00
}
2023-04-26 20:50:37 +00:00
bool totp_config_file_update_crypto_signatures ( const PluginState * plugin_state ) {
FlipperFormat * config_file = plugin_state - > config_file_context - > config_file ;
flipper_format_rewind ( config_file ) ;
bool update_result = false ;
do {
if ( ! flipper_format_insert_or_update_hex (
config_file , TOTP_CONFIG_KEY_BASE_IV , plugin_state - > base_iv , TOTP_IV_SIZE ) ) {
break ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
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 ) ) {
break ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
if ( ! flipper_format_insert_or_update_bool (
config_file , TOTP_CONFIG_KEY_PINSET , & plugin_state - > pin_set , 1 ) ) {
2022-10-12 02:01:37 +00:00
break ;
}
2022-10-13 14:00:20 +00:00
2023-04-26 20:50:37 +00:00
update_result = true ;
} while ( false ) ;
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
return update_result ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
void totp_config_file_close ( PluginState * const plugin_state ) {
if ( plugin_state - > config_file_context = = NULL ) return ;
totp_token_info_iterator_free ( plugin_state - > config_file_context - > token_info_iterator_context ) ;
totp_close_config_file ( plugin_state - > config_file_context - > config_file ) ;
free ( plugin_state - > config_file_context ) ;
plugin_state - > config_file_context = NULL ;
totp_close_storage ( ) ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
void totp_config_file_reset ( PluginState * const plugin_state ) {
totp_config_file_close ( plugin_state ) ;
Storage * storage = totp_open_storage ( ) ;
storage_simply_remove ( storage , CONFIG_FILE_PATH ) ;
totp_close_storage ( ) ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
bool totp_config_file_update_encryption (
PluginState * plugin_state ,
const uint8_t * new_pin ,
uint8_t new_pin_length ) {
FlipperFormat * config_file = plugin_state - > config_file_context - > config_file ;
Stream * stream = flipper_format_get_raw_stream ( config_file ) ;
size_t original_offset = stream_tell ( stream ) ;
if ( ! stream_rewind ( stream ) ) {
return false ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
uint8_t old_iv [ TOTP_IV_SIZE ] ;
memcpy ( & old_iv [ 0 ] , & plugin_state - > iv [ 0 ] , TOTP_IV_SIZE ) ;
2022-10-13 14:00:20 +00:00
2023-04-26 20:50:37 +00:00
memset ( & plugin_state - > iv [ 0 ] , 0 , TOTP_IV_SIZE ) ;
memset ( & plugin_state - > base_iv [ 0 ] , 0 , TOTP_IV_SIZE ) ;
if ( plugin_state - > crypto_verify_data ! = NULL ) {
free ( plugin_state - > crypto_verify_data ) ;
plugin_state - > crypto_verify_data = NULL ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
CryptoSeedIVResult seed_result =
totp_crypto_seed_iv ( plugin_state , new_pin_length > 0 ? new_pin : NULL , new_pin_length ) ;
if ( seed_result & CryptoSeedIVResultFlagSuccess & &
seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData ) {
if ( ! totp_config_file_update_crypto_signatures ( plugin_state ) ) {
return false ;
2023-01-18 16:52:33 +00:00
}
2023-04-26 20:50:37 +00:00
} else if ( seed_result = = CryptoSeedIVResultFailed ) {
return false ;
}
2023-01-18 16:52:33 +00:00
2023-04-26 20:50:37 +00:00
char buffer [ sizeof ( TOTP_CONFIG_KEY_TOKEN_SECRET ) + 1 ] ;
bool result = true ;
while ( true ) {
if ( ! stream_seek_to_char ( stream , ' \n ' , StreamDirectionForward ) ) {
break ;
2023-04-01 14:45:52 +00:00
}
2023-04-26 20:50:37 +00:00
size_t buffer_read_size ;
if ( ( buffer_read_size = stream_read ( stream , ( uint8_t * ) & buffer [ 0 ] , sizeof ( buffer ) ) ) = = 0 ) {
break ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
if ( ! stream_seek ( stream , - ( int32_t ) buffer_read_size , StreamOffsetFromCurrent ) ) {
result = false ;
break ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
if ( strncmp ( buffer , " \n " TOTP_CONFIG_KEY_TOKEN_SECRET " : " , sizeof ( buffer ) ) = = 0 ) {
uint32_t secret_bytes_count ;
if ( ! flipper_format_get_value_count (
config_file , TOTP_CONFIG_KEY_TOKEN_SECRET , & secret_bytes_count ) ) {
secret_bytes_count = 0 ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
if ( secret_bytes_count > 1 ) {
size_t secret_token_start = stream_tell ( stream ) + 1 ;
uint8_t * encrypted_token = malloc ( secret_bytes_count ) ;
furi_check ( encrypted_token ! = NULL ) ;
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
if ( ! flipper_format_read_hex (
config_file ,
TOTP_CONFIG_KEY_TOKEN_SECRET ,
encrypted_token ,
secret_bytes_count ) ) {
result = false ;
free ( encrypted_token ) ;
break ;
}
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
size_t plain_token_length ;
uint8_t * plain_token = totp_crypto_decrypt (
encrypted_token , secret_bytes_count , & old_iv [ 0 ] , & plain_token_length ) ;
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
free ( encrypted_token ) ;
size_t encrypted_token_length ;
encrypted_token = totp_crypto_encrypt (
plain_token , plain_token_length , & plugin_state - > iv [ 0 ] , & encrypted_token_length ) ;
2022-10-21 19:56:58 +00:00
2023-04-26 20:50:37 +00:00
memset_s ( plain_token , plain_token_length , 0 , plain_token_length ) ;
free ( plain_token ) ;
2022-10-12 02:01:37 +00:00
2023-04-26 20:50:37 +00:00
if ( ! stream_seek ( stream , secret_token_start , StreamOffsetFromStart ) ) {
result = false ;
free ( encrypted_token ) ;
break ;
}
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
if ( ! flipper_format_write_hex (
config_file ,
TOTP_CONFIG_KEY_TOKEN_SECRET ,
encrypted_token ,
encrypted_token_length ) ) {
free ( encrypted_token ) ;
result = false ;
break ;
}
2022-12-26 20:31:38 +00:00
2023-04-26 20:50:37 +00:00
free ( encrypted_token ) ;
2022-12-26 20:31:38 +00:00
}
2023-04-26 20:50:37 +00:00
}
2022-12-26 20:31:38 +00:00
}
2023-04-26 20:50:37 +00:00
stream_seek ( stream , original_offset , StreamOffsetFromStart ) ;
return result ;
2023-01-06 23:07:26 +00:00
}
2023-04-26 20:50:37 +00:00
TokenInfoIteratorContext * totp_config_get_token_iterator_context ( const PluginState * plugin_state ) {
return plugin_state - > config_file_context - > token_info_iterator_context ;
2022-12-26 20:31:38 +00:00
}