mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-04-25 03:29:58 -07:00
201 lines
7.5 KiB
C
201 lines
7.5 KiB
C
#include "config.h"
|
|
#include <stdlib.h>
|
|
#include "../../types/common.h"
|
|
#include "../../types/token_info.h"
|
|
|
|
#define CONFIG_FILE_DIRECTORY_PATH "/ext/apps/Misc"
|
|
#define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf"
|
|
#define CONFIG_FILE_HEADER "Flipper TOTP plugin config file"
|
|
#define CONFIG_FILE_VERSION 1
|
|
|
|
Storage* totp_open_storage() {
|
|
return furi_record_open(RECORD_STORAGE);
|
|
}
|
|
|
|
void totp_close_storage() {
|
|
furi_record_close(RECORD_STORAGE);
|
|
}
|
|
|
|
FlipperFormat* totp_open_config_file(Storage* storage) {
|
|
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
|
|
|
if (storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK) {
|
|
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);
|
|
return NULL;
|
|
}
|
|
} 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 NULL;
|
|
}
|
|
}
|
|
|
|
if (!flipper_format_file_open_new(fff_data_file, CONFIG_FILE_PATH)) {
|
|
totp_close_config_file(fff_data_file);
|
|
FURI_LOG_E(LOGGING_TAG, "Error creating new file %s", CONFIG_FILE_PATH);
|
|
return NULL;
|
|
}
|
|
|
|
flipper_format_write_header_cstr(fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_VERSION);
|
|
float tmp_tz = 0;
|
|
flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &tmp_tz, 1);
|
|
if(!flipper_format_rewind(fff_data_file)) {
|
|
totp_close_config_file(fff_data_file);
|
|
FURI_LOG_E(LOGGING_TAG, "Rewind error");
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
return fff_data_file;
|
|
}
|
|
|
|
void totp_full_save_config_file(PluginState* const plugin_state) {
|
|
Storage* storage = totp_open_storage();
|
|
FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
|
|
|
|
flipper_format_file_open_always(fff_data_file, CONFIG_FILE_PATH);
|
|
flipper_format_write_header_cstr(fff_data_file, CONFIG_FILE_HEADER, CONFIG_FILE_VERSION);
|
|
flipper_format_write_hex(fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE);
|
|
flipper_format_write_hex(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length);
|
|
flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1);
|
|
ListNode* node = plugin_state->tokens_list;
|
|
while (node != NULL) {
|
|
TokenInfo* token_info = node->data;
|
|
flipper_format_write_string_cstr(fff_data_file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name);
|
|
flipper_format_write_hex(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length);
|
|
node = node->next;
|
|
}
|
|
|
|
totp_close_config_file(fff_data_file);
|
|
totp_close_storage();
|
|
}
|
|
|
|
void totp_config_file_load_base(PluginState* const plugin_state) {
|
|
Storage* storage = totp_open_storage();
|
|
FlipperFormat* fff_data_file = totp_open_config_file(storage);
|
|
|
|
plugin_state->timezone_offset = 0;
|
|
|
|
string_t temp_str;
|
|
uint32_t temp_data32;
|
|
string_init(temp_str);
|
|
|
|
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
|
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
|
|
return;
|
|
}
|
|
|
|
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)) {
|
|
plugin_state->crypto_verify_data = malloc(sizeof(uint8_t) * crypto_size);
|
|
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;
|
|
}
|
|
}
|
|
|
|
flipper_format_rewind(fff_data_file);
|
|
|
|
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");
|
|
}
|
|
|
|
string_clear(temp_str);
|
|
totp_close_config_file(fff_data_file);
|
|
totp_close_storage();
|
|
}
|
|
|
|
void totp_config_file_load_tokens(PluginState* const plugin_state) {
|
|
Storage* storage = totp_open_storage();
|
|
FlipperFormat* fff_data_file = totp_open_config_file(storage);
|
|
|
|
string_t temp_str;
|
|
uint32_t temp_data32;
|
|
string_init(temp_str);
|
|
|
|
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
|
|
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
|
|
return;
|
|
}
|
|
|
|
uint8_t index = 0;
|
|
bool has_any_plain_secret = false;
|
|
while (true) {
|
|
if (!flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_NAME, temp_str)) {
|
|
break;
|
|
}
|
|
|
|
TokenInfo* tokenInfo = malloc(sizeof(TokenInfo));
|
|
|
|
const char* temp_cstr = string_get_cstr(temp_str);
|
|
tokenInfo->name = (char *)malloc(strlen(temp_cstr) + 1);
|
|
strcpy(tokenInfo->name, temp_cstr);
|
|
|
|
uint32_t secret_bytes_count;
|
|
if (!flipper_format_get_value_count(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, &secret_bytes_count)) {
|
|
continue;
|
|
}
|
|
|
|
if (secret_bytes_count == 1) { // Plain secret key
|
|
if (!flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str)) {
|
|
continue;
|
|
}
|
|
|
|
temp_cstr = string_get_cstr(temp_str);
|
|
token_info_set_secret(tokenInfo, temp_cstr, strlen(temp_cstr), &plugin_state->iv[0]);
|
|
has_any_plain_secret = true;
|
|
FURI_LOG_W(LOGGING_TAG, "Found token with plain secret");
|
|
} else { // encrypted
|
|
tokenInfo->token_length = secret_bytes_count;
|
|
tokenInfo->token = malloc(tokenInfo->token_length);
|
|
if (!flipper_format_read_hex(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, tokenInfo->token, tokenInfo->token_length)) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
FURI_LOG_D(LOGGING_TAG, "Found token \"%s\"", tokenInfo->name);
|
|
|
|
if (plugin_state->tokens_list == NULL) {
|
|
plugin_state->tokens_list = list_init_head(tokenInfo);
|
|
} else {
|
|
list_add(plugin_state->tokens_list, tokenInfo);
|
|
}
|
|
|
|
index++;
|
|
}
|
|
|
|
plugin_state->tokens_count = index;
|
|
plugin_state->token_list_loaded = true;
|
|
|
|
FURI_LOG_D(LOGGING_TAG, "Found %d tokens", index);
|
|
|
|
string_clear(temp_str);
|
|
totp_close_config_file(fff_data_file);
|
|
totp_close_storage();
|
|
|
|
if (has_any_plain_secret) {
|
|
totp_full_save_config_file(plugin_state);
|
|
}
|
|
}
|
|
|
|
void totp_close_config_file(FlipperFormat* file) {
|
|
if (file == NULL) return;
|
|
flipper_format_file_close(file);
|
|
flipper_format_free(file);
|
|
}
|