Skip to content

Commit

Permalink
A better fix for #8
Browse files Browse the repository at this point in the history
  • Loading branch information
akopachov committed Oct 21, 2022
1 parent 2674ab5 commit 75b3849
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 74 deletions.
50 changes: 33 additions & 17 deletions scenes/add_new_token/totp_scene_add_new_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -227,31 +227,47 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
break;
case ConfirmButton: {
TokenInfo* tokenInfo = token_info_alloc();
tokenInfo->name = malloc(scene_state->token_name_length + 1);
strcpy(tokenInfo->name, scene_state->token_name);

token_info_set_secret(
bool token_secret_set = token_info_set_secret(
tokenInfo,
scene_state->token_secret,
scene_state->token_secret_length,
&plugin_state->iv[0]);

tokenInfo->algo = scene_state->algo;
tokenInfo->digits = scene_state->digits_count;
if(token_secret_set) {
tokenInfo->name = malloc(scene_state->token_name_length + 1);
strcpy(tokenInfo->name, scene_state->token_name);
tokenInfo->algo = scene_state->algo;
tokenInfo->digits = scene_state->digits_count;

if(plugin_state->tokens_list == NULL) {
plugin_state->tokens_list = list_init_head(tokenInfo);
} else {
list_add(plugin_state->tokens_list, tokenInfo);
}
plugin_state->tokens_count++;
if(plugin_state->tokens_list == NULL) {
plugin_state->tokens_list = list_init_head(tokenInfo);
} else {
list_add(plugin_state->tokens_list, tokenInfo);
}
plugin_state->tokens_count++;

totp_config_file_save_new_token(tokenInfo);
totp_config_file_save_new_token(tokenInfo);

GenerateTokenSceneContext generate_scene_context = {
.current_token_index = plugin_state->tokens_count - 1};
totp_scene_director_activate_scene(
plugin_state, TotpSceneGenerateToken, &generate_scene_context);
GenerateTokenSceneContext generate_scene_context = {
.current_token_index = plugin_state->tokens_count - 1};
totp_scene_director_activate_scene(
plugin_state, TotpSceneGenerateToken, &generate_scene_context);
} else {
token_info_free(tokenInfo);
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, "Back", NULL, NULL);
dialog_message_set_text(
message,
"Token secret is invalid",
SCREEN_WIDTH_CENTER,
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
dialog_message_show(plugin_state->dialogs, message);
dialog_message_free(message);
scene_state->selected_control = TokenSecretTextBox;
update_screen_y_offset(scene_state);
}
break;
}
}
Expand Down
67 changes: 48 additions & 19 deletions scenes/generate_token/totp_scene_generate_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ void update_totp_params(PluginState* const plugin_state) {
SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;

if(scene_state->current_token_index < plugin_state->tokens_count) {
TokenInfo* tokenInfo = list_element_at(plugin_state->tokens_list, scene_state->current_token_index)->data;
TokenInfo* tokenInfo =
list_element_at(plugin_state->tokens_list, scene_state->current_token_index)->data;

scene_state->need_token_update = true;
scene_state->last_code_name = tokenInfo->name;
Expand All @@ -102,7 +103,31 @@ void totp_scene_generate_token_activate(
PluginState* plugin_state,
const GenerateTokenSceneContext* context) {
if(!plugin_state->token_list_loaded) {
totp_config_file_load_tokens(plugin_state);
TokenLoadingResult token_load_result = totp_config_file_load_tokens(plugin_state);
if(token_load_result != TokenLoadingResultSuccess) {
DialogMessage* message = dialog_message_alloc();
dialog_message_set_buttons(message, NULL, "Okay", NULL);
if(token_load_result == TokenLoadingResultWarning) {
dialog_message_set_text(
message,
"Unable to load some tokens\nPlease review conf file",
SCREEN_WIDTH_CENTER,
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
} else if(token_load_result == TokenLoadingResultError) {
dialog_message_set_text(
message,
"Unable to load tokens\nPlease review conf file",
SCREEN_WIDTH_CENTER,
SCREEN_HEIGHT_CENTER,
AlignCenter,
AlignCenter);
}

dialog_message_show(plugin_state->dialogs, message);
dialog_message_free(message);
}
}
SceneState* scene_state = malloc(sizeof(SceneState));
if(context == NULL) {
Expand Down Expand Up @@ -154,23 +179,27 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
plugin_state->tokens_list, scene_state->current_token_index)
->data);

uint8_t key_length;
uint8_t* key = totp_crypto_decrypt(
tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);

i_token_to_str(
totp_at(
get_totp_algo_impl(tokenInfo->algo),
token_info_get_digits_count(tokenInfo),
key,
key_length,
curr_ts,
plugin_state->timezone_offset,
TOKEN_LIFETIME),
scene_state->last_code,
tokenInfo->digits);
memset(key, 0, key_length);
free(key);
if(tokenInfo->token != NULL && tokenInfo->token_length > 0) {
uint8_t key_length;
uint8_t* key = totp_crypto_decrypt(
tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);

i_token_to_str(
totp_at(
get_totp_algo_impl(tokenInfo->algo),
token_info_get_digits_count(tokenInfo),
key,
key_length,
curr_ts,
plugin_state->timezone_offset,
TOKEN_LIFETIME),
scene_state->last_code,
tokenInfo->digits);
memset(key, 0, key_length);
free(key);
} else {
i_token_to_str(0, scene_state->last_code, tokenInfo->digits);
}

if(is_new_token_time) {
notification_message(plugin_state->notification, &sequence_short_vibro_and_sound);
Expand Down
5 changes: 1 addition & 4 deletions services/base32/base32.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
// limitations under the License.

#include <string.h>
#include <stdbool.h>

#include "base32.h"

Expand All @@ -26,11 +25,9 @@ int base32_decode(const uint8_t* encoded, uint8_t* result, int bufSize) {
int count = 0;
for(const uint8_t* ptr = encoded; count < bufSize && *ptr; ++ptr) {
uint8_t ch = *ptr;
bool chIsValid = (ch >= '0' && ch <= '8') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
if(!chIsValid) {
if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-') {
continue;
}

buffer <<= 5;

// Deal with commonly mistyped characters
Expand Down
79 changes: 51 additions & 28 deletions services/config/config.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,15 @@ FlipperFormat* totp_open_config_file(Storage* storage) {
void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_info) {
flipper_format_seek_to_end(file);
flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name);
bool token_is_valid = token_info->token != NULL && token_info->token_length > 0;
if(!token_is_valid) {
flipper_format_write_comment_cstr(file, "!!! WARNING BEGIN: INVALID TOKEN !!!");
}
flipper_format_write_hex(
file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length);
if(!token_is_valid) {
flipper_format_write_comment_cstr(file, "!!! WARNING END !!!");
}
flipper_format_write_string_cstr(
file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info));
uint32_t digits_count_as_uint32 = token_info_get_digits_as_int(token_info);
Expand Down Expand Up @@ -312,7 +319,7 @@ void totp_config_file_load_base(PluginState* const plugin_state) {
totp_close_storage();
}

void totp_config_file_load_tokens(PluginState* const plugin_state) {
TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) {
Storage* storage = totp_open_storage();
FlipperFormat* fff_data_file = totp_open_config_file(storage);

Expand All @@ -322,9 +329,10 @@ void totp_config_file_load_tokens(PluginState* const plugin_state) {
if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
furi_string_free(temp_str);
return;
return TokenLoadingResultError;
}

TokenLoadingResult result = TokenLoadingResultSuccess;
uint8_t index = 0;
bool has_any_plain_secret = false;

Expand All @@ -342,48 +350,61 @@ void totp_config_file_load_tokens(PluginState* const plugin_state) {
uint32_t secret_bytes_count;
if(!flipper_format_get_value_count(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, &secret_bytes_count)) {
token_info_free(tokenInfo);
continue;
secret_bytes_count = 0;
}

if(secret_bytes_count == 1) { // Plain secret key
if(!flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str)) {
token_info_free(tokenInfo);
continue;
if(flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str)) {
temp_cstr = furi_string_get_cstr(temp_str);
if(token_info_set_secret(
tokenInfo, temp_cstr, strlen(temp_cstr), &plugin_state->iv[0])) {
FURI_LOG_W(LOGGING_TAG, "Token \"%s\" has plain secret", tokenInfo->name);
} else {
tokenInfo->token = NULL;
tokenInfo->token_length = 0;
FURI_LOG_W(LOGGING_TAG, "Token \"%s\" has invalid secret", tokenInfo->name);
result = TokenLoadingResultWarning;
}
} else {
tokenInfo->token = NULL;
tokenInfo->token_length = 0;
result = TokenLoadingResultWarning;
}

temp_cstr = furi_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)) {
token_info_free(tokenInfo);
continue;
if(secret_bytes_count > 0) {
tokenInfo->token = malloc(tokenInfo->token_length);
if(!flipper_format_read_hex(
fff_data_file,
TOTP_CONFIG_KEY_TOKEN_SECRET,
tokenInfo->token,
tokenInfo->token_length)) {
free(tokenInfo->token);
tokenInfo->token = NULL;
tokenInfo->token_length = 0;
result = TokenLoadingResultWarning;
}
} else {
tokenInfo->token = NULL;
result = TokenLoadingResultWarning;
}
}

if(!flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str)) {
token_info_free(tokenInfo);
continue;
if(flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str)) {
token_info_set_algo_from_str(tokenInfo, temp_str);
} else {
tokenInfo->algo = SHA1;
}

token_info_set_algo_from_str(tokenInfo, temp_str);

if(!flipper_format_read_uint32(
if(flipper_format_read_uint32(
fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1)) {
token_info_free(tokenInfo);
continue;
token_info_set_digits_from_int(tokenInfo, temp_data32);
} else {
tokenInfo->digits = TOTP_6_DIGITS;
}

token_info_set_digits_from_int(tokenInfo, temp_data32);

FURI_LOG_D(LOGGING_TAG, "Found token \"%s\"", tokenInfo->name);

if(plugin_state->tokens_list == NULL) {
Expand All @@ -407,6 +428,8 @@ void totp_config_file_load_tokens(PluginState* const plugin_state) {
if(has_any_plain_secret) {
totp_full_save_config_file(plugin_state);
}

return result;
}

void totp_close_config_file(FlipperFormat* file) {
Expand Down
8 changes: 7 additions & 1 deletion services/config/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,18 @@
#include "../../types/token_info.h"
#include "constants.h"

typedef enum {
TokenLoadingResultSuccess,
TokenLoadingResultWarning,
TokenLoadingResultError
} TokenLoadingResult;

Storage* totp_open_storage();
void totp_close_storage();
FlipperFormat* totp_open_config_file(Storage* storage);
void totp_close_config_file(FlipperFormat* file);
void totp_full_save_config_file(PluginState* const plugin_state);
void totp_config_file_load_base(PluginState* const plugin_state);
void totp_config_file_load_tokens(PluginState* const plugin_state);
TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state);
void totp_config_file_save_new_token(TokenInfo* token_info);
void totp_config_file_update_timezone_offset(float new_timezone_offset);
14 changes: 10 additions & 4 deletions types/token_info.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,26 @@ void token_info_free(TokenInfo* token_info) {
free(token_info);
}

void token_info_set_secret(
bool token_info_set_secret(
TokenInfo* token_info,
const char* base32_token_secret,
uint8_t token_secret_length,
uint8_t* iv) {
uint8_t* plain_secret = malloc(token_secret_length);
int plain_secret_length =
base32_decode((uint8_t*)base32_token_secret, plain_secret, token_secret_length);

token_info->token =
totp_crypto_encrypt(plain_secret, plain_secret_length, iv, &token_info->token_length);
bool result;
if(plain_secret_length >= 0) {
token_info->token =
totp_crypto_encrypt(plain_secret, plain_secret_length, iv, &token_info->token_length);
result = true;
} else {
result = false;
}

memset(plain_secret, 0, token_secret_length);
free(plain_secret);
return result;
}

uint8_t token_info_get_digits_count(TokenInfo* token_info) {
Expand Down
2 changes: 1 addition & 1 deletion types/token_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ typedef struct {

TokenInfo* token_info_alloc();
void token_info_free(TokenInfo* token_info);
void token_info_set_secret(
bool token_info_set_secret(
TokenInfo* token_info,
const char* base32_token_secret,
uint8_t token_secret_length,
Expand Down

0 comments on commit 75b3849

Please sign in to comment.