alex.kopachov 3 лет назад
Родитель
Сommit
75b38491c8

+ 33 - 17
scenes/add_new_token/totp_scene_add_new_token.c

@@ -227,31 +227,47 @@ bool totp_scene_add_new_token_handle_event(PluginEvent* const event, PluginState
                     break;
                     break;
                 case ConfirmButton: {
                 case ConfirmButton: {
                     TokenInfo* tokenInfo = token_info_alloc();
                     TokenInfo* tokenInfo = token_info_alloc();
-                    tokenInfo->name = malloc(scene_state->token_name_length + 1);
-                    strcpy(tokenInfo->name, scene_state->token_name);
-
-                    token_info_set_secret(
+                    bool token_secret_set = token_info_set_secret(
                         tokenInfo,
                         tokenInfo,
                         scene_state->token_secret,
                         scene_state->token_secret,
                         scene_state->token_secret_length,
                         scene_state->token_secret_length,
                         &plugin_state->iv[0]);
                         &plugin_state->iv[0]);
 
 
-                    tokenInfo->algo = scene_state->algo;
-                    tokenInfo->digits = scene_state->digits_count;
+                    if(token_secret_set) {
+                        tokenInfo->name = malloc(scene_state->token_name_length + 1);
+                        strcpy(tokenInfo->name, scene_state->token_name);
+                        tokenInfo->algo = scene_state->algo;
+                        tokenInfo->digits = scene_state->digits_count;
 
 
-                    if(plugin_state->tokens_list == NULL) {
-                        plugin_state->tokens_list = list_init_head(tokenInfo);
-                    } else {
-                        list_add(plugin_state->tokens_list, tokenInfo);
-                    }
-                    plugin_state->tokens_count++;
+                        if(plugin_state->tokens_list == NULL) {
+                            plugin_state->tokens_list = list_init_head(tokenInfo);
+                        } else {
+                            list_add(plugin_state->tokens_list, tokenInfo);
+                        }
+                        plugin_state->tokens_count++;
 
 
-                    totp_config_file_save_new_token(tokenInfo);
+                        totp_config_file_save_new_token(tokenInfo);
 
 
-                    GenerateTokenSceneContext generate_scene_context = {
-                        .current_token_index = plugin_state->tokens_count - 1};
-                    totp_scene_director_activate_scene(
-                        plugin_state, TotpSceneGenerateToken, &generate_scene_context);
+                        GenerateTokenSceneContext generate_scene_context = {
+                            .current_token_index = plugin_state->tokens_count - 1};
+                        totp_scene_director_activate_scene(
+                            plugin_state, TotpSceneGenerateToken, &generate_scene_context);
+                    } else {
+                        token_info_free(tokenInfo);
+                        DialogMessage* message = dialog_message_alloc();
+                        dialog_message_set_buttons(message, "Back", NULL, NULL);
+                        dialog_message_set_text(
+                            message,
+                            "Token secret is invalid",
+                            SCREEN_WIDTH_CENTER,
+                            SCREEN_HEIGHT_CENTER,
+                            AlignCenter,
+                            AlignCenter);
+                        dialog_message_show(plugin_state->dialogs, message);
+                        dialog_message_free(message);
+                        scene_state->selected_control = TokenSecretTextBox;
+                        update_screen_y_offset(scene_state);
+                    }
                     break;
                     break;
                 }
                 }
                 }
                 }

+ 48 - 19
scenes/generate_token/totp_scene_generate_token.c

@@ -87,7 +87,8 @@ void update_totp_params(PluginState* const plugin_state) {
     SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
     SceneState* scene_state = (SceneState*)plugin_state->current_scene_state;
 
 
     if(scene_state->current_token_index < plugin_state->tokens_count) {
     if(scene_state->current_token_index < plugin_state->tokens_count) {
-        TokenInfo* tokenInfo = list_element_at(plugin_state->tokens_list, scene_state->current_token_index)->data;
+        TokenInfo* tokenInfo =
+            list_element_at(plugin_state->tokens_list, scene_state->current_token_index)->data;
 
 
         scene_state->need_token_update = true;
         scene_state->need_token_update = true;
         scene_state->last_code_name = tokenInfo->name;
         scene_state->last_code_name = tokenInfo->name;
@@ -102,7 +103,31 @@ void totp_scene_generate_token_activate(
     PluginState* plugin_state,
     PluginState* plugin_state,
     const GenerateTokenSceneContext* context) {
     const GenerateTokenSceneContext* context) {
     if(!plugin_state->token_list_loaded) {
     if(!plugin_state->token_list_loaded) {
-        totp_config_file_load_tokens(plugin_state);
+        TokenLoadingResult token_load_result = totp_config_file_load_tokens(plugin_state);
+        if(token_load_result != TokenLoadingResultSuccess) {
+            DialogMessage* message = dialog_message_alloc();
+            dialog_message_set_buttons(message, NULL, "Okay", NULL);
+            if(token_load_result == TokenLoadingResultWarning) {
+                dialog_message_set_text(
+                    message,
+                    "Unable to load some tokens\nPlease review conf file",
+                    SCREEN_WIDTH_CENTER,
+                    SCREEN_HEIGHT_CENTER,
+                    AlignCenter,
+                    AlignCenter);
+            } else if(token_load_result == TokenLoadingResultError) {
+                dialog_message_set_text(
+                    message,
+                    "Unable to load tokens\nPlease review conf file",
+                    SCREEN_WIDTH_CENTER,
+                    SCREEN_HEIGHT_CENTER,
+                    AlignCenter,
+                    AlignCenter);
+            }
+
+            dialog_message_show(plugin_state->dialogs, message);
+            dialog_message_free(message);
+        }
     }
     }
     SceneState* scene_state = malloc(sizeof(SceneState));
     SceneState* scene_state = malloc(sizeof(SceneState));
     if(context == NULL) {
     if(context == NULL) {
@@ -154,23 +179,27 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
                              plugin_state->tokens_list, scene_state->current_token_index)
                              plugin_state->tokens_list, scene_state->current_token_index)
                              ->data);
                              ->data);
 
 
-        uint8_t key_length;
-        uint8_t* key = totp_crypto_decrypt(
-            tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);
-
-        i_token_to_str(
-            totp_at(
-                get_totp_algo_impl(tokenInfo->algo),
-                token_info_get_digits_count(tokenInfo),
-                key,
-                key_length,
-                curr_ts,
-                plugin_state->timezone_offset,
-                TOKEN_LIFETIME),
-            scene_state->last_code,
-            tokenInfo->digits);
-        memset(key, 0, key_length);
-        free(key);
+        if(tokenInfo->token != NULL && tokenInfo->token_length > 0) {
+            uint8_t key_length;
+            uint8_t* key = totp_crypto_decrypt(
+                tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);
+
+            i_token_to_str(
+                totp_at(
+                    get_totp_algo_impl(tokenInfo->algo),
+                    token_info_get_digits_count(tokenInfo),
+                    key,
+                    key_length,
+                    curr_ts,
+                    plugin_state->timezone_offset,
+                    TOKEN_LIFETIME),
+                scene_state->last_code,
+                tokenInfo->digits);
+            memset(key, 0, key_length);
+            free(key);
+        } else {
+            i_token_to_str(0, scene_state->last_code, tokenInfo->digits);
+        }
 
 
         if(is_new_token_time) {
         if(is_new_token_time) {
             notification_message(plugin_state->notification, &sequence_short_vibro_and_sound);
             notification_message(plugin_state->notification, &sequence_short_vibro_and_sound);

+ 1 - 4
services/base32/base32.c

@@ -16,7 +16,6 @@
 // limitations under the License.
 // limitations under the License.
 
 
 #include <string.h>
 #include <string.h>
-#include <stdbool.h>
 
 
 #include "base32.h"
 #include "base32.h"
 
 
@@ -26,11 +25,9 @@ int base32_decode(const uint8_t* encoded, uint8_t* result, int bufSize) {
     int count = 0;
     int count = 0;
     for(const uint8_t* ptr = encoded; count < bufSize && *ptr; ++ptr) {
     for(const uint8_t* ptr = encoded; count < bufSize && *ptr; ++ptr) {
         uint8_t ch = *ptr;
         uint8_t ch = *ptr;
-        bool chIsValid = (ch >= '0' && ch <= '8') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
-        if(!chIsValid) {
+        if(ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n' || ch == '-') {
             continue;
             continue;
         }
         }
-
         buffer <<= 5;
         buffer <<= 5;
 
 
         // Deal with commonly mistyped characters
         // Deal with commonly mistyped characters

+ 51 - 28
services/config/config.c

@@ -155,8 +155,15 @@ FlipperFormat* totp_open_config_file(Storage* storage) {
 void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_info) {
 void totp_config_file_save_new_token_i(FlipperFormat* file, TokenInfo* token_info) {
     flipper_format_seek_to_end(file);
     flipper_format_seek_to_end(file);
     flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name);
     flipper_format_write_string_cstr(file, TOTP_CONFIG_KEY_TOKEN_NAME, token_info->name);
+    bool token_is_valid = token_info->token != NULL && token_info->token_length > 0;
+    if(!token_is_valid) {
+        flipper_format_write_comment_cstr(file, "!!! WARNING BEGIN: INVALID TOKEN !!!");
+    }
     flipper_format_write_hex(
     flipper_format_write_hex(
         file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length);
         file, TOTP_CONFIG_KEY_TOKEN_SECRET, token_info->token, token_info->token_length);
+    if(!token_is_valid) {
+        flipper_format_write_comment_cstr(file, "!!! WARNING END !!!");
+    }
     flipper_format_write_string_cstr(
     flipper_format_write_string_cstr(
         file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info));
         file, TOTP_CONFIG_KEY_TOKEN_ALGO, token_info_get_algo_as_cstr(token_info));
     uint32_t digits_count_as_uint32 = token_info_get_digits_as_int(token_info);
     uint32_t digits_count_as_uint32 = token_info_get_digits_as_int(token_info);
@@ -312,7 +319,7 @@ void totp_config_file_load_base(PluginState* const plugin_state) {
     totp_close_storage();
     totp_close_storage();
 }
 }
 
 
-void totp_config_file_load_tokens(PluginState* const plugin_state) {
+TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state) {
     Storage* storage = totp_open_storage();
     Storage* storage = totp_open_storage();
     FlipperFormat* fff_data_file = totp_open_config_file(storage);
     FlipperFormat* fff_data_file = totp_open_config_file(storage);
 
 
@@ -322,9 +329,10 @@ void totp_config_file_load_tokens(PluginState* const plugin_state) {
     if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
     if(!flipper_format_read_header(fff_data_file, temp_str, &temp_data32)) {
         FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
         FURI_LOG_E(LOGGING_TAG, "Missing or incorrect header");
         furi_string_free(temp_str);
         furi_string_free(temp_str);
-        return;
+        return TokenLoadingResultError;
     }
     }
 
 
+    TokenLoadingResult result = TokenLoadingResultSuccess;
     uint8_t index = 0;
     uint8_t index = 0;
     bool has_any_plain_secret = false;
     bool has_any_plain_secret = false;
 
 
@@ -342,48 +350,61 @@ void totp_config_file_load_tokens(PluginState* const plugin_state) {
         uint32_t secret_bytes_count;
         uint32_t secret_bytes_count;
         if(!flipper_format_get_value_count(
         if(!flipper_format_get_value_count(
                fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, &secret_bytes_count)) {
                fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, &secret_bytes_count)) {
-            token_info_free(tokenInfo);
-            continue;
+            secret_bytes_count = 0;
         }
         }
 
 
         if(secret_bytes_count == 1) { // Plain secret key
         if(secret_bytes_count == 1) { // Plain secret key
-            if(!flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str)) {
-                token_info_free(tokenInfo);
-                continue;
+            if(flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_SECRET, temp_str)) {
+                temp_cstr = furi_string_get_cstr(temp_str);
+                if(token_info_set_secret(
+                       tokenInfo, temp_cstr, strlen(temp_cstr), &plugin_state->iv[0])) {
+                    FURI_LOG_W(LOGGING_TAG, "Token \"%s\" has plain secret", tokenInfo->name);
+                } else {
+                    tokenInfo->token = NULL;
+                    tokenInfo->token_length = 0;
+                    FURI_LOG_W(LOGGING_TAG, "Token \"%s\" has invalid secret", tokenInfo->name);
+                    result = TokenLoadingResultWarning;
+                }
+            } else {
+                tokenInfo->token = NULL;
+                tokenInfo->token_length = 0;
+                result = TokenLoadingResultWarning;
             }
             }
 
 
-            temp_cstr = furi_string_get_cstr(temp_str);
-            token_info_set_secret(tokenInfo, temp_cstr, strlen(temp_cstr), &plugin_state->iv[0]);
             has_any_plain_secret = true;
             has_any_plain_secret = true;
-            FURI_LOG_W(LOGGING_TAG, "Found token with plain secret");
         } else { // encrypted
         } else { // encrypted
             tokenInfo->token_length = secret_bytes_count;
             tokenInfo->token_length = secret_bytes_count;
-            tokenInfo->token = malloc(tokenInfo->token_length);
-            if(!flipper_format_read_hex(
-                   fff_data_file,
-                   TOTP_CONFIG_KEY_TOKEN_SECRET,
-                   tokenInfo->token,
-                   tokenInfo->token_length)) {
-                token_info_free(tokenInfo);
-                continue;
+            if(secret_bytes_count > 0) {
+                tokenInfo->token = malloc(tokenInfo->token_length);
+                if(!flipper_format_read_hex(
+                       fff_data_file,
+                       TOTP_CONFIG_KEY_TOKEN_SECRET,
+                       tokenInfo->token,
+                       tokenInfo->token_length)) {
+                    free(tokenInfo->token);
+                    tokenInfo->token = NULL;
+                    tokenInfo->token_length = 0;
+                    result = TokenLoadingResultWarning;
+                }
+            } else {
+                tokenInfo->token = NULL;
+                result = TokenLoadingResultWarning;
             }
             }
         }
         }
 
 
-        if(!flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str)) {
-            token_info_free(tokenInfo);
-            continue;
+        if(flipper_format_read_string(fff_data_file, TOTP_CONFIG_KEY_TOKEN_ALGO, temp_str)) {
+            token_info_set_algo_from_str(tokenInfo, temp_str);
+        } else {
+            tokenInfo->algo = SHA1;
         }
         }
 
 
-        token_info_set_algo_from_str(tokenInfo, temp_str);
-
-        if(!flipper_format_read_uint32(
+        if(flipper_format_read_uint32(
                fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1)) {
                fff_data_file, TOTP_CONFIG_KEY_TOKEN_DIGITS, &temp_data32, 1)) {
-            token_info_free(tokenInfo);
-            continue;
+            token_info_set_digits_from_int(tokenInfo, temp_data32);
+        } else {
+            tokenInfo->digits = TOTP_6_DIGITS;
         }
         }
 
 
-        token_info_set_digits_from_int(tokenInfo, temp_data32);
-
         FURI_LOG_D(LOGGING_TAG, "Found token \"%s\"", tokenInfo->name);
         FURI_LOG_D(LOGGING_TAG, "Found token \"%s\"", tokenInfo->name);
 
 
         if(plugin_state->tokens_list == NULL) {
         if(plugin_state->tokens_list == NULL) {
@@ -407,6 +428,8 @@ void totp_config_file_load_tokens(PluginState* const plugin_state) {
     if(has_any_plain_secret) {
     if(has_any_plain_secret) {
         totp_full_save_config_file(plugin_state);
         totp_full_save_config_file(plugin_state);
     }
     }
+
+    return result;
 }
 }
 
 
 void totp_close_config_file(FlipperFormat* file) {
 void totp_close_config_file(FlipperFormat* file) {

+ 7 - 1
services/config/config.h

@@ -6,12 +6,18 @@
 #include "../../types/token_info.h"
 #include "../../types/token_info.h"
 #include "constants.h"
 #include "constants.h"
 
 
+typedef enum {
+    TokenLoadingResultSuccess,
+    TokenLoadingResultWarning,
+    TokenLoadingResultError
+} TokenLoadingResult;
+
 Storage* totp_open_storage();
 Storage* totp_open_storage();
 void totp_close_storage();
 void totp_close_storage();
 FlipperFormat* totp_open_config_file(Storage* storage);
 FlipperFormat* totp_open_config_file(Storage* storage);
 void totp_close_config_file(FlipperFormat* file);
 void totp_close_config_file(FlipperFormat* file);
 void totp_full_save_config_file(PluginState* const plugin_state);
 void totp_full_save_config_file(PluginState* const plugin_state);
 void totp_config_file_load_base(PluginState* const plugin_state);
 void totp_config_file_load_base(PluginState* const plugin_state);
-void totp_config_file_load_tokens(PluginState* const plugin_state);
+TokenLoadingResult totp_config_file_load_tokens(PluginState* const plugin_state);
 void totp_config_file_save_new_token(TokenInfo* token_info);
 void totp_config_file_save_new_token(TokenInfo* token_info);
 void totp_config_file_update_timezone_offset(float new_timezone_offset);
 void totp_config_file_update_timezone_offset(float new_timezone_offset);

+ 10 - 4
types/token_info.c

@@ -20,7 +20,7 @@ void token_info_free(TokenInfo* token_info) {
     free(token_info);
     free(token_info);
 }
 }
 
 
-void 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,
     uint8_t token_secret_length,
     uint8_t token_secret_length,
@@ -28,12 +28,18 @@ void token_info_set_secret(
     uint8_t* plain_secret = malloc(token_secret_length);
     uint8_t* plain_secret = malloc(token_secret_length);
     int plain_secret_length =
     int plain_secret_length =
         base32_decode((uint8_t*)base32_token_secret, plain_secret, token_secret_length);
         base32_decode((uint8_t*)base32_token_secret, plain_secret, token_secret_length);
-
-    token_info->token =
-        totp_crypto_encrypt(plain_secret, plain_secret_length, iv, &token_info->token_length);
+    bool result;
+    if(plain_secret_length >= 0) {
+        token_info->token =
+            totp_crypto_encrypt(plain_secret, plain_secret_length, iv, &token_info->token_length);
+        result = true;
+    } else {
+        result = false;
+    }
 
 
     memset(plain_secret, 0, token_secret_length);
     memset(plain_secret, 0, token_secret_length);
     free(plain_secret);
     free(plain_secret);
+    return result;
 }
 }
 
 
 uint8_t token_info_get_digits_count(TokenInfo* token_info) {
 uint8_t token_info_get_digits_count(TokenInfo* token_info) {

+ 1 - 1
types/token_info.h

@@ -16,7 +16,7 @@ typedef struct {
 
 
 TokenInfo* token_info_alloc();
 TokenInfo* token_info_alloc();
 void token_info_free(TokenInfo* token_info);
 void token_info_free(TokenInfo* token_info);
-void 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,
     uint8_t token_secret_length,
     uint8_t token_secret_length,