From 0a68d80028673555624507ead32b4f726604cb0b Mon Sep 17 00:00:00 2001 From: MX <10697207+xMasterX@users.noreply.github.com> Date: Fri, 28 Oct 2022 18:34:35 +0300 Subject: [PATCH] update totp https://github.com/akopachov/flipper-zero_authenticator --- .../scenes/add_new_token/totp_input_text.c | 18 +- .../scenes/add_new_token/totp_input_text.h | 2 +- .../add_new_token/totp_scene_add_new_token.c | 15 +- .../add_new_token/totp_scene_add_new_token.h | 4 +- .../scenes/app_settings/totp_app_settings.c | 8 +- .../scenes/app_settings/totp_app_settings.h | 6 +- .../authenticate/totp_scene_authenticate.c | 7 +- .../authenticate/totp_scene_authenticate.h | 4 +- .../totp_scene_generate_token.c | 16 +- .../totp_scene_generate_token.h | 8 +- .../plugins/totp/scenes/scene_director.c | 10 +- .../plugins/totp/scenes/scene_director.h | 2 +- .../scenes/token_menu/totp_scene_token_menu.c | 17 +- .../scenes/token_menu/totp_scene_token_menu.h | 6 +- .../plugins/totp/scenes/totp_scenes_enum.h | 1 + applications/plugins/totp/services/cli/cli.c | 65 +++++ applications/plugins/totp/services/cli/cli.h | 7 + .../plugins/totp/services/cli/cli_helpers.c | 21 ++ .../plugins/totp/services/cli/cli_helpers.h | 40 ++++ .../totp/services/cli/commands/add/add.c | 226 ++++++++++++++++++ .../totp/services/cli/commands/add/add.h | 14 ++ .../services/cli/commands/delete/delete.c | 107 +++++++++ .../services/cli/commands/delete/delete.h | 13 + .../totp/services/cli/commands/help/help.c | 42 ++++ .../totp/services/cli/commands/help/help.h | 11 + .../totp/services/cli/commands/list/list.c | 71 ++++++ .../totp/services/cli/commands/list/list.h | 11 + .../services/cli/commands/timezone/timezone.c | 54 +++++ .../services/cli/commands/timezone/timezone.h | 12 + .../plugins/totp/services/config/config.c | 32 +-- .../plugins/totp/services/config/config.h | 4 +- .../plugins/totp/services/crypto/crypto.c | 19 +- .../plugins/totp/services/crypto/crypto.h | 10 +- .../plugins/totp/services/crypto/memset_s.c | 22 ++ .../plugins/totp/services/crypto/memset_s.h | 16 ++ .../plugins/totp/services/list/list.c | 4 + .../plugins/totp/services/totp/totp.c | 18 +- .../plugins/totp/services/totp/totp.h | 6 +- .../plugins/totp/services/ui/ui_controls.c | 6 +- .../plugins/totp/services/ui/ui_controls.h | 6 +- applications/plugins/totp/totp_app.c | 28 ++- .../plugins/totp/types/plugin_state.h | 2 +- applications/plugins/totp/types/token_info.c | 5 +- applications/plugins/totp/types/token_info.h | 4 +- 44 files changed, 886 insertions(+), 114 deletions(-) create mode 100644 applications/plugins/totp/services/cli/cli.c create mode 100644 applications/plugins/totp/services/cli/cli.h create mode 100644 applications/plugins/totp/services/cli/cli_helpers.c create mode 100644 applications/plugins/totp/services/cli/cli_helpers.h create mode 100644 applications/plugins/totp/services/cli/commands/add/add.c create mode 100644 applications/plugins/totp/services/cli/commands/add/add.h create mode 100644 applications/plugins/totp/services/cli/commands/delete/delete.c create mode 100644 applications/plugins/totp/services/cli/commands/delete/delete.h create mode 100644 applications/plugins/totp/services/cli/commands/help/help.c create mode 100644 applications/plugins/totp/services/cli/commands/help/help.h create mode 100644 applications/plugins/totp/services/cli/commands/list/list.c create mode 100644 applications/plugins/totp/services/cli/commands/list/list.h create mode 100644 applications/plugins/totp/services/cli/commands/timezone/timezone.c create mode 100644 applications/plugins/totp/services/cli/commands/timezone/timezone.h create mode 100644 applications/plugins/totp/services/crypto/memset_s.c create mode 100644 applications/plugins/totp/services/crypto/memset_s.h diff --git a/applications/plugins/totp/scenes/add_new_token/totp_input_text.c b/applications/plugins/totp/scenes/add_new_token/totp_input_text.c index e3a7f68a6..811cd2976 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_input_text.c +++ b/applications/plugins/totp/scenes/add_new_token/totp_input_text.c @@ -2,6 +2,16 @@ #include #include "../../types/common.h" +size_t strnlen(const char* s, size_t maxlen) { + size_t len; + + for(len = 0; len < maxlen; len++, s++) { + if(!*s) break; + } + + return len; +} + void view_draw(View* view, Canvas* canvas) { furi_assert(view); if(view->draw_callback) { @@ -32,10 +42,14 @@ static void commit_text_input_callback(void* context) { InputTextSceneState* text_input_state = (InputTextSceneState*)context; if(text_input_state->callback != 0) { InputTextSceneCallbackResult* result = malloc(sizeof(InputTextSceneCallbackResult)); - result->user_input_length = strlen(text_input_state->text_input_buffer); + result->user_input_length = + strnlen(text_input_state->text_input_buffer, INPUT_BUFFER_SIZE); result->user_input = malloc(result->user_input_length + 1); result->callback_data = text_input_state->callback_data; - strcpy(result->user_input, text_input_state->text_input_buffer); + strlcpy( + result->user_input, + text_input_state->text_input_buffer, + result->user_input_length + 1); text_input_state->callback(result); } } diff --git a/applications/plugins/totp/scenes/add_new_token/totp_input_text.h b/applications/plugins/totp/scenes/add_new_token/totp_input_text.h index a73a227b5..dda0dc301 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_input_text.h +++ b/applications/plugins/totp/scenes/add_new_token/totp_input_text.h @@ -10,7 +10,7 @@ typedef struct { char* user_input; - uint8_t user_input_length; + size_t user_input_length; void* callback_data; } InputTextSceneCallbackResult; diff --git a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c index fc39b66cd..cc4e6a69d 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c +++ b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.c @@ -25,9 +25,9 @@ typedef enum { typedef struct { char* token_name; - uint8_t token_name_length; + size_t token_name_length; char* token_secret; - uint8_t token_secret_length; + size_t token_secret_length; bool saved; Control selected_control; InputTextSceneContext* token_name_input_context; @@ -35,12 +35,12 @@ typedef struct { InputTextSceneState* input_state; uint32_t input_started_at; int16_t current_token_index; - int32_t screen_y_offset; + int16_t screen_y_offset; TokenHashAlgo algo; TokenDigitsCount digits_count; } SceneState; -void totp_scene_add_new_token_init(PluginState* plugin_state) { +void totp_scene_add_new_token_init(const PluginState* plugin_state) { UNUSED(plugin_state); } @@ -235,7 +235,10 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState if(token_secret_set) { tokenInfo->name = malloc(scene_state->token_name_length + 1); - strcpy(tokenInfo->name, scene_state->token_name); + strlcpy( + tokenInfo->name, + scene_state->token_name, + scene_state->token_name_length + 1); tokenInfo->algo = scene_state->algo; tokenInfo->digits = scene_state->digits_count; @@ -308,6 +311,6 @@ void totp_scene_add_new_token_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_add_new_token_free(PluginState* plugin_state) { +void totp_scene_add_new_token_free(const PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h index b65c567a2..7a0b0e68a 100644 --- a/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h +++ b/applications/plugins/totp/scenes/add_new_token/totp_scene_add_new_token.h @@ -10,11 +10,11 @@ typedef struct { uint8_t current_token_index; } TokenAddEditSceneContext; -void totp_scene_add_new_token_init(PluginState* plugin_state); +void totp_scene_add_new_token_init(const PluginState* plugin_state); void totp_scene_add_new_token_activate( PluginState* plugin_state, const TokenAddEditSceneContext* context); void totp_scene_add_new_token_render(Canvas* const canvas, PluginState* plugin_state); bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState* plugin_state); void totp_scene_add_new_token_deactivate(PluginState* plugin_state); -void totp_scene_add_new_token_free(PluginState* plugin_state); +void totp_scene_add_new_token_free(const PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/app_settings/totp_app_settings.c b/applications/plugins/totp/scenes/app_settings/totp_app_settings.c index cdb775a8d..4e03de433 100644 --- a/applications/plugins/totp/scenes/app_settings/totp_app_settings.c +++ b/applications/plugins/totp/scenes/app_settings/totp_app_settings.c @@ -16,7 +16,7 @@ typedef struct { Control selected_control; } SceneState; -void totp_scene_app_settings_init(PluginState* plugin_state) { +void totp_scene_app_settings_init(const PluginState* plugin_state) { UNUSED(plugin_state); } @@ -53,7 +53,7 @@ static void two_digit_to_str(int8_t num, char* str) { } void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; canvas_set_font(canvas, FontPrimary); canvas_draw_str_aligned(canvas, 0, 0, AlignLeft, AlignTop, "Timezone offset"); @@ -90,7 +90,7 @@ void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_st scene_state->selected_control == ConfirmButton); } -bool totp_scene_app_settings_handle_event(PluginEvent* const event, PluginState* plugin_state) { +bool totp_scene_app_settings_handle_event(const PluginEvent* const event, PluginState* plugin_state) { if(event->type == EventTypeKey) { SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; if(event->input.type == InputTypePress) { @@ -171,6 +171,6 @@ void totp_scene_app_settings_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_app_settings_free(PluginState* plugin_state) { +void totp_scene_app_settings_free(const PluginState* plugin_state) { UNUSED(plugin_state); } \ No newline at end of file diff --git a/applications/plugins/totp/scenes/app_settings/totp_app_settings.h b/applications/plugins/totp/scenes/app_settings/totp_app_settings.h index b97de3390..be51e9dc9 100644 --- a/applications/plugins/totp/scenes/app_settings/totp_app_settings.h +++ b/applications/plugins/totp/scenes/app_settings/totp_app_settings.h @@ -10,11 +10,11 @@ typedef struct { uint8_t current_token_index; } AppSettingsSceneContext; -void totp_scene_app_settings_init(PluginState* plugin_state); +void totp_scene_app_settings_init(const PluginState* plugin_state); void totp_scene_app_settings_activate( PluginState* plugin_state, const AppSettingsSceneContext* context); void totp_scene_app_settings_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_app_settings_handle_event(PluginEvent* const event, PluginState* plugin_state); +bool totp_scene_app_settings_handle_event(const PluginEvent* const event, PluginState* plugin_state); void totp_scene_app_settings_deactivate(PluginState* plugin_state); -void totp_scene_app_settings_free(PluginState* plugin_state); \ No newline at end of file +void totp_scene_app_settings_free(const PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c index 73cbb4aaa..c03f87542 100644 --- a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c +++ b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.c @@ -24,10 +24,11 @@ void totp_scene_authenticate_activate(PluginState* plugin_state) { scene_state->code_length = 0; memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH); plugin_state->current_scene_state = scene_state; + memset(&plugin_state->iv[0], 0, TOTP_IV_SIZE); } void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; int v_shift = 0; if(scene_state->code_length > 0) { @@ -72,7 +73,7 @@ void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_st } } -bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState* plugin_state) { +bool totp_scene_authenticate_handle_event(const PluginEvent* const event, PluginState* plugin_state) { if(event->type == EventTypeKey) { if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { return false; @@ -155,6 +156,6 @@ void totp_scene_authenticate_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_authenticate_free(PluginState* plugin_state) { +void totp_scene_authenticate_free(const PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h index f1199a425..aa308d983 100644 --- a/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h +++ b/applications/plugins/totp/scenes/authenticate/totp_scene_authenticate.h @@ -9,6 +9,6 @@ void totp_scene_authenticate_init(PluginState* plugin_state); void totp_scene_authenticate_activate(PluginState* plugin_state); void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState* plugin_state); +bool totp_scene_authenticate_handle_event(const PluginEvent* const event, PluginState* plugin_state); void totp_scene_authenticate_deactivate(PluginState* plugin_state); -void totp_scene_authenticate_free(PluginState* plugin_state); +void totp_scene_authenticate_free(const PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c index df5a3e746..7b5f7391b 100644 --- a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c +++ b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.c @@ -9,6 +9,7 @@ #include "../../services/totp/totp.h" #include "../../services/config/config.h" #include "../../services/crypto/crypto.h" +#include "../../services/crypto/memset_s.h" #include "../scene_director.h" #include "../token_menu/totp_scene_token_menu.h" @@ -95,7 +96,7 @@ void update_totp_params(PluginState* const plugin_state) { } } -void totp_scene_generate_token_init(PluginState* plugin_state) { +void totp_scene_generate_token_init(const PluginState* plugin_state) { UNUSED(plugin_state); } @@ -130,7 +131,7 @@ void totp_scene_generate_token_activate( } } SceneState* scene_state = malloc(sizeof(SceneState)); - if(context == NULL) { + if(context == NULL || context->current_token_index > plugin_state->tokens_count) { scene_state->current_token_index = 0; } else { scene_state->current_token_index = context->current_token_index; @@ -180,7 +181,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ ->data); if(tokenInfo->token != NULL && tokenInfo->token_length > 0) { - uint8_t key_length; + size_t key_length; uint8_t* key = totp_crypto_decrypt( tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length); @@ -195,7 +196,7 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ TOKEN_LIFETIME), scene_state->last_code, tokenInfo->digits); - memset(key, 0, key_length); + memset_s(key, sizeof(key), 0, key_length); free(key); } else { i_token_to_str(0, scene_state->last_code, tokenInfo->digits); @@ -265,7 +266,9 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_ } } -bool totp_scene_generate_token_handle_event(PluginEvent* const event, PluginState* plugin_state) { +bool totp_scene_generate_token_handle_event( + const PluginEvent* const event, + PluginState* plugin_state) { if(event->type == EventTypeKey) { if(event->input.type == InputTypeLong && event->input.key == InputKeyBack) { return false; @@ -314,11 +317,10 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) { if(plugin_state->current_scene_state == NULL) return; SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; - free(scene_state->last_code); free(scene_state); plugin_state->current_scene_state = NULL; } -void totp_scene_generate_token_free(PluginState* plugin_state) { +void totp_scene_generate_token_free(const PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h index 1284c7b41..e4ca818b6 100644 --- a/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h +++ b/applications/plugins/totp/scenes/generate_token/totp_scene_generate_token.h @@ -10,11 +10,13 @@ typedef struct { uint8_t current_token_index; } GenerateTokenSceneContext; -void totp_scene_generate_token_init(PluginState* plugin_state); +void totp_scene_generate_token_init(const PluginState* plugin_state); void totp_scene_generate_token_activate( PluginState* plugin_state, const GenerateTokenSceneContext* context); void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_generate_token_handle_event(PluginEvent* const event, PluginState* plugin_state); +bool totp_scene_generate_token_handle_event( + const PluginEvent* const event, + PluginState* plugin_state); void totp_scene_generate_token_deactivate(PluginState* plugin_state); -void totp_scene_generate_token_free(PluginState* plugin_state); +void totp_scene_generate_token_free(const PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/scene_director.c b/applications/plugins/totp/scenes/scene_director.c index 9a07b49fb..5265123f5 100644 --- a/applications/plugins/totp/scenes/scene_director.c +++ b/applications/plugins/totp/scenes/scene_director.c @@ -28,6 +28,8 @@ void totp_scene_director_activate_scene( case TotpSceneAppSettings: totp_scene_app_settings_activate(plugin_state, context); break; + case TotpSceneNone: + break; } plugin_state->current_scene = scene; @@ -51,6 +53,8 @@ void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state case TotpSceneAppSettings: totp_scene_app_settings_deactivate(plugin_state); break; + case TotpSceneNone: + break; } } @@ -79,10 +83,12 @@ void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_ case TotpSceneAppSettings: totp_scene_app_settings_render(canvas, plugin_state); break; + case TotpSceneNone: + break; } } -void totp_scene_director_dispose(PluginState* const plugin_state) { +void totp_scene_director_dispose(const PluginState* const plugin_state) { totp_scene_generate_token_free(plugin_state); totp_scene_authenticate_free(plugin_state); totp_scene_add_new_token_free(plugin_state); @@ -108,6 +114,8 @@ bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* con case TotpSceneAppSettings: processing = totp_scene_app_settings_handle_event(event, plugin_state); break; + case TotpSceneNone: + break; } return processing; diff --git a/applications/plugins/totp/scenes/scene_director.h b/applications/plugins/totp/scenes/scene_director.h index 3c25afff6..cc06029d3 100644 --- a/applications/plugins/totp/scenes/scene_director.h +++ b/applications/plugins/totp/scenes/scene_director.h @@ -12,5 +12,5 @@ void totp_scene_director_activate_scene( void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state); void totp_scene_director_init_scenes(PluginState* const plugin_state); void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state); -void totp_scene_director_dispose(PluginState* const plugin_state); +void totp_scene_director_dispose(const PluginState* const plugin_state); bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state); diff --git a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c index 8e2356f86..c4286ded9 100644 --- a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c +++ b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.c @@ -21,7 +21,7 @@ typedef struct { int16_t current_token_index; } SceneState; -void totp_scene_token_menu_init(PluginState* plugin_state) { +void totp_scene_token_menu_init(const PluginState* plugin_state) { UNUSED(plugin_state); } @@ -38,7 +38,7 @@ void totp_scene_token_menu_activate( } void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state) { - SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; + const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; if(scene_state->current_token_index < 0) { ui_control_button_render( canvas, @@ -84,7 +84,7 @@ void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_stat } } -bool totp_scene_token_menu_handle_event(PluginEvent* const event, PluginState* plugin_state) { +bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state) { if(event->type == EventTypeKey) { SceneState* scene_state = (SceneState*)plugin_state->current_scene_state; if(event->input.type == InputTypePress) { @@ -139,13 +139,8 @@ bool totp_scene_token_menu_handle_event(PluginEvent* const event, PluginState* p dialog_message_show(plugin_state->dialogs, message); dialog_message_free(message); if(dialog_result == DialogMessageButtonRight) { - uint8_t i = 0; - - ListNode* list_node = plugin_state->tokens_list; - while(i < scene_state->current_token_index && list_node->next != NULL) { - list_node = list_node->next; - i++; - } + ListNode* list_node = list_element_at( + plugin_state->tokens_list, scene_state->current_token_index); TokenInfo* tokenInfo = list_node->data; token_info_free(tokenInfo); @@ -197,6 +192,6 @@ void totp_scene_token_menu_deactivate(PluginState* plugin_state) { plugin_state->current_scene_state = NULL; } -void totp_scene_token_menu_free(PluginState* plugin_state) { +void totp_scene_token_menu_free(const PluginState* plugin_state) { UNUSED(plugin_state); } diff --git a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h index 0b117cb25..52e33e728 100644 --- a/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h +++ b/applications/plugins/totp/scenes/token_menu/totp_scene_token_menu.h @@ -10,11 +10,11 @@ typedef struct { uint8_t current_token_index; } TokenMenuSceneContext; -void totp_scene_token_menu_init(PluginState* plugin_state); +void totp_scene_token_menu_init(const PluginState* plugin_state); void totp_scene_token_menu_activate( PluginState* plugin_state, const TokenMenuSceneContext* context); void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state); -bool totp_scene_token_menu_handle_event(PluginEvent* const event, PluginState* plugin_state); +bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginState* plugin_state); void totp_scene_token_menu_deactivate(PluginState* plugin_state); -void totp_scene_token_menu_free(PluginState* plugin_state); +void totp_scene_token_menu_free(const PluginState* plugin_state); diff --git a/applications/plugins/totp/scenes/totp_scenes_enum.h b/applications/plugins/totp/scenes/totp_scenes_enum.h index 72bf4d76e..c2b153a02 100644 --- a/applications/plugins/totp/scenes/totp_scenes_enum.h +++ b/applications/plugins/totp/scenes/totp_scenes_enum.h @@ -1,6 +1,7 @@ #pragma once typedef enum { + TotpSceneNone, TotpSceneAuthentication, TotpSceneGenerateToken, TotpSceneAddNewToken, diff --git a/applications/plugins/totp/services/cli/cli.c b/applications/plugins/totp/services/cli/cli.c new file mode 100644 index 000000000..76e58a02d --- /dev/null +++ b/applications/plugins/totp/services/cli/cli.c @@ -0,0 +1,65 @@ +// Original idea: https://github.com/br0ziliy + +#include "cli.h" +#include +#include "cli_helpers.h" +#include "commands/list/list.h" +#include "commands/add/add.h" +#include "commands/delete/delete.h" +#include "commands/timezone/timezone.h" +#include "commands/help/help.h" + +static void totp_cli_print_unknown_command(const FuriString* unknown_command) { + TOTP_CLI_PRINTF( + "Command \"%s\" is unknown. Use \"" TOTP_CLI_COMMAND_HELP + "\" command to get list of available commands.", + furi_string_get_cstr(unknown_command)); +} + +static void totp_cli_handler(Cli* cli, FuriString* args, void* context) { + PluginState* plugin_state = (PluginState*)context; + + FuriString* cmd = furi_string_alloc(); + + args_read_string_and_trim(args, cmd); + + if(furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_HELP) == 0 || + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_HELP_ALT) == 0 || + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_HELP_ALT2) == 0 || furi_string_empty(cmd)) { + totp_cli_command_help_handle(); + } else if( + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_ADD) == 0 || + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_ADD_ALT) == 0 || + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_ADD_ALT2) == 0) { + totp_cli_command_add_handle(plugin_state, args, cli); + } else if( + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_LIST) == 0 || + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_LIST_ALT) == 0) { + totp_cli_command_list_handle(plugin_state, cli); + } else if( + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DELETE) == 0 || + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_DELETE_ALT) == 0) { + totp_cli_command_delete_handle(plugin_state, args, cli); + } else if( + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE) == 0 || + furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE_ALT) == 0) { + totp_cli_command_timezone_handle(plugin_state, args, cli); + } else { + totp_cli_print_unknown_command(cmd); + } + + furi_string_free(cmd); +} + +void totp_cli_register_command_handler(PluginState* plugin_state) { + Cli* cli = furi_record_open(RECORD_CLI); + cli_add_command( + cli, TOTP_CLI_COMMAND_NAME, CliCommandFlagParallelSafe, totp_cli_handler, plugin_state); + furi_record_close(RECORD_CLI); +} + +void totp_cli_unregister_command_handler() { + Cli* cli = furi_record_open(RECORD_CLI); + cli_delete_command(cli, TOTP_CLI_COMMAND_NAME); + furi_record_close(RECORD_CLI); +} \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/cli.h b/applications/plugins/totp/services/cli/cli.h new file mode 100644 index 000000000..5297dd61b --- /dev/null +++ b/applications/plugins/totp/services/cli/cli.h @@ -0,0 +1,7 @@ +#pragma once + +#include +#include "../../types/plugin_state.h" + +void totp_cli_register_command_handler(PluginState* plugin_state); +void totp_cli_unregister_command_handler(); \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/cli_helpers.c b/applications/plugins/totp/services/cli/cli_helpers.c new file mode 100644 index 000000000..4a0b8b352 --- /dev/null +++ b/applications/plugins/totp/services/cli/cli_helpers.c @@ -0,0 +1,21 @@ +#include "cli_helpers.h" +#include + +bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli) { + if(plugin_state->current_scene == TotpSceneAuthentication) { + TOTP_CLI_PRINTF("Pleases enter PIN on your flipper device\r\n"); + + while(plugin_state->current_scene == TotpSceneAuthentication && + !cli_cmd_interrupt_received(cli)) { + furi_delay_ms(100); + } + + TOTP_CLI_DELETE_LAST_LINE(); + + if(plugin_state->current_scene == TotpSceneAuthentication) { + return false; + } + } + + return true; +} \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/cli_helpers.h b/applications/plugins/totp/services/cli/cli_helpers.h new file mode 100644 index 000000000..9b19f926b --- /dev/null +++ b/applications/plugins/totp/services/cli/cli_helpers.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include "../../types/plugin_state.h" + +#define TOTP_CLI_COMMAND_NAME "totp" + +#define DOCOPT_ARGUMENT(arg) "<" arg ">" +#define DOCOPT_OPTIONAL(param) "[" param "]" +#define DOCOPT_REQUIRED(param) "(" param ")" +#define DOCOPT_OPTION(option, value) option " " value +#define DOCOPT_SWITCH(option) option +#define DOCOPT_OPTIONS "[options]" +#define DOCOPT_DEFAULT(val) "[default: " val "]" + +#define TOTP_CLI_PRINTF(format, ...) \ + do { \ + _Pragma(STRINGIFY(GCC diagnostic push)) \ + _Pragma(STRINGIFY(GCC diagnostic ignored "-Wdouble-promotion")) \ + printf(format, ##__VA_ARGS__); \ + _Pragma(STRINGIFY(GCC diagnostic pop)) \ + } while(false) + +#define TOTP_CLI_DELETE_LAST_LINE() \ + TOTP_CLI_PRINTF("\033[A\33[2K\r"); \ + fflush(stdout) + +#define TOTP_CLI_DELETE_CURRENT_LINE() \ + TOTP_CLI_PRINTF("\33[2K\r"); \ + fflush(stdout) + +#define TOTP_CLI_DELETE_LAST_CHAR() \ + TOTP_CLI_PRINTF("\b \b"); \ + fflush(stdout) + +#define TOTP_CLI_PRINT_INVALID_ARGUMENTS() \ + TOTP_CLI_PRINTF( \ + "Invalid command arguments. use \"help\" command to get list of available commands") + +bool totp_cli_ensure_authenticated(const PluginState* plugin_state, Cli* cli); diff --git a/applications/plugins/totp/services/cli/commands/add/add.c b/applications/plugins/totp/services/cli/commands/add/add.c new file mode 100644 index 000000000..c1ce42617 --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/add/add.c @@ -0,0 +1,226 @@ +#include "add.h" +#include +#include +#include "../../../list/list.h" +#include "../../../../types/token_info.h" +#include "../../../config/config.h" +#include "../../cli_helpers.h" +#include "../../../../scenes/scene_director.h" + +#define TOTP_CLI_COMMAND_ADD_ARG_NAME "name" +#define TOTP_CLI_COMMAND_ADD_ARG_ALGO "algo" +#define TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX "-a" +#define TOTP_CLI_COMMAND_ADD_ARG_DIGITS "digits" +#define TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX "-d" +#define TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX "-u" + +static bool token_info_set_digits_from_str(TokenInfo* token_info, const FuriString* str) { + switch(furi_string_get_char(str, 0)) { + case '6': + token_info->digits = TOTP_6_DIGITS; + return true; + case '8': + token_info->digits = TOTP_8_DIGITS; + return true; + } + + return false; +} + +static bool token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) { + if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) { + token_info->algo = SHA1; + return true; + } + + if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME) == 0) { + token_info->algo = SHA256; + return true; + } + + if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA512_NAME) == 0) { + token_info->algo = SHA512; + return true; + } + + return false; +} + +void totp_cli_command_add_docopt_commands() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ADD ", " TOTP_CLI_COMMAND_ADD_ALT + ", " TOTP_CLI_COMMAND_ADD_ALT2 " Add new token\r\n"); +} + +void totp_cli_command_add_docopt_usage() { + TOTP_CLI_PRINTF( + " " TOTP_CLI_COMMAND_NAME + " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_ADD " | " TOTP_CLI_COMMAND_ADD_ALT " | " TOTP_CLI_COMMAND_ADD_ALT2) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_NAME) " " DOCOPT_OPTIONAL( + DOCOPT_OPTION( + TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX, + DOCOPT_ARGUMENT( + TOTP_CLI_COMMAND_ADD_ARG_ALGO))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_DIGITS))) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX)) "\r\n"); +} + +void totp_cli_command_add_docopt_arguments() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_ADD_ARG_NAME " Token name\r\n"); +} + +void totp_cli_command_add_docopt_options() { + TOTP_CLI_PRINTF(" " DOCOPT_OPTION( + TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX, + DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_ADD_ARG_ALGO)) " Token hashing algorithm.\r\n"); + TOTP_CLI_PRINTF( + " Could be one of: sha1, sha256, sha512 " DOCOPT_DEFAULT("sha1") "\r\n"); + TOTP_CLI_PRINTF(" " DOCOPT_OPTION( + TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX, + DOCOPT_ARGUMENT( + TOTP_CLI_COMMAND_ADD_ARG_DIGITS)) " Number of digits to generate, one of: 6, 8 " DOCOPT_DEFAULT("6") "\r\n"); + TOTP_CLI_PRINTF(" " DOCOPT_SWITCH( + TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) " Show console user input as-is without masking\r\n"); +} + +static void furi_string_secure_free(FuriString* str) { + for(long i = furi_string_size(str) - 1; i >= 0; i--) { + furi_string_set_char(str, i, '\0'); + } + + furi_string_free(str); +} + +void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { + FuriString* temp_str = furi_string_alloc(); + TokenInfo* token_info = token_info_alloc(); + + // Reading token name + if(!args_read_probably_quoted_string_and_trim(args, temp_str)) { + TOTP_CLI_PRINT_INVALID_ARGUMENTS(); + furi_string_free(temp_str); + token_info_free(token_info); + return; + } + + size_t temp_cstr_len = furi_string_size(temp_str); + token_info->name = malloc(temp_cstr_len + 1); + strlcpy(token_info->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1); + + // Read optional arguments + bool mask_user_input = true; + while(args_read_string_and_trim(args, temp_str)) { + bool parsed = false; + if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX) == 0) { + if(!args_read_string_and_trim(args, temp_str)) { + TOTP_CLI_PRINTF("Missed value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX + "\"\r\n"); + } else if(!token_info_set_algo_from_str(token_info, temp_str)) { + TOTP_CLI_PRINTF( + "\"%s\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_ALGO_PREFIX + "\"\r\n", + furi_string_get_cstr(temp_str)); + } else { + parsed = true; + } + } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX) == 0) { + if(!args_read_string_and_trim(args, temp_str)) { + TOTP_CLI_PRINTF( + "Missed value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX + "\"\r\n"); + } else if(!token_info_set_digits_from_str(token_info, temp_str)) { + TOTP_CLI_PRINTF( + "\"%s\" is incorrect value for argument \"" TOTP_CLI_COMMAND_ADD_ARG_DIGITS_PREFIX + "\"\r\n", + furi_string_get_cstr(temp_str)); + } else { + parsed = true; + } + } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) == 0) { + mask_user_input = false; + parsed = true; + } + + if(!parsed) { + TOTP_CLI_PRINT_INVALID_ARGUMENTS(); + furi_string_free(temp_str); + token_info_free(token_info); + return; + } + } + + // Reading token secret + furi_string_reset(temp_str); + TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]\r\n"); + + uint8_t c; + while(cli_read(cli, &c, 1) == 1) { + if(c == CliSymbolAsciiEsc) { + // Some keys generating escape-sequences + // We need to ignore them as we case about alpha-numerics only + uint8_t c2; + cli_read_timeout(cli, &c2, 1, 0); + cli_read_timeout(cli, &c2, 1, 0); + } else if(c == CliSymbolAsciiETX) { + TOTP_CLI_DELETE_CURRENT_LINE(); + TOTP_CLI_PRINTF("Cancelled by user\r\n"); + furi_string_secure_free(temp_str); + token_info_free(token_info); + return; + } else if((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) { + if(mask_user_input) { + putc('*', stdout); + } else { + putc(c, stdout); + } + fflush(stdout); + furi_string_push_back(temp_str, c); + } else if(c == CliSymbolAsciiBackspace || c == CliSymbolAsciiDel) { + size_t temp_str_size = furi_string_size(temp_str); + if(temp_str_size > 0) { + TOTP_CLI_DELETE_LAST_CHAR(); + furi_string_left(temp_str, temp_str_size - 1); + } + } else if(c == CliSymbolAsciiCR) { + cli_nl(); + break; + } + } + + TOTP_CLI_DELETE_LAST_LINE(); + + if(!totp_cli_ensure_authenticated(plugin_state, cli)) { + furi_string_secure_free(temp_str); + token_info_free(token_info); + return; + } + + if(!token_info_set_secret( + token_info, + furi_string_get_cstr(temp_str), + furi_string_size(temp_str), + plugin_state->iv)) { + TOTP_CLI_PRINTF("Token secret seems to be invalid and can not be parsed\r\n"); + furi_string_secure_free(temp_str); + token_info_free(token_info); + return; + } + + furi_string_secure_free(temp_str); + + bool load_generate_token_scene = false; + if(plugin_state->current_scene == TotpSceneGenerateToken) { + totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL); + load_generate_token_scene = true; + } + + if(plugin_state->tokens_list == NULL) { + plugin_state->tokens_list = list_init_head(token_info); + } else { + list_add(plugin_state->tokens_list, token_info); + } + plugin_state->tokens_count++; + totp_config_file_save_new_token(token_info); + + if(load_generate_token_scene) { + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + } + + TOTP_CLI_PRINTF("Token \"%s\" has been successfully added\r\n", token_info->name); +} \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/commands/add/add.h b/applications/plugins/totp/services/cli/commands/add/add.h new file mode 100644 index 000000000..7b1138e5b --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/add/add.h @@ -0,0 +1,14 @@ +#pragma once + +#include +#include "../../../../types/plugin_state.h" + +#define TOTP_CLI_COMMAND_ADD "add" +#define TOTP_CLI_COMMAND_ADD_ALT "mk" +#define TOTP_CLI_COMMAND_ADD_ALT2 "new" + +void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cli* cli); +void totp_cli_command_add_docopt_commands(); +void totp_cli_command_add_docopt_usage(); +void totp_cli_command_add_docopt_arguments(); +void totp_cli_command_add_docopt_options(); \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/commands/delete/delete.c b/applications/plugins/totp/services/cli/commands/delete/delete.c new file mode 100644 index 000000000..bbeb6ec4d --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/delete/delete.c @@ -0,0 +1,107 @@ +#include "delete.h" + +#include +#include +#include +#include "../../../list/list.h" +#include "../../../config/config.h" +#include "../../cli_helpers.h" +#include "../../../../scenes/scene_director.h" + +#define TOTP_CLI_COMMAND_DELETE_ARG_INDEX "index" +#define TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX "-f" + +void totp_cli_command_delete_docopt_commands() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_DELETE ", " TOTP_CLI_COMMAND_DELETE_ALT + " Delete existing token\r\n"); +} + +void totp_cli_command_delete_docopt_usage() { + TOTP_CLI_PRINTF( + " " TOTP_CLI_COMMAND_NAME + " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_DELETE " | " TOTP_CLI_COMMAND_DELETE_ALT) " " DOCOPT_ARGUMENT( + TOTP_CLI_COMMAND_DELETE_ARG_INDEX) " " DOCOPT_OPTIONAL(DOCOPT_SWITCH(TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX)) "\r\n"); +} + +void totp_cli_command_delete_docopt_arguments() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_DELETE_ARG_INDEX " Token index in the list\r\n"); +} + +void totp_cli_command_delete_docopt_options() { + TOTP_CLI_PRINTF(" " DOCOPT_SWITCH( + TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX) " Force command to do not ask user for interactive confirmation\r\n"); +} + +void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { + int token_number; + if(!args_read_int_and_trim(args, &token_number) || token_number <= 0 || + token_number > plugin_state->tokens_count) { + TOTP_CLI_PRINT_INVALID_ARGUMENTS(); + return; + } + + FuriString* temp_str = furi_string_alloc(); + bool confirm_needed = true; + if(args_read_string_and_trim(args, temp_str)) { + if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_DELETE_ARG_FORCE_SUFFIX) == 0) { + confirm_needed = false; + } else { + TOTP_CLI_PRINTF("Unknown argument \"%s\"\r\n", furi_string_get_cstr(temp_str)); + TOTP_CLI_PRINT_INVALID_ARGUMENTS(); + furi_string_free(temp_str); + return; + } + } + furi_string_free(temp_str); + + if(!totp_cli_ensure_authenticated(plugin_state, cli)) { + return; + } + + ListNode* list_node = list_element_at(plugin_state->tokens_list, token_number - 1); + + TokenInfo* token_info = list_node->data; + + bool confirmed = !confirm_needed; + if(confirm_needed) { + TOTP_CLI_PRINTF("WARNING!\r\n"); + TOTP_CLI_PRINTF( + "TOKEN \"%s\" WILL BE PERMANENTLY DELETED WITHOUT ABILITY TO RECOVER IT.\r\n", + token_info->name); + TOTP_CLI_PRINTF("Confirm? [y/n]\r\n"); + fflush(stdout); + char user_pick; + do { + user_pick = tolower(cli_getc(cli)); + } while(user_pick != 'y' && user_pick != 'n' && user_pick != CliSymbolAsciiCR && + user_pick != CliSymbolAsciiETX && user_pick != CliSymbolAsciiEsc); + + confirmed = user_pick == 'y' || user_pick == CliSymbolAsciiCR; + } + + if(confirmed) { + if(!totp_cli_ensure_authenticated(plugin_state, cli)) { + return; + } + + bool activate_generate_token_scene = false; + if(plugin_state->current_scene != TotpSceneAuthentication) { + totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL); + activate_generate_token_scene = true; + } + + plugin_state->tokens_list = list_remove(plugin_state->tokens_list, list_node); + plugin_state->tokens_count--; + + totp_full_save_config_file(plugin_state); + + if(activate_generate_token_scene) { + 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 { + TOTP_CLI_PRINTF("User not confirmed\r\n"); + } +} \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/commands/delete/delete.h b/applications/plugins/totp/services/cli/commands/delete/delete.h new file mode 100644 index 000000000..0b60932e3 --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/delete/delete.h @@ -0,0 +1,13 @@ +#pragma once + +#include +#include "../../../../types/plugin_state.h" + +#define TOTP_CLI_COMMAND_DELETE "delete" +#define TOTP_CLI_COMMAND_DELETE_ALT "rm" + +void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args, Cli* cli); +void totp_cli_command_delete_docopt_commands(); +void totp_cli_command_delete_docopt_usage(); +void totp_cli_command_delete_docopt_arguments(); +void totp_cli_command_delete_docopt_options(); \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/commands/help/help.c b/applications/plugins/totp/services/cli/commands/help/help.c new file mode 100644 index 000000000..ab592fbba --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/help/help.c @@ -0,0 +1,42 @@ +#include "help.h" +#include "../../cli_helpers.h" +#include "../add/add.h" +#include "../delete/delete.h" +#include "../list/list.h" +#include "../timezone/timezone.h" + +void totp_cli_command_help_docopt_commands() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT + ", " TOTP_CLI_COMMAND_HELP_ALT2 " Show command usage help\r\n"); +} + +void totp_cli_command_help_docopt_usage() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " DOCOPT_REQUIRED( + TOTP_CLI_COMMAND_HELP " | " TOTP_CLI_COMMAND_HELP_ALT + " | " TOTP_CLI_COMMAND_HELP_ALT2) "\r\n"); +} + +void totp_cli_command_help_handle() { + TOTP_CLI_PRINTF("Usage:\r\n"); + totp_cli_command_help_docopt_usage(); + totp_cli_command_list_docopt_usage(); + totp_cli_command_add_docopt_usage(); + totp_cli_command_delete_docopt_usage(); + totp_cli_command_timezone_docopt_usage(); + cli_nl(); + TOTP_CLI_PRINTF("Commands:\r\n"); + totp_cli_command_help_docopt_commands(); + totp_cli_command_list_docopt_commands(); + totp_cli_command_add_docopt_commands(); + totp_cli_command_delete_docopt_commands(); + totp_cli_command_timezone_docopt_commands(); + cli_nl(); + TOTP_CLI_PRINTF("Arguments:\r\n"); + totp_cli_command_add_docopt_arguments(); + totp_cli_command_delete_docopt_arguments(); + totp_cli_command_timezone_docopt_arguments(); + cli_nl(); + TOTP_CLI_PRINTF("Options:\r\n"); + totp_cli_command_add_docopt_options(); + totp_cli_command_delete_docopt_options(); +} \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/commands/help/help.h b/applications/plugins/totp/services/cli/commands/help/help.h new file mode 100644 index 000000000..4268b8bc5 --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/help/help.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +#define TOTP_CLI_COMMAND_HELP "help" +#define TOTP_CLI_COMMAND_HELP_ALT "h" +#define TOTP_CLI_COMMAND_HELP_ALT2 "?" + +void totp_cli_command_help_handle(); +void totp_cli_command_help_docopt_commands(); +void totp_cli_command_help_docopt_usage(); \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/commands/list/list.c b/applications/plugins/totp/services/cli/commands/list/list.c new file mode 100644 index 000000000..61791084d --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/list/list.c @@ -0,0 +1,71 @@ +#include "list.h" +#include +#include "../../../list/list.h" +#include "../../../../types/token_info.h" +#include "../../../config/constants.h" +#include "../../cli_helpers.h" + +static char* get_algo_as_cstr(TokenHashAlgo algo) { + switch(algo) { + case SHA1: + return TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME; + case SHA256: + return TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME; + case SHA512: + return TOTP_CONFIG_TOKEN_ALGO_SHA512_NAME; + } + + return "UNKNOWN"; +} + +static uint8_t get_digits_as_int(TokenDigitsCount digits) { + switch(digits) { + case TOTP_6_DIGITS: + return 6; + case TOTP_8_DIGITS: + return 8; + } + + return 6; +} + +void totp_cli_command_list_docopt_commands() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_LIST ", " TOTP_CLI_COMMAND_LIST_ALT + " List all available tokens\r\n"); +} + +void totp_cli_command_list_docopt_usage() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_NAME " " DOCOPT_REQUIRED( + TOTP_CLI_COMMAND_LIST " | " TOTP_CLI_COMMAND_LIST_ALT) "\r\n"); +} + +void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) { + if(!totp_cli_ensure_authenticated(plugin_state, cli)) { + return; + } + + if(plugin_state->tokens_list == NULL) { + TOTP_CLI_PRINTF("There are no tokens"); + return; + } + + ListNode* node = plugin_state->tokens_list; + + TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n"); + TOTP_CLI_PRINTF("| %-*s | %-*s | %-*s | %-s |\r\n", 3, "#", 27, "Name", 6, "Algo", "Digits"); + TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n"); + uint16_t index = 1; + while(node != NULL) { + TokenInfo* token_info = (TokenInfo*)node->data; + token_info_get_digits_count(token_info); + TOTP_CLI_PRINTF( + "| %-3" PRIu16 " | %-27.27s | %-6s | %-6" PRIu8 " |\r\n", + index, + token_info->name, + get_algo_as_cstr(token_info->algo), + get_digits_as_int(token_info->digits)); + node = node->next; + index++; + } + TOTP_CLI_PRINTF("+-----+-----------------------------+--------+--------+\r\n"); +} \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/commands/list/list.h b/applications/plugins/totp/services/cli/commands/list/list.h new file mode 100644 index 000000000..d8c3cb127 --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/list/list.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include "../../../../types/plugin_state.h" + +#define TOTP_CLI_COMMAND_LIST "list" +#define TOTP_CLI_COMMAND_LIST_ALT "ls" + +void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli); +void totp_cli_command_list_docopt_commands(); +void totp_cli_command_list_docopt_usage(); diff --git a/applications/plugins/totp/services/cli/commands/timezone/timezone.c b/applications/plugins/totp/services/cli/commands/timezone/timezone.c new file mode 100644 index 000000000..d997aa116 --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/timezone/timezone.c @@ -0,0 +1,54 @@ +#include "timezone.h" +#include +#include "../../../config/config.h" +#include "../../../../scenes/scene_director.h" +#include "../../cli_helpers.h" + +#define TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE "timezone" + +void totp_cli_command_timezone_docopt_commands() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_TIMEZONE ", " TOTP_CLI_COMMAND_TIMEZONE_ALT + " Get or set current timezone\r\n"); +} + +void totp_cli_command_timezone_docopt_usage() { + TOTP_CLI_PRINTF( + " " TOTP_CLI_COMMAND_NAME + " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_TIMEZONE " | " TOTP_CLI_COMMAND_TIMEZONE_ALT) " " DOCOPT_OPTIONAL( + DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE)) "\r\n"); +} + +void totp_cli_command_timezone_docopt_arguments() { + TOTP_CLI_PRINTF(" " TOTP_CLI_COMMAND_TIMEZONE_ARG_TIMEZONE + " Timezone offset in hours to be set.\r\n"); + TOTP_CLI_PRINTF( + " If not provided then current timezone offset will be printed\r\n"); +} + +void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli) { + if(!totp_cli_ensure_authenticated(plugin_state, cli)) { + return; + } + + FuriString* temp_str = furi_string_alloc(); + if(args_read_string_and_trim(args, temp_str)) { + float tz = strtof(furi_string_get_cstr(temp_str), NULL); + if(tz >= -12.75f && tz <= 12.75f) { + plugin_state->timezone_offset = tz; + totp_config_file_update_timezone_offset(tz); + TOTP_CLI_PRINTF("Timezone is set to %f\r\n", tz); + if(plugin_state->current_scene == TotpSceneGenerateToken) { + totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL); + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL); + } else if(plugin_state->current_scene == TotpSceneAppSettings) { + totp_scene_director_activate_scene(plugin_state, TotpSceneNone, NULL); + totp_scene_director_activate_scene(plugin_state, TotpSceneAppSettings, NULL); + } + } else { + TOTP_CLI_PRINTF("Invalid timezone offset\r\n"); + } + } else { + TOTP_CLI_PRINTF("Current timezone offset is %f\r\n", plugin_state->timezone_offset); + } + furi_string_free(temp_str); +} \ No newline at end of file diff --git a/applications/plugins/totp/services/cli/commands/timezone/timezone.h b/applications/plugins/totp/services/cli/commands/timezone/timezone.h new file mode 100644 index 000000000..0c0d82abf --- /dev/null +++ b/applications/plugins/totp/services/cli/commands/timezone/timezone.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include "../../../../types/plugin_state.h" + +#define TOTP_CLI_COMMAND_TIMEZONE "timezone" +#define TOTP_CLI_COMMAND_TIMEZONE_ALT "tz" + +void totp_cli_command_timezone_handle(PluginState* plugin_state, FuriString* args, Cli* cli); +void totp_cli_command_timezone_docopt_commands(); +void totp_cli_command_timezone_docopt_usage(); +void totp_cli_command_timezone_docopt_arguments(); \ No newline at end of file diff --git a/applications/plugins/totp/services/config/config.c b/applications/plugins/totp/services/config/config.c index 9a72f9ca8..bb6cffde0 100644 --- a/applications/plugins/totp/services/config/config.c +++ b/applications/plugins/totp/services/config/config.c @@ -10,7 +10,7 @@ #define CONFIG_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf" #define CONFIG_FILE_BACKUP_PATH CONFIG_FILE_PATH ".backup" -uint8_t token_info_get_digits_as_int(TokenInfo* token_info) { +static uint8_t token_info_get_digits_as_int(const TokenInfo* token_info) { switch(token_info->digits) { case TOTP_6_DIGITS: return 6; @@ -21,7 +21,7 @@ uint8_t token_info_get_digits_as_int(TokenInfo* token_info) { return 6; } -void token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) { +static void token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) { switch(digits) { case 6: token_info->digits = TOTP_6_DIGITS; @@ -32,7 +32,7 @@ void token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) { } } -char* token_info_get_algo_as_cstr(TokenInfo* token_info) { +static char* token_info_get_algo_as_cstr(const TokenInfo* token_info) { switch(token_info->algo) { case SHA1: return TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME; @@ -45,12 +45,12 @@ char* token_info_get_algo_as_cstr(TokenInfo* token_info) { return NULL; } -void token_info_set_algo_from_str(TokenInfo* token_info, FuriString* str) { +static void token_info_set_algo_from_str(TokenInfo* token_info, const FuriString* str) { if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME) == 0) { token_info->algo = SHA1; - } else if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME)) { + } else if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME) == 0) { token_info->algo = SHA256; - } else if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA512_NAME)) { + } else if(furi_string_cmpi_str(str, TOTP_CONFIG_TOKEN_ALGO_SHA512_NAME) == 0) { token_info->algo = SHA512; } } @@ -152,7 +152,7 @@ FlipperFormat* totp_open_config_file(Storage* storage) { return fff_data_file; } -void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_info) { +void totp_config_file_save_new_token_i(FlipperFormat* file, const 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; @@ -170,7 +170,7 @@ void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_inf flipper_format_write_uint32(file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &digits_count_as_uint32, 1); } -void totp_config_file_save_new_token(TokenInfo* token_info) { +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); @@ -190,7 +190,7 @@ void totp_config_file_update_timezone_offset(float new_timezone_offset) { totp_close_storage(); } -void totp_full_save_config_file(PluginState* const plugin_state) { +void totp_full_save_config_file(const PluginState* const plugin_state) { Storage* storage = totp_open_storage(); FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); @@ -209,7 +209,7 @@ void totp_full_save_config_file(PluginState* const plugin_state) { flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1); ListNode* node = plugin_state->tokens_list; while(node != NULL) { - TokenInfo* token_info = node->data; + const TokenInfo* token_info = node->data; totp_config_file_save_new_token_i(fff_data_file, token_info); node = node->next; } @@ -343,9 +343,9 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) TokenInfo* tokenInfo = token_info_alloc(); - const char* temp_cstr = furi_string_get_cstr(temp_str); - tokenInfo->name = (char*)malloc(strlen(temp_cstr) + 1); - strcpy(tokenInfo->name, temp_cstr); + size_t temp_cstr_len = furi_string_size(temp_str); + tokenInfo->name = (char*)malloc(temp_cstr_len + 1); + strlcpy(tokenInfo->name, furi_string_get_cstr(temp_str), temp_cstr_len + 1); uint32_t secret_bytes_count; if(!flipper_format_get_value_count( @@ -355,9 +355,11 @@ TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) if(secret_bytes_count == 1) { // Plain secret key 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])) { + tokenInfo, + furi_string_get_cstr(temp_str), + furi_string_size(temp_str), + &plugin_state->iv[0])) { FURI_LOG_W(LOGGING_TAG, "Token \"%s\" has plain secret", tokenInfo->name); } else { tokenInfo->token = NULL; diff --git a/applications/plugins/totp/services/config/config.h b/applications/plugins/totp/services/config/config.h index 76cb40b2c..d452ad4b3 100644 --- a/applications/plugins/totp/services/config/config.h +++ b/applications/plugins/totp/services/config/config.h @@ -16,8 +16,8 @@ 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_full_save_config_file(const PluginState* const plugin_state); void totp_config_file_load_base(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_save_new_token(const TokenInfo* token_info); void totp_config_file_update_timezone_offset(float new_timezone_offset); diff --git a/applications/plugins/totp/services/crypto/crypto.c b/applications/plugins/totp/services/crypto/crypto.c index ade2f9f49..79e41e6fd 100644 --- a/applications/plugins/totp/services/crypto/crypto.c +++ b/applications/plugins/totp/services/crypto/crypto.c @@ -3,6 +3,7 @@ #include #include "../config/config.h" #include "../../types/common.h" +#include "memset_s.h" #define CRYPTO_KEY_SLOT 2 #define CRYPTO_VERIFY_KEY "FFF_Crypto_pass" @@ -11,13 +12,13 @@ uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, - const uint8_t plain_data_length, + const size_t plain_data_length, const uint8_t* iv, - uint8_t* encrypted_data_length) { + size_t* encrypted_data_length) { uint8_t* encrypted_data; size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR; if(remain) { - uint8_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR; + size_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR; uint8_t* plain_data_aligned = malloc(plain_data_aligned_length); memset(plain_data_aligned, 0, plain_data_aligned_length); memcpy(plain_data_aligned, plain_data, plain_data_length); @@ -29,7 +30,7 @@ uint8_t* totp_crypto_encrypt( furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length); furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT); - memset(plain_data_aligned, 0, plain_data_aligned_length); + memset_s(plain_data_aligned, sizeof(plain_data_aligned), 0, plain_data_aligned_length); free(plain_data_aligned); } else { encrypted_data = malloc(plain_data_length); @@ -45,9 +46,9 @@ uint8_t* totp_crypto_encrypt( uint8_t* totp_crypto_decrypt( const uint8_t* encrypted_data, - const uint8_t encrypted_data_length, + const size_t encrypted_data_length, const uint8_t* iv, - uint8_t* decrypted_data_length) { + size_t* decrypted_data_length) { *decrypted_data_length = encrypted_data_length; uint8_t* decrypted_data = malloc(*decrypted_data_length); furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv); @@ -56,7 +57,7 @@ uint8_t* totp_crypto_decrypt( return decrypted_data; } -void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length) { +void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { if(plugin_state->crypto_verify_data == NULL) { FURI_LOG_D(LOGGING_TAG, "Generating new IV"); furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE); @@ -118,8 +119,8 @@ void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_le } bool totp_crypto_verify_key(const PluginState* plugin_state) { - uint8_t decrypted_key_length; - uint8_t* decrypted_key = totp_crypto_decrypt( + size_t decrypted_key_length; + const uint8_t* decrypted_key = totp_crypto_decrypt( plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length, &plugin_state->iv[0], diff --git a/applications/plugins/totp/services/crypto/crypto.h b/applications/plugins/totp/services/crypto/crypto.h index 9fc319659..f0a28f798 100644 --- a/applications/plugins/totp/services/crypto/crypto.h +++ b/applications/plugins/totp/services/crypto/crypto.h @@ -4,13 +4,13 @@ uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, - const uint8_t plain_data_length, + const size_t plain_data_length, const uint8_t* iv, - uint8_t* encrypted_data_length); + size_t* encrypted_data_length); uint8_t* totp_crypto_decrypt( const uint8_t* encrypted_data, - const uint8_t encrypted_data_length, + const size_t encrypted_data_length, const uint8_t* iv, - uint8_t* decrypted_data_length); -void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length); + size_t* decrypted_data_length); +void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); bool totp_crypto_verify_key(const PluginState* plugin_state); \ No newline at end of file diff --git a/applications/plugins/totp/services/crypto/memset_s.c b/applications/plugins/totp/services/crypto/memset_s.c new file mode 100644 index 000000000..81c285c0d --- /dev/null +++ b/applications/plugins/totp/services/crypto/memset_s.c @@ -0,0 +1,22 @@ +#include "memset_s.h" + +#define RSIZE_MAX 0x7fffffffffffffffUL + +errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n) { + if(!s || smax > RSIZE_MAX) { + return EINVAL; + } + + errno_t violation_present = 0; + if(n > smax) { + n = smax; + violation_present = EINVAL; + } + + volatile unsigned char* v = s; + for(rsize_t i = 0u; i < n; ++i) { + *v++ = (unsigned char)c; + } + + return violation_present; +} \ No newline at end of file diff --git a/applications/plugins/totp/services/crypto/memset_s.h b/applications/plugins/totp/services/crypto/memset_s.h new file mode 100644 index 000000000..2889e23b2 --- /dev/null +++ b/applications/plugins/totp/services/crypto/memset_s.h @@ -0,0 +1,16 @@ +#pragma once + +#include +#include +#include + +#ifndef _RSIZE_T_DECLARED +typedef uint64_t rsize_t; +#define _RSIZE_T_DECLARED +#endif +#ifndef _ERRNOT_DECLARED +typedef int16_t errno_t; +#define _ERRNOT_DECLARED +#endif + +errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n); \ No newline at end of file diff --git a/applications/plugins/totp/services/list/list.c b/applications/plugins/totp/services/list/list.c index 77df1105a..3a3317980 100644 --- a/applications/plugins/totp/services/list/list.c +++ b/applications/plugins/totp/services/list/list.c @@ -44,6 +44,10 @@ ListNode* list_element_at(ListNode* head, uint16_t index) { } ListNode* list_remove(ListNode* head, ListNode* ep) { + if(head == NULL) { + return NULL; + } + if(head == ep) { ListNode* new_head = head->next; free(head); diff --git a/applications/plugins/totp/services/totp/totp.c b/applications/plugins/totp/services/totp/totp.c index 90e49367d..68531e171 100644 --- a/applications/plugins/totp/services/totp/totp.c +++ b/applications/plugins/totp/services/totp/totp.c @@ -42,14 +42,14 @@ uint32_t otp_generate( TOTP_ALGO algo, uint8_t digits, const uint8_t* plain_secret, - uint8_t plain_secret_length, + size_t plain_secret_length, uint64_t input) { uint8_t* hmac = malloc(64); memset(hmac, 0, 64); uint64_t input_swapped = swap_uint64(input); - int hmac_len = (*(algo))(plain_secret, plain_secret_length, (uint8_t*)&input_swapped, 8, hmac); + int hmac_len = (*algo)(plain_secret, plain_secret_length, (uint8_t*)&input_swapped, 8, hmac); if(hmac_len == 0) { free(hmac); return OTP_ERROR; @@ -80,7 +80,7 @@ uint32_t totp_at( TOTP_ALGO algo, uint8_t digits, const uint8_t* plain_secret, - uint8_t plain_secret_length, + size_t plain_secret_length, uint64_t for_time, float timezone, uint8_t interval) { @@ -96,9 +96,9 @@ uint32_t totp_at( static int totp_algo_sha1( const uint8_t* key, - uint8_t key_length, + size_t key_length, const uint8_t* input, - uint8_t input_length, + size_t input_length, uint8_t* output) { hmac_sha1(key, key_length, input, input_length, output); return HMAC_SHA1_RESULT_SIZE; @@ -106,9 +106,9 @@ static int totp_algo_sha1( static int totp_algo_sha256( const uint8_t* key, - uint8_t key_length, + size_t key_length, const uint8_t* input, - uint8_t input_length, + size_t input_length, uint8_t* output) { hmac_sha256(key, key_length, input, input_length, output); return HMAC_SHA256_RESULT_SIZE; @@ -116,9 +116,9 @@ static int totp_algo_sha256( static int totp_algo_sha512( const uint8_t* key, - uint8_t key_length, + size_t key_length, const uint8_t* input, - uint8_t input_length, + size_t input_length, uint8_t* output) { hmac_sha512(key, key_length, input, input_length, output); return HMAC_SHA512_RESULT_SIZE; diff --git a/applications/plugins/totp/services/totp/totp.h b/applications/plugins/totp/services/totp/totp.h index 31e70e01b..431ca11aa 100644 --- a/applications/plugins/totp/services/totp/totp.h +++ b/applications/plugins/totp/services/totp/totp.h @@ -17,9 +17,9 @@ */ typedef int (*TOTP_ALGO)( const uint8_t* key, - uint8_t key_length, + size_t key_length, const uint8_t* input, - uint8_t input_length, + size_t input_length, uint8_t* output); /* @@ -47,7 +47,7 @@ uint32_t totp_at( TOTP_ALGO algo, uint8_t digits, const uint8_t* plain_secret, - uint8_t plain_secret_length, + size_t plain_secret_length, uint64_t for_time, float timezone, uint8_t interval); diff --git a/applications/plugins/totp/services/ui/ui_controls.c b/applications/plugins/totp/services/ui/ui_controls.c index 7f6a4dd4d..8ed73498c 100644 --- a/applications/plugins/totp/services/ui/ui_controls.c +++ b/applications/plugins/totp/services/ui/ui_controls.c @@ -5,7 +5,7 @@ #define TEXT_BOX_HEIGHT 13 #define TEXT_BOX_MARGIN 4 -void ui_control_text_box_render(Canvas* const canvas, int8_t y, char* text, bool is_selected) { +void ui_control_text_box_render(Canvas* const canvas, int16_t y, const char* text, bool is_selected) { if(y < -TEXT_BOX_HEIGHT) { return; } @@ -44,7 +44,7 @@ void ui_control_select_render( int16_t x, int16_t y, uint8_t width, - char* text, + const char* text, bool is_selected) { if(y < -TEXT_BOX_HEIGHT) { return; @@ -99,7 +99,7 @@ void ui_control_button_render( int16_t y, uint8_t width, uint8_t height, - char* text, + const char* text, bool is_selected) { if(y < -height) { return; diff --git a/applications/plugins/totp/services/ui/ui_controls.h b/applications/plugins/totp/services/ui/ui_controls.h index e86b3e5d9..02b278cf9 100644 --- a/applications/plugins/totp/services/ui/ui_controls.h +++ b/applications/plugins/totp/services/ui/ui_controls.h @@ -3,19 +3,19 @@ #include #include -void ui_control_text_box_render(Canvas* const canvas, int8_t y, char* text, bool is_selected); +void ui_control_text_box_render(Canvas* const canvas, int16_t y, const char* text, bool is_selected); void ui_control_button_render( Canvas* const canvas, int16_t x, int16_t y, uint8_t width, uint8_t height, - char* text, + const char* text, bool is_selected); void ui_control_select_render( Canvas* const canvas, int16_t x, int16_t y, uint8_t width, - char* text, + const char* text, bool is_selected); diff --git a/applications/plugins/totp/totp_app.c b/applications/plugins/totp/totp_app.c index 24fcbd36d..3bc85e211 100644 --- a/applications/plugins/totp/totp_app.c +++ b/applications/plugins/totp/totp_app.c @@ -18,6 +18,7 @@ #include "scenes/scene_director.h" #include "services/ui/constants.h" #include "services/crypto/crypto.h" +#include "services/cli/cli.h" #define IDLE_TIMEOUT 60000 @@ -37,12 +38,15 @@ static void input_callback(InputEvent* input_event, FuriMessageQueue* event_queu furi_message_queue_put(event_queue, &event, FuriWaitForever); } -static bool totp_state_init(PluginState* const plugin_state) { +static bool totp_plugin_state_init(PluginState* const plugin_state) { plugin_state->gui = furi_record_open(RECORD_GUI); plugin_state->notification = furi_record_open(RECORD_NOTIFICATION); plugin_state->dialogs = 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) { @@ -77,7 +81,9 @@ static bool totp_state_init(PluginState* const plugin_state) { return true; } -static void 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); @@ -106,16 +112,16 @@ int32_t totp_app() { FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(PluginEvent)); PluginState* plugin_state = malloc(sizeof(PluginState)); - if (!totp_state_init(plugin_state)) { + if (!totp_plugin_state_init(plugin_state)) { FURI_LOG_E(LOGGING_TAG, "App state initialization failed\r\n"); - plugin_state_free(plugin_state); + totp_plugin_state_free(plugin_state); return 254; } ValueMutex state_mutex; if(!init_mutex(&state_mutex, plugin_state, sizeof(PluginState))) { FURI_LOG_E(LOGGING_TAG, "Cannot create mutex\r\n"); - plugin_state_free(plugin_state); + totp_plugin_state_free(plugin_state); return 255; } @@ -134,20 +140,20 @@ int32_t totp_app() { if (plugin_state->changing_scene) continue; FuriStatus event_status = furi_message_queue_get(event_queue, &event, 100); - PluginState* plugin_state = acquire_mutex_block(&state_mutex); + PluginState* plugin_state_m = acquire_mutex_block(&state_mutex); if(event_status == FuriStatusOk) { if (event.type == EventTypeKey) { last_user_interaction_time = furi_get_tick(); } - processing = totp_scene_director_handle_event(&event, plugin_state); - } else if (plugin_state->pin_set && plugin_state->current_scene != TotpSceneAuthentication && furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { - totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL); + processing = totp_scene_director_handle_event(&event, plugin_state_m); + } else if (plugin_state_m->pin_set && plugin_state_m->current_scene != TotpSceneAuthentication && furi_get_tick() - last_user_interaction_time > IDLE_TIMEOUT) { + totp_scene_director_activate_scene(plugin_state_m, TotpSceneAuthentication, NULL); } view_port_update(view_port); - release_mutex(&state_mutex, plugin_state); + release_mutex(&state_mutex, plugin_state_m); } view_port_enabled_set(view_port, false); @@ -155,6 +161,6 @@ int32_t totp_app() { view_port_free(view_port); furi_message_queue_free(event_queue); delete_mutex(&state_mutex); - plugin_state_free(plugin_state); + totp_plugin_state_free(plugin_state); return 0; } diff --git a/applications/plugins/totp/types/plugin_state.h b/applications/plugins/totp/types/plugin_state.h index 98afe53cf..26e7e244b 100644 --- a/applications/plugins/totp/types/plugin_state.h +++ b/applications/plugins/totp/types/plugin_state.h @@ -22,7 +22,7 @@ typedef struct { uint8_t tokens_count; uint8_t* crypto_verify_data; - uint8_t crypto_verify_data_length; + size_t crypto_verify_data_length; bool pin_set; uint8_t iv[TOTP_IV_SIZE]; uint8_t base_iv[TOTP_IV_SIZE]; diff --git a/applications/plugins/totp/types/token_info.c b/applications/plugins/totp/types/token_info.c index 09ad1230a..2a37c4d44 100644 --- a/applications/plugins/totp/types/token_info.c +++ b/applications/plugins/totp/types/token_info.c @@ -5,6 +5,7 @@ #include "common.h" #include "../services/base32/base32.h" #include "../services/crypto/crypto.h" +#include "../services/crypto/memset_s.h" TokenInfo* token_info_alloc() { TokenInfo* tokenInfo = malloc(sizeof(TokenInfo)); @@ -23,7 +24,7 @@ void token_info_free(TokenInfo* token_info) { bool token_info_set_secret( TokenInfo* token_info, const char* base32_token_secret, - uint8_t token_secret_length, + size_t token_secret_length, uint8_t* iv) { uint8_t* plain_secret = malloc(token_secret_length); int plain_secret_length = @@ -37,7 +38,7 @@ bool token_info_set_secret( result = false; } - memset(plain_secret, 0, token_secret_length); + memset_s(plain_secret, sizeof(plain_secret), 0, token_secret_length); free(plain_secret); return result; } diff --git a/applications/plugins/totp/types/token_info.h b/applications/plugins/totp/types/token_info.h index e40c6e9bf..3d0f0ec61 100644 --- a/applications/plugins/totp/types/token_info.h +++ b/applications/plugins/totp/types/token_info.h @@ -8,7 +8,7 @@ typedef enum { TOTP_6_DIGITS, TOTP_8_DIGITS } TokenDigitsCount; typedef struct { uint8_t* token; - uint8_t token_length; + size_t token_length; char* name; TokenHashAlgo algo; TokenDigitsCount digits; @@ -19,6 +19,6 @@ void token_info_free(TokenInfo* token_info); bool token_info_set_secret( TokenInfo* token_info, const char* base32_token_secret, - uint8_t token_secret_length, + size_t token_secret_length, uint8_t* iv); uint8_t token_info_get_digits_count(TokenInfo* token_info);