MX
2023-08-05 13:57:55 +03:00
parent 74ffb02b56
commit afa7bd7f79
57 changed files with 1521 additions and 577 deletions

View File

@@ -9,7 +9,8 @@
#include "../../types/common.h"
#include "../../types/token_info.h"
#include "../../features_config.h"
#include "../crypto/crypto.h"
#include "../crypto/crypto_facade.h"
#include "../crypto/constants.h"
#include "migrations/common_migration.h"
#define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf"
@@ -110,7 +111,16 @@ static char* totp_config_file_backup_i(Storage* storage) {
static bool 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) {
bool conf_file_exists = storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK;
if(!conf_file_exists) {
FURI_LOG_I(LOGGING_TAG, "Application catalog needs to be migrated");
FS_Error migration_result =
storage_common_migrate(storage, EXT_PATH("authenticator"), CONFIG_FILE_DIRECTORY_PATH);
FURI_LOG_I(LOGGING_TAG, "Migrated catalog. Result code: %d", (int)migration_result);
conf_file_exists = storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK;
}
if(conf_file_exists) {
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);
@@ -119,16 +129,6 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** 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) {
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);
return false;
}
}
if(!flipper_format_file_open_new(fff_data_file, CONFIG_FILE_PATH)) {
totp_close_config_file(fff_data_file);
@@ -139,6 +139,13 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) {
flipper_format_write_header_cstr(
fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_ACTUAL_VERSION);
uint32_t tmp_uint32 = CRYPTO_LATEST_VERSION;
flipper_format_write_uint32(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, &tmp_uint32, 1);
tmp_uint32 = DEFAULT_CRYPTO_KEY_SLOT;
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, &tmp_uint32, 1);
flipper_format_write_comment_cstr(
fff_data_file,
"Config file format specification can be found here: https://github.com/akopachov/flipper-zero_authenticator/blob/master/docs/conf-file_description.md");
@@ -146,7 +153,7 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) {
float tmp_tz = 0;
flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &tmp_tz, 1);
uint32_t tmp_uint32 = NotificationMethodSound | NotificationMethodVibro;
tmp_uint32 = NotificationMethodSound | NotificationMethodVibro;
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1);
@@ -154,7 +161,11 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) {
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1);
tmp_uint32 = 0;
tmp_uint32 = AutomationKeyboardLayoutQWERTY;
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, &tmp_uint32, 1);
tmp_uint32 = 0; //-V1048
flipper_format_write_uint32(fff_data_file, TOTP_CONFIG_KEY_FONT, &tmp_uint32, 1);
if(!flipper_format_rewind(fff_data_file)) {
@@ -233,6 +244,12 @@ bool totp_config_file_update_automation_method(const PluginState* plugin_state)
break;
}
tmp_uint32 = plugin_state->automation_kb_layout;
if(!flipper_format_insert_or_update_uint32(
file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, &tmp_uint32, 1)) {
break;
}
update_result = true;
} while(false);
@@ -265,6 +282,12 @@ bool totp_config_file_update_user_settings(const PluginState* plugin_state) {
break;
}
tmp_uint32 = plugin_state->automation_kb_layout;
if(!flipper_format_insert_or_update_uint32(
file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, &tmp_uint32, 1)) {
break;
}
update_result = true;
} while(false);
@@ -344,8 +367,38 @@ bool totp_config_file_load(PluginState* const plugin_state) {
}
}
uint32_t tmp_uint32;
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, &tmp_uint32, 1)) {
FURI_LOG_E(LOGGING_TAG, "Missing required " TOTP_CONFIG_KEY_CRYPTO_VERSION "property");
break;
}
plugin_state->crypto_settings.crypto_version = tmp_uint32;
if(!flipper_format_rewind(fff_data_file)) {
break;
}
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, &tmp_uint32, 1)) {
FURI_LOG_E(
LOGGING_TAG, "Missing required " TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT "property");
break;
}
plugin_state->crypto_settings.crypto_key_slot = tmp_uint32;
if(!flipper_format_rewind(fff_data_file)) {
break;
}
if(!flipper_format_read_hex(
fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE)) {
fff_data_file,
TOTP_CONFIG_KEY_BASE_IV,
&plugin_state->crypto_settings.base_iv[0],
CRYPTO_IV_LENGTH)) {
FURI_LOG_D(LOGGING_TAG, "Missing base IV");
}
@@ -357,22 +410,23 @@ bool totp_config_file_load(PluginState* const plugin_state) {
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;
plugin_state->crypto_settings.crypto_verify_data =
malloc(sizeof(uint8_t) * crypto_size);
furi_check(plugin_state->crypto_settings.crypto_verify_data != NULL);
plugin_state->crypto_settings.crypto_verify_data_length = crypto_size;
if(!flipper_format_read_hex(
fff_data_file,
TOTP_CONFIG_KEY_CRYPTO_VERIFY,
plugin_state->crypto_verify_data,
plugin_state->crypto_settings.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;
free(plugin_state->crypto_settings.crypto_verify_data);
plugin_state->crypto_settings.crypto_verify_data = NULL;
plugin_state->crypto_settings.crypto_verify_data_length = 0;
}
} else {
plugin_state->crypto_verify_data = NULL;
plugin_state->crypto_verify_data_length = 0;
plugin_state->crypto_settings.crypto_verify_data = NULL;
plugin_state->crypto_settings.crypto_verify_data_length = 0;
}
if(!flipper_format_rewind(fff_data_file)) {
@@ -390,13 +444,17 @@ bool totp_config_file_load(PluginState* const plugin_state) {
}
if(!flipper_format_read_bool(
fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
plugin_state->pin_set = true;
fff_data_file,
TOTP_CONFIG_KEY_PINSET,
&plugin_state->crypto_settings.pin_required,
1)) {
plugin_state->crypto_settings.pin_required = true;
}
flipper_format_rewind(fff_data_file);
if(!flipper_format_rewind(fff_data_file)) {
break;
}
uint32_t tmp_uint32;
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_NOTIFICATION_METHOD, &tmp_uint32, 1)) {
tmp_uint32 = NotificationMethodSound | NotificationMethodVibro;
@@ -404,7 +462,9 @@ bool totp_config_file_load(PluginState* const plugin_state) {
plugin_state->notification_method = tmp_uint32;
flipper_format_rewind(fff_data_file);
if(!flipper_format_rewind(fff_data_file)) {
break;
}
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_METHOD, &tmp_uint32, 1)) {
@@ -413,6 +473,21 @@ bool totp_config_file_load(PluginState* const plugin_state) {
plugin_state->automation_method = tmp_uint32;
if(!flipper_format_rewind(fff_data_file)) {
break;
}
if(!flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, &tmp_uint32, 1)) {
tmp_uint32 = AutomationKeyboardLayoutQWERTY;
}
plugin_state->automation_kb_layout = tmp_uint32;
if(!flipper_format_rewind(fff_data_file)) {
break;
}
if(!flipper_format_read_uint32(fff_data_file, TOTP_CONFIG_KEY_FONT, &tmp_uint32, 1)) {
tmp_uint32 = 0;
}
@@ -425,7 +500,9 @@ bool totp_config_file_load(PluginState* const plugin_state) {
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);
storage,
plugin_state->config_file_context->config_file,
&plugin_state->crypto_settings);
result = true;
} while(false);
@@ -438,21 +515,39 @@ bool totp_config_file_update_crypto_signatures(const PluginState* plugin_state)
flipper_format_rewind(config_file);
bool update_result = false;
do {
uint32_t tmp_uint32 = plugin_state->crypto_settings.crypto_version;
if(!flipper_format_insert_or_update_uint32(
config_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, &tmp_uint32, 1)) {
break;
}
tmp_uint32 = plugin_state->crypto_settings.crypto_key_slot;
if(!flipper_format_insert_or_update_uint32(
config_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, &tmp_uint32, 1)) {
break;
}
if(!flipper_format_insert_or_update_hex(
config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE)) {
config_file,
TOTP_CONFIG_KEY_BASE_IV,
plugin_state->crypto_settings.base_iv,
CRYPTO_IV_LENGTH)) {
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)) {
plugin_state->crypto_settings.crypto_verify_data,
plugin_state->crypto_settings.crypto_verify_data_length)) {
break;
}
if(!flipper_format_insert_or_update_bool(
config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
config_file,
TOTP_CONFIG_KEY_PINSET,
&plugin_state->crypto_settings.pin_required,
1)) {
break;
}
@@ -480,6 +575,7 @@ void totp_config_file_reset(PluginState* const plugin_state) {
bool totp_config_file_update_encryption(
PluginState* plugin_state,
uint8_t new_crypto_key_slot,
const uint8_t* new_pin,
uint8_t new_pin_length) {
FlipperFormat* config_file = plugin_state->config_file_context->config_file;
@@ -489,23 +585,28 @@ bool totp_config_file_update_encryption(
return false;
}
uint8_t old_iv[TOTP_IV_SIZE];
memcpy(&old_iv[0], &plugin_state->iv[0], TOTP_IV_SIZE);
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;
if(!totp_crypto_check_key_slot(new_crypto_key_slot)) {
return false;
}
CryptoSeedIVResult seed_result =
totp_crypto_seed_iv(plugin_state, new_pin_length > 0 ? new_pin : NULL, new_pin_length);
CryptoSettings old_crypto_settings = plugin_state->crypto_settings;
memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH);
memset(&plugin_state->crypto_settings.base_iv[0], 0, CRYPTO_IV_LENGTH);
if(plugin_state->crypto_settings.crypto_verify_data != NULL) {
free(plugin_state->crypto_settings.crypto_verify_data);
plugin_state->crypto_settings.crypto_verify_data = NULL;
}
plugin_state->crypto_settings.crypto_key_slot = new_crypto_key_slot;
plugin_state->crypto_settings.crypto_version = CRYPTO_LATEST_VERSION;
CryptoSeedIVResult seed_result = totp_crypto_seed_iv(
&plugin_state->crypto_settings, 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;
}
seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData &&
!totp_config_file_update_crypto_signatures(plugin_state)) {
return false;
} else if(seed_result == CryptoSeedIVResultFailed) {
return false;
}
@@ -552,12 +653,15 @@ bool totp_config_file_update_encryption(
size_t plain_token_length;
uint8_t* plain_token = totp_crypto_decrypt(
encrypted_token, secret_bytes_count, &old_iv[0], &plain_token_length);
encrypted_token, secret_bytes_count, &old_crypto_settings, &plain_token_length);
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);
plain_token,
plain_token_length,
&plugin_state->crypto_settings,
&encrypted_token_length);
memset_s(plain_token, plain_token_length, 0, plain_token_length);
free(plain_token);
@@ -588,6 +692,36 @@ bool totp_config_file_update_encryption(
return result;
}
bool totp_config_file_ensure_latest_encryption(
PluginState* plugin_state,
const uint8_t* pin,
uint8_t pin_length) {
bool result = true;
if(plugin_state->crypto_settings.crypto_version < CRYPTO_LATEST_VERSION) {
FURI_LOG_I(LOGGING_TAG, "Migration to crypto v%d is needed", CRYPTO_LATEST_VERSION);
char* backup_path = totp_config_file_backup(plugin_state);
if(backup_path != NULL) {
free(backup_path);
uint8_t crypto_key_slot = plugin_state->crypto_settings.crypto_key_slot;
if(!totp_crypto_check_key_slot(crypto_key_slot)) {
crypto_key_slot = DEFAULT_CRYPTO_KEY_SLOT;
}
result =
totp_config_file_update_encryption(plugin_state, crypto_key_slot, pin, pin_length);
FURI_LOG_I(
LOGGING_TAG,
"Migration to crypto v%d is done. Result: %d",
CRYPTO_LATEST_VERSION,
result);
} else {
result = false;
}
}
return result;
}
TokenInfoIteratorContext* totp_config_get_token_iterator_context(const PluginState* plugin_state) {
return plugin_state->config_file_context->token_info_iterator_context;
}

View File

@@ -73,15 +73,29 @@ void totp_config_file_close(PluginState* const plugin_state);
/**
* @brief Updates config file encryption by re-encrypting it using new user's PIN and new randomly generated IV
* @param plugin_state application state
* @param new_crypto_key_slot new crypto key slot to be used
* @param new_pin new user's PIN
* @param new_pin_length new user's PIN length
* @return \c true if config file encryption successfully updated; \c false otherwise
*/
bool totp_config_file_update_encryption(
PluginState* plugin_state,
uint8_t new_crypto_key_slot,
const uint8_t* new_pin,
uint8_t new_pin_length);
/**
* @brief Ensures application config file uses latest encryption and upgrades encryption if needed
* @param plugin_state application state
* @param pin user's PIN
* @param pin_length user's PIN length
* @return \c true if operation succeeded; \c false otherwise
*/
bool totp_config_file_ensure_latest_encryption(
PluginState* plugin_state,
const uint8_t* pin,
uint8_t pin_length);
/**
* @brief Gets token info iterator context
* @param plugin_state application state

View File

@@ -2,9 +2,9 @@
#include <storage/storage.h>
#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("authenticator")
#define CONFIG_FILE_DIRECTORY_PATH STORAGE_APP_DATA_PATH_PREFIX
#define CONFIG_FILE_HEADER "Flipper TOTP plugin config file"
#define CONFIG_FILE_ACTUAL_VERSION (6)
#define CONFIG_FILE_ACTUAL_VERSION (8)
#define TOTP_CONFIG_KEY_TIMEZONE "Timezone"
#define TOTP_CONFIG_KEY_TOKEN_NAME "TokenName"
@@ -18,4 +18,7 @@
#define TOTP_CONFIG_KEY_PINSET "PinIsSet"
#define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod"
#define TOTP_CONFIG_KEY_AUTOMATION_METHOD "AutomationMethod"
#define TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT "AutomationKbLayout"
#define TOTP_CONFIG_KEY_FONT "Font"
#define TOTP_CONFIG_KEY_CRYPTO_VERSION "CryptoVersion"
#define TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT "CryptoKeySlot"

View File

@@ -1,6 +1,7 @@
#include "common_migration.h"
#include "../constants.h"
#include "../../../types/token_info.h"
#include "../../../types/automation_kb_layout.h"
#include <flipper_format/flipper_format_i.h>
bool totp_config_migrate_to_latest(
@@ -17,6 +18,28 @@ bool totp_config_migrate_to_latest(
break;
}
if(flipper_format_read_string(
fff_backup_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, temp_str);
} else {
uint32_t old_crypto_version = 1;
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, &old_crypto_version, 1);
}
flipper_format_rewind(fff_backup_data_file);
if(flipper_format_read_string(
fff_backup_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, temp_str);
} else {
uint32_t default_old_key_slot = 2;
flipper_format_write_uint32(
fff_data_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, &default_old_key_slot, 1);
}
flipper_format_rewind(fff_backup_data_file);
if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str)) {
flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str);
}
@@ -68,6 +91,21 @@ bool totp_config_migrate_to_latest(
flipper_format_rewind(fff_backup_data_file);
if(flipper_format_read_string(
fff_backup_data_file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, temp_str)) {
flipper_format_write_string(
fff_data_file, TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT, temp_str);
} else {
uint32_t default_automation_kb_layout = AutomationKeyboardLayoutQWERTY;
flipper_format_write_uint32(
fff_data_file,
TOTP_CONFIG_KEY_AUTOMATION_KB_LAYOUT,
&default_automation_kb_layout,
1);
}
flipper_format_rewind(fff_backup_data_file);
while(true) {
if(!flipper_format_read_string(
fff_backup_data_file, TOTP_CONFIG_KEY_TOKEN_NAME, temp_str)) {

View File

@@ -4,6 +4,7 @@
#include <flipper_format/flipper_format_stream.h>
#include <toolbox/stream/file_stream.h>
#include "../../types/common.h"
#include "../../types/crypto_settings.h"
#define CONFIG_FILE_PART_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf.part"
#define STREAM_COPY_BUFFER_SIZE 128
@@ -15,7 +16,7 @@ struct TokenInfoIteratorContext {
size_t last_seek_index;
TokenInfo* current_token;
FlipperFormat* config_file;
uint8_t* iv;
CryptoSettings* crypto_settings;
Storage* storage;
};
@@ -237,8 +238,10 @@ static bool
return result;
}
TokenInfoIteratorContext*
totp_token_info_iterator_alloc(Storage* storage, FlipperFormat* config_file, uint8_t* iv) {
TokenInfoIteratorContext* totp_token_info_iterator_alloc(
Storage* storage,
FlipperFormat* config_file,
CryptoSettings* crypto_settings) {
Stream* stream = flipper_format_get_raw_stream(config_file);
stream_rewind(stream);
size_t tokens_count = 0;
@@ -256,7 +259,7 @@ TokenInfoIteratorContext*
context->total_count = tokens_count;
context->current_token = token_info_alloc();
context->config_file = config_file;
context->iv = iv;
context->crypto_settings = crypto_settings;
context->storage = storage;
return context;
}
@@ -453,7 +456,7 @@ bool totp_token_info_iterator_go_to(TokenInfoIteratorContext* context, size_t to
furi_string_get_cstr(temp_str),
furi_string_size(temp_str),
PlainTokenSecretEncodingBase32,
context->iv)) {
context->crypto_settings)) {
FURI_LOG_W(
LOGGING_TAG,
"Token \"%s\" has plain secret",

View File

@@ -28,11 +28,13 @@ enum TotpIteratorUpdateTokenResults {
* @brief Initializes a new token info iterator
* @param storage storage reference
* @param config_file config file to use
* @param iv initialization vector (IV) to be used for encryption\decryption
* @param crypto_settings crypto settings
* @return Token info iterator context
*/
TokenInfoIteratorContext*
totp_token_info_iterator_alloc(Storage* storage, FlipperFormat* config_file, uint8_t* iv);
TokenInfoIteratorContext* totp_token_info_iterator_alloc(
Storage* storage,
FlipperFormat* config_file,
CryptoSettings* crypto_settings);
/**
* @brief Navigates iterator to the token with given index