Alexander Kopachov 2 лет назад
Родитель
Сommit
86a90ab232

+ 12 - 0
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"]
+        ),
     ],
 )

+ 1 - 0
lib/wolfssl

@@ -0,0 +1 @@
+Subproject commit 3b3c175af0e993ffaae251871421e206cc41963f

+ 10 - 9
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;

+ 3 - 3
services/config/constants.h

@@ -2,9 +2,9 @@
 
 #include <storage/storage.h>
 
-#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"

+ 9 - 2
services/config/migrations/common_migration.c

@@ -4,6 +4,8 @@
 #include "../../../types/automation_kb_layout.h"
 #include <flipper_format/flipper_format_i.h>
 
+#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);

+ 3 - 1
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);
 }

+ 2 - 1
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)
+#define CRYPTO_LATEST_VERSION (3)

+ 19 - 0
services/crypto/crypto_facade.c

@@ -3,6 +3,7 @@
 #include <furi/core/check.h>
 #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");
 }

+ 2 - 2
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) {

+ 12 - 9
services/crypto/crypto_v2.c

@@ -5,7 +5,8 @@
 #include <furi_hal_random.h>
 #include <furi_hal_version.h>
 #include "../../types/common.h"
-#include "../hmac/hmac_sha512.h"
+#include "../../wolfssl_config.h"
+#include <wolfssl/wolfcrypt/hmac.h>
 #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;

+ 194 - 0
services/crypto/crypto_v3.c

@@ -0,0 +1,194 @@
+#include "crypto_v3.h"
+#include <stdlib.h>
+#include <furi.h>
+#include <furi_hal_crypto.h>
+#include <furi_hal_random.h>
+#include <furi_hal_version.h>
+#include "../../types/common.h"
+#include "../../wolfssl_config.h"
+#include <wolfssl/wolfcrypt/hmac.h>
+#include <wolfssl/wolfcrypt/pwdbased.h>
+#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;
+}

+ 52 - 0
services/crypto/crypto_v3.h

@@ -0,0 +1,52 @@
+#pragma once
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#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);

+ 0 - 12
services/hmac/byteswap.c

@@ -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);
-}

+ 0 - 17
services/hmac/byteswap.h

@@ -1,17 +0,0 @@
-#pragma once
-
-#include <stdint.h>
-
-/**
- * @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);

+ 0 - 59
services/hmac/hmac_common.h

@@ -1,59 +0,0 @@
-#include <string.h>
-#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;
-}

+ 0 - 24
services/hmac/hmac_sha1.c

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-#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"

+ 0 - 11
services/hmac/hmac_sha1.h

@@ -1,11 +0,0 @@
-#pragma once
-
-#include <stddef.h>
-
-#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);

+ 0 - 24
services/hmac/hmac_sha256.c

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-#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"

+ 0 - 11
services/hmac/hmac_sha256.h

@@ -1,11 +0,0 @@
-#pragma once
-
-#include <stddef.h>
-
-#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);

+ 0 - 24
services/hmac/hmac_sha512.c

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-#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"

+ 0 - 11
services/hmac/hmac_sha512.h

@@ -1,11 +0,0 @@
-#pragma once
-
-#include <stddef.h>
-
-#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);

+ 0 - 30
services/hmac/memxor.c

@@ -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;
-}

+ 0 - 28
services/hmac/memxor.h

@@ -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 <stddef.h>
-
-/* 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);

+ 0 - 251
services/hmac/sha1.c

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-/* Written by Scott G. Miller
-   Credits:
-      Robert Klep <robert@ilse.nl>  -- Expansion function fix
-*/
-
-/* Specification.  */
-#include "sha1.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#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:
- */

+ 0 - 84
services/hmac/sha1.h

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-#pragma once
-
-#include <stdio.h>
-#include <stdint.h>
-
-#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:
- */

+ 0 - 283
services/hmac/sha256.c

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-/* Written by David Madore, considerably copypasting from
-   Scott G. Miller's sha1.c
-*/
-
-/* Specification.  */
-#include "sha256.h"
-
-#include <stdint.h>
-#include <string.h>
-#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:
- */

+ 0 - 79
services/hmac/sha256.h

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-#pragma once
-
-#include <stdio.h>
-#include <stdint.h>
-
-#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:
- */

+ 0 - 309
services/hmac/sha512.c

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-/* Written by David Madore, considerably copypasting from
-   Scott G. Miller's sha1.c
-*/
-
-/* Specification.  */
-#include "sha512.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#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:
- */

+ 0 - 82
services/hmac/sha512.h

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-#pragma once
-
-#include <stdio.h>
-#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:
- */

+ 0 - 11
services/hmac/sha_pad_buffer.c

@@ -1,11 +0,0 @@
-#include "sha_pad_buffer.h"
-#include <string.h>
-
-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);
-        }
-    }
-}

+ 0 - 4
services/hmac/sha_pad_buffer.h

@@ -1,4 +0,0 @@
-#include <stddef.h>
-#include <stdint.h>
-
-void sha_pad_buffer(uint8_t* buffer, size_t size);

+ 0 - 44
services/hmac/u64.h

@@ -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 <https://www.gnu.org/licenses/>.  */
-
-/* Written by Paul Eggert.  */
-
-#pragma once
-
-#include <stdint.h>
-
-#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))

+ 33 - 11
services/totp/totp.c

@@ -4,12 +4,16 @@
 #include <stdint.h>
 #include <math.h>
 #include <timezone_utils.h>
-#include "../hmac/hmac_sha1.h"
-#include "../hmac/hmac_sha256.h"
-#include "../hmac/hmac_sha512.h"
-#include "../hmac/byteswap.h"
+#include "../../wolfssl_config.h"
+#include <wolfssl/wolfcrypt/hmac.h>
 
-#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);

+ 3 - 0
totp_app.c

@@ -18,6 +18,7 @@
 #include "services/crypto/crypto_facade.h"
 #include "cli/cli.h"
 #include "version.h"
+#include <wolfssl/version.h>
 
 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);
 

+ 2 - 2
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

+ 34 - 0
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