/*
* \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_LIBRARY_H_
#define _CBE_LIBRARY_H_
/* Genode includes */
#include
#include
/* CBE includes */
#include
#include
extern "C" void cbe_cxx_init();
extern "C" void cbe_cxx_final();
namespace Cbe {
using namespace Genode;
class Library;
Genode::uint32_t object_size(Library const &);
} /* namespace Cbe */
class Cbe::Library : public Cbe::Spark_object<353944>
{
private:
/*
* Ada/SPARK compatible bindings
*
* Ada functions cannot have out parameters. Hence we call Ada
* procedures that return the 'progress' result as last out parameter.
*/
void _has_io_request(Request &, Io_buffer::Index &) const;
void _crypto_add_key_required(Request &, Key &) const;
void _crypto_remove_key_required(Request &, Key::Id &) const;
void _crypto_cipher_data_required(Request &, Crypto_plain_buffer::Index &) const;
void _crypto_plain_data_required(Request &, Crypto_cipher_buffer::Index &) const;
void _info(Info &) const;
void _peek_generated_ta_request(Trust_anchor_request &) const;
void _peek_generated_ta_sb_hash(Trust_anchor_request const &, Hash &) const;
void _peek_generated_ta_key_value_plaintext(Trust_anchor_request const &, Key_plaintext_value &) const;
void _peek_generated_ta_key_value_ciphertext(Trust_anchor_request const &, Key_ciphertext_value &) const;
public:
Library();
/**
* Get highest virtual-block-address useable by the current active snapshot
*
* \return highest addressable virtual-block-address
*/
Virtual_block_address max_vba() const;
/**
* Get information about the CBE
*
* \return information structure
*/
Info info() const
{
Info inf { };
_info(inf);
return inf;
}
void execute(Io_buffer &io_buf,
Crypto_plain_buffer &crypto_plain_buf,
Crypto_cipher_buffer &crypto_cipher_buf);
/**
* Return whether the last call to 'execute' has made progress or not
*/
bool execute_progress() const;
/**
* Check if the CBE can accept a new requeust
*
* \return true if a request can be accepted, otherwise false
*/
bool client_request_acceptable() const;
/**
* Submit a new request
*
* This method must only be called after executing 'request_acceptable'
* returned true.
*
* \param request block request
*/
void submit_client_request(Request const &request, uint32_t id);
/**
* Check for any completed request
*
* \return a valid block request will be returned if there is an
* completed request, otherwise an invalid one
*/
Request peek_completed_client_request() const;
/**
* Drops the completed request
*
* This method must only be called after executing
* 'peek_completed_request' returned a valid request.
*
*/
void drop_completed_client_request(Request const &req);
/*
* Backend block I/O
*/
/**
* Submit read request data from the backend block session to the CBE
*
* The given data will be transfered to the CBE.
*
* \param request reference to the request from the CBE
* \param data reference to the data associated with the
* request
*
* \return true if the CBE acknowledged the request
*/
void io_request_completed(Io_buffer::Index const &data_index,
bool const success);
/**
* Return a write request for the backend block session
*
* \param result valid request in case the is one pending that
* needs data, otherwise an invalid one is returned
*/
Request has_io_request(Io_buffer::Index &data_index) const
{
Request result { };
_has_io_request(result, data_index);
return result;
}
void has_io_request(Request &req, Io_buffer::Index &data_index) const
{
_has_io_request(req, data_index);
}
/**
* Obtain data for write request for the backend block session
*
* The CBE will transfer the payload to the given data.
*
* \param request reference to the Block::Request processed
* by the CBE
* \param data reference to the data associated with the
* Request
*
* \return true if the CBE could process the request
*/
void io_request_in_progress(Io_buffer::Index const &data_index);
void client_transfer_read_data_required(Request &,
uint64_t &,
Crypto_plain_buffer::Index &) const;
void client_transfer_read_data_in_progress(Crypto_plain_buffer::Index const &);
void client_transfer_read_data_completed(Crypto_plain_buffer::Index const &, bool);
void client_transfer_write_data_required(Request &,
uint64_t &,
Crypto_plain_buffer::Index &) const;
void client_transfer_write_data_in_progress(Crypto_plain_buffer::Index const &);
void client_transfer_write_data_completed(Crypto_plain_buffer::Index const &, bool);
/**
* Query list of active snapshots
*
* \param ids reference to destination buffer
*/
void active_snapshot_ids(Active_snapshot_ids &ids) const;
Request crypto_add_key_required(Key &key) const
{
Request result { };
_crypto_add_key_required(result, key);
return result;
}
void crypto_add_key_requested(Request const &req);
void crypto_add_key_completed(Request const &req);
Request crypto_remove_key_required(Key::Id &key_id) const
{
Request result { };
_crypto_remove_key_required(result, key_id);
return result;
}
void crypto_remove_key_requested(Request const &req);
void crypto_remove_key_completed(Request const &req);
/**
* CBE requests encrytion
*
* \param result valid request in case the is one pending that
* needs encrytion, otherwise an invalid one is
* returned
*/
Request crypto_cipher_data_required(Crypto_plain_buffer::Index &data_index) const
{
Request result { };
_crypto_cipher_data_required(result, data_index);
return result;
}
/**
* Return plain data for given encryption request
*
* \param request reference to the Block::Request processed
* by the CBE
* \param data reference to the data associated with the
* Block::Request
*/
void crypto_cipher_data_requested(
Crypto_plain_buffer::Index const &data_index);
/**
* Collect cipher data for given completed encryption request
*
* \param request reference to the Block::Request processed
* by the CBE
* \param data reference to the data associated with the
* Block::Request
*
* \return true if the CBE could obtain the encrypted data,
* otherwise false
*/
void supply_crypto_cipher_data(Crypto_cipher_buffer::Index const &data_index,
bool const data_valid);
/**
* CBE requests decryption
*
* \param result valid request in case the is one pending that
* needs decrytion, otherwise an invalid one is
* returned
*/
Request crypto_plain_data_required(Crypto_cipher_buffer::Index &data_index) const
{
Request result { };
_crypto_plain_data_required(result, data_index);
return result;
}
/**
* Return cipher data for given decryption request
*
* \param request reference to the Block::Request processed
* by the CBE
* \param data reference to the data associated with the
* Block::Request
*
* \return true if the CBE could supply the ciphr data,
* otherwise false
*/
void crypto_plain_data_requested(
Crypto_cipher_buffer::Index const &data_index);
/**
* Collect plain data for given completed decryption request
*
* \param request reference to the Block::Request processed
* by the CBE
* \param data reference to the data associated with the
* Block::Request
*
* \return true if the CBE could obtain the decrypted data,
* otherwise false
*/
void supply_crypto_plain_data(Crypto_plain_buffer::Index const &data_index,
bool const data_valid);
/**
* CBE trust anchor request
*
* \return valid TA request in case there is one pending, otherwise an
* invalid one is returned
*/
Trust_anchor_request peek_generated_ta_request() const
{
Trust_anchor_request request { };
_peek_generated_ta_request(request);
return request;
}
/**
* Drop generated TA request
*
* \param request reference to the request processed by the TA
*/
void drop_generated_ta_request(Trust_anchor_request const &request);
/**
* Peek generated TA superblock hash
*
* \param request reference to the request
* \return superblock hash
*/
Hash peek_generated_ta_sb_hash(Trust_anchor_request const &request) const
{
Cbe::Hash hash { };
_peek_generated_ta_sb_hash(request, hash);
return hash;
}
/**
* Mark generated TA secure superblock request complete
*
* \param request reference to the request completed by the TA
*/
void mark_generated_ta_secure_sb_request_complete(Trust_anchor_request const &request);
/**
* Mark generated TA create key request complete
*
* \param request reference to the request completed by the TA
* \param key reference to the key plaintext created by the TA
*/
void mark_generated_ta_create_key_request_complete(Trust_anchor_request const &request,
Key_plaintext_value const &key);
/**
* Peek generated TA key ciphertext
*
* \param request reference to the request
* \return key ciphertext
*/
Key_ciphertext_value peek_generated_ta_key_value_ciphertext(Trust_anchor_request const &request) const
{
Cbe::Key_ciphertext_value ck { };
_peek_generated_ta_key_value_ciphertext(request, ck);
return ck;
}
/**
* Peek generated TA key plaintext
*
* \param request reference to the request
* \return key plaintext
*/
Key_plaintext_value peek_generated_ta_key_value_plaintext(Trust_anchor_request const &request) const
{
Cbe::Key_plaintext_value pk { };
_peek_generated_ta_key_value_plaintext(request, pk);
return pk;
}
/**
* Mark generated TA decrypt key request complete
*
* \param request reference to the request completed by the TA
* \param key reference to the key plaintext decrypted by the TA
*/
void mark_generated_ta_decrypt_key_request_complete(Trust_anchor_request const &reference,
Key_plaintext_value const &key);
/**
* Mark generated TA encrypt key request complete
*
* \param request reference to the request completed by the TA
* \param key reference to the key ciphertext encrypted by the TA
*/
void mark_generated_ta_encrypt_key_request_complete(Trust_anchor_request const &request,
Key_ciphertext_value const &key);
/**
* Mark generated TA last superblock hash request complete
*
* \param request reference to the request completed by the TA
* \param hash reference to the superblock hash stored in the TA
*/
void mark_generated_ta_last_sb_hash_request_complete(Trust_anchor_request const &request,
Hash const &hash);
};
#endif /* _CBE_LIBRARY_H_ */