From 446e0a1ea4ea2d115d5dfdf1d3184e9206128694 Mon Sep 17 00:00:00 2001 From: Alexander Kopachov Date: Thu, 3 Aug 2023 12:08:14 +0200 Subject: [PATCH] Refactoring (#183) --- cli/commands/add/add.c | 14 +- cli/commands/pin/pin.c | 2 +- cli/commands/update/update.c | 14 +- services/config/config.c | 93 ++++++----- services/config/token_info_iterator.c | 17 +- services/config/token_info_iterator.h | 8 +- services/crypto/crypto_facade.c | 46 +++--- services/crypto/crypto_facade.h | 30 ++-- services/crypto/crypto_v1.c | 52 +++--- services/crypto/crypto_v1.h | 21 +-- services/crypto/crypto_v2.c | 70 +++++---- services/crypto/crypto_v2.h | 26 ++- totp_app.c | 148 +++++++++++------- types/crypto_settings.h | 41 +++++ types/plugin_state.h | 40 +---- types/token_info.c | 12 +- types/token_info.h | 11 +- .../add_new_token/totp_scene_add_new_token.c | 13 +- .../authenticate/totp_scene_authenticate.c | 10 +- .../totp_scene_generate_token.c | 86 ++++------ version.h | 5 + .../generate_totp_code/generate_totp_code.c | 20 +-- .../generate_totp_code/generate_totp_code.h | 7 +- 23 files changed, 374 insertions(+), 412 deletions(-) create mode 100644 types/crypto_settings.h create mode 100644 version.h diff --git a/cli/commands/add/add.c b/cli/commands/add/add.c index 15d94c7e53e..074458f1120 100644 --- a/cli/commands/add/add.c +++ b/cli/commands/add/add.c @@ -11,9 +11,7 @@ struct TotpAddContext { FuriString* args; Cli* cli; - uint8_t* iv; - uint8_t crypto_version; - uint8_t crypto_key_slot; + const CryptoSettings* crypto_settings; }; enum TotpIteratorUpdateTokenResultsEx { @@ -70,9 +68,7 @@ static TotpIteratorUpdateTokenResult furi_string_get_cstr(temp_str), furi_string_size(temp_str), token_secret_encoding, - context_t->iv, - context_t->crypto_version, - context_t->crypto_key_slot); + context_t->crypto_settings); furi_string_secure_free(temp_str); @@ -171,11 +167,7 @@ void totp_cli_command_add_handle(PluginState* plugin_state, FuriString* args, Cl TOTP_CLI_LOCK_UI(plugin_state); struct TotpAddContext add_context = { - .args = args, - .cli = cli, - .iv = &plugin_state->iv[0], - .crypto_version = plugin_state->crypto_version, - .crypto_key_slot = plugin_state->crypto_key_slot}; + .args = args, .cli = cli, .crypto_settings = &plugin_state->crypto_settings}; TotpIteratorUpdateTokenResult add_result = totp_token_info_iterator_add_new_token(iterator_context, &add_token_handler, &add_context); diff --git a/cli/commands/pin/pin.c b/cli/commands/pin/pin.c index da32846b83a..2b989a713b3 100644 --- a/cli/commands/pin/pin.c +++ b/cli/commands/pin/pin.c @@ -105,7 +105,7 @@ void totp_cli_command_pin_handle(PluginState* plugin_state, FuriString* args, Cl bool do_change = false; bool do_remove = false; - uint8_t crypto_key_slot = plugin_state->crypto_key_slot; + uint8_t crypto_key_slot = plugin_state->crypto_settings.crypto_key_slot; bool arguments_parsed = true; while(args_read_string_and_trim(args, temp_str)) { diff --git a/cli/commands/update/update.c b/cli/commands/update/update.c index b846b16ae0c..0435eff4876 100644 --- a/cli/commands/update/update.c +++ b/cli/commands/update/update.c @@ -13,9 +13,7 @@ struct TotpUpdateContext { FuriString* args; Cli* cli; - uint8_t* iv; - uint8_t crypto_version; - uint8_t crypto_key_slot; + const CryptoSettings* crypto_settings; }; enum TotpIteratorUpdateTokenResultsEx { @@ -98,9 +96,7 @@ static TotpIteratorUpdateTokenResult furi_string_get_cstr(temp_str), furi_string_size(temp_str), token_secret_encoding, - context_t->iv, - context_t->crypto_version, - context_t->crypto_key_slot)) { + context_t->crypto_settings)) { furi_string_secure_free(temp_str); return TotpIteratorUpdateTokenResultInvalidSecret; } @@ -155,11 +151,7 @@ void totp_cli_command_update_handle(PluginState* plugin_state, FuriString* args, totp_token_info_iterator_go_to(iterator_context, token_number - 1); struct TotpUpdateContext update_context = { - .args = args, - .cli = cli, - .iv = &plugin_state->iv[0], - .crypto_version = plugin_state->crypto_version, - .crypto_key_slot = plugin_state->crypto_key_slot}; + .args = args, .cli = cli, .crypto_settings = &plugin_state->crypto_settings}; TotpIteratorUpdateTokenResult update_result = totp_token_info_iterator_update_current_token( iterator_context, &update_token_handler, &update_context); diff --git a/services/config/config.c b/services/config/config.c index be4e5d550ed..19b1cf36885 100644 --- a/services/config/config.c +++ b/services/config/config.c @@ -375,7 +375,7 @@ bool totp_config_file_load(PluginState* const plugin_state) { break; } - plugin_state->crypto_version = tmp_uint32; + plugin_state->crypto_settings.crypto_version = tmp_uint32; if(!flipper_format_rewind(fff_data_file)) { break; @@ -388,7 +388,7 @@ bool totp_config_file_load(PluginState* const plugin_state) { break; } - plugin_state->crypto_key_slot = tmp_uint32; + plugin_state->crypto_settings.crypto_key_slot = tmp_uint32; if(!flipper_format_rewind(fff_data_file)) { break; @@ -397,7 +397,7 @@ bool totp_config_file_load(PluginState* const plugin_state) { if(!flipper_format_read_hex( fff_data_file, TOTP_CONFIG_KEY_BASE_IV, - &plugin_state->base_iv[0], + &plugin_state->crypto_settings.base_iv[0], CRYPTO_IV_LENGTH)) { FURI_LOG_D(LOGGING_TAG, "Missing base IV"); } @@ -410,22 +410,23 @@ bool totp_config_file_load(PluginState* const plugin_state) { if(flipper_format_get_value_count( fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, &crypto_size) && crypto_size > 0) { - plugin_state->crypto_verify_data = malloc(sizeof(uint8_t) * crypto_size); - furi_check(plugin_state->crypto_verify_data != NULL); - plugin_state->crypto_verify_data_length = crypto_size; + plugin_state->crypto_settings.crypto_verify_data = + malloc(sizeof(uint8_t) * crypto_size); + furi_check(plugin_state->crypto_settings.crypto_verify_data != NULL); + plugin_state->crypto_settings.crypto_verify_data_length = crypto_size; if(!flipper_format_read_hex( fff_data_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_verify_data, + plugin_state->crypto_settings.crypto_verify_data, crypto_size)) { FURI_LOG_D(LOGGING_TAG, "Missing crypto verify token"); - free(plugin_state->crypto_verify_data); - plugin_state->crypto_verify_data = NULL; - plugin_state->crypto_verify_data_length = 0; + free(plugin_state->crypto_settings.crypto_verify_data); + plugin_state->crypto_settings.crypto_verify_data = NULL; + plugin_state->crypto_settings.crypto_verify_data_length = 0; } } else { - plugin_state->crypto_verify_data = NULL; - plugin_state->crypto_verify_data_length = 0; + plugin_state->crypto_settings.crypto_verify_data = NULL; + plugin_state->crypto_settings.crypto_verify_data_length = 0; } if(!flipper_format_rewind(fff_data_file)) { @@ -443,8 +444,11 @@ bool totp_config_file_load(PluginState* const plugin_state) { } if(!flipper_format_read_bool( - fff_data_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { - plugin_state->pin_set = true; + fff_data_file, + TOTP_CONFIG_KEY_PINSET, + &plugin_state->crypto_settings.pin_required, + 1)) { + plugin_state->crypto_settings.pin_required = true; } if(!flipper_format_rewind(fff_data_file)) { @@ -498,9 +502,7 @@ bool totp_config_file_load(PluginState* const plugin_state) { totp_token_info_iterator_alloc( storage, plugin_state->config_file_context->config_file, - plugin_state->iv, - plugin_state->crypto_version, - plugin_state->crypto_key_slot); + &plugin_state->crypto_settings); result = true; } while(false); @@ -513,33 +515,39 @@ bool totp_config_file_update_crypto_signatures(const PluginState* plugin_state) flipper_format_rewind(config_file); bool update_result = false; do { - uint32_t tmp_uint32 = plugin_state->crypto_version; + uint32_t tmp_uint32 = plugin_state->crypto_settings.crypto_version; if(!flipper_format_insert_or_update_uint32( config_file, TOTP_CONFIG_KEY_CRYPTO_VERSION, &tmp_uint32, 1)) { break; } - tmp_uint32 = plugin_state->crypto_key_slot; + tmp_uint32 = plugin_state->crypto_settings.crypto_key_slot; if(!flipper_format_insert_or_update_uint32( config_file, TOTP_CONFIG_KEY_CRYPTO_KEY_SLOT, &tmp_uint32, 1)) { break; } if(!flipper_format_insert_or_update_hex( - config_file, TOTP_CONFIG_KEY_BASE_IV, plugin_state->base_iv, CRYPTO_IV_LENGTH)) { + config_file, + TOTP_CONFIG_KEY_BASE_IV, + plugin_state->crypto_settings.base_iv, + CRYPTO_IV_LENGTH)) { break; } if(!flipper_format_insert_or_update_hex( config_file, TOTP_CONFIG_KEY_CRYPTO_VERIFY, - plugin_state->crypto_verify_data, - plugin_state->crypto_verify_data_length)) { + plugin_state->crypto_settings.crypto_verify_data, + plugin_state->crypto_settings.crypto_verify_data_length)) { break; } if(!flipper_format_insert_or_update_bool( - config_file, TOTP_CONFIG_KEY_PINSET, &plugin_state->pin_set, 1)) { + config_file, + TOTP_CONFIG_KEY_PINSET, + &plugin_state->crypto_settings.pin_required, + 1)) { break; } @@ -581,24 +589,20 @@ bool totp_config_file_update_encryption( return false; } - uint8_t old_iv[CRYPTO_IV_LENGTH]; - memcpy(&old_iv[0], &plugin_state->iv[0], CRYPTO_IV_LENGTH); - - uint8_t old_crypto_key_slot = plugin_state->crypto_key_slot; - uint8_t old_crypto_version = plugin_state->crypto_version; + CryptoSettings old_crypto_settings = plugin_state->crypto_settings; - memset(&plugin_state->iv[0], 0, CRYPTO_IV_LENGTH); - memset(&plugin_state->base_iv[0], 0, CRYPTO_IV_LENGTH); - if(plugin_state->crypto_verify_data != NULL) { - free(plugin_state->crypto_verify_data); - plugin_state->crypto_verify_data = NULL; + memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH); + memset(&plugin_state->crypto_settings.base_iv[0], 0, CRYPTO_IV_LENGTH); + if(plugin_state->crypto_settings.crypto_verify_data != NULL) { + free(plugin_state->crypto_settings.crypto_verify_data); + plugin_state->crypto_settings.crypto_verify_data = NULL; } - plugin_state->crypto_key_slot = new_crypto_key_slot; - plugin_state->crypto_version = CRYPTO_LATEST_VERSION; + plugin_state->crypto_settings.crypto_key_slot = new_crypto_key_slot; + plugin_state->crypto_settings.crypto_version = CRYPTO_LATEST_VERSION; - CryptoSeedIVResult seed_result = - totp_crypto_seed_iv(plugin_state, new_pin_length > 0 ? new_pin : NULL, new_pin_length); + CryptoSeedIVResult seed_result = totp_crypto_seed_iv( + &plugin_state->crypto_settings, new_pin_length > 0 ? new_pin : NULL, new_pin_length); if(seed_result & CryptoSeedIVResultFlagSuccess && seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData && !totp_config_file_update_crypto_signatures(plugin_state)) { @@ -649,21 +653,14 @@ bool totp_config_file_update_encryption( size_t plain_token_length; uint8_t* plain_token = totp_crypto_decrypt( - encrypted_token, - secret_bytes_count, - &old_iv[0], - old_crypto_version, - old_crypto_key_slot, - &plain_token_length); + encrypted_token, secret_bytes_count, &old_crypto_settings, &plain_token_length); free(encrypted_token); size_t encrypted_token_length; encrypted_token = totp_crypto_encrypt( plain_token, plain_token_length, - &plugin_state->iv[0], - plugin_state->crypto_version, - plugin_state->crypto_key_slot, + &plugin_state->crypto_settings, &encrypted_token_length); memset_s(plain_token, plain_token_length, 0, plain_token_length); @@ -700,12 +697,12 @@ bool totp_config_file_ensure_latest_encryption( const uint8_t* pin, uint8_t pin_length) { bool result = true; - if(plugin_state->crypto_version < CRYPTO_LATEST_VERSION) { + if(plugin_state->crypto_settings.crypto_version < CRYPTO_LATEST_VERSION) { FURI_LOG_I(LOGGING_TAG, "Migration to crypto v%d is needed", CRYPTO_LATEST_VERSION); char* backup_path = totp_config_file_backup(plugin_state); if(backup_path != NULL) { free(backup_path); - uint8_t crypto_key_slot = plugin_state->crypto_key_slot; + uint8_t crypto_key_slot = plugin_state->crypto_settings.crypto_key_slot; if(!totp_crypto_check_key_slot(crypto_key_slot)) { crypto_key_slot = DEFAULT_CRYPTO_KEY_SLOT; } diff --git a/services/config/token_info_iterator.c b/services/config/token_info_iterator.c index 6e7a9a2e02d..75424ef435f 100644 --- a/services/config/token_info_iterator.c +++ b/services/config/token_info_iterator.c @@ -4,6 +4,7 @@ #include #include #include "../../types/common.h" +#include "../../types/crypto_settings.h" #define CONFIG_FILE_PART_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf.part" #define STREAM_COPY_BUFFER_SIZE 128 @@ -15,9 +16,7 @@ struct TokenInfoIteratorContext { size_t last_seek_index; TokenInfo* current_token; FlipperFormat* config_file; - uint8_t* iv; - uint8_t crypto_version; - uint8_t crypto_key_slot; + CryptoSettings* crypto_settings; Storage* storage; }; @@ -242,9 +241,7 @@ static bool TokenInfoIteratorContext* totp_token_info_iterator_alloc( Storage* storage, FlipperFormat* config_file, - uint8_t* iv, - uint8_t crypto_version, - uint8_t crypto_key_slot) { + CryptoSettings* crypto_settings) { Stream* stream = flipper_format_get_raw_stream(config_file); stream_rewind(stream); size_t tokens_count = 0; @@ -262,9 +259,7 @@ TokenInfoIteratorContext* totp_token_info_iterator_alloc( context->total_count = tokens_count; context->current_token = token_info_alloc(); context->config_file = config_file; - context->iv = iv; - context->crypto_version = crypto_version; - context->crypto_key_slot = crypto_key_slot; + context->crypto_settings = crypto_settings; context->storage = storage; return context; } @@ -461,9 +456,7 @@ bool totp_token_info_iterator_go_to(TokenInfoIteratorContext* context, size_t to furi_string_get_cstr(temp_str), furi_string_size(temp_str), PlainTokenSecretEncodingBase32, - context->iv, - context->crypto_version, - context->crypto_key_slot)) { + context->crypto_settings)) { FURI_LOG_W( LOGGING_TAG, "Token \"%s\" has plain secret", diff --git a/services/config/token_info_iterator.h b/services/config/token_info_iterator.h index f30f35f9c5a..ce4d8c72b2e 100644 --- a/services/config/token_info_iterator.h +++ b/services/config/token_info_iterator.h @@ -28,17 +28,13 @@ enum TotpIteratorUpdateTokenResults { * @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 - * @param crypto_version crypto algorithm version to be used - * @param crypto_key_slot crypto key slot to be used + * @param crypto_settings crypto settings * @return Token info iterator context */ TokenInfoIteratorContext* totp_token_info_iterator_alloc( Storage* storage, FlipperFormat* config_file, - uint8_t* iv, - uint8_t crypto_version, - uint8_t crypto_key_slot); + CryptoSettings* crypto_settings); /** * @brief Navigates iterator to the token with given index diff --git a/services/crypto/crypto_facade.c b/services/crypto/crypto_facade.c index 79a5e925dad..acbc09a4ee6 100644 --- a/services/crypto/crypto_facade.c +++ b/services/crypto/crypto_facade.c @@ -1,5 +1,6 @@ #include "crypto_facade.h" #include +#include #include "crypto_v1.h" #include "crypto_v2.h" #include "constants.h" @@ -18,17 +19,16 @@ bool totp_crypto_check_key_slot(uint8_t key_slot) { uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, const size_t plain_data_length, - const uint8_t* iv, - uint8_t crypto_version, - uint8_t key_slot, + const CryptoSettings* crypto_settings, size_t* encrypted_data_length) { - if(crypto_version == 1) { - return totp_crypto_encrypt_v1(plain_data, plain_data_length, iv, encrypted_data_length); + if(crypto_settings->crypto_version == 1) { + return totp_crypto_encrypt_v1( + plain_data, plain_data_length, crypto_settings, encrypted_data_length); } - if(crypto_version == 2) { + if(crypto_settings->crypto_version == 2) { return totp_crypto_encrypt_v2( - plain_data, plain_data_length, iv, key_slot, encrypted_data_length); + plain_data, plain_data_length, crypto_settings, encrypted_data_length); } furi_crash("Unsupported crypto version"); @@ -37,43 +37,41 @@ uint8_t* totp_crypto_encrypt( uint8_t* totp_crypto_decrypt( const uint8_t* encrypted_data, const size_t encrypted_data_length, - const uint8_t* iv, - uint8_t crypto_version, - uint8_t key_slot, + const CryptoSettings* crypto_settings, size_t* decrypted_data_length) { - if(crypto_version == 1) { + if(crypto_settings->crypto_version == 1) { return totp_crypto_decrypt_v1( - encrypted_data, encrypted_data_length, iv, decrypted_data_length); + encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length); } - if(crypto_version == 2) { + if(crypto_settings->crypto_version == 2) { return totp_crypto_decrypt_v2( - encrypted_data, encrypted_data_length, iv, key_slot, decrypted_data_length); + encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length); } furi_crash("Unsupported crypto version"); } CryptoSeedIVResult - totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { - if(plugin_state->crypto_version == 1) { - return totp_crypto_seed_iv_v1(plugin_state, pin, pin_length); + totp_crypto_seed_iv(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length) { + if(crypto_settings->crypto_version == 1) { + return totp_crypto_seed_iv_v1(crypto_settings, pin, pin_length); } - if(plugin_state->crypto_version == 2) { - return totp_crypto_seed_iv_v2(plugin_state, pin, pin_length); + if(crypto_settings->crypto_version == 2) { + return totp_crypto_seed_iv_v2(crypto_settings, pin, pin_length); } furi_crash("Unsupported crypto version"); } -bool totp_crypto_verify_key(const PluginState* plugin_state) { - if(plugin_state->crypto_version == 1) { - return totp_crypto_verify_key_v1(plugin_state); +bool totp_crypto_verify_key(const CryptoSettings* crypto_settings) { + if(crypto_settings->crypto_version == 1) { + return totp_crypto_verify_key_v1(crypto_settings); } - if(plugin_state->crypto_version == 2) { - return totp_crypto_verify_key_v2(plugin_state); + if(crypto_settings->crypto_version == 2) { + return totp_crypto_verify_key_v2(crypto_settings); } furi_crash("Unsupported crypto version"); diff --git a/services/crypto/crypto_facade.h b/services/crypto/crypto_facade.h index 64d62126b68..bbcbf7c0074 100644 --- a/services/crypto/crypto_facade.h +++ b/services/crypto/crypto_facade.h @@ -1,6 +1,9 @@ #pragma once -#include "../../types/plugin_state.h" +#include +#include +#include +#include "../../types/crypto_settings.h" #include "common_types.h" /** @@ -14,52 +17,43 @@ bool totp_crypto_check_key_slot(uint8_t key_slot); * @brief Encrypts plain data using built-in certificate and given initialization vector (IV) * @param plain_data plain data to be encrypted * @param plain_data_length plain data length - * @param iv initialization vector (IV) to be used to encrypt plain data - * @param crypto_version version of crypto algorithms to use - * @param key_slot key slot to be used + * @param crypto_settings crypto settings * @param[out] encrypted_data_length encrypted data length * @return Encrypted data */ uint8_t* totp_crypto_encrypt( const uint8_t* plain_data, const size_t plain_data_length, - const uint8_t* iv, - uint8_t crypto_version, - uint8_t key_slot, + const CryptoSettings* crypto_settings, size_t* encrypted_data_length); /** * @brief Decrypts encrypted data using built-in certificate and given initialization vector (IV) * @param encrypted_data encrypted data to be decrypted * @param encrypted_data_length encrypted data length - * @param iv initialization vector (IV) to be used to encrypt plain data - * @param crypto_version version of crypto algorithms to use - * @param key_slot key slot to be used + * @param crypto_settings crypto settings * @param[out] decrypted_data_length decrypted data length * @return Decrypted data */ uint8_t* totp_crypto_decrypt( const uint8_t* encrypted_data, const size_t encrypted_data_length, - const uint8_t* iv, - uint8_t crypto_version, - uint8_t key_slot, + const CryptoSettings* crypto_settings, size_t* decrypted_data_length); /** * @brief Seed initialization vector (IV) using user's PIN - * @param plugin_state application state - * @param key_slot key slot to be used + * @param crypto_settings crypto settings * @param pin user's PIN * @param pin_length user's PIN length * @return Results of seeding IV */ CryptoSeedIVResult - totp_crypto_seed_iv(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); + totp_crypto_seed_iv(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length); /** * @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption - * @param plugin_state application state + * @param crypto_settings crypto settings * @return \c true if cryptographic information is valid; \c false otherwise */ -bool totp_crypto_verify_key(const PluginState* plugin_state); \ No newline at end of file +bool totp_crypto_verify_key(const CryptoSettings* crypto_settings); diff --git a/services/crypto/crypto_v1.c b/services/crypto/crypto_v1.c index c3488753626..d637599f561 100644 --- a/services/crypto/crypto_v1.c +++ b/services/crypto/crypto_v1.c @@ -1,4 +1,6 @@ #include "crypto_v1.h" +#include +#include #include #include #include @@ -15,7 +17,7 @@ static const char* CRYPTO_VERIFY_KEY = "FFF_Crypto_pass"; uint8_t* totp_crypto_encrypt_v1( const uint8_t* plain_data, const size_t plain_data_length, - const uint8_t* iv, + const CryptoSettings* crypto_settings, size_t* encrypted_data_length) { uint8_t* encrypted_data; size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR; @@ -30,7 +32,7 @@ uint8_t* totp_crypto_encrypt_v1( furi_check(encrypted_data != NULL); *encrypted_data_length = plain_data_aligned_length; - furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv); + furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv); furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length); furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT); @@ -41,7 +43,7 @@ uint8_t* totp_crypto_encrypt_v1( furi_check(encrypted_data != NULL); *encrypted_data_length = plain_data_length; - furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv); + furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv); furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length); furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT); } @@ -52,26 +54,28 @@ uint8_t* totp_crypto_encrypt_v1( uint8_t* totp_crypto_decrypt_v1( const uint8_t* encrypted_data, const size_t encrypted_data_length, - const uint8_t* iv, + const CryptoSettings* crypto_settings, size_t* decrypted_data_length) { *decrypted_data_length = encrypted_data_length; uint8_t* decrypted_data = malloc(*decrypted_data_length); furi_check(decrypted_data != NULL); - furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, iv); + furi_hal_crypto_store_load_key(CRYPTO_KEY_SLOT, crypto_settings->iv); furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length); furi_hal_crypto_store_unload_key(CRYPTO_KEY_SLOT); return decrypted_data; } -CryptoSeedIVResult - totp_crypto_seed_iv_v1(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { +CryptoSeedIVResult totp_crypto_seed_iv_v1( + CryptoSettings* crypto_settings, + const uint8_t* pin, + uint8_t pin_length) { CryptoSeedIVResult result; - if(plugin_state->crypto_verify_data == NULL) { + if(crypto_settings->crypto_verify_data == NULL) { FURI_LOG_I(LOGGING_TAG, "Generating new IV"); - furi_hal_random_fill_buf(&plugin_state->base_iv[0], TOTP_IV_SIZE); + furi_hal_random_fill_buf(&crypto_settings->base_iv[0], TOTP_IV_SIZE); } - memcpy(&plugin_state->iv[0], &plugin_state->base_iv[0], TOTP_IV_SIZE); + memcpy(&crypto_settings->iv[0], &crypto_settings->base_iv[0], TOTP_IV_SIZE); if(pin != NULL && pin_length > 0) { uint8_t max_i; if(pin_length > TOTP_IV_SIZE) { @@ -81,7 +85,7 @@ CryptoSeedIVResult } for(uint8_t i = 0; i < max_i; i++) { - plugin_state->iv[i] = plugin_state->iv[i] ^ (uint8_t)(pin[i] * (i + 1)); + crypto_settings->iv[i] = crypto_settings->iv[i] ^ (uint8_t)(pin[i] * (i + 1)); } } else { uint8_t max_i; @@ -94,24 +98,24 @@ CryptoSeedIVResult const uint8_t* uid = (const uint8_t*)UID64_BASE; //-V566 for(uint8_t i = 0; i < max_i; i++) { - plugin_state->iv[i] = plugin_state->iv[i] ^ uid[i]; + crypto_settings->iv[i] = crypto_settings->iv[i] ^ uid[i]; } } result = CryptoSeedIVResultFlagSuccess; - if(plugin_state->crypto_verify_data == NULL) { + if(crypto_settings->crypto_verify_data == NULL) { FURI_LOG_I(LOGGING_TAG, "Generating crypto verify data"); - plugin_state->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH); - furi_check(plugin_state->crypto_verify_data != NULL); - plugin_state->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH; + crypto_settings->crypto_verify_data = malloc(CRYPTO_VERIFY_KEY_LENGTH); + furi_check(crypto_settings->crypto_verify_data != NULL); + crypto_settings->crypto_verify_data_length = CRYPTO_VERIFY_KEY_LENGTH; - plugin_state->crypto_verify_data = totp_crypto_encrypt_v1( + crypto_settings->crypto_verify_data = totp_crypto_encrypt_v1( (const uint8_t*)CRYPTO_VERIFY_KEY, CRYPTO_VERIFY_KEY_LENGTH, - &plugin_state->iv[0], - &plugin_state->crypto_verify_data_length); + crypto_settings, + &crypto_settings->crypto_verify_data_length); - plugin_state->pin_set = pin != NULL && pin_length > 0; + crypto_settings->pin_required = pin != NULL && pin_length > 0; result |= CryptoSeedIVResultFlagNewCryptoVerifyData; } @@ -119,12 +123,12 @@ CryptoSeedIVResult return result; } -bool totp_crypto_verify_key_v1(const PluginState* plugin_state) { +bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings) { size_t decrypted_key_length; uint8_t* decrypted_key = totp_crypto_decrypt_v1( - plugin_state->crypto_verify_data, - plugin_state->crypto_verify_data_length, - &plugin_state->iv[0], + crypto_settings->crypto_verify_data, + crypto_settings->crypto_verify_data_length, + crypto_settings, &decrypted_key_length); bool key_valid = true; diff --git a/services/crypto/crypto_v1.h b/services/crypto/crypto_v1.h index 45973909f9e..80e850196fc 100644 --- a/services/crypto/crypto_v1.h +++ b/services/crypto/crypto_v1.h @@ -1,49 +1,52 @@ #pragma once -#include "../../types/plugin_state.h" +#include +#include +#include +#include "../../types/crypto_settings.h" #include "common_types.h" /** * @brief Encrypts plain data using built-in certificate and given initialization vector (IV) * @param plain_data plain data to be encrypted * @param plain_data_length plain data length - * @param iv initialization vector (IV) to be used to encrypt plain data + * @param crypto_settings crypto settings * @param[out] encrypted_data_length encrypted data length * @return Encrypted data */ uint8_t* totp_crypto_encrypt_v1( const uint8_t* plain_data, const size_t plain_data_length, - const uint8_t* iv, + const CryptoSettings* crypto_settings, size_t* encrypted_data_length); /** * @brief Decrypts encrypted data using built-in certificate and given initialization vector (IV) * @param encrypted_data encrypted data to be decrypted * @param encrypted_data_length encrypted data length - * @param iv initialization vector (IV) to be used to encrypt plain data + * @param crypto_settings crypto settings * @param[out] decrypted_data_length decrypted data length * @return Decrypted data */ uint8_t* totp_crypto_decrypt_v1( const uint8_t* encrypted_data, const size_t encrypted_data_length, - const uint8_t* iv, + const CryptoSettings* crypto_settings, size_t* decrypted_data_length); /** * @brief Seed initialization vector (IV) using user's PIN - * @param plugin_state application state + * @param crypto_settings crypto settings * @param pin user's PIN * @param pin_length user's PIN length * @return Results of seeding IV */ CryptoSeedIVResult - totp_crypto_seed_iv_v1(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); + totp_crypto_seed_iv_v1(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length); /** * @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption - * @param plugin_state application state + * @param crypto_settings crypto settings * @return \c true if cryptographic information is valid; \c false otherwise */ -bool totp_crypto_verify_key_v1(const PluginState* plugin_state); \ No newline at end of file +bool totp_crypto_verify_key_v1(const CryptoSettings* crypto_settings); \ No newline at end of file diff --git a/services/crypto/crypto_v2.c b/services/crypto/crypto_v2.c index 4be569193ba..897a7fd32ec 100644 --- a/services/crypto/crypto_v2.c +++ b/services/crypto/crypto_v2.c @@ -1,4 +1,6 @@ #include "crypto_v2.h" +#include +#include #include #include #include @@ -28,8 +30,7 @@ static uint8_t get_crypto_verify_key_length() { uint8_t* totp_crypto_encrypt_v2( const uint8_t* plain_data, const size_t plain_data_length, - const uint8_t* iv, - uint8_t key_slot, + const CryptoSettings* crypto_settings, size_t* encrypted_data_length) { uint8_t* encrypted_data; size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR; @@ -45,12 +46,14 @@ uint8_t* totp_crypto_encrypt_v2( *encrypted_data_length = plain_data_aligned_length; furi_check( - furi_hal_crypto_store_load_key(key_slot, iv), "Encryption failed: store_load_key"); + furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv), + "Encryption failed: store_load_key"); furi_check( furi_hal_crypto_encrypt(plain_data_aligned, encrypted_data, plain_data_aligned_length), "Encryption failed: encrypt"); furi_check( - furi_hal_crypto_store_unload_key(key_slot), "Encryption failed: store_unload_key"); + furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot), + "Encryption failed: store_unload_key"); memset_s(plain_data_aligned, plain_data_aligned_length, 0, plain_data_aligned_length); free(plain_data_aligned); @@ -60,12 +63,14 @@ uint8_t* totp_crypto_encrypt_v2( *encrypted_data_length = plain_data_length; furi_check( - furi_hal_crypto_store_load_key(key_slot, iv), "Encryption failed: store_load_key"); + furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv), + "Encryption failed: store_load_key"); furi_check( furi_hal_crypto_encrypt(plain_data, encrypted_data, plain_data_length), "Encryption failed: encrypt"); furi_check( - furi_hal_crypto_store_unload_key(key_slot), "Encryption failed: store_unload_key"); + furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot), + "Encryption failed: store_unload_key"); } return encrypted_data; @@ -74,29 +79,34 @@ uint8_t* totp_crypto_encrypt_v2( uint8_t* totp_crypto_decrypt_v2( const uint8_t* encrypted_data, const size_t encrypted_data_length, - const uint8_t* iv, - uint8_t key_slot, + const CryptoSettings* crypto_settings, size_t* decrypted_data_length) { *decrypted_data_length = encrypted_data_length; uint8_t* decrypted_data = malloc(*decrypted_data_length); furi_check(decrypted_data != NULL); - furi_check(furi_hal_crypto_store_load_key(key_slot, iv), "Decryption failed: store_load_key"); + furi_check( + furi_hal_crypto_store_load_key(crypto_settings->crypto_key_slot, crypto_settings->iv), + "Decryption failed: store_load_key"); furi_check( furi_hal_crypto_decrypt(encrypted_data, decrypted_data, encrypted_data_length), "Decryption failed: decrypt"); - furi_check(furi_hal_crypto_store_unload_key(key_slot), "Decryption failed: store_unload_key"); + furi_check( + furi_hal_crypto_store_unload_key(crypto_settings->crypto_key_slot), + "Decryption failed: store_unload_key"); return decrypted_data; } -CryptoSeedIVResult - totp_crypto_seed_iv_v2(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length) { +CryptoSeedIVResult totp_crypto_seed_iv_v2( + CryptoSettings* crypto_settings, + const uint8_t* pin, + uint8_t pin_length) { CryptoSeedIVResult result; - if(plugin_state->crypto_verify_data == NULL) { + if(crypto_settings->crypto_verify_data == NULL) { FURI_LOG_I(LOGGING_TAG, "Generating new IV"); - furi_hal_random_fill_buf(&plugin_state->base_iv[0], CRYPTO_IV_LENGTH); + furi_hal_random_fill_buf(&crypto_settings->base_iv[0], CRYPTO_IV_LENGTH); } - memcpy(&plugin_state->iv[0], &plugin_state->base_iv[0], CRYPTO_IV_LENGTH); + memcpy(&crypto_settings->iv[0], &crypto_settings->base_iv[0], CRYPTO_IV_LENGTH); const uint8_t* device_uid = get_device_uid(); uint8_t device_uid_length = get_device_uid_length(); @@ -117,7 +127,7 @@ CryptoSeedIVResult uint8_t hmac[HMAC_SHA512_RESULT_SIZE] = {0}; int hmac_result_code = hmac_sha512( - hmac_key, hmac_key_length, &plugin_state->base_iv[0], CRYPTO_IV_LENGTH, &hmac[0]); + hmac_key, hmac_key_length, &crypto_settings->base_iv[0], CRYPTO_IV_LENGTH, &hmac[0]); memset_s(hmac_key, hmac_key_length, 0, hmac_key_length); free(hmac_key); @@ -125,25 +135,24 @@ CryptoSeedIVResult if(hmac_result_code == 0) { uint8_t offset = hmac[HMAC_SHA512_RESULT_SIZE - 1] % (HMAC_SHA512_RESULT_SIZE - CRYPTO_IV_LENGTH - 1); - memcpy(&plugin_state->iv[0], &hmac[offset], CRYPTO_IV_LENGTH); + memcpy(&crypto_settings->iv[0], &hmac[offset], CRYPTO_IV_LENGTH); result = CryptoSeedIVResultFlagSuccess; - if(plugin_state->crypto_verify_data == NULL) { + if(crypto_settings->crypto_verify_data == NULL) { const uint8_t* crypto_vkey = get_crypto_verify_key(); uint8_t crypto_vkey_length = get_crypto_verify_key_length(); FURI_LOG_I(LOGGING_TAG, "Generating crypto verify data"); - plugin_state->crypto_verify_data = malloc(crypto_vkey_length); - furi_check(plugin_state->crypto_verify_data != NULL); - plugin_state->crypto_verify_data_length = crypto_vkey_length; + crypto_settings->crypto_verify_data = malloc(crypto_vkey_length); + furi_check(crypto_settings->crypto_verify_data != NULL); + crypto_settings->crypto_verify_data_length = crypto_vkey_length; - plugin_state->crypto_verify_data = totp_crypto_encrypt_v2( + crypto_settings->crypto_verify_data = totp_crypto_encrypt_v2( crypto_vkey, crypto_vkey_length, - &plugin_state->iv[0], - plugin_state->crypto_key_slot, - &plugin_state->crypto_verify_data_length); + crypto_settings, + &crypto_settings->crypto_verify_data_length); - plugin_state->pin_set = pin != NULL && pin_length > 0; + crypto_settings->pin_required = pin != NULL && pin_length > 0; result |= CryptoSeedIVResultFlagNewCryptoVerifyData; } @@ -154,13 +163,12 @@ CryptoSeedIVResult return result; } -bool totp_crypto_verify_key_v2(const PluginState* plugin_state) { +bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings) { size_t decrypted_key_length; uint8_t* decrypted_key = totp_crypto_decrypt_v2( - plugin_state->crypto_verify_data, - plugin_state->crypto_verify_data_length, - &plugin_state->iv[0], - plugin_state->crypto_key_slot, + crypto_settings->crypto_verify_data, + crypto_settings->crypto_verify_data_length, + crypto_settings, &decrypted_key_length); const uint8_t* crypto_vkey = get_crypto_verify_key(); diff --git a/services/crypto/crypto_v2.h b/services/crypto/crypto_v2.h index 42b15e9e703..1395e7046fd 100644 --- a/services/crypto/crypto_v2.h +++ b/services/crypto/crypto_v2.h @@ -1,54 +1,52 @@ #pragma once -#include "../../types/plugin_state.h" +#include +#include +#include +#include "../../types/crypto_settings.h" #include "common_types.h" /** * @brief Encrypts plain data using built-in certificate and given initialization vector (IV) * @param plain_data plain data to be encrypted * @param plain_data_length plain data length - * @param iv initialization vector (IV) to be used to encrypt plain data - * @param key_slot key slot to be used + * @param crypto_settings crypto settings * @param[out] encrypted_data_length encrypted data length * @return Encrypted data */ uint8_t* totp_crypto_encrypt_v2( const uint8_t* plain_data, const size_t plain_data_length, - const uint8_t* iv, - uint8_t key_slot, + const CryptoSettings* crypto_settings, size_t* encrypted_data_length); /** * @brief Decrypts encrypted data using built-in certificate and given initialization vector (IV) * @param encrypted_data encrypted data to be decrypted * @param encrypted_data_length encrypted data length - * @param iv initialization vector (IV) to be used to encrypt plain data - * @param key_slot key slot to be used + * @param crypto_settings crypto settings * @param[out] decrypted_data_length decrypted data length * @return Decrypted data */ uint8_t* totp_crypto_decrypt_v2( const uint8_t* encrypted_data, const size_t encrypted_data_length, - const uint8_t* iv, - uint8_t key_slot, + const CryptoSettings* crypto_settings, size_t* decrypted_data_length); /** * @brief Seed initialization vector (IV) using user's PIN - * @param plugin_state application state - * @param key_slot key slot to be used + * @param crypto_settings crypto settings * @param pin user's PIN * @param pin_length user's PIN length * @return Results of seeding IV */ CryptoSeedIVResult - totp_crypto_seed_iv_v2(PluginState* plugin_state, const uint8_t* pin, uint8_t pin_length); + totp_crypto_seed_iv_v2(CryptoSettings* crypto_settings, const uint8_t* pin, uint8_t pin_length); /** * @brief Verifies whether cryptographic information (certificate + IV) is valid and can be used for encryption and decryption - * @param plugin_state application state + * @param crypto_settings crypto settings * @return \c true if cryptographic information is valid; \c false otherwise */ -bool totp_crypto_verify_key_v2(const PluginState* plugin_state); \ No newline at end of file +bool totp_crypto_verify_key_v2(const CryptoSettings* crypto_settings); \ No newline at end of file diff --git a/totp_app.c b/totp_app.c index dc9c6781e8f..251d7bb5ba2 100644 --- a/totp_app.c +++ b/totp_app.c @@ -17,6 +17,7 @@ #include "ui/common_dialogs.h" #include "services/crypto/crypto_facade.h" #include "cli/cli.h" +#include "version.h" struct TotpRenderCallbackContext { FuriMutex* mutex; @@ -39,46 +40,28 @@ static void input_callback(InputEvent* const input_event, void* const ctx) { furi_message_queue_put(event_queue, &event, FuriWaitForever); } -static bool totp_activate_initial_scene(PluginState* const plugin_state) { - 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_app, message); - dialog_message_free(message); - if(!totp_crypto_check_key_slot(plugin_state->crypto_key_slot)) { - totp_dialogs_config_loading_error(plugin_state); - return false; - } - - if(dialog_result == DialogMessageButtonRight) { - totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication); - } else { - CryptoSeedIVResult seed_result = totp_crypto_seed_iv(plugin_state, NULL, 0); - 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 == CryptoSeedIVResultFailed) { - totp_dialogs_config_loading_error(plugin_state); - return false; - } +static bool first_run_init(PluginState* const plugin_state) { + 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_app, message); + dialog_message_free(message); + if(!totp_crypto_check_key_slot(plugin_state->crypto_settings.crypto_key_slot)) { + totp_dialogs_config_loading_error(plugin_state); + return false; + } - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - } - } else if(plugin_state->pin_set) { + if(dialog_result == DialogMessageButtonRight) { totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication); } else { - CryptoSeedIVResult seed_result = totp_crypto_seed_iv(plugin_state, NULL, 0); + CryptoSeedIVResult seed_result = + totp_crypto_seed_iv(&plugin_state->crypto_settings, NULL, 0); if(seed_result & CryptoSeedIVResultFlagSuccess && seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) { if(!totp_config_file_update_crypto_signatures(plugin_state)) { @@ -90,24 +73,65 @@ static bool totp_activate_initial_scene(PluginState* const plugin_state) { return false; } - if(totp_crypto_verify_key(plugin_state)) { - totp_config_file_ensure_latest_encryption(plugin_state, NULL, 0); - totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); - } else { - FURI_LOG_E( - LOGGING_TAG, - "Digital signature verification failed. Looks like conf file was created on another flipper and can't be used on any other"); - DialogMessage* message = dialog_message_alloc(); - dialog_message_set_buttons(message, "Exit", NULL, NULL); - dialog_message_set_text( - message, - "Digital signature verification failed", - SCREEN_WIDTH_CENTER, - SCREEN_HEIGHT_CENTER, - AlignCenter, - AlignCenter); - dialog_message_show(plugin_state->dialogs_app, message); - dialog_message_free(message); + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); + } + + return true; +} + +static bool pinless_activation(PluginState* const plugin_state) { + CryptoSeedIVResult seed_result = totp_crypto_seed_iv(&plugin_state->crypto_settings, NULL, 0); + 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 == CryptoSeedIVResultFailed) { + totp_dialogs_config_loading_error(plugin_state); + return false; + } + + if(totp_crypto_verify_key(&plugin_state->crypto_settings)) { + totp_config_file_ensure_latest_encryption(plugin_state, NULL, 0); + totp_scene_director_activate_scene(plugin_state, TotpSceneGenerateToken); + } else { + FURI_LOG_E( + LOGGING_TAG, + "Digital signature verification failed. Looks like conf file was created on another device and can't be used on any other"); + DialogMessage* message = dialog_message_alloc(); + dialog_message_set_buttons(message, "Exit", NULL, NULL); + dialog_message_set_text( + message, + "Digital signature verification failed", + SCREEN_WIDTH_CENTER, + SCREEN_HEIGHT_CENTER, + AlignCenter, + AlignCenter); + dialog_message_show(plugin_state->dialogs_app, message); + dialog_message_free(message); + return false; + } + + return true; +} + +static bool pin_activation(PluginState* const plugin_state) { + totp_scene_director_activate_scene(plugin_state, TotpSceneAuthentication); + return true; +} + +static bool totp_activate_initial_scene(PluginState* const plugin_state) { + if(plugin_state->crypto_settings.crypto_verify_data == NULL) { + if(!first_run_init(plugin_state)) { + return false; + } + } else if(plugin_state->crypto_settings.pin_required) { + if(!pin_activation(plugin_state)) { + return false; + } + } else { + if(!pinless_activation(plugin_state)) { return false; } } @@ -130,7 +154,7 @@ static bool on_user_idle(void* context) { static bool totp_plugin_state_init(PluginState* const plugin_state) { plugin_state->gui = furi_record_open(RECORD_GUI); plugin_state->dialogs_app = furi_record_open(RECORD_DIALOGS); - memset(&plugin_state->iv[0], 0, CRYPTO_IV_LENGTH); + memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH); if(!totp_config_file_load(plugin_state)) { totp_dialogs_config_loading_error(plugin_state); @@ -147,7 +171,7 @@ static bool totp_plugin_state_init(PluginState* const plugin_state) { } #endif - if(plugin_state->pin_set) { + if(plugin_state->crypto_settings.pin_required) { plugin_state->idle_timeout_context = idle_timeout_alloc(TOTP_AUTO_LOCK_IDLE_TIMEOUT_SEC, &on_user_idle, plugin_state); idle_timeout_start(plugin_state->idle_timeout_context); @@ -169,8 +193,8 @@ static void totp_plugin_state_free(PluginState* plugin_state) { totp_config_file_close(plugin_state); - if(plugin_state->crypto_verify_data != NULL) { - free(plugin_state->crypto_verify_data); + if(plugin_state->crypto_settings.crypto_verify_data != NULL) { + free(plugin_state->crypto_settings.crypto_verify_data); } #ifdef TOTP_BADBT_AUTOMATION_ENABLED @@ -188,6 +212,12 @@ static void totp_plugin_state_free(PluginState* plugin_state) { } int32_t totp_app() { + FURI_LOG_I( + LOGGING_TAG, + "App version: %" PRIu8 ".%" PRIu8 ".%" PRIu8, + TOTP_APP_VERSION_MAJOR, + TOTP_APP_VERSION_MINOR, + TOTP_APP_VERSION_PATCH); PluginState* plugin_state = malloc(sizeof(PluginState)); furi_check(plugin_state != NULL); diff --git a/types/crypto_settings.h b/types/crypto_settings.h new file mode 100644 index 00000000000..8b970fd6d84 --- /dev/null +++ b/types/crypto_settings.h @@ -0,0 +1,41 @@ +#pragma once + +#include +#include "../services/crypto/constants.h" + +typedef struct { + /** + * @brief Crypto key slot to be used + */ + uint8_t crypto_key_slot; + + /** + * @brief Crypto algorithms version to be used + */ + uint8_t crypto_version; + + /** + * @brief Initialization vector (IV) to be used for encryption\decryption + */ + uint8_t iv[CRYPTO_IV_LENGTH]; + + /** + * @brief Basic randomly-generated initialization vector (IV) + */ + uint8_t base_iv[CRYPTO_IV_LENGTH]; + + /** + * @brief Encrypted well-known data + */ + uint8_t* crypto_verify_data; + + /** + * @brief Encrypted well-known data length + */ + size_t crypto_verify_data_length; + + /** + * @brief Whether user's PIN is required or not + */ + bool pin_required; +} CryptoSettings; \ No newline at end of file diff --git a/types/plugin_state.h b/types/plugin_state.h index 8c20093efb7..a3b2f5c8fe7 100644 --- a/types/plugin_state.h +++ b/types/plugin_state.h @@ -13,7 +13,7 @@ #ifdef TOTP_BADBT_AUTOMATION_ENABLED #include "../workers/bt_type_code/bt_type_code.h" #endif -#include "../services/crypto/constants.h" +#include "crypto_settings.h" /** * @brief Application state structure @@ -49,31 +49,6 @@ typedef struct { */ ConfigFileContext* config_file_context; - /** - * @brief Encrypted well-known data - */ - uint8_t* crypto_verify_data; - - /** - * @brief Encrypted well-known data length - */ - size_t crypto_verify_data_length; - - /** - * @brief Whether PIN is set by user or not - */ - bool pin_set; - - /** - * @brief Initialization vector (IV) to be used for encryption\decryption - */ - uint8_t iv[CRYPTO_IV_LENGTH]; - - /** - * @brief Basic randomly-generated initialization vector (IV) - */ - uint8_t base_iv[CRYPTO_IV_LENGTH]; - /** * @brief Notification method */ @@ -107,17 +82,12 @@ typedef struct { uint8_t active_font_index; /** - * @brief Crypto key slot to be used - */ - uint8_t crypto_key_slot; - - /** - * @brief Crypto algorithms version to be used + * @brief Application even queue */ - uint8_t crypto_version; + FuriMessageQueue* event_queue; /** - * @brief Application even queue + * @brief Crypto settings */ - FuriMessageQueue* event_queue; + CryptoSettings crypto_settings; } PluginState; diff --git a/types/token_info.c b/types/token_info.c index bb7140c5be1..1d1e7316066 100644 --- a/types/token_info.c +++ b/types/token_info.c @@ -1,4 +1,5 @@ #include "token_info.h" +#include #include #include #include @@ -25,9 +26,7 @@ bool token_info_set_secret( const char* plain_token_secret, size_t token_secret_length, PlainTokenSecretEncoding plain_token_secret_encoding, - const uint8_t* iv, - uint8_t crypto_version, - uint8_t crypto_key_slot) { + const CryptoSettings* crypto_settings) { if(token_secret_length == 0) return false; uint8_t* plain_secret; size_t plain_secret_length; @@ -57,12 +56,7 @@ bool token_info_set_secret( } token_info->token = totp_crypto_encrypt( - plain_secret, - plain_secret_length, - iv, - crypto_version, - crypto_key_slot, - &token_info->token_length); + plain_secret, plain_secret_length, crypto_settings, &token_info->token_length); result = true; } else { result = false; diff --git a/types/token_info.h b/types/token_info.h index cb786c6846c..969445dff5b 100644 --- a/types/token_info.h +++ b/types/token_info.h @@ -1,8 +1,9 @@ #pragma once -#include +#include #include #include +#include "crypto_settings.h" #define TOKEN_HASH_ALGO_SHA1_NAME "sha1" #define TOKEN_HASH_ALGO_STEAM_NAME "steam" @@ -200,9 +201,7 @@ void token_info_free(TokenInfo* token_info); * @param plain_token_secret plain token secret * @param token_secret_length plain token secret length * @param plain_token_secret_encoding plain token secret encoding - * @param iv initialization vecor (IV) to be used for encryption - * @param crypto_version crypto algorithm version to be used - * @param crypto_key_slot crypto key slot to be used + * @param crypto_settings crypto settings * @return \c true if token successfully set; \c false otherwise */ bool token_info_set_secret( @@ -210,9 +209,7 @@ bool token_info_set_secret( const char* plain_token_secret, size_t token_secret_length, PlainTokenSecretEncoding plain_token_secret_encoding, - const uint8_t* iv, - uint8_t crypto_version, - uint8_t crypto_key_slot); + const CryptoSettings* crypto_settings); /** * @brief Sets token digits count from \c uint8_t value diff --git a/ui/scenes/add_new_token/totp_scene_add_new_token.c b/ui/scenes/add_new_token/totp_scene_add_new_token.c index 5baee5a78f5..6ae288d4c6d 100644 --- a/ui/scenes/add_new_token/totp_scene_add_new_token.c +++ b/ui/scenes/add_new_token/totp_scene_add_new_token.c @@ -42,9 +42,7 @@ typedef struct { struct TotpAddContext { SceneState* scene_state; - uint8_t* iv; - uint8_t crypto_version; - uint8_t crypto_key_slot; + const CryptoSettings* crypto_settings; }; enum TotpIteratorUpdateTokenResultsEx { TotpIteratorUpdateTokenResultInvalidSecret = 1 }; @@ -60,9 +58,7 @@ static TotpIteratorUpdateTokenResult add_token_handler(TokenInfo* tokenInfo, con context_t->scene_state->token_secret, context_t->scene_state->token_secret_length, PlainTokenSecretEncodingBase32, - context_t->iv, - context_t->crypto_version, - context_t->crypto_key_slot)) { + context_t->crypto_settings)) { return TotpIteratorUpdateTokenResultInvalidSecret; } @@ -275,10 +271,7 @@ bool totp_scene_add_new_token_handle_event( break; case ConfirmButton: { struct TotpAddContext add_context = { - .iv = plugin_state->iv, - .scene_state = scene_state, - .crypto_version = plugin_state->crypto_version, - .crypto_key_slot = plugin_state->crypto_key_slot}; + .scene_state = scene_state, .crypto_settings = &plugin_state->crypto_settings}; TokenInfoIteratorContext* iterator_context = totp_config_get_token_iterator_context(plugin_state); TotpIteratorUpdateTokenResult add_result = totp_token_info_iterator_add_new_token( diff --git a/ui/scenes/authenticate/totp_scene_authenticate.c b/ui/scenes/authenticate/totp_scene_authenticate.c index dc4a389137c..ea407395a2d 100644 --- a/ui/scenes/authenticate/totp_scene_authenticate.c +++ b/ui/scenes/authenticate/totp_scene_authenticate.c @@ -24,7 +24,7 @@ void totp_scene_authenticate_activate(PluginState* plugin_state) { scene_state->code_length = 0; memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH); plugin_state->current_scene_state = scene_state; - memset(&plugin_state->iv[0], 0, CRYPTO_IV_LENGTH); + memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH); } void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_state) { @@ -35,7 +35,7 @@ void totp_scene_authenticate_render(Canvas* const canvas, PluginState* plugin_st v_shift = -10; } - if(plugin_state->crypto_verify_data == NULL) { + if(plugin_state->crypto_settings.crypto_verify_data == NULL) { canvas_draw_str_aligned( canvas, SCREEN_WIDTH_CENTER, @@ -123,14 +123,14 @@ bool totp_scene_authenticate_handle_event( } } else if(event->input.type == InputTypeRelease && event->input.key == InputKeyOk) { CryptoSeedIVResult seed_result = totp_crypto_seed_iv( - plugin_state, &scene_state->code_input[0], scene_state->code_length); + &plugin_state->crypto_settings, &scene_state->code_input[0], scene_state->code_length); if(seed_result & CryptoSeedIVResultFlagSuccess && seed_result & CryptoSeedIVResultFlagNewCryptoVerifyData) { totp_config_file_update_crypto_signatures(plugin_state); } - if(totp_crypto_verify_key(plugin_state)) { + if(totp_crypto_verify_key(&plugin_state->crypto_settings)) { FURI_LOG_D(LOGGING_TAG, "PIN is valid"); totp_config_file_ensure_latest_encryption( plugin_state, &scene_state->code_input[0], scene_state->code_length); @@ -138,7 +138,7 @@ bool totp_scene_authenticate_handle_event( } else { FURI_LOG_D(LOGGING_TAG, "PIN is NOT valid"); memset(&scene_state->code_input[0], 0, MAX_CODE_LENGTH); - memset(&plugin_state->iv[0], 0, CRYPTO_IV_LENGTH); + memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH); scene_state->code_length = 0; DialogMessage* message = dialog_message_alloc(); diff --git a/ui/scenes/generate_token/totp_scene_generate_token.c b/ui/scenes/generate_token/totp_scene_generate_token.c index 02f3857ebf3..de1c0685f78 100644 --- a/ui/scenes/generate_token/totp_scene_generate_token.c +++ b/ui/scenes/generate_token/totp_scene_generate_token.c @@ -33,8 +33,8 @@ typedef struct { typedef struct { char last_code[TokenDigitsCountMax + 1]; TotpUsbTypeCodeWorkerContext* usb_type_code_worker_context; - NotificationMessage const** notification_sequence_new_token; - NotificationMessage const** notification_sequence_automation; + NotificationMessage const* notification_sequence_new_token[8]; + NotificationMessage const* notification_sequence_automation[11]; FuriMutex* last_code_update_sync; TotpGenerateCodeWorkerContext* generate_code_worker_context; UiPrecalculatedDimensions ui_precalculated_dimensions; @@ -44,40 +44,29 @@ typedef struct { static const NotificationSequence* get_notification_sequence_new_token(const PluginState* plugin_state, SceneState* scene_state) { - if(scene_state->notification_sequence_new_token == NULL) { - uint8_t i = 0; - uint8_t length = 4; + if(scene_state->notification_sequence_new_token[0] == NULL) { + NotificationMessage const** sequence = &scene_state->notification_sequence_new_token[0]; + *(sequence++) = &message_display_backlight_on; + *(sequence++) = &message_green_255; if(plugin_state->notification_method & NotificationMethodVibro) { - length += 2; + *(sequence++) = &message_vibro_on; } if(plugin_state->notification_method & NotificationMethodSound) { - length += 2; + *(sequence++) = &message_note_c5; } - scene_state->notification_sequence_new_token = malloc(sizeof(void*) * length); - furi_check(scene_state->notification_sequence_new_token != NULL); - scene_state->notification_sequence_new_token[i++] = &message_display_backlight_on; - scene_state->notification_sequence_new_token[i++] = &message_green_255; - if(plugin_state->notification_method & NotificationMethodVibro) { - scene_state->notification_sequence_new_token[i++] = &message_vibro_on; - } - - if(plugin_state->notification_method & NotificationMethodSound) { - scene_state->notification_sequence_new_token[i++] = &message_note_c5; - } - - scene_state->notification_sequence_new_token[i++] = &message_delay_50; + *(sequence++) = &message_delay_50; if(plugin_state->notification_method & NotificationMethodVibro) { - scene_state->notification_sequence_new_token[i++] = &message_vibro_off; + *(sequence++) = &message_vibro_off; } if(plugin_state->notification_method & NotificationMethodSound) { - scene_state->notification_sequence_new_token[i++] = &message_sound_off; + *(sequence++) = &message_sound_off; } - scene_state->notification_sequence_new_token[i++] = NULL; + *(sequence++) = NULL; } return (NotificationSequence*)scene_state->notification_sequence_new_token; @@ -85,44 +74,33 @@ static const NotificationSequence* static const NotificationSequence* get_notification_sequence_automation(const PluginState* plugin_state, SceneState* scene_state) { - if(scene_state->notification_sequence_automation == NULL) { - uint8_t i = 0; - uint8_t length = 3; - if(plugin_state->notification_method & NotificationMethodVibro) { - length += 2; - } + if(scene_state->notification_sequence_automation[0] == NULL) { + NotificationMessage const** sequence = &scene_state->notification_sequence_automation[0]; - if(plugin_state->notification_method & NotificationMethodSound) { - length += 6; - } - - scene_state->notification_sequence_automation = malloc(sizeof(void*) * length); - furi_check(scene_state->notification_sequence_automation != NULL); - - scene_state->notification_sequence_automation[i++] = &message_blue_255; + *(sequence++) = &message_blue_255; if(plugin_state->notification_method & NotificationMethodVibro) { - scene_state->notification_sequence_automation[i++] = &message_vibro_on; + *(sequence++) = &message_vibro_on; } if(plugin_state->notification_method & NotificationMethodSound) { - scene_state->notification_sequence_automation[i++] = &message_note_d5; //-V525 - scene_state->notification_sequence_automation[i++] = &message_delay_50; - scene_state->notification_sequence_automation[i++] = &message_note_e4; - scene_state->notification_sequence_automation[i++] = &message_delay_50; - scene_state->notification_sequence_automation[i++] = &message_note_f3; + *(sequence++) = &message_note_d5; //-V525 + *(sequence++) = &message_delay_50; + *(sequence++) = &message_note_e4; + *(sequence++) = &message_delay_50; + *(sequence++) = &message_note_f3; } - scene_state->notification_sequence_automation[i++] = &message_delay_50; + *(sequence++) = &message_delay_50; if(plugin_state->notification_method & NotificationMethodVibro) { - scene_state->notification_sequence_automation[i++] = &message_vibro_off; + *(sequence++) = &message_vibro_off; } if(plugin_state->notification_method & NotificationMethodSound) { - scene_state->notification_sequence_automation[i++] = &message_sound_off; + *(sequence++) = &message_sound_off; } - scene_state->notification_sequence_automation[i++] = NULL; + *(sequence++) = NULL; } return (NotificationSequence*)scene_state->notification_sequence_automation; @@ -213,6 +191,8 @@ void totp_scene_generate_token_activate(PluginState* plugin_state) { scene_state->active_font = available_fonts[plugin_state->active_font_index]; scene_state->notification_app = furi_record_open(RECORD_NOTIFICATION); + scene_state->notification_sequence_automation[0] = NULL; + scene_state->notification_sequence_new_token[0] = NULL; #ifdef TOTP_BADBT_AUTOMATION_ENABLED @@ -235,9 +215,7 @@ void totp_scene_generate_token_activate(PluginState* plugin_state) { totp_token_info_iterator_get_current_token(iterator_context), scene_state->last_code_update_sync, plugin_state->timezone_offset, - plugin_state->iv, - plugin_state->crypto_version, - plugin_state->crypto_key_slot); + &plugin_state->crypto_settings); totp_generate_code_worker_set_code_generated_handler( scene_state->generate_code_worker_context, &on_new_token_code_generated, plugin_state); @@ -448,14 +426,6 @@ void totp_scene_generate_token_deactivate(PluginState* plugin_state) { } #endif - if(scene_state->notification_sequence_new_token != NULL) { - free(scene_state->notification_sequence_new_token); - } - - if(scene_state->notification_sequence_automation != NULL) { - free(scene_state->notification_sequence_automation); - } - furi_mutex_free(scene_state->last_code_update_sync); free(scene_state); diff --git a/version.h b/version.h new file mode 100644 index 00000000000..e6925b600ad --- /dev/null +++ b/version.h @@ -0,0 +1,5 @@ +#pragma once + +#define TOTP_APP_VERSION_MAJOR (3) +#define TOTP_APP_VERSION_MINOR (2) +#define TOTP_APP_VERSION_PATCH (0) \ No newline at end of file diff --git a/workers/generate_totp_code/generate_totp_code.c b/workers/generate_totp_code/generate_totp_code.c index f028fece899..20a7bb54c47 100644 --- a/workers/generate_totp_code/generate_totp_code.c +++ b/workers/generate_totp_code/generate_totp_code.c @@ -1,5 +1,6 @@ #include "generate_totp_code.h" #include +#include #include "../../services/crypto/crypto_facade.h" #include "../../services/totp/totp.h" #include "../../services/convert/convert.h" @@ -14,9 +15,7 @@ struct TotpGenerateCodeWorkerContext { FuriMutex* code_buffer_sync; const TokenInfo* token_info; float timezone_offset; - uint8_t* iv; - uint8_t crypto_version; - uint8_t crypto_key_slot; + const CryptoSettings* crypto_settings; TOTP_NEW_CODE_GENERATED_HANDLER on_new_code_generated_handler; void* on_new_code_generated_handler_context; TOTP_CODE_LIFETIME_CHANGED_HANDLER on_code_lifetime_changed_handler; @@ -71,12 +70,7 @@ static void generate_totp_code( if(token_info->token != NULL && token_info->token_length > 0) { size_t key_length; uint8_t* key = totp_crypto_decrypt( - token_info->token, - token_info->token_length, - context->iv, - context->crypto_version, - context->crypto_key_slot, - &key_length); + token_info->token, token_info->token_length, context->crypto_settings, &key_length); int_token_to_str( totp_at( @@ -154,18 +148,14 @@ TotpGenerateCodeWorkerContext* totp_generate_code_worker_start( const TokenInfo* token_info, FuriMutex* code_buffer_sync, float timezone_offset, - uint8_t* iv, - uint8_t crypto_version, - uint8_t crypto_key_slot) { + const CryptoSettings* crypto_settings) { TotpGenerateCodeWorkerContext* context = malloc(sizeof(TotpGenerateCodeWorkerContext)); furi_check(context != NULL); context->code_buffer = code_buffer; context->token_info = token_info; context->code_buffer_sync = code_buffer_sync; context->timezone_offset = timezone_offset; - context->iv = iv; - context->crypto_version = crypto_version; - context->crypto_key_slot = crypto_key_slot; + context->crypto_settings = crypto_settings; context->thread = furi_thread_alloc(); furi_thread_set_name(context->thread, "TOTPGenerateWorker"); furi_thread_set_stack_size(context->thread, 2048); diff --git a/workers/generate_totp_code/generate_totp_code.h b/workers/generate_totp_code/generate_totp_code.h index c96799eeb25..eb234313e3a 100644 --- a/workers/generate_totp_code/generate_totp_code.h +++ b/workers/generate_totp_code/generate_totp_code.h @@ -38,8 +38,7 @@ enum TotGenerateCodeWorkerEvents { * @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 - * @param crypto_key_slot crypto key slot to be used + * @param crypto_settings crypto settings * @return worker context */ TotpGenerateCodeWorkerContext* totp_generate_code_worker_start( @@ -47,9 +46,7 @@ TotpGenerateCodeWorkerContext* totp_generate_code_worker_start( const TokenInfo* token_info, FuriMutex* code_buffer_sync, float timezone_offset, - uint8_t* iv, - uint8_t crypto_version, - uint8_t crypto_key_slot); + const CryptoSettings* crypto_settings); /** * @brief Stops generate code worker