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