Jelajahi Sumber

Implemented #26 (#27)

* Implemented #26 
* Improved HID worker shutdown code
* Refactoring
Alexander Kopachov 3 tahun lalu
induk
melakukan
ee4252c239

+ 1 - 1
scenes/app_settings/totp_app_settings.c

@@ -101,7 +101,7 @@ bool totp_scene_app_settings_handle_event(
     }
     }
 
 
     SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
     SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
-    if(event->input.type != InputTypePress) {
+    if(event->input.type != InputTypePress && event->input.type != InputTypeRepeat) {
         return true;
         return true;
     }
     }
 
 

+ 1 - 1
scenes/generate_token/totp_scene_generate_token.c

@@ -293,7 +293,7 @@ bool totp_scene_generate_token_handle_event(
         return true;
         return true;
     }
     }
 
 
-    if(event->input.type != InputTypePress) {
+    if(event->input.type != InputTypePress && event->input.type != InputTypeRepeat) {
         return true;
         return true;
     }
     }
 
 

+ 34 - 0
scenes/scene_director.h

@@ -5,12 +5,46 @@
 #include "../types/plugin_event.h"
 #include "../types/plugin_event.h"
 #include "totp_scenes_enum.h"
 #include "totp_scenes_enum.h"
 
 
+/**
+ * @brief Activates scene
+ * @param plugin_state application state
+ * @param scene scene to be activated
+ * @param context scene context to be passed to the scene activation method
+ */
 void totp_scene_director_activate_scene(
 void totp_scene_director_activate_scene(
     PluginState* const plugin_state,
     PluginState* const plugin_state,
     Scene scene,
     Scene scene,
     const void* context);
     const void* context);
+
+/**
+ * @brief Deactivate current scene
+ * @param plugin_state application state
+ */
 void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state);
 void totp_scene_director_deactivate_active_scene(PluginState* const plugin_state);
+
+/**
+ * @brief Initializes all the available scenes
+ * @param plugin_state application state
+ */
 void totp_scene_director_init_scenes(PluginState* const plugin_state);
 void totp_scene_director_init_scenes(PluginState* const plugin_state);
+
+/**
+ * @brief Renders current scene
+ * @param canvas canvas to render at
+ * @param plugin_state application state
+ */
 void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state);
 void totp_scene_director_render(Canvas* const canvas, PluginState* const plugin_state);
+
+/**
+ * @brief Disposes all the available scenes
+ * @param plugin_state application state
+ */
 void totp_scene_director_dispose(const PluginState* const plugin_state);
 void totp_scene_director_dispose(const PluginState* const plugin_state);
+
+/**
+ * @brief Handles application event for the current scene
+ * @param event event to be handled
+ * @param plugin_state application state
+ * @return \c true if event handled and applilcation should continue; \c false if application should be closed
+ */
 bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state);
 bool totp_scene_director_handle_event(PluginEvent* const event, PluginState* const plugin_state);

+ 7 - 6
scenes/token_menu/totp_scene_token_menu.c

@@ -147,13 +147,14 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt
             dialog_message_free(message);
             dialog_message_free(message);
             if(dialog_result == DialogMessageButtonRight &&
             if(dialog_result == DialogMessageButtonRight &&
                !scene_state->current_token_index.is_null) {
                !scene_state->current_token_index.is_null) {
-                ListNode* list_node = list_element_at(
-                    plugin_state->tokens_list, scene_state->current_token_index.value);
-
-                TokenInfo* tokenInfo = list_node->data;
-                token_info_free(tokenInfo);
-                plugin_state->tokens_list = list_remove(plugin_state->tokens_list, list_node);
+                TokenInfo* tokenInfo = NULL;
+                plugin_state->tokens_list = list_remove_at(
+                    plugin_state->tokens_list,
+                    scene_state->current_token_index.value,
+                    (void**)&tokenInfo);
                 plugin_state->tokens_count--;
                 plugin_state->tokens_count--;
+                furi_check(tokenInfo != NULL);
+                token_info_free(tokenInfo);
 
 
                 totp_full_save_config_file(plugin_state);
                 totp_full_save_config_file(plugin_state);
                 totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
                 totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);

+ 26 - 0
scenes/totp_scenes_enum.h

@@ -1,10 +1,36 @@
 #pragma once
 #pragma once
 
 
+/**
+ * @brief TOTP application scenes
+ */
 typedef enum {
 typedef enum {
+    /**
+     * @brief Empty scene which does nothing 
+     */
     TotpSceneNone,
     TotpSceneNone,
+
+    /**
+     * @brief Scene where user have to enter PIN to authenticate 
+     */
     TotpSceneAuthentication,
     TotpSceneAuthentication,
+
+    /**
+     * @brief Scene where actual TOTP token is getting generated and displayed to the user 
+     */
     TotpSceneGenerateToken,
     TotpSceneGenerateToken,
+
+    /**
+     * @brief Scene where user can add new token 
+     */
     TotpSceneAddNewToken,
     TotpSceneAddNewToken,
+
+    /**
+     * @brief Scene with a menu for given token, allowing user to do multiple actions
+     */
     TotpSceneTokenMenu,
     TotpSceneTokenMenu,
+
+    /**
+     * @brief Scene where user can change application settings 
+     */
     TotpSceneAppSettings
     TotpSceneAppSettings
 } Scene;
 } Scene;

+ 0 - 2
services/base32/base32.c

@@ -15,8 +15,6 @@
 // See the License for the specific language governing permissions and
 // See the License for the specific language governing permissions and
 // limitations under the License.
 // limitations under the License.
 
 
-#include <string.h>
-
 #include "base32.h"
 #include "base32.h"
 
 
 int base32_decode(const uint8_t* encoded, uint8_t* result, int bufSize) {
 int base32_decode(const uint8_t* encoded, uint8_t* result, int bufSize) {

+ 8 - 2
services/base32/base32.h

@@ -29,5 +29,11 @@
 
 
 #include <stdint.h>
 #include <stdint.h>
 
 
-int base32_decode(const uint8_t* encoded, uint8_t* result, int bufSize)
-    __attribute__((visibility("hidden")));
+/**
+ * @brief Decodes Base-32 encoded bytes into plain bytes.
+ * @param encoded Base-32 encoded bytes
+ * @param[out] result result output buffer
+ * @param bufSize result output buffer size
+ * @return Decoded result length in bytes if successfully decoded; \c -1 otherwise
+ */
+int base32_decode(const uint8_t* encoded, uint8_t* result, int bufSize);

+ 5 - 0
services/cli/cli.c

@@ -8,6 +8,7 @@
 #include "commands/delete/delete.h"
 #include "commands/delete/delete.h"
 #include "commands/timezone/timezone.h"
 #include "commands/timezone/timezone.h"
 #include "commands/help/help.h"
 #include "commands/help/help.h"
+#include "commands/move/move.h"
 
 
 static void totp_cli_print_unknown_command(const FuriString* unknown_command) {
 static void totp_cli_print_unknown_command(const FuriString* unknown_command) {
     TOTP_CLI_PRINTF(
     TOTP_CLI_PRINTF(
@@ -44,6 +45,10 @@ static void totp_cli_handler(Cli* cli, FuriString* args, void* context) {
         furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE) == 0 ||
         furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE) == 0 ||
         furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE_ALT) == 0) {
         furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_TIMEZONE_ALT) == 0) {
         totp_cli_command_timezone_handle(plugin_state, args, cli);
         totp_cli_command_timezone_handle(plugin_state, args, cli);
+    } else if(
+        furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_MOVE) == 0 ||
+        furi_string_cmp_str(cmd, TOTP_CLI_COMMAND_MOVE_ALT) == 0) {
+        totp_cli_command_move_handle(plugin_state, args, cli);
     } else {
     } else {
         totp_cli_print_unknown_command(cmd);
         totp_cli_print_unknown_command(cmd);
     }
     }

+ 2 - 0
services/cli/commands/add/add.c

@@ -175,6 +175,8 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
         } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) == 0) {
         } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_ADD_ARG_UNSECURE_PREFIX) == 0) {
             mask_user_input = false;
             mask_user_input = false;
             parsed = true;
             parsed = true;
+        } else {
+            TOTP_CLI_PRINTF("Unknown argument \"%s\"\r\n", furi_string_get_cstr(temp_str));
         }
         }
 
 
         if(!parsed) {
         if(!parsed) {

+ 4 - 0
services/cli/commands/help/help.c

@@ -4,6 +4,7 @@
 #include "../delete/delete.h"
 #include "../delete/delete.h"
 #include "../list/list.h"
 #include "../list/list.h"
 #include "../timezone/timezone.h"
 #include "../timezone/timezone.h"
+#include "../move/move.h"
 
 
 void totp_cli_command_help_docopt_commands() {
 void totp_cli_command_help_docopt_commands() {
     TOTP_CLI_PRINTF("  " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT
     TOTP_CLI_PRINTF("  " TOTP_CLI_COMMAND_HELP ", " TOTP_CLI_COMMAND_HELP_ALT
@@ -23,6 +24,7 @@ void totp_cli_command_help_handle() {
     totp_cli_command_add_docopt_usage();
     totp_cli_command_add_docopt_usage();
     totp_cli_command_delete_docopt_usage();
     totp_cli_command_delete_docopt_usage();
     totp_cli_command_timezone_docopt_usage();
     totp_cli_command_timezone_docopt_usage();
+    totp_cli_command_move_docopt_usage();
     cli_nl();
     cli_nl();
     TOTP_CLI_PRINTF("Commands:\r\n");
     TOTP_CLI_PRINTF("Commands:\r\n");
     totp_cli_command_help_docopt_commands();
     totp_cli_command_help_docopt_commands();
@@ -30,6 +32,7 @@ void totp_cli_command_help_handle() {
     totp_cli_command_add_docopt_commands();
     totp_cli_command_add_docopt_commands();
     totp_cli_command_delete_docopt_commands();
     totp_cli_command_delete_docopt_commands();
     totp_cli_command_timezone_docopt_commands();
     totp_cli_command_timezone_docopt_commands();
+    totp_cli_command_move_docopt_commands();
     cli_nl();
     cli_nl();
     TOTP_CLI_PRINTF("Arguments:\r\n");
     TOTP_CLI_PRINTF("Arguments:\r\n");
     totp_cli_command_add_docopt_arguments();
     totp_cli_command_add_docopt_arguments();
@@ -39,4 +42,5 @@ void totp_cli_command_help_handle() {
     TOTP_CLI_PRINTF("Options:\r\n");
     TOTP_CLI_PRINTF("Options:\r\n");
     totp_cli_command_add_docopt_options();
     totp_cli_command_add_docopt_options();
     totp_cli_command_delete_docopt_options();
     totp_cli_command_delete_docopt_options();
+    totp_cli_command_move_docopt_options();
 }
 }

+ 164 - 0
services/cli/commands/move/move.c

@@ -0,0 +1,164 @@
+#include "move.h"
+
+#include <stdlib.h>
+#include <lib/toolbox/args.h>
+#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_MOVE_ARG_INDEX "index"
+
+#define TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME "name"
+#define TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME_PREFIX "-n"
+
+#define TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX "index"
+#define TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX_PREFIX "-i"
+
+void totp_cli_command_move_docopt_commands() {
+    TOTP_CLI_PRINTF("  " TOTP_CLI_COMMAND_MOVE ", " TOTP_CLI_COMMAND_MOVE_ALT
+                    "         Move\\rename token\r\n");
+}
+
+void totp_cli_command_move_docopt_usage() {
+    TOTP_CLI_PRINTF(
+        "  " TOTP_CLI_COMMAND_NAME
+        " " DOCOPT_REQUIRED(TOTP_CLI_COMMAND_MOVE " | " TOTP_CLI_COMMAND_MOVE_ALT) " " DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_INDEX) " " DOCOPT_OPTIONAL(
+            DOCOPT_OPTION(
+                TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME_PREFIX,
+                DOCOPT_ARGUMENT(
+                    TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME))) " " DOCOPT_OPTIONAL(DOCOPT_OPTION(TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX_PREFIX, DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX))) "\r\n");
+}
+
+void totp_cli_command_move_docopt_options() {
+    TOTP_CLI_PRINTF("  " DOCOPT_OPTION(
+        TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME_PREFIX,
+        DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME)) "      New token name.\r\n");
+    TOTP_CLI_PRINTF("  " DOCOPT_OPTION(
+        TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX_PREFIX,
+        DOCOPT_ARGUMENT(TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX)) "     New token index.\r\n");
+}
+
+void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, Cli* cli) {
+    int token_index;
+    if(!args_read_int_and_trim(args, &token_index)) {
+        TOTP_CLI_PRINT_INVALID_ARGUMENTS();
+        return;
+    }
+
+    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+        return;
+    }
+
+    if(token_index < 1 || token_index > plugin_state->tokens_count) {
+        TOTP_CLI_PRINT_INVALID_ARGUMENTS();
+        return;
+    }
+
+    FuriString* temp_str = furi_string_alloc();
+
+    char* new_token_name = NULL;
+    int new_token_index = 0;
+
+    while(args_read_string_and_trim(args, temp_str)) {
+        bool parsed = false;
+        if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME_PREFIX) == 0) {
+            if(!args_read_string_and_trim(args, temp_str)) {
+                TOTP_CLI_PRINTF(
+                    "Missed value for argument \"" TOTP_CLI_COMMAND_MOVE_ARG_NEW_NAME_PREFIX
+                    "\"\r\n");
+            } else {
+                if(new_token_name != NULL) {
+                    free(new_token_name);
+                }
+
+                new_token_name = malloc(furi_string_size(temp_str) + 1);
+                if(new_token_name == NULL) {
+                    furi_string_free(temp_str);
+                    return;
+                }
+
+                strlcpy(
+                    new_token_name,
+                    furi_string_get_cstr(temp_str),
+                    furi_string_size(temp_str) + 1);
+                parsed = true;
+            }
+        } else if(furi_string_cmpi_str(temp_str, TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX_PREFIX) == 0) {
+            if(!args_read_int_and_trim(args, &new_token_index)) {
+                TOTP_CLI_PRINTF(
+                    "Missed value for argument \"" TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX_PREFIX
+                    "\"\r\n");
+            } else if(new_token_index < 1 || new_token_index > plugin_state->tokens_count) {
+                TOTP_CLI_PRINTF(
+                    "\"%" PRId16
+                    "\" is incorrect value for argument \"" TOTP_CLI_COMMAND_MOVE_ARG_NEW_INDEX_PREFIX
+                    "\"\r\n",
+                    new_token_index);
+            } else {
+                parsed = true;
+            }
+        } else {
+            TOTP_CLI_PRINTF("Unknown argument \"%s\"\r\n", furi_string_get_cstr(temp_str));
+        }
+
+        if(!parsed) {
+            TOTP_CLI_PRINT_INVALID_ARGUMENTS();
+            furi_string_free(temp_str);
+            if(new_token_name != NULL) {
+                free(new_token_name);
+            }
+            return;
+        }
+    }
+
+    if(!totp_cli_ensure_authenticated(plugin_state, cli)) {
+        furi_string_free(temp_str);
+        if(new_token_name != NULL) {
+            free(new_token_name);
+        }
+        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;
+    }
+
+    bool token_updated = false;
+    TokenInfo* token_info = NULL;
+    if(new_token_index > 0) {
+        plugin_state->tokens_list =
+            list_remove_at(plugin_state->tokens_list, token_index - 1, (void**)&token_info);
+        furi_check(token_info != NULL);
+        plugin_state->tokens_list =
+            list_insert_at(plugin_state->tokens_list, new_token_index - 1, token_info);
+        token_updated = true;
+    } else {
+        token_info = list_element_at(plugin_state->tokens_list, token_index - 1)->data;
+    }
+
+    if(new_token_name != NULL) {
+        free(token_info->name);
+        token_info->name = new_token_name;
+        token_updated = true;
+    }
+
+    if(token_updated) {
+        totp_full_save_config_file(plugin_state);
+    }
+
+    if(activate_generate_token_scene) {
+        totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
+    }
+
+    if(token_updated) {
+        TOTP_CLI_PRINTF("Token \"%s\" has been successfully updated\r\n", token_info->name);
+    } else {
+        TOTP_CLI_PRINT_INVALID_ARGUMENTS();
+    }
+
+    furi_string_free(temp_str);
+}

+ 12 - 0
services/cli/commands/move/move.h

@@ -0,0 +1,12 @@
+#pragma once
+
+#include <cli/cli.h>
+#include "../../../../types/plugin_state.h"
+
+#define TOTP_CLI_COMMAND_MOVE "move"
+#define TOTP_CLI_COMMAND_MOVE_ALT "mv"
+
+void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, Cli* cli);
+void totp_cli_command_move_docopt_commands();
+void totp_cli_command_move_docopt_usage();
+void totp_cli_command_move_docopt_options();

+ 59 - 0
services/config/config.h

@@ -6,18 +6,77 @@
 #include "../../types/token_info.h"
 #include "../../types/token_info.h"
 #include "constants.h"
 #include "constants.h"
 
 
+/**
+ * @brief Token loading results
+ */
 typedef enum {
 typedef enum {
+    /**
+     * @brief All the tokens loaded successfully 
+     */
     TokenLoadingResultSuccess,
     TokenLoadingResultSuccess,
+
+    /**
+     * @brief All the tokens loaded, but there are some warnings
+     */
     TokenLoadingResultWarning,
     TokenLoadingResultWarning,
+
+    /**
+     * @brief Tokens not loaded because of error(s) 
+     */
     TokenLoadingResultError
     TokenLoadingResultError
 } TokenLoadingResult;
 } TokenLoadingResult;
 
 
+/**
+ * @brief Opens storage record
+ * @return Storage record
+ */
 Storage* totp_open_storage();
 Storage* totp_open_storage();
+
+/**
+ * @brief Closes storage record
+ */
 void totp_close_storage();
 void totp_close_storage();
+
+/**
+ * @brief Opens or creates TOTP application standard config file
+ * @param storage storage record to use
+ * @return Config file reference
+ */
 FlipperFormat* totp_open_config_file(Storage* storage);
 FlipperFormat* totp_open_config_file(Storage* storage);
+
+/**
+ * @brief Closes config file
+ * @param file config file reference
+ */
 void totp_close_config_file(FlipperFormat* file);
 void totp_close_config_file(FlipperFormat* file);
+
+/**
+ * @brief Saves all the settings and tokens to an application config file
+ * @param plugin_state application state
+ */
 void totp_full_save_config_file(const PluginState* const plugin_state);
 void totp_full_save_config_file(const PluginState* const plugin_state);
+
+/**
+ * @brief Loads basic information from an application config file into application state without loading all the tokens
+ * @param plugin_state application state
+ */
 void totp_config_file_load_base(PluginState* const plugin_state);
 void totp_config_file_load_base(PluginState* const plugin_state);
+
+/**
+ * @brief Loads tokens from an application config file into application state
+ * @param plugin_state application state
+ * @return Results of the loading
+ */
 TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state);
 TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state);
+
+/**
+ * @brief Add new token to the end of the application config file
+ * @param token_info token information to be saved
+ */
 void totp_config_file_save_new_token(const TokenInfo* token_info);
 void totp_config_file_save_new_token(const TokenInfo* token_info);
+
+/**
+ * @brief Updates timezone offset in an application config file
+ * @param new_timezone_offset new timezone offset to be set
+ */
 void totp_config_file_update_timezone_offset(float new_timezone_offset);
 void totp_config_file_update_timezone_offset(float new_timezone_offset);

+ 30 - 0
services/crypto/crypto.h

@@ -2,15 +2,45 @@
 
 
 #include "../../types/plugin_state.h"
 #include "../../types/plugin_state.h"
 
 
+/**
+ * @brief Encrypts plain data using built-in certificate and given initialization vector (IV)
+ * @param plain_data plain data to be encrypted
+ * @param plain_data_length plain data length
+ * @param iv initialization vector (IV) to be used to encrypt plain data
+ * @param[out] encrypted_data_length encrypted data length
+ * @return Encrypted data
+ */
 uint8_t* totp_crypto_encrypt(
 uint8_t* totp_crypto_encrypt(
     const uint8_t* plain_data,
     const uint8_t* plain_data,
     const size_t plain_data_length,
     const size_t plain_data_length,
     const uint8_t* iv,
     const uint8_t* iv,
     size_t* encrypted_data_length);
     size_t* encrypted_data_length);
+
+/**
+ * @brief Decrypts encrypted data using built-in certificate and given initialization vector (IV)
+ * @param encrypted_data encrypted data to be decrypted
+ * @param encrypted_data_length encrypted data length
+ * @param iv initialization vector (IV) to be used to encrypt plain data
+ * @param[out] decrypted_data_length decrypted data length
+ * @return Decrypted data
+ */
 uint8_t* totp_crypto_decrypt(
 uint8_t* totp_crypto_decrypt(
     const uint8_t* encrypted_data,
     const uint8_t* encrypted_data,
     const size_t encrypted_data_length,
     const size_t encrypted_data_length,
     const uint8_t* iv,
     const uint8_t* iv,
     size_t* decrypted_data_length);
     size_t* decrypted_data_length);
+
+/**
+ * @brief Seed initialization vector (IV) using user's PIN
+ * @param plugin_state application state
+ * @param pin user's PIN
+ * @param pin_length user's PIN length
+ */
 void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length);
 void totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length);
+
+/**
+ * @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption
+ * @param plugin_state application state
+ * @return \c true if cryptographic information is valid; \c false otherwise
+ */
 bool totp_crypto_verify_key(const PluginState* plugin_state);
 bool totp_crypto_verify_key(const PluginState* plugin_state);

+ 8 - 1
services/crypto/memset_s.h

@@ -2,7 +2,6 @@
 
 
 #include <errno.h>
 #include <errno.h>
 #include <stdint.h>
 #include <stdint.h>
-#include <string.h>
 
 
 #ifndef _RSIZE_T_DECLARED
 #ifndef _RSIZE_T_DECLARED
 typedef uint64_t rsize_t;
 typedef uint64_t rsize_t;
@@ -13,4 +12,12 @@ typedef int16_t errno_t; //-V677
 #define _ERRNOT_DECLARED
 #define _ERRNOT_DECLARED
 #endif
 #endif
 
 
+/**
+ * @brief Copies the value \p c into each of the first \p n characters of the object pointed to by \p s.
+ * @param s pointer to the object to fill
+ * @param smax size of the destination object
+ * @param c fill byte
+ * @param n number of bytes to fill
+ * @return \c 0 on success; non-zero otherwise
+ */
 errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n);
 errno_t memset_s(void* s, rsize_t smax, int c, rsize_t n);

+ 9 - 5
services/hid_worker/hid_worker.c

@@ -1,6 +1,6 @@
 #include "hid_worker.h"
 #include "hid_worker.h"
 
 
-const uint8_t hid_number_keys[10] = {
+static const uint8_t hid_number_keys[10] = {
     HID_KEYBOARD_0,
     HID_KEYBOARD_0,
     HID_KEYBOARD_1,
     HID_KEYBOARD_1,
     HID_KEYBOARD_2,
     HID_KEYBOARD_2,
@@ -19,6 +19,10 @@ static void totp_hid_worker_restore_usb_mode(TotpHidWorkerTypeContext* context)
     }
     }
 }
 }
 
 
+static inline bool totp_hid_worker_stop_requested() {
+    return furi_thread_flags_get() & TotpHidWorkerEvtStop;
+}
+
 static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
 static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
     context->usb_mode_prev = furi_hal_usb_get_config();
     context->usb_mode_prev = furi_hal_usb_get_config();
     furi_hal_usb_unlock();
     furi_hal_usb_unlock();
@@ -27,11 +31,11 @@ static void totp_hid_worker_type_code(TotpHidWorkerTypeContext* context) {
     do {
     do {
         furi_delay_ms(500);
         furi_delay_ms(500);
         i++;
         i++;
-    } while(!furi_hal_hid_is_connected() && i < 50);
-    furi_delay_ms(500);
+    } while(!furi_hal_hid_is_connected() && i < 100 && !totp_hid_worker_stop_requested());
 
 
     if(furi_hal_hid_is_connected() &&
     if(furi_hal_hid_is_connected() &&
        furi_mutex_acquire(context->string_sync, 500) == FuriStatusOk) {
        furi_mutex_acquire(context->string_sync, 500) == FuriStatusOk) {
+        furi_delay_ms(500);
         i = 0;
         i = 0;
         while(i < context->string_length && context->string[i] != 0) {
         while(i < context->string_length && context->string[i] != 0) {
             uint8_t digit = context->string[i] - '0';
             uint8_t digit = context->string[i] - '0';
@@ -91,7 +95,7 @@ TotpHidWorkerTypeContext* totp_hid_worker_start() {
 }
 }
 
 
 void totp_hid_worker_stop(TotpHidWorkerTypeContext* context) {
 void totp_hid_worker_stop(TotpHidWorkerTypeContext* context) {
-    furi_assert(context);
+    furi_assert(context != NULL);
     furi_thread_flags_set(furi_thread_get_id(context->thread), TotpHidWorkerEvtStop);
     furi_thread_flags_set(furi_thread_get_id(context->thread), TotpHidWorkerEvtStop);
     furi_thread_join(context->thread);
     furi_thread_join(context->thread);
     furi_thread_free(context->thread);
     furi_thread_free(context->thread);
@@ -101,6 +105,6 @@ void totp_hid_worker_stop(TotpHidWorkerTypeContext* context) {
 }
 }
 
 
 void totp_hid_worker_notify(TotpHidWorkerTypeContext* context, TotpHidWorkerEvtFlags event) {
 void totp_hid_worker_notify(TotpHidWorkerTypeContext* context, TotpHidWorkerEvtFlags event) {
-    furi_assert(context);
+    furi_assert(context != NULL);
     furi_thread_flags_set(furi_thread_get_id(context->thread), event);
     furi_thread_flags_set(furi_thread_get_id(context->thread), event);
 }
 }

+ 11 - 0
services/hmac/byteswap.h

@@ -2,5 +2,16 @@
 
 
 #include <stdint.h>
 #include <stdint.h>
 
 
+/**
+ * @brief Swap bytes in 32-bit value
+ * @param val value to swap bytes in
+ * @return Value with bytes swapped
+ */
 uint32_t swap_uint32(uint32_t val);
 uint32_t swap_uint32(uint32_t val);
+
+/**
+ * @brief Swap bytes in 64-bit value
+ * @param val value to swap bytes in
+ * @return Value with bytes swapped
+ */
 uint64_t swap_uint64(uint64_t val);
 uint64_t swap_uint64(uint64_t val);

+ 58 - 1
services/list/list.c

@@ -29,7 +29,7 @@ ListNode* list_add(ListNode* head, void* data) {
 }
 }
 
 
 ListNode* list_find(ListNode* head, const void* data) {
 ListNode* list_find(ListNode* head, const void* data) {
-    ListNode* it;
+    ListNode* it = NULL;
 
 
     for(it = head; it != NULL; it = it->next)
     for(it = head; it != NULL; it = it->next)
         if(it->data == data) break;
         if(it->data == data) break;
@@ -67,6 +67,63 @@ ListNode* list_remove(ListNode* head, ListNode* ep) {
     return head;
     return head;
 }
 }
 
 
+ListNode* list_remove_at(ListNode* head, uint16_t index, void** removed_node_data) {
+    if(head == NULL) {
+        return NULL;
+    }
+
+    ListNode* it;
+    ListNode* prev = NULL;
+
+    uint16_t i;
+
+    for(it = head, i = 0; it != NULL && i < index; prev = it, it = it->next, i++)
+        ;
+
+    if(it == NULL) return head;
+
+    ListNode* new_head = head;
+    if(prev == NULL) {
+        new_head = it->next;
+    } else {
+        prev->next = it->next;
+    }
+
+    if(removed_node_data != NULL) {
+        *removed_node_data = it->data;
+    }
+
+    free(it);
+
+    return new_head;
+}
+
+ListNode* list_insert_at(ListNode* head, uint16_t index, void* data) {
+    if(index == 0 || head == NULL) {
+        ListNode* new_head = list_init_head(data);
+        if(new_head != NULL) {
+            new_head->next = head;
+        }
+        return new_head;
+    }
+
+    ListNode* it;
+    ListNode* prev = NULL;
+
+    uint16_t i;
+
+    for(it = head, i = 0; it != NULL && i < index; prev = it, it = it->next, i++)
+        ;
+
+    ListNode* new = malloc(sizeof(ListNode));
+    if(new == NULL) return NULL;
+    new->data = data;
+    new->next = it;
+    prev->next = new;
+
+    return head;
+}
+
 void list_free(ListNode* head) {
 void list_free(ListNode* head) {
     ListNode* it = head;
     ListNode* it = head;
     ListNode* tmp;
     ListNode* tmp;

+ 70 - 10
services/list/list.h

@@ -3,25 +3,85 @@
 #include <stdlib.h>
 #include <stdlib.h>
 #include <inttypes.h>
 #include <inttypes.h>
 
 
+/**
+ * @brief Single linked list node
+ */
 typedef struct ListNode {
 typedef struct ListNode {
+    /**
+     * @brief Pointer to the data assigned to the current list node
+     */
     void* data;
     void* data;
+
+    /**
+     * @brief Pointer to the next list node
+     */
     struct ListNode* next;
     struct ListNode* next;
 } ListNode;
 } ListNode;
 
 
+/**
+ * @brief Initializes a new list node head
+ * @param data data to be assigned to the head list node
+ * @return Head list node
+ */
 ListNode* list_init_head(void* data);
 ListNode* list_init_head(void* data);
+
+/**
+ * @brief Adds new list node to the end of the list
+ * @param head head list node
+ * @param data data to be assigned to the newly added list node
+ * @return Head list node
+ */
 ListNode* list_add(
 ListNode* list_add(
     ListNode* head,
     ListNode* head,
     void* data); /* adds element with specified data to the end of the list and returns new head node. */
     void* data); /* adds element with specified data to the end of the list and returns new head node. */
-ListNode* list_find(
-    ListNode* head,
-    const void* data); /* returns pointer of element with specified data in list. */
-ListNode* list_element_at(
-    ListNode* head,
-    uint16_t index); /* returns pointer of element with specified index in list. */
-ListNode* list_remove(
-    ListNode* head,
-    ListNode* ep); /* removes element from the list and returns new head node. */
-void list_free(ListNode* head); /* deletes all elements of the list. */
+
+/**
+ * @brief Searches list node with the given assigned \p data in the list
+ * @param head head list node
+ * @param data data to be searched
+ * @return List node containing \p data if there is such a node in the list; \c NULL otherwise
+ */
+ListNode* list_find(ListNode* head, const void* data);
+
+/**
+ * @brief Searches list node with the given \p index in the list
+ * @param head head list node
+ * @param index desired list node index
+ * @return List node with the given \p index in the list if there is such a list node; \c NULL otherwise
+ */
+ListNode* list_element_at(ListNode* head, uint16_t index);
+
+/**
+ * @brief Removes list node from the list
+ * @param head head list node
+ * @param ep list node to be removed
+ * @return Head list node
+ */
+ListNode* list_remove(ListNode* head, ListNode* ep);
+
+/**
+ * @brief Removes list node with the given \p index in the list from the list
+ * @param head head list node
+ * @param index index of the node to be removed
+ * @param[out] removed_node_data data which was assigned to the removed list node
+ * @return Head list node
+ */
+ListNode* list_remove_at(ListNode* head, uint16_t index, void** removed_node_data);
+
+/**
+ * @brief Inserts new list node at the given index
+ * @param head head list node
+ * @param index index in the list where the new list node should be inserted
+ * @param data data to be assgned to the new list node
+ * @return Head list node
+ */
+ListNode* list_insert_at(ListNode* head, uint16_t index, void* data);
+
+/**
+ * @brief Disposes all the list nodes in the list
+ * @param head head list node
+ */
+void list_free(ListNode* head);
 
 
 #define TOTP_LIST_INIT_OR_ADD(head, item, assert) \
 #define TOTP_LIST_INIT_OR_ADD(head, item, assert) \
     do {                                          \
     do {                                          \

+ 40 - 1
services/roll_value/roll_value.h

@@ -2,7 +2,17 @@
 
 
 #include <stdint.h>
 #include <stdint.h>
 
 
-typedef enum { RollOverflowBehaviorStop, RollOverflowBehaviorRoll } TotpRollValueOverflowBehavior;
+typedef enum {
+    /**
+     * @brief Do not change value if it reached constraint
+     */
+    RollOverflowBehaviorStop,
+
+    /**
+     * @brief Set value to opposite constraint value if it reached constraint
+     */
+    RollOverflowBehaviorRoll
+} TotpRollValueOverflowBehavior;
 
 
 #define TOTP_ROLL_VALUE_FN_HEADER(type, step_type) \
 #define TOTP_ROLL_VALUE_FN_HEADER(type, step_type) \
     void totp_roll_value_##type(                   \
     void totp_roll_value_##type(                   \
@@ -12,6 +22,35 @@ typedef enum { RollOverflowBehaviorStop, RollOverflowBehaviorRoll } TotpRollValu
         type max,                                  \
         type max,                                  \
         TotpRollValueOverflowBehavior overflow_behavior)
         TotpRollValueOverflowBehavior overflow_behavior)
 
 
+/**
+ * @brief Rolls \c int8_t \p value using \p min and \p max as an value constraints with \p step step.
+ *        When value reaches constraint value \p overflow_behavior defines what to do next.
+ * @param[in,out] value value to roll
+ * @param step step to be used to change value
+ * @param min minimal possible value
+ * @param max maximum possible value
+ * @param overflow_behavior defines what to do when value reaches constraint value
+ */
 TOTP_ROLL_VALUE_FN_HEADER(int8_t, int8_t);
 TOTP_ROLL_VALUE_FN_HEADER(int8_t, int8_t);
+
+/**
+ * @brief Rolls \c uint8_t \p value using \p min and \p max as an value constraints with \p step step.
+ *        When value reaches constraint value \p overflow_behavior defines what to do next.
+ * @param[in,out] value value to roll
+ * @param step step to be used to change value
+ * @param min minimal possible value
+ * @param max maximum possible value
+ * @param overflow_behavior defines what to do when value reaches constraint value
+ */
 TOTP_ROLL_VALUE_FN_HEADER(uint8_t, int8_t);
 TOTP_ROLL_VALUE_FN_HEADER(uint8_t, int8_t);
+
+/**
+ * @brief Rolls \c uint16_t \p value using \p min and \p max as an value constraints with \p step step.
+ *        When value reaches constraint value \p overflow_behavior defines what to do next.
+ * @param[in,out] value value to roll
+ * @param step step to be used to change value
+ * @param min minimal possible value
+ * @param max maximum possible value
+ * @param overflow_behavior defines what to do when value reaches constraint value
+ */
 TOTP_ROLL_VALUE_FN_HEADER(uint16_t, int16_t);
 TOTP_ROLL_VALUE_FN_HEADER(uint16_t, int16_t);

+ 12 - 0
services/timezone_utils/timezone_utils.h

@@ -2,5 +2,17 @@
 
 
 #include <inttypes.h>
 #include <inttypes.h>
 
 
+/**
+ * @brief Calculates timezone offset in seconds given timezone offset in hours.
+ * @param hours timezone offset in hours
+ * @return Timezone offset in seconds.
+ */
 int32_t timezone_offset_from_hours(float hours);
 int32_t timezone_offset_from_hours(float hours);
+
+/**
+ * @brief Applies timezone offset to a given time.
+ * @param time time to apply offset to.
+ * @param offset timezone offset in seconds.
+ * @return Time with timezone offset applied.
+ */
 uint64_t timezone_offset_apply(uint64_t time, int32_t offset);
 uint64_t timezone_offset_apply(uint64_t time, int32_t offset);

+ 23 - 40
services/totp/totp.c

@@ -11,48 +11,43 @@
 #include "../hmac/byteswap.h"
 #include "../hmac/byteswap.h"
 #include "../timezone_utils/timezone_utils.h"
 #include "../timezone_utils/timezone_utils.h"
 
 
-/*
-	Generates the timeblock for a time in seconds.
-	
-	Timeblocks are the amount of intervals in a given time. For example,
-	if 1,000,000 seconds has passed for 30 second intervals, you would get
-	33,333 timeblocks (intervals), where timeblock++ is effectively +30 seconds.
-	
-	for_time is a time in seconds to get the current timeblocks
-	
-	Returns
-			timeblock given for_time, using data->interval
-		error, 0
-*/
+#define HMAC_MAX_SIZE 64
+
+/**
+ * @brief Generates the timeblock for a time in seconds.
+ *        Timeblocks are the amount of intervals in a given time. For example,
+ *        if 1,000,000 seconds has passed for 30 second intervals, you would get
+ *        33,333 timeblocks (intervals), where timeblock++ is effectively +30 seconds.
+ * @param interval in seconds
+ * @param for_time a time in seconds to get the current timeblocks
+ * @return Timeblock given \p for_time using \p interval
+ */
 uint64_t totp_timecode(uint8_t interval, uint64_t for_time) {
 uint64_t totp_timecode(uint8_t interval, uint64_t for_time) {
     return for_time / interval;
     return for_time / interval;
 }
 }
 
 
-/*
-	Generates an OTP (One Time Password).
-	
-	input is a number used to generate the OTP
-	out_str is the null-terminated output string already allocated
-	
-	Returns
-			OTP code if otp code was successfully generated
-		0 otherwise
-*/
+/**
+ * @brief Generates an OTP (One Time Password)
+ * @param algo hashing algorithm to be used
+ * @param digits desired TOTP code length
+ * @param plain_secret plain token secret
+ * @param plain_secret_length plain token secret length
+ * @param input input data for OTP code generation
+ * @return OTP code if code was successfully generated; 0 otherwise
+ */
 uint32_t otp_generate(
 uint32_t otp_generate(
     TOTP_ALGO algo,
     TOTP_ALGO algo,
     uint8_t digits,
     uint8_t digits,
     const uint8_t* plain_secret,
     const uint8_t* plain_secret,
     size_t plain_secret_length,
     size_t plain_secret_length,
     uint64_t input) {
     uint64_t input) {
-    uint8_t* hmac = malloc(64);
-    if(hmac == NULL) return OTP_ERROR;
-    memset(hmac, 0, 64);
+    uint8_t hmac[HMAC_MAX_SIZE] = {0};
 
 
     uint64_t input_swapped = swap_uint64(input);
     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[0]);
     if(hmac_len == 0) {
     if(hmac_len == 0) {
-        free(hmac);
         return OTP_ERROR;
         return OTP_ERROR;
     }
     }
 
 
@@ -62,21 +57,9 @@ uint32_t otp_generate(
          (hmac[offset + 2] & 0xFF) << 8 | (hmac[offset + 3] & 0xFF));
          (hmac[offset + 2] & 0xFF) << 8 | (hmac[offset + 3] & 0xFF));
     i_code %= (uint64_t)pow(10, digits);
     i_code %= (uint64_t)pow(10, digits);
 
 
-    free(hmac);
     return i_code;
     return i_code;
 }
 }
 
 
-/*
-	Generates a OTP key using the totp algorithm.
-	
-	for_time is the time the generated key will be created for
-	offset is a timeblock adjustment for the generated key
-	out_str is the null-terminated output string already allocated
-	
-	Returns
-			TOTP code if otp code was successfully generated
-		0 otherwise
-*/
 uint32_t totp_at(
 uint32_t totp_at(
     TOTP_ALGO algo,
     TOTP_ALGO algo,
     uint8_t digits,
     uint8_t digits,

+ 29 - 25
services/totp/totp.h

@@ -5,16 +5,15 @@
 
 
 #define OTP_ERROR (0)
 #define OTP_ERROR (0)
 
 
-/*
-	Must compute HMAC using passed arguments,
-	  output as char array through output.
-	
-	key is secret key.
-	input is input number.
-	output is an output buffer of the resulting HMAC operation.
-	
-	Must return 0 if error, or the length in bytes of the HMAC operation.
-*/
+/**
+ * @brief Must compute HMAC using passed arguments, output as char array through output.
+ *        \p key is secret key buffer.
+ *        \p key_length is secret key buffer length.
+ *        \p input is input buffer.
+ *        \p input_length is input buffer length.
+ *	      \p output is an output buffer of the resulting HMAC operation.
+ *        Must return 0 if error, or the length in bytes of the HMAC operation.
+ */
 typedef int (*TOTP_ALGO)(
 typedef int (*TOTP_ALGO)(
     const uint8_t* key,
     const uint8_t* key,
     size_t key_length,
     size_t key_length,
@@ -22,27 +21,32 @@ typedef int (*TOTP_ALGO)(
     size_t input_length,
     size_t input_length,
     uint8_t* output);
     uint8_t* output);
 
 
-/*
-    Computes HMAC using SHA1
-*/
+/**
+ * @brief Computes HMAC using SHA1
+ */
 extern const TOTP_ALGO TOTP_ALGO_SHA1;
 extern const TOTP_ALGO TOTP_ALGO_SHA1;
 
 
-/*
-    Computes HMAC using SHA256
-*/
+/**
+ * @brief Computes HMAC using SHA256
+ */
 extern const TOTP_ALGO TOTP_ALGO_SHA256;
 extern const TOTP_ALGO TOTP_ALGO_SHA256;
 
 
-/*
-    Computes HMAC using SHA512
-*/
+/**
+ * @brief Computes HMAC using SHA512
+ */
 extern const TOTP_ALGO TOTP_ALGO_SHA512;
 extern const TOTP_ALGO TOTP_ALGO_SHA512;
 
 
-/*
-	Computes TOTP token
-    Returns:
-        TOTP token on success
-        0 otherwise
-*/
+/**
+ * @brief Generates a OTP key using the totp algorithm.
+ * @param algo hashing algorithm to be used
+ * @param digits desired TOTP code length
+ * @param plain_secret plain token secret
+ * @param plain_secret_length plain token secret length
+ * @param for_time the time the generated key will be created for
+ * @param timezone UTC timezone adjustment for the generated key
+ * @param interval token lifetime in seconds
+ * @return TOTP code if code was successfully generated; 0 otherwise
+ */
 uint32_t totp_at(
 uint32_t totp_at(
     TOTP_ALGO algo,
     TOTP_ALGO algo,
     uint8_t digits,
     uint8_t digits,

+ 28 - 0
services/ui/ui_controls.h

@@ -3,11 +3,29 @@
 #include <inttypes.h>
 #include <inttypes.h>
 #include <gui/gui.h>
 #include <gui/gui.h>
 
 
+/**
+ * @brief Renders TextBox control
+ * @param canvas canvas to render control at
+ * @param y vertical position of a control to be rendered at
+ * @param text text to be rendered inside control
+ * @param is_selected whether control should be rendered as focused or not
+ */
 void ui_control_text_box_render(
 void ui_control_text_box_render(
     Canvas* const canvas,
     Canvas* const canvas,
     int16_t y,
     int16_t y,
     const char* text,
     const char* text,
     bool is_selected);
     bool is_selected);
+
+/**
+ * @brief Renders Button control
+ * @param canvas canvas to render control at
+ * @param x horizontal position of a control to be rendered at
+ * @param y vertical position of a control to be rendered at
+ * @param width control width
+ * @param height control height
+ * @param text text to be rendered inside control
+ * @param is_selected whether control should be rendered as focused or not
+ */
 void ui_control_button_render(
 void ui_control_button_render(
     Canvas* const canvas,
     Canvas* const canvas,
     int16_t x,
     int16_t x,
@@ -16,6 +34,16 @@ void ui_control_button_render(
     uint8_t height,
     uint8_t height,
     const char* text,
     const char* text,
     bool is_selected);
     bool is_selected);
+
+/**
+ * @brief Renders Select control
+ * @param canvas canvas to render control at
+ * @param x horizontal position of a control to be rendered at
+ * @param y vertical position of a control to be rendered at
+ * @param width control width
+ * @param text text to be rendered inside control
+ * @param is_selected whether control should be rendered as focused or not
+ */
 void ui_control_select_render(
 void ui_control_select_render(
     Canvas* const canvas,
     Canvas* const canvas,
     int16_t x,
     int16_t x,

+ 60 - 0
types/plugin_state.h

@@ -8,22 +8,82 @@
 
 
 #define TOTP_IV_SIZE 16
 #define TOTP_IV_SIZE 16
 
 
+/**
+ * @brief Application state structure
+ */
 typedef struct {
 typedef struct {
+    /**
+     * @brief Application current scene
+     */
     Scene current_scene;
     Scene current_scene;
+
+    /**
+     * @brief Application current scene state
+     */
     void* current_scene_state;
     void* current_scene_state;
+
+    /**
+     * @brief Whether scene is changing now 
+     */
     bool changing_scene;
     bool changing_scene;
+
+    /**
+     * @brief Reference to the firmware notification subsystem
+     */
     NotificationApp* notification;
     NotificationApp* notification;
+
+    /**
+     * @brief Reference to the firmware dialogs subsystem 
+     */
     DialogsApp* dialogs;
     DialogsApp* dialogs;
+
+    /**
+     * @brief Reference to the firmware GUI subsystem
+     */
     Gui* gui;
     Gui* gui;
 
 
+    /**
+     * @brief Timezone UTC offset in hours 
+     */
     float timezone_offset;
     float timezone_offset;
+
+    /**
+     * @brief Token list head node 
+     */
     ListNode* tokens_list;
     ListNode* tokens_list;
+
+    /**
+     * @brief Whether token list is loaded or not 
+     */
     bool token_list_loaded;
     bool token_list_loaded;
+
+    /**
+     * @brief Tokens list length 
+     */
     uint16_t tokens_count;
     uint16_t tokens_count;
 
 
+    /**
+     * @brief Encrypted well-known string data
+     */
     uint8_t* crypto_verify_data;
     uint8_t* crypto_verify_data;
+
+    /**
+     * @brief Encrypted well-known string data length
+     */
     size_t crypto_verify_data_length;
     size_t crypto_verify_data_length;
+
+    /**
+     * @brief Whether PIN is set by user or not 
+     */
     bool pin_set;
     bool pin_set;
+
+    /**
+     * @brief Initialization vector (IV) to be used for encryption\decryption 
+     */
     uint8_t iv[TOTP_IV_SIZE];
     uint8_t iv[TOTP_IV_SIZE];
+
+    /**
+     * @brief Basic randomly-generated initialization vector (IV)
+     */
     uint8_t base_iv[TOTP_IV_SIZE];
     uint8_t base_iv[TOTP_IV_SIZE];
 } PluginState;
 } PluginState;

+ 79 - 2
types/token_info.h

@@ -2,25 +2,102 @@
 
 
 #include <inttypes.h>
 #include <inttypes.h>
 
 
-typedef enum { SHA1, SHA256, SHA512 } TokenHashAlgo;
+/**
+ * @brief Hashing algorithm to be used to generate token
+ */
+typedef enum {
+    /**
+     * @brief SHA1 hashing algorithm
+     */
+    SHA1,
 
 
-typedef enum { TOTP_6_DIGITS, TOTP_8_DIGITS } TokenDigitsCount;
+    /**
+     * @brief SHA256 hashing algorithm
+     */
+    SHA256,
+
+    /**
+     * @brief SHA512 hashing algorithm
+     */
+    SHA512
+} TokenHashAlgo;
+
+/**
+ * @brief Token digits count to be generated.
+ */
+typedef enum {
+    /**
+     * @brief 6 digits
+     */
+    TOTP_6_DIGITS,
+
+    /**
+     * @brief 8 digits
+     */
+    TOTP_8_DIGITS
+} TokenDigitsCount;
 
 
 #define TOTP_TOKEN_DIGITS_MAX_COUNT 8
 #define TOTP_TOKEN_DIGITS_MAX_COUNT 8
 
 
+/**
+ * @brief TOTP token information
+ */
 typedef struct {
 typedef struct {
+    /**
+     * @brief Encrypted token secret 
+     */
     uint8_t* token;
     uint8_t* token;
+
+    /**
+     * @brief Encrypted token secret length 
+     */
     size_t token_length;
     size_t token_length;
+
+    /**
+     * @brief User-friendly token name 
+     */
     char* name;
     char* name;
+
+    /**
+     * @brief Hashing algorithm
+     */
     TokenHashAlgo algo;
     TokenHashAlgo algo;
+
+    /**
+     * @brief Desired TOTP token length 
+     */
     TokenDigitsCount digits;
     TokenDigitsCount digits;
 } TokenInfo;
 } TokenInfo;
 
 
+/**
+ * @brief Allocates a new instance of \c TokenInfo
+ * @return 
+ */
 TokenInfo* token_info_alloc();
 TokenInfo* token_info_alloc();
+
+/**
+ * @brief Disposes all the resources allocated by the given \c TokenInfo instance
+ * @param token_info instance to be disposed
+ */
 void token_info_free(TokenInfo* token_info);
 void token_info_free(TokenInfo* token_info);
+
+/**
+ * @brief Encrypts & sets plain token secret to the given instance of \c TokenInfo
+ * @param token_info instance where secret should be updated
+ * @param base32_token_secret plain token secret in Base32 format
+ * @param token_secret_length plain token secret length
+ * @param iv initialization vecor (IV) to be used for encryption
+ * @return \c true if token successfully set; \c false otherwise
+ */
 bool token_info_set_secret(
 bool token_info_set_secret(
     TokenInfo* token_info,
     TokenInfo* token_info,
     const char* base32_token_secret,
     const char* base32_token_secret,
     size_t token_secret_length,
     size_t token_secret_length,
     const uint8_t* iv);
     const uint8_t* iv);
+
+/**
+ * @brief Gets token digits count as \c uint8_t type
+ * @param token_info instance which's desired digits count should be returned
+ * @return Token digits length as \c uint8_t type
+ */
 uint8_t token_info_get_digits_count(const TokenInfo* token_info);
 uint8_t token_info_get_digits_count(const TokenInfo* token_info);