Просмотр исходного кода

Refactoring & bugfixes (#142)

* Another round of refactoring

* * FlipC.org assets added

* Few bugfixes

* * Updated firmware references

* CLang format ran
Alexander Kopachov 2 лет назад
Родитель
Сommit
c11a7224c6

+ 16 - 12
cli/commands/add/add.c

@@ -20,7 +20,8 @@ enum TotpIteratorUpdateTokenResultsEx {
     TotpIteratorUpdateTokenResultInvalidArguments = 3
 };
 
-static TotpIteratorUpdateTokenResult add_token_handler(TokenInfo* token_info, const void* context) {
+static TotpIteratorUpdateTokenResult
+    add_token_handler(TokenInfo* token_info, const void* context) {
     const struct TotpAddContext* context_t = context;
 
     // Reading token name
@@ -32,7 +33,7 @@ static TotpIteratorUpdateTokenResult add_token_handler(TokenInfo* token_info, co
 
     // Read optional arguments
     bool mask_user_input = true;
-    PlainTokenSecretEncoding token_secret_encoding = PLAIN_TOKEN_ENCODING_BASE32;
+    PlainTokenSecretEncoding token_secret_encoding = PlainTokenSecretEncodingBase32;
     while(args_read_string_and_trim(context_t->args, temp_str)) {
         bool parsed = false;
         if(!totp_cli_try_read_algo(token_info, temp_str, context_t->args, &parsed) &&
@@ -71,7 +72,7 @@ static TotpIteratorUpdateTokenResult add_token_handler(TokenInfo* token_info, co
 
     furi_string_secure_free(temp_str);
 
-    if (!secret_set) {
+    if(!secret_set) {
         return TotpIteratorUpdateTokenResultInvalidSecret;
     }
 
@@ -148,24 +149,27 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl
         return;
     }
 
-    TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
 
     TOTP_CLI_LOCK_UI(plugin_state);
 
-    struct TotpAddContext add_context = { .args = args, .cli = cli, .iv = &plugin_state->iv[0] };
-    TotpIteratorUpdateTokenResult add_result = totp_token_info_iterator_add_new_token(iterator_context, &add_token_handler, &add_context);
+    struct TotpAddContext add_context = {.args = args, .cli = cli, .iv = &plugin_state->iv[0]};
+    TotpIteratorUpdateTokenResult add_result =
+        totp_token_info_iterator_add_new_token(iterator_context, &add_token_handler, &add_context);
 
     if(add_result == TotpIteratorUpdateTokenResultSuccess) {
         TOTP_CLI_PRINTF_SUCCESS(
-                "Token \"%s\" has been successfully added\r\n",
-                furi_string_get_cstr(totp_token_info_iterator_get_current_token(iterator_context)->name));
-    } else if (add_result == TotpIteratorUpdateTokenResultCancelled) {
+            "Token \"%s\" has been successfully added\r\n",
+            furi_string_get_cstr(
+                totp_token_info_iterator_get_current_token(iterator_context)->name));
+    } else if(add_result == TotpIteratorUpdateTokenResultCancelled) {
         TOTP_CLI_PRINTF_INFO("Cancelled by user\r\n");
-    } else if (add_result == TotpIteratorUpdateTokenResultInvalidArguments) {
+    } else if(add_result == TotpIteratorUpdateTokenResultInvalidArguments) {
         totp_cli_print_invalid_arguments();
-    } else if (add_result == TotpIteratorUpdateTokenResultInvalidSecret) {
+    } else if(add_result == TotpIteratorUpdateTokenResultInvalidSecret) {
         TOTP_CLI_PRINTF_ERROR("Token secret seems to be invalid and can not be parsed\r\n");
-    } else if (add_result == TotpIteratorUpdateTokenResultFileUpdateFailed) {
+    } else if(add_result == TotpIteratorUpdateTokenResultFileUpdateFailed) {
         totp_cli_print_error_updating_config_file();
     }
 

+ 5 - 4
cli/commands/delete/delete.c

@@ -36,12 +36,12 @@ void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args,
         return;
     }
 
-    TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
 
     int token_number;
     if(!args_read_int_and_trim(args, &token_number) || token_number <= 0 ||
-       (size_t)token_number >
-            totp_token_info_iterator_get_total_count(iterator_context)) {
+       (size_t)token_number > totp_token_info_iterator_get_total_count(iterator_context)) {
         totp_cli_print_invalid_arguments();
         return;
     }
@@ -62,7 +62,8 @@ void totp_cli_command_delete_handle(PluginState* plugin_state, FuriString* args,
 
     TOTP_CLI_LOCK_UI(plugin_state);
 
-    size_t original_token_index = totp_token_info_iterator_get_current_token_index(iterator_context);
+    size_t original_token_index =
+        totp_token_info_iterator_get_current_token_index(iterator_context);
     totp_token_info_iterator_go_to(iterator_context, token_number - 1);
     const TokenInfo* token_info = totp_token_info_iterator_get_current_token(iterator_context);
     const char* token_info_name = furi_string_get_cstr(token_info->name);

+ 8 - 6
cli/commands/details/details.c

@@ -18,21 +18,21 @@
     } while(false)
 
 static void print_automation_features(const TokenInfo* token_info) {
-    if(token_info->automation_features == TOKEN_AUTOMATION_FEATURE_NONE) {
+    if(token_info->automation_features == TokenAutomationFeatureNone) {
         TOTP_CLI_PRINTF("| %-20s | %-28.28s |\r\n", "Automation features", "None");
         return;
     }
 
     bool header_printed = false;
-    if(token_info->automation_features & TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END) {
+    if(token_info->automation_features & TokenAutomationFeatureEnterAtTheEnd) {
         TOTP_CLI_PRINTF_AUTOMATION_FEATURE("Type <Enter> key at the end", header_printed);
     }
 
-    if(token_info->automation_features & TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END) {
+    if(token_info->automation_features & TokenAutomationFeatureTabAtTheEnd) {
         TOTP_CLI_PRINTF_AUTOMATION_FEATURE("Type <Tab> key at the end", header_printed);
     }
 
-    if(token_info->automation_features & TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER) {
+    if(token_info->automation_features & TokenAutomationFeatureTypeSlower) {
         TOTP_CLI_PRINTF_AUTOMATION_FEATURE("Type slower", header_printed);
     }
 }
@@ -54,7 +54,8 @@ void totp_cli_command_details_handle(PluginState* plugin_state, FuriString* args
     }
 
     int token_number;
-    TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
     if(!args_read_int_and_trim(args, &token_number) || token_number <= 0 ||
        (size_t)token_number > totp_token_info_iterator_get_total_count(iterator_context)) {
         totp_cli_print_invalid_arguments();
@@ -63,7 +64,8 @@ void totp_cli_command_details_handle(PluginState* plugin_state, FuriString* args
 
     TOTP_CLI_LOCK_UI(plugin_state);
 
-    size_t original_token_index = totp_token_info_iterator_get_current_token_index(iterator_context);
+    size_t original_token_index =
+        totp_token_info_iterator_get_current_token_index(iterator_context);
     if(totp_token_info_iterator_go_to(iterator_context, token_number - 1)) {
         const TokenInfo* token_info = totp_token_info_iterator_get_current_token(iterator_context);
 

+ 2 - 1
cli/commands/list/list.c

@@ -21,7 +21,8 @@ void totp_cli_command_list_handle(PluginState* plugin_state, Cli* cli) {
         return;
     }
 
-    TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
     size_t total_count = totp_token_info_iterator_get_total_count(iterator_context);
     if(total_count <= 0) {
         TOTP_CLI_PRINTF("There are no tokens");

+ 6 - 3
cli/commands/move/move.c

@@ -33,7 +33,8 @@ void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, C
     }
 
     int token_number;
-    TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
     size_t total_count = totp_token_info_iterator_get_total_count(iterator_context);
     if(!args_read_int_and_trim(args, &token_number) || token_number < 1 ||
        (size_t)token_number > total_count) {
@@ -59,7 +60,8 @@ void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, C
     size_t token_index = token_number - 1;
     size_t new_token_index = new_token_number - 1;
 
-    size_t original_token_index = totp_token_info_iterator_get_current_token_index(iterator_context);
+    size_t original_token_index =
+        totp_token_info_iterator_get_current_token_index(iterator_context);
 
     totp_cli_print_processing();
 
@@ -68,7 +70,8 @@ void totp_cli_command_move_handle(PluginState* plugin_state, FuriString* args, C
         totp_cli_delete_last_line();
         TOTP_CLI_PRINTF_SUCCESS(
             "Token \"%s\" has been successfully updated\r\n",
-            furi_string_get_cstr(totp_token_info_iterator_get_current_token(iterator_context)->name));
+            furi_string_get_cstr(
+                totp_token_info_iterator_get_current_token(iterator_context)->name));
     } else {
         totp_cli_delete_last_line();
         totp_cli_print_error_updating_config_file();

+ 29 - 21
cli/commands/update/update.c

@@ -22,8 +22,11 @@ enum TotpIteratorUpdateTokenResultsEx {
     TotpIteratorUpdateTokenResultInvalidArguments = 3
 };
 
-static bool
-    totp_cli_try_read_name(TokenInfo* token_info, const FuriString* arg, FuriString* args, bool* parsed) {
+static bool totp_cli_try_read_name(
+    TokenInfo* token_info,
+    const FuriString* arg,
+    FuriString* args,
+    bool* parsed) {
     if(furi_string_cmpi_str(arg, TOTP_CLI_COMMAND_ARG_NAME_PREFIX) == 0) {
         if(!args_read_probably_quoted_string_and_trim(args, token_info->name) ||
            furi_string_empty(token_info->name)) {
@@ -48,14 +51,15 @@ static bool totp_cli_try_read_change_secret_flag(const FuriString* arg, bool* pa
     return false;
 }
 
-static TotpIteratorUpdateTokenResult update_token_handler(TokenInfo* token_info, const void* context) {
+static TotpIteratorUpdateTokenResult
+    update_token_handler(TokenInfo* token_info, const void* context) {
     const struct TotpUpdateContext* context_t = context;
 
     // Read optional arguments
     FuriString* temp_str = furi_string_alloc();
     bool mask_user_input = true;
     bool update_token_secret = false;
-    PlainTokenSecretEncoding token_secret_encoding = PLAIN_TOKEN_ENCODING_BASE32;
+    PlainTokenSecretEncoding token_secret_encoding = PlainTokenSecretEncodingBase32;
     while(args_read_string_and_trim(context_t->args, temp_str)) {
         bool parsed = false;
         if(!totp_cli_try_read_name(token_info, temp_str, context_t->args, &parsed) &&
@@ -82,17 +86,17 @@ static TotpIteratorUpdateTokenResult update_token_handler(TokenInfo* token_info,
         TOTP_CLI_PRINTF("Enter token secret and confirm with [ENTER]\r\n");
         bool token_secret_read = totp_cli_read_line(context_t->cli, temp_str, mask_user_input);
         totp_cli_delete_last_line();
-        if (!token_secret_read) {
+        if(!token_secret_read) {
             furi_string_secure_free(temp_str);
             return TotpIteratorUpdateTokenResultCancelled;
         }
 
-        if (!token_info_set_secret(
-            token_info,
-            furi_string_get_cstr(temp_str),
-            furi_string_size(temp_str),
-            token_secret_encoding,
-            context_t->iv)) {
+        if(!token_info_set_secret(
+               token_info,
+               furi_string_get_cstr(temp_str),
+               furi_string_size(temp_str),
+               token_secret_encoding,
+               context_t->iv)) {
             furi_string_secure_free(temp_str);
             return TotpIteratorUpdateTokenResultInvalidSecret;
         }
@@ -131,7 +135,8 @@ void totp_cli_command_update_handle(PluginState* plugin_state, FuriString* args,
         return;
     }
 
-    TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
 
     int token_number;
     if(!args_read_int_and_trim(args, &token_number) || token_number <= 0 ||
@@ -145,23 +150,26 @@ void totp_cli_command_update_handle(PluginState* plugin_state, FuriString* args,
     size_t previous_index = totp_token_info_iterator_get_current_token_index(iterator_context);
     totp_token_info_iterator_go_to(iterator_context, token_number - 1);
 
-    struct TotpUpdateContext update_context = { .args = args, .cli = cli, .iv = &plugin_state->iv[0] };
-    TotpIteratorUpdateTokenResult update_result = totp_token_info_iterator_update_current_token(iterator_context, &update_token_handler, &update_context);
-        
+    struct TotpUpdateContext update_context = {
+        .args = args, .cli = cli, .iv = &plugin_state->iv[0]};
+    TotpIteratorUpdateTokenResult update_result = totp_token_info_iterator_update_current_token(
+        iterator_context, &update_token_handler, &update_context);
+
     if(update_result == TotpIteratorUpdateTokenResultSuccess) {
         TOTP_CLI_PRINTF_SUCCESS(
             "Token \"%s\" has been successfully updated\r\n",
-            furi_string_get_cstr(totp_token_info_iterator_get_current_token(iterator_context)->name));
-    } else if (update_result == TotpIteratorUpdateTokenResultInvalidArguments) {
+            furi_string_get_cstr(
+                totp_token_info_iterator_get_current_token(iterator_context)->name));
+    } else if(update_result == TotpIteratorUpdateTokenResultInvalidArguments) {
         totp_cli_print_invalid_arguments();
-    } else if (update_result == TotpIteratorUpdateTokenResultCancelled) {
+    } else if(update_result == TotpIteratorUpdateTokenResultCancelled) {
         TOTP_CLI_PRINTF_INFO("Cancelled by user\r\n");
-    } else if (update_result == TotpIteratorUpdateTokenResultInvalidSecret) {
+    } else if(update_result == TotpIteratorUpdateTokenResultInvalidSecret) {
         TOTP_CLI_PRINTF_ERROR("Token secret seems to be invalid and can not be parsed\r\n");
-    } else if (update_result == TotpIteratorUpdateTokenResultFileUpdateFailed) {        
+    } else if(update_result == TotpIteratorUpdateTokenResultFileUpdateFailed) {
         totp_cli_print_error_updating_config_file();
     }
-    
+
     totp_token_info_iterator_go_to(iterator_context, previous_index);
     TOTP_CLI_UNLOCK_UI(plugin_state);
 }

+ 2 - 2
cli/common_command_arguments.c

@@ -121,10 +121,10 @@ bool totp_cli_try_read_plain_token_secret_encoding(
             totp_cli_printf_missed_argument_value(TOTP_CLI_COMMAND_ARG_SECRET_ENCODING_PREFIX);
         } else {
             if(furi_string_cmpi_str(arg, PLAIN_TOKEN_ENCODING_BASE32_NAME) == 0) {
-                *secret_encoding = PLAIN_TOKEN_ENCODING_BASE32;
+                *secret_encoding = PlainTokenSecretEncodingBase32;
                 *parsed = true;
             } else if(furi_string_cmpi_str(arg, PLAIN_TOKEN_ENCODING_BASE64_NAME) == 0) {
-                *secret_encoding = PLAIN_TOKEN_ENCODING_BASE64;
+                *secret_encoding = PlainTokenSecretEncodingBase64;
                 *parsed = true;
             } else {
                 TOTP_CLI_PRINTF_ERROR(

+ 1 - 0
lib/base64/base64.c

@@ -1,6 +1,7 @@
 /*
  * Base64 encoding/decoding (RFC1341)
  * Copyright (c) 2005, Jouni Malinen <j@w1.fi>
+ * Modified and optimized for Flipepr Zero device purposes by Alex Kopachov (@akopachov)
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as

+ 6 - 9
services/config/config.c

@@ -68,7 +68,7 @@ static void totp_close_config_file(FlipperFormat* file) {
  */
 static char* totp_config_file_backup_i(Storage* storage) {
     if(!storage_dir_exists(storage, CONFIG_FILE_BACKUP_DIR) &&
-        !storage_simply_mkdir(storage, CONFIG_FILE_BACKUP_DIR)) {
+       !storage_simply_mkdir(storage, CONFIG_FILE_BACKUP_DIR)) {
         return NULL;
     }
 
@@ -434,9 +434,7 @@ bool totp_config_file_load(PluginState* const plugin_state) {
         plugin_state->config_file_context->config_file = fff_data_file;
         plugin_state->config_file_context->token_info_iterator_context =
             totp_token_info_iterator_alloc(
-                storage,
-                plugin_state->config_file_context->config_file, 
-                plugin_state->iv);
+                storage, plugin_state->config_file_context->config_file, plugin_state->iv);
         result = true;
     } while(false);
 
@@ -493,8 +491,7 @@ bool totp_config_file_update_encryption(
     PluginState* plugin_state,
     const uint8_t* new_pin,
     uint8_t new_pin_length) {
-    FlipperFormat* config_file =
-        plugin_state->config_file_context->config_file;
+    FlipperFormat* config_file = plugin_state->config_file_context->config_file;
     Stream* stream = flipper_format_get_raw_stream(config_file);
     size_t original_offset = stream_tell(stream);
     if(!stream_rewind(stream)) {
@@ -513,12 +510,12 @@ bool totp_config_file_update_encryption(
 
     CryptoSeedIVResult seed_result =
         totp_crypto_seed_iv(plugin_state, new_pin_length > 0 ? new_pin : NULL, new_pin_length);
-    if(seed_result & CRYPTO_SEED_IV_RESULT_FLAG_SUCCESS &&
-       seed_result & CRYPTO_SEED_IV_RESULT_FLAG_NEW_CRYPTO_VERIFY_DATA) {
+    if(seed_result & CryptoSeedIVResultFlagSuccess &&
+       seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) {
         if(!totp_config_file_update_crypto_signatures(plugin_state)) {
             return false;
         }
-    } else if(seed_result == CRYPTO_SEED_IV_RESULT_FAILED) {
+    } else if(seed_result == CryptoSeedIVResultFailed) {
         return false;
     }
 

+ 3 - 3
services/config/migrations/common_migration.c

@@ -98,7 +98,7 @@ bool totp_config_migrate_to_latest(
                 const uint32_t default_algo = SHA1;
                 flipper_format_write_uint32(
                     fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, &default_algo, 1);
-                const uint32_t default_digits = TOTP_6_DIGITS;
+                const uint32_t default_digits = TotpSixDigitsCount;
                 flipper_format_write_uint32(
                     fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &default_digits, 1);
             }
@@ -120,7 +120,7 @@ bool totp_config_migrate_to_latest(
                 flipper_format_write_string(
                     fff_data_file, TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES, temp_str);
             } else {
-                const uint32_t default_automation_features = TOKEN_AUTOMATION_FEATURE_NONE;
+                const uint32_t default_automation_features = TokenAutomationFeatureNone;
                 flipper_format_write_uint32(
                     fff_data_file,
                     TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES,
@@ -132,7 +132,7 @@ bool totp_config_migrate_to_latest(
         Stream* stream = flipper_format_get_raw_stream(fff_data_file);
         size_t current_pos = stream_tell(stream);
         size_t total_size = stream_size(stream);
-        if (current_pos < total_size) {
+        if(current_pos < total_size) {
             stream_delete(stream, total_size - current_pos);
         }
 

+ 7 - 1
services/config/migrations/common_migration.h

@@ -2,6 +2,12 @@
 
 #include <flipper_format/flipper_format.h>
 
+/**
+ * @brief Migrates config file to the latest version
+ * @param fff_data_file original config file to be migrated
+ * @param fff_backup_data_file backup copy of original config file
+ * @return \c true if operation succeeded; \c false otherwise
+ */
 bool totp_config_migrate_to_latest(
     FlipperFormat* fff_data_file,
-    FlipperFormat* fff_backup_data_file);
+    FlipperFormat* fff_backup_data_file);

+ 67 - 26
services/config/token_info_iterator.c

@@ -90,7 +90,7 @@ static bool seek_to_token(size_t token_index, TokenInfoIteratorContext* context)
         context->last_seek_offset = stream_tell(stream);
         context->last_seek_index = token_index;
     } else {
-        if (!stream_seek(stream, context->last_seek_offset, StreamOffsetFromStart)) {
+        if(!stream_seek(stream, context->last_seek_offset, StreamOffsetFromStart)) {
             return false;
         }
     }
@@ -110,11 +110,34 @@ static bool stream_insert_stream(Stream* dst, Stream* src) {
     return true;
 }
 
-static bool totp_token_info_iterator_save_current_token_info_changes(TokenInfoIteratorContext* context) {
+static bool ensure_stream_ends_with_lf(Stream* stream) {
+    uint8_t last_char;
+    size_t original_pos = stream_tell(stream);
+    if(!stream_seek(stream, -1, StreamOffsetFromEnd) || stream_read(stream, &last_char, 1) < 1) {
+        return false;
+    }
+
+    if(last_char != '\n') {
+        const uint8_t lf = '\n';
+        if(!stream_write(stream, &lf, 1)) {
+            return false;
+        }
+    }
+
+    if(!stream_seek(stream, original_pos, StreamOffsetFromStart)) {
+        return false;
+    }
+
+    return true;
+}
+
+static bool
+    totp_token_info_iterator_save_current_token_info_changes(TokenInfoIteratorContext* context) {
     bool is_new_token = context->current_index >= context->total_count;
     Stream* stream = flipper_format_get_raw_stream(context->config_file);
     if(is_new_token) {
-        if(!flipper_format_seek_to_end(context->config_file)) {
+        if(!ensure_stream_ends_with_lf(stream) ||
+           !flipper_format_seek_to_end(context->config_file)) {
             return false;
         }
     } else {
@@ -137,7 +160,7 @@ static bool totp_token_info_iterator_save_current_token_info_changes(TokenInfoIt
     }
 
     FlipperFormat* temp_ff = flipper_format_file_alloc(context->storage);
-    if (!flipper_format_file_open_always(temp_ff, CONFIG_FILE_PART_FILE_PATH)) {
+    if(!flipper_format_file_open_always(temp_ff, CONFIG_FILE_PART_FILE_PATH)) {
         flipper_format_free(temp_ff);
         return false;
     }
@@ -218,7 +241,8 @@ static bool totp_token_info_iterator_save_current_token_info_changes(TokenInfoIt
     return result;
 }
 
-TokenInfoIteratorContext* totp_token_info_iterator_alloc(Storage* storage, FlipperFormat* config_file, uint8_t* iv) {
+TokenInfoIteratorContext*
+    totp_token_info_iterator_alloc(Storage* storage, FlipperFormat* config_file, uint8_t* iv) {
     Stream* stream = flipper_format_get_raw_stream(config_file);
     stream_rewind(stream);
     size_t tokens_count = 0;
@@ -255,8 +279,12 @@ bool totp_token_info_iterator_remove_current_token_info(TokenInfoIteratorContext
     Stream* stream = flipper_format_get_raw_stream(context->config_file);
     size_t begin_offset = stream_tell(stream);
     size_t end_offset;
+    if(!ensure_stream_ends_with_lf(stream)) {
+        return false;
+    }
+
     if(context->current_index >= context->total_count - 1) {
-        end_offset = stream_size(stream);
+        end_offset = stream_size(stream) - 1;
     } else if(seek_to_token(context->current_index + 1, context)) {
         end_offset = stream_tell(stream);
     } else {
@@ -281,24 +309,29 @@ bool totp_token_info_iterator_move_current_token_info(
     size_t new_index) {
     if(context->current_index == new_index) return true;
 
+    Stream* stream = flipper_format_get_raw_stream(context->config_file);
+
+    if(!ensure_stream_ends_with_lf(stream)) {
+        return false;
+    }
+
     if(!seek_to_token(context->current_index, context)) {
         return false;
     }
 
-    Stream* stream = flipper_format_get_raw_stream(context->config_file);
     size_t begin_offset = stream_tell(stream);
     size_t end_offset;
     if(context->current_index >= context->total_count - 1) {
-        end_offset = stream_size(stream);
+        end_offset = stream_size(stream) - 1;
     } else if(seek_to_token(context->current_index + 1, context)) {
         end_offset = stream_tell(stream);
     } else {
         return false;
     }
 
-    
     Stream* temp_stream = file_stream_alloc(context->storage);
-    if (!file_stream_open(temp_stream, CONFIG_FILE_PART_FILE_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)) {
+    if(!file_stream_open(
+           temp_stream, CONFIG_FILE_PART_FILE_PATH, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS)) {
         stream_free(temp_stream);
         return false;
     }
@@ -330,7 +363,7 @@ bool totp_token_info_iterator_move_current_token_info(
         context->last_seek_offset = 0;
         context->last_seek_index = 0;
         if(new_index >= context->total_count - 1) {
-            if(!stream_seek(stream, stream_size(stream), StreamOffsetFromStart)) {
+            if(!stream_seek(stream, stream_size(stream) - 1, StreamOffsetFromStart)) {
                 break;
             }
         } else if(!seek_to_token(new_index, context)) {
@@ -349,12 +382,15 @@ bool totp_token_info_iterator_move_current_token_info(
     return result;
 }
 
-TotpIteratorUpdateTokenResult totp_token_info_iterator_update_current_token(TokenInfoIteratorContext* context, TOTP_ITERATOR_UPDATE_TOKEN_ACTION update, const void* update_context) {
+TotpIteratorUpdateTokenResult totp_token_info_iterator_update_current_token(
+    TokenInfoIteratorContext* context,
+    TOTP_ITERATOR_UPDATE_TOKEN_ACTION update,
+    const void* update_context) {
     TotpIteratorUpdateTokenResult result = update(context->current_token, update_context);
-    if (result == TotpIteratorUpdateTokenResultSuccess) {
-        if (!totp_token_info_iterator_save_current_token_info_changes(context)) {
+    if(result == TotpIteratorUpdateTokenResultSuccess) {
+        if(!totp_token_info_iterator_save_current_token_info_changes(context)) {
             result = TotpIteratorUpdateTokenResultFileUpdateFailed;
-        } 
+        }
 
         return result;
     }
@@ -363,17 +399,20 @@ TotpIteratorUpdateTokenResult totp_token_info_iterator_update_current_token(Toke
     return result;
 }
 
-TotpIteratorUpdateTokenResult totp_token_info_iterator_add_new_token(TokenInfoIteratorContext* context, TOTP_ITERATOR_UPDATE_TOKEN_ACTION update, const void* update_context) {
+TotpIteratorUpdateTokenResult totp_token_info_iterator_add_new_token(
+    TokenInfoIteratorContext* context,
+    TOTP_ITERATOR_UPDATE_TOKEN_ACTION update,
+    const void* update_context) {
     size_t previous_index = context->current_index;
     context->current_index = context->total_count;
     token_info_set_defaults(context->current_token);
     TotpIteratorUpdateTokenResult result = update(context->current_token, update_context);
-    if (result == TotpIteratorUpdateTokenResultSuccess &&
-        !totp_token_info_iterator_save_current_token_info_changes(context)) {
+    if(result == TotpIteratorUpdateTokenResultSuccess &&
+       !totp_token_info_iterator_save_current_token_info_changes(context)) {
         result = TotpIteratorUpdateTokenResultFileUpdateFailed;
     }
 
-    if (result != TotpIteratorUpdateTokenResultSuccess) {
+    if(result != TotpIteratorUpdateTokenResultSuccess) {
         totp_token_info_iterator_go_to(context, previous_index);
     }
 
@@ -417,7 +456,7 @@ bool totp_token_info_iterator_go_to(TokenInfoIteratorContext* context, size_t to
                    tokenInfo,
                    furi_string_get_cstr(temp_str),
                    furi_string_size(temp_str),
-                   PLAIN_TOKEN_ENCODING_BASE32,
+                   PlainTokenSecretEncodingBase32,
                    context->iv)) {
                 FURI_LOG_W(
                     LOGGING_TAG,
@@ -469,7 +508,7 @@ bool totp_token_info_iterator_go_to(TokenInfoIteratorContext* context, size_t to
     if(!flipper_format_read_uint32(
            context->config_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1) ||
        !token_info_set_digits_from_int(tokenInfo, temp_data32)) {
-        tokenInfo->digits = TOTP_6_DIGITS;
+        tokenInfo->digits = TotpSixDigitsCount;
     }
 
     if(!flipper_format_read_uint32(
@@ -482,20 +521,20 @@ bool totp_token_info_iterator_go_to(TokenInfoIteratorContext* context, size_t to
            context->config_file, TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES, &temp_data32, 1)) {
         tokenInfo->automation_features = temp_data32;
     } else {
-        tokenInfo->automation_features = TOKEN_AUTOMATION_FEATURE_NONE;
+        tokenInfo->automation_features = TokenAutomationFeatureNone;
     }
 
     stream_seek(stream, original_offset, StreamOffsetFromStart);
 
-    if(token_update_needed &&
-        !totp_token_info_iterator_save_current_token_info_changes(context)) {
+    if(token_update_needed && !totp_token_info_iterator_save_current_token_info_changes(context)) {
         return false;
     }
 
     return true;
 }
 
-const TokenInfo* totp_token_info_iterator_get_current_token(const TokenInfoIteratorContext* context) {
+const TokenInfo*
+    totp_token_info_iterator_get_current_token(const TokenInfoIteratorContext* context) {
     return context->current_token;
 }
 
@@ -507,6 +546,8 @@ size_t totp_token_info_iterator_get_total_count(const TokenInfoIteratorContext*
     return context->total_count;
 }
 
-void totp_token_info_iterator_attach_to_config_file(TokenInfoIteratorContext* context, FlipperFormat* config_file) {
+void totp_token_info_iterator_attach_to_config_file(
+    TokenInfoIteratorContext* context,
+    FlipperFormat* config_file) {
     context->config_file = config_file;
 }

+ 94 - 15
services/config/token_info_iterator.h

@@ -6,37 +6,116 @@
 
 typedef int TotpIteratorUpdateTokenResult;
 
+typedef TotpIteratorUpdateTokenResult (
+    *TOTP_ITERATOR_UPDATE_TOKEN_ACTION)(TokenInfo* const token_info, const void* context);
+
+typedef struct TokenInfoIteratorContext TokenInfoIteratorContext;
+
 enum TotpIteratorUpdateTokenResults {
+
+    /**
+     * @brief Token successfully updated
+     */
     TotpIteratorUpdateTokenResultSuccess = 0,
+
+    /**
+     * @brief An error ocurred during updating config file
+     */
     TotpIteratorUpdateTokenResultFileUpdateFailed = -1
 };
 
-typedef TotpIteratorUpdateTokenResult (*TOTP_ITERATOR_UPDATE_TOKEN_ACTION)(
-    TokenInfo* const token_info,
-    const void* context);
-
-typedef struct TokenInfoIteratorContext TokenInfoIteratorContext;
-
-TokenInfoIteratorContext* totp_token_info_iterator_alloc(Storage* storage, FlipperFormat* config_file, uint8_t* iv);
-
+/**
+ * @brief Initializes a new token info iterator
+ * @param storage storage reference
+ * @param config_file config file to use
+ * @param iv initialization vector (IV) to be used for encryption\decryption
+ * @return Token info iterator context
+ */
+TokenInfoIteratorContext*
+    totp_token_info_iterator_alloc(Storage* storage, FlipperFormat* config_file, uint8_t* iv);
+
+/**
+ * @brief Navigates iterator to the token with given index
+ * @param context token info iterator context
+ * @param token_index token index to navigate to
+ * @return \c true if navigation succeeded; \c false otherwise
+ */
 bool totp_token_info_iterator_go_to(TokenInfoIteratorContext* context, size_t token_index);
 
+/**
+ * @brief Moves current token to a given new index
+ * @param context token info iterator context
+ * @param new_index new token index to move current token to
+ * @return \c true if operation succeeded; \c false otherwise
+ */
 bool totp_token_info_iterator_move_current_token_info(
     TokenInfoIteratorContext* context,
     size_t new_index);
 
-TotpIteratorUpdateTokenResult totp_token_info_iterator_update_current_token(TokenInfoIteratorContext* context, TOTP_ITERATOR_UPDATE_TOKEN_ACTION update, const void* update_context);
-
-TotpIteratorUpdateTokenResult totp_token_info_iterator_add_new_token(TokenInfoIteratorContext* context, TOTP_ITERATOR_UPDATE_TOKEN_ACTION update, const void* update_context);
-
+/**
+ * @brief Updates current token info using given update action
+ * @param context token info iterator context
+ * @param update action which is responsible to make all the necessary updates to token info
+ * @param update_context update action context
+ * @return \c true if operation succeeded; \c false otherwise
+ */
+TotpIteratorUpdateTokenResult totp_token_info_iterator_update_current_token(
+    TokenInfoIteratorContext* context,
+    TOTP_ITERATOR_UPDATE_TOKEN_ACTION update,
+    const void* update_context);
+
+/**
+ * @brief Adds new token info to the end of the list using given update action
+ * @param context token info iterator context
+ * @param update action which is responsible to make all the necessary updates to token info
+ * @param update_context update action context
+ * @return \c true if operation succeeded; \c false otherwise
+ */
+TotpIteratorUpdateTokenResult totp_token_info_iterator_add_new_token(
+    TokenInfoIteratorContext* context,
+    TOTP_ITERATOR_UPDATE_TOKEN_ACTION update,
+    const void* update_context);
+
+/**
+ * @brief Remvoves current token info
+ * @param context token info iterator context
+ * @return \c true if operation succeeded; \c false otherwise
+ */
 bool totp_token_info_iterator_remove_current_token_info(TokenInfoIteratorContext* context);
 
+/**
+ * @brief Disposes token info iterator and releases all the resources
+ * @param context token info iterator context
+ */
 void totp_token_info_iterator_free(TokenInfoIteratorContext* context);
 
-const TokenInfo* totp_token_info_iterator_get_current_token(const TokenInfoIteratorContext* context);
-
+/**
+ * @brief Gets current token info
+ * @param context token info iterator context
+ * @return current token info
+ */
+const TokenInfo*
+    totp_token_info_iterator_get_current_token(const TokenInfoIteratorContext* context);
+
+/**
+ * @brief Gets current token info index
+ * @param context token info iterator context
+ * @return current token info index
+ */
 size_t totp_token_info_iterator_get_current_token_index(const TokenInfoIteratorContext* context);
 
+/**
+ * @brief Gets total amount of token infos found
+ * @param context token info iterator context
+ * @return amount of token infos found
+ */
 size_t totp_token_info_iterator_get_total_count(const TokenInfoIteratorContext* context);
 
-void totp_token_info_iterator_attach_to_config_file(TokenInfoIteratorContext* context, FlipperFormat* config_file);
+/**
+ * @brief Attaches token info iterator to another config file
+ * @param context token info iterator context
+ * @param config_file config file reference to attach token info iterator to
+ */
+void totp_token_info_iterator_attach_to_config_file(
+    TokenInfoIteratorContext* context,
+    FlipperFormat* config_file);

+ 2 - 2
services/crypto/crypto.c

@@ -96,7 +96,7 @@ CryptoSeedIVResult
         }
     }
 
-    result = CRYPTO_SEED_IV_RESULT_FLAG_SUCCESS;
+    result = CryptoSeedIVResultFlagSuccess;
     if(plugin_state->crypto_verify_data == NULL) {
         FURI_LOG_I(LOGGING_TAG, "Generating crypto verify data");
         plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH);
@@ -111,7 +111,7 @@ CryptoSeedIVResult
 
         plugin_state->pin_set = pin != NULL && pin_length > 0;
 
-        result |= CRYPTO_SEED_IV_RESULT_FLAG_NEW_CRYPTO_VERIFY_DATA;
+        result |= CryptoSeedIVResultFlagNewCryptoVerifyData;
     }
 
     return result;

+ 3 - 3
services/crypto/crypto.h

@@ -9,17 +9,17 @@ enum CryptoSeedIVResults {
     /**
      * @brief IV seeding operation failed
      */
-    CRYPTO_SEED_IV_RESULT_FAILED = 0b00,
+    CryptoSeedIVResultFailed = 0b00,
 
     /**
      * @brief IV seeding operation succeeded
      */
-    CRYPTO_SEED_IV_RESULT_FLAG_SUCCESS = 0b01,
+    CryptoSeedIVResultFlagSuccess = 0b01,
 
     /**
      * @brief As a part of IV seeding operation new crypto verify data has been generated
      */
-    CRYPTO_SEED_IV_RESULT_FLAG_NEW_CRYPTO_VERIFY_DATA = 0b10
+    CryptoSeedIVResultFlagNewCryptoVerifyData = 0b10
 };
 
 /**

+ 6 - 6
totp_app.c

@@ -54,13 +54,13 @@ static bool totp_activate_initial_scene(PluginState* const plugin_state) {
             totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication);
         } else {
             CryptoSeedIVResult seed_result = totp_crypto_seed_iv(plugin_state, NULL, 0);
-            if(seed_result & CRYPTO_SEED_IV_RESULT_FLAG_SUCCESS &&
-               seed_result & CRYPTO_SEED_IV_RESULT_FLAG_NEW_CRYPTO_VERIFY_DATA) {
+            if(seed_result & CryptoSeedIVResultFlagSuccess &&
+               seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) {
                 if(!totp_config_file_update_crypto_signatures(plugin_state)) {
                     totp_dialogs_config_loading_error(plugin_state);
                     return false;
                 }
-            } else if(seed_result == CRYPTO_SEED_IV_RESULT_FAILED) {
+            } else if(seed_result == CryptoSeedIVResultFailed) {
                 totp_dialogs_config_loading_error(plugin_state);
                 return false;
             }
@@ -71,13 +71,13 @@ static bool totp_activate_initial_scene(PluginState* const plugin_state) {
         totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication);
     } else {
         CryptoSeedIVResult seed_result = totp_crypto_seed_iv(plugin_state, NULL, 0);
-        if(seed_result & CRYPTO_SEED_IV_RESULT_FLAG_SUCCESS &&
-           seed_result & CRYPTO_SEED_IV_RESULT_FLAG_NEW_CRYPTO_VERIFY_DATA) {
+        if(seed_result & CryptoSeedIVResultFlagSuccess &&
+           seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) {
             if(!totp_config_file_update_crypto_signatures(plugin_state)) {
                 totp_dialogs_config_loading_error(plugin_state);
                 return false;
             }
-        } else if(seed_result == CRYPTO_SEED_IV_RESULT_FAILED) {
+        } else if(seed_result == CryptoSeedIVResultFailed) {
             totp_dialogs_config_loading_error(plugin_state);
             return false;
         }

+ 11 - 11
types/token_info.c

@@ -30,13 +30,13 @@ bool token_info_set_secret(
     uint8_t* plain_secret;
     size_t plain_secret_length;
     size_t plain_secret_size;
-    if(plain_token_secret_encoding == PLAIN_TOKEN_ENCODING_BASE32) {
+    if(plain_token_secret_encoding == PlainTokenSecretEncodingBase32) {
         plain_secret_size = token_secret_length;
         plain_secret = malloc(plain_secret_size);
         furi_check(plain_secret != NULL);
         plain_secret_length =
             base32_decode((const uint8_t*)plain_token_secret, plain_secret, plain_secret_size);
-    } else if(plain_token_secret_encoding == PLAIN_TOKEN_ENCODING_BASE64) {
+    } else if(plain_token_secret_encoding == PlainTokenSecretEncodingBase64) {
         plain_secret_length = 0;
         plain_secret = base64_decode(
             (const uint8_t*)plain_token_secret,
@@ -69,13 +69,13 @@ bool token_info_set_secret(
 bool token_info_set_digits_from_int(TokenInfo* token_info, uint8_t digits) {
     switch(digits) {
     case 5:
-        token_info->digits = TOTP_5_DIGITS;
+        token_info->digits = TotpFiveDigitsCount;
         return true;
     case 6:
-        token_info->digits = TOTP_6_DIGITS;
+        token_info->digits = TotpSixDigitsCount;
         return true;
     case 8:
-        token_info->digits = TOTP_8_DIGITS;
+        token_info->digits = TotpEightDigitsCount;
         return true;
     default:
         break;
@@ -136,22 +136,22 @@ char* token_info_get_algo_as_cstr(const TokenInfo* token_info) {
 
 bool token_info_set_automation_feature_from_str(TokenInfo* token_info, const FuriString* str) {
     if(furi_string_cmpi_str(str, TOTP_TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END_NAME) == 0) {
-        token_info->automation_features |= TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END;
+        token_info->automation_features |= TokenAutomationFeatureEnterAtTheEnd;
         return true;
     }
 
     if(furi_string_cmpi_str(str, TOTP_TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END_NAME) == 0) {
-        token_info->automation_features |= TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END;
+        token_info->automation_features |= TokenAutomationFeatureTabAtTheEnd;
         return true;
     }
 
     if(furi_string_cmpi_str(str, TOTP_TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER_NAME) == 0) {
-        token_info->automation_features |= TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER;
+        token_info->automation_features |= TokenAutomationFeatureTypeSlower;
         return true;
     }
 
     if(furi_string_cmpi_str(str, TOTP_TOKEN_AUTOMATION_FEATURE_NONE_NAME) == 0) {
-        token_info->automation_features = TOKEN_AUTOMATION_FEATURE_NONE;
+        token_info->automation_features = TokenAutomationFeatureNone;
         return true;
     }
 
@@ -175,8 +175,8 @@ TokenInfo* token_info_clone(const TokenInfo* src) {
 void token_info_set_defaults(TokenInfo* token_info) {
     furi_check(token_info != NULL);
     token_info->algo = SHA1;
-    token_info->digits = TOTP_6_DIGITS;
+    token_info->digits = TotpSixDigitsCount;
     token_info->duration = TOTP_TOKEN_DURATION_DEFAULT;
-    token_info->automation_features = TOKEN_AUTOMATION_FEATURE_NONE;
+    token_info->automation_features = TokenAutomationFeatureNone;
     furi_string_reset(token_info->name);
 }

+ 14 - 14
types/token_info.h

@@ -34,22 +34,22 @@ enum TokenHashAlgos {
     /**
      * @brief SHA1 hashing algorithm
      */
-    SHA1,
+    SHA1 = 0,
 
     /**
      * @brief SHA256 hashing algorithm
      */
-    SHA256,
+    SHA256 = 1,
 
     /**
      * @brief SHA512 hashing algorithm
      */
-    SHA512,
+    SHA512 = 2,
 
     /**
      * @brief Algorithm used by Steam (Valve)
      */
-    STEAM
+    STEAM = 3
 };
 
 /**
@@ -57,19 +57,19 @@ enum TokenHashAlgos {
  */
 enum TokenDigitsCounts {
     /**
-     * @brief 6 digits
+     * @brief 5 digits
      */
-    TOTP_5_DIGITS = 5,
+    TotpFiveDigitsCount = 5,
 
     /**
      * @brief 6 digits
      */
-    TOTP_6_DIGITS = 6,
+    TotpSixDigitsCount = 6,
 
     /**
      * @brief 8 digits
      */
-    TOTP_8_DIGITS = 8
+    TotpEightDigitsCount = 8
 };
 
 /**
@@ -79,22 +79,22 @@ enum TokenAutomationFeatures {
     /**
      * @brief No features enabled
      */
-    TOKEN_AUTOMATION_FEATURE_NONE = 0b000,
+    TokenAutomationFeatureNone = 0b000,
 
     /**
      * @brief Press "Enter" key at the end as a part of token input automation
      */
-    TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END = 0b001,
+    TokenAutomationFeatureEnterAtTheEnd = 0b001,
 
     /**
      * @brief Press "Tab" key at the end as a part of token input automation
      */
-    TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END = 0b010,
+    TokenAutomationFeatureTabAtTheEnd = 0b010,
 
     /**
      * @brief Press keys slower and wait longer between keystrokes
      */
-    TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER = 0b100
+    TokenAutomationFeatureTypeSlower = 0b100
 };
 
 /**
@@ -105,12 +105,12 @@ enum PlainTokenSecretEncodings {
     /**
      * @brief Base32 encoding
      */
-    PLAIN_TOKEN_ENCODING_BASE32 = 0,
+    PlainTokenSecretEncodingBase32 = 0,
 
     /**
      * @brief Base64 encoding
      */
-    PLAIN_TOKEN_ENCODING_BASE64 = 1
+    PlainTokenSecretEncodingBase64 = 1
 };
 
 /**

+ 23 - 19
ui/scenes/add_new_token/totp_scene_add_new_token.c

@@ -12,7 +12,10 @@
 
 char* TOKEN_ALGO_LIST[] = {"SHA1", "SHA256", "SHA512", "Steam"};
 char* TOKEN_DIGITS_TEXT_LIST[] = {"5 digits", "6 digits", "8 digits"};
-TokenDigitsCount TOKEN_DIGITS_VALUE_LIST[] = {TOTP_5_DIGITS, TOTP_6_DIGITS, TOTP_8_DIGITS};
+TokenDigitsCount TOKEN_DIGITS_VALUE_LIST[] = {
+    TotpFiveDigitsCount,
+    TotpSixDigitsCount,
+    TotpEightDigitsCount};
 
 typedef enum {
     TokenNameTextBox,
@@ -46,9 +49,7 @@ struct TotpAddContext {
     uint8_t* iv;
 };
 
-enum TotpIteratorUpdateTokenResultsEx {
-    TotpIteratorUpdateTokenResultInvalidSecret = 1
-};
+enum TotpIteratorUpdateTokenResultsEx { TotpIteratorUpdateTokenResultInvalidSecret = 1 };
 
 static void on_token_name_user_comitted(InputTextSceneCallbackResult* result) {
     SceneState* scene_state = result->callback_data;
@@ -74,16 +75,19 @@ static void update_duration_text(SceneState* scene_state) {
 
 static TotpIteratorUpdateTokenResult add_token_handler(TokenInfo* tokenInfo, const void* context) {
     const struct TotpAddContext* context_t = context;
-    if (!token_info_set_secret(
-        tokenInfo,
-        context_t->scene_state->token_secret,
-        context_t->scene_state->token_secret_length,
-        PLAIN_TOKEN_ENCODING_BASE32,
-        context_t->iv)) {
+    if(!token_info_set_secret(
+           tokenInfo,
+           context_t->scene_state->token_secret,
+           context_t->scene_state->token_secret_length,
+           PlainTokenSecretEncodingBase32,
+           context_t->iv)) {
         return TotpIteratorUpdateTokenResultInvalidSecret;
     }
 
-    furi_string_set_strn(tokenInfo->name, context_t->scene_state->token_name, context_t->scene_state->token_name_length + 1);
+    furi_string_set_strn(
+        tokenInfo->name,
+        context_t->scene_state->token_name,
+        context_t->scene_state->token_name_length + 1);
     tokenInfo->algo = context_t->scene_state->algo;
     tokenInfo->digits = TOKEN_DIGITS_VALUE_LIST[context_t->scene_state->digits_count_index];
     tokenInfo->duration = context_t->scene_state->duration;
@@ -277,16 +281,16 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
         case TokenDurationSelect:
             break;
         case ConfirmButton: {
-            struct TotpAddContext add_context = { .iv = plugin_state->iv, .scene_state = scene_state };
-            TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+            struct TotpAddContext add_context = {
+                .iv = plugin_state->iv, .scene_state = scene_state};
+            TokenInfoIteratorContext* iterator_context =
+                totp_config_get_token_iterator_context(plugin_state);
             TotpIteratorUpdateTokenResult add_result = totp_token_info_iterator_add_new_token(
-                iterator_context,
-                &add_token_handler,
-                &add_context);
+                iterator_context, &add_token_handler, &add_context);
 
-            if (add_result == TotpIteratorUpdateTokenResultSuccess) {
+            if(add_result == TotpIteratorUpdateTokenResultSuccess) {
                 totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken);
-            } else if (add_result == TotpIteratorUpdateTokenResultInvalidSecret) {
+            } else if(add_result == TotpIteratorUpdateTokenResultInvalidSecret) {
                 DialogMessage* message = dialog_message_alloc();
                 dialog_message_set_buttons(message, "Back", NULL, NULL);
                 dialog_message_set_text(
@@ -300,7 +304,7 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
                 dialog_message_free(message);
                 scene_state->selected_control = TokenSecretTextBox;
                 update_screen_y_offset(scene_state);
-            } else if (add_result == TotpIteratorUpdateTokenResultFileUpdateFailed) {
+            } else if(add_result == TotpIteratorUpdateTokenResultFileUpdateFailed) {
                 totp_dialogs_config_updating_error(plugin_state);
             }
 

+ 2 - 2
ui/scenes/authenticate/totp_scene_authenticate.c

@@ -118,8 +118,8 @@ bool totp_scene_authenticate_handle_event(
         CryptoSeedIVResult seed_result = totp_crypto_seed_iv(
             plugin_state, &scene_state->code_input[0], scene_state->code_length);
 
-        if(seed_result & CRYPTO_SEED_IV_RESULT_FLAG_SUCCESS &&
-           seed_result & CRYPTO_SEED_IV_RESULT_FLAG_NEW_CRYPTO_VERIFY_DATA) {
+        if(seed_result & CryptoSeedIVResultFlagSuccess &&
+           seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) {
             totp_config_file_update_crypto_signatures(plugin_state);
         }
 

+ 31 - 16
ui/scenes/generate_token/totp_scene_generate_token.c

@@ -128,7 +128,8 @@ static const NotificationSequence*
 
 static void update_totp_params(PluginState* const plugin_state, size_t token_index) {
     SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
-    TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
     if(totp_token_info_iterator_go_to(iterator_context, token_index)) {
         totp_generate_code_worker_notify(
             scene_state->generate_code_worker_context, TotpGenerateCodeWorkerEventForceUpdate);
@@ -137,9 +138,9 @@ static void update_totp_params(PluginState* const plugin_state, size_t token_ind
 
 static void draw_totp_code(Canvas* const canvas, const PluginState* const plugin_state) {
     const SceneState* scene_state = plugin_state->current_scene_state;
-    const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
-    uint8_t code_length =
-        totp_token_info_iterator_get_current_token(iterator_context)->digits;
+    const TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
+    uint8_t code_length = totp_token_info_iterator_get_current_token(iterator_context)->digits;
     uint8_t offset_x = scene_state->ui_precalculated_dimensions.code_offset_x;
     uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width;
     uint8_t offset_x_inc = scene_state->ui_precalculated_dimensions.code_offset_x_inc;
@@ -162,8 +163,13 @@ static void draw_totp_code(Canvas* const canvas, const PluginState* const plugin
 
 static void on_new_token_code_generated(bool time_left, void* context) {
     const PluginState* plugin_state = context;
+    const TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
+    if(totp_token_info_iterator_get_total_count(iterator_context) == 0) {
+        return;
+    }
+
     SceneState* scene_state = plugin_state->current_scene_state;
-    const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
     const TokenInfo* current_token = totp_token_info_iterator_get_current_token(iterator_context);
 
     uint8_t char_width = modeNine_15ptFontInfo.charInfo[0].width;
@@ -222,7 +228,8 @@ void totp_scene_generate_token_activate(PluginState* plugin_state) {
             scene_state->last_code_update_sync);
     }
 #endif
-    const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    const TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
     scene_state->generate_code_worker_context = totp_generate_code_worker_start(
         scene_state->last_code,
         totp_token_info_iterator_get_current_token(iterator_context),
@@ -238,11 +245,13 @@ void totp_scene_generate_token_activate(PluginState* plugin_state) {
         &on_code_lifetime_updated_generated,
         scene_state);
 
-    update_totp_params(plugin_state, totp_token_info_iterator_get_current_token_index(iterator_context));
+    update_totp_params(
+        plugin_state, totp_token_info_iterator_get_current_token_index(iterator_context));
 }
 
 void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_state) {
-    const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    const TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
     if(totp_token_info_iterator_get_total_count(iterator_context) == 0) {
         canvas_draw_str_aligned(
             canvas,
@@ -264,8 +273,8 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
     const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
 
     canvas_set_font(canvas, FontPrimary);
-    const char* token_name_cstr = furi_string_get_cstr(
-        totp_token_info_iterator_get_current_token(iterator_context)->name);
+    const char* token_name_cstr =
+        furi_string_get_cstr(totp_token_info_iterator_get_current_token(iterator_context)->name);
     uint16_t token_name_width = canvas_string_width(canvas, token_name_cstr);
     if(SCREEN_WIDTH - token_name_width > 18) {
         canvas_draw_str_aligned(
@@ -344,7 +353,8 @@ bool totp_scene_generate_token_handle_event(
         if(event->input.key == InputKeyDown &&
            plugin_state->automation_method & AutomationMethodBadUsb) {
             scene_state = (SceneState*)plugin_state->current_scene_state;
-            const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+            const TokenInfoIteratorContext* iterator_context =
+                totp_config_get_token_iterator_context(plugin_state);
             totp_usb_type_code_worker_notify(
                 scene_state->usb_type_code_worker_context,
                 TotpUsbTypeCodeWorkerEventType,
@@ -359,7 +369,8 @@ bool totp_scene_generate_token_handle_event(
             event->input.key == InputKeyUp &&
             plugin_state->automation_method & AutomationMethodBadBt) {
             scene_state = (SceneState*)plugin_state->current_scene_state;
-            const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+            const TokenInfoIteratorContext* iterator_context =
+                totp_config_get_token_iterator_context(plugin_state);
             totp_bt_type_code_worker_notify(
                 plugin_state->bt_type_code_worker_context,
                 TotpBtTypeCodeWorkerEventType,
@@ -382,8 +393,10 @@ bool totp_scene_generate_token_handle_event(
     case InputKeyDown:
         break;
     case InputKeyRight: {
-        const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
-        size_t current_token_index = totp_token_info_iterator_get_current_token_index(iterator_context);
+        const TokenInfoIteratorContext* iterator_context =
+            totp_config_get_token_iterator_context(plugin_state);
+        size_t current_token_index =
+            totp_token_info_iterator_get_current_token_index(iterator_context);
         totp_roll_value_size_t(
             &current_token_index,
             1,
@@ -395,8 +408,10 @@ bool totp_scene_generate_token_handle_event(
         break;
     }
     case InputKeyLeft: {
-        const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
-        size_t current_token_index = totp_token_info_iterator_get_current_token_index(iterator_context);
+        const TokenInfoIteratorContext* iterator_context =
+            totp_config_get_token_iterator_context(plugin_state);
+        size_t current_token_index =
+            totp_token_info_iterator_get_current_token_index(iterator_context);
         totp_roll_value_size_t(
             &current_token_index,
             -1,

+ 9 - 5
ui/scenes/token_menu/totp_scene_token_menu.c

@@ -29,7 +29,8 @@ void totp_scene_token_menu_activate(PluginState* plugin_state) {
 
 void totp_scene_token_menu_render(Canvas* const canvas, PluginState* plugin_state) {
     const SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
-    const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+    const TokenInfoIteratorContext* iterator_context =
+        totp_config_get_token_iterator_context(plugin_state);
     if(totp_token_info_iterator_get_total_count(iterator_context) == 0) {
         ui_control_button_render(
             canvas,
@@ -87,17 +88,19 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt
 
     switch(event->input.key) {
     case InputKeyUp: {
-        const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+        const TokenInfoIteratorContext* iterator_context =
+            totp_config_get_token_iterator_context(plugin_state);
         totp_roll_value_uint8_t(
             &scene_state->selected_control, -1, AddNewToken, AppSettings, RollOverflowBehaviorRoll);
         if(scene_state->selected_control == DeleteToken &&
-            totp_token_info_iterator_get_total_count(iterator_context) == 0) {
+           totp_token_info_iterator_get_total_count(iterator_context) == 0) {
             scene_state->selected_control--;
         }
         break;
     }
     case InputKeyDown: {
-        const TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+        const TokenInfoIteratorContext* iterator_context =
+            totp_config_get_token_iterator_context(plugin_state);
         totp_roll_value_uint8_t(
             &scene_state->selected_control, 1, AddNewToken, AppSettings, RollOverflowBehaviorRoll);
         if(scene_state->selected_control == DeleteToken &&
@@ -130,7 +133,8 @@ bool totp_scene_token_menu_handle_event(const PluginEvent* const event, PluginSt
             DialogMessageButton dialog_result =
                 dialog_message_show(plugin_state->dialogs_app, message);
             dialog_message_free(message);
-            TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state);
+            TokenInfoIteratorContext* iterator_context =
+                totp_config_get_token_iterator_context(plugin_state);
             if(dialog_result == DialogMessageButtonRight &&
                totp_token_info_iterator_get_total_count(iterator_context) > 0) {
                 if(!totp_token_info_iterator_remove_current_token_info(iterator_context)) {

+ 50 - 1
workers/bt_type_code/bt_type_code.h

@@ -8,23 +8,72 @@ typedef uint8_t TotpBtTypeCodeWorkerEvent;
 
 typedef struct TotpBtTypeCodeWorkerContext TotpBtTypeCodeWorkerContext;
 
+/**
+ * @brief Bluetooth token input automation worker events
+ */
 enum TotpBtTypeCodeWorkerEvents {
+
+    /**
+     * @brief Reserved, should not be used anywhere
+     */
     TotpBtTypeCodeWorkerEventReserved = 0b00,
+
+    /**
+     * @brief Stop worker
+     */
     TotpBtTypeCodeWorkerEventStop = 0b01,
+
+    /**
+     * @brief Trigger token input automation
+     */
     TotpBtTypeCodeWorkerEventType = 0b10
 };
 
+/**
+ * @brief Initializes bluetooth token input automation worker
+ * @return worker context
+ */
 TotpBtTypeCodeWorkerContext* totp_bt_type_code_worker_init();
+
+/**
+ * @brief Disposes bluetooth token input automation worker and releases all the allocated resources
+ * @param context worker context
+ */
 void totp_bt_type_code_worker_free(TotpBtTypeCodeWorkerContext* context);
+
+/**
+ * @brief Starts bluetooth token input automation worker
+ * @param context worker context
+ * @param code_buffer code buffer to be used to automate
+ * @param code_buffer_size code buffer size
+ * @param code_buffer_sync code buffer synchronization primitive
+ */
 void totp_bt_type_code_worker_start(
     TotpBtTypeCodeWorkerContext* context,
     char* code_buffer,
     uint8_t code_buffer_size,
     FuriMutex* code_buffer_sync);
+
+/**
+ * @brief Stops bluetooth token input automation worker
+ * @param context worker context
+ */
 void totp_bt_type_code_worker_stop(TotpBtTypeCodeWorkerContext* context);
+
+/**
+ * @brief Notifies bluetooth token input automation worker with a given event
+ * @param context worker context
+ * @param event event to notify worker with
+ * @param flags event flags
+ */
 void totp_bt_type_code_worker_notify(
     TotpBtTypeCodeWorkerContext* context,
     TotpBtTypeCodeWorkerEvent event,
     uint8_t flags);
 
-bool totp_bt_type_code_worker_is_advertising(const TotpBtTypeCodeWorkerContext* context);
+/**
+ * @brief Gets information whether Bluetooth is advertising now or not
+ * @param context worker context
+ * @return \c true if Bluetooth is advertising now; \c false otherwise
+ */
+bool totp_bt_type_code_worker_is_advertising(const TotpBtTypeCodeWorkerContext* context);

+ 49 - 0
workers/generate_totp_code/generate_totp_code.h

@@ -11,26 +11,75 @@ typedef void (*TOTP_CODE_LIFETIME_CHANGED_HANDLER)(float code_lifetime_percent,
 
 typedef struct TotpGenerateCodeWorkerContext TotpGenerateCodeWorkerContext;
 
+/**
+ * @brief Generate token worker events
+ */
 enum TotGenerateCodeWorkerEvents {
+
+    /**
+     * @brief Reserved, should not be used anywhere
+     */
     TotpGenerateCodeWorkerEventReserved = 0b00,
+
+    /**
+     * @brief Stop worker
+     */
     TotpGenerateCodeWorkerEventStop = 0b01,
+
+    /**
+     * @brief Trigger token input automation
+     */
     TotpGenerateCodeWorkerEventForceUpdate = 0b10
 };
 
+/**
+ * @brief Starts generate code worker
+ * @param code_buffer code buffer to generate code to
+ * @param token_info token info to be used to generate code
+ * @param code_buffer_sync code buffer synchronization primitive
+ * @param timezone_offset timezone offset to be used to generate code
+ * @param iv initialization vector (IV) to be used to decrypt token secret
+ * @return worker context
+ */
 TotpGenerateCodeWorkerContext* totp_generate_code_worker_start(
     char* code_buffer,
     const TokenInfo* token_info,
     FuriMutex* code_buffer_sync,
     float timezone_offset,
     uint8_t* iv);
+
+/**
+ * @brief Stops generate code worker
+ * @param context worker context
+ */
 void totp_generate_code_worker_stop(TotpGenerateCodeWorkerContext* context);
+
+/**
+ * @brief Notifies generate code worker with a given event
+ * @param context worker context
+ * @param event event to notify worker with
+ */
 void totp_generate_code_worker_notify(
     TotpGenerateCodeWorkerContext* context,
     TotpGenerateCodeWorkerEvent event);
+
+/**
+ * @brief Sets new handler for "on new code generated" event
+ * @param context worker context
+ * @param on_new_code_generated_handler handler
+ * @param on_new_code_generated_handler_context handler context 
+ */
 void totp_generate_code_worker_set_code_generated_handler(
     TotpGenerateCodeWorkerContext* context,
     TOTP_NEW_CODE_GENERATED_HANDLER on_new_code_generated_handler,
     void* on_new_code_generated_handler_context);
+
+/**
+ * @brief Sets new handler for "on code lifetime changed" event
+ * @param context worker context
+ * @param on_code_lifetime_changed_handler handler
+ * @param on_code_lifetime_changed_handler_context handler context 
+ */
 void totp_generate_code_worker_set_lifetime_changed_handler(
     TotpGenerateCodeWorkerContext* context,
     TOTP_CODE_LIFETIME_CHANGED_HANDLER on_code_lifetime_changed_handler,

+ 4 - 4
workers/type-code-common.c

@@ -14,7 +14,7 @@ static const uint8_t hid_number_keys[] = {
     HID_KEYBOARD_Z};
 
 static uint32_t get_keystroke_delay(TokenAutomationFeature features) {
-    if(features & TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER) {
+    if(features & TokenAutomationFeatureTypeSlower) {
         return 100;
     }
 
@@ -22,7 +22,7 @@ static uint32_t get_keystroke_delay(TokenAutomationFeature features) {
 }
 
 static uint32_t get_keypress_delay(TokenAutomationFeature features) {
-    if(features & TOKEN_AUTOMATION_FEATURE_TYPE_SLOWER) {
+    if(features & TokenAutomationFeatureTypeSlower) {
         return 60;
     }
 
@@ -64,13 +64,13 @@ void totp_type_code_worker_execute_automation(
         i++;
     }
 
-    if(features & TOKEN_AUTOMATION_FEATURE_ENTER_AT_THE_END) {
+    if(features & TokenAutomationFeatureEnterAtTheEnd) {
         furi_delay_ms(get_keystroke_delay(features));
         totp_type_code_worker_press_key(
             HID_KEYBOARD_RETURN, key_press_fn, key_release_fn, features);
     }
 
-    if(features & TOKEN_AUTOMATION_FEATURE_TAB_AT_THE_END) {
+    if(features & TokenAutomationFeatureTabAtTheEnd) {
         furi_delay_ms(get_keystroke_delay(features));
         totp_type_code_worker_press_key(HID_KEYBOARD_TAB, key_press_fn, key_release_fn, features);
     }

+ 8 - 0
workers/type-code-common.h

@@ -4,6 +4,14 @@
 
 typedef bool (*TOTP_AUTOMATION_KEY_HANDLER)(uint16_t key);
 
+/**
+ * @brief Executes token input automation using given key press\release handlers
+ * @param key_press_fn key press handler
+ * @param key_release_fn key release handler
+ * @param code_buffer code buffer to be typed
+ * @param code_buffer_size code buffer size
+ * @param features automation features
+ */
 void totp_type_code_worker_execute_automation(
     TOTP_AUTOMATION_KEY_HANDLER key_press_fn,
     TOTP_AUTOMATION_KEY_HANDLER key_release_fn,

+ 35 - 1
workers/usb_type_code/usb_type_code.h

@@ -8,18 +8,52 @@ typedef uint8_t TotpUsbTypeCodeWorkerEvent;
 
 typedef struct TotpUsbTypeCodeWorkerContext TotpUsbTypeCodeWorkerContext;
 
+/**
+ * @brief USB token input automation worker events
+ */
 enum TotpUsbTypeCodeWorkerEvents {
+
+    /**
+     * @brief Reserved, should not be used anywhere
+     */
     TotpUsbTypeCodeWorkerEventReserved = 0b00,
+
+    /**
+     * @brief Stop worker
+     */
     TotpUsbTypeCodeWorkerEventStop = 0b01,
+
+    /**
+     * @brief Trigger token input automation
+     */
     TotpUsbTypeCodeWorkerEventType = 0b10
 };
 
+/**
+ * @brief Starts USB token input automation worker
+ * @param code_buffer code buffer to be used to automate
+ * @param code_buffer_size code buffer size
+ * @param code_buffer_sync code buffer synchronization primitive
+ * @return worker context
+ */
 TotpUsbTypeCodeWorkerContext* totp_usb_type_code_worker_start(
     char* code_buffer,
     uint8_t code_buffer_size,
     FuriMutex* code_buffer_sync);
+
+/**
+ * @brief Stops USB token input automation worker
+ * @param context worker context
+ */
 void totp_usb_type_code_worker_stop(TotpUsbTypeCodeWorkerContext* context);
+
+/**
+ * @brief Notifies USB token input automation worker with a given event
+ * @param context worker context
+ * @param event event to notify worker with
+ * @param flags event flags
+ */
 void totp_usb_type_code_worker_notify(
     TotpUsbTypeCodeWorkerContext* context,
     TotpUsbTypeCodeWorkerEvent event,
-    uint8_t flags);
+    uint8_t flags);