mirror of
https://github.com/genodelabs/genode.git
synced 2025-04-11 05:12:05 +00:00
parent
5d808cdc01
commit
c0f8022a78
@ -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
|
||||
|
@ -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;
|
@ -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;
|
166
repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.cc
Normal file
166
repos/gems/src/lib/aes_cbc_4k/aes_cbc_4k.cc
Normal file
@ -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 <base/log.h>
|
||||
#include <util/string.h>
|
||||
|
||||
#include <aes_cbc_4k/aes_cbc_4k.h>
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/sha.h>
|
||||
|
||||
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<Genode::uint64_t &>(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 <typename T>
|
||||
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 <typename T, typename S>
|
||||
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<unsigned char const *>(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<unsigned char const *>(plain.values),
|
||||
reinterpret_cast<unsigned char *>(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<unsigned char const *>(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<unsigned char const *>(cipher.values),
|
||||
reinterpret_cast<unsigned char *>(plain.values),
|
||||
sizeof(plain.values), &aes_key, iv.values, AES_DECRYPT);
|
||||
|
||||
cleanup_crypto_data(aes_key, iv);
|
||||
}
|
@ -1,2 +0,0 @@
|
||||
pragma SPARK_Mode (On);
|
||||
pragma Check_Policy (Debug, Disable);
|
Loading…
x
Reference in New Issue
Block a user