diff --git a/repos/gems/lib/mk/aes_cbc_4k.mk b/repos/gems/lib/mk/aes_cbc_4k.mk index 97fdfa630c..e608140e6b 100644 --- a/repos/gems/lib/mk/aes_cbc_4k.mk +++ b/repos/gems/lib/mk/aes_cbc_4k.mk @@ -1,10 +1,9 @@ -SRC_ADB := aes_cbc_4k.adb -LIBS += spark libsparkcrypto +LIBSSL_PORT_DIR = $(call select_from_ports,openssl) -CC_ADA_OPT += -gnatec=$(REP_DIR)/src/lib/aes_cbc_4k/spark.adc +LIBS += libcrypto +SRC_CC += aes_cbc_4k.cc INC_DIR += $(REP_DIR)/src/lib/aes_cbc_4k - -aes_cbc_4k.o : aes_cbc_4k.ads +INC_DIR += $(LIBSSL_PORT_DIR)/include vpath % $(REP_DIR)/src/lib/aes_cbc_4k diff --git a/repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.adb b/repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.adb deleted file mode 100644 index 5903978be7..0000000000 --- a/repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.adb +++ /dev/null @@ -1,100 +0,0 @@ -pragma Ada_2012; - -with LSC.AES_Generic.CBC; -with LSC.SHA2_Generic; -with Ada.Unchecked_Conversion; - -package body Aes_Cbc_4k with SPARK_Mode -is - function Init_IV (Key : Key_Type; Block_Number : Block_Number_Type) - return Ciphertext_Base_Type - with post => Init_IV'Result'Length = 16; - - function Init_IV (Key : Key_Type; Block_Number : Block_Number_Type) - return Ciphertext_Base_Type - is - - type IV_Key_Base_Type is array (Natural range <>) of Byte; - subtype IV_Key_Index_Type is Natural range 1 .. 32; - subtype IV_Key_Type is IV_Key_Base_Type (IV_Key_Index_Type); - - function Hash is new LSC.SHA2_Generic.Hash_SHA256 - (Natural, Byte, Key_Base_Type, IV_Key_Index_Type, Byte, IV_Key_Type); - - type Padding_Type is array (Natural range <>) of Byte; - type Block_Number_Text_Type is record - Block_Number : Block_Number_Type; - Padding : Padding_Type (1 .. 8); - end record - with Size => 128; - - Block_Number_Text : constant Block_Number_Text_Type := - (Block_Number => Block_Number, Padding => (others => 0)); - - type Block_Number_Plaintext_Base_Type - is array (Natural range <>) of Byte; - - subtype Block_Number_Plaintext_Index_Type is Natural range 1 .. 16; - - subtype Block_Number_Plaintext_Type - is Block_Number_Plaintext_Base_Type (Block_Number_Plaintext_Index_Type); - - function Convert is new Ada.Unchecked_Conversion - (Block_Number_Text_Type, Block_Number_Plaintext_Type); - - function Enc_Key is new LSC.AES_Generic.Enc_Key - (Natural, Byte, IV_Key_Base_Type); - - function Encrypt is new LSC.AES_Generic.Encrypt - (Natural, Byte, Block_Number_Plaintext_Base_Type, Natural, Byte, - Ciphertext_Base_Type); - - begin - return - Encrypt ( - Plaintext => Convert (Block_Number_Text), - Key => Enc_Key (Hash (Key), LSC.AES_Generic.L256)) - (Natural'First .. Natural'First + 15); - end Init_IV; - - procedure Encrypt (Key : Key_Type; - Block_Number : Block_Number_Type; - Plaintext : Plaintext_Type; - Ciphertext : out Ciphertext_Type) - is - function Enc_Key is new LSC.AES_Generic.Enc_Key - (Natural, Byte, Key_Base_Type); - - procedure Encrypt is new LSC.AES_Generic.CBC.Encrypt - (Natural, Byte, Plaintext_Base_Type, Natural, Byte, - Ciphertext_Base_Type); - - IV : constant Ciphertext_Base_Type := Init_IV (Key, Block_Number); - begin - - Encrypt (Plaintext => Plaintext, - IV => IV, - Key => Enc_Key (Key, LSC.AES_Generic.L256), - Ciphertext => Ciphertext); - end Encrypt; - - procedure Decrypt (Key : Key_Type; - Block_Number : Block_Number_Type; - Ciphertext : Ciphertext_Type; - Plaintext : out Plaintext_Type) - is - function Dec_Key is new LSC.AES_Generic.Dec_Key - (Natural, Byte, Key_Base_Type); - - procedure Decrypt is new LSC.AES_Generic.CBC.Decrypt - (Natural, Byte, Plaintext_Base_Type, Natural, Byte, - Ciphertext_Base_Type); - - begin - Decrypt (Ciphertext => Ciphertext, - IV => Init_IV (Key, Block_Number), - Key => Dec_Key (Key, LSC.AES_Generic.L256), - Plaintext => Plaintext); - end Decrypt; - -end Aes_Cbc_4k; diff --git a/repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.ads b/repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.ads deleted file mode 100644 index 62a65aadeb..0000000000 --- a/repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.ads +++ /dev/null @@ -1,39 +0,0 @@ -package Aes_Cbc_4k with SPARK_Mode -is - - -- pragma Pure; -- not possible because libsparkcrypto is not known as pure - - type Byte is mod 2**8 with Size => 8; - type Key_Base_Type is array (Natural range <>) of Byte; - subtype Key_Type is Key_Base_Type (1 .. 32); - type Block_Number_Type is mod 2**64 with Size => 64; - - type Plaintext_Base_Type is array (Natural range <>) of Byte; - subtype Plaintext_Index_Type is Natural range 1 .. 4096; - subtype Plaintext_Type is Plaintext_Base_Type (Plaintext_Index_Type); - - type Ciphertext_Base_Type is array (Natural range <>) of Byte; - subtype Ciphertext_Index_Type is Natural range 1 .. 4096; - subtype Ciphertext_Type is Ciphertext_Base_Type (Ciphertext_Index_Type); - - procedure Encrypt (Key : Key_Type; - Block_Number : Block_Number_Type; - Plaintext : Plaintext_Type; - Ciphertext : out Ciphertext_Type) - with Export, - Convention => C, - External_Name => - "_ZN10Aes_cbc_4k7encryptERKNS_3KeyENS_12Block_numberERKNS_" & - "9PlaintextERNS_10CiphertextE"; - - procedure Decrypt (Key : Key_Type; - Block_Number : Block_Number_Type; - Ciphertext : Ciphertext_Type; - Plaintext : out Plaintext_Type) - with Export, - Convention => C, - External_Name => - "_ZN10Aes_cbc_4k7decryptERKNS_3KeyENS_12Block_numberERKNS_" & - "10CiphertextERNS_9PlaintextE"; - -end Aes_Cbc_4k; diff --git a/repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.cc b/repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.cc new file mode 100644 index 0000000000..936c590cba --- /dev/null +++ b/repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.cc @@ -0,0 +1,166 @@ +/* + * \brief Using libcrypto/openssl to implement aes_cbc_4k interface + * \author Alexander Boettcher + * \date 2020-09-24 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#include +#include + +#include + +#include +#include + +namespace Aes_cbc +{ + /* an enum by the OpenSSL library about the size of IV would be nice ! */ + struct Iv { + unsigned char values[16]; + }; + + struct Sn { + unsigned char values[sizeof(Iv::values)] { }; /* zero initialized */ + + Sn(Aes_cbc_4k::Block_number const &nr) { + reinterpret_cast(values) = nr.value; } + }; + + struct Hash { + unsigned char values[SHA256_DIGEST_LENGTH]; + }; +}; + +static bool hash_key(Aes_cbc_4k::Key const &key, Aes_cbc::Hash &hash) +{ + static_assert(sizeof(key.values) == sizeof(hash.values), + "-key- size vs -hash- size mismatch"); + + SHA256_CTX context; + if (!SHA256_Init(&context)) + return false; + + if (!SHA256_Update(&context, key.values, sizeof(key.values))) + return false; + + if (!SHA256_Final(hash.values, &context)) + return false; + + return true; +} + +/* + * clean up crypto temporary crypto data on stack + */ +template +static void inline cleanup_crypto_data(T &t) +{ + Genode::memset(&t, 0, sizeof(t)); + /* trigger compiler to not drop the memset */ + asm volatile(""::"r"(&t):"memory"); +} + +template +static void inline cleanup_crypto_data(T &t, S &s) +{ + Genode::memset(&t, 0, sizeof(t)); + Genode::memset(&s, 0, sizeof(s)); + /* trigger compiler to not drop the memsets */ + asm volatile(""::"r"(&t),"r"(&s):"memory"); +} + +/** + * Calculate initialization vector (IV) according to + * "Encrypted salt-sector initialization vector" (ESSIV) algorithm + * by Clemens Fruhwirth (July 18, 2005) published in + * "New Methods in Hard Disk Encryption" paper. + */ +static bool calculate_iv(Aes_cbc_4k::Key const &key, + Aes_cbc_4k::Block_number const &block, + Aes_cbc::Iv &cipher_iv) +{ + Aes_cbc::Hash hash_of_key; + if (!hash_key(key, hash_of_key)) + return false; + + AES_KEY key_for_iv; + if (AES_set_encrypt_key(hash_of_key.values, sizeof(hash_of_key.values) * 8, + &key_for_iv)) { + /* clean up crypto relevant data which stays otherwise on stack */ + cleanup_crypto_data(hash_of_key); + return false; + } + + Aes_cbc::Sn const plain { block }; + Aes_cbc::Iv ivec { }; /* zero IV */ + + static_assert(sizeof(plain.values) == sizeof(cipher_iv.values), + "-plain- size vs -iv- size mismatch"); + + AES_cbc_encrypt(plain.values, cipher_iv.values, sizeof(plain.values), + &key_for_iv, ivec.values, AES_ENCRYPT); + + cleanup_crypto_data(hash_of_key, key_for_iv); + + return true; +} + +void Aes_cbc_4k::encrypt(Key const &key, Block_number const block_number, + Plaintext const &plain, Ciphertext &cipher) +{ + static_assert(sizeof(plain.values) == 4096, "Plain text size mismatch"); + static_assert(sizeof(cipher.values) == 4096, "Cipher size mismatch"); + static_assert(sizeof(key.values) == 32, "Key size mismatch"); + + AES_KEY aes_key; + if (AES_set_encrypt_key(reinterpret_cast(key.values), + sizeof(key.values) * 8, &aes_key)) { + Genode::error("setting encrypt key"); + return; + } + + Aes_cbc::Iv iv; + if (!calculate_iv(key, block_number, iv)) { + Genode::error("iv calculation"); + cleanup_crypto_data(aes_key); + return; + } + + AES_cbc_encrypt(reinterpret_cast(plain.values), + reinterpret_cast(cipher.values), + sizeof(cipher.values), &aes_key, iv.values, AES_ENCRYPT); + + /* clean up crypto relevant data which stays otherwise on stack */ + cleanup_crypto_data(aes_key, iv); +} + +void Aes_cbc_4k::decrypt(Key const &key, Block_number const block_number, + Ciphertext const &cipher, Plaintext &plain) +{ + AES_KEY aes_key; + if (AES_set_decrypt_key(reinterpret_cast(key.values), + sizeof(key.values) * 8, &aes_key)) { + Genode::error("setting decrypt key"); + return; + } + + Aes_cbc::Iv iv; + if (!calculate_iv(key, block_number, iv)) { + Genode::error("iv calculation"); + cleanup_crypto_data(aes_key); + return; + } + + AES_cbc_encrypt(reinterpret_cast(cipher.values), + reinterpret_cast(plain.values), + sizeof(plain.values), &aes_key, iv.values, AES_DECRYPT); + + cleanup_crypto_data(aes_key, iv); +} diff --git a/repos/gems/src/lib/aes_cbc_4k/spark.adc b/repos/gems/src/lib/aes_cbc_4k/spark.adc deleted file mode 100644 index c1f72d5b92..0000000000 --- a/repos/gems/src/lib/aes_cbc_4k/spark.adc +++ /dev/null @@ -1,2 +0,0 @@ -pragma SPARK_Mode (On); -pragma Check_Policy (Debug, Disable);