Skip to content

Commit

Permalink
tresor: check hash of all read vba data
Browse files Browse the repository at this point in the history
During one of the many re-factorization steps that were applied to the Tresor
library and its predecessor, the CBE library, one of the main features of the
project, the integrity check, accidentally received a grave regression. The
most recent version of the Tresor still used to check all hashes of meta-data
blocks but ignored the hashes of the actual data blocks.

With this commit, the hashes of all but yet uninitialized data blocks get
checked. The reason for ignoring uninitialized blocks is that they are not
actually read from disc but simply generated as an all-zeros block in the
driver in order to prevent having to initialize them all to zero in
Tresor-Init. That said, the integrity of these blocks cannot be compomised.
The according hashes in the meta data remain unset until the data block gets
written for the first time.

Ref genodelabs#5062
  • Loading branch information
m-stein committed Mar 22, 2024
1 parent c4205aa commit 443e2d5
Show file tree
Hide file tree
Showing 4 changed files with 25 additions and 10 deletions.
1 change: 1 addition & 0 deletions repos/gems/src/lib/tresor/block_io.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ void Block_io_channel::_read_client_data(bool &progress)
case REQ_SUBMITTED: _file.read(READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); break;
case READ_OK:

calc_hash(_blk, req._hash);
_generate_req<Crypto_request>(
PLAINTEXT_BLK_SUPPLIED, progress, Crypto_request::DECRYPT_CLIENT_DATA, req._client_req_offset,
req._client_req_tag, req._key_id, *(Key_value *)0, req._pba, req._vba, _blk);
Expand Down
4 changes: 2 additions & 2 deletions repos/gems/src/lib/tresor/include/tresor/block_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,8 @@ class Tresor::Block_io : public Module
struct Read_client_data : Request
{
Read_client_data(Module_id m, Module_channel_id c, Physical_block_address p, Virtual_block_address v,
Key_id k, Request_tag t, Request_offset o, bool &s)
: Request(m, c, Request::READ_CLIENT_DATA, o, t, k, p, v, *(Block*)0, *(Hash*)0, s) { }
Key_id k, Request_tag t, Request_offset o, Hash &h, bool &s)
: Request(m, c, Request::READ_CLIENT_DATA, o, t, k, p, v, *(Block*)0, h, s) { }
};

Block_io(Vfs::Env &, Xml_node const &);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ class Tresor::Virtual_block_device_channel : public Module_channel

void _read_vba(bool &);

bool _check_and_decode_read_blk(bool &, bool);
bool _check_and_decode_read_blk(bool &);

Tree_node_index _node_idx(Tree_level_index, Virtual_block_address) const;

Expand Down
28 changes: 21 additions & 7 deletions repos/gems/src/lib/tresor/virtual_block_device.cc
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ void Virtual_block_device_channel::_read_vba(bool &progress)

case READ_BLK_SUCCEEDED:
{
if (!_check_and_decode_read_blk(progress, false))
if (!_check_and_decode_read_blk(progress))
break;

if (!_lvl) {
Expand All @@ -112,7 +112,7 @@ void Virtual_block_device_channel::_read_vba(bool &progress)
} else
_generate_req<Block_io::Read_client_data>(
READ_BLK_SUCCEEDED, progress, node.pba, _vba, req._curr_key_id,
req._client_req_tag, req._client_req_offset);
req._client_req_tag, req._client_req_offset, _hash);
_lvl--;
break;
}
Expand Down Expand Up @@ -147,13 +147,27 @@ void Virtual_block_device_channel::_update_nodes_of_branch_of_written_vba()
}


bool Virtual_block_device_channel::_check_and_decode_read_blk(bool &progress, bool check_leaf_data = true)
bool Virtual_block_device_channel::_check_and_decode_read_blk(bool &progress)
{
if (!check_leaf_data && !_lvl)
return true;
Request &req { *_req_ptr };
Hash *node_hash_ptr;
if (_lvl) {
calc_hash(_encoded_blk, _hash);
if (_lvl < snap().max_level)
node_hash_ptr = &_node(_lvl + 1, _vba).hash;
else
node_hash_ptr = &snap().hash;
} else {
Type_1_node &node { _node(_lvl + 1, _vba) };
if (req._type == Request::READ_VBA) {
if (node.gen == INITIAL_GENERATION)
return true;
} else
calc_hash(_data_blk, _hash);

Hash &hash { _lvl < snap().max_level ? _node(_lvl + 1, _vba).hash : snap().hash };
if (!check_hash(_lvl ? _encoded_blk : _data_blk, hash)) {
node_hash_ptr = &node.hash;
}
if (_hash != *node_hash_ptr) {
_mark_req_failed(progress, "check hash of read block");
return false;
}
Expand Down

0 comments on commit 443e2d5

Please sign in to comment.