From 86a90ab2327203cbe778b3a087f65eb207ee6a64 Mon Sep 17 00:00:00 2001 From: Alexander Kopachov Date: Wed, 9 Aug 2023 16:24:31 +0200 Subject: [PATCH] Implemented #185 (#187) --- application.fam | 12 + lib/wolfssl | 1 + services/config/config.c | 19 +- services/config/constants.h | 6 +- services/config/migrations/common_migration.c | 11 +- services/config/token_info_iterator.c | 4 +- services/crypto/constants.h | 3 +- services/crypto/crypto_facade.c | 19 ++ services/crypto/crypto_v1.c | 4 +- services/crypto/crypto_v2.c | 21 +- services/crypto/crypto_v3.c | 194 +++++++++++ services/crypto/crypto_v3.h | 52 +++ services/hmac/byteswap.c | 12 - services/hmac/byteswap.h | 17 - services/hmac/hmac_common.h | 59 ---- services/hmac/hmac_sha1.c | 24 -- services/hmac/hmac_sha1.h | 11 - services/hmac/hmac_sha256.c | 24 -- services/hmac/hmac_sha256.h | 11 - services/hmac/hmac_sha512.c | 24 -- services/hmac/hmac_sha512.h | 11 - services/hmac/memxor.c | 30 -- services/hmac/memxor.h | 28 -- services/hmac/sha1.c | 251 -------------- services/hmac/sha1.h | 84 ----- services/hmac/sha256.c | 283 ---------------- services/hmac/sha256.h | 79 ----- services/hmac/sha512.c | 309 ------------------ services/hmac/sha512.h | 82 ----- services/hmac/sha_pad_buffer.c | 11 - services/hmac/sha_pad_buffer.h | 4 - services/hmac/u64.h | 44 --- services/totp/totp.c | 44 ++- totp_app.c | 3 + types/crypto_settings.h | 4 +- wolfssl_config.h | 34 ++ 36 files changed, 391 insertions(+), 1438 deletions(-) create mode 160000 lib/wolfssl create mode 100644 services/crypto/crypto_v3.c create mode 100644 services/crypto/crypto_v3.h delete mode 100644 services/hmac/byteswap.c delete mode 100644 services/hmac/byteswap.h delete mode 100644 services/hmac/hmac_common.h delete mode 100644 services/hmac/hmac_sha1.c delete mode 100644 services/hmac/hmac_sha1.h delete mode 100644 services/hmac/hmac_sha256.c delete mode 100644 services/hmac/hmac_sha256.h delete mode 100644 services/hmac/hmac_sha512.c delete mode 100644 services/hmac/hmac_sha512.h delete mode 100644 services/hmac/memxor.c delete mode 100644 services/hmac/memxor.h delete mode 100644 services/hmac/sha1.c delete mode 100644 services/hmac/sha1.h delete mode 100644 services/hmac/sha256.c delete mode 100644 services/hmac/sha256.h delete mode 100644 services/hmac/sha512.c delete mode 100644 services/hmac/sha512.h delete mode 100644 services/hmac/sha_pad_buffer.c delete mode 100644 services/hmac/sha_pad_buffer.h delete mode 100644 services/hmac/u64.h create mode 100644 wolfssl_config.h diff --git a/application.fam b/application.fam index aba01fe739f..b0b175a8190 100644 --- a/application.fam +++ b/application.fam @@ -41,5 +41,17 @@ App( Lib( name="fonts", ), + Lib( + name="wolfssl", + sources=[ + "wolfcrypt/src/pwdbased.c", + "wolfcrypt/src/hmac.c", + "wolfcrypt/src/hash.c", + "wolfcrypt/src/sha.c", + "wolfcrypt/src/sha256.c", + "wolfcrypt/src/sha512.c" + ], + cflags=["-Wno-error", "-include${FAP_SRC_DIR}/wolfssl_config.h"] + ), ], ) diff --git a/lib/wolfssl b/lib/wolfssl new file mode 160000 index 00000000000..3b3c175af0e --- /dev/null +++ b/lib/wolfssl @@ -0,0 +1 @@ +Subproject commit 3b3c175af0e993ffaae251871421e206cc41963f diff --git a/services/config/config.c b/services/config/config.c index 19b1cf36885..6ccba23c015 100644 --- a/services/config/config.c +++ b/services/config/config.c @@ -112,7 +112,8 @@ static bool totp_open_config_file(Storage* storage, FlipperFormat** file) { FlipperFormat* fff_data_file = flipper_format_file_alloc(storage); bool conf_file_exists = storage_common_stat(storage, CONFIG_FILE_PATH, NULL) == FSE_OK; - if(!conf_file_exists) { + if(!conf_file_exists && + storage_common_stat(storage, EXT_PATH("authenticator"), NULL) == FSE_OK) { FURI_LOG_I(LOGGING_TAG, "Application catalog needs to be migrated"); FS_Error migration_result = storage_common_migrate(storage, EXT_PATH("authenticator"), CONFIG_FILE_DIRECTORY_PATH); @@ -396,10 +397,10 @@ bool totp_config_file_load(PluginState* const plugin_state) { if(!flipper_format_read_hex( fff_data_file, - TOTP_CONFIG_KEY_BASE_IV, - &plugin_state->crypto_settings.base_iv[0], - CRYPTO_IV_LENGTH)) { - FURI_LOG_D(LOGGING_TAG, "Missing base IV"); + TOTP_CONFIG_KEY_SALT, + &plugin_state->crypto_settings.salt[0], + CRYPTO_SALT_LENGTH)) { + FURI_LOG_D(LOGGING_TAG, "Missing salt"); } if(!flipper_format_rewind(fff_data_file)) { @@ -529,9 +530,9 @@ bool totp_config_file_update_crypto_signatures(const PluginState* plugin_state) if(!flipper_format_insert_or_update_hex( config_file, - TOTP_CONFIG_KEY_BASE_IV, - plugin_state->crypto_settings.base_iv, - CRYPTO_IV_LENGTH)) { + TOTP_CONFIG_KEY_SALT, + &plugin_state->crypto_settings.salt[0], + CRYPTO_SALT_LENGTH)) { break; } @@ -592,7 +593,7 @@ bool totp_config_file_update_encryption( CryptoSettings old_crypto_settings = plugin_state->crypto_settings; memset(&plugin_state->crypto_settings.iv[0], 0, CRYPTO_IV_LENGTH); - memset(&plugin_state->crypto_settings.base_iv[0], 0, CRYPTO_IV_LENGTH); + memset(&plugin_state->crypto_settings.salt[0], 0, CRYPTO_SALT_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; diff --git a/services/config/constants.h b/services/config/constants.h index 1205bae073a..97c8f0d0a5a 100644 --- a/services/config/constants.h +++ b/services/config/constants.h @@ -2,9 +2,9 @@ #include -#define CONFIG_FILE_DIRECTORY_PATH STORAGE_APP_DATA_PATH_PREFIX +#define CONFIG_FILE_DIRECTORY_PATH EXT_PATH("apps_data/totp") #define CONFIG_FILE_HEADER "Flipper TOTP plugin config file" -#define CONFIG_FILE_ACTUAL_VERSION (8) +#define CONFIG_FILE_ACTUAL_VERSION (9) #define TOTP_CONFIG_KEY_TIMEZONE "Timezone" #define TOTP_CONFIG_KEY_TOKEN_NAME "TokenName" @@ -14,7 +14,7 @@ #define TOTP_CONFIG_KEY_TOKEN_DURATION "TokenDuration" #define TOTP_CONFIG_KEY_TOKEN_AUTOMATION_FEATURES "TokenAutomationFeatures" #define TOTP_CONFIG_KEY_CRYPTO_VERIFY "Crypto" -#define TOTP_CONFIG_KEY_BASE_IV "BaseIV" +#define TOTP_CONFIG_KEY_SALT "Salt" #define TOTP_CONFIG_KEY_PINSET "PinIsSet" #define TOTP_CONFIG_KEY_NOTIFICATION_METHOD "NotificationMethod" #define TOTP_CONFIG_KEY_AUTOMATION_METHOD "AutomationMethod" diff --git a/services/config/migrations/common_migration.c b/services/config/migrations/common_migration.c index 4a12cbd3a98..33a441e724c 100644 --- a/services/config/migrations/common_migration.c +++ b/services/config/migrations/common_migration.c @@ -4,6 +4,8 @@ #include "../../../types/automation_kb_layout.h" #include +#define TOTP_OLD_CONFIG_KEY_BASE_IV "BaseIV" + bool totp_config_migrate_to_latest( FlipperFormat* fff_data_file, FlipperFormat* fff_backup_data_file) { @@ -40,8 +42,13 @@ bool totp_config_migrate_to_latest( flipper_format_rewind(fff_backup_data_file); - if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str)) { - flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_BASE_IV, temp_str); + if(flipper_format_read_string(fff_backup_data_file, TOTP_CONFIG_KEY_SALT, temp_str)) { + flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_SALT, temp_str); + } else if( + flipper_format_rewind(fff_backup_data_file) && + flipper_format_read_string( + fff_backup_data_file, TOTP_OLD_CONFIG_KEY_BASE_IV, temp_str)) { + flipper_format_write_string(fff_data_file, TOTP_CONFIG_KEY_SALT, temp_str); } flipper_format_rewind(fff_backup_data_file); diff --git a/services/config/token_info_iterator.c b/services/config/token_info_iterator.c index 75424ef435f..3d47b9616c8 100644 --- a/services/config/token_info_iterator.c +++ b/services/config/token_info_iterator.c @@ -7,7 +7,7 @@ #include "../../types/crypto_settings.h" #define CONFIG_FILE_PART_FILE_PATH CONFIG_FILE_DIRECTORY_PATH "/totp.conf.part" -#define STREAM_COPY_BUFFER_SIZE 128 +#define STREAM_COPY_BUFFER_SIZE (128) struct TokenInfoIteratorContext { size_t total_count; @@ -547,4 +547,6 @@ void totp_token_info_iterator_attach_to_config_file( TokenInfoIteratorContext* context, FlipperFormat* config_file) { context->config_file = config_file; + Stream* stream = flipper_format_get_raw_stream(context->config_file); + stream_seek(stream, context->last_seek_offset, StreamOffsetFromStart); } \ No newline at end of file diff --git a/services/crypto/constants.h b/services/crypto/constants.h index 294ae4361a9..ad306e4db9d 100644 --- a/services/crypto/constants.h +++ b/services/crypto/constants.h @@ -1,6 +1,7 @@ #pragma once #define CRYPTO_IV_LENGTH (16) +#define CRYPTO_SALT_LENGTH (16) // According to this explanation: https://github.com/flipperdevices/flipperzero-firmware/issues/2885#issuecomment-1646664666 // disabling usage of any key which is "the same across all devices" @@ -8,4 +9,4 @@ #define ACCEPTABLE_CRYPTO_KEY_SLOT_END (100) #define DEFAULT_CRYPTO_KEY_SLOT ACCEPTABLE_CRYPTO_KEY_SLOT_START -#define CRYPTO_LATEST_VERSION (2) \ No newline at end of file +#define CRYPTO_LATEST_VERSION (3) \ No newline at end of file diff --git a/services/crypto/crypto_facade.c b/services/crypto/crypto_facade.c index acbc09a4ee6..73f1ef0ccfa 100644 --- a/services/crypto/crypto_facade.c +++ b/services/crypto/crypto_facade.c @@ -3,6 +3,7 @@ #include #include "crypto_v1.h" #include "crypto_v2.h" +#include "crypto_v3.h" #include "constants.h" bool totp_crypto_check_key_slot(uint8_t key_slot) { @@ -31,6 +32,11 @@ uint8_t* totp_crypto_encrypt( plain_data, plain_data_length, crypto_settings, encrypted_data_length); } + if(crypto_settings->crypto_version == 3) { + return totp_crypto_encrypt_v3( + plain_data, plain_data_length, crypto_settings, encrypted_data_length); + } + furi_crash("Unsupported crypto version"); } @@ -49,6 +55,11 @@ uint8_t* totp_crypto_decrypt( encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length); } + if(crypto_settings->crypto_version == 3) { + return totp_crypto_decrypt_v3( + encrypted_data, encrypted_data_length, crypto_settings, decrypted_data_length); + } + furi_crash("Unsupported crypto version"); } @@ -62,6 +73,10 @@ CryptoSeedIVResult return totp_crypto_seed_iv_v2(crypto_settings, pin, pin_length); } + if(crypto_settings->crypto_version == 3) { + return totp_crypto_seed_iv_v3(crypto_settings, pin, pin_length); + } + furi_crash("Unsupported crypto version"); } @@ -74,5 +89,9 @@ bool totp_crypto_verify_key(const CryptoSettings* crypto_settings) { return totp_crypto_verify_key_v2(crypto_settings); } + if(crypto_settings->crypto_version == 3) { + return totp_crypto_verify_key_v3(crypto_settings); + } + furi_crash("Unsupported crypto version"); } \ No newline at end of file diff --git a/services/crypto/crypto_v1.c b/services/crypto/crypto_v1.c index d637599f561..cdd19cc310f 100644 --- a/services/crypto/crypto_v1.c +++ b/services/crypto/crypto_v1.c @@ -72,10 +72,10 @@ CryptoSeedIVResult totp_crypto_seed_iv_v1( CryptoSeedIVResult result; if(crypto_settings->crypto_verify_data == NULL) { FURI_LOG_I(LOGGING_TAG, "Generating new IV"); - furi_hal_random_fill_buf(&crypto_settings->base_iv[0], TOTP_IV_SIZE); + furi_hal_random_fill_buf(&crypto_settings->salt[0], CRYPTO_SALT_LENGTH); } - memcpy(&crypto_settings->iv[0], &crypto_settings->base_iv[0], TOTP_IV_SIZE); + memcpy(&crypto_settings->iv[0], &crypto_settings->salt[0], TOTP_IV_SIZE); if(pin != NULL && pin_length > 0) { uint8_t max_i; if(pin_length > TOTP_IV_SIZE) { diff --git a/services/crypto/crypto_v2.c b/services/crypto/crypto_v2.c index 897a7fd32ec..18453d578e2 100644 --- a/services/crypto/crypto_v2.c +++ b/services/crypto/crypto_v2.c @@ -5,7 +5,8 @@ #include #include #include "../../types/common.h" -#include "../hmac/hmac_sha512.h" +#include "../../wolfssl_config.h" +#include #include "memset_s.h" #include "constants.h" @@ -102,12 +103,10 @@ CryptoSeedIVResult totp_crypto_seed_iv_v2( uint8_t pin_length) { CryptoSeedIVResult result; if(crypto_settings->crypto_verify_data == NULL) { - FURI_LOG_I(LOGGING_TAG, "Generating new IV"); - furi_hal_random_fill_buf(&crypto_settings->base_iv[0], CRYPTO_IV_LENGTH); + FURI_LOG_I(LOGGING_TAG, "Generating new salt"); + furi_hal_random_fill_buf(&crypto_settings->salt[0], CRYPTO_SALT_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(); @@ -125,16 +124,20 @@ CryptoSeedIVResult totp_crypto_seed_iv_v2( memcpy(hmac_key + device_uid_length, pin, pin_length); } - uint8_t hmac[HMAC_SHA512_RESULT_SIZE] = {0}; - int hmac_result_code = hmac_sha512( - hmac_key, hmac_key_length, &crypto_settings->base_iv[0], CRYPTO_IV_LENGTH, &hmac[0]); + uint8_t hmac[WC_SHA512_DIGEST_SIZE] = {0}; + + Hmac hmac_context; + wc_HmacSetKey(&hmac_context, WC_SHA512, hmac_key, hmac_key_length); + wc_HmacUpdate(&hmac_context, &crypto_settings->salt[0], CRYPTO_SALT_LENGTH); + int hmac_result_code = wc_HmacFinal(&hmac_context, &hmac[0]); + wc_HmacFree(&hmac_context); memset_s(hmac_key, hmac_key_length, 0, hmac_key_length); free(hmac_key); if(hmac_result_code == 0) { uint8_t offset = - hmac[HMAC_SHA512_RESULT_SIZE - 1] % (HMAC_SHA512_RESULT_SIZE - CRYPTO_IV_LENGTH - 1); + hmac[WC_SHA512_DIGEST_SIZE - 1] % (WC_SHA512_DIGEST_SIZE - CRYPTO_IV_LENGTH - 1); memcpy(&crypto_settings->iv[0], &hmac[offset], CRYPTO_IV_LENGTH); result = CryptoSeedIVResultFlagSuccess; diff --git a/services/crypto/crypto_v3.c b/services/crypto/crypto_v3.c new file mode 100644 index 00000000000..a0fcc0b8330 --- /dev/null +++ b/services/crypto/crypto_v3.c @@ -0,0 +1,194 @@ +#include "crypto_v3.h" +#include +#include +#include +#include +#include +#include "../../types/common.h" +#include "../../wolfssl_config.h" +#include +#include +#include "memset_s.h" +#include "constants.h" + +#define CRYPTO_ALIGNMENT_FACTOR (16) +#define PBKDF2_ITERATIONS_COUNT (200) + +static const uint8_t* get_device_uid() { + return (const uint8_t*)UID64_BASE; //-V566 +} + +static uint8_t get_device_uid_length() { + return furi_hal_version_uid_size(); +} + +static const uint8_t* get_crypto_verify_key() { + return get_device_uid(); +} + +static uint8_t get_crypto_verify_key_length() { + return get_device_uid_length(); +} + +uint8_t* totp_crypto_encrypt_v3( + const uint8_t* plain_data, + const size_t plain_data_length, + const CryptoSettings* crypto_settings, + size_t* encrypted_data_length) { + uint8_t* encrypted_data; + size_t remain = plain_data_length % CRYPTO_ALIGNMENT_FACTOR; + if(remain) { + size_t plain_data_aligned_length = plain_data_length - remain + CRYPTO_ALIGNMENT_FACTOR; + uint8_t* plain_data_aligned = malloc(plain_data_aligned_length); + furi_check(plain_data_aligned != NULL); + 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); + furi_check(encrypted_data != NULL); + *encrypted_data_length = plain_data_aligned_length; + + furi_check( + 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(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); + } else { + encrypted_data = malloc(plain_data_length); + furi_check(encrypted_data != NULL); + *encrypted_data_length = plain_data_length; + + furi_check( + 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(crypto_settings->crypto_key_slot), + "Encryption failed: store_unload_key"); + } + + return encrypted_data; +} + +uint8_t* totp_crypto_decrypt_v3( + const uint8_t* encrypted_data, + const size_t encrypted_data_length, + 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(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(crypto_settings->crypto_key_slot), + "Decryption failed: store_unload_key"); + return decrypted_data; +} + +CryptoSeedIVResult totp_crypto_seed_iv_v3( + CryptoSettings* crypto_settings, + const uint8_t* pin, + uint8_t pin_length) { + CryptoSeedIVResult result; + if(crypto_settings->crypto_verify_data == NULL) { + FURI_LOG_I(LOGGING_TAG, "Generating new salt"); + furi_hal_random_fill_buf(&crypto_settings->salt[0], CRYPTO_SALT_LENGTH); + } + + const uint8_t* device_uid = get_device_uid(); + uint8_t device_uid_length = get_device_uid_length(); + + uint8_t pbkdf_key_length = device_uid_length; + if(pin != NULL && pin_length > 0) { + pbkdf_key_length += pin_length; + } + + uint8_t* pbkdf_key = malloc(pbkdf_key_length); + furi_check(pbkdf_key != NULL); + + memcpy(pbkdf_key, device_uid, device_uid_length); + + if(pin != NULL && pin_length > 0) { + memcpy(pbkdf_key + device_uid_length, pin, pin_length); + } + + uint8_t pbkdf_output[WC_SHA512_DIGEST_SIZE] = {0}; + + int pbkdf_result_code = wc_PBKDF2( + &pbkdf_output[0], + pbkdf_key, + pbkdf_key_length, + &crypto_settings->salt[0], + CRYPTO_SALT_LENGTH, + PBKDF2_ITERATIONS_COUNT, + WC_SHA512_DIGEST_SIZE, + WC_SHA512); + + memset_s(pbkdf_key, pbkdf_key_length, 0, pbkdf_key_length); + free(pbkdf_key); + + if(pbkdf_result_code == 0) { + uint8_t offset = pbkdf_output[WC_SHA512_DIGEST_SIZE - 1] % + (WC_SHA512_DIGEST_SIZE - CRYPTO_IV_LENGTH - 1); + memcpy(&crypto_settings->iv[0], &pbkdf_output[offset], CRYPTO_IV_LENGTH); + result = CryptoSeedIVResultFlagSuccess; + 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"); + 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; + + crypto_settings->crypto_verify_data = totp_crypto_encrypt_v3( + crypto_vkey, + crypto_vkey_length, + crypto_settings, + &crypto_settings->crypto_verify_data_length); + + crypto_settings->pin_required = pin != NULL && pin_length > 0; + + result |= CryptoSeedIVResultFlagNewCryptoVerifyData; + } + } else { + result = CryptoSeedIVResultFailed; + } + + memset_s(&pbkdf_output[0], WC_SHA512_DIGEST_SIZE, 0, WC_SHA512_DIGEST_SIZE); + + return result; +} + +bool totp_crypto_verify_key_v3(const CryptoSettings* crypto_settings) { + size_t decrypted_key_length; + uint8_t* decrypted_key = totp_crypto_decrypt_v3( + 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(); + uint8_t crypto_vkey_length = get_crypto_verify_key_length(); + bool key_valid = true; + for(uint8_t i = 0; i < crypto_vkey_length && key_valid; i++) { + if(decrypted_key[i] != crypto_vkey[i]) key_valid = false; + } + + free(decrypted_key); + + return key_valid; +} \ No newline at end of file diff --git a/services/crypto/crypto_v3.h b/services/crypto/crypto_v3.h new file mode 100644 index 00000000000..39c718aab53 --- /dev/null +++ b/services/crypto/crypto_v3.h @@ -0,0 +1,52 @@ +#pragma once + +#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 crypto_settings crypto settings + * @param[out] encrypted_data_length encrypted data length + * @return Encrypted data + */ +uint8_t* totp_crypto_encrypt_v3( + const uint8_t* plain_data, + const size_t plain_data_length, + 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 crypto_settings crypto settings + * @param[out] decrypted_data_length decrypted data length + * @return Decrypted data + */ +uint8_t* totp_crypto_decrypt_v3( + const uint8_t* encrypted_data, + const size_t encrypted_data_length, + const CryptoSettings* crypto_settings, + size_t* decrypted_data_length); + +/** + * @brief Seed initialization vector (IV) using user's PIN + * @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_v3(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 crypto_settings crypto settings + * @return \c true if cryptographic information is valid; \c false otherwise + */ +bool totp_crypto_verify_key_v3(const CryptoSettings* crypto_settings); \ No newline at end of file diff --git a/services/hmac/byteswap.c b/services/hmac/byteswap.c deleted file mode 100644 index e922deec0d8..00000000000 --- a/services/hmac/byteswap.c +++ /dev/null @@ -1,12 +0,0 @@ -#include "byteswap.h" - -uint32_t swap_uint32(uint32_t val) { - val = ((val << 8) & 0xFF00FF00) | ((val >> 8) & 0xFF00FF); - return (val << 16) | (val >> 16); -} - -uint64_t swap_uint64(uint64_t val) { - val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL); - val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL); - return (val << 32) | (val >> 32); -} diff --git a/services/hmac/byteswap.h b/services/hmac/byteswap.h deleted file mode 100644 index 2e3f1743f07..00000000000 --- a/services/hmac/byteswap.h +++ /dev/null @@ -1,17 +0,0 @@ -#pragma once - -#include - -/** - * @brief Swap bytes in 32-bit value - * @param val value to swap bytes in - * @return Value with bytes swapped - */ -uint32_t swap_uint32(uint32_t val); - -/** - * @brief Swap bytes in 64-bit value - * @param val value to swap bytes in - * @return Value with bytes swapped - */ -uint64_t swap_uint64(uint64_t val); diff --git a/services/hmac/hmac_common.h b/services/hmac/hmac_common.h deleted file mode 100644 index 3499cb800b8..00000000000 --- a/services/hmac/hmac_common.h +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include "memxor.h" - -#define IPAD 0x36 -#define OPAD 0x5c - -/* Concatenate two preprocessor tokens. */ -#define _GLHMAC_CONCAT_(prefix, suffix) prefix##suffix -#define _GLHMAC_CONCAT(prefix, suffix) _GLHMAC_CONCAT_(prefix, suffix) - -#define HMAC_ALG _GLHMAC_CONCAT(sha, GL_HMAC_NAME) - -#define GL_HMAC_CTX _GLHMAC_CONCAT(HMAC_ALG, _ctx) -#define GL_HMAC_FN _GLHMAC_CONCAT(hmac_, HMAC_ALG) -#define GL_HMAC_FN_INIT _GLHMAC_CONCAT(HMAC_ALG, _init_ctx) -#define GL_HMAC_FN_BLOC _GLHMAC_CONCAT(HMAC_ALG, _process_block) -#define GL_HMAC_FN_PROC _GLHMAC_CONCAT(HMAC_ALG, _process_bytes) -#define GL_HMAC_FN_FINI _GLHMAC_CONCAT(HMAC_ALG, _finish_ctx) - -static void - hmac_hash(const void* key, size_t keylen, const void* in, size_t inlen, int pad, void* resbuf) { - struct GL_HMAC_CTX hmac_ctx; - char block[GL_HMAC_BLOCKSIZE]; - - memset(block, pad, sizeof block); - memxor(block, key, keylen); - - GL_HMAC_FN_INIT(&hmac_ctx); - GL_HMAC_FN_BLOC(block, sizeof block, &hmac_ctx); - GL_HMAC_FN_PROC(in, inlen, &hmac_ctx); - GL_HMAC_FN_FINI(&hmac_ctx, resbuf); -} - -int GL_HMAC_FN(const void* key, size_t keylen, const void* in, size_t inlen, void* resbuf) { - char optkeybuf[GL_HMAC_HASHSIZE]; - char innerhash[GL_HMAC_HASHSIZE]; - - /* Ensure key size is <= block size. */ - if(keylen > GL_HMAC_BLOCKSIZE) { - struct GL_HMAC_CTX keyhash; - - GL_HMAC_FN_INIT(&keyhash); - GL_HMAC_FN_PROC(key, keylen, &keyhash); - GL_HMAC_FN_FINI(&keyhash, optkeybuf); - - key = optkeybuf; - /* zero padding of the key to the block size - is implicit in the memxor. */ - keylen = sizeof optkeybuf; - } - - /* Compute INNERHASH from KEY and IN. */ - hmac_hash(key, keylen, in, inlen, IPAD, innerhash); - - /* Compute result from KEY and INNERHASH. */ - hmac_hash(key, keylen, innerhash, sizeof innerhash, OPAD, resbuf); - - return 0; -} diff --git a/services/hmac/hmac_sha1.c b/services/hmac/hmac_sha1.c deleted file mode 100644 index 0a78d569a69..00000000000 --- a/services/hmac/hmac_sha1.c +++ /dev/null @@ -1,24 +0,0 @@ -/* hmac-sha1.c -- hashed message authentication codes - Copyright (C) 2018-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#include "hmac_sha1.h" - -#include "sha1.h" - -#define GL_HMAC_NAME 1 -#define GL_HMAC_BLOCKSIZE 64 -#define GL_HMAC_HASHSIZE 20 -#include "hmac_common.h" diff --git a/services/hmac/hmac_sha1.h b/services/hmac/hmac_sha1.h deleted file mode 100644 index 25ff2f648a5..00000000000 --- a/services/hmac/hmac_sha1.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -#define HMAC_SHA1_RESULT_SIZE 20 - -/* Compute Hashed Message Authentication Code with SHA-1, over BUFFER - data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the - output to pre-allocated 20 byte minimum RESBUF buffer. Return 0 on - success. */ -int hmac_sha1(const void* key, size_t keylen, const void* in, size_t inlen, void* restrict resbuf); diff --git a/services/hmac/hmac_sha256.c b/services/hmac/hmac_sha256.c deleted file mode 100644 index 00ac2a177ce..00000000000 --- a/services/hmac/hmac_sha256.c +++ /dev/null @@ -1,24 +0,0 @@ -/* hmac-sha256.c -- hashed message authentication codes - Copyright (C) 2018-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#include "hmac_sha256.h" -#include "sha256.h" - -#define GL_HMAC_NAME 256 -#define GL_HMAC_BLOCKSIZE 64 -#define GL_HMAC_HASHSIZE 32 - -#include "hmac_common.h" diff --git a/services/hmac/hmac_sha256.h b/services/hmac/hmac_sha256.h deleted file mode 100644 index 9aeaf10d68f..00000000000 --- a/services/hmac/hmac_sha256.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -#define HMAC_SHA256_RESULT_SIZE 32 - -/* Compute Hashed Message Authentication Code with SHA-256, over BUFFER - data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the - output to pre-allocated 32 byte minimum RESBUF buffer. Return 0 on - success. */ -int hmac_sha256(const void* key, size_t keylen, const void* in, size_t inlen, void* restrict resbuf); diff --git a/services/hmac/hmac_sha512.c b/services/hmac/hmac_sha512.c deleted file mode 100644 index dc9342a91ef..00000000000 --- a/services/hmac/hmac_sha512.c +++ /dev/null @@ -1,24 +0,0 @@ -/* hmac-sha512.c -- hashed message authentication codes - Copyright (C) 2018-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#include "hmac_sha512.h" - -#include "sha512.h" - -#define GL_HMAC_NAME 512 -#define GL_HMAC_BLOCKSIZE 128 -#define GL_HMAC_HASHSIZE 64 -#include "hmac_common.h" diff --git a/services/hmac/hmac_sha512.h b/services/hmac/hmac_sha512.h deleted file mode 100644 index 712b7f4a0dd..00000000000 --- a/services/hmac/hmac_sha512.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once - -#include - -#define HMAC_SHA512_RESULT_SIZE 64 - -/* Compute Hashed Message Authentication Code with SHA-512, over BUFFER - data of BUFLEN bytes using the KEY of KEYLEN bytes, writing the - output to pre-allocated 64 byte minimum RESBUF buffer. Return 0 on - success. */ -int hmac_sha512(const void* key, size_t keylen, const void* in, size_t inlen, void* restrict resbuf); diff --git a/services/hmac/memxor.c b/services/hmac/memxor.c deleted file mode 100644 index ab6026aa321..00000000000 --- a/services/hmac/memxor.c +++ /dev/null @@ -1,30 +0,0 @@ -/* memxor.c -- perform binary exclusive OR operation of two memory blocks. - Copyright (C) 2005, 2006 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Simon Josefsson. The interface was inspired by memxor - in Niels Möller's Nettle. */ - -#include "memxor.h" - -void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n) { - char const* s = (char const*)src; - char* d = (char*)dest; - - for(; n > 0; n--) *d++ ^= *s++; - - return dest; -} diff --git a/services/hmac/memxor.h b/services/hmac/memxor.h deleted file mode 100644 index 71aa604c8a7..00000000000 --- a/services/hmac/memxor.h +++ /dev/null @@ -1,28 +0,0 @@ -/* memxor.h -- perform binary exclusive OR operation on memory blocks. - Copyright (C) 2005 Free Software Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Simon Josefsson. The interface was inspired by memxor - in Niels Möller's Nettle. */ - -#pragma once - -#include - -/* Compute binary exclusive OR of memory areas DEST and SRC, putting - the result in DEST, of length N bytes. Returns a pointer to - DEST. */ -void* memxor(void* /*restrict*/ dest, const void* /*restrict*/ src, size_t n); diff --git a/services/hmac/sha1.c b/services/hmac/sha1.c deleted file mode 100644 index 29f22e3c30c..00000000000 --- a/services/hmac/sha1.c +++ /dev/null @@ -1,251 +0,0 @@ -/* sha1.c - Functions to compute SHA1 message digest of files or - memory blocks according to the NIST specification FIPS-180-1. - - Copyright (C) 2000-2001, 2003-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -/* Written by Scott G. Miller - Credits: - Robert Klep -- Expansion function fix -*/ - -/* Specification. */ -#include "sha1.h" - -#include -#include - -#include "sha_pad_buffer.h" - -#ifdef WORDS_BIGENDIAN -#define SWAP(n) (n) -#else -#include "byteswap.h" -#define SWAP(n) swap_uint32(n) -#endif - -/* Take a pointer to a 160 bit block of data (five 32 bit ints) and - initialize it to the start constants of the SHA1 algorithm. This - must be called before using hash in the call to sha1_hash. */ -void sha1_init_ctx(struct sha1_ctx* ctx) { - ctx->A = 0x67452301; - ctx->B = 0xefcdab89; - ctx->C = 0x98badcfe; - ctx->D = 0x10325476; - ctx->E = 0xc3d2e1f0; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Copy the 4 byte value from v into the memory location pointed to by *cp, - If your architecture allows unaligned access this is equivalent to - * (uint32_t *) cp = v */ -static void set_uint32(char* cp, uint32_t v) { - memcpy(cp, &v, sizeof v); -} - -/* Put result from CTX in first 20 bytes following RESBUF. The result - must be in little endian byte order. */ -void* sha1_read_ctx(const struct sha1_ctx* ctx, void* resbuf) { - char* r = resbuf; - set_uint32(r + 0 * sizeof ctx->A, SWAP(ctx->A)); - set_uint32(r + 1 * sizeof ctx->B, SWAP(ctx->B)); - set_uint32(r + 2 * sizeof ctx->C, SWAP(ctx->C)); - set_uint32(r + 3 * sizeof ctx->D, SWAP(ctx->D)); - set_uint32(r + 4 * sizeof ctx->E, SWAP(ctx->E)); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -void* sha1_finish_ctx(struct sha1_ctx* ctx, void* resbuf) { - /* Take yet unprocessed bytes into account. */ - uint32_t bytes = ctx->buflen; - size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if(ctx->total[0] < bytes) ++ctx->total[1]; - - /* Put the 64-bit file length in *bits* at the end of the buffer. */ - ctx->buffer[size - 2] = SWAP((ctx->total[1] << 3) | (ctx->total[0] >> 29)); - ctx->buffer[size - 1] = SWAP(ctx->total[0] << 3); - - sha_pad_buffer(&((uint8_t*)ctx->buffer)[bytes], (size - 2) * 4 - bytes); - - /* Process last bytes. */ - sha1_process_block(ctx->buffer, size * 4, ctx); - - return sha1_read_ctx(ctx, resbuf); -} - -/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void* sha1_buffer(const char* buffer, size_t len, void* resblock) { - struct sha1_ctx ctx; - - /* Initialize the computation context. */ - sha1_init_ctx(&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - sha1_process_bytes(buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha1_finish_ctx(&ctx, resblock); -} - -void sha1_process_bytes(const void* buffer, size_t len, struct sha1_ctx* ctx) { - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if(ctx->buflen != 0) { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if(ctx->buflen > 64) { - sha1_process_block(ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ - memcpy(ctx->buffer, &((char*)ctx->buffer)[(left_over + add) & ~63], ctx->buflen); - } - - buffer = (const char*)buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if(len >= 64) { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -#define UNALIGNED_P(p) ((uintptr_t)(p) % sizeof(uint32_t) != 0) - if(UNALIGNED_P(buffer)) - while(len > 64) { - sha1_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx); //-V1086 - buffer = (const char*)buffer + 64; - len -= 64; - } - else -#endif - { - sha1_process_block(buffer, len & ~63, ctx); - buffer = (const char*)buffer + (len & ~63); - len &= 63; - } - } - - /* Move remaining bytes in internal buffer. */ - if(len > 0) { - size_t left_over = ctx->buflen; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, len); - left_over += len; - if(left_over >= 64) { - sha1_process_block(ctx->buffer, 64, ctx); - left_over -= 64; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 64. */ - memcpy(ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between md5.c and sha1.c --- */ - -/* SHA1 round constants */ -static const int sha1_round_constants[4] = {0x5a827999, 0x6ed9eba1, 0x8f1bbcdc, 0xca62c1d6}; - -/* Round functions. Note that F2 is the same as F4. */ -#define F1(B, C, D) (D ^ (B & (C ^ D))) -#define F2_4(B, C, D) (B ^ C ^ D) -#define F3(B, C, D) ((B & C) | (D & (B | C))) -#define FN(I, B, C, D) (I == 0 ? F1(B, C, D) : (I == 2 ? F3(B, C, D) : F2_4(B, C, D))) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void sha1_process_block(const void* buffer, size_t len, struct sha1_ctx* ctx) { - const uint32_t* words = buffer; - size_t nwords = len / sizeof(uint32_t); - const uint32_t* endp = words + nwords; - uint32_t x[16]; - uint32_t a = ctx->A; - uint32_t b = ctx->B; - uint32_t c = ctx->C; - uint32_t d = ctx->D; - uint32_t e = ctx->E; - uint32_t lolen = len; - - /* First increment the byte count. RFC 1321 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += lolen; - ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); - -#define rol(x, n) (((x) << (n)) | ((uint32_t)(x) >> (32 - (n)))) - -#define M(I) \ - (tm = x[I & 0x0f] ^ x[(I - 14) & 0x0f] ^ x[(I - 8) & 0x0f] ^ x[(I - 3) & 0x0f], \ - (x[I & 0x0f] = rol(tm, 1))) - -#define R(A, B, C, D, E, F, K, M, KI) \ - do { \ - E += rol(A, 5) + F(KI, B, C, D) + K + M; \ - B = rol(B, 30); \ - } while(0) - - while(words < endp) { - uint32_t tm; - int t; - for(t = 0; t < 16; t++) { - x[t] = SWAP(*words); - words++; - } - - for(uint8_t i = 0; i < 80; i++) { - uint32_t m = i < 16 ? x[i] : M(i); - uint8_t ki = i / 20; - int k_const = sha1_round_constants[ki]; - R(a, b, c, d, e, FN, k_const, m, ki); - uint32_t tt = a; - a = e; - e = d; - d = c; - c = b; - b = tt; - } - - a = ctx->A += a; - b = ctx->B += b; - c = ctx->C += c; - d = ctx->D += d; - e = ctx->E += e; - } -} - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/services/hmac/sha1.h b/services/hmac/sha1.h deleted file mode 100644 index e9eb7712a72..00000000000 --- a/services/hmac/sha1.h +++ /dev/null @@ -1,84 +0,0 @@ -/* Declarations of functions and data types used for SHA1 sum - library functions. - Copyright (C) 2000-2001, 2003, 2005-2006, 2008-2022 Free Software - Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define SHA1_DIGEST_SIZE 20 - -/* Structure to save state of computation between the single steps. */ -struct sha1_ctx { - uint32_t A; - uint32_t B; - uint32_t C; - uint32_t D; - uint32_t E; - - uint32_t total[2]; - uint32_t buflen; /* ≥ 0, ≤ 128 */ - uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ -}; - -/* Initialize structure containing state of computation. */ -extern void sha1_init_ctx(struct sha1_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void sha1_process_block(const void* buffer, size_t len, struct sha1_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void sha1_process_bytes(const void* buffer, size_t len, struct sha1_ctx* ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 20 bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void* sha1_finish_ctx(struct sha1_ctx* ctx, void* restrict resbuf); - -/* Put result from CTX in first 20 bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. */ -extern void* sha1_read_ctx(const struct sha1_ctx* ctx, void* restrict resbuf); - -/* Compute SHA1 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void* sha1_buffer(const char* buffer, size_t len, void* restrict resblock); - -#ifdef __cplusplus -} -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/services/hmac/sha256.c b/services/hmac/sha256.c deleted file mode 100644 index 09ba272e74f..00000000000 --- a/services/hmac/sha256.c +++ /dev/null @@ -1,283 +0,0 @@ -/* sha256.c - Functions to compute SHA256 message digest of files or - memory blocks according to the NIST specification FIPS-180-2. - - Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -/* Written by David Madore, considerably copypasting from - Scott G. Miller's sha1.c -*/ - -/* Specification. */ -#include "sha256.h" - -#include -#include -#include "sha_pad_buffer.h" - -#ifdef WORDS_BIGENDIAN -#define SWAP(n) (n) -#else -#include "byteswap.h" -#define SWAP(n) swap_uint32(n) -#endif - -/* - Takes a pointer to a 256 bit block of data (eight 32 bit ints) and - initializes it to the start constants of the SHA256 algorithm. This - must be called before using hash in the call to sha256_hash -*/ -void sha256_init_ctx(struct sha256_ctx* ctx) { - ctx->state[0] = 0x6a09e667UL; - ctx->state[1] = 0xbb67ae85UL; - ctx->state[2] = 0x3c6ef372UL; - ctx->state[3] = 0xa54ff53aUL; - ctx->state[4] = 0x510e527fUL; - ctx->state[5] = 0x9b05688cUL; - ctx->state[6] = 0x1f83d9abUL; - ctx->state[7] = 0x5be0cd19UL; - - ctx->total[0] = ctx->total[1] = 0; - ctx->buflen = 0; -} - -/* Copy the value from v into the memory location pointed to by *CP, - If your architecture allows unaligned access, this is equivalent to - * (__typeof__ (v) *) cp = v */ -static void set_uint32(char* cp, uint32_t v) { - memcpy(cp, &v, sizeof v); -} - -/* Put result from CTX in first 32 bytes following RESBUF. - The result must be in little endian byte order. */ -void* sha256_read_ctx(const struct sha256_ctx* ctx, void* resbuf) { - int i; - char* r = resbuf; - - for(i = 0; i < 8; i++) set_uint32(r + i * sizeof ctx->state[0], SWAP(ctx->state[i])); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -static void sha256_conclude_ctx(struct sha256_ctx* ctx) { - /* Take yet unprocessed bytes into account. */ - size_t bytes = ctx->buflen; - size_t size = (bytes < 56) ? 64 / 4 : 64 * 2 / 4; - - /* Now count remaining bytes. */ - ctx->total[0] += bytes; - if(ctx->total[0] < bytes) ++ctx->total[1]; - - /* Put the 64-bit file length in *bits* at the end of the buffer. - Use set_uint32 rather than a simple assignment, to avoid risk of - unaligned access. */ - set_uint32((char*)&ctx->buffer[size - 2], SWAP((ctx->total[1] << 3) | (ctx->total[0] >> 29))); - set_uint32((char*)&ctx->buffer[size - 1], SWAP(ctx->total[0] << 3)); - - sha_pad_buffer(&((uint8_t*)ctx->buffer)[bytes], (size - 2) * 4 - bytes); - - /* Process last bytes. */ - sha256_process_block(ctx->buffer, size * 4, ctx); -} - -void* sha256_finish_ctx(struct sha256_ctx* ctx, void* resbuf) { - sha256_conclude_ctx(ctx); - return sha256_read_ctx(ctx, resbuf); -} - -/* Compute SHA256 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void* sha256_buffer(const char* buffer, size_t len, void* resblock) { - struct sha256_ctx ctx; - - /* Initialize the computation context. */ - sha256_init_ctx(&ctx); - - /* Process whole buffer but last len % 64 bytes. */ - sha256_process_bytes(buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha256_finish_ctx(&ctx, resblock); -} - -void sha256_process_bytes(const void* buffer, size_t len, struct sha256_ctx* ctx) { - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if(ctx->buflen != 0) { - size_t left_over = ctx->buflen; - size_t add = 128 - left_over > len ? len : 128 - left_over; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if(ctx->buflen > 64) { - sha256_process_block(ctx->buffer, ctx->buflen & ~63, ctx); - - ctx->buflen &= 63; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 64 ≤ (left_over + add) & ~63. */ - memcpy(ctx->buffer, &((char*)ctx->buffer)[(left_over + add) & ~63], ctx->buflen); - } - - buffer = (const char*)buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if(len >= 64) { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -#define UNALIGNED_P(p) ((uintptr_t)(p) % sizeof(uint32_t) != 0) - if(UNALIGNED_P(buffer)) - while(len > 64) { - sha256_process_block(memcpy(ctx->buffer, buffer, 64), 64, ctx); //-V1086 - buffer = (const char*)buffer + 64; - len -= 64; - } - else -#endif - { - sha256_process_block(buffer, len & ~63, ctx); - buffer = (const char*)buffer + (len & ~63); - len &= 63; - } - } - - /* Move remaining bytes in internal buffer. */ - if(len > 0) { - size_t left_over = ctx->buflen; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, len); - left_over += len; - if(left_over >= 64) { - sha256_process_block(ctx->buffer, 64, ctx); - left_over -= 64; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 64. */ - memcpy(ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between sha1.c and sha256.c --- */ - -/* SHA256 round constants */ -#define K(I) sha256_round_constants[I] -static const uint32_t sha256_round_constants[64] = { - 0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL, 0x59f111f1UL, - 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL, 0x243185beUL, 0x550c7dc3UL, - 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL, 0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, - 0x0fc19dc6UL, 0x240ca1ccUL, 0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, - 0x983e5152UL, 0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL, - 0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL, 0x53380d13UL, - 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL, 0xa2bfe8a1UL, 0xa81a664bUL, - 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL, 0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, - 0x19a4c116UL, 0x1e376c08UL, 0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, - 0x5b9cca4fUL, 0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL, - 0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL, -}; - -/* Round functions. */ -#define F2(A, B, C) ((A & B) | (C & (A | B))) -#define F1(E, F, G) (G ^ (E & (F ^ G))) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 64 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void sha256_process_block(const void* buffer, size_t len, struct sha256_ctx* ctx) { - const uint32_t* words = buffer; - size_t nwords = len / sizeof(uint32_t); - const uint32_t* endp = words + nwords; - uint32_t x[16]; - uint32_t a = ctx->state[0]; - uint32_t b = ctx->state[1]; - uint32_t c = ctx->state[2]; - uint32_t d = ctx->state[3]; - uint32_t e = ctx->state[4]; - uint32_t f = ctx->state[5]; - uint32_t g = ctx->state[6]; - uint32_t h = ctx->state[7]; - uint32_t lolen = len; - - /* First increment the byte count. FIPS PUB 180-2 specifies the possible - length of the file up to 2^64 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] += lolen; - ctx->total[1] += (len >> 31 >> 1) + (ctx->total[0] < lolen); - -#define rol(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) -#define S0(x) (rol(x, 25) ^ rol(x, 14) ^ (x >> 3)) -#define S1(x) (rol(x, 15) ^ rol(x, 13) ^ (x >> 10)) -#define SS0(x) (rol(x, 30) ^ rol(x, 19) ^ rol(x, 10)) -#define SS1(x) (rol(x, 26) ^ rol(x, 21) ^ rol(x, 7)) - -#define M(I) \ - (tm = S1(x[(I - 2) & 0x0f]) + x[(I - 7) & 0x0f] + S0(x[(I - 15) & 0x0f]) + x[I & 0x0f], \ - x[I & 0x0f] = tm) - -#define R(A, B, C, D, E, F, G, H, K, M) \ - do { \ - t0 = SS0(A) + F2(A, B, C); \ - t1 = H + SS1(E) + F1(E, F, G) + K + M; \ - D += t1; \ - H = t0 + t1; \ - } while(0) - - while(words < endp) { - uint32_t tm; - uint32_t t0, t1; - int t; - /* FIXME: see sha1.c for a better implementation. */ - for(t = 0; t < 16; t++) { - x[t] = SWAP(*words); - words++; - } - - for(int i = 0; i < 64; i++) { - uint32_t xx = i < 16 ? x[i] : M(i); - R(a, b, c, d, e, f, g, h, K(i), xx); - uint32_t tt = a; - a = h; - h = g; - g = f; - f = e; - e = d; - d = c; - c = b; - b = tt; - } - - a = ctx->state[0] += a; - b = ctx->state[1] += b; - c = ctx->state[2] += c; - d = ctx->state[3] += d; - e = ctx->state[4] += e; - f = ctx->state[5] += f; - g = ctx->state[6] += g; - h = ctx->state[7] += h; - } -} - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/services/hmac/sha256.h b/services/hmac/sha256.h deleted file mode 100644 index 964f2eb9788..00000000000 --- a/services/hmac/sha256.h +++ /dev/null @@ -1,79 +0,0 @@ -/* Declarations of functions and data types used for SHA256 sum - library functions. - Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#pragma once - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -enum { SHA256_DIGEST_SIZE = 256 / 8 }; - -/* Structure to save state of computation between the single steps. */ -struct sha256_ctx { - uint32_t state[8]; - - uint32_t total[2]; - size_t buflen; /* ≥ 0, ≤ 128 */ - uint32_t buffer[32]; /* 128 bytes; the first buflen bytes are in use */ -}; - -/* Initialize structure containing state of computation. */ -extern void sha256_init_ctx(struct sha256_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 64!!! */ -extern void sha256_process_block(const void* buffer, size_t len, struct sha256_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 64. */ -extern void sha256_process_bytes(const void* buffer, size_t len, struct sha256_ctx* ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 32 (28) bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void* sha256_finish_ctx(struct sha256_ctx* ctx, void* restrict resbuf); - -/* Put result from CTX in first 32 (28) bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. */ -extern void* sha256_read_ctx(const struct sha256_ctx* ctx, void* restrict resbuf); - -/* Compute SHA256 message digest for LEN bytes beginning at BUFFER. - The result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void* sha256_buffer(const char* buffer, size_t len, void* restrict resblock); - -#ifdef __cplusplus -} -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/services/hmac/sha512.c b/services/hmac/sha512.c deleted file mode 100644 index ffe2864fbd9..00000000000 --- a/services/hmac/sha512.c +++ /dev/null @@ -1,309 +0,0 @@ -/* sha512.c - Functions to compute SHA512 message digest of files or - memory blocks according to the NIST specification FIPS-180-2. - - Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -/* Written by David Madore, considerably copypasting from - Scott G. Miller's sha1.c -*/ - -/* Specification. */ -#include "sha512.h" - -#include -#include - -#include "byteswap.h" -#include "sha_pad_buffer.h" - -#define SWAP(n) swap_uint64(n) - -/* - Takes a pointer to a 512 bit block of data (eight 64 bit ints) and - initializes it to the start constants of the SHA512 algorithm. This - must be called before using hash in the call to sha512_hash -*/ -void sha512_init_ctx(struct sha512_ctx* ctx) { - ctx->state[0] = u64hilo(0x6a09e667, 0xf3bcc908); - ctx->state[1] = u64hilo(0xbb67ae85, 0x84caa73b); - ctx->state[2] = u64hilo(0x3c6ef372, 0xfe94f82b); - ctx->state[3] = u64hilo(0xa54ff53a, 0x5f1d36f1); - ctx->state[4] = u64hilo(0x510e527f, 0xade682d1); - ctx->state[5] = u64hilo(0x9b05688c, 0x2b3e6c1f); - ctx->state[6] = u64hilo(0x1f83d9ab, 0xfb41bd6b); - ctx->state[7] = u64hilo(0x5be0cd19, 0x137e2179); - - ctx->total[0] = ctx->total[1] = u64lo(0); - ctx->buflen = 0; -} - -/* Copy the value from V into the memory location pointed to by *CP, - If your architecture allows unaligned access, this is equivalent to - * (__typeof__ (v) *) cp = v */ -static void set_uint64(char* cp, u64 v) { - memcpy(cp, &v, sizeof v); -} - -/* Put result from CTX in first 64 bytes following RESBUF. - The result must be in little endian byte order. */ -void* sha512_read_ctx(const struct sha512_ctx* ctx, void* resbuf) { - int i; - char* r = resbuf; - - for(i = 0; i < 8; i++) set_uint64(r + i * sizeof ctx->state[0], SWAP(ctx->state[i])); - - return resbuf; -} - -/* Process the remaining bytes in the internal buffer and the usual - prolog according to the standard and write the result to RESBUF. */ -static void sha512_conclude_ctx(struct sha512_ctx* ctx) { - /* Take yet unprocessed bytes into account. */ - size_t bytes = ctx->buflen; - size_t size = (bytes < 112) ? 128 / 8 : 128 * 2 / 8; - - /* Now count remaining bytes. */ - ctx->total[0] = u64plus(ctx->total[0], u64lo(bytes)); - if(u64lt(ctx->total[0], u64lo(bytes))) ctx->total[1] = u64plus(ctx->total[1], u64lo(1)); - - /* Put the 128-bit file length in *bits* at the end of the buffer. - Use set_uint64 rather than a simple assignment, to avoid risk of - unaligned access. */ - set_uint64( - (char*)&ctx->buffer[size - 2], - SWAP(u64or(u64shl(ctx->total[1], 3), u64shr(ctx->total[0], 61)))); - set_uint64((char*)&ctx->buffer[size - 1], SWAP(u64shl(ctx->total[0], 3))); - - sha_pad_buffer(&((uint8_t*)ctx->buffer)[bytes], (size - 2) * 8 - bytes); - - /* Process last bytes. */ - sha512_process_block(ctx->buffer, size * 8, ctx); -} - -void* sha512_finish_ctx(struct sha512_ctx* ctx, void* resbuf) { - sha512_conclude_ctx(ctx); - return sha512_read_ctx(ctx, resbuf); -} - -/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. The - result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -void* sha512_buffer(const char* buffer, size_t len, void* resblock) { - struct sha512_ctx ctx; - - /* Initialize the computation context. */ - sha512_init_ctx(&ctx); - - /* Process whole buffer but last len % 128 bytes. */ - sha512_process_bytes(buffer, len, &ctx); - - /* Put result in desired memory area. */ - return sha512_finish_ctx(&ctx, resblock); -} - -void sha512_process_bytes(const void* buffer, size_t len, struct sha512_ctx* ctx) { - /* When we already have some bits in our internal buffer concatenate - both inputs first. */ - if(ctx->buflen != 0) { - size_t left_over = ctx->buflen; - size_t add = 256 - left_over > len ? len : 256 - left_over; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, add); - ctx->buflen += add; - - if(ctx->buflen > 128) { - sha512_process_block(ctx->buffer, ctx->buflen & ~127, ctx); - - ctx->buflen &= 127; - /* The regions in the following copy operation cannot overlap, - because ctx->buflen < 128 ≤ (left_over + add) & ~127. */ - memcpy(ctx->buffer, &((char*)ctx->buffer)[(left_over + add) & ~127], ctx->buflen); - } - - buffer = (const char*)buffer + add; - len -= add; - } - - /* Process available complete blocks. */ - if(len >= 128) { -#if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) -#define UNALIGNED_P(p) ((uintptr_t)(p) % sizeof(u64) != 0) - if(UNALIGNED_P(buffer)) - while(len > 128) { - sha512_process_block(memcpy(ctx->buffer, buffer, 128), 128, ctx); //-V1086 - buffer = (const char*)buffer + 128; - len -= 128; - } - else -#endif - { - sha512_process_block(buffer, len & ~127, ctx); - buffer = (const char*)buffer + (len & ~127); - len &= 127; - } - } - - /* Move remaining bytes in internal buffer. */ - if(len > 0) { - size_t left_over = ctx->buflen; - - memcpy(&((char*)ctx->buffer)[left_over], buffer, len); - left_over += len; - if(left_over >= 128) { - sha512_process_block(ctx->buffer, 128, ctx); - left_over -= 128; - /* The regions in the following copy operation cannot overlap, - because left_over ≤ 128. */ - memcpy(ctx->buffer, &ctx->buffer[16], left_over); - } - ctx->buflen = left_over; - } -} - -/* --- Code below is the primary difference between sha1.c and sha512.c --- */ - -/* SHA512 round constants */ -#define K(I) sha512_round_constants[I] -static u64 const sha512_round_constants[80] = { - u64init(0x428a2f98, 0xd728ae22), u64init(0x71374491, 0x23ef65cd), - u64init(0xb5c0fbcf, 0xec4d3b2f), u64init(0xe9b5dba5, 0x8189dbbc), - u64init(0x3956c25b, 0xf348b538), u64init(0x59f111f1, 0xb605d019), - u64init(0x923f82a4, 0xaf194f9b), u64init(0xab1c5ed5, 0xda6d8118), - u64init(0xd807aa98, 0xa3030242), u64init(0x12835b01, 0x45706fbe), - u64init(0x243185be, 0x4ee4b28c), u64init(0x550c7dc3, 0xd5ffb4e2), - u64init(0x72be5d74, 0xf27b896f), u64init(0x80deb1fe, 0x3b1696b1), - u64init(0x9bdc06a7, 0x25c71235), u64init(0xc19bf174, 0xcf692694), - u64init(0xe49b69c1, 0x9ef14ad2), u64init(0xefbe4786, 0x384f25e3), - u64init(0x0fc19dc6, 0x8b8cd5b5), u64init(0x240ca1cc, 0x77ac9c65), - u64init(0x2de92c6f, 0x592b0275), u64init(0x4a7484aa, 0x6ea6e483), - u64init(0x5cb0a9dc, 0xbd41fbd4), u64init(0x76f988da, 0x831153b5), - u64init(0x983e5152, 0xee66dfab), u64init(0xa831c66d, 0x2db43210), - u64init(0xb00327c8, 0x98fb213f), u64init(0xbf597fc7, 0xbeef0ee4), - u64init(0xc6e00bf3, 0x3da88fc2), u64init(0xd5a79147, 0x930aa725), - u64init(0x06ca6351, 0xe003826f), u64init(0x14292967, 0x0a0e6e70), - u64init(0x27b70a85, 0x46d22ffc), u64init(0x2e1b2138, 0x5c26c926), - u64init(0x4d2c6dfc, 0x5ac42aed), u64init(0x53380d13, 0x9d95b3df), - u64init(0x650a7354, 0x8baf63de), u64init(0x766a0abb, 0x3c77b2a8), - u64init(0x81c2c92e, 0x47edaee6), u64init(0x92722c85, 0x1482353b), - u64init(0xa2bfe8a1, 0x4cf10364), u64init(0xa81a664b, 0xbc423001), - u64init(0xc24b8b70, 0xd0f89791), u64init(0xc76c51a3, 0x0654be30), - u64init(0xd192e819, 0xd6ef5218), u64init(0xd6990624, 0x5565a910), - u64init(0xf40e3585, 0x5771202a), u64init(0x106aa070, 0x32bbd1b8), - u64init(0x19a4c116, 0xb8d2d0c8), u64init(0x1e376c08, 0x5141ab53), - u64init(0x2748774c, 0xdf8eeb99), u64init(0x34b0bcb5, 0xe19b48a8), - u64init(0x391c0cb3, 0xc5c95a63), u64init(0x4ed8aa4a, 0xe3418acb), - u64init(0x5b9cca4f, 0x7763e373), u64init(0x682e6ff3, 0xd6b2b8a3), - u64init(0x748f82ee, 0x5defb2fc), u64init(0x78a5636f, 0x43172f60), - u64init(0x84c87814, 0xa1f0ab72), u64init(0x8cc70208, 0x1a6439ec), - u64init(0x90befffa, 0x23631e28), u64init(0xa4506ceb, 0xde82bde9), - u64init(0xbef9a3f7, 0xb2c67915), u64init(0xc67178f2, 0xe372532b), - u64init(0xca273ece, 0xea26619c), u64init(0xd186b8c7, 0x21c0c207), - u64init(0xeada7dd6, 0xcde0eb1e), u64init(0xf57d4f7f, 0xee6ed178), - u64init(0x06f067aa, 0x72176fba), u64init(0x0a637dc5, 0xa2c898a6), - u64init(0x113f9804, 0xbef90dae), u64init(0x1b710b35, 0x131c471b), - u64init(0x28db77f5, 0x23047d84), u64init(0x32caab7b, 0x40c72493), - u64init(0x3c9ebe0a, 0x15c9bebc), u64init(0x431d67c4, 0x9c100d4c), - u64init(0x4cc5d4be, 0xcb3e42b6), u64init(0x597f299c, 0xfc657e2a), - u64init(0x5fcb6fab, 0x3ad6faec), u64init(0x6c44198c, 0x4a475817), -}; - -/* Round functions. */ -#define F2(A, B, C) u64or(u64and(A, B), u64and(C, u64or(A, B))) -#define F1(E, F, G) u64xor(G, u64and(E, u64xor(F, G))) - -/* Process LEN bytes of BUFFER, accumulating context into CTX. - It is assumed that LEN % 128 == 0. - Most of this code comes from GnuPG's cipher/sha1.c. */ - -void sha512_process_block(const void* buffer, size_t len, struct sha512_ctx* ctx) { - u64 const* words = buffer; - u64 const* endp = words + len / sizeof(u64); - u64 x[16]; - u64 a = ctx->state[0]; - u64 b = ctx->state[1]; - u64 c = ctx->state[2]; - u64 d = ctx->state[3]; - u64 e = ctx->state[4]; - u64 f = ctx->state[5]; - u64 g = ctx->state[6]; - u64 h = ctx->state[7]; - u64 lolen = u64size(len); - - /* First increment the byte count. FIPS PUB 180-2 specifies the possible - length of the file up to 2^128 bits. Here we only compute the - number of bytes. Do a double word increment. */ - ctx->total[0] = u64plus(ctx->total[0], lolen); - ctx->total[1] = u64plus( - ctx->total[1], u64plus(u64size(len >> 31 >> 31 >> 2), u64lo(u64lt(ctx->total[0], lolen)))); - -#define S0(x) u64xor(u64rol(x, 63), u64xor(u64rol(x, 56), u64shr(x, 7))) -#define S1(x) u64xor(u64rol(x, 45), u64xor(u64rol(x, 3), u64shr(x, 6))) -#define SS0(x) u64xor(u64rol(x, 36), u64xor(u64rol(x, 30), u64rol(x, 25))) -#define SS1(x) u64xor(u64rol(x, 50), u64xor(u64rol(x, 46), u64rol(x, 23))) - -#define M(I) \ - (x[(I)&15] = u64plus( \ - x[(I)&15], \ - u64plus(S1(x[((I)-2) & 15]), u64plus(x[((I)-7) & 15], S0(x[((I)-15) & 15]))))) - -#define R(A, B, C, D, E, F, G, H, K, M) \ - do { \ - u64 t0 = u64plus(SS0(A), F2(A, B, C)); \ - u64 t1 = u64plus(H, u64plus(SS1(E), u64plus(F1(E, F, G), u64plus(K, M)))); \ - D = u64plus(D, t1); \ - H = u64plus(t0, t1); \ - } while(0) - - while(words < endp) { - int t; - /* FIXME: see sha1.c for a better implementation. */ - for(t = 0; t < 16; t++) { - x[t] = SWAP(*words); - words++; - } - - for(int i = 0; i < 80; i++) { - u64 xx = i < 16 ? x[i] : M(i); - R(a, b, c, d, e, f, g, h, K(i), xx); - u64 tt = a; - a = h; - h = g; - g = f; - f = e; - e = d; - d = c; - c = b; - b = tt; - } - - a = ctx->state[0] = u64plus(ctx->state[0], a); - b = ctx->state[1] = u64plus(ctx->state[1], b); - c = ctx->state[2] = u64plus(ctx->state[2], c); - d = ctx->state[3] = u64plus(ctx->state[3], d); - e = ctx->state[4] = u64plus(ctx->state[4], e); - f = ctx->state[5] = u64plus(ctx->state[5], f); - g = ctx->state[6] = u64plus(ctx->state[6], g); - h = ctx->state[7] = u64plus(ctx->state[7], h); - } -} - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/services/hmac/sha512.h b/services/hmac/sha512.h deleted file mode 100644 index 38590829e8e..00000000000 --- a/services/hmac/sha512.h +++ /dev/null @@ -1,82 +0,0 @@ -/* Declarations of functions and data types used for SHA512 and SHA384 sum - library functions. - Copyright (C) 2005-2006, 2008-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -#pragma once - -#include -#include "u64.h" - -#ifdef __cplusplus -extern "C" { -#endif - -enum { SHA512_DIGEST_SIZE = 512 / 8 }; - -/* Structure to save state of computation between the single steps. */ -struct sha512_ctx { - u64 state[8]; - - u64 total[2]; - size_t buflen; /* ≥ 0, ≤ 256 */ - u64 buffer[32]; /* 256 bytes; the first buflen bytes are in use */ -}; - -/* Initialize structure containing state of computation. */ -extern void sha512_init_ctx(struct sha512_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is necessary that LEN is a multiple of 128!!! */ -extern void sha512_process_block(const void* buffer, size_t len, struct sha512_ctx* ctx); - -/* Starting with the result of former calls of this function (or the - initialization function update the context for the next LEN bytes - starting at BUFFER. - It is NOT required that LEN is a multiple of 128. */ -extern void sha512_process_bytes(const void* buffer, size_t len, struct sha512_ctx* ctx); - -/* Process the remaining bytes in the buffer and put result from CTX - in first 64 (48) bytes following RESBUF. The result is always in little - endian byte order, so that a byte-wise output yields to the wanted - ASCII representation of the message digest. */ -extern void* sha512_finish_ctx(struct sha512_ctx* ctx, void* restrict resbuf); - -/* Put result from CTX in first 64 (48) bytes following RESBUF. The result is - always in little endian byte order, so that a byte-wise output yields - to the wanted ASCII representation of the message digest. - - IMPORTANT: On some systems it is required that RESBUF is correctly - aligned for a 32 bits value. */ -extern void* sha512_read_ctx(const struct sha512_ctx* ctx, void* restrict resbuf); - -/* Compute SHA512 message digest for LEN bytes beginning at BUFFER. - The result is always in little endian byte order, so that a byte-wise - output yields to the wanted ASCII representation of the message - digest. */ -extern void* sha512_buffer(const char* buffer, size_t len, void* restrict resblock); - -#ifdef __cplusplus -} -#endif - -/* - * Hey Emacs! - * Local Variables: - * coding: utf-8 - * End: - */ diff --git a/services/hmac/sha_pad_buffer.c b/services/hmac/sha_pad_buffer.c deleted file mode 100644 index badedbcc7d3..00000000000 --- a/services/hmac/sha_pad_buffer.c +++ /dev/null @@ -1,11 +0,0 @@ -#include "sha_pad_buffer.h" -#include - -void sha_pad_buffer(uint8_t* buffer, size_t size) { - if(size > 0) { - buffer[0] = 0x80; - if(size > 1) { - memset(&buffer[1], 0, size - 1); - } - } -} \ No newline at end of file diff --git a/services/hmac/sha_pad_buffer.h b/services/hmac/sha_pad_buffer.h deleted file mode 100644 index 7dba40fa968..00000000000 --- a/services/hmac/sha_pad_buffer.h +++ /dev/null @@ -1,4 +0,0 @@ -#include -#include - -void sha_pad_buffer(uint8_t* buffer, size_t size); \ No newline at end of file diff --git a/services/hmac/u64.h b/services/hmac/u64.h deleted file mode 100644 index 91e42e6c991..00000000000 --- a/services/hmac/u64.h +++ /dev/null @@ -1,44 +0,0 @@ -/* uint64_t-like operations that work even on hosts lacking uint64_t - - Copyright (C) 2006, 2009-2022 Free Software Foundation, Inc. - - This file is free software: you can redistribute it and/or modify - it under the terms of the GNU Lesser General Public License as - published by the Free Software Foundation; either version 2.1 of the - License, or (at your option) any later version. - - This file is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with this program. If not, see . */ - -/* Written by Paul Eggert. */ - -#pragma once - -#include - -#ifndef _GL_U64_INLINE -#define _GL_U64_INLINE _GL_INLINE -#endif - -/* Return X rotated left by N bits, where 0 < N < 64. */ -#define u64rol(x, n) u64or(u64shl(x, n), u64shr(x, 64 - (n))) - -/* Native implementations are trivial. See below for comments on what - these operations do. */ -typedef uint64_t u64; -#define u64hilo(hi, lo) ((u64)(((u64)(hi) << 32) + (lo))) -#define u64init(hi, lo) u64hilo(hi, lo) -#define u64lo(x) ((u64)(x)) -#define u64size(x) u64lo(x) -#define u64lt(x, y) ((x) < (y)) -#define u64and(x, y) ((x) & (y)) -#define u64or(x, y) ((x) | (y)) -#define u64xor(x, y) ((x) ^ (y)) -#define u64plus(x, y) ((x) + (y)) -#define u64shl(x, n) ((x) << (n)) -#define u64shr(x, n) ((x) >> (n)) diff --git a/services/totp/totp.c b/services/totp/totp.c index 45a283b066d..04fec08a0a1 100644 --- a/services/totp/totp.c +++ b/services/totp/totp.c @@ -4,12 +4,16 @@ #include #include #include -#include "../hmac/hmac_sha1.h" -#include "../hmac/hmac_sha256.h" -#include "../hmac/hmac_sha512.h" -#include "../hmac/byteswap.h" +#include "../../wolfssl_config.h" +#include -#define HMAC_MAX_RESULT_SIZE HMAC_SHA512_RESULT_SIZE +#define HMAC_MAX_RESULT_SIZE WC_SHA512_DIGEST_SIZE + +static uint64_t swap_uint64(uint64_t val) { + val = ((val << 8) & 0xFF00FF00FF00FF00ULL) | ((val >> 8) & 0x00FF00FF00FF00FFULL); + val = ((val << 16) & 0xFFFF0000FFFF0000ULL) | ((val >> 16) & 0x0000FFFF0000FFFFULL); + return (val << 32) | (val >> 32); +} /** * @brief Generates the timeblock for a time in seconds. @@ -68,14 +72,34 @@ uint64_t totp_at( algo, plain_secret, plain_secret_length, totp_timecode(interval, for_time_adjusted)); } +static int totp_algo_common( + int type, + const uint8_t* key, + size_t key_length, + const uint8_t* input, + size_t input_length, + uint8_t* output) { + Hmac hmac; + int ret = wc_HmacSetKey(&hmac, type, key, key_length); + if(ret == 0) { + ret = wc_HmacUpdate(&hmac, input, input_length); + } + + if(ret == 0) { + ret = wc_HmacFinal(&hmac, output); + } + + wc_HmacFree(&hmac); + return ret == 0 ? wc_HmacSizeByType(type) : 0; +} + static int totp_algo_sha1( const uint8_t* key, size_t key_length, const uint8_t* input, size_t input_length, uint8_t* output) { - hmac_sha1(key, key_length, input, input_length, output); - return HMAC_SHA1_RESULT_SIZE; + return totp_algo_common(WC_SHA, key, key_length, input, input_length, output); } static int totp_algo_sha256( @@ -84,8 +108,7 @@ static int totp_algo_sha256( const uint8_t* input, size_t input_length, uint8_t* output) { - hmac_sha256(key, key_length, input, input_length, output); - return HMAC_SHA256_RESULT_SIZE; + return totp_algo_common(WC_SHA256, key, key_length, input, input_length, output); } static int totp_algo_sha512( @@ -94,8 +117,7 @@ static int totp_algo_sha512( const uint8_t* input, size_t input_length, uint8_t* output) { - hmac_sha512(key, key_length, input, input_length, output); - return HMAC_SHA512_RESULT_SIZE; + return totp_algo_common(WC_SHA512, key, key_length, input, input_length, output); } const TOTP_ALGO TOTP_ALGO_SHA1 = (TOTP_ALGO)(&totp_algo_sha1); diff --git a/totp_app.c b/totp_app.c index 251d7bb5ba2..aed19953317 100644 --- a/totp_app.c +++ b/totp_app.c @@ -18,6 +18,7 @@ #include "services/crypto/crypto_facade.h" #include "cli/cli.h" #include "version.h" +#include struct TotpRenderCallbackContext { FuriMutex* mutex; @@ -218,6 +219,8 @@ int32_t totp_app() { TOTP_APP_VERSION_MAJOR, TOTP_APP_VERSION_MINOR, TOTP_APP_VERSION_PATCH); + FURI_LOG_I(LOGGING_TAG, "WolfSSL version: " LIBWOLFSSL_VERSION_STRING); + PluginState* plugin_state = malloc(sizeof(PluginState)); furi_check(plugin_state != NULL); diff --git a/types/crypto_settings.h b/types/crypto_settings.h index 8b970fd6d84..22daf147e2d 100644 --- a/types/crypto_settings.h +++ b/types/crypto_settings.h @@ -20,9 +20,9 @@ typedef struct { uint8_t iv[CRYPTO_IV_LENGTH]; /** - * @brief Basic randomly-generated initialization vector (IV) + * @brief Randomly-generated salt */ - uint8_t base_iv[CRYPTO_IV_LENGTH]; + uint8_t salt[CRYPTO_SALT_LENGTH]; /** * @brief Encrypted well-known data diff --git a/wolfssl_config.h b/wolfssl_config.h new file mode 100644 index 00000000000..6500d642258 --- /dev/null +++ b/wolfssl_config.h @@ -0,0 +1,34 @@ +#pragma once + +#define NO_OLD_SHA_NAMES +#define WOLFCRYPT_ONLY +#define NO_SIG_WRAPPER +#define NO_AES +#define NO_AES_CBC +#define NO_DES3 +#define NO_DSA +#define NO_RSA +#define NO_DH +#define NO_RC4 +#define NO_MD4 +#define NO_MD5 +#define NO_PKCS12 +#define NO_PKCS8 +#define WC_NO_RNG +#define NO_FILESYSTEM +#define NO_WRITEV +#define NO_MAIN_DRIVER +#define NO_DEV_RANDOM +#define WOLFSSL_SHA512 +#define WOLFSSL_NOSHA512_224 +#define WOLFSSL_NOSHA512_256 +#define USE_SLOW_SHA512 +#define USE_SLOW_SHA256 +#define USE_SLOW_SHA +#define NO_CERTS +#define NO_WOLFSSL_MEMORY +#define WOLFSSL_NO_PEM +#define NO_PSK +#define NO_ERROR_STRINGS +#define NO_OLD_TLS +#define SINGLE_THREADED