gems: import Genode-specific code of the CBE

The CBE repository contained a lot of Genode-specific code despite the fact
that the CBE core logic is not bound to Genode in any way. Therefore the
Genode-specific CBE code is moved to the 'gems' repository to form part of
Genode mainline. The remaining CBE code becomes a port in Genode instead of
being invoked as sub-repository.

The commit combines the following work steps:

* add all files removed from CBE repository
* add CBE port files
* make all CBE libs and targets build again
* make all CBE run scripts succeed again
* make all CBE recipes build again
* make CBE autopilot succeed again
* let CBE autopilot use 'libsparcrypto' contrib dir and Genode build dir
  instead of '.ci' dir in CBE contrib dir (remove '.ci' dir from CBE repo)
* let CBE autopilot always check for all ports
* make CBE autopilot directly executable
* fix license headers in all Genode CBE files
* remove unused VFS replay component
* remove unused CBE test
* remove unused external crypto
* remove unused files in run dir
* remove unused external trust anchor
* add cbe_tester test to autopilot list
* get rid of directories 'include/cbe_*' and 'include/utils'

Fixes #3937
This commit is contained in:
Martin Stein
2020-11-10 11:57:26 +01:00
committed by Christian Helmuth
parent 24181f2bf6
commit 30b8f4efc8
136 changed files with 18863 additions and 0 deletions

View File

@ -0,0 +1,17 @@
--
-- \brief Integration of the Consistent Block Encrypter (CBE)
-- \author Martin Stein
-- \author Josef Soentgen
-- \date 2020-11-10
--
--
-- 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.
--
package Dummy
is
end Dummy;

View File

@ -0,0 +1,297 @@
/*
* \brief Integration of the Consistent Block Encrypter (CBE)
* \author Martin Stein
* \author Josef Soentgen
* \date 2020-11-10
*/
/*
* 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.
*/
#ifndef _CBE_VFS__IO_JOB_
#define _CBE_VFS__IO_JOB_
namespace Vfs_cbe {
using file_size = Vfs::file_size;
using file_offset = Vfs::file_offset;
struct Io_job
{
struct Unsupported_Operation : Genode::Exception { };
struct Invalid_state : Genode::Exception { };
enum State { PENDING, IN_PROGRESS, COMPLETE, };
static State _initial_state(Cbe::Request::Operation const op)
{
using Op = Cbe::Request::Operation;
switch (op) {
case Op::READ: return State::PENDING;
case Op::WRITE: return State::PENDING;
case Op::SYNC: return State::PENDING;
default: throw Unsupported_Operation();
}
}
static char const *_state_to_string(State s)
{
switch (s) {
case State::PENDING: return "PENDING";
case State::IN_PROGRESS: return "IN_PROGRESS";
case State::COMPLETE: return "COMPLETE";
}
throw Invalid_state();
}
Vfs::Vfs_handle &_handle;
Cbe::Request::Operation const _op;
Cbe::Io_buffer::Index const _index;
State _state;
file_offset const _base_offset;
file_offset _current_offset;
file_size _current_count;
bool _success;
bool _complete;
bool _read(Cbe::Library &cbe, Cbe::Io_buffer &io_data)
{
bool progress = false;
switch (_state) {
case State::PENDING:
_handle.seek(_base_offset + _current_offset);
if (!_handle.fs().queue_read(&_handle, _current_count)) {
return progress;
}
cbe.io_request_in_progress(_index);
_state = State::IN_PROGRESS;
progress = true;
[[fallthrough]];
case State::IN_PROGRESS:
{
using Result = Vfs::File_io_service::Read_result;
bool completed = false;
file_size out = 0;
char * const data = reinterpret_cast<char *const>(&io_data.item(_index));
Result const result =
_handle.fs().complete_read(&_handle,
data + _current_offset,
_current_count, out);
if ( result == Result::READ_QUEUED
|| result == Result::READ_ERR_INTERRUPT
|| result == Result::READ_ERR_AGAIN
|| result == Result::READ_ERR_WOULD_BLOCK) {
return progress;
} else
if (result == Result::READ_OK) {
_current_offset += out;
_current_count -= out;
_success = true;
} else
if ( result == Result::READ_ERR_IO
|| result == Result::READ_ERR_INVALID) {
_success = false;
completed = true;
}
if (_current_count == 0 || completed) {
_state = State::COMPLETE;
} else {
_state = State::PENDING;
/* partial read, keep trying */
return true;
}
progress = true;
}
[[fallthrough]];
case State::COMPLETE:
cbe.io_request_completed(_index, _success);
_complete = true;
progress = true;
default: break;
}
return progress;
}
bool _write(Cbe::Library &cbe, Cbe::Io_buffer &io_data)
{
bool progress = false;
switch (_state) {
case State::PENDING:
_handle.seek(_base_offset + _current_offset);
cbe.io_request_in_progress(_index);
_state = State::IN_PROGRESS;
progress = true;
[[fallthrough]];
case State::IN_PROGRESS:
{
using Result = Vfs::File_io_service::Write_result;
bool completed = false;
file_size out = 0;
Result result = Result::WRITE_ERR_INVALID;
try {
char const * const data =
reinterpret_cast<char const * const>(&io_data.item(_index));
result = _handle.fs().write(&_handle,
data + _current_offset,
_current_count, out);
} catch (Vfs::File_io_service::Insufficient_buffer) {
return progress;
}
if ( result == Result::WRITE_ERR_AGAIN
|| result == Result::WRITE_ERR_INTERRUPT
|| result == Result::WRITE_ERR_WOULD_BLOCK) {
return progress;
} else
if (result == Result::WRITE_OK) {
_current_offset += out;
_current_count -= out;
_success = true;
} else
if ( result == Result::WRITE_ERR_IO
|| result == Result::WRITE_ERR_INVALID) {
_success = false;
completed = true;
}
if (_current_count == 0 || completed) {
_state = State::COMPLETE;
} else {
_state = State::PENDING;
/* partial write, keep trying */
return true;
}
progress = true;
}
[[fallthrough]];
case State::COMPLETE:
cbe.io_request_completed(_index, _success);
_complete = true;
progress = true;
default: break;
}
return progress;
}
bool _sync(Cbe::Library &cbe, Cbe::Io_buffer &io_data)
{
bool progress = false;
switch (_state) {
case State::PENDING:
if (!_handle.fs().queue_sync(&_handle)) {
return progress;
}
cbe.io_request_in_progress(_index);
_state = State::IN_PROGRESS;
progress = true;
[[fallthrough]];
case State::IN_PROGRESS:
{
using Result = Vfs::File_io_service::Sync_result;
Result const result = _handle.fs().complete_sync(&_handle);
if (result == Result::SYNC_QUEUED) {
return progress;
} else
if (result == Result::SYNC_ERR_INVALID) {
_success = false;
} else
if (result == Result::SYNC_OK) {
_success = true;
}
_state = State::COMPLETE;
progress = true;
}
[[fallthrough]];
case State::COMPLETE:
cbe.io_request_completed(_index, _success);
_complete = true;
progress = true;
default: break;
}
return progress;
}
Io_job(Vfs::Vfs_handle &handle,
Cbe::Request::Operation op,
Cbe::Io_buffer::Index index,
file_offset base_offset,
file_size length)
:
_handle { handle },
_op { op },
_index { index },
_state { _initial_state(op) },
_base_offset { base_offset },
_current_offset { 0 },
_current_count { length },
_success { false },
_complete { false }
{ }
bool completed() const { return _complete; }
bool succeeded() const { return _success; }
void print(Genode::Output &out) const
{
Genode::print(out, "(", to_string(_op), ")",
" state: ", _state_to_string(_state),
" base_offset: ", _base_offset,
" current_offset: ", _current_offset,
" current_count: ", _current_count,
" success: ", _success,
" complete: ", _complete);
}
bool execute(Cbe::Library &cbe, Cbe::Io_buffer &io_data)
{
using Op = Cbe::Request::Operation;
switch (_op) {
case Op::READ: return _read(cbe, io_data);
case Op::WRITE: return _write(cbe, io_data);
case Op::SYNC: return _sync(cbe, io_data);
default: return false;
}
}
};
} /* namespace Vfs_cbe */
#endif /* _CBE_VFS__IO_JOB_ */

View File

@ -0,0 +1,3 @@
TARGET := lib-vfs-cbe
REQUIRES = x86_64
LIBS = vfs_cbe

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,284 @@
/*
* \brief Integration of the Consistent Block Encrypter (CBE)
* \author Martin Stein
* \author Josef Soentgen
* \date 2020-11-10
*/
/*
* 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 <cbe/types.h>
#include <cbe/crypto/interface.h>
namespace {
using namespace Genode;
struct Crypto : Cbe_crypto::Interface
{
struct Buffer_size_mismatch : Genode::Exception { };
struct Key_value_size_mismatch : Genode::Exception { };
struct {
uint32_t id { };
Aes_cbc_4k::Key key { };
bool used { false };
} keys [Slots::NUM_SLOTS];
struct {
struct crypt_ring {
unsigned head { 0 };
unsigned tail { 0 };
struct {
Cbe::Request request { };
Cbe::Block_data data { };
} queue [4];
unsigned max() const {
return sizeof(queue) / sizeof(queue[0]); }
bool acceptable() const {
return ((head + 1) % max() != tail); }
template <typename FUNC>
bool enqueue(FUNC const &fn)
{
if (!acceptable())
return false;
fn(queue[head]);
head = (head + 1) % max();
return true;
}
template <typename FUNC>
bool apply_crypt(FUNC const &fn)
{
if (head == tail)
return false;
if (!fn(queue[tail]))
return false;
tail = (tail + 1) % max();
return true;
}
};
struct crypt_ring encrypt;
struct crypt_ring decrypt;
template <typename FUNC>
bool queue_encrypt(FUNC const &fn) { return encrypt.enqueue(fn); }
template <typename FUNC>
bool apply_encrypt(FUNC const &fn) { return encrypt.apply_crypt(fn); }
template <typename FUNC>
bool queue_decrypt(FUNC const &fn) { return decrypt.enqueue(fn); }
template <typename FUNC>
bool apply_decrypt(FUNC const &fn) { return decrypt.apply_crypt(fn); }
} jobs { };
template <typename FUNC>
bool apply_to_unused_key(FUNC const &fn)
{
for (unsigned i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
if (keys[i].used) continue;
return fn(keys[i]);
}
return false;
}
template <typename FUNC>
bool apply_key(uint32_t const id, FUNC const &fn)
{
for (unsigned i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) {
if (!keys[i].used || id != keys[i].id) continue;
return fn(keys[i]);
}
return false;
}
Crypto() { }
/***************
** interface **
***************/
bool execute() override
{
return true;
}
bool add_key(uint32_t const id,
char const * const value,
size_t value_len) override
{
return apply_to_unused_key([&](auto &key_slot) {
if (value_len != sizeof(key_slot.key))
return false;
if (!_slots.store(id))
return false;
Genode::memcpy(key_slot.key.values, value, sizeof(key_slot.key));
key_slot.id = id;
key_slot.used = true;
return true;
});
}
bool remove_key(uint32_t const id) override
{
return apply_key (id, [&] (auto &meta) {
Genode::memset(meta.key.values, 0, sizeof(meta.key.values));
meta.used = false;
_slots.remove(id);
return true;
});
}
bool submit_encryption_request(uint64_t const block_number,
uint32_t const key_id,
char const *src,
size_t const src_len) override
{
if (!src || src_len != sizeof (Cbe::Block_data)) {
error("buffer has wrong size");
throw Buffer_size_mismatch();
}
if (!jobs.encrypt.acceptable())
return false;
return apply_key (key_id, [&] (auto &meta) {
return jobs.queue_encrypt([&] (auto &job) {
job.request = Cbe::Request(Cbe::Request::Operation::WRITE,
false, block_number, 0, 1, key_id, 0);
uint64_t block_id = job.request.block_number();
Aes_cbc_4k::Block_number block_number { block_id };
Aes_cbc_4k::Plaintext const &plaintext = *reinterpret_cast<Aes_cbc_4k::Plaintext const *>(src);
Aes_cbc_4k::Ciphertext &ciphertext = *reinterpret_cast<Aes_cbc_4k::Ciphertext *>(&job.data);
/* paranoia */
static_assert(sizeof(plaintext) == sizeof(job.data), "size mismatch");
Aes_cbc_4k::encrypt(meta.key, block_number, plaintext, ciphertext);
});
});
}
Complete_request encryption_request_complete(char * const dst,
size_t const dst_len) override
{
static_assert(sizeof(Cbe::Block_data) == sizeof(Aes_cbc_4k::Ciphertext), "size mismatch");
static_assert(sizeof(Cbe::Block_data) == sizeof(Aes_cbc_4k::Plaintext), "size mismatch");
if (dst_len != sizeof (Cbe::Block_data)) {
error("buffer has wrong size");
throw Buffer_size_mismatch();
}
uint64_t block_id = 0;
bool const valid = jobs.apply_encrypt([&](auto const &job) {
Genode::memcpy(dst, &job.data, sizeof(job.data));
block_id = job.request.block_number();
return true;
});
return Complete_request { .valid = valid,
.block_number = block_id };
}
bool submit_decryption_request(uint64_t const block_number,
uint32_t const key_id,
char const *src,
size_t const src_len) override
{
if (src_len != sizeof (Cbe::Block_data)) {
error("buffer has wrong size");
throw Buffer_size_mismatch();
}
if (!jobs.decrypt.acceptable())
return false;
/* use apply_key to make sure key_id is actually known */
return apply_key (key_id, [&] (auto &) {
return jobs.queue_decrypt([&] (auto &job) {
job.request = Cbe::Request(Cbe::Request::Operation::READ,
false, block_number, 0, 1, key_id, 0);
Genode::memcpy(&job.data, src, sizeof(job.data));
});
});
}
Complete_request decryption_request_complete(char *dst, size_t dst_len) override
{
static_assert(sizeof(Cbe::Block_data) == sizeof(Aes_cbc_4k::Ciphertext), "size mismatch");
static_assert(sizeof(Cbe::Block_data) == sizeof(Aes_cbc_4k::Plaintext), "size mismatch");
if (dst_len != sizeof (Cbe::Block_data)) {
error("buffer has wrong size");
throw Buffer_size_mismatch();
}
uint64_t block_id = 0;
bool const valid = jobs.apply_decrypt([&](auto const &job) {
bool ok = apply_key (job.request.key_id(), [&] (auto &meta) {
block_id = job.request.block_number();
Aes_cbc_4k::Block_number block_number { block_id };
Aes_cbc_4k::Ciphertext const &ciphertext = *reinterpret_cast<Aes_cbc_4k::Ciphertext const *>(&job.data);
Aes_cbc_4k::Plaintext &plaintext = *reinterpret_cast<Aes_cbc_4k::Plaintext *>(dst);
/* paranoia */
static_assert(sizeof(ciphertext) == sizeof(job.data), "size mismatch");
Aes_cbc_4k::decrypt(meta.key, block_number, ciphertext, plaintext);
return true;
});
return ok;
});
return Complete_request { .valid = valid,
.block_number = block_id };
}
};
} /* anonymous namespace */
Cbe_crypto::Interface &Cbe_crypto::get_interface()
{
static Crypto inst;
return inst;
}

View File

@ -0,0 +1,17 @@
--
-- \brief Integration of the Consistent Block Encrypter (CBE)
-- \author Martin Stein
-- \author Josef Soentgen
-- \date 2020-11-10
--
--
-- 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.
--
package Dummy
is
end Dummy;

View File

@ -0,0 +1,3 @@
TARGET := lib-vfs-cbe_crypto-aes_cbc
REQUIRES = x86_64
LIBS = vfs_cbe_crypto_aes_cbc

View File

@ -0,0 +1,141 @@
/*
* \brief Integration of the Consistent Block Encrypter (CBE)
* \author Martin Stein
* \author Josef Soentgen
* \date 2020-11-10
*/
/*
* 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.
*/
/* Genode includes */
#include <base/log.h>
#include <util/string.h>
/* cbe_crypto includes */
#include <cbe/crypto/interface.h>
namespace {
using namespace Genode;
struct Crypto : Cbe_crypto::Interface
{
char _internal_buffer[Cbe_crypto::BLOCK_SIZE] { };
struct Request
{
uint64_t block_number;
bool pending;
};
Request _request { 0, false };
Crypto() { }
/***************
** interface **
***************/
bool execute() override
{
return false;
}
bool add_key(uint32_t const id, char const *, size_t) override
{
if (!_slots.store(id)) {
return false;
}
log("Add key: id " , id);
return true;
}
bool remove_key(uint32_t const id) override
{
log("Remove key: id " , id);
_slots.remove(id);
return true;
}
bool _submit_request(uint64_t const block_number,
uint32_t const /* key_id */,
char const *src,
size_t const src_len)
{
if (_request.pending) {
return false;
}
if (src_len < sizeof (_internal_buffer)) {
error("buffer too small");
throw Buffer_too_small();
}
_request.pending = true;
_request.block_number = block_number;
Genode::memcpy(_internal_buffer, src, sizeof (_internal_buffer));
return true;
}
bool submit_encryption_request(uint64_t const block_number,
uint32_t const key_id,
char const *src,
size_t const src_len) override
{
return _submit_request(block_number, key_id, src, src_len);
}
Complete_request _request_complete(char *dst, size_t const dst_len)
{
if (!_request.pending) {
return Complete_request { .valid = false, .block_number = 0 };
}
if (dst_len < sizeof (_internal_buffer)) {
error("buffer too small");
throw Buffer_too_small();
}
Genode::memcpy(dst, _internal_buffer, sizeof (_internal_buffer));
_request.pending = false;
return Complete_request {
.valid = true,
.block_number = _request.block_number };
}
Complete_request encryption_request_complete(char *dst, size_t const dst_len) override
{
return _request_complete(dst, dst_len);
}
bool submit_decryption_request(uint64_t const block_number,
uint32_t const key_id,
char const *src,
size_t const src_len) override
{
return _submit_request(block_number, key_id, src, src_len);
}
Complete_request decryption_request_complete(char *dst, size_t dst_len) override
{
return _request_complete(dst, dst_len);
}
};
} /* anonymous namespace */
Cbe_crypto::Interface &Cbe_crypto::get_interface()
{
static Crypto inst;
return inst;
}

View File

@ -0,0 +1,3 @@
TARGET := lib-vfs-cbe_crypto-memcopy
REQUIRES = x86_64
LIBS = vfs_cbe_crypto_memcopy

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
TARGET := lib-vfs-cbe_trust_anchor
REQUIRES = x86_64
LIBS = vfs_cbe_trust_anchor

File diff suppressed because it is too large Load Diff