Procházet zdrojové kódy

* Made PIN optional (#4)

* Few refactoring
alex.kopachov před 3 roky
rodič
revize
9c1d1b97c3

+ 3 - 37
scenes/authenticate/totp_scene_authenticate.c

@@ -6,10 +6,9 @@
 #include "../../services/config/config.h"
 #include "../../services/config/config.h"
 #include "../scene_director.h"
 #include "../scene_director.h"
 #include "../totp_scenes_enum.h"
 #include "../totp_scenes_enum.h"
+#include "../../services/crypto/crypto.h"
 
 
 #define MAX_CODE_LENGTH TOTP_IV_SIZE
 #define MAX_CODE_LENGTH TOTP_IV_SIZE
-#define CRYPTO_VERIFY_KEY "FFF_Crypto_pass"
-#define CRYPTO_VERIFY_KEY_LENGTH 16
 
 
 typedef struct {
 typedef struct {
     uint8_t code_input[MAX_CODE_LENGTH];
     uint8_t code_input[MAX_CODE_LENGTH];
@@ -93,42 +92,9 @@ bool totp_scene_authenticate_handle_event(PluginEvent* const event, PluginState*
                     }
                     }
                     break;
                     break;
                 case InputKeyOk:
                 case InputKeyOk:
-                    if (plugin_state->crypto_verify_data == NULL) {
-                        FURI_LOG_D(LOGGING_TAG, "Generating new IV");
-                        furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE);
-                    }
-
-                    memcpy(&plugin_state->iv[0], &plugin_state->base_iv[0], TOTP_IV_SIZE);
-                    for (uint8_t i = 0; i < scene_state->code_length; i++) {
-                        plugin_state->iv[i] = plugin_state->iv[i] ^ (uint8_t)(scene_state->code_input[i] * (i + 1));
-                    }
-
-                    if (plugin_state->crypto_verify_data == NULL) {
-                        FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data");
-                        plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH);
-                        plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH;
-                        Storage* storage = totp_open_storage();
-                        FlipperFormat* config_file = totp_open_config_file(storage);
-                        furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, &plugin_state->iv[0]);
-                        furi_hal_crypto_encrypt((uint8_t* )CRYPTO_VERIFY_KEY, plugin_state->crypto_verify_data, CRYPTO_VERIFY_KEY_LENGTH);
-                        furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
-                        flipper_format_insert_or_update_hex(config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE);
-                        flipper_format_insert_or_update_hex(config_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, plugin_state->crypto_verify_data, CRYPTO_VERIFY_KEY_LENGTH);
-                        totp_close_config_file(config_file);
-                        totp_close_storage();
-                    }
-
-                    uint8_t decrypted_key[CRYPTO_VERIFY_KEY_LENGTH];
-                    furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, &plugin_state->iv[0]);
-                    furi_hal_crypto_decrypt(plugin_state->crypto_verify_data, &decrypted_key[0], CRYPTO_VERIFY_KEY_LENGTH);
-                    furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
-
-                    bool key_valid = true;
-                    for (uint8_t i = 0; i < CRYPTO_VERIFY_KEY_LENGTH && key_valid; i++) {
-                        if (decrypted_key[i] != CRYPTO_VERIFY_KEY[i]) key_valid = false;
-                    }
+                    totp_crypto_seed_iv(plugin_state, &scene_state->code_input[0], scene_state->code_length);
 
 
-                    if (key_valid) {
+                    if (totp_crypto_verify_key(plugin_state)) {
                         FURI_LOG_D(LOGGING_TAG, "PIN is valid");
                         FURI_LOG_D(LOGGING_TAG, "PIN is valid");
                         totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
                         totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
                     } else {
                     } else {

+ 5 - 7
scenes/generate_token/totp_scene_generate_token.c

@@ -8,6 +8,7 @@
 #include "../../services/ui/constants.h"
 #include "../../services/ui/constants.h"
 #include "../../services/totp/totp.h"
 #include "../../services/totp/totp.h"
 #include "../../services/config/config.h"
 #include "../../services/config/config.h"
+#include "../../services/crypto/crypto.h"
 #include "../scene_director.h"
 #include "../scene_director.h"
 #include "../token_menu/totp_scene_token_menu.h"
 #include "../token_menu/totp_scene_token_menu.h"
 
 
@@ -133,14 +134,11 @@ void totp_scene_generate_token_render(Canvas* const canvas, PluginState* plugin_
 
 
         TokenInfo* tokenInfo = (TokenInfo*)(list_element_at(plugin_state->tokens_list, scene_state->current_token_index)->data);
         TokenInfo* tokenInfo = (TokenInfo*)(list_element_at(plugin_state->tokens_list, scene_state->current_token_index)->data);
 
 
-        uint8_t* key = malloc(tokenInfo->token_length);
+        uint8_t key_length;
+        uint8_t* key = totp_crypto_decrypt(tokenInfo->token, tokenInfo->token_length, &plugin_state->iv[0], &key_length);
 
 
-        furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, &plugin_state->iv[0]);
-        furi_hal_crypto_decrypt(tokenInfo->token, key, tokenInfo->token_length);
-        furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
-
-        i_token_to_str(totp_at(get_totp_algo_impl(tokenInfo->algo), token_info_get_digits_count(tokenInfo), key, tokenInfo->token_length, curr_ts, plugin_state->timezone_offset, TOKEN_LIFETIME), scene_state->last_code, tokenInfo->digits);
-        memset(key, 0, tokenInfo->token_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);
         free(key);
 
 
         if (is_new_token_time) {
         if (is_new_token_time) {

+ 7 - 0
services/config/config.c

@@ -167,6 +167,7 @@ void totp_full_save_config_file(PluginState* const plugin_state) {
     flipper_format_write_hex(fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE);
     flipper_format_write_hex(fff_data_file, TOTP_CONFIG_KEY_BASE_IV, &plugin_state->base_iv[0], TOTP_IV_SIZE);
     flipper_format_write_hex(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length);
     flipper_format_write_hex(fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length);
     flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1);
     flipper_format_write_float(fff_data_file, TOTP_CONFIG_KEY_TIMEZONE, &plugin_state->timezone_offset, 1);
+    flipper_format_write_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1);
     ListNode* node = plugin_state->tokens_list;
     ListNode* node = plugin_state->tokens_list;
     while (node != NULL) {
     while (node != NULL) {
         TokenInfo* token_info = node->data;
         TokenInfo* token_info = node->data;
@@ -247,6 +248,12 @@ void totp_config_file_load_base(PluginState* const plugin_state) {
         FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0");
         FURI_LOG_D(LOGGING_TAG, "Missing timezone offset information, defaulting to 0");
     }
     }
 
 
+    flipper_format_rewind(fff_data_file);
+
+    if (!flipper_format_read_bool(fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) {
+        plugin_state->pin_set = true;
+    }    
+
     furi_string_free(temp_str);
     furi_string_free(temp_str);
     totp_close_config_file(fff_data_file);
     totp_close_config_file(fff_data_file);
     totp_close_storage();
     totp_close_storage();

+ 1 - 0
services/config/constants.h

@@ -10,6 +10,7 @@
 #define TOTP_CONFIG_KEY_TOKEN_DIGITS "TokenDigits"
 #define TOTP_CONFIG_KEY_TOKEN_DIGITS "TokenDigits"
 #define TOTP_CONFIG_KEY_CRYPTO_VERIFY "Crypto"
 #define TOTP_CONFIG_KEY_CRYPTO_VERIFY "Crypto"
 #define TOTP_CONFIG_KEY_BASE_IV "BaseIV"
 #define TOTP_CONFIG_KEY_BASE_IV "BaseIV"
+#define TOTP_CONFIG_KEY_PINSET "PinIsSet"
 
 
 #define TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME "sha1"
 #define TOTP_CONFIG_TOKEN_ALGO_SHA1_NAME "sha1"
 #define TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME "sha256"
 #define TOTP_CONFIG_TOKEN_ALGO_SHA256_NAME "sha256"

+ 92 - 0
services/crypto/crypto.c

@@ -0,0 +1,92 @@
+#include "crypto.h"
+#include <furi.h>
+#include <furi_hal.h>
+#include "../config/config.h"
+#include "../../types/common.h"
+
+#define CRYPTO_KEY_SLOT 2
+#define CRYPTO_VERIFY_KEY "FFF_Crypto_pass"
+#define CRYPTO_VERIFY_KEY_LENGTH 16
+#define CRYPTO_ALIGNMENT_FACTOR 16
+
+uint8_t* totp_crypto_encrypt(const uint8_t* plain_data, const uint8_t plain_data_length, const uint8_t* iv, uint8_t* encrypted_data_length) {
+    uint8_t* encrypted_data;
+    size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR;
+    if(remain) {
+        uint8_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR;
+        uint8_t* plain_data_aligned = malloc(plain_data_aligned_length);
+        memset(plain_data_aligned, 0, plain_data_aligned_length);
+        memcpy(plain_data_aligned, plain_data, plain_data_length);
+        
+        encrypted_data = malloc(plain_data_aligned_length);
+        *encrypted_data_length = plain_data_aligned_length;
+    
+        furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
+        furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length);
+        furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
+
+        memset(plain_data_aligned, 0, plain_data_aligned_length);
+        free(plain_data_aligned);
+    } else {
+        encrypted_data = malloc(plain_data_length);
+        *encrypted_data_length = plain_data_length;
+
+        furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
+        furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length);
+        furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
+    }
+
+    return encrypted_data;
+}
+
+uint8_t* totp_crypto_decrypt(const uint8_t* encrypted_data, const uint8_t encrypted_data_length, const uint8_t* iv, uint8_t* decrypted_data_length) {
+    *decrypted_data_length = encrypted_data_length;
+    uint8_t* decrypted_data = malloc(*decrypted_data_length);
+    furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
+    furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length);
+    furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
+    return decrypted_data;
+}
+
+void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length) {
+    if (plugin_state->crypto_verify_data == NULL) {
+        FURI_LOG_D(LOGGING_TAG, "Generating new IV");
+        furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE);
+    }
+
+    memcpy(&plugin_state->iv[0], &plugin_state->base_iv[0], TOTP_IV_SIZE);
+    if (pin != NULL && pin_length > 0) {
+        for (uint8_t i = 0; i < pin_length; i++) {
+            plugin_state->iv[i] = plugin_state->iv[i] ^ (uint8_t)(pin[i] * (i + 1));
+        }
+    }
+
+    if (plugin_state->crypto_verify_data == NULL) {
+        FURI_LOG_D(LOGGING_TAG, "Generating crypto verify data");
+        plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH);
+        plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH;
+        Storage* storage = totp_open_storage();
+        FlipperFormat* config_file = totp_open_config_file(storage);
+
+        plugin_state->crypto_verify_data = totp_crypto_encrypt((uint8_t* )CRYPTO_VERIFY_KEY, CRYPTO_VERIFY_KEY_LENGTH, &plugin_state->iv[0], &plugin_state->crypto_verify_data_length);
+
+        flipper_format_insert_or_update_hex(config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, TOTP_IV_SIZE);
+        flipper_format_insert_or_update_hex(config_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, plugin_state->crypto_verify_data, CRYPTO_VERIFY_KEY_LENGTH);
+        plugin_state->pin_set = pin != NULL && pin_length > 0;
+        flipper_format_insert_or_update_bool(config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1);
+        totp_close_config_file(config_file);
+        totp_close_storage();
+    }
+}
+
+bool totp_crypto_verify_key(const PluginState* plugin_state) {
+    uint8_t decrypted_key_length;
+    uint8_t* decrypted_key = totp_crypto_decrypt(plugin_state->crypto_verify_data, plugin_state->crypto_verify_data_length, &plugin_state->iv[0], &decrypted_key_length);
+
+    bool key_valid = true;
+    for (uint8_t i = 0; i < CRYPTO_VERIFY_KEY_LENGTH && key_valid; i++) {
+        if (decrypted_key[i] != CRYPTO_VERIFY_KEY[i]) key_valid = false;
+    }
+
+    return key_valid;
+}

+ 8 - 0
services/crypto/crypto.h

@@ -0,0 +1,8 @@
+#pragma once
+
+#include "../../types/plugin_state.h"
+
+uint8_t* totp_crypto_encrypt(const uint8_t* plain_data, const uint8_t plain_data_length, const uint8_t* iv, uint8_t* encrypted_data_length);
+uint8_t* totp_crypto_decrypt(const uint8_t* encrypted_data, const uint8_t encrypted_data_length, const uint8_t* iv, uint8_t* decrypted_data_length);
+void totp_crypto_seed_iv(PluginState* plugin_state, uint8_t* pin, uint8_t pin_length);
+bool totp_crypto_verify_key(const PluginState* plugin_state);

+ 21 - 1
totp_app.c

@@ -16,6 +16,8 @@
 #include "types/event_type.h"
 #include "types/event_type.h"
 #include "types/common.h"
 #include "types/common.h"
 #include "scenes/scene_director.h"
 #include "scenes/scene_director.h"
+#include "services/ui/constants.h"
+#include "services/crypto/crypto.h"
 
 
 #define IDLE_TIMEOUT 60000
 #define IDLE_TIMEOUT 60000
 
 
@@ -42,7 +44,25 @@ static void totp_state_init(PluginState* const plugin_state) {
     totp_config_file_load_base(plugin_state);
     totp_config_file_load_base(plugin_state);
 
 
     totp_scene_director_init_scenes(plugin_state);
     totp_scene_director_init_scenes(plugin_state);
-    totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
+
+    if (plugin_state->crypto_verify_data == NULL) {
+        DialogMessage* message = dialog_message_alloc();
+        dialog_message_set_buttons(message, "No", NULL, "Yes");
+        dialog_message_set_text(message, "Would you like to setup PIN?", SCREEN_WIDTH_CENTER, SCREEN_HEIGHT_CENTER, AlignCenter, AlignCenter);
+        DialogMessageButton dialog_result = dialog_message_show(plugin_state->dialogs, message);
+        dialog_message_free(message);
+        if (dialog_result == DialogMessageButtonRight) {
+            totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
+        } else {
+            totp_crypto_seed_iv(plugin_state, NULL, 0);
+            totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
+        }
+    } else if (plugin_state->pin_set) {
+        totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication, NULL);
+    } else {
+        totp_crypto_seed_iv(plugin_state, NULL, 0);
+        totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken, NULL);
+    }
 }
 }
 
 
 static void dispose_plugin_state(PluginState* plugin_state) {
 static void dispose_plugin_state(PluginState* plugin_state) {

+ 0 - 1
types/common.h

@@ -1,4 +1,3 @@
 #pragma once
 #pragma once
 
 
 #define LOGGING_TAG "TOTP APP"
 #define LOGGING_TAG "TOTP APP"
-#define CRYPTO_KEY_SLOT 2

+ 1 - 0
types/plugin_state.h

@@ -23,6 +23,7 @@ typedef struct {
 
 
     uint8_t* crypto_verify_data;
     uint8_t* crypto_verify_data;
     uint8_t crypto_verify_data_length;
     uint8_t crypto_verify_data_length;
+    bool pin_set;
     uint8_t iv[TOTP_IV_SIZE];
     uint8_t iv[TOTP_IV_SIZE];
     uint8_t base_iv[TOTP_IV_SIZE];
     uint8_t base_iv[TOTP_IV_SIZE];
 } PluginState;
 } PluginState;

+ 2 - 16
types/token_info.c

@@ -4,6 +4,7 @@
 #include "stdlib.h"
 #include "stdlib.h"
 #include "common.h"
 #include "common.h"
 #include "../services/base32/base32.h"
 #include "../services/base32/base32.h"
+#include "../services/crypto/crypto.h"
 
 
 TokenInfo* token_info_alloc() {
 TokenInfo* token_info_alloc() {
     TokenInfo* tokenInfo = malloc(sizeof(TokenInfo));
     TokenInfo* tokenInfo = malloc(sizeof(TokenInfo));
@@ -22,23 +23,8 @@ void token_info_free(TokenInfo* token_info) {
 void token_info_set_secret(TokenInfo* token_info, const char* base32_token_secret, uint8_t token_secret_length, uint8_t* iv) {
 void token_info_set_secret(TokenInfo* token_info, const char* base32_token_secret, uint8_t token_secret_length, uint8_t* iv) {
     uint8_t* plain_secret = malloc(token_secret_length);
     uint8_t* plain_secret = malloc(token_secret_length);
     int plain_secret_length = base32_decode((uint8_t *)base32_token_secret, plain_secret, token_secret_length);
     int plain_secret_length = base32_decode((uint8_t *)base32_token_secret, plain_secret, token_secret_length);
-    token_info->token_length = plain_secret_length;
 
 
-    size_t remain = token_info->token_length % 16;
-    if(remain) {
-        token_info->token_length = token_info->token_length - remain + 16;
-        uint8_t* plain_secret_aligned = malloc(token_info->token_length);
-        memcpy(plain_secret_aligned, plain_secret, plain_secret_length);
-        memset(plain_secret, 0, plain_secret_length);
-        free(plain_secret);
-        plain_secret = plain_secret_aligned;
-    }
-
-    token_info->token = malloc(token_info->token_length);
-    
-    furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv);
-    furi_hal_crypto_encrypt(plain_secret, token_info->token, token_info->token_length);
-    furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT);
+    token_info->token = totp_crypto_encrypt(plain_secret, plain_secret_length, iv, &token_info->token_length);
 
 
     memset(plain_secret, 0, token_info->token_length);
     memset(plain_secret, 0, token_info->token_length);
     free(plain_secret);
     free(plain_secret);