tresor: check only the last secured superblock

Instead of iterating over all superblocks and checking each valid one,
check only the one whose hash matches the hash stored in the trust anchor.
I.e., the last one that was secured to the trust anchor. We must assume that
the other superblocks were corrupted in the meantime by operating the Tresor
container and, anyway, these Superblocks are not used anymore.

Ref #5077
This commit is contained in:
Martin Stein 2024-03-19 13:49:24 +01:00 committed by Christian Helmuth
parent d2af024349
commit 016a769605
4 changed files with 55 additions and 47 deletions

View File

@ -43,18 +43,25 @@ class Tresor_check::Main : private Vfs::Env::User
Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this };
Signal_handler<Main> _sigh { _env.ep(), *this, &Main::_handle_signal };
Tresor::Path const _block_io_path { _config_rom.xml().sub_node("block-io").attribute_value("path", Tresor::Path()) };
Tresor::Path const _trust_anchor_path { _config_rom.xml().sub_node("trust-anchor").attribute_value("path", Tresor::Path()) };
Vfs::Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, Vfs::Directory_service::OPEN_MODE_RDWR) };
Vfs::Vfs_handle &_ta_decrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
Vfs::Vfs_handle &_ta_encrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
Vfs::Vfs_handle &_ta_generate_key_file { open_file(_vfs_env, { _trust_anchor_path, "/generate_key" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
Vfs::Vfs_handle &_ta_initialize_file { open_file(_vfs_env, { _trust_anchor_path, "/initialize" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
Vfs::Vfs_handle &_ta_hash_file { open_file(_vfs_env, { _trust_anchor_path, "/hash" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
Block_io _block_io { _block_io_file };
Vbd_check _vbd_check { };
Ft_check _ft_check { };
Sb_check _sb_check { };
Trust_anchor _trust_anchor { { _ta_decrypt_file, _ta_encrypt_file, _ta_generate_key_file, _ta_initialize_file, _ta_hash_file } };
Sb_check::Check _check_superblocks { };
void _wakeup_back_end_services() { _vfs_env.io().commit(); }
void _handle_signal()
{
while(_sb_check.execute(_check_superblocks, _vbd_check, _ft_check, _block_io));
while(_sb_check.execute(_check_superblocks, _vbd_check, _ft_check, _block_io, _trust_anchor));
if (_check_superblocks.complete())
_env.parent().exit(_check_superblocks.success() ? 0 : -1);
_wakeup_back_end_services();

View File

@ -868,7 +868,7 @@ class Tresor_tester::Main : Vfs::Env::User, Client_data_interface, Crypto_key_fi
case Command::IN_PROGRESS:
{
Sb_check::Check &req = *cmd.check_superblocks_ptr;
progress |= _sb_check.execute(req, _vbd_check, _ft_check, _block_io);
progress |= _sb_check.execute(req, _vbd_check, _ft_check, _block_io, _trust_anchor);
_try_complete_command(cmd, req, progress);
break;
}

View File

@ -19,6 +19,7 @@
#include <tresor/vbd_check.h>
#include <tresor/ft_check.h>
#include <tresor/block_io.h>
#include <tresor/trust_anchor.h>
namespace Tresor { class Sb_check; }
@ -34,23 +35,25 @@ struct Tresor::Sb_check : Noncopyable
enum State {
INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, CHECK_VBD, CHECK_VBD_SUCCEEDED, CHECK_FT, CHECK_FT_SUCCEEDED,
CHECK_MT, CHECK_MT_SUCCEEDED};
CHECK_MT, CHECK_MT_SUCCEEDED, READ_SB_HASH, READ_SB_HASH_SUCCEEDED };
using Helper = Request_helper<Check, State>;
Helper _helper;
Generation _highest_gen { 0 };
Superblock_index _highest_gen_sb_idx { 0 };
Hash _hash { };
bool _scan_for_highest_gen_sb_done { false };
Superblock_index _sb_idx { 0 };
Superblock_index _sb_idx { };
Superblock _sb { };
Snapshot_index _snap_idx { 0 };
Constructible<Tree_root> _tree_root { };
Block _blk { };
Generatable_request<Helper, State, Trust_anchor::Read_hash> _read_sb_hash { };
Generatable_request<Helper, State, Vbd_check::Check> _check_vbd { };
Generatable_request<Helper, State, Ft_check::Check> _check_ft { };
Generatable_request<Helper, State, Block_io::Read> _read_block { };
void _check_snap(bool &);
public:
Check() : _helper(*this) { }
@ -59,7 +62,7 @@ struct Tresor::Sb_check : Noncopyable
void print(Output &out) const { Genode::print(out, "check"); }
bool execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io);
bool execute(Vbd_check &, Ft_check &, Block_io &, Trust_anchor &);
bool complete() const { return _helper.complete(); }
bool success() const { return _helper.success(); }
@ -67,7 +70,7 @@ struct Tresor::Sb_check : Noncopyable
Sb_check() { }
bool execute(Check &check, Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io) { return check.execute(vbd_check, ft_check, block_io); };
bool execute(Check &check, Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io, Trust_anchor &trust_anchor) { return check.execute(vbd_check, ft_check, block_io, trust_anchor); };
static constexpr char const *name() { return "sb_check"; }
};

View File

@ -13,62 +13,62 @@
/* tresor includes */
#include <tresor/sb_check.h>
#include <tresor/hash.h>
using namespace Tresor;
bool Sb_check::Check::execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io)
void Sb_check::Check::_check_snap(bool &progress)
{
Snapshot &snap { _sb.snapshots.items[_snap_idx] };
if (!snap.valid) {
_helper.state = CHECK_VBD_SUCCEEDED;
progress = true;
if (VERBOSE_CHECK)
log(" skip snap ", _snap_idx, " as it is unused");
return;
}
_tree_root.construct(snap.pba, snap.gen, snap.hash, snap.max_level, _sb.degree, snap.nr_of_leaves);
_check_vbd.generate(_helper, CHECK_VBD, CHECK_VBD_SUCCEEDED, progress, *_tree_root);
if (VERBOSE_CHECK)
log(" check snap ", _snap_idx, " (", snap, ")");
}
bool Sb_check::Check::execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io, Trust_anchor &trust_anchor)
{
bool progress = false;
switch (_helper.state) {
case INIT:
_highest_gen = 0;
_highest_gen_sb_idx = 0;
_snap_idx = 0;
_sb_idx = 0;
_scan_for_highest_gen_sb_done = false;
_read_sb_hash.generate(_helper, READ_SB_HASH, READ_SB_HASH_SUCCEEDED, progress, _hash);
break;
case READ_SB_HASH: progress |= _read_sb_hash.execute(trust_anchor); break;
case READ_SB_HASH_SUCCEEDED:
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _sb_idx, _blk);
break;
case READ_BLK: progress |= _read_block.execute(block_io); break;
case READ_BLK_SUCCEEDED:
_sb.decode_from_blk(_blk);
if (_scan_for_highest_gen_sb_done) {
if (check_hash(_blk, _hash)) {
_sb.decode_from_blk(_blk);
if (VERBOSE_CHECK)
log("check superblock ", _sb_idx, " hash ", _hash, "\n read superblock");
if (!_sb.valid()) {
_helper.mark_failed(progress, "no valid superblock");;
_helper.mark_failed(progress, "superblock marked invalid");;
break;
}
Snapshot &snap { _sb.snapshots.items[_snap_idx] };
if (snap.valid) {
Snapshot &snap { _sb.snapshots.items[_snap_idx] };
_tree_root.construct(snap.pba, snap.gen, snap.hash, snap.max_level, _sb.degree, snap.nr_of_leaves);
_check_vbd.generate(_helper, CHECK_VBD, CHECK_VBD_SUCCEEDED, progress, *_tree_root);
if (VERBOSE_CHECK)
log(" check snap ", _snap_idx, " (", snap, ")");
} else {
_helper.state = CHECK_VBD_SUCCEEDED;
progress = true;
if (VERBOSE_CHECK)
log(" skip snap ", _snap_idx, " as it is unused");
}
} else {
Snapshot &snap { _sb.curr_snap() };
if (_sb.valid() && snap.gen > _highest_gen) {
_highest_gen = snap.gen;
_highest_gen_sb_idx = _sb_idx;
}
_snap_idx = 0;
_check_snap(progress);
} else
if (_sb_idx < MAX_SUPERBLOCK_INDEX) {
_sb_idx++;
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _sb_idx, _blk);
progress = true;
} else {
_scan_for_highest_gen_sb_done = true;
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _highest_gen_sb_idx, _blk);
if (VERBOSE_CHECK)
log("check superblock ", _highest_gen_sb_idx, "\n read superblock");
}
}
} else
_helper.mark_failed(progress, "superblock not found");
break;
case CHECK_VBD: progress |= _check_vbd.execute(vbd_check, block_io); break;
@ -76,10 +76,8 @@ bool Sb_check::Check::execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io
if (_snap_idx < MAX_SNAP_IDX) {
_snap_idx++;
_helper.state = READ_BLK_SUCCEEDED;
progress = true;
_check_snap(progress);
} else {
_snap_idx = 0;
_tree_root.construct(_sb.free_number, _sb.free_gen, _sb.free_hash, _sb.free_max_level, _sb.free_degree, _sb.free_leaves);
_check_ft.generate(_helper, CHECK_FT, CHECK_FT_SUCCEEDED, progress, *_tree_root);
if (VERBOSE_CHECK)