diff --git a/repos/gems/lib/mk/tresor.mk b/repos/gems/lib/mk/tresor.mk index bcf420be6f..1e5417d84a 100644 --- a/repos/gems/lib/mk/tresor.mk +++ b/repos/gems/lib/mk/tresor.mk @@ -1,7 +1,6 @@ TRESOR_DIR := $(REP_DIR)/src/lib/tresor SRC_CC += crypto.cc -SRC_CC += request_pool.cc SRC_CC += hash.cc SRC_CC += trust_anchor.cc SRC_CC += block_io.cc @@ -9,7 +8,6 @@ SRC_CC += meta_tree.cc SRC_CC += virtual_block_device.cc SRC_CC += superblock_control.cc SRC_CC += free_tree.cc -SRC_CC += module.cc SRC_CC += vbd_initializer.cc SRC_CC += ft_initializer.cc SRC_CC += sb_initializer.cc diff --git a/repos/gems/lib/mk/vfs_tresor.mk b/repos/gems/lib/mk/vfs_tresor.mk index 88ed1baf9e..549024bf5c 100644 --- a/repos/gems/lib/mk/vfs_tresor.mk +++ b/repos/gems/lib/mk/vfs_tresor.mk @@ -1,6 +1,6 @@ LIB_DIR := $(REP_DIR)/src/lib/vfs/tresor -SRC_CC := vfs.cc splitter.cc +SRC_CC := vfs.cc INC_DIR += $(LIB_DIR) diff --git a/repos/gems/run/tresor_tester.run b/repos/gems/run/tresor_tester.run index 402ed36509..e864e69b25 100644 --- a/repos/gems/run/tresor_tester.run +++ b/repos/gems/run/tresor_tester.run @@ -238,7 +238,7 @@ append config { - + - - - - - - + + + + + + - - - - - - - - + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - + + + + + + + + + + + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -403,195 +400,195 @@ append config { - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + @@ -612,439 +609,439 @@ if {[benchmark_blk_count] > 0} { append config { - + - - - + + + - - - + + + - - - + + + - - - + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + } @@ -1052,18 +1049,18 @@ if {[benchmark_blk_count] > 0} { append config { - + } } append config { - + - - - - - + + + + + diff --git a/repos/gems/run/vfs_tresor.run b/repos/gems/run/vfs_tresor.run index 10c81a8e0e..7cf48b2ee6 100644 --- a/repos/gems/run/vfs_tresor.run +++ b/repos/gems/run/vfs_tresor.run @@ -1,24 +1,26 @@ assert_spec linux +set dd [installed_command dd] + create_boot_directory -proc tresor_image_file { } { - return "vfs_tresor_block.img" -} +proc tresor_image_name { } { return "vfs_tresor_block.img" } -set use_interactively [expr ![get_cmd_switch --autopilot]] +proc tresor_image_size_mb { } { return 4 } -import_from_depot [depot_user]/pkg/[drivers_interactive_pkg] \ - [depot_user]/pkg/terminal \ - [depot_user]/src/ncurses \ +proc local_tresor_image { } { return bin/[tresor_image_name] } + +proc autopilot_tresor_image { } { return /tmp/[tresor_image_name].[exec id -un] } + +import_from_depot [depot_user]/src/ncurses \ [depot_user]/src/bash \ - [depot_user]/src/coreutils \ - [depot_user]/src/nitpicker - + [depot_user]/src/coreutils build { - core lib/ld timer init - server/lx_fs + core + timer + init + lib/ld lib/vfs_tresor lib/vfs_tresor_crypto_aes_cbc lib/vfs_tresor_crypto_memcopy @@ -26,17 +28,24 @@ build { lib/vfs_import lib/vfs_jitterentropy lib/vfs_pipe - lib/vfs lib/libc lib/posix lib/libcrypto + lib/vfs + lib/libc + lib/libm + lib/posix + lib/libcrypto test/vfs_stress test/libc server/log_terminal server/report_rom server/fs_rom + server/lx_fs + server/vfs app/tresor_init_trust_anchor + app/tresor_init app/sequence } -set config { +append config { @@ -54,64 +63,20 @@ set config { + - - - - - - - - - - - - - - - - - - - - - - - - - - - - } - -append_if $use_interactively config { - - - - - - - - - - - } - -append_if [expr !$use_interactively] config { - - + - } + -append config { @@ -127,15 +92,9 @@ append config { - - - - - - + @@ -146,8 +105,7 @@ append config { - - + @@ -156,12 +114,37 @@ append config { - + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -188,12 +171,12 @@ append config { - + - + @@ -202,8 +185,6 @@ append config { - - @@ -230,7 +211,7 @@ append config { - + @@ -266,21 +247,23 @@ append config { - - + + - + + + - - - + + + @@ -294,19 +277,28 @@ set shell_script "run/vfs_tresor.sh" set repo "[repository_contains $shell_script]" exec cp $repo/$shell_script bin/ +exec rm -rf [local_tresor_image] +if { [get_cmd_switch --autopilot] } { + + exec rm -rf [autopilot_tresor_image] + catch { exec $dd if=/dev/urandom of=[autopilot_tresor_image] bs=1M count=[tresor_image_size_mb] } + exec ln -sf -T [autopilot_tresor_image] [local_tresor_image] + +} else { + + catch { exec $dd if=/dev/urandom of=[local_tresor_image] bs=1M count=[tresor_image_size_mb] } +} + set boot_modules [build_artifacts] - -append boot_modules { vfs_tresor.sh encrypted_private_key superblock_hash } -lappend boot_modules [tresor_image_file] - -set fd [open [run_dir]/genode/focus w] -puts $fd " \" domain=\"default\"/>" -close $fd +append boot_modules { vfs_tresor.sh } +lappend boot_modules [tresor_image_name] build_boot_image $boot_modules -if {$use_interactively} { - run_genode_until forever -} else { - run_genode_until {.*--- Automated Tresor testing finished.*} 1800 +run_genode_until {.*"/bin/bash".* exited with exit value 0.*\n} 120 + +if { [get_cmd_switch --autopilot] } { + + exec rm -rf [local_tresor_image] + exec rm -rf [autopilot_tresor_image] } diff --git a/repos/gems/run/vfs_tresor.sh b/repos/gems/run/vfs_tresor.sh index bfc4f955eb..3fea3fd2d0 100644 --- a/repos/gems/run/vfs_tresor.sh +++ b/repos/gems/run/vfs_tresor.sh @@ -55,33 +55,25 @@ test_read_compare_1() { fi } -test_create_snapshot() { +test_deinitialize() { local tresor_dir="$1" - - echo "Create snapshot" - echo true > $tresor_dir/control/create_snapshot + echo "Deinitialize" + local state="$(< $tresor_dir/control/deinitialize)" + echo true > $tresor_dir/control/deinitialize } -test_list_snapshots() { +wait_for_deinitialize() { local tresor_dir="$1" - - echo "List content of '$tresor_dir'" - ls -l $tresor_dir/snapshots -} - -test_discard_snapshot() { - local tresor_dir="$1" - local snap_id=$2 - - echo "Discard snapshot with id: $snap_id" - echo $snap_id > $tresor_dir/control/discard_snapshot + echo "Wait for deinitialize" + local state="$(< $tresor_dir/control/deinitialize)" } test_rekey_start() { local tresor_dir="$1" echo "Start rekeying" - echo on > $tresor_dir/control/rekey + local state="$(< $tresor_dir/control/rekey)" + echo true > $tresor_dir/control/rekey echo "Reykeying started" } @@ -137,16 +129,14 @@ wait_for_rekeying() { echo "Wait for rekeying to finish..." while : ; do local done=0 - local file_content="$(< $tresor_dir/control/rekey_progress)" + local file_content="$(< $tresor_dir/control/rekey)" # XXX remove later echo "file_content: ${file_content}" case "$file_content" in - *at*) - if [ "$verbose" = "yes" ]; then - echo "Rekeying: $file_content" - fi + *failed*) + done=1; ;; - *idle*) + *succeeded*) done=1; ;; esac @@ -163,16 +153,14 @@ wait_for_vbd_extension() { echo "Wait for VBD extension to finish..." while : ; do local done=0 - local file_content="$(< $tresor_dir/control/extend_progress)" + local file_content="$(< $tresor_dir/control/extend)" # XXX remove later echo "file_content: ${file_content}" case "$file_content" in - *at*) - if [ "$verbose" = "yes" ]; then - echo "Extending VBD: $file_content" - fi + *failed*) + done=1; ;; - *idle*) + *succeeded*) done=1; ;; esac @@ -189,16 +177,14 @@ wait_for_ft_extension() { echo "Wait for FT extension to finish..." while : ; do local done=0 - local file_content="$(< $tresor_dir/control/extend_progress)" + local file_content="$(< $tresor_dir/control/extend)" # XXX remove later echo "file_content: ${file_content}" case "$file_content" in - *at*) - if [ "$verbose" = "yes" ]; then - echo "Extending FT: $file_content" - fi + *failed*) + done=1; ;; - *idle*) + *succeeded*) done=1; ;; esac @@ -212,95 +198,37 @@ wait_for_ft_extension() { main() { local tresor_dir="/dev/tresor" local data_file="$tresor_dir/current/data" - + echo "list files..." ls -l $tresor_dir - - for i in $(seq 3); do - - echo "--> Run $i:" - - test_read_seq_unaligned_512 "$data_file" "1048576" - - local pattern_file="/tmp/pattern" - produce_pattern "$i" "4096" > $pattern_file - - test_write_1 "$data_file" "419" - test_write_1 "$data_file" "63" - test_write_1 "$data_file" "333" - - test_vbd_extension "$tresor_dir" "1000" - test_read_compare_1 "$data_file" "63" - test_write_1 "$data_file" "175" - test_read_compare_1 "$data_file" "419" - test_write_1 "$data_file" "91" - test_read_compare_1 "$data_file" "175" - test_read_compare_1 "$data_file" "91" - test_read_compare_1 "$data_file" "333" - wait_for_vbd_extension "$tresor_dir" - - test_write_1 "$data_file" "32" - test_write_1 "$data_file" "77" - test_write_1 "$data_file" "199" - - #test_ft_extension "$tresor_dir" "1000" - test_read_compare_1 "$data_file" "32" - test_write_1 "$data_file" "211" - test_read_compare_1 "$data_file" "77" - test_write_1 "$data_file" "278" - test_read_compare_1 "$data_file" "199" - test_read_compare_1 "$data_file" "278" - test_read_compare_1 "$data_file" "211" - #wait_for_ft_extension "$tresor_dir" - - test_write_1 "$data_file" "0" - test_write_1 "$data_file" "8" - test_write_1 "$data_file" "16" - test_write_1 "$data_file" "490" - test_write_1 "$data_file" "468" - - test_read_compare_1 "$data_file" "0" - test_read_compare_1 "$data_file" "8" - test_read_compare_1 "$data_file" "16" - test_read_compare_1 "$data_file" "490" - - #test_rekey "$tresor_dir" - - test_rekey_start "$tresor_dir" - test_write_1 "$data_file" "0" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "490" - test_rekey_state "$tresor_dir" - test_write_1 "$data_file" "16" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "468" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "8" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "16" - test_rekey_state "$tresor_dir" - test_read_compare_1 "$data_file" "0" - test_write_1 "$data_file" "300" - test_write_1 "$data_file" "240" - test_write_1 "$data_file" "201" - test_write_1 "$data_file" "328" - wait_for_rekeying "$tresor_dir" "yes" - - echo "--> Run $i done" - - done - - echo "--> Read/Compare test" - test_read_compare_1 "$data_file" "0" - test_read_compare_1 "$data_file" "490" - test_read_compare_1 "$data_file" "468" - test_read_compare_1 "$data_file" "8" - test_read_compare_1 "$data_file" "16" - echo "--> Read/Compare test done" - - echo "--- Automated Tresor testing finished, shell is yours ---" + echo "produce pattern..." + local pattern_file="/tmp/pattern" + produce_pattern "1" "4096" > $pattern_file + echo "write..." + test_write_1 "$data_file" "20" + echo "read..." + test_read_compare_1 "$data_file" "20" + test_write_1 "$data_file" "20" + echo "extend VBD..." + test_vbd_extension "$tresor_dir" "100" + test_write_1 "$data_file" "2" + test_read_compare_1 "$data_file" "2" + wait_for_vbd_extension "$tresor_dir" + echo "extend FT..." + test_ft_extension "$tresor_dir" "100" + test_write_1 "$data_file" "2" + test_read_compare_1 "$data_file" "2" + wait_for_ft_extension "$tresor_dir" + echo "rekey..." + test_rekey_start "$tresor_dir" + test_write_1 "$data_file" "2" + test_read_compare_1 "$data_file" "2" + wait_for_rekeying "$tresor_dir" "no" + test_deinitialize "$tresor_dir" + wait_for_deinitialize "$tresor_dir" + echo "done!" } main "$@" # just drop into shell -# exit 0 +exit 0 diff --git a/repos/gems/run/vfs_tresor_init.run b/repos/gems/run/vfs_tresor_init.run deleted file mode 100644 index 3007541865..0000000000 --- a/repos/gems/run/vfs_tresor_init.run +++ /dev/null @@ -1,153 +0,0 @@ -assert_spec linux - -proc tresor_image_file { } { - return "vfs_tresor_block.img" -} - -set image_size 32 - -proc tresor_image_size_mb { } { - global image_size - return $image_size -} - -build { - core lib/ld init timer - server/lx_block - server/lx_fs - server/vfs lib/vfs - app/sequence - - app/tresor_init_trust_anchor - app/tresor_init - lib/vfs_tresor_crypto_aes_cbc - lib/vfs_tresor_trust_anchor - lib/vfs_jitterentropy - lib/libc - lib/libcrypto -} - -create_boot_directory - -append config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} - -install_config $config - -exec rm -rf bin/[tresor_image_file] -exec truncate -s [tresor_image_size_mb]M bin/[tresor_image_file] - -build_boot_image [list {*}[build_artifacts] [tresor_image_file]] - -run_genode_until {.*child "initialize_tresor" exited with exit value 0.*\n} 240 - -exec cp [run_dir]/genode/encrypted_private_key bin -exec cp [run_dir]/genode/superblock_hash bin diff --git a/repos/gems/src/app/file_vault/main.cc b/repos/gems/src/app/file_vault/main.cc index 9df6d65696..cf9b7a7778 100644 --- a/repos/gems/src/app/file_vault/main.cc +++ b/repos/gems/src/app/file_vault/main.cc @@ -641,8 +641,28 @@ class File_vault::Main size_t nr_of_ft_children, size_t nr_of_ft_leafs); - static bool tresor_control_file_yields_state_idle(Xml_node const &fs_query_listing, - char const *file_name); + template + static bool listing_file_starts_with(Xml_node const &fs_query_listing, + char const *file_name, + String const &str) + { + bool result { false }; + bool done { false }; + fs_query_listing.with_optional_sub_node("dir", [&] (Xml_node const &node_0) { + node_0.for_each_sub_node("file", [&] (Xml_node const &node_1) { + if (done) { + return; + } + if (node_1.attribute_value("name", String<16>()) == file_name) { + node_1.with_raw_content([&] (char const *base, size_t size) { + result = String { Cstring {base, size} } == str; + done = true; + }); + } + }); + }); + return result; + } /*************************************************** @@ -699,28 +719,6 @@ void Main::_handle_ui_config() } -bool Main::tresor_control_file_yields_state_idle(Xml_node const &fs_query_listing, - char const *file_name) -{ - bool result { false }; - bool done { false }; - fs_query_listing.with_optional_sub_node("dir", [&] (Xml_node const &node_0) { - node_0.for_each_sub_node("file", [&] (Xml_node const &node_1) { - if (done) { - return; - } - if (node_1.attribute_value("name", String<16>()) == file_name) { - node_1.with_raw_content([&] (char const *base, size_t size) { - result = String<5> { Cstring {base, size} } == "idle"; - done = true; - }); - } - }); - }); - return result; -} - - void Main::_update_sandbox_config() { Buffered_xml const config { _heap, "config", [&] (Xml_generator &xml) { @@ -940,16 +938,20 @@ void Main::_handle_resizing_fs_query_listing(Xml_node const &node) switch (_resizing_state) { case Resizing_state::WAIT_TILL_DEVICE_IS_READY: - if (tresor_control_file_yields_state_idle(node, "extend_progress")) { + if (listing_file_starts_with(node, "extend", String<10>("succeeded")) || + listing_file_starts_with(node, "extend", String<5>("none"))) { _resizing_state = Resizing_state::ISSUE_REQUEST_AT_DEVICE; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to extend: tresor not ready"); + break; case Resizing_state::IN_PROGRESS_AT_DEVICE: - if (tresor_control_file_yields_state_idle(node, "extend_progress")) { + if (listing_file_starts_with(node, "extend", String<10>("succeeded"))) { switch (_resizing_type) { case Resizing_type::EXPAND_CLIENT_FS: @@ -972,7 +974,10 @@ void Main::_handle_resizing_fs_query_listing(Xml_node const &node) } _resizing_state = Resizing_state::DETERMINE_CLIENT_FS_SIZE; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to extend: operation failed at tresor"); + break; default: @@ -992,13 +997,16 @@ void Main::_handle_lock_fs_query_listing(Xml_node const &node) switch (_state) { case State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE: - if (tresor_control_file_yields_state_idle(node, "deinitialize")) { + if (listing_file_starts_with(node, "deinitialize", String<10>("succeeded"))) { _set_state(State::UNLOCK_OBTAIN_PARAMETERS); _setup_obtain_params_passphrase = Input_passphrase { }; _setup_obtain_params_select = Setup_obtain_params_select::PASSPHRASE_INPUT; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to deinitialize: operation failed at tresor"); + break; default: @@ -1024,20 +1032,27 @@ void Main::_handle_rekeying_fs_query_listing(Xml_node const &node) switch (_rekeying_state) { case Rekeying_state::WAIT_TILL_DEVICE_IS_READY: - if (tresor_control_file_yields_state_idle(node, "rekey_progress")) { + if (listing_file_starts_with(node, "rekey", String<10>("succeeded")) || + listing_file_starts_with(node, "rekey", String<5>("none"))) { _rekeying_state = Rekeying_state::ISSUE_REQUEST_AT_DEVICE; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to rekey: tresor not ready"); + break; case Rekeying_state::IN_PROGRESS_AT_DEVICE: - if (tresor_control_file_yields_state_idle(node, "rekey_progress")) { + if (listing_file_starts_with(node, "rekey", String<10>("succeeded"))) { _rekeying_state = Rekeying_state::INACTIVE; Signal_transmitter(_state_handler).submit(); - } + + } else + error("failed to rekey: operation failed at tresor"); + break; default: @@ -1465,10 +1480,8 @@ void File_vault::Main::handle_sandbox_state() update_dialog = true; update_sandbox = true; - } else { - + } else _unlock_retry_delay.schedule(Microseconds { 3000000 }); - } }); break; diff --git a/repos/gems/src/app/file_vault/sandbox.h b/repos/gems/src/app/file_vault/sandbox.h index 0087da5a4d..6f1d788f68 100644 --- a/repos/gems/src/app/file_vault/sandbox.h +++ b/repos/gems/src/app/file_vault/sandbox.h @@ -299,7 +299,6 @@ namespace File_vault { xml.node("tresor", [&] () { xml.attribute("name", "tresor"); xml.attribute("verbose", "no"); - xml.attribute("debug", "no"); xml.attribute("block", File_path { "/", tresor_img_file_name }); xml.attribute("crypto", "/crypto"); xml.attribute("trust_anchor", "/trust_anchor"); @@ -531,7 +530,7 @@ namespace File_vault { } void gen_tresor_vfs_block_start_node(Xml_generator &xml, - Child_state const &child) + Child_state const &child) { child.gen_start_node(xml, [&] () { diff --git a/repos/gems/src/app/tresor_check/main.cc b/repos/gems/src/app/tresor_check/main.cc index 2e00c3939a..523833162d 100644 --- a/repos/gems/src/app/tresor_check/main.cc +++ b/repos/gems/src/app/tresor_check/main.cc @@ -31,76 +31,44 @@ using namespace Tresor; namespace Tresor_check { class Main; } -class Tresor_check::Main : private Vfs::Env::User, private Tresor::Module_composition, public Tresor::Module, public Module_channel +class Tresor_check::Main : private Vfs::Env::User { private: - enum State { INIT, REQ_GENERATED, CHECK_SBS_SUCCEEDED }; + enum State { INIT, CHECK_SB, CHECK_SB_SUCCEEDED }; Env &_env; Heap _heap { _env.ram(), _env.rm() }; Attached_rom_dataspace _config_rom { _env, "config" }; Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; Signal_handler
_sigh { _env.ep(), *this, &Main::_handle_signal }; - Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") }; - Crypto _crypto { _vfs_env, _config_rom.xml().sub_node("crypto") }; - Block_io _block_io { _vfs_env, _config_rom.xml().sub_node("block-io") }; + Tresor::Path const _block_io_path { _config_rom.xml().sub_node("block-io").attribute_value("path", Tresor::Path()) }; + Vfs::Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, 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 { }; - bool _generated_req_success { }; - State _state { INIT }; - - NONCOPYABLE(Main); - - void _generated_req_completed(State_uint state_uint) override - { - if (!_generated_req_success) { - error("command pool: request failed because generated request failed)"); - _env.parent().exit(-1); - return; - } - _state = (State)state_uint; - } - - void wakeup_vfs_user() override { _sigh.local_submit(); } + Sb_check::Check _check_superblocks { }; void _wakeup_back_end_services() { _vfs_env.io().commit(); } void _handle_signal() { - execute_modules(); + while(_sb_check.execute(_check_superblocks, _vbd_check, _ft_check, _block_io)); + if (_check_superblocks.complete()) + _env.parent().exit(_check_superblocks.success() ? 0 : -1); _wakeup_back_end_services(); } + /******************** + ** Vfs::Env::User ** + ********************/ + + void wakeup_vfs_user() override { _sigh.local_submit(); } + public: - Main(Env &env) : Module_channel { COMMAND_POOL, 0 }, _env { env } - { - add_module(COMMAND_POOL, *this); - add_module(CRYPTO, _crypto); - add_module(TRUST_ANCHOR, _trust_anchor); - add_module(BLOCK_IO, _block_io); - add_module(VBD_CHECK, _vbd_check); - add_module(FT_CHECK, _ft_check); - add_module(SB_CHECK, _sb_check); - add_channel(*this); - _handle_signal(); - } - - void execute(bool &progress) override - { - switch(_state) { - case INIT: - - generate_req(CHECK_SBS_SUCCEEDED, progress, _generated_req_success); - _state = REQ_GENERATED; - break; - - case CHECK_SBS_SUCCEEDED: _env.parent().exit(0); break; - default: break; - } - } + Main(Env &env) : _env(env) { _handle_signal(); } }; void Component::construct(Genode::Env &env) { static Tresor_check::Main main { env }; } diff --git a/repos/gems/src/app/tresor_init/main.cc b/repos/gems/src/app/tresor_init/main.cc index 2d818e8e04..008db35459 100644 --- a/repos/gems/src/app/tresor_init/main.cc +++ b/repos/gems/src/app/tresor_init/main.cc @@ -34,86 +34,116 @@ using namespace Tresor; namespace Tresor_init { class Main; } -class Tresor_init::Main : private Vfs::Env::User, private Tresor::Module_composition, public Tresor::Module, public Module_channel +class Tresor_init::Main : private Vfs::Env::User, private Crypto_key_files_interface { private: - enum State { INIT, REQ_GENERATED, INIT_SBS_SUCCEEDED }; + struct Crypto_key + { + Key_id const key_id; + Vfs::Vfs_handle &encrypt_file; + Vfs::Vfs_handle &decrypt_file; + }; Env &_env; Heap _heap { _env.ram(), _env.rm() }; Attached_rom_dataspace _config_rom { _env, "config" }; Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; Signal_handler
_sigh { _env.ep(), *this, &Main::_handle_signal }; - Constructible _cfg { }; - Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") }; - Crypto _crypto { _vfs_env, _config_rom.xml().sub_node("crypto") }; - Block_io _block_io { _vfs_env, _config_rom.xml().sub_node("block-io") }; + Configuration _cfg { _config_rom.xml() }; + Tresor::Path const _crypto_path { _config_rom.xml().sub_node("crypto").attribute_value("path", Tresor::Path()) }; + 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 &_crypto_add_key_file { open_file(_vfs_env, { _crypto_path, "/add_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) }; + Vfs::Vfs_handle &_crypto_remove_key_file { open_file(_vfs_env, { _crypto_path, "/remove_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) }; + 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) }; + Trust_anchor _trust_anchor { { _ta_decrypt_file, _ta_encrypt_file, _ta_generate_key_file, _ta_initialize_file, _ta_hash_file } }; + Crypto _crypto { {*this, _crypto_add_key_file, _crypto_remove_key_file} }; + Block_io _block_io { _block_io_file }; + Constructible _crypto_keys[2] { }; Pba_allocator _pba_alloc { NR_OF_SUPERBLOCK_SLOTS }; Vbd_initializer _vbd_initializer { }; Ft_initializer _ft_initializer { }; Sb_initializer _sb_initializer { }; - bool _generated_req_success { }; - State _state { INIT }; + Sb_initializer::Initialize _init_superblocks {{ + Tree_configuration { + (Tree_level_index)(_cfg.vbd_nr_of_lvls() - 1), + (Tree_degree)_cfg.vbd_nr_of_children(), + _cfg.vbd_nr_of_leafs() + }, + Tree_configuration { + (Tree_level_index)_cfg.ft_nr_of_lvls() - 1, + (Tree_degree)_cfg.ft_nr_of_children(), + _cfg.ft_nr_of_leafs() + }, + Tree_configuration { + (Tree_level_index)_cfg.ft_nr_of_lvls() - 1, + (Tree_degree)_cfg.ft_nr_of_children(), + _cfg.ft_nr_of_leafs() + }, + _pba_alloc + }}; - NONCOPYABLE(Main); - - void _generated_req_completed(State_uint state_uint) override + Constructible &_crypto_key(Key_id key_id) { - if (!_generated_req_success) { - error("command pool: request failed because generated request failed)"); - _env.parent().exit(-1); - return; - } - _state = (State)state_uint; + for (Constructible &key : _crypto_keys) + if (key.constructed() && key->key_id == key_id) + return key; + ASSERT_NEVER_REACHED; } - void wakeup_vfs_user() override { _sigh.local_submit(); } - void _wakeup_back_end_services() { _vfs_env.io().commit(); } void _handle_signal() { - execute_modules(); + while(_sb_initializer.execute(_init_superblocks, _block_io, _trust_anchor, _vbd_initializer, _ft_initializer)); + if (_init_superblocks.complete()) + _env.parent().exit(_init_superblocks.success() ? 0 : -1); _wakeup_back_end_services(); } + /******************************** + ** Crypto_key_files_interface ** + ********************************/ + + void add_crypto_key(Key_id key_id) override + { + for (Constructible &key : _crypto_keys) + if (!key.constructed()) { + key.construct(key_id, + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR), + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) + ); + return; + } + ASSERT_NEVER_REACHED; + } + + void remove_crypto_key(Key_id key_id) override + { + Constructible &crypto_key = _crypto_key(key_id); + _vfs_env.root_dir().close(&crypto_key->encrypt_file); + _vfs_env.root_dir().close(&crypto_key->decrypt_file); + crypto_key.destruct(); + } + + Vfs::Vfs_handle &encrypt_file(Key_id key_id) override { return _crypto_key(key_id)->encrypt_file; } + Vfs::Vfs_handle &decrypt_file(Key_id key_id) override { return _crypto_key(key_id)->decrypt_file; } + + /******************** + ** Vfs::Env::User ** + ********************/ + + void wakeup_vfs_user() override { _sigh.local_submit(); } + public: - Main(Env &env) : Module_channel { COMMAND_POOL, 0 }, _env { env } - { - add_module(COMMAND_POOL, *this); - add_module(CRYPTO, _crypto); - add_module(TRUST_ANCHOR, _trust_anchor); - add_module(BLOCK_IO, _block_io); - add_module(VBD_INITIALIZER, _vbd_initializer); - add_module(FT_INITIALIZER, _ft_initializer); - add_module(SB_INITIALIZER, _sb_initializer); - add_channel(*this); - _cfg.construct(_config_rom.xml()); - _handle_signal(); - } - - void execute(bool &progress) override - { - switch(_state) { - case INIT: - - generate_req( - INIT_SBS_SUCCEEDED, progress, (Tree_level_index)_cfg->vbd_nr_of_lvls() - 1, - (Tree_degree)_cfg->vbd_nr_of_children(), _cfg->vbd_nr_of_leafs(), - (Tree_level_index)_cfg->ft_nr_of_lvls() - 1, - (Tree_degree)_cfg->ft_nr_of_children(), _cfg->ft_nr_of_leafs(), - (Tree_level_index)_cfg->ft_nr_of_lvls() - 1, - (Tree_degree)_cfg->ft_nr_of_children(), _cfg->ft_nr_of_leafs(), _pba_alloc, - _generated_req_success); - _state = REQ_GENERATED; - break; - - case INIT_SBS_SUCCEEDED: _env.parent().exit(0); break; - default: break; - } - } + Main(Env &env) : _env(env) { _handle_signal(); } }; void Component::construct(Genode::Env &env) { static Tresor_init::Main main { env }; } diff --git a/repos/gems/src/app/tresor_init_trust_anchor/component.cc b/repos/gems/src/app/tresor_init_trust_anchor/component.cc index f15f8c0988..45a8704778 100644 --- a/repos/gems/src/app/tresor_init_trust_anchor/component.cc +++ b/repos/gems/src/app/tresor_init_trust_anchor/component.cc @@ -89,9 +89,8 @@ class Main : Vfs::Env::User char const *name, Vfs::File_system &vfs, Genode::Allocator &alloc) - : - _vfs { vfs }, - _vfs_handle { nullptr } + : + _vfs(vfs), _vfs_handle(nullptr) { using Result = Vfs::Directory_service::Open_result; @@ -207,9 +206,7 @@ class Main : Vfs::Env::User public: - Main(Env &env) - : - _env { env } + Main(Env &env) : _env(env) { Xml_node const &config { _config_rom.xml() }; diff --git a/repos/gems/src/app/tresor_tester/main.cc b/repos/gems/src/app/tresor_tester/main.cc index e89b01457b..c63cc0d484 100644 --- a/repos/gems/src/app/tresor_tester/main.cc +++ b/repos/gems/src/app/tresor_tester/main.cc @@ -24,11 +24,10 @@ /* tresor includes */ #include #include -#include +#include #include #include #include -#include #include #include #include @@ -40,192 +39,182 @@ namespace Tresor_tester { + enum { VERBOSE = 0 }; + using namespace Genode; using namespace Tresor; using Salt = uint64_t; + template class Schedule; class Log_node; - class Benchmark_node; + class Start_benchmark_node; class Benchmark; - class Trust_anchor_node; - class Request_node; class Command; + class Initialize_trust_anchor_node; class Snapshot_reference; class Snapshot_reference_tree; - class Client_data; + class Request_node; class Main; - - template - T read_attribute(Xml_node const &node, char const *attr) - { - T value { }; - ASSERT(node.has_attribute(attr)); - ASSERT(node.attribute(attr).value(value)); - return value; - } } - -struct Tresor_tester::Log_node -{ - using String = Genode::String<128>; - - String const string; - - NONCOPYABLE(Log_node); - - Log_node(Xml_node const &node) : string { node.attribute_value("string", String { }) } { } -}; - - -struct Tresor_tester::Benchmark_node -{ - using Label = String<128>; - - enum Operation { START, STOP }; - - Operation const op; - bool const label_avail; - Label const label; - - NONCOPYABLE(Benchmark_node); - - Operation read_op_attr(Xml_node const &node) - { - ASSERT(node.has_attribute("op")); - if (node.attribute("op").has_value("start")) return START; - if (node.attribute("op").has_value("stop")) return STOP; - ASSERT_NEVER_REACHED; - } - - Benchmark_node(Xml_node const &node) - : - op { read_op_attr(node) }, label_avail { op == START && node.has_attribute("label") }, - label { label_avail ? node.attribute_value("label", Label { }) : Label { } } - { } - - Benchmark_node(Operation op, bool label_avail, Label label) : op(op), label_avail(label_avail), label(label) { } -}; - - -class Tresor_tester::Benchmark +template +class Tresor_tester::Schedule : Noncopyable { private: - enum State { STARTED, STOPPED }; - - Genode::Env &_env; - Timer::Connection _timer { _env }; - State _state { STOPPED }; - Microseconds _start_time { 0 }; - Number_of_blocks _num_virt_blks_read { 0 }; - Number_of_blocks _num_virt_blks_written { 0 }; - Benchmark_node const *_start_node_ptr { }; - - NONCOPYABLE(Benchmark); + T *_tail { }; + List _list { }; public: - Benchmark(Genode::Env &env) : _env { env } { } + using Item = List::Element; - void execute_cmd(Benchmark_node const &node) + void add_tail(T &request) { - switch (node.op) { - case Benchmark_node::START: + _list.insert(&request, _tail); + _tail = &request; + } - ASSERT(_state == STOPPED); - _num_virt_blks_read = 0; - _num_virt_blks_written = 0; - _state = STARTED; - _start_node_ptr = &node; - _start_time = _timer.curr_time().trunc_to_plain_us(); - break; + bool empty() const { return !_list.first(); } - case Benchmark_node::STOP: + template + void with_head(FN && fn) + { + if (_list.first()) + fn(*_list.first()); + } - ASSERT(_state == STARTED); - uint64_t const stop_time_us { _timer.curr_time().trunc_to_plain_us().value }; - log(""); - if (_start_node_ptr->label_avail) - log("Benchmark result \"", _start_node_ptr->label, "\""); - else - log("Benchmark result"); + void remove_head() + { + T *head = _list.first(); + if (!head) + return; - double const passed_time_sec { (double)(stop_time_us - _start_time.value) / (double)(1000 * 1000) }; - log(" Ran ", passed_time_sec, " seconds."); + _list.remove(head); + if (_tail == head) + _tail = _list.first(); + } - if (_num_virt_blks_read) { + template + void try_yield_head(CAN_YIELD_TO_FN && can_yield_to) + { + T *head = _list.first(); + if (!head) + return; - size_t const bytes_read { _num_virt_blks_read * Tresor::BLOCK_SIZE }; - double const mibyte_read { (double)bytes_read / (double)(1024 * 1024) }; - double const mibyte_per_sec_read { - (double)bytes_read / (double)passed_time_sec / (double)(1024 * 1024) }; + T *next = head->Item::_next; + if (!next || !can_yield_to(*next)) + return; - log(" Have read ", mibyte_read, " mebibyte in total."); - log(" Have read ", mibyte_per_sec_read, " mebibyte per second."); - } + remove_head(); + _list.insert(head, next); + } +}; - if (_num_virt_blks_written) { +class Tresor_tester::Benchmark : Noncopyable +{ + public: - size_t bytes_written { _num_virt_blks_written * Tresor::BLOCK_SIZE }; - double const mibyte_written { (double)bytes_written / (double)(1024 * 1024) }; - double const mibyte_per_sec_written { - (double)bytes_written / (double)passed_time_sec / (double)(1024 * 1024) }; + using Label = String<128>; - log(" Have written ", mibyte_written, " mebibyte in total."); - log(" Have written ", mibyte_per_sec_written, " mebibyte per second."); - } - log(""); - _state = STOPPED; - break; + private: + + Timer::Connection &_timer; + Label const _label; + Microseconds const _start_time; + Number_of_blocks _num_virt_blks_read { }; + Number_of_blocks _num_virt_blks_written { }; + + /* + * Noncopyable + */ + Benchmark(Benchmark const &) = delete; + Benchmark &operator = (Benchmark const &) = delete; + + public: + + Benchmark(Timer::Connection &timer, Label const &label) + : + _timer(timer), _label(label), _start_time(timer.curr_time().trunc_to_plain_us()) + { } + + ~Benchmark() + { + uint64_t const stop_time_us { _timer.curr_time().trunc_to_plain_us().value }; + log(""); + log("Benchmark result \"", _label, "\""); + + double const passed_time_sec { (double)(stop_time_us - _start_time.value) / (double)(1000 * 1000) }; + log(" Ran ", passed_time_sec, " seconds."); + + if (_num_virt_blks_read) { + + size_t const bytes_read { _num_virt_blks_read * Tresor::BLOCK_SIZE }; + double const mibyte_read { (double)bytes_read / (double)(1024 * 1024) }; + double const mibyte_per_sec_read { + (double)bytes_read / (double)passed_time_sec / (double)(1024 * 1024) }; + + log(" Have read ", mibyte_read, " mebibyte in total."); + log(" Have read ", mibyte_per_sec_read, " mebibyte per second."); } + if (_num_virt_blks_written) { + + size_t bytes_written { _num_virt_blks_written * Tresor::BLOCK_SIZE }; + double const mibyte_written { (double)bytes_written / (double)(1024 * 1024) }; + double const mibyte_per_sec_written { + (double)bytes_written / (double)passed_time_sec / (double)(1024 * 1024) }; + + log(" Have written ", mibyte_written, " mebibyte in total."); + log(" Have written ", mibyte_per_sec_written, " mebibyte per second."); + } + log(""); } void raise_num_virt_blks_read() { _num_virt_blks_read++; } void raise_num_virt_blks_written() { _num_virt_blks_written++; } }; - -struct Tresor_tester::Trust_anchor_node +struct Tresor_tester::Start_benchmark_node : Noncopyable { - using Operation = Trust_anchor_request::Type; + Benchmark::Label const label; - Operation const op; + Start_benchmark_node(Xml_node const &node) : label(node.attribute_value("label", Benchmark::Label())) { } +}; + +struct Tresor_tester::Log_node : Noncopyable +{ + using String = Genode::String<128>; + + String const string; + + Log_node(Xml_node const &node) : string(node.attribute_value("string", String())) { } +}; + +struct Tresor_tester::Initialize_trust_anchor_node : Noncopyable +{ Passphrase const passphrase; - NONCOPYABLE(Trust_anchor_node); - - Operation read_op_attr(Xml_node const &node) - { - ASSERT(node.has_attribute("op")); - if (node.attribute("op").has_value("initialize")) - return Operation::INITIALIZE; - ASSERT_NEVER_REACHED; - } - - Trust_anchor_node(Xml_node const &node) + Initialize_trust_anchor_node(Xml_node const &node) : - op { read_op_attr(node) }, - passphrase { op == Operation::INITIALIZE ? node.attribute_value("passphrase", Passphrase()) : Passphrase() } + passphrase(node.attribute_value("passphrase", Passphrase())) { } }; - -struct Tresor_tester::Request_node +struct Tresor_tester::Request_node : Noncopyable { - using Operation = Tresor::Request::Operation; + enum Operation { + READ, WRITE, SYNC, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, REKEY, EXTEND_VBD, + EXTEND_FREE_TREE, DEINITIALIZE, INITIALIZE }; Operation const op; Virtual_block_address const vba; - Number_of_blocks const count; + Number_of_blocks const num_blocks; bool const sync; bool const salt_avail; Salt const salt; Snapshot_id const snap_id; - NONCOPYABLE(Request_node); - Operation read_op_attr(Xml_node const &node) { ASSERT(node.has_attribute("op")); @@ -234,7 +223,7 @@ struct Tresor_tester::Request_node if (node.attribute("op").has_value("sync")) return Operation::SYNC; if (node.attribute("op").has_value("create_snapshot")) return Operation::CREATE_SNAPSHOT; if (node.attribute("op").has_value("discard_snapshot")) return Operation::DISCARD_SNAPSHOT; - if (node.attribute("op").has_value("extend_ft")) return Operation::EXTEND_FT; + if (node.attribute("op").has_value("extend_ft")) return Operation::EXTEND_FREE_TREE; if (node.attribute("op").has_value("extend_vbd")) return Operation::EXTEND_VBD; if (node.attribute("op").has_value("rekey")) return Operation::REKEY; if (node.attribute("op").has_value("deinitialize")) return Operation::DEINITIALIZE; @@ -243,156 +232,143 @@ struct Tresor_tester::Request_node Request_node(Xml_node const &node) : - op { read_op_attr(node) }, - vba { has_vba() ? read_attribute(node, "vba") : 0 }, - count { has_count() ? read_attribute(node, "count") : 0 }, - sync { read_attribute(node, "sync") }, - salt_avail { has_salt() ? node.has_attribute("salt") : false }, - salt { has_salt() && salt_avail ? read_attribute(node, "salt") : 0 }, - snap_id { has_snap_id() ? read_attribute(node, "id") : 0 } + op(read_op_attr(node)), + vba(node.attribute_value("vba", (Virtual_block_address)0)), + num_blocks(node.attribute_value("num_blocks", (Number_of_blocks)0)), + sync(node.attribute_value("sync", false)), + salt_avail(node.has_attribute("salt")), + salt(node.attribute_value("salt", (Salt)0)), + snap_id(node.attribute_value("id", (Snapshot_id)0)) { } +}; - bool has_vba() const { return op == Operation::READ || op == Operation::WRITE || op == Operation::SYNC; } +struct Tresor_tester::Command : Avl_node, Schedule::Item +{ + friend class Schedule; - bool has_salt() const { return op == Operation::READ || op == Operation::WRITE; } + using Node_type = String<64>; + using Id = uint64_t; - bool has_count() const + enum Type { + REQUEST, INIT_TRUST_ANCHOR, START_BENCHMARK, FINISH_BENCHMARK, CONSTRUCT, DESTRUCT, INITIALIZE, CHECK, + CHECK_SNAPSHOTS, LOG }; + + enum State { INIT, IN_PROGRESS, COMPLETE }; + + /* + * Noncopyable + */ + Command(Command const &) = delete; + Command &operator = (Command const &) = delete; + + Type const type; + Id const id; + State state { INIT }; + Constructible request_node { }; + Constructible init_trust_anchor_node { }; + Constructible start_benchmark_node { }; + Constructible log_node { }; + Constructible initialize_config { }; + Trust_anchor::Initialize *init_trust_anchor_ptr { }; + Sb_initializer::Initialize *init_superblocks_ptr { }; + Sb_check::Check *check_superblocks_ptr { }; + Superblock_control::Initialize *init_sb_control_ptr { }; + Superblock_control::Deinitialize *deinit_sb_control_ptr { }; + Superblock_control::Create_snapshot *create_snap_ptr { }; + Superblock_control::Discard_snapshot *discard_snap_ptr { }; + Superblock_control::Write_vbas *write_vbas_ptr { }; + Superblock_control::Read_vbas *read_vbas_ptr { }; + Superblock_control::Rekey *rekey_ptr { }; + Superblock_control::Extend_vbd *extend_vbd_ptr { }; + Superblock_control::Extend_free_tree *extend_free_tree_ptr { }; + Superblock_control::Synchronize *sync_ptr { }; + Superblock::State sb_state { Superblock::INVALID }; + Generation generation { }; + bool rekey_finished { }; + bool extend_vbd_finished { }; + bool extend_free_tree_finished { }; + bool restarted { }; + + char const *op_to_string() const { - return op == Operation::READ || op == Operation::WRITE || op == Operation::SYNC || - op == Operation::EXTEND_FT || op == Operation::EXTEND_VBD; + switch (type) { + case INITIALIZE: return "initialize tresor container"; + case REQUEST: + switch(request_node->op) { + case Request_node::INITIALIZE: return "initialize superblock control"; + case Request_node::DEINITIALIZE: return "deinitialize superblock control"; + case Request_node::CREATE_SNAPSHOT: return "create snapshot"; + case Request_node::DISCARD_SNAPSHOT: return "discard snapshot"; + case Request_node::READ: return "read"; + case Request_node::WRITE: return "write"; + case Request_node::SYNC: return "sync"; + case Request_node::REKEY: return "rekey"; + case Request_node::EXTEND_VBD: return "extend virtual block device"; + case Request_node::EXTEND_FREE_TREE: return "extend free tree"; + } + ASSERT_NEVER_REACHED; + case INIT_TRUST_ANCHOR: return "initialize trust anchor"; + case START_BENCHMARK: return "start benchmark"; + case FINISH_BENCHMARK: return "finish benchmark"; + case CONSTRUCT: return "construct"; + case DESTRUCT: return "destruct"; + case CHECK: return "check"; + case CHECK_SNAPSHOTS: return "check_snapshots"; + case LOG: return "log"; + } + ASSERT_NEVER_REACHED; } - bool has_snap_id() const { return op == Operation::DISCARD_SNAPSHOT || op == Operation::CREATE_SNAPSHOT; } + static Type type_from_node(Xml_node const &node) + { + Xml_node::Type const nt = node.type(); + if (nt == "initialize") { return INITIALIZE; } + if (nt == "request") { return REQUEST; } + if (nt == "initialize-trust-anchor") { return INIT_TRUST_ANCHOR; } + if (nt == "start-benchmark") { return START_BENCHMARK; } + if (nt == "finish-benchmark") { return FINISH_BENCHMARK; } + if (nt == "construct") { return CONSTRUCT; } + if (nt == "destruct") { return DESTRUCT; } + if (nt == "check") { return CHECK; } + if (nt == "check-snapshots") { return CHECK_SNAPSHOTS; } + if (nt == "log") { return LOG; } + ASSERT_NEVER_REACHED; + } - void print(Genode::Output &out) const { Genode::print(out, "op ", Tresor::Request::op_to_string(op)); } + bool higher(Command *other_ptr) { return other_ptr->id > id; } + + Command(Xml_node const &node, Id id) : type(type_from_node(node)), id(id) + { + switch (type) { + case INITIALIZE: initialize_config.construct(node); break; + case REQUEST: request_node.construct(node); break; + case INIT_TRUST_ANCHOR: init_trust_anchor_node.construct(node); break; + case START_BENCHMARK: start_benchmark_node.construct(node); break; + case LOG: log_node.construct(node); break; + default: break; + } + } + + template + void with_command(Command::Id id, FUNC && func) + { + if (id != this->id) { + Command *cmd_ptr { Avl_node::child(id > this->id) }; + ASSERT(cmd_ptr); + cmd_ptr->with_command(id, func); + } else + func(*this); + } + + void print(Genode::Output &out) const { Genode::print(out, "id ", id, " op \"", op_to_string(), "\""); } }; - -class Tresor_tester::Command : public Module_channel -{ - public: - - enum Type { INVALID, REQUEST, TRUST_ANCHOR, BENCHMARK, CONSTRUCT, DESTRUCT, INITIALIZE, CHECK, CHECK_SNAPSHOTS, LOG }; - - enum State { PENDING, IN_PROGRESS, CREATE_SNAP_COMPLETED, DISCARD_SNAP_COMPLETED, COMPLETED }; - - private: - - using Type_string = String<64>; - - Tresor_tester::Main &_main; - Type _type { INVALID }; - Module_channel_id _id { 0 }; - State _state { PENDING }; - bool _success { false }; - Generation _gen { INVALID_GENERATION }; - bool _data_mismatch { false }; - Constructible _request_node { }; - Constructible _trust_anchor_node { }; - Constructible _benchmark_node { }; - Constructible _log_node { }; - Constructible _initialize { }; - - NONCOPYABLE(Command); - - void _generated_req_completed(State_uint state_uint) override; - - static char const *_type_to_string(Type type) - { - switch (type) { - case INITIALIZE: return "initialize"; - case INVALID: return "invalid"; - case REQUEST: return "request"; - case TRUST_ANCHOR: return "trust_anchor"; - case BENCHMARK: return "benchmark"; - case CONSTRUCT: return "construct"; - case DESTRUCT: return "destruct"; - case CHECK: return "check"; - case CHECK_SNAPSHOTS: return "check_snapshots"; - case LOG: return "log"; - } - ASSERT_NEVER_REACHED; - } - - static Type _type_from_string(Type_string str) - { - if (str == "initialize") { return INITIALIZE; } - if (str == "request") { return REQUEST; } - if (str == "trust-anchor") { return TRUST_ANCHOR; } - if (str == "benchmark") { return BENCHMARK; } - if (str == "construct") { return CONSTRUCT; } - if (str == "destruct") { return DESTRUCT; } - if (str == "check") { return CHECK; } - if (str == "check-snapshots") { return CHECK_SNAPSHOTS; } - if (str == "log") { return LOG; } - ASSERT_NEVER_REACHED; - } - - public: - - Command(Xml_node const &node, Tresor_tester::Main &main, Module_channel_id id) - : - Module_channel { COMMAND_POOL, id }, _main { main }, _type { _type_from_string(node.type()) }, _id { id } - { - switch (_type) { - case INITIALIZE: _initialize.construct(node); break; - case REQUEST: _request_node.construct(node); break; - case TRUST_ANCHOR: _trust_anchor_node.construct(node); break; - case BENCHMARK: _benchmark_node.construct(node); break; - case LOG: _log_node.construct(node); break; - default: break; - } - } - - bool may_have_data_mismatch() const - { - return _type == REQUEST && _request_node->op == Tresor::Request::READ && _request_node->salt_avail; - } - - bool synchronize() const - { - switch (_type) { - case REQUEST: return _request_node->sync; - case INVALID: ASSERT_NEVER_REACHED; - default: return true; - } - ASSERT_NEVER_REACHED; - } - - void print(Genode::Output &out) const - { - Genode::print(out, "id ", _id, " type ", _type_to_string(_type)); - if (_type == REQUEST) - Genode::print(out, " ", *_request_node); - } - - Type type() const { return _type ; } - State state() const { return _state ; } - Module_channel_id id() const { return _id ; } - bool success() const { return _success ; } - bool data_mismatch() const { return _data_mismatch ; } - Request_node const &request_node() const { return *_request_node ; } - Trust_anchor_node const &trust_anchor_node() const { return *_trust_anchor_node; } - Benchmark_node const &benchmark_node() const { return *_benchmark_node ; } - Log_node const &log_node() const { return *_log_node ; } - Tresor_init::Configuration const &initialize() const { return *_initialize ; } - - void state (State state) { _state = state; } - void success (bool success) { _success = success; } - void data_mismatch (bool data_mismatch) { _data_mismatch = data_mismatch; } - - void execute(bool &progress); -}; - - -struct Tresor_tester::Snapshot_reference : public Genode::Avl_node +struct Tresor_tester::Snapshot_reference : Avl_node { Snapshot_id const id; Generation const gen; - NONCOPYABLE(Snapshot_reference); - - Snapshot_reference(Snapshot_id id, Generation gen) : id { id }, gen { gen } { } + Snapshot_reference(Snapshot_id id, Generation gen) : id(id), gen(gen) { } template void with_ref(Snapshot_id target_id, FUNC && func) const @@ -412,7 +388,6 @@ struct Tresor_tester::Snapshot_reference : public Genode::Avl_nodeid > id; } }; - struct Tresor_tester::Snapshot_reference_tree : public Avl_tree { template @@ -425,61 +400,54 @@ struct Tresor_tester::Snapshot_reference_tree : public Avl_tree _signal_handler { _env.ep(), *this, &Main::_handle_signal }; - Benchmark _benchmark { _env }; - Module_channel_id _next_command_id { 0 }; - unsigned long _num_uncompleted_cmds { 0 }; + Tresor::Path const _crypto_path { _config_rom.xml().sub_node("crypto").attribute_value("path", Tresor::Path()) }; + 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 &_crypto_add_key_file { open_file(_vfs_env, { _crypto_path, "/add_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) }; + Vfs::Vfs_handle &_crypto_remove_key_file { open_file(_vfs_env, { _crypto_path, "/remove_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) }; + 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) }; + Timer::Connection _timer { _env }; + Constructible _benchmark { }; + Avl_tree _command_tree { }; + Schedule _command_schedule { }; unsigned long _num_errors { 0 }; - Tresor::Block _blk_data { }; Snapshot_reference_tree _snap_refs { }; Constructible _free_tree { }; Constructible _vbd { }; Constructible _sb_control { }; - Constructible _request_pool { }; - Constructible _client_data { }; Constructible _meta_tree { }; - Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") }; - Crypto _crypto { _vfs_env, _config_rom.xml().sub_node("crypto") }; - Block_io _block_io { _vfs_env, _config_rom.xml().sub_node("block-io") }; + Trust_anchor _trust_anchor { { _ta_decrypt_file, _ta_encrypt_file, _ta_generate_key_file, _ta_initialize_file, _ta_hash_file } }; + Crypto _crypto { {*this, _crypto_add_key_file, _crypto_remove_key_file} }; + Block_io _block_io { _block_io_file }; Pba_allocator _pba_alloc { NR_OF_SUPERBLOCK_SLOTS }; Vbd_initializer _vbd_initializer { }; Ft_initializer _ft_initializer { }; Sb_initializer _sb_initializer { }; - Sb_check _sb_check { }; Vbd_check _vbd_check { }; Ft_check _ft_check { }; - bool _generated_req_success { false }; - - NONCOPYABLE(Main); + Sb_check _sb_check { }; + Constructible _crypto_keys[2] { }; static void _generate_blk_data(Tresor::Block &blk_data, Virtual_block_address vba, Salt salt) { @@ -494,66 +462,16 @@ class Tresor_tester::Main : private Vfs::Env::User, private Module_composition, } } - template - void _with_first_processable_cmd(FUNC && func) + Constructible &_crypto_key(Key_id key_id) { - bool first_uncompleted_cmd { true }; - bool done { false }; - for_each_channel([&] (Command &cmd) - { - if (done) - return; - - if (cmd.state() == Command::PENDING) { - done = true; - if (first_uncompleted_cmd || !cmd.synchronize()) - func(cmd); - } - if (cmd.state() == Command::IN_PROGRESS) { - if (cmd.synchronize()) - done = true; - else - first_uncompleted_cmd = false; - } - }); - } - - void _try_end_program() - { - if (_num_uncompleted_cmds == 0) { - if (_num_errors > 0) { - for_each_channel([&] (Command &cmd) { - if (cmd.state() != Command::COMPLETED) - return; - - if (cmd.success() && (!cmd.may_have_data_mismatch() || !cmd.data_mismatch())) - return; - - log("cmd failed: ", cmd); - }); - _env.parent().exit(-1); - } else - _env.parent().exit(0); - } + for (Constructible &key : _crypto_keys) + if (key.constructed() && key->key_id == key_id) + return key; + ASSERT_NEVER_REACHED; } void _wakeup_back_end_services() { _vfs_env.io().commit(); } - void _handle_signal() - { - execute_modules(); - _try_end_program(); - _wakeup_back_end_services(); - } - - void wakeup_vfs_user() override { _signal_handler.local_submit(); } - - void execute(bool &progress) override - { - _with_first_processable_cmd([&] (Command &cmd) { - cmd.execute(progress); }); - } - void _remove_snap_ref(Snapshot_reference &ref) { _snap_refs.remove(&ref); @@ -561,50 +479,471 @@ class Tresor_tester::Main : private Vfs::Env::User, private Module_composition, destroy(_heap, &ref); } - public: - - Main(Genode::Env &env) : _env { env } + void _reset_snap_refs() { - add_module(CRYPTO, _crypto); - add_module(TRUST_ANCHOR, _trust_anchor); - add_module(COMMAND_POOL, *this); - add_module(BLOCK_IO, _block_io); - add_module(VBD_INITIALIZER, _vbd_initializer); - add_module(FT_INITIALIZER, _ft_initializer); - add_module(SB_INITIALIZER, _sb_initializer); - add_module(SB_CHECK, _sb_check); - add_module(VBD_CHECK, _vbd_check); - add_module(FT_CHECK, _ft_check); - _config_rom.xml().sub_node("commands").for_each_sub_node([&] (Xml_node const &node) { - add_channel(*new (_heap) Command(node, *this, _next_command_id++)); - _num_uncompleted_cmds++; - }); - _handle_signal(); + while (_snap_refs.first()) + _remove_snap_ref(*_snap_refs.first()); } - void mark_command_in_progress(Module_channel_id cmd_id) + void _remove_snap_refs_with_same_gen(Snapshot_id id) { - with_channel(cmd_id, [&] (Command &cmd) { - ASSERT(cmd.state() == Command::PENDING); - cmd.state(Command::IN_PROGRESS); - }); + Generation gen { _snap_id_to_gen(id) }; + while (1) { + Snapshot_reference *ref_ptr { nullptr }; + _snap_refs.for_each([&] (Snapshot_reference const &ref) { + if (!ref_ptr && ref.gen == gen) + ref_ptr = const_cast(&ref); + }); + if (ref_ptr) { + _remove_snap_ref(*ref_ptr); + } else + break; + } } - void mark_command_completed(Module_channel_id cmd_id, bool success) + void _mark_command_complete(Command &cmd, bool success) { - with_channel(cmd_id, [&] (Command &cmd) { - ASSERT(cmd.state() == Command::IN_PROGRESS); - cmd.state(Command::COMPLETED); - _num_uncompleted_cmds--; - cmd.success(success); - if (!cmd.success()) { - warning("cmd ", cmd, " failed"); - _num_errors++; + cmd.state = Command::COMPLETE; + if (VERBOSE) + log("finished command: ", cmd); + if (!success) { + _num_errors++; + error("command failed: ", cmd); + } + } + + void _mark_command_in_progress(Command &cmd, bool &progress) + { + cmd.state = Command::IN_PROGRESS; + progress = true; + if (VERBOSE && !cmd.restarted) { + log("started command: ", cmd); + cmd.restarted = true; + } + } + + template + void _try_complete_command(Command &cmd, REQUEST &req, bool &progress) + { + if (!req.complete()) + return; + + _mark_command_complete(cmd, req.success()); + destroy(_heap, &req); + progress = true; + return; + } + + template + void _try_complete_multi_request_command(Command &cmd, REQUEST &req, bool cmd_finished, bool &progress) + { + if (!req.complete()) + return; + + if (!req.success()) { + _mark_command_complete(cmd, false); + destroy(_heap, &req); + progress = true; + return; + } + destroy(_heap, &req); + if (cmd_finished) { + _mark_command_complete(cmd, true); + return; + } + cmd.state = Command::INIT; + progress = true; + return; + } + + bool _execute_command(Command &cmd) + { + bool progress = false; + switch (cmd.type) { + case Command::INIT_TRUST_ANCHOR: + + switch(cmd.state) { + case Command::INIT: + { + Initialize_trust_anchor_node &node { *cmd.init_trust_anchor_node }; + cmd.init_trust_anchor_ptr = new (_heap) Trust_anchor::Initialize({node.passphrase}); + _mark_command_in_progress(cmd, progress); + break; } - }); + case Command::IN_PROGRESS: + { + Trust_anchor::Initialize &req = *cmd.init_trust_anchor_ptr; + progress |= _trust_anchor.execute(req); + _try_complete_command(cmd, req, progress); + break; + } + default: break; + } + break; + + case Command::INITIALIZE: + + switch(cmd.state) { + case Command::INIT: + { + _reset_snap_refs(); + Tresor_init::Configuration const &cfg { *cmd.initialize_config }; + cmd.init_superblocks_ptr = new (_heap) Sb_initializer::Initialize({ + Tree_configuration { + (Tree_level_index)(cfg.vbd_nr_of_lvls() - 1), + (Tree_degree)cfg.vbd_nr_of_children(), + cfg.vbd_nr_of_leafs() + }, + Tree_configuration { + (Tree_level_index)cfg.ft_nr_of_lvls() - 1, + (Tree_degree)cfg.ft_nr_of_children(), + cfg.ft_nr_of_leafs() + }, + Tree_configuration { + (Tree_level_index)cfg.ft_nr_of_lvls() - 1, + (Tree_degree)cfg.ft_nr_of_children(), + cfg.ft_nr_of_leafs() + }, + _pba_alloc + }); + _mark_command_in_progress(cmd, progress); + break; + } + case Command::IN_PROGRESS: + { + Sb_initializer::Initialize &req = *cmd.init_superblocks_ptr; + progress |= _sb_initializer.execute(req, _block_io, _trust_anchor, _vbd_initializer, _ft_initializer); + _try_complete_command(cmd, req, progress); + break; + } + default: break; + } + break; + + case Command::CONSTRUCT: + + switch(cmd.state) { + case Command::INIT: + + _meta_tree.construct(); + _free_tree.construct(); + _vbd.construct(); + _sb_control.construct(); + cmd.init_sb_control_ptr = new (_heap) Superblock_control::Initialize({cmd.sb_state}); + _mark_command_in_progress(cmd, progress); + break; + + case Command::IN_PROGRESS: + { + Superblock_control::Initialize &req = *cmd.init_sb_control_ptr; + progress |= _sb_control->execute(req, _block_io, _crypto, _trust_anchor); + _try_complete_command(cmd, req, progress); + break; + } + default: break; + } + break; + + case Command::DESTRUCT: + + switch(cmd.state) { + case Command::INIT: + + _meta_tree.destruct(); + _free_tree.destruct(); + _vbd.destruct(); + _sb_control.destruct(); + _mark_command_complete(cmd, true); + progress = true; + break; + + default: break; + } + break; + + case Command::START_BENCHMARK: + + switch(cmd.state) { + case Command::INIT: + + _benchmark.construct(_timer, cmd.start_benchmark_node->label); + _mark_command_complete(cmd, true); + progress = true; + break; + + default: break; + } + break; + + case Command::FINISH_BENCHMARK: + + switch(cmd.state) { + case Command::INIT: + + _benchmark.destruct(); + _mark_command_complete(cmd, true); + progress = true; + break; + + default: break; + } + break; + + case Command::CHECK_SNAPSHOTS: + + switch(cmd.state) { + case Command::INIT: + { + bool success { true }; + Snapshots_info snap_info { _sb_control->snapshots_info() }; + bool snap_gen_ok[MAX_NR_OF_SNAPSHOTS] { false }; + _snap_refs.for_each([&] (Snapshot_reference const &snap_ref) { + bool snap_ref_ok { false }; + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + if (snap_info.generations[idx] == snap_ref.gen) { + snap_ref_ok = true; + snap_gen_ok[idx] = true; + } + } + if (!snap_ref_ok) { + warning("snap (", snap_ref, ") not known to tresor"); + success = false; + } + }); + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + if (snap_info.generations[idx] != INVALID_GENERATION && !snap_gen_ok[idx]) { + warning("snap (idx ", idx, " gen ", snap_info.generations[idx], ") not known to tester"); + success = false; + } + } + _mark_command_complete(cmd, success); + progress = true; + break; + } + default: break; + } + break; + + case Command::REQUEST: + + switch(cmd.state) { + case Command::INIT: + { + Request_node const &node { *cmd.request_node }; + switch (node.op) { + case Request_node::WRITE: + cmd.write_vbas_ptr = new (_heap) Superblock_control::Write_vbas({node.vba, node.num_blocks, 0, cmd.id}); + break; + case Request_node::READ: + cmd.read_vbas_ptr = new (_heap) Superblock_control::Read_vbas({node.vba, node.num_blocks, 0, cmd.id}); + break; + case Request_node::SYNC: + cmd.sync_ptr = new (_heap) Superblock_control::Synchronize({}); + break; + case Request_node::REKEY: + cmd.rekey_ptr = new (_heap) Superblock_control::Rekey({cmd.rekey_finished}); + break; + case Request_node::EXTEND_VBD: + cmd.extend_vbd_ptr = new (_heap) Superblock_control::Extend_vbd({node.num_blocks, cmd.extend_vbd_finished}); + break; + case Request_node::EXTEND_FREE_TREE: + cmd.extend_free_tree_ptr = new (_heap) Superblock_control::Extend_free_tree({node.num_blocks, cmd.extend_free_tree_finished}); + break; + case Request_node::DEINITIALIZE: + cmd.deinit_sb_control_ptr = new (_heap) Superblock_control::Deinitialize({}); + break; + case Request_node::CREATE_SNAPSHOT: + cmd.create_snap_ptr = new (_heap) Superblock_control::Create_snapshot({cmd.generation}); + break; + case Request_node::DISCARD_SNAPSHOT: + cmd.discard_snap_ptr = new (_heap) Superblock_control::Discard_snapshot({_snap_id_to_gen(node.snap_id)}); + break; + default: ASSERT_NEVER_REACHED; + } + _mark_command_in_progress(cmd, progress); + break; + } + case Command::IN_PROGRESS: + { + Request_node &node = *cmd.request_node; + switch (node.op) { + case Request_node::WRITE: + { + Superblock_control::Write_vbas &req = *cmd.write_vbas_ptr; + progress |= _sb_control->execute(req, *_vbd, *this, _block_io, *_free_tree, *_meta_tree, _crypto); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::READ: + { + Superblock_control::Read_vbas &req = *cmd.read_vbas_ptr; + progress |= _sb_control->execute(req, *_vbd, *this, _block_io, _crypto); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::SYNC: + { + Superblock_control::Synchronize &req = *cmd.sync_ptr; + progress |= _sb_control->execute(req, _block_io, _trust_anchor); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::REKEY: + { + Superblock_control::Rekey &req = *cmd.rekey_ptr; + progress |= _sb_control->execute(req, *_vbd, *_free_tree, *_meta_tree, _block_io, _crypto, _trust_anchor); + _try_complete_multi_request_command(cmd, req, cmd.rekey_finished, progress); + break; + } + case Request_node::EXTEND_VBD: + { + Superblock_control::Extend_vbd &req = *cmd.extend_vbd_ptr; + progress |= _sb_control->execute(req, *_vbd, *_free_tree, *_meta_tree, _block_io, _trust_anchor); + _try_complete_multi_request_command(cmd, req, cmd.extend_vbd_finished, progress); + break; + } + case Request_node::EXTEND_FREE_TREE: + { + Superblock_control::Extend_free_tree &req = *cmd.extend_free_tree_ptr; + progress |= _sb_control->execute(req, *_free_tree, *_meta_tree, _block_io, _trust_anchor); + _try_complete_multi_request_command(cmd, req, cmd.extend_free_tree_finished, progress); + break; + } + case Request_node::DEINITIALIZE: + { + Superblock_control::Deinitialize &req = *cmd.deinit_sb_control_ptr; + progress |= _sb_control->execute(req, _block_io, _crypto, _trust_anchor); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::CREATE_SNAPSHOT: + { + Superblock_control::Create_snapshot &req = *cmd.create_snap_ptr; + progress |= _sb_control->execute(req, _block_io, _trust_anchor); + if (req.complete() && req.success()) + _snap_refs.insert(new (_heap) Snapshot_reference { cmd.request_node->snap_id, cmd.generation }); + _try_complete_command(cmd, req, progress); + break; + } + case Request_node::DISCARD_SNAPSHOT: + { + Superblock_control::Discard_snapshot &req = *cmd.discard_snap_ptr; + progress |= _sb_control->execute(req, _block_io, _trust_anchor); + if (req.complete() && req.success()) + _remove_snap_refs_with_same_gen(node.snap_id); + _try_complete_command(cmd, req, progress); + break; + } + default: ASSERT_NEVER_REACHED; + } + break; + } + default: break; + } + break; + + case Command::LOG: + + switch(cmd.state) { + case Command::INIT: + + log("\n", cmd.log_node->string, "\n"); + _mark_command_complete(cmd, true); + progress = true; + break; + + default: break; + } + break; + + case Command::CHECK: + + switch(cmd.state) { + case Command::INIT: + + cmd.check_superblocks_ptr = new (_heap) Sb_check::Check(); + _mark_command_in_progress(cmd, progress); + break; + + case Command::IN_PROGRESS: + { + Sb_check::Check &req = *cmd.check_superblocks_ptr; + progress |= _sb_check.execute(req, _vbd_check, _ft_check, _block_io); + _try_complete_command(cmd, req, progress); + break; + } + default: break; + } + break; + + default: ASSERT_NEVER_REACHED; + } + return progress; } - Generation snap_id_to_gen(Snapshot_id id) + bool _execute_commands() + { + bool progress = false; + _command_schedule.with_head([&] (Command &head) { + + progress |= _execute_command(head); + if (head.state == Command::COMPLETE) { + _command_schedule.remove_head(); + return; + } + if (head.type != Command::REQUEST) + return; + + Request_node::Operation op = head.request_node->op; + if (op != Request_node::REKEY && + op != Request_node::EXTEND_VBD && + op != Request_node::EXTEND_FREE_TREE) + return; + + if (head.request_node->sync) + return; + + if (head.state != Command::INIT) + return; + + _command_schedule.try_yield_head([&] (Command &to_cmd) { + + if (to_cmd.type != Command::REQUEST) + return false; + + Request_node::Operation op = to_cmd.request_node->op; + return op == Request_node::READ || + op == Request_node::WRITE || + op == Request_node::SYNC || + op == Request_node::DISCARD_SNAPSHOT; + }); + }); + return progress; + } + + void _handle_signal() + { + while (_execute_commands()); + if (_command_schedule.empty()) { + if (_num_errors) { + error(_num_errors, " command", _num_errors > 1 ? "s" : "", " failed!"); + _env.parent().exit(-1); + } else { + log("All commands succeeded!"); + _env.parent().exit(0); + } + } + _wakeup_back_end_services(); + } + + template + void _with_command(Command::Id id, FUNC && func) + { + ASSERT(_command_tree.first()); + _command_tree.first()->with_command(id, func); + } + + Generation _snap_id_to_gen(Snapshot_id id) { Generation gen { INVALID_GENERATION }; _snap_refs.with_ref(id, [&] (Snapshot_reference const &ref) { @@ -613,230 +952,93 @@ class Tresor_tester::Main : private Vfs::Env::User, private Module_composition, return gen; } - void add_snap_ref(Snapshot_id id, Generation gen) { _snap_refs.insert(new (_heap) Snapshot_reference { id, gen }); } - void remove_snap_refs_with_same_gen(Snapshot_id id) + /******************** + ** Vfs::Env::User ** + ********************/ + + void wakeup_vfs_user() override { _signal_handler.local_submit(); } + + + /******************************** + ** Crypto_key_files_interface ** + ********************************/ + + void add_crypto_key(Key_id key_id) override { - Generation gen { snap_id_to_gen(id) }; - while (1) { - Snapshot_reference *ref_ptr { nullptr }; - _snap_refs.for_each([&] (Snapshot_reference const &ref) { - if (!ref_ptr && ref.gen == gen) - ref_ptr = const_cast(&ref); - }); - if (ref_ptr) - _remove_snap_ref(*ref_ptr); - else - break; - } + for (Constructible &key : _crypto_keys) + if (!key.constructed()) { + key.construct(key_id, + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR), + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) + ); + return; + } + ASSERT_NEVER_REACHED; } - void reset_snap_refs() + void remove_crypto_key(Key_id key_id) override { - while (_snap_refs.first()) - _remove_snap_ref(*_snap_refs.first()); + Constructible &crypto_key = _crypto_key(key_id); + _vfs_env.root_dir().close(&crypto_key->encrypt_file); + _vfs_env.root_dir().close(&crypto_key->decrypt_file); + crypto_key.destruct(); } - Pba_allocator &pba_alloc() { return _pba_alloc; } + Vfs::Vfs_handle &encrypt_file(Key_id key_id) override { return _crypto_key(key_id)->encrypt_file; } + Vfs::Vfs_handle &decrypt_file(Key_id key_id) override { return _crypto_key(key_id)->decrypt_file; } - void generate_blk_data(Request_tag tresor_req_tag, Virtual_block_address vba, Tresor::Block &blk_data) + + /*************************** + ** Client_data_interface ** + ***************************/ + + void obtain_data(Obtain_data_attr const &attr) override { - with_channel(tresor_req_tag, [&] (Command &cmd) { - ASSERT(cmd.type() == Command::REQUEST); - Request_node const &req_node { cmd.request_node() }; - if (req_node.salt_avail) - _generate_blk_data(blk_data, vba, req_node.salt); + _with_command(attr.in_req_tag, [&] (Command &cmd) { + ASSERT(cmd.type == Command::REQUEST); + Request_node const &node { *cmd.request_node }; + if (node.salt_avail) + _generate_blk_data(attr.out_blk, attr.in_vba, node.salt); }); - _benchmark.raise_num_virt_blks_written(); + if (_benchmark.constructed()) + _benchmark->raise_num_virt_blks_written(); } - void verify_blk_data(Request_tag tresor_req_tag, Virtual_block_address vba, Tresor::Block &blk_data) + void supply_data(Supply_data_attr const &attr) override { - with_channel(tresor_req_tag, [&] (Command &cmd) { - ASSERT(cmd.type() == Command::REQUEST); - Request_node const &req_node { cmd.request_node() }; - if (req_node.salt_avail) { + _with_command(attr.in_req_tag, [&] (Command &cmd) { + ASSERT(cmd.type == Command::REQUEST); + Request_node const &node { *cmd.request_node }; + if (node.salt_avail) { Tresor::Block gen_blk_data { }; - _generate_blk_data(gen_blk_data, vba, req_node.salt); + _generate_blk_data(gen_blk_data, attr.in_vba, node.salt); - if (memcmp(&blk_data, &gen_blk_data, BLOCK_SIZE)) { - cmd.data_mismatch(true); - warning("client data mismatch: vba=", vba, " req_tag=", tresor_req_tag); + if (memcmp(&attr.in_blk, &gen_blk_data, BLOCK_SIZE)) { + warning("client data mismatch: vba=", attr.in_vba, " req_tag=", attr.in_req_tag); _num_errors++; } } }); - _benchmark.raise_num_virt_blks_read(); + if (_benchmark.constructed()) + _benchmark->raise_num_virt_blks_read(); } - void construct_tresor_modules() - { - _free_tree.construct(); - _vbd.construct(); - _sb_control.construct(); - _request_pool.construct(); - _client_data.construct(*this); - _meta_tree.construct(); - add_module(FREE_TREE, *_free_tree); - add_module(VIRTUAL_BLOCK_DEVICE, *_vbd); - add_module(SUPERBLOCK_CONTROL, *_sb_control); - add_module(REQUEST_POOL, *_request_pool); - add_module(CLIENT_DATA, *_client_data); - add_module(META_TREE, *_meta_tree); - } + public: - void destruct_tresor_modules() + Main(Genode::Env &env) : _env(env) { - remove_module(META_TREE); - remove_module(CLIENT_DATA); - remove_module(REQUEST_POOL); - remove_module(SUPERBLOCK_CONTROL); - remove_module(VIRTUAL_BLOCK_DEVICE); - remove_module(FREE_TREE); - _meta_tree.destruct(); - _client_data.destruct(); - _request_pool.destruct(); - _sb_control.destruct(); - _vbd.destruct(); - _free_tree.destruct(); - } - - void check_snapshots(Command &cmd, bool &progress) - { - mark_command_in_progress(cmd.id()); - bool success { true }; - Snapshots_info snap_info { _sb_control->snapshots_info() }; - bool snap_gen_ok[MAX_NR_OF_SNAPSHOTS] { false }; - _snap_refs.for_each([&] (Snapshot_reference const &snap_ref) { - bool snap_ref_ok { false }; - for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { - if (snap_info.generations[idx] == snap_ref.gen) { - snap_ref_ok = true; - snap_gen_ok[idx] = true; - } - } - if (!snap_ref_ok) { - warning("snap (", snap_ref, ") not known to tresor"); - _num_errors++; - success = false; - } + Command::Id command_id { 0 }; + _config_rom.xml().sub_node("commands").for_each_sub_node([&] (Xml_node const &node) { + Command *cmd_ptr = new (_heap) Command(node, command_id++); + _command_tree.insert(cmd_ptr); + _command_schedule.add_tail(*cmd_ptr); }); - for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { - if (snap_info.generations[idx] != INVALID_GENERATION && !snap_gen_ok[idx]) { - warning("snap (idx ", idx, " gen ", snap_info.generations[idx], ") not known to tester"); - _num_errors++; - success = false; - } - } - mark_command_completed(cmd.id(), success); - progress = true; + _handle_signal(); } - - Benchmark &benchmark() { return _benchmark; } }; -void Tresor_tester::Client_data::_request_submitted(Module_request &mod_req) -{ - Request &req { *static_cast(&mod_req) }; - switch (req._type) { - case Request::OBTAIN_PLAINTEXT_BLK: _main.generate_blk_data(req._req_tag, req._vba, req._blk); break; - case Request::SUPPLY_PLAINTEXT_BLK: _main.verify_blk_data(req._req_tag, req._vba, req._blk); break; - } - req._success = true; -} - - -void Tresor_tester::Command::_generated_req_completed(State_uint state_uint) -{ - if (state_uint == CREATE_SNAP_COMPLETED) - _main.add_snap_ref(request_node().snap_id, _gen); - - if (state_uint == DISCARD_SNAP_COMPLETED) - _main.remove_snap_refs_with_same_gen(request_node().snap_id); - - _main.mark_command_completed(id(), _success); -} - - -void Tresor_tester::Command::execute(bool &progress) -{ - switch (type()) { - case REQUEST: - { - Request_node const &node { request_node() }; - State state { COMPLETED }; - _gen = INVALID_GENERATION; - if (node.op == Request::DISCARD_SNAPSHOT) { - _gen = _main.snap_id_to_gen(node.snap_id); - state = DISCARD_SNAP_COMPLETED; - } - if (node.op == Request::CREATE_SNAPSHOT) - state = CREATE_SNAP_COMPLETED; - - generate_req( - state, progress, node.op, node.has_vba() ? node.vba : 0, - 0, node.has_count() ? node.count : 0, 0, id(), _gen, _success); - - _main.mark_command_in_progress(id()); - break; - } - case Command::TRUST_ANCHOR: - { - Trust_anchor_node const &node { trust_anchor_node() }; - ASSERT(node.op == Trust_anchor_request::INITIALIZE); - generate_req(COMPLETED, progress, node.passphrase, _success); - _main.mark_command_in_progress(id()); - break; - } - case Command::INITIALIZE: - { - _main.reset_snap_refs(); - Tresor_init::Configuration const &cfg { initialize() }; - generate_req(COMPLETED, progress, - (Tree_level_index)(cfg.vbd_nr_of_lvls() - 1), - (Tree_degree)cfg.vbd_nr_of_children(), cfg.vbd_nr_of_leafs(), - (Tree_level_index)cfg.ft_nr_of_lvls() - 1, - (Tree_degree)cfg.ft_nr_of_children(), cfg.ft_nr_of_leafs(), - (Tree_level_index)cfg.ft_nr_of_lvls() - 1, - (Tree_degree)cfg.ft_nr_of_children(), cfg.ft_nr_of_leafs(), _main.pba_alloc(), _success); - _main.mark_command_in_progress(id()); - break; - } - case Command::CHECK: - generate_req(COMPLETED, progress, _success); - _main.mark_command_in_progress(id()); - break; - case LOG: - log("\n", log_node().string, "\n"); - _main.mark_command_in_progress(id()); - _main.mark_command_completed(id(), true); - progress = true; - break; - case BENCHMARK: - _main.benchmark().execute_cmd(benchmark_node()); - _main.mark_command_in_progress(id()); - _main.mark_command_completed(id(), true); - progress = true; - break; - case CONSTRUCT: - _main.construct_tresor_modules(); - _main.mark_command_in_progress(id()); - _main.mark_command_completed(id(), true); - progress = true; - break; - case DESTRUCT: - _main.destruct_tresor_modules(); - _main.mark_command_in_progress(id()); - _main.mark_command_completed(id(), true); - progress = true; - break; - case CHECK_SNAPSHOTS: _main.check_snapshots(*this, progress); break; - default: break; - } -} - - void Component::construct(Genode::Env &env) { static Tresor_tester::Main main(env); } diff --git a/repos/gems/src/lib/tresor/block_io.cc b/repos/gems/src/lib/tresor/block_io.cc index e1c0b6b2ee..9abc54eee4 100644 --- a/repos/gems/src/lib/tresor/block_io.cc +++ b/repos/gems/src/lib/tresor/block_io.cc @@ -12,199 +12,79 @@ */ /* tresor includes */ -#include #include #include using namespace Tresor; -Block_io_request::Block_io_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type, - Request_offset client_req_offset, Request_tag client_req_tag, Key_id key_id, - Physical_block_address pba, Virtual_block_address vba, Block &blk, Hash &hash, - bool &success) -: - Module_request { src_module_id, src_chan_id, BLOCK_IO }, _type { type }, - _client_req_offset { client_req_offset }, _client_req_tag { client_req_tag }, - _key_id { key_id }, _pba { pba }, _vba { vba }, _blk { blk }, _hash { hash }, _success { success } -{ } - -char const *Block_io_request::type_to_string(Type type) +bool Block_io::Sync::execute(Vfs::Vfs_handle &file) { - switch (type) { - case READ: return "read"; - case WRITE: return "write"; - case SYNC: return "sync"; - case READ_CLIENT_DATA: return "read_client_data"; - case WRITE_CLIENT_DATA: return "write_client_data"; - } - ASSERT_NEVER_REACHED; -} + bool progress = false; + switch (_helper.state) { + case INIT: + _file.construct(_helper.state, file); + _helper.state = SYNC; + progress = true; + break; -void Block_io_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_generated_req_success) { - error("block io: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -void Block_io_channel::_mark_req_failed(bool &progress, Error_string str) -{ - error("request failed: failed to ", str); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Block_io_channel::_mark_req_successful(bool &progress) -{ - Request &req { *_req_ptr }; - req._success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; - if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == req._pba)) { - switch (req._type) { - case Request::READ: - case Request::WRITE: - log("block_io: ", req.type_to_string(req._type), " pba ", req._pba, " hash ", hash(req._blk)); - break; - default: break; - } - } -} - - -void Block_io_channel::_read(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _file.read(READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); break; - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + case SYNC: _file->sync(SYNC_OK, FILE_ERR, progress); break; + case SYNC_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Block_io_channel::_read_client_data(bool &progress) +bool Block_io::Read::execute(Vfs::Vfs_handle &file) { + bool progress = false; + switch (_helper.state) { + case INIT: - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _file.read(READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); break; + _file.construct(_helper.state, file); + _helper.state = READ; + progress = true; + break; + + case READ: _file->read(READ_OK, FILE_ERR, _attr.in_pba * BLOCK_SIZE, { (char *)&_attr.out_block, BLOCK_SIZE }, progress); break; case READ_OK: - calc_hash(_blk, req._hash); - _generate_req( - 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); - return; - - case PLAINTEXT_BLK_SUPPLIED: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: break; - } -} - - -void Block_io_channel::_write_client_data(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - _generate_req( - CIPHERTEXT_BLK_OBTAINED, progress, Crypto_request::ENCRYPT_CLIENT_DATA, req._client_req_offset, - req._client_req_tag, req._key_id, *(Key_value *)0, req._pba, req._vba, _blk); + _helper.mark_succeeded(progress); + if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == _attr.in_pba)) + log("block_io: ", *this, " hash ", hash(_attr.out_block)); break; - case CIPHERTEXT_BLK_OBTAINED: + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; + default: break; + } + return progress; +} - calc_hash(_blk, req._hash); - _file.write(WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); break; + +bool Block_io::Write::execute(Vfs::Vfs_handle &file) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, file); + _helper.state = WRITE; + progress = true; break; - case WRITE_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + case WRITE: _file->write(WRITE_OK, FILE_ERR, _attr.in_pba * BLOCK_SIZE, { (char *)&_attr.in_block, BLOCK_SIZE }, progress); break; + case WRITE_OK: + + _helper.mark_succeeded(progress); + if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == _attr.in_pba)) + log("block_io: ", *this, " hash ", hash(_attr.in_block)); + break; + + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } -} - - -void Block_io_channel::_write(bool &progress) -{ - - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _file.write(WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); break; - case WRITE_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: break; - } -} - - -void Block_io_channel::_sync(bool &progress) -{ - switch (_state) { - case REQ_SUBMITTED: _file.sync(SYNC_OK, FILE_ERR, progress); break; - case SYNC_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: break; - } -} - - -void Block_io_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - switch (_req_ptr->_type) { - case Request::READ: _read(progress); break; - case Request::WRITE: _write(progress); break; - case Request::SYNC: _sync(progress); break; - case Request::READ_CLIENT_DATA: _read_client_data(progress); break; - case Request::WRITE_CLIENT_DATA: _write_client_data(progress); break; - } -} - - -void Block_io::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -void Block_io_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Block_io_channel::Block_io_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node) -: - Module_channel { BLOCK_IO, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) } -{ } - - -Block_io::Block_io(Vfs::Env &vfs_env, Xml_node const &xml_node) -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++, vfs_env, xml_node); - add_channel(*chan); - } + return progress; } diff --git a/repos/gems/src/lib/tresor/crypto.cc b/repos/gems/src/lib/tresor/crypto.cc index 8a2f7e2a64..22b40a8d98 100644 --- a/repos/gems/src/lib/tresor/crypto.cc +++ b/repos/gems/src/lib/tresor/crypto.cc @@ -13,317 +13,101 @@ /* tresor includes */ #include -#include #include using namespace Tresor; -Crypto_request::Crypto_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type, - Request_offset client_req_offset, Request_tag client_req_tag, Key_id key_id, - Key_value const &key_plaintext, Physical_block_address pba, Virtual_block_address vba, - Block &blk, bool &success) -: - Module_request { src_module_id, src_chan_id, CRYPTO }, _type { type }, _client_req_offset { client_req_offset }, - _client_req_tag { client_req_tag }, _pba { pba }, _vba { vba }, _key_id { key_id }, _key_plaintext { key_plaintext }, - _blk { blk }, _success { success } -{ } - - -void Crypto_request::print(Output &out) const +bool Crypto::Add_key::execute(Crypto::Attr const &crypto_attr) { - Genode::print(out, type_to_string(_type)); - switch (_type) { - case ADD_KEY: - case REMOVE_KEY: Genode::print(out, " ", _key_id); break; - case DECRYPT: - case ENCRYPT: - case DECRYPT_CLIENT_DATA: - case ENCRYPT_CLIENT_DATA: Genode::print(out, " pba ", _pba); break; - default: break; - } -} + bool progress { false }; + switch (_helper.state) { + case INIT: - -char const *Crypto_request::type_to_string(Type type) -{ - switch (type) { - case ADD_KEY: return "add_key"; - case REMOVE_KEY: return "remove_key"; - case ENCRYPT_CLIENT_DATA: return "encrypt_client_data"; - case DECRYPT_CLIENT_DATA: return "decrypt_client_data"; - case ENCRYPT: return "encrypt"; - case DECRYPT: return "decrypt"; - } - ASSERT_NEVER_REACHED; -} - - -void Crypto_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_generated_req_success) { - error("crypto: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -Constructible &Crypto_channel::_key_dir(Key_id key_id) -{ - for (Constructible &key_dir : _key_dirs) - if (key_dir.constructed() && key_dir->key_id == key_id) - return key_dir; - ASSERT_NEVER_REACHED; -} - - -void Crypto_channel::_mark_req_failed(bool &progress, char const *str) -{ - error("crypto: request (", *_req_ptr, ") failed at step \"", str, "\""); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Crypto_channel::_mark_req_successful(bool &progress) -{ - Request &req { *_req_ptr }; - req._success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; - if (VERBOSE_WRITE_VBA && req._type == Request::ENCRYPT_CLIENT_DATA) - log(" encrypt leaf data: plaintext ", _blk, " hash ", hash(_blk), - "\n update branch:\n ", Branch_lvl_prefix("leaf data: "), req._blk); - - if (VERBOSE_READ_VBA && req._type == Request::DECRYPT_CLIENT_DATA) - log(" ", Branch_lvl_prefix("leaf data: "), req._blk, - "\n decrypt leaf data: plaintext ", _blk, " hash ", hash(_blk)); - - if (VERBOSE_CRYPTO) { - switch (req._type) { - case Request::DECRYPT_CLIENT_DATA: - case Request::ENCRYPT_CLIENT_DATA: - log("crypto: ", req.type_to_string(req._type), " pba ", req._pba, " vba ", req._vba, - " plain ", _blk, " cipher ", req._blk); - break; - default: break; - } - } - if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == req._pba)) { - switch (req._type) { - case Request::DECRYPT_CLIENT_DATA: - log("block_io: read pba ", req._pba, " hash ", hash(req._blk), " (plaintext hash ", hash(_blk), ")"); - break; - case Request::ENCRYPT_CLIENT_DATA: - log("block_io: write pba ", req._pba, " hash ", hash(req._blk), " (plaintext hash ", hash(_blk), ")"); - break; - default: break; - } - } -} - - -void Crypto_channel::_add_key(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - memcpy(_add_key_buf, &req._key_id, sizeof(Key_id)); - memcpy(_add_key_buf + sizeof(Key_id), &req._key_plaintext, KEY_SIZE); - _add_key_file.write(WRITE_OK, FILE_ERR, 0, { _add_key_buf, sizeof(_add_key_buf) }, progress); + _file.construct(_helper.state, crypto_attr.add_key_file); + memcpy(_write_buf, &_attr.in_key.id, sizeof(Key_id)); + memcpy(_write_buf + sizeof(Key_id), &_attr.in_key.value, sizeof(Key_value)); + _helper.state = WRITE; + progress = true; break; - case WRITE_OK: - { - Constructible *key_dir_ptr { nullptr }; - for (Constructible &key_dir : _key_dirs) - if (!key_dir.constructed()) - key_dir_ptr = &key_dir; - if (!key_dir_ptr) { - _mark_req_failed(progress, "find unused key dir"); - break; - } - key_dir_ptr->construct(*this, req._key_id); - _mark_req_successful(progress); - break; - } - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: break; - } -} - - -void Crypto_channel::_remove_key(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _remove_key_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._key_id, sizeof(Key_id) }, progress); break; + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { _write_buf, sizeof(_write_buf) }, progress); break; case WRITE_OK: - _key_dir(req._key_id).destruct(); - _mark_req_successful(progress); + crypto_attr.key_files.add_crypto_key(_attr.in_key.id); + _helper.mark_succeeded(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: return; - } -} - - -void Crypto_channel::_encrypt_client_data(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - _generate_req( - PLAINTEXT_BLK_OBTAINED, progress, Client_data_request::OBTAIN_PLAINTEXT_BLK, - req._client_req_offset, req._client_req_tag, req._pba, req._vba, _blk);; - break; - - case PLAINTEXT_BLK_OBTAINED: - - _key_dir(req._key_id)->encrypt_file.write( - WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); - break; - - case WRITE_OK: - - _key_dir(req._key_id)->encrypt_file.read( - READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); - break; - - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation"); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Crypto_channel::_encrypt(bool &progress) +bool Crypto::Remove_key::execute(Crypto::Attr const &crypto_attr) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress { false }; + switch (_helper.state) { + case INIT: - _key_dir(req._key_id)->encrypt_file.write( - WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + _file.construct(_helper.state, crypto_attr.remove_key_file); + _helper.state = WRITE; + progress = true; break; + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_key_id, sizeof(Key_id) }, progress); break; case WRITE_OK: - _key_dir(req._key_id)->encrypt_file.read( - READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + crypto_attr.key_files.remove_crypto_key(_attr.in_key_id); + _helper.mark_succeeded(progress); break; - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation"); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Crypto_channel::_decrypt(bool &progress) +bool Crypto::Encrypt::execute(Crypto::Attr const &crypto_attr) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress { false }; + switch (_helper.state) { + case INIT: - _key_dir(req._key_id)->decrypt_file.write( - WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + _file.construct(_helper.state, crypto_attr.key_files.encrypt_file(_attr.in_key_id)); + _offset = _attr.in_pba * BLOCK_SIZE; + _helper.state = WRITE; + progress = true; break; - case WRITE_OK: - - _key_dir(req._key_id)->decrypt_file.read( - READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); - break; - - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation"); break; + case WRITE: _file->write(WRITE_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file-operation error"); break; default: break; } + return progress; } -void Crypto_channel::_decrypt_client_data(bool &progress) +bool Crypto::Decrypt::execute(Crypto::Attr const &crypto_attr) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress { false }; + switch (_helper.state) { + case INIT: - _key_dir(req._key_id)->decrypt_file.write( - WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); + _file.construct(_helper.state, crypto_attr.key_files.decrypt_file(_attr.in_key_id)); + _offset = _attr.in_pba * BLOCK_SIZE; + _helper.state = WRITE; + progress = true; break; - case WRITE_OK: - - _key_dir(req._key_id)->decrypt_file.read( - READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); - break; - - case READ_OK: - - _generate_req( - PLAINTEXT_BLK_SUPPLIED, progress, Client_data_request::SUPPLY_PLAINTEXT_BLK, - req._client_req_offset, req._client_req_tag, req._pba, req._vba, _blk);; - break; - - case PLAINTEXT_BLK_SUPPLIED: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + case WRITE: _file->write(WRITE_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file-operation error"); break; default: break; } -} - - -void Crypto_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -void Crypto_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - switch (_req_ptr->_type) { - case Request::ADD_KEY: _add_key(progress); break; - case Request::REMOVE_KEY: _remove_key(progress); break; - case Request::DECRYPT: _decrypt(progress); break; - case Request::ENCRYPT: _encrypt(progress); break; - case Request::DECRYPT_CLIENT_DATA: _decrypt_client_data(progress); break; - case Request::ENCRYPT_CLIENT_DATA: _encrypt_client_data(progress); break; - } -} - - -void Crypto::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -Crypto_channel::Crypto_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node) -: - Module_channel { CRYPTO, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) } -{ } - - -Crypto::Crypto(Vfs::Env &vfs_env, Xml_node const &xml_node) -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++, vfs_env, xml_node); - add_channel(*chan); - } + return progress; } diff --git a/repos/gems/src/lib/tresor/free_tree.cc b/repos/gems/src/lib/tresor/free_tree.cc index 2b08554122..472a232d26 100644 --- a/repos/gems/src/lib/tresor/free_tree.cc +++ b/repos/gems/src/lib/tresor/free_tree.cc @@ -13,62 +13,22 @@ /* tresor includes */ #include -#include -#include #include using namespace Tresor; -char const *Free_tree_request::type_to_string(Type type) +bool Free_tree::Allocate_pbas::_can_alloc_pba_of(Type_2_node &node) { - switch (type) { - case ALLOC_FOR_NON_RKG: return "alloc_for_non_rkg"; - case ALLOC_FOR_RKG_CURR_GEN_BLKS: return "alloc_for_rkg_curr_gen_blks"; - case ALLOC_FOR_RKG_OLD_GEN_BLKS: return "alloc_for_rkg_old_gen_blks"; - case EXTENSION_STEP: return "extension_step"; - } - ASSERT_NEVER_REACHED; -} - - -Free_tree_request::Free_tree_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type, - Tree_root &ft, Tree_root &mt, Snapshots const &snapshots, Generation last_secured_gen, - Generation curr_gen, Generation free_gen, Number_of_blocks num_required_pbas, - Tree_walk_pbas &new_blocks, Type_1_node_walk const &old_blocks, - Tree_level_index max_lvl, Virtual_block_address vba, Tree_degree vbd_degree, - Virtual_block_address vbd_max_vba, bool rekeying, Key_id prev_key_id, - Key_id curr_key_id, Virtual_block_address rekeying_vba, Physical_block_address &pba, - Number_of_blocks &num_pbas, bool &success) - -: - Module_request { src_module_id, src_chan_id, FREE_TREE }, _type { type }, _ft { ft }, _mt { mt }, - _curr_gen { curr_gen }, _free_gen { free_gen }, _num_required_pbas { num_required_pbas }, _new_blocks { new_blocks }, - _old_blocks { old_blocks }, _max_lvl { max_lvl }, _vba { vba }, _vbd_degree { vbd_degree }, _vbd_max_vba { vbd_max_vba }, - _rekeying { rekeying }, _prev_key_id { prev_key_id }, _curr_key_id { curr_key_id }, _rekeying_vba { rekeying_vba }, - _success { success }, _snapshots { snapshots }, _last_secured_gen { last_secured_gen }, _pba { pba }, _num_pbas { num_pbas } -{ } - - -void Free_tree::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -bool Free_tree_channel::_can_alloc_pba_of(Type_2_node &node) -{ - Request &req { *_req_ptr }; - if (node.pba == 0 || node.pba == INVALID_PBA || node.free_gen > req._last_secured_gen) + if (node.pba == 0 || node.pba == INVALID_PBA || node.free_gen > _attr.in_last_secured_gen) return false; if (!node.reserved) return true; - if (req._rekeying && node.last_key_id == req._prev_key_id && node.last_vba < req._rekeying_vba) + if (_attr.in_rekeying && node.last_key_id == _attr.in_prev_key_id && node.last_vba < _attr.in_rekeying_vba) return true; - for (Snapshot const &snap : req._snapshots.items) + for (Snapshot const &snap : _attr.in_snapshots.items) if (snap.valid && node.free_gen > snap.gen && node.alloc_gen < snap.gen + 1) return false; @@ -76,62 +36,48 @@ bool Free_tree_channel::_can_alloc_pba_of(Type_2_node &node) } -void Free_tree_channel::_generated_req_completed(State_uint state_uint) +void Free_tree::Allocate_pbas::_alloc_pba_of(Type_2_node &t2_node) { - if (!_generated_req_success) { - error("free tree: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -void Free_tree_channel::_alloc_pba_of(Type_2_node &t2_node) -{ - Request &req { *_req_ptr }; Tree_level_index vbd_lvl { 0 }; - for (; vbd_lvl <= req._max_lvl && req._new_blocks.pbas[vbd_lvl]; vbd_lvl++); + for (; vbd_lvl <= _attr.in_max_lvl && _attr.in_out_new_blocks.pbas[vbd_lvl]; vbd_lvl++); - Virtual_block_address node_min_vba { vbd_node_min_vba(_vbd_degree_log_2, vbd_lvl, req._vba) }; - req._new_blocks.pbas[vbd_lvl] = t2_node.pba; - t2_node.alloc_gen = req._old_blocks.nodes[vbd_lvl].gen; - t2_node.free_gen = req._free_gen; - Virtual_block_address rkg_vba { req._rekeying_vba }; - switch (req._type) { - case Request::ALLOC_FOR_NON_RKG: + Virtual_block_address node_min_vba { vbd_node_min_vba(_vbd_degree_log_2, vbd_lvl, _attr.in_vba) }; + _attr.in_out_new_blocks.pbas[vbd_lvl] = t2_node.pba; + t2_node.alloc_gen = _attr.in_old_blocks.nodes[vbd_lvl].gen; + t2_node.free_gen = _attr.in_free_gen; + Virtual_block_address rkg_vba { _attr.in_rekeying_vba }; + switch (_attr.in_application) { + case NON_REKEYING: t2_node.reserved = true; - t2_node.pba = req._old_blocks.nodes[vbd_lvl].pba; + t2_node.pba = _attr.in_old_blocks.nodes[vbd_lvl].pba; t2_node.last_vba = node_min_vba; - if (req._rekeying) { - if (req._vba < rkg_vba) - t2_node.last_key_id = req._curr_key_id; + if (_attr.in_rekeying) { + if (_attr.in_vba < rkg_vba) + t2_node.last_key_id = _attr.in_curr_key_id; else - t2_node.last_key_id = req._prev_key_id; + t2_node.last_key_id = _attr.in_prev_key_id; } else - t2_node.last_key_id = req._curr_key_id; + t2_node.last_key_id = _attr.in_curr_key_id; break; - case Request::ALLOC_FOR_RKG_CURR_GEN_BLKS: + case REKEYING_IN_CURRENT_GENERATION: t2_node.reserved = false; - t2_node.pba = req._old_blocks.nodes[vbd_lvl].pba; + t2_node.pba = _attr.in_old_blocks.nodes[vbd_lvl].pba; t2_node.last_vba = node_min_vba; - t2_node.last_key_id = req._prev_key_id; + t2_node.last_key_id = _attr.in_prev_key_id; break; - case Request::ALLOC_FOR_RKG_OLD_GEN_BLKS: + case REKEYING_IN_OLDER_GENERATION: { t2_node.reserved = true; - Virtual_block_address node_max_vba { vbd_node_max_vba(_vbd_degree_log_2, vbd_lvl, req._vba) }; - if (rkg_vba < node_max_vba && rkg_vba < req._vbd_max_vba) { - t2_node.last_key_id = req._prev_key_id; + Virtual_block_address node_max_vba { vbd_node_max_vba(_vbd_degree_log_2, vbd_lvl, _attr.in_vba) }; + if (rkg_vba < node_max_vba && rkg_vba < _attr.in_vbd_max_vba) { + t2_node.last_key_id = _attr.in_prev_key_id; t2_node.last_vba = rkg_vba + 1; - } else if (rkg_vba == node_max_vba || rkg_vba == req._vbd_max_vba) { - t2_node.last_key_id = req._curr_key_id; + } else if (rkg_vba == node_max_vba || rkg_vba == _attr.in_vbd_max_vba) { + t2_node.last_key_id = _attr.in_curr_key_id; t2_node.last_vba = node_min_vba; } else ASSERT_NEVER_REACHED; @@ -142,78 +88,59 @@ void Free_tree_channel::_alloc_pba_of(Type_2_node &t2_node) } -void Free_tree_channel::_mark_req_failed(bool &progress, char const *str) -{ - error(Request::type_to_string(_req_ptr->_type), " request failed, reason: \"", str, "\""); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Free_tree_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Free_tree_channel::_start_tree_traversal(bool &progress) -{ - Request &req { *_req_ptr }; - _num_pbas = 0; - _lvl = req._ft.max_lvl; - _node_idx[_lvl] = 0; - _t1_blks[_lvl].nodes[_node_idx[_lvl]] = req._ft.t1_node(); - _generate_req(SEEK_DOWN, progress, req._ft.pba, _blk); -} - - -void Free_tree_channel::_traverse_curr_node(bool &progress) +void Free_tree::Allocate_pbas::_traverse_curr_node(bool &progress) { if (_lvl) { Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; if (t1_node.pba) - _generate_req(SEEK_DOWN, progress, t1_node.pba, _blk); + _read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, t1_node.pba, _blk); else { - _state = SEEK_LEFT_OR_UP; + _helper.state = SEEK_LEFT_OR_UP; progress = true; } } else { Type_2_node &t2_node { _t2_blk.nodes[_node_idx[_lvl]] }; - if (_num_pbas < _req_ptr->_num_required_pbas && _can_alloc_pba_of(t2_node)) { + if (_num_pbas < _attr.in_num_required_pbas && _can_alloc_pba_of(t2_node)) { if (_apply_allocation) _alloc_pba_of(t2_node); _num_pbas++; } - _state = SEEK_LEFT_OR_UP; + _helper.state = SEEK_LEFT_OR_UP; progress = true; } } -void Free_tree_channel::_alloc_pbas(bool &progress) +void Free_tree::Allocate_pbas::_start_tree_traversal(bool &progress) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + _num_pbas = 0; + _lvl = _attr.in_out_ft.max_lvl; + _node_idx[_lvl] = 0; + _t1_blks[_lvl].nodes[_node_idx[_lvl]] = _attr.in_out_ft.t1_node(); + _read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, _attr.in_out_ft.pba, _blk); +} - _vbd_degree_log_2 = log2(req._vbd_degree); + +bool Free_tree::Allocate_pbas::execute(Block_io &block_io, Meta_tree &meta_tree) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _vbd_degree_log_2 = log2(_attr.in_vbd_degree); _apply_allocation = false; _start_tree_traversal(progress); break; + case READ_BLK: progress |= _read_block.execute(block_io); break; case SEEK_DOWN: { if (!check_hash(_blk, _t1_blks[_lvl].nodes[_node_idx[_lvl]].hash)) { - _mark_req_failed(progress, "hash mismatch"); + _helper.mark_failed(progress, "hash mismatch"); break; } _lvl--; - _node_idx[_lvl] = req._ft.degree - 1; + _node_idx[_lvl] = _attr.in_out_ft.degree - 1; if (_lvl) _t1_blks[_lvl].decode_from_blk(_blk); else @@ -223,31 +150,31 @@ void Free_tree_channel::_alloc_pbas(bool &progress) } case SEEK_LEFT_OR_UP: - if (_lvl < req._ft.max_lvl) { - if (_node_idx[_lvl] && _num_pbas < _req_ptr->_num_required_pbas) { + if (_lvl < _attr.in_out_ft.max_lvl) { + if (_node_idx[_lvl] && _num_pbas < _attr.in_num_required_pbas) { _node_idx[_lvl]--; _traverse_curr_node(progress); } else { _lvl++; Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; if (_apply_allocation) - if (t1_node.is_volatile(req._curr_gen)) { - _state = WRITE_BLK; + if (t1_node.is_volatile(_attr.in_curr_gen)) { + _helper.state = ALLOC_PBA_SUCCEEDED; progress = true; } else - _generate_req(WRITE_BLK, progress, req._mt, req._curr_gen, t1_node.pba); + _allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, t1_node.pba); else { - _state = SEEK_LEFT_OR_UP; + _helper.state = SEEK_LEFT_OR_UP; progress = true; } } } else { if (_apply_allocation) { - req._ft.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); - _mark_req_successful(progress); + _attr.in_out_ft.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); + _helper.mark_succeeded(progress); } else { - if (_num_pbas < req._num_required_pbas) - _mark_req_failed(progress, "not enough free pbas"); + if (_num_pbas < _attr.in_num_required_pbas) + _helper.mark_failed(progress, "not enough free pbas"); else { _apply_allocation = true; _start_tree_traversal(progress); @@ -256,68 +183,55 @@ void Free_tree_channel::_alloc_pbas(bool &progress) } break; - case WRITE_BLK: + case ALLOC_PBA: progress |= _allocate_pba.execute(meta_tree, block_io); break; + case ALLOC_PBA_SUCCEEDED: { if (_lvl > 1) _t1_blks[_lvl - 1].encode_to_blk(_blk); else _t2_blk.encode_to_blk(_blk); Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; - t1_node.gen = req._curr_gen; + t1_node.gen = _attr.in_curr_gen; calc_hash(_blk, t1_node.hash); - _generate_req(SEEK_LEFT_OR_UP, progress, t1_node.pba, _blk); + _write_block.generate(_helper, WRITE_BLK, SEEK_LEFT_OR_UP, progress, t1_node.pba, _blk); break; } + case WRITE_BLK: progress |= _write_block.execute(block_io); break; default: break; } + return progress; } -void Free_tree_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - switch(_req_ptr->_type) { - case Request::ALLOC_FOR_NON_RKG: - case Request::ALLOC_FOR_RKG_CURR_GEN_BLKS: - case Request::ALLOC_FOR_RKG_OLD_GEN_BLKS: _alloc_pbas(progress); break; - case Request::EXTENSION_STEP: _extension_step(progress); break; - } -} - - -void Free_tree_channel::_generate_write_blk_req(bool &progress) +void Free_tree::Extend_tree::_generate_write_blk_req(bool &progress) { if (_lvl > 1) _t1_blks[_lvl].encode_to_blk(_blk); else _t2_blk.encode_to_blk(_blk); - _generate_req(WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _blk); if (VERBOSE_FT_EXTENSION) log(" lvl ", _lvl, " write to pba ", _new_pbas.pbas[_lvl]); } -void Free_tree_channel::_add_new_root_lvl() +void Free_tree::Extend_tree::_add_new_root_lvl() { - Request &req { *_req_ptr }; - ASSERT(req._ft.max_lvl < TREE_MAX_LEVEL); - req._ft.max_lvl++; - _t1_blks[req._ft.max_lvl] = { }; - _t1_blks[req._ft.max_lvl].nodes[0] = req._ft.t1_node(); - _new_pbas.pbas[req._ft.max_lvl] = alloc_pba_from_range(req._pba, req._num_pbas); - req._ft.t1_node({ _new_pbas.pbas[req._ft.max_lvl], req._curr_gen }); + ASSERT(_attr.in_out_ft.max_lvl < TREE_MAX_LEVEL); + _attr.in_out_ft.max_lvl++; + _t1_blks[_attr.in_out_ft.max_lvl] = { }; + _t1_blks[_attr.in_out_ft.max_lvl].nodes[0] = _attr.in_out_ft.t1_node(); + _new_pbas.pbas[_attr.in_out_ft.max_lvl] = alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas); + _attr.in_out_ft.t1_node({ _new_pbas.pbas[_attr.in_out_ft.max_lvl], _attr.in_curr_gen }); if (VERBOSE_FT_EXTENSION) - log(" set root: ", req._ft, "\n set lvl ", req._ft.max_lvl, " node 0: ", - _t1_blks[req._ft.max_lvl].nodes[0]); + log(" set root: ", _attr.in_out_ft, "\n set lvl ", _attr.in_out_ft.max_lvl, " node 0: ", + _t1_blks[_attr.in_out_ft.max_lvl].nodes[0]); } -void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_index dst_node_idx) +void Free_tree::Extend_tree::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_index dst_node_idx) { - Request &req { *_req_ptr }; _num_leaves = 0; _lvl = dst_lvl; if (dst_lvl > 1) { @@ -331,17 +245,17 @@ void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_i log(" reset lvl ", lvl); } } - for (; _lvl && req._num_pbas; _lvl--) { + for (; _lvl && _attr.in_out_num_pbas; _lvl--) { Tree_node_index node_idx = (_lvl == dst_lvl) ? dst_node_idx : 0; if (_lvl > 1) { - _new_pbas.pbas[_lvl - 1] = alloc_pba_from_range(req._pba, req._num_pbas); - _t1_blks[_lvl].nodes[node_idx] = { _new_pbas.pbas[_lvl - 1], req._curr_gen }; + _new_pbas.pbas[_lvl - 1] = alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas); + _t1_blks[_lvl].nodes[node_idx] = { _new_pbas.pbas[_lvl - 1], _attr.in_curr_gen }; if (VERBOSE_FT_EXTENSION) log(" set _lvl d ", _lvl, " node ", node_idx, ": ", _t1_blks[_lvl].nodes[node_idx]); } else { - for (; node_idx < req._ft.degree && req._num_pbas; node_idx++) { - _t2_blk.nodes[node_idx] = { alloc_pba_from_range(req._pba, req._num_pbas) }; + for (; node_idx < _attr.in_out_ft.degree && _attr.in_out_num_pbas; node_idx++) { + _t2_blk.nodes[node_idx] = { alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas) }; _num_leaves++; if (VERBOSE_FT_EXTENSION) log(" set _lvl e ", _lvl, " node ", node_idx, ": ", _t2_blk.nodes[node_idx]); @@ -353,80 +267,80 @@ void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_i } -void Free_tree_channel::_extension_step(bool &progress) +bool Free_tree::Extend_tree::execute(Block_io &block_io, Meta_tree &meta_tree) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: _num_leaves = 0; - _vba = req._ft.num_leaves; + _vba = _attr.in_out_ft.num_leaves; _old_pbas = { }; _old_generations = { }; _new_pbas = { }; - _lvl = req._ft.max_lvl; - _old_pbas.pbas[_lvl] = req._ft.pba; - _old_generations.items[_lvl] = req._ft.gen; - if (_vba <= tree_max_max_vba(req._ft.degree, req._ft.max_lvl)) { + _lvl = _attr.in_out_ft.max_lvl; + _old_pbas.pbas[_lvl] = _attr.in_out_ft.pba; + _old_generations.items[_lvl] = _attr.in_out_ft.gen; + if (_vba <= tree_max_max_vba(_attr.in_out_ft.degree, _attr.in_out_ft.max_lvl)) { - _generate_req(READ_BLK_SUCCEEDED, progress, req._ft.pba, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _attr.in_out_ft.pba, _blk); if (VERBOSE_FT_EXTENSION) - log(" root (", req._ft, "): load to lvl ", _lvl); + log(" root (", _attr.in_out_ft, "): load to lvl ", _lvl); } else { _add_new_root_lvl(); - _add_new_branch_at(req._ft.max_lvl, 1); + _add_new_branch_at(_attr.in_out_ft.max_lvl, 1); _generate_write_blk_req(progress); if (VERBOSE_FT_EXTENSION) - log(" pbas allocated: curr gen ", req._curr_gen); + log(" pbas allocated: curr gen ", _attr.in_curr_gen); } break; + case READ_BLK: progress |= _read_block.execute(block_io); break; case READ_BLK_SUCCEEDED: if (_lvl > 1) { _t1_blks[_lvl].decode_from_blk(_blk); - if (_lvl < req._ft.max_lvl) { - Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + if (_lvl < _attr.in_out_ft.max_lvl) { + Tree_node_index node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree); if (!check_hash(_blk, _t1_blks[_lvl + 1].nodes[node_idx].hash)) - _mark_req_failed(progress, "hash mismatch"); + _helper.mark_failed(progress, "hash mismatch"); } else - if (!check_hash(_blk, req._ft.hash)) - _mark_req_failed(progress, "hash mismatch"); + if (!check_hash(_blk, _attr.in_out_ft.hash)) + _helper.mark_failed(progress, "hash mismatch"); - Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl, req._ft.degree); + Tree_node_index node_idx = tree_node_index(_vba, _lvl, _attr.in_out_ft.degree); Type_1_node &t1_node = _t1_blks[_lvl].nodes[node_idx]; if (t1_node.valid()) { _lvl--; _old_pbas.pbas [_lvl] = t1_node.pba; _old_generations.items[_lvl] = t1_node.gen; - _generate_req(READ_BLK_SUCCEEDED, progress, t1_node.pba, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, t1_node.pba, _blk); if (VERBOSE_FT_EXTENSION) log(" lvl ", _lvl + 1, " node ", node_idx, " (", t1_node, "): load to lvl ", _lvl); } else { _alloc_lvl = _lvl; _add_new_branch_at(_lvl, node_idx); - if (_old_generations.items[_alloc_lvl] == req._curr_gen) { + if (_old_generations.items[_alloc_lvl] == _attr.in_curr_gen) { _alloc_pba = _old_pbas.pbas[_alloc_lvl]; - _state = ALLOC_PBA_SUCCEEDED; + _helper.state = ALLOC_PBA_SUCCEEDED; progress = true; } else { _alloc_pba = _old_pbas.pbas[_alloc_lvl]; - _generate_req( - ALLOC_PBA_SUCCEEDED, progress, Meta_tree_request::ALLOC_PBA, req._mt, req._curr_gen, _alloc_pba); + _allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, _alloc_pba); } } } else { _t2_blk.decode_from_blk(_blk); - Tree_node_index t1_node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + Tree_node_index t1_node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree); if (!check_hash(_blk, _t1_blks[_lvl + 1].nodes[t1_node_idx].hash)) - _mark_req_failed(progress, "hash mismatch"); + _helper.mark_failed(progress, "hash mismatch"); - Tree_node_index t2_node_idx = t2_node_idx_for_vba(_vba, req._ft.degree); + Tree_node_index t2_node_idx = tree_node_index(_vba, _lvl, _attr.in_out_ft.degree); if (_t2_blk.nodes[t2_node_idx].valid()) - _mark_req_failed(progress, "t2 node valid"); + _helper.mark_failed(progress, "t2 node valid"); _add_new_branch_at(_lvl, t2_node_idx); _alloc_lvl = _lvl; @@ -434,41 +348,41 @@ void Free_tree_channel::_extension_step(bool &progress) log(" alloc lvl ", _alloc_lvl); _alloc_pba = _old_pbas.pbas[_alloc_lvl]; - _generate_req( - ALLOC_PBA_SUCCEEDED, progress, Meta_tree_request::ALLOC_PBA, req._mt, req._curr_gen, _alloc_pba); + _allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, _alloc_pba); } break; + case ALLOC_PBA: progress |= _allocate_pba.execute(meta_tree, block_io); break; case ALLOC_PBA_SUCCEEDED: _new_pbas.pbas[_alloc_lvl] = _alloc_pba; - if (_alloc_lvl < req._ft.max_lvl) { + if (_alloc_lvl < _attr.in_out_ft.max_lvl) { _alloc_lvl++; - if (_old_generations.items[_alloc_lvl] == req._curr_gen) { + if (_old_generations.items[_alloc_lvl] == _attr.in_curr_gen) { _alloc_pba = _old_pbas.pbas[_alloc_lvl]; - _state = ALLOC_PBA_SUCCEEDED; + _helper.state = ALLOC_PBA_SUCCEEDED; progress = true; } else { _alloc_pba = _old_pbas.pbas[_alloc_lvl]; - _generate_req( - ALLOC_PBA_SUCCEEDED, progress, Meta_tree_request::ALLOC_PBA, req._mt, req._curr_gen, _alloc_pba); + _allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, _alloc_pba); } } else { _generate_write_blk_req(progress); if (VERBOSE_FT_EXTENSION) - log(" pbas allocated: curr gen ", req._curr_gen); + log(" pbas allocated: curr gen ", _attr.in_curr_gen); } break; + case WRITE_BLK: progress |= _write_block.execute(block_io); break; case WRITE_BLK_SUCCEEDED: - if (_lvl < req._ft.max_lvl) { + if (_lvl < _attr.in_out_ft.max_lvl) { if (_lvl > 1) { - Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + Tree_node_index node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree); Type_1_node &t1_node { _t1_blks[_lvl + 1].nodes[node_idx] }; - t1_node = { _new_pbas.pbas[_lvl], req._curr_gen }; + t1_node = { _new_pbas.pbas[_lvl], _attr.in_curr_gen }; calc_hash(_blk, t1_node.hash); if (VERBOSE_FT_EXTENSION) log(" set lvl ", _lvl + 1, " node ", node_idx, ": ", t1_node); @@ -476,9 +390,9 @@ void Free_tree_channel::_extension_step(bool &progress) _lvl++; _generate_write_blk_req(progress); } else { - Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree); + Tree_node_index node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree); Type_1_node &t1_node = _t1_blks[_lvl + 1].nodes[node_idx]; - t1_node = { _new_pbas.pbas[_lvl], req._curr_gen }; + t1_node = { _new_pbas.pbas[_lvl], _attr.in_curr_gen }; calc_hash(_blk, t1_node.hash); if (VERBOSE_FT_EXTENSION) log(" set lvl ", _lvl + 1, " t1_node ", node_idx, ": ", t1_node); @@ -487,30 +401,14 @@ void Free_tree_channel::_extension_step(bool &progress) _generate_write_blk_req(progress); } } else { - req._ft.t1_node({ _new_pbas.pbas[_lvl], req._curr_gen }); - calc_hash(_blk, req._ft.hash); - req._ft.num_leaves += _num_leaves; - _mark_req_successful(progress); + _attr.in_out_ft.t1_node({ _new_pbas.pbas[_lvl], _attr.in_curr_gen }); + calc_hash(_blk, _attr.in_out_ft.hash); + _attr.in_out_ft.num_leaves += _num_leaves; + _helper.mark_succeeded(progress); } break; default: break; } -} - - -void Free_tree_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Free_tree::Free_tree() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } + return progress; } diff --git a/repos/gems/src/lib/tresor/ft_check.cc b/repos/gems/src/lib/tresor/ft_check.cc index ce24a19097..388b2a1634 100644 --- a/repos/gems/src/lib/tresor/ft_check.cc +++ b/repos/gems/src/lib/tresor/ft_check.cc @@ -13,73 +13,66 @@ /* tresor includes */ #include -#include #include using namespace Tresor; -Ft_check_request::Ft_check_request(Module_id src_mod, Module_channel_id src_chan, Tree_root const &ft, bool &success) -: - Module_request { src_mod, src_chan, FT_CHECK }, _ft { ft }, _success { success } -{ } - - -bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) +bool Ft_check::Check::_execute_node(Block_io &block_io, Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { bool &check_node { _check_node[lvl][node_idx] }; if (check_node == false) return false; - Request &req { *_req_ptr }; - switch (_state) { - case REQ_IN_PROGRESS: + switch (_helper.state) { + case IN_PROGRESS: if (lvl == 1) { Type_2_node const &node { _t2_blk.nodes[node_idx] }; if (!_num_remaining_leaves) { if (node.valid()) { - _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, - ") valid but no leaves remaining" }); + _helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, + ") valid but no leaves remaining" }); break; } check_node = false; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); break; } _num_remaining_leaves--; check_node = false; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " done"); + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " done"); } else { Type_1_node const &node { _t1_blks.items[lvl].nodes[node_idx] }; if (!node.valid()) { if (_num_remaining_leaves) { - _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ", - _num_remaining_leaves, " leaves remaining" }); + _helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ", + _num_remaining_leaves, " leaves remaining" }); break; } check_node = false; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused"); break; } - _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _blk); if (VERBOSE_CHECK) - log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " (", node, "): load to lvl ", lvl - 1); } break; + case READ_BLK: progress |= _read_block.execute(block_io); break; case READ_BLK_SUCCEEDED: { Type_1_node const &node { _t1_blks.items[lvl].nodes[node_idx] }; if (node.gen != INITIAL_GENERATION && !check_hash(_blk, node.hash)) { - _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" }); + _helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" }); break; } if (lvl == 2) @@ -89,11 +82,11 @@ bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_ for (bool &cn : _check_node[lvl - 1]) cn = true; - _state = REQ_IN_PROGRESS; + _helper.state = IN_PROGRESS; check_node = false; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " has good hash"); + log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " has good hash"); break; } default: break; @@ -102,81 +95,24 @@ bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_ } -void Ft_check_channel::execute(bool &progress) +bool Ft_check::Check::execute(Block_io &block_io) { - if (!_req_ptr) - return; - - if (_state == REQ_SUBMITTED) { - for (Tree_level_index lvl { 1 }; lvl <= _req_ptr->_ft.max_lvl + 1; lvl++) - for (Tree_node_index node_idx { 0 }; node_idx < _req_ptr->_ft.degree; node_idx++) + bool progress = false; + if (_helper.state == INIT) { + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_ft.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_ft.degree; node_idx++) _check_node[lvl][node_idx] = false; - _num_remaining_leaves = _req_ptr->_ft.num_leaves; - _t1_blks.items[_req_ptr->_ft.max_lvl + 1].nodes[0] = _req_ptr->_ft.t1_node(); - _check_node[_req_ptr->_ft.max_lvl + 1][0] = true; - _state = REQ_IN_PROGRESS; + _num_remaining_leaves = _attr.in_ft.num_leaves; + _t1_blks.items[_attr.in_ft.max_lvl + 1].nodes[0] = _attr.in_ft.t1_node(); + _check_node[_attr.in_ft.max_lvl + 1][0] = true; + _helper.state = IN_PROGRESS; } - for (Tree_level_index lvl { 1 }; lvl <= _req_ptr->_ft.max_lvl + 1; lvl++) - for (Tree_node_index node_idx { 0 }; node_idx < _req_ptr->_ft.degree; node_idx++) - if (_execute_node(lvl, node_idx, progress)) - return; + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_ft.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_ft.degree; node_idx++) + if (_execute_node(block_io, lvl, node_idx, progress)) + return progress; - _mark_req_successful(progress); -} - - -void Ft_check_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_generated_req_success) { - error("ft check: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -void Ft_check_channel::_mark_req_failed(bool &progress, Error_string str) -{ - error("ft check request (", *_req_ptr, ") failed: ", str); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Ft_check_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Ft_check_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Ft_check::Ft_check() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Ft_check::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + _helper.mark_succeeded(progress); + return progress; } diff --git a/repos/gems/src/lib/tresor/ft_initializer.cc b/repos/gems/src/lib/tresor/ft_initializer.cc index e092ba7a28..55da497e74 100644 --- a/repos/gems/src/lib/tresor/ft_initializer.cc +++ b/repos/gems/src/lib/tresor/ft_initializer.cc @@ -13,20 +13,67 @@ */ /* tresor includes */ -#include #include #include using namespace Tresor; -Ft_initializer_request::Ft_initializer_request(Module_id src_mod, Module_channel_id src_chan, - Tree_root &ft, Pba_allocator &pba_alloc, bool &success) -: - Module_request { src_mod, src_chan, FT_INITIALIZER }, _ft { ft }, _pba_alloc { pba_alloc }, _success { success } -{ } +void Ft_initializer::Initialize::_reset_level(Tree_level_index lvl, Node_state node_state) +{ + if (lvl == 1) + for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) { + _t2_blk.nodes[idx] = { }; + _t2_node_states[idx] = node_state; + } + else + for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) { + _t1_blks.items[lvl].nodes[idx] = { }; + _t1_node_states[lvl][idx] = node_state; + } +} -bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &progress) +bool Ft_initializer::Initialize::execute(Block_io &block_io) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _num_remaining_leaves = _attr.in_tree_cfg.num_leaves; + for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++) + _reset_level(lvl, DONE); + + _t1_node_states[_attr.in_tree_cfg.max_lvl + 1][0] = INIT_BLOCK; + _helper.state = EXECUTE_NODES; + progress = true; + break; + + case EXECUTE_NODES: + + for (Tree_node_index node_idx = 0; node_idx < _attr.in_tree_cfg.degree; node_idx++) + if (_execute_t2_node(node_idx, progress)) + return progress; + + for (Tree_level_index lvl = 1; lvl <= _attr.in_tree_cfg.max_lvl + 1; lvl++) + for (Tree_node_index node_idx = 0; node_idx < _attr.in_tree_cfg.degree; node_idx++) + if (_execute_t1_node(lvl, node_idx, progress)) + return progress; + + if (_num_remaining_leaves) + _helper.mark_failed(progress, "leaves remaining"); + else { + _attr.out_tree_root = _t1_blks.items[_attr.in_tree_cfg.max_lvl + 1].nodes[0]; + _helper.mark_succeeded(progress); + } + break; + + case WRITE_BLOCK: progress |= _write_block.execute(block_io); break; + default: break;; + } + return progress; +} + +bool Ft_initializer::Initialize::_execute_t2_node(Tree_node_index node_idx, bool &progress) { Node_state &node_state { _t2_node_states[node_idx] }; Type_2_node &node { _t2_blk.nodes[node_idx] }; @@ -42,8 +89,8 @@ bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &pr if (_num_remaining_leaves) { node = { }; - if (!_req_ptr->_pba_alloc.alloc(node.pba)) { - _mark_req_failed(progress, "allocate pba"); + if (!_attr.in_out_pba_alloc.alloc(node.pba)) { + _helper.mark_failed(progress, "allocate pba"); break; } node_state = DONE; @@ -60,13 +107,13 @@ bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &pr } break; - case WRITE_BLK: ASSERT_NEVER_REACHED; + case WRITING_BLOCK: ASSERT_NEVER_REACHED; } return true; } -bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) +bool Ft_initializer::Initialize::_execute_t1_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { Type_1_node &node { _t1_blks.items[lvl].nodes[node_idx] }; Node_state &node_state { _t1_node_states[lvl][node_idx] }; @@ -92,8 +139,8 @@ bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_in case INIT_NODE: { node = { }; - if (!_req_ptr->_pba_alloc.alloc(node.pba)) { - _mark_req_failed(progress, "allocate pba"); + if (!_attr.in_out_pba_alloc.alloc(node.pba)) { + _helper.mark_failed(progress, "allocate pba"); break; } if (lvl == 2) @@ -101,15 +148,13 @@ bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_in else _t1_blks.items[lvl - 1].encode_to_blk(_blk); calc_hash(_blk, node.hash); - generate_req(EXECUTE_NODES, progress, node.pba, _blk, _generated_req_success); - _state = REQ_GENERATED; - node_state = WRITE_BLK; - progress = true; + _write_block.generate(_helper, WRITE_BLOCK, EXECUTE_NODES, progress, node.pba, _blk); + node_state = WRITING_BLOCK; if (VERBOSE_FT_INIT) log("[ft_init] node: ", lvl, " ", node_idx, " assign pba: ", node.pba); break; } - case WRITE_BLK: + case WRITING_BLOCK: node_state = DONE; progress = true; @@ -119,115 +164,3 @@ bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_in } return true; } - - -void Ft_initializer_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_generated_req_success) { - error("ft initializer request (", *_req_ptr, ") failed because generated request failed"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -void Ft_initializer_channel::_mark_req_failed(bool &progress, char const *str) -{ - error("ft initializer request (", *_req_ptr, ") failed because: ", str); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Ft_initializer_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_ft.t1_node(_t1_blks.items[_req_ptr->_ft.max_lvl + 1].nodes[0]); - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Ft_initializer_channel::_reset_level(Tree_level_index lvl, Node_state node_state) -{ - if (lvl == 1) - for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) { - _t2_blk.nodes[idx] = { }; - _t2_node_states[idx] = node_state; - } - else - for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) { - _t1_blks.items[lvl].nodes[idx] = { }; - _t1_node_states[lvl][idx] = node_state; - } -} - - -void Ft_initializer_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - _num_remaining_leaves = req._ft.num_leaves; - for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++) - _reset_level(lvl, DONE); - - _t1_node_states[req._ft.max_lvl + 1][0] = INIT_BLOCK; - _state = EXECUTE_NODES; - progress = true; - return; - - case EXECUTE_NODES: - - for (Tree_node_index node_idx = 0; node_idx < req._ft.degree; node_idx++) - if (_execute_t2_node(node_idx, progress)) - return; - - for (Tree_level_index lvl = 1; lvl <= req._ft.max_lvl + 1; lvl++) - for (Tree_node_index node_idx = 0; node_idx < req._ft.degree; node_idx++) - if (_execute_t1_node(lvl, node_idx, progress)) - return; - - if (_num_remaining_leaves) - _mark_req_failed(progress, "leaves remaining"); - else - _mark_req_successful(progress); - return; - - default: return; - } -} - - -void Ft_initializer_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Ft_initializer::Ft_initializer() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Ft_initializer::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} diff --git a/repos/gems/src/lib/tresor/include/tresor/block_io.h b/repos/gems/src/lib/tresor/include/tresor/block_io.h index 7da5c7cb3d..732c62aeb8 100644 --- a/repos/gems/src/lib/tresor/include/tresor/block_io.h +++ b/repos/gems/src/lib/tresor/include/tresor/block_io.h @@ -18,147 +18,132 @@ #include #include -namespace Tresor { +namespace Tresor { class Block_io; } - class Block_io; - class Block_io_request; - class Block_io_channel; -} - -class Tresor::Block_io_request : public Module_request -{ - friend class Block_io_channel; - - public: - - enum Type { READ, WRITE, SYNC, READ_CLIENT_DATA, WRITE_CLIENT_DATA }; - - private: - - Type const _type; - Request_offset const _client_req_offset; - Request_tag const _client_req_tag; - Key_id const _key_id; - Physical_block_address const _pba; - Virtual_block_address const _vba; - Block &_blk; - Hash &_hash; - bool &_success; - - NONCOPYABLE(Block_io_request); - - public: - - Block_io_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Key_id, - Physical_block_address, Virtual_block_address, Block &, Hash &, bool &); - - static char const *type_to_string(Type); - - void print(Output &out) const override { Genode::print(out, type_to_string(_type), " pba ", _pba); } -}; - -class Tresor::Block_io_channel : public Module_channel +class Tresor::Block_io : Noncopyable { private: - using Request = Block_io_request; + Vfs::Vfs_handle &_file; + addr_t _user { }; - enum State { - REQ_SUBMITTED, REQ_COMPLETE, CIPHERTEXT_BLK_OBTAINED, PLAINTEXT_BLK_SUPPLIED, REQ_GENERATED, - READ_OK, WRITE_OK, SYNC_OK, FILE_ERR }; + public: - State _state { REQ_COMPLETE }; - Block _blk { }; - bool _generated_req_success { false }; - Block_io_request *_req_ptr { }; - Vfs::Env &_vfs_env; - Tresor::Path const _path; - Read_write_file _file { _state, _vfs_env, _path }; + class Read; + class Write; + class Sync; - NONCOPYABLE(Block_io_channel); + Block_io(Vfs::Vfs_handle &file) : _file(file) { } - void _generated_req_completed(State_uint) override; - - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) + template + bool execute(REQ &req) { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); + if (!_user) + _user = (addr_t)&req; + + if (_user != (addr_t)&req) + return false; + + bool progress = req.execute(_file); + if (req.complete()) + _user = 0; + + return progress; } - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == REQ_COMPLETE; } - - void _read(bool &); - - void _write(bool &); - - void _read_client_data(bool &); - - void _write_client_data(bool &); - - void _sync(bool &); - - void _mark_req_failed(bool &, Error_string); - - void _mark_req_successful(bool &); - - public: - - Block_io_channel(Module_channel_id, Vfs::Env &, Xml_node const &); - - void execute(bool &); + static constexpr char const *name() { return "block_io"; } }; -class Tresor::Block_io : public Module +class Tresor::Block_io::Read : Noncopyable { + public: + + using Module = Block_io; + + struct Attr + { + Physical_block_address const in_pba; + Block &out_block; + }; + private: - using Request = Block_io_request; - using Channel = Block_io_channel; + enum State { INIT, COMPLETE, READ, READ_OK, FILE_ERR }; - Constructible _channels[1] { }; - - NONCOPYABLE(Block_io); + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; public: - struct Read : Request + Read(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "read pba ", _attr.in_pba); } + + bool execute(Vfs::Vfs_handle &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Block_io::Write : Noncopyable +{ + public: + + using Module = Block_io; + + struct Attr { - Read(Module_id m, Module_channel_id c, Physical_block_address a, Block &b, bool &s) - : Request(m, c, Request::READ, 0, 0, 0, a, 0, b, *(Hash*)0, s) { } + Physical_block_address const in_pba; + Block const &in_block; }; - struct Write : Request - { - Write(Module_id m, Module_channel_id c, Physical_block_address a, Block const &b, bool &s) - : Request(m, c, Request::WRITE, 0, 0, 0, a, 0, *const_cast(&b), *(Hash*)0, s) { } - }; + private: - struct Sync : Request - { - Sync(Module_id m, Module_channel_id c, bool &s) - : Request(m, c, Request::SYNC, 0, 0, 0, 0, 0, *(Block*)0, *(Hash*)0, s) { } - }; + enum State { INIT, COMPLETE, WRITE, WRITE_OK, FILE_ERR }; - struct Write_client_data : Request - { - Write_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, Hash &h, bool &s) - : Request(m, c, Request::WRITE_CLIENT_DATA, o, t, k, p, v, *(Block*)0, h, s) { } - }; + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; - 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, Hash &h, bool &s) - : Request(m, c, Request::READ_CLIENT_DATA, o, t, k, p, v, *(Block*)0, h, s) { } - }; + public: - Block_io(Vfs::Env &, Xml_node const &); + Write(Attr const &attr) : _helper(*this), _attr(attr) { } - void execute(bool &) override; + void print(Output &out) const { Genode::print(out, "write pba ", _attr.in_pba); } + + bool execute(Vfs::Vfs_handle &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Block_io::Sync : Noncopyable +{ + public: + + using Module = Block_io; + + struct Attr { }; + + private: + + enum State { INIT, COMPLETE, SYNC, SYNC_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + + public: + + Sync(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "sync"); } + + bool execute(Vfs::Vfs_handle &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #endif /* _TRESOR__BLOCK_IO_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/client_data.h b/repos/gems/src/lib/tresor/include/tresor/client_data.h deleted file mode 100644 index f7f7a53d09..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/client_data.h +++ /dev/null @@ -1,69 +0,0 @@ -/* - * \brief Module that provides access to the client request data - * \author Martin Stein - * \date 2023-02-13 - */ - -/* - * Copyright (C) 2023 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 _TRESOR__CLIENT_DATA_H_ -#define _TRESOR__CLIENT_DATA_H_ - -/* tresor includes */ -#include - -namespace Tresor { class Client_data_request; } - -namespace Vfs_tresor { class Client_data; } - -namespace Tresor_tester { class Client_data; } - -class Tresor::Client_data_request : public Module_request -{ - friend class ::Vfs_tresor::Client_data; - friend class ::Tresor_tester::Client_data; - - public: - - enum Type { OBTAIN_PLAINTEXT_BLK, SUPPLY_PLAINTEXT_BLK }; - - private: - - Type const _type; - Request_offset const _req_off; - Request_tag const _req_tag; - Physical_block_address const _pba; - Virtual_block_address const _vba; - Block &_blk; - bool &_success; - - NONCOPYABLE(Client_data_request); - - public: - - Client_data_request(Module_id src_mod_id, Module_channel_id src_chan_id, Type type, - Request_offset req_off, Request_tag req_tag, Physical_block_address pba, - Virtual_block_address vba, Block &blk, bool &success) - : - Module_request { src_mod_id, src_chan_id, CLIENT_DATA }, _type { type }, _req_off { req_off }, - _req_tag { req_tag }, _pba { pba }, _vba { vba }, _blk { blk }, _success { success } - { } - - static char const *type_to_string(Type type) - { - switch (type) { - case OBTAIN_PLAINTEXT_BLK: return "obtain_plaintext_blk"; - case SUPPLY_PLAINTEXT_BLK: return "supply_plaintext_blk"; - } - ASSERT_NEVER_REACHED; - } - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } -}; - -#endif /* _TRESOR__CLIENT_DATA_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/client_data_interface.h b/repos/gems/src/lib/tresor/include/tresor/client_data_interface.h new file mode 100644 index 0000000000..9456ebcda7 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/client_data_interface.h @@ -0,0 +1,47 @@ +/* + * \brief Interface for providing access to the client request data + * \author Martin Stein + * \date 2023-02-13 + */ + +/* + * Copyright (C) 2023 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 _TRESOR__CLIENT_DATA_INTERFACE_H_ +#define _TRESOR__CLIENT_DATA_INTERFACE_H_ + +/* tresor includes */ +#include + +namespace Tresor { class Client_data_interface; } + +struct Tresor::Client_data_interface : Interface +{ + struct Obtain_data_attr + { + Request_offset const in_req_off; + Request_tag const in_req_tag; + Physical_block_address const in_pba; + Virtual_block_address const in_vba; + Block &out_blk; + }; + + virtual void obtain_data(Obtain_data_attr const &) = 0; + + struct Supply_data_attr + { + Request_offset const in_req_off; + Request_tag const in_req_tag; + Physical_block_address const in_pba; + Virtual_block_address const in_vba; + Block const &in_blk; + }; + + virtual void supply_data(Supply_data_attr const &) = 0; +}; + +#endif /* _TRESOR__CLIENT_DATA_INTERFACE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/crypto.h b/repos/gems/src/lib/tresor/include/tresor/crypto.h index 0098ab9083..3eaaa2d519 100644 --- a/repos/gems/src/lib/tresor/include/tresor/crypto.h +++ b/repos/gems/src/lib/tresor/include/tresor/crypto.h @@ -21,155 +21,187 @@ namespace Tresor { class Crypto; - class Crypto_request; - class Crypto_channel; + class Crypto_key_files_interface; } -class Tresor::Crypto_request : public Module_request +struct Tresor::Crypto_key_files_interface : Interface { - friend class Crypto_channel; + virtual void add_crypto_key(Key_id) = 0; - public: + virtual void remove_crypto_key(Key_id) = 0; - enum Type { ADD_KEY, REMOVE_KEY, DECRYPT, ENCRYPT, DECRYPT_CLIENT_DATA, ENCRYPT_CLIENT_DATA }; + virtual Vfs::Vfs_handle &encrypt_file(Key_id) = 0; - private: - - Type const _type; - Request_offset const _client_req_offset; - Request_tag const _client_req_tag; - Physical_block_address const _pba; - Virtual_block_address const _vba; - Key_id const _key_id; - Key_value const &_key_plaintext; - Block &_blk; - bool &_success; - - NONCOPYABLE(Crypto_request); - - public: - - Crypto_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Key_id, - Key_value const &, Physical_block_address, Virtual_block_address, Block &, bool &); - - static const char *type_to_string(Type); - - void print(Output &) const override; + virtual Vfs::Vfs_handle &decrypt_file(Key_id) = 0; }; -class Tresor::Crypto_channel : public Module_channel +class Tresor::Crypto : Noncopyable { - private: + public: - using Request = Crypto_request; - - enum State { - REQ_SUBMITTED, REQ_COMPLETE, PLAINTEXT_BLK_OBTAINED, PLAINTEXT_BLK_SUPPLIED, REQ_GENERATED, - READ_OK, WRITE_OK, FILE_ERR }; - - struct Key_directory + struct Attr { - Crypto_channel &chan; - Key_id key_id; - Read_write_file encrypt_file { chan._state, chan._vfs_env, { chan._path, "/keys/", key_id, "/encrypt" } }; - Read_write_file decrypt_file { chan._state, chan._vfs_env, { chan._path, "/keys/", key_id, "/decrypt" } }; - - NONCOPYABLE(Key_directory); - - Key_directory(Crypto_channel &chan, Key_id key_id) : chan { chan }, key_id { key_id } { } + Crypto_key_files_interface &key_files; + Vfs::Vfs_handle &add_key_file; + Vfs::Vfs_handle &remove_key_file; }; - Vfs::Env &_vfs_env; - Tresor::Path const _path; - char _add_key_buf[sizeof(Key_id) + KEY_SIZE] { }; - Write_only_file _add_key_file { _state, _vfs_env, { _path, "/add_key" } }; - Write_only_file _remove_key_file { _state, _vfs_env, { _path, "/remove_key" } }; - Constructible _key_dirs[2] { }; - State _state { REQ_COMPLETE }; - bool _generated_req_success { false }; - Block _blk { }; - Request *_req_ptr { }; + private: - NONCOPYABLE(Crypto_channel); + Attr const _attr; + addr_t _user { }; - void _generated_req_completed(State_uint) override; + public: - void _request_submitted(Module_request &) override; + class Encrypt; + class Decrypt; + class Add_key; + class Remove_key; - bool _request_complete() override { return _state == REQ_COMPLETE; } + Crypto(Attr const &attr) : _attr(attr) { } - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) + template + bool execute(REQ &req) { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); + if (!_user) + _user = (addr_t)&req; + + if (_user != (addr_t)&req) + return false; + + bool progress = req.execute(_attr); + if (req.complete()) + _user = 0; + + return progress; } - void _add_key(bool &); - - void _remove_key(bool &); - - void _decrypt(bool &); - - void _encrypt(bool &); - - void _encrypt_client_data(bool &); - - void _decrypt_client_data(bool &); - - void _mark_req_failed(bool &, char const *); - - void _mark_req_successful(bool &); - - Constructible &_key_dir(Key_id key_id); - - public: - - Crypto_channel(Module_channel_id, Vfs::Env &, Xml_node const &); - - void execute(bool &); + static constexpr char const *name() { return "crypto"; } }; -class Tresor::Crypto : public Module +class Tresor::Crypto::Encrypt : Noncopyable { + public: + + using Module = Crypto; + + struct Attr + { + Key_id const in_key_id; + Physical_block_address const in_pba; + Block &in_out_blk; + }; + private: - using Request = Crypto_request; - using Channel = Crypto_channel; + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; - Constructible _channels[1] { }; - - NONCOPYABLE(Crypto); + Request_helper _helper; + Attr const _attr; + off_t _offset { }; + Constructible > _file { }; public: - struct Add_key : Request + Encrypt(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "encrypt pba ", _attr.in_pba); } + + bool execute(Crypto::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Crypto::Decrypt : Noncopyable +{ + public: + + using Module = Crypto; + + struct Attr { - Add_key(Module_id src_mod, Module_channel_id src_chan, Key &key, bool &succ) - : Request(src_mod, src_chan, Request::ADD_KEY, 0, 0, key.id, key.value, 0, 0, *(Block*)0, succ) { } + Key_id const in_key_id; + Physical_block_address const in_pba; + Block &in_out_blk; }; - struct Remove_key : Request - { - Remove_key(Module_id src_mod, Module_channel_id src_chan, Key_id key, bool &succ) - : Request(src_mod, src_chan, Request::REMOVE_KEY, 0, 0, key, *(Key_value*)0, 0, 0, *(Block*)0, succ) { } - }; + private: - struct Decrypt : Request - { - Decrypt(Module_id src_mod, Module_channel_id src_chan, Key_id key, Physical_block_address pba, Block &blk, bool &succ) - : Request(src_mod, src_chan, Request::DECRYPT, 0, 0, key, *(Key_value*)0, pba, 0, blk, succ) { } - }; + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; - struct Encrypt : Request - { - Encrypt(Module_id src_mod, Module_channel_id src_chan, Key_id key, Physical_block_address pba, Block &blk, bool &succ) - : Request(src_mod, src_chan, Request::ENCRYPT, 0, 0, key, *(Key_value*)0, pba, 0, blk, succ) { } - }; + Request_helper _helper; + Attr const _attr; + off_t _offset { }; + Constructible > _file { }; - Crypto(Vfs::Env &, Xml_node const &); + public: - void execute(bool &) override; + Decrypt(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "decrypt pba ", _attr.in_pba); } + + bool execute(Crypto::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Crypto::Add_key : Noncopyable +{ + public: + + using Module = Crypto; + + struct Attr { Key const &in_key; }; + + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + char _write_buf[sizeof(Key_id) + sizeof(Key_value)] { }; + Constructible > _file { }; + + public: + + Add_key(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "add key id ", _attr.in_key.id); } + + bool execute(Crypto::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Crypto::Remove_key : Noncopyable +{ + public: + + using Module = Crypto; + + struct Attr { Key_id const in_key_id; }; + + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + + public: + + Remove_key(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "remove key id ", _attr.in_key_id); } + + bool execute(Crypto::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #endif /* _TRESOR__CRYPTO_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/file.h b/repos/gems/src/lib/tresor/include/tresor/file.h index 188865e87b..c8a3a4f305 100644 --- a/repos/gems/src/lib/tresor/include/tresor/file.h +++ b/repos/gems/src/lib/tresor/include/tresor/file.h @@ -33,8 +33,17 @@ namespace Tresor { template class File; template class Read_write_file; template class Write_only_file; + + inline Vfs::Vfs_handle &open_file(Vfs::Env &env, Tresor::Path const &path, Vfs::Directory_service::Open_mode mode) + { + using Open_result = Vfs::Directory_service::Open_result; + Vfs::Vfs_handle *handle { nullptr }; + ASSERT(env.root_dir().open(path.string(), mode, &handle, env.alloc()) == Open_result::OPEN_OK); + return *handle; + } } + template class Tresor::File { @@ -43,34 +52,34 @@ class Tresor::File using Read_result = Vfs::File_io_service::Read_result; using Write_result = Vfs::File_io_service::Write_result; using Sync_result = Vfs::File_io_service::Sync_result; - using Open_result = Vfs::Directory_service::Open_result; enum State { IDLE, SYNC_QUEUED, READ_QUEUED, READ_INITIALIZED, WRITE_INITIALIZED, WRITE_OFFSET_APPLIED }; - Vfs::Env &_env; + Vfs::Env *_env { }; + Tresor::Path const *_path { }; HOST_STATE &_host_state; State _state { IDLE }; Vfs::Vfs_handle &_handle; Vfs::file_size _num_processed_bytes { 0 }; - Vfs::Vfs_handle &_open(Tresor::Path path, Vfs::Directory_service::Open_mode mode) - { - Vfs::Vfs_handle *handle { nullptr }; - ASSERT(_env.root_dir().open(path.string(), mode, &handle, _env.alloc()) == Open_result::OPEN_OK); - return *handle; - } + /* + * Noncopyable + */ + File(File const &) = delete; + File &operator = (File const &) = delete; public: - File(HOST_STATE &host_state, Vfs::Vfs_handle &handle) : _host_state { host_state }, _handle { handle } { } + File(HOST_STATE &host_state, Vfs::Vfs_handle &handle) : _host_state(host_state), _handle(handle) { } - File(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path path, Vfs::Directory_service::Open_mode mode) - : _env { env }, _host_state { host_state }, _handle { _open(path, mode) } { } + File(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path const &path, Vfs::Directory_service::Open_mode mode) + : _env(&env), _path(&path), _host_state(host_state), _handle(open_file(*_env, *_path, mode)) { } ~File() { ASSERT(_state == IDLE); - _env.root_dir().close(&_handle); + if (_env) + _env->root_dir().close(&_handle); } void read(HOST_STATE succeeded, HOST_STATE failed, Vfs::file_offset off, Byte_range_ptr dst, bool &progress) @@ -116,7 +125,7 @@ class Tresor::File default: - error("read failed"); + error("file: read failed"); _host_state = failed; _state = IDLE; progress = true; @@ -167,7 +176,7 @@ class Tresor::File default: - error("write failed"); + error("file: write failed"); _host_state = failed; _state = IDLE; progress = true; @@ -204,7 +213,7 @@ class Tresor::File default: - error("sync failed"); + error("file: sync failed"); _host_state = failed; _state = IDLE; progress = true; @@ -218,15 +227,15 @@ class Tresor::File template struct Tresor::Read_write_file : public File { - Read_write_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path path) - : File { host_state, env, path, Vfs::Directory_service::OPEN_MODE_RDWR } { } + Read_write_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path const &path) + : File(host_state, env, path, Vfs::Directory_service::OPEN_MODE_RDWR) { } }; template struct Tresor::Write_only_file : public File { - Write_only_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path path) - : File { host_state, env, path, Vfs::Directory_service::OPEN_MODE_WRONLY } { } + Write_only_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path const &path) + : File(host_state, env, path, Vfs::Directory_service::OPEN_MODE_WRONLY) { } }; #endif /* _TRESOR__FILE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/free_tree.h b/repos/gems/src/lib/tresor/include/tresor/free_tree.h index c2618e86be..3f9a434c36 100644 --- a/repos/gems/src/lib/tresor/include/tresor/free_tree.h +++ b/repos/gems/src/lib/tresor/include/tresor/free_tree.h @@ -16,80 +16,68 @@ /* tresor includes */ #include +#include +#include -namespace Tresor { +namespace Tresor { class Free_tree; } - class Free_tree; - class Free_tree_request; - class Free_tree_channel; -} - -class Tresor::Free_tree_request : public Module_request +class Tresor::Free_tree : Noncopyable { - friend class Free_tree_channel; - public: - enum Type { ALLOC_FOR_NON_RKG, ALLOC_FOR_RKG_CURR_GEN_BLKS, ALLOC_FOR_RKG_OLD_GEN_BLKS, EXTENSION_STEP }; + class Allocate_pbas; + class Extend_tree; - private: + template + bool execute(REQUEST &req, Block_io &block_io, Meta_tree &meta_tree) { return req.execute(block_io, meta_tree); } - Type const _type; - Tree_root &_ft; - Tree_root &_mt; - Generation const _curr_gen; - Generation const _free_gen; - Number_of_blocks const _num_required_pbas; - Tree_walk_pbas &_new_blocks; - Type_1_node_walk const &_old_blocks; - Tree_level_index const _max_lvl; - Virtual_block_address const _vba; - Tree_degree const _vbd_degree; - Virtual_block_address const _vbd_max_vba; - bool const _rekeying; - Key_id const _prev_key_id; - Key_id const _curr_key_id; - Virtual_block_address const _rekeying_vba; - bool &_success; - Snapshots const &_snapshots; - Generation const _last_secured_gen; - Physical_block_address &_pba; - Number_of_blocks &_num_pbas; - - NONCOPYABLE(Free_tree_request); - - public: - - Free_tree_request(Module_id, Module_channel_id, Type, Tree_root &, Tree_root &, Snapshots const &, - Generation, Generation, Generation, Number_of_blocks, Tree_walk_pbas &, Type_1_node_walk const &, - Tree_level_index, Virtual_block_address, Tree_degree, Virtual_block_address, - bool, Key_id, Key_id, Virtual_block_address, Physical_block_address &, Number_of_blocks &, bool &); - - static char const *type_to_string(Type); - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + static constexpr char const *name() { return "free_tree"; } }; - -class Tresor::Free_tree_channel : public Module_channel +class Tresor::Free_tree::Allocate_pbas : Noncopyable { + public: + + using Module = Free_tree; + + enum Application { NON_REKEYING, REKEYING_IN_CURRENT_GENERATION, REKEYING_IN_OLDER_GENERATION }; + + struct Attr + { + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Snapshots const &in_snapshots; + Generation const in_last_secured_gen; + Generation const in_curr_gen; + Generation const in_free_gen; + Number_of_blocks const in_num_required_pbas; + Tree_walk_pbas &in_out_new_blocks; + Type_1_node_walk const &in_old_blocks; + Tree_level_index const in_max_lvl; + Virtual_block_address const in_vba; + Tree_degree const in_vbd_degree; + Virtual_block_address const in_vbd_max_vba; + bool const in_rekeying; + Key_id const in_prev_key_id; + Key_id const in_curr_key_id; + Virtual_block_address const in_rekeying_vba; + Application const in_application; + }; + private: - using Request = Free_tree_request; - enum State { - REQ_SUBMITTED, REQ_GENERATED, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, READ_BLK_SUCCEEDED, - ALLOC_PBA_SUCCEEDED, WRITE_BLK_SUCCEEDED, REQ_COMPLETE }; + INIT, COMPLETE, SEEK_DOWN, SEEK_LEFT_OR_UP, READ_BLK, READ_BLK_SUCCEEDED, + ALLOC_PBA, ALLOC_PBA_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED }; - Request *_req_ptr { nullptr }; - State _state { REQ_COMPLETE }; + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; Virtual_block_address _vba { }; Tree_walk_pbas _old_pbas { }; Tree_walk_pbas _new_pbas { }; Tree_walk_generations _old_generations { }; - Number_of_leaves _num_leaves { 0 }; - Physical_block_address _alloc_pba { 0 }; - Tree_level_index _alloc_lvl { 0 }; Number_of_blocks _num_pbas { 0 }; Block _blk { }; Tree_node_index _node_idx[TREE_MAX_NR_OF_LEVELS] { }; @@ -98,36 +86,71 @@ class Tresor::Free_tree_channel : public Module_channel Type_2_node_block _t2_blk { }; Tree_degree_log_2 _vbd_degree_log_2 { 0 }; Tree_level_index _lvl { 0 }; - bool _generated_req_success { false }; - - NONCOPYABLE(Free_tree_channel); - - void _generated_req_completed(State_uint) override; - - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) - { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); - } - - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == REQ_COMPLETE; } - - void _mark_req_failed(bool &, char const *); - - bool _can_alloc_pba_of(Type_2_node &); + Generatable_request _read_block { }; + Generatable_request _write_block { }; + Generatable_request _allocate_pba { }; void _alloc_pba_of(Type_2_node &); - void _traverse_curr_node(bool &); + bool _can_alloc_pba_of(Type_2_node &); - void _mark_req_successful(bool &); + void _traverse_curr_node(bool &); void _start_tree_traversal(bool &); - void _advance_to_next_node(); + public: + + Allocate_pbas(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Allocate_pbas() { } + + void print(Output &out) const { Genode::print(out, "allocate pbas"); } + + bool execute(Block_io &, Meta_tree &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Free_tree::Extend_tree : Noncopyable +{ + public: + + using Module = Free_tree; + + struct Attr + { + Generation const in_curr_gen; + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Physical_block_address &in_out_first_pba; + Number_of_blocks &in_out_num_pbas; + }; + + private: + + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, WRITE_BLK, + WRITE_BLK_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_leaves _num_leaves { 0 }; + Virtual_block_address _vba { }; + Tree_walk_pbas _old_pbas { }; + Tree_walk_generations _old_generations { }; + Tree_walk_pbas _new_pbas { }; + Tree_level_index _lvl { 0 }; + Block _blk { }; + Type_1_node_block _t1_blks[TREE_MAX_NR_OF_LEVELS] { }; + Type_2_node_block _t2_blk { }; + Tree_level_index _alloc_lvl { 0 }; + Physical_block_address _alloc_pba { 0 }; + Generatable_request _read_block { }; + Generatable_request _write_block { }; + Generatable_request _allocate_pba { }; void _add_new_branch_at(Tree_level_index, Tree_node_index); @@ -135,41 +158,18 @@ class Tresor::Free_tree_channel : public Module_channel void _generate_write_blk_req(bool &); - void _extension_step(bool &); - - void _alloc_pbas(bool &); - public: - Free_tree_channel(Module_channel_id id) : Module_channel { FREE_TREE, id } { } + Extend_tree(Attr const &attr) : _helper(*this), _attr(attr) { } - void execute(bool &); -}; + ~Extend_tree() { } -class Tresor::Free_tree : public Module -{ - private: + void print(Output &out) const { Genode::print(out, "extend tree"); } - using Channel = Free_tree_channel; - using Request = Free_tree_request; + bool execute(Block_io &, Meta_tree &); - Constructible _channels[1] { }; - - NONCOPYABLE(Free_tree); - - void execute(bool &) override; - - public: - - struct Extension_step : Request - { - Extension_step(Module_id mod_id, Module_channel_id chan_id, Generation curr_gen, Tree_root &ft, Tree_root &mt, - Physical_block_address &pba, Number_of_blocks &num_pbas, bool &succ) - : Request(mod_id, chan_id, Request::EXTENSION_STEP, ft, mt, *(Snapshots *)0, 0, curr_gen, 0, 0, *(Tree_walk_pbas*)0, - *(Type_1_node_walk*)0, 0, 0, 0, 0, 0, 0, 0, 0, pba, num_pbas, succ) { } - }; - - Free_tree(); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #endif /* _TRESOR__FREE_TREE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/ft_check.h b/repos/gems/src/lib/tresor/include/tresor/ft_check.h index a8168311e7..2db3e92627 100644 --- a/repos/gems/src/lib/tresor/include/tresor/ft_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/ft_check.h @@ -16,95 +16,54 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Ft_check; } - class Ft_check; - class Ft_check_request; - class Ft_check_channel; -} - - -class Tresor::Ft_check_request : public Module_request +struct Tresor::Ft_check : Noncopyable { - friend class Ft_check_channel; + class Check : Noncopyable + { + public: - private: + using Module = Ft_check; - Tree_root const &_ft; - bool &_success; + struct Attr { Tree_root const &in_ft; }; - NONCOPYABLE(Ft_check_request); + private: - public: + enum State { INIT, IN_PROGRESS, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED }; - Ft_check_request(Module_id, Module_channel_id, Tree_root const &, bool &); + using Helper = Request_helper; - void print(Output &out) const override { Genode::print(out, "check ", _ft); } -}; + Helper _helper; + Attr const _attr; + Type_1_node_block_walk _t1_blks { }; + Type_2_node_block _t2_blk { }; + bool _check_node[TREE_MAX_NR_OF_LEVELS + 1][NUM_NODES_PER_BLK] { }; + Number_of_leaves _num_remaining_leaves { 0 }; + Block _blk { }; + Generatable_request _read_block { }; + bool _execute_node(Block_io &, Tree_level_index, Tree_node_index, bool &); -class Tresor::Ft_check_channel : public Module_channel -{ - private: + public: - using Request = Ft_check_request; + Check(Attr const &attr) : _helper(*this), _attr(attr) { } - enum State : State_uint { REQ_SUBMITTED, REQ_IN_PROGRESS, REQ_COMPLETE, REQ_GENERATED, READ_BLK_SUCCEEDED }; + void print(Output &out) const { Genode::print(out, "check ", _attr.in_ft); } - State _state { REQ_COMPLETE }; - Type_1_node_block_walk _t1_blks { }; - Type_2_node_block _t2_blk { }; - bool _check_node[TREE_MAX_NR_OF_LEVELS + 1][NUM_NODES_PER_BLK] { }; - Number_of_leaves _num_remaining_leaves { 0 }; - Request *_req_ptr { }; - Block _blk { }; - bool _generated_req_success { false }; + bool execute(Block_io &); - NONCOPYABLE(Ft_check_channel); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - void _generated_req_completed(State_uint) override; + Ft_check() { } - void _request_submitted(Module_request &) override; + bool execute(Check &req, Block_io &block_io) { return req.execute(block_io); } - bool _request_complete() override { return _state == REQ_COMPLETE; } - - void _mark_req_failed(bool &, Error_string); - - void _mark_req_successful(bool &); - - bool _execute_node(Tree_level_index, Tree_node_index, bool &); - - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) - { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); - } - - public: - - Ft_check_channel(Module_channel_id id) : Module_channel { FT_CHECK, id } { } - - void execute(bool &); -}; - - -class Tresor::Ft_check : public Module -{ - private: - - using Channel = Ft_check_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Ft_check); - - public: - - Ft_check(); - - void execute(bool &) override; + static constexpr char const *name() { return "ft_check"; } }; #endif /* _TRESOR__FT_CHECK_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h b/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h index 6b07ff3a2e..e79ccd51e8 100644 --- a/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h +++ b/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h @@ -17,97 +17,68 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Ft_initializer; } - class Ft_initializer; - class Ft_initializer_request; - class Ft_initializer_channel; -} - - -class Tresor::Ft_initializer_request : public Module_request +class Tresor::Ft_initializer : Noncopyable { - friend class Ft_initializer_channel; - - private: - - Tree_root &_ft; - Pba_allocator &_pba_alloc; - bool &_success; - - NONCOPYABLE(Ft_initializer_request); - public: - Ft_initializer_request(Module_id, Module_channel_id, Tree_root &, Pba_allocator &, bool &); + class Initialize : Noncopyable + { + public: - void print(Output &out) const override { Genode::print(out, "init"); } -}; + using Module = Ft_initializer; + struct Attr + { + Tree_configuration const in_tree_cfg; + Type_1_node &out_tree_root; + Pba_allocator &in_out_pba_alloc; + }; -class Tresor::Ft_initializer_channel : public Module_channel -{ - private: + private: - using Request = Ft_initializer_request; + enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITING_BLOCK }; - enum State { REQ_GENERATED, REQ_SUBMITTED, EXECUTE_NODES, REQ_COMPLETE }; + enum State { INIT, COMPLETE, EXECUTE_NODES, WRITE_BLOCK }; - enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLK }; + using Helper = Request_helper; - State _state { REQ_COMPLETE }; - Request *_req_ptr { }; - Type_2_node_block _t2_blk { }; - Type_1_node_block_walk _t1_blks { }; - Node_state _t1_node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { }; - Node_state _t2_node_states[NUM_NODES_PER_BLK] { }; - Number_of_leaves _num_remaining_leaves { 0 }; - bool _generated_req_success { false }; - Block _blk { }; + Helper _helper; + Attr const _attr; + Type_2_node_block _t2_blk { }; + Type_1_node_block_walk _t1_blks { }; + Node_state _t1_node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { }; + Node_state _t2_node_states[NUM_NODES_PER_BLK] { }; + Number_of_leaves _num_remaining_leaves { 0 }; + Block _blk { }; + Generatable_request _write_block { }; - NONCOPYABLE(Ft_initializer_channel); + void _reset_level(Tree_level_index, Node_state); - void _reset_level(Tree_level_index, Node_state); + bool _execute_t2_node(Tree_node_index, bool &); - void _generated_req_completed(State_uint) override; + bool _execute_t1_node(Tree_level_index, Tree_node_index, bool &); - bool _request_complete() override { return _state == REQ_COMPLETE; } + public: - void _request_submitted(Module_request &) override; + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } - bool _execute_t2_node(Tree_node_index, bool &); + ~Initialize() { } - bool _execute_t1_node(Tree_level_index, Tree_node_index, bool &); + void print(Output &out) const { Genode::print(out, "initialize"); } - void _mark_req_failed(bool &, char const *); + bool execute(Block_io &); - void _mark_req_successful(bool &); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - public: - - Ft_initializer_channel(Module_channel_id id) : Module_channel { FT_INITIALIZER, id } { } - - void execute(bool &); -}; - - -class Tresor::Ft_initializer : public Module -{ - private: - - using Channel = Ft_initializer_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Ft_initializer); - - public: - - Ft_initializer(); - - void execute(bool &) override; + bool execute(Initialize &req, Block_io &block_io) { return req.execute(block_io); } + static constexpr char const *name() { return "ft_initializer"; } }; #endif /* _TRESOR__FT_INITIALIZER_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/meta_tree.h b/repos/gems/src/lib/tresor/include/tresor/meta_tree.h index d529b56ce6..18619af7a5 100644 --- a/repos/gems/src/lib/tresor/include/tresor/meta_tree.h +++ b/repos/gems/src/lib/tresor/include/tresor/meta_tree.h @@ -1,5 +1,5 @@ /* - * \brief Module for doing VBD COW allocations on the meta tree + * \brief Module for doing PBA allocations for the Free Tree via the Meta Tree * \author Martin Stein * \date 2023-02-13 */ @@ -16,74 +16,49 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Meta_tree; } - class Meta_tree; - class Meta_tree_request; - class Meta_tree_channel; -} - -class Tresor::Meta_tree_request : public Module_request +class Tresor::Meta_tree : Noncopyable { - friend class Meta_tree_channel; - public: - enum Type { ALLOC_PBA }; + class Allocate_pba; - private: + bool execute(Allocate_pba &, Block_io &); - Type const _type; - Tree_root &_mt; - Generation const _curr_gen; - Physical_block_address &_pba; - bool &_success; - - NONCOPYABLE(Meta_tree_request); - - public: - - Meta_tree_request(Module_id, Module_channel_id, Type, Tree_root &, Generation, Physical_block_address &, bool &); - - static char const *type_to_string(Type); - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + static constexpr char const *name() { return "meta_tree"; } }; -class Tresor::Meta_tree_channel : public Module_channel +class Tresor::Meta_tree::Allocate_pba : Noncopyable { + public: + + using Module = Meta_tree; + + struct Attr + { + Tree_root &in_out_mt; + Generation const in_curr_gen; + Physical_block_address &in_out_pba; + }; + private: - using Request = Meta_tree_request; + enum State { INIT, COMPLETE, READ_BLK, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, WRITE_BLK_SUCCEEDED }; - enum State { REQ_SUBMITTED, REQ_GENERATED, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, COMPLETE }; + using Helper = Request_helper; - State _state { COMPLETE }; - Request *_req_ptr { nullptr }; + Helper _helper; + Attr const _attr; Block _blk { }; Tree_node_index _node_idx[TREE_MAX_NR_OF_LEVELS] { }; Type_1_node_block _t1_blks[TREE_MAX_NR_OF_LEVELS] { }; Type_2_node_block _t2_blk { }; Tree_level_index _lvl { 0 }; - bool _generated_req_success { false }; - - NONCOPYABLE(Meta_tree_channel); - - void _generated_req_completed(State_uint) override; - - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) - { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); - } - - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == COMPLETE; } - - void _mark_req_failed(bool &, char const *); + Generatable_request _read_block { }; + Generatable_request _write_block { }; bool _can_alloc_pba_of(Type_2_node &); @@ -91,38 +66,20 @@ class Tresor::Meta_tree_channel : public Module_channel void _traverse_curr_node(bool &); - void _mark_req_successful(bool &); - void _start_tree_traversal(bool &); public: - Meta_tree_channel(Module_channel_id id) : Module_channel { META_TREE, id } { } + Allocate_pba(Attr const &attr) : _helper(*this), _attr(attr) { } - void execute(bool &); -}; + ~Allocate_pba() { } -class Tresor::Meta_tree : public Module -{ - private: + void print(Output &out) const { Genode::print(out, "allocate pba"); } - using Channel = Meta_tree_channel; + bool execute(Block_io &); - Constructible _channels[1] { }; - - NONCOPYABLE(Meta_tree); - - void execute(bool &) override; - - public: - - struct Alloc_pba : Meta_tree_request - { - Alloc_pba(Module_id src_mod, Module_channel_id src_chan, Tree_root &mt, Generation gen, Physical_block_address &pba, bool &succ) - : Meta_tree_request(src_mod, src_chan, Meta_tree_request::ALLOC_PBA, mt, gen, pba, succ) { } - }; - - Meta_tree(); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #endif /* _TRESOR__META_TREE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/module.h b/repos/gems/src/lib/tresor/include/tresor/module.h deleted file mode 100644 index 9c960c32fb..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/module.h +++ /dev/null @@ -1,223 +0,0 @@ -/* - * \brief Framework for component internal modularization - * \author Martin Stein - * \date 2023-02-13 - */ - -/* - * Copyright (C) 2023 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 _TRESOR__MODULE_H_ -#define _TRESOR__MODULE_H_ - -/* base includes */ -#include - -/* tresor includes */ -#include -#include -#include - -namespace Tresor { - - using namespace Genode; - - using Module_id = uint64_t; - using Module_channel_id = uint64_t; - - enum { INVALID_MODULE_ID = ~(Module_id)0, INVALID_MODULE_CHANNEL_ID = ~(Module_channel_id)0 }; - - enum Module_id_enum : Module_id { - CRYPTO = 0, CLIENT_DATA = 1, TRUST_ANCHOR = 2, COMMAND_POOL = 3, BLOCK_IO = 4, CACHE = 5, META_TREE = 6, - FREE_TREE = 7, VIRTUAL_BLOCK_DEVICE = 8, SUPERBLOCK_CONTROL = 9, VBD_INITIALIZER = 10, FT_INITIALIZER = 11, - SB_INITIALIZER = 12, REQUEST_POOL = 13, SB_CHECK = 14, VBD_CHECK = 15, FT_CHECK = 16, SPLITTER = 17, MAX_MODULE_ID = 17 }; - - char const *module_name(Module_id module_id); - - class Module_request; - class Module_channel; - class Module; - class Module_composition; -} - - -class Tresor::Module_request : public Interface -{ - private: - - Module_id _src_module_id; - Module_channel_id _src_chan_id; - Module_id _dst_module_id; - Module_channel_id _dst_chan_id { INVALID_MODULE_CHANNEL_ID }; - - NONCOPYABLE(Module_request); - - public: - - Module_request(Module_id, Module_channel_id, Module_id); - - void dst_chan_id(Module_channel_id id) { _dst_chan_id = id; } - - Module_id src_module_id() const { return _src_module_id; } - Module_channel_id src_chan_id() const { return _src_chan_id; } - Module_id dst_module_id() const { return _dst_module_id; } - Module_channel_id dst_chan_id() const { return _dst_chan_id; } - - virtual void print(Output &) const = 0; - - virtual ~Module_request() { } -}; - - -class Tresor::Module_channel : private Avl_node -{ - friend class Module; - friend class Avl_node; - friend class Avl_tree; - - public: - - using State_uint = uint64_t; - - private: - - enum { GEN_REQ_BUF_SIZE = 4000 }; - - enum Generated_request_state { NONE, PENDING, IN_PROGRESS }; - - Module_request *_req_ptr { nullptr }; - Module_id _module_id; - Module_channel_id _id; - Generated_request_state _gen_req_state { NONE }; - uint8_t _gen_req_buf[GEN_REQ_BUF_SIZE] { }; - State_uint _gen_req_complete_state { 0 }; - - NONCOPYABLE(Module_channel); - - bool higher(Module_channel *ptr) { return ptr->_id > _id; } - - virtual void _generated_req_completed(State_uint) { ASSERT_NEVER_REACHED; } - - virtual void _request_submitted(Module_request &) { ASSERT_NEVER_REACHED; } - - virtual bool _request_complete() { ASSERT_NEVER_REACHED; } - - public: - - Module_channel(Module_id module_id, Module_channel_id id) : _module_id { module_id }, _id { id } { }; - - template - void generate_req(State_uint complete_state, bool &progress, ARGS &&... args) - { - ASSERT(_gen_req_state == NONE); - static_assert(sizeof(REQUEST) <= GEN_REQ_BUF_SIZE); - construct_at(_gen_req_buf, _module_id, _id, args...); - _gen_req_state = PENDING; - _gen_req_complete_state = complete_state; - progress = true; - } - - template - void with_channel(Module_channel_id id, FUNC && func) - { - if (id != _id) { - Module_channel *chan_ptr { Avl_node::child(id > _id) }; - ASSERT(chan_ptr); - chan_ptr->with_channel(id, func); - } else - func(*static_cast(this)); - } - - void generated_req_completed(); - - bool try_submit_request(Module_request &); - - Module_channel_id id() const { return _id; } - - virtual ~Module_channel() { } -}; - - -class Tresor::Module : public Interface -{ - private: - - Avl_tree _channels { }; - - NONCOPYABLE(Module); - - public: - - template - void with_channel(Module_channel_id id, FUNC && func) - { - ASSERT(_channels.first()); - _channels.first()->with_channel(id, func); - } - - template - void for_each_channel(FUNC && func) - { - _channels.for_each([&] (Module_channel const &const_chan) { - func(*static_cast(const_cast(&const_chan))); }); - } - - template - void for_each_generated_request(FUNC && handle_request) - { - for_each_channel([&] (Module_channel &chan) { - if (chan._gen_req_state != Module_channel::PENDING) - return; - - Module_request &req = *(Module_request *)chan._gen_req_buf; - if (handle_request(req)) { - chan._gen_req_state = Module_channel::IN_PROGRESS; - return; - } - }); - } - - template - void for_each_completed_request(FUNC && handle_request) - { - for_each_channel([&] (Module_channel &chan) { - if (chan._req_ptr && chan._request_complete()) { - handle_request(*chan._req_ptr); - chan._req_ptr = nullptr; - } - }); - return; - } - - bool try_submit_request(Module_request &); - - void add_channel(Module_channel &chan) { _channels.insert(&chan); } - - Module() { } - - virtual ~Module() { } - - virtual void execute(bool &) { } -}; - - -class Tresor::Module_composition -{ - private: - - Module *_module_ptrs[MAX_MODULE_ID + 1] { }; - - public: - - void add_module(Module_id module_id, Module &mod); - - void remove_module(Module_id module_id); - - void execute_modules(); -}; - -#endif /* _TRESOR__MODULE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/noncopyable.h b/repos/gems/src/lib/tresor/include/tresor/noncopyable.h deleted file mode 100644 index 1ff52ef79c..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/noncopyable.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * \brief Macro to make a class non-copyable - * \author Martin Stein - * \date 2023-06-09 - */ - -/* - * Copyright (C) 2023 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 _TRESOR__NONCOPYABLE_H_ -#define _TRESOR__NONCOPYABLE_H_ - -#define NONCOPYABLE(class_name) \ - class_name(class_name const &) = delete; \ - class_name &operator = (class_name const &) = delete; \ - -#endif /* _TRESOR__NONCOPYABLE_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/request_pool.h b/repos/gems/src/lib/tresor/include/tresor/request_pool.h deleted file mode 100644 index 93a1dd9969..0000000000 --- a/repos/gems/src/lib/tresor/include/tresor/request_pool.h +++ /dev/null @@ -1,180 +0,0 @@ -/* - * \brief Module for scheduling requests for processing - * \author Martin Stein - * \date 2023-03-17 - */ - -/* - * Copyright (C) 2023 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 _TRESOR__REQUEST_POOL_H_ -#define _TRESOR__REQUEST_POOL_H_ - -/* tresor includes */ -#include -#include - -namespace Tresor { - - class Request; - class Request_pool; - class Request_pool_channel; - class Request_pool_channel_queue; -} - -class Tresor::Request : public Module_request -{ - NONCOPYABLE(Request); - - friend class Request_pool_channel; - - public: - - enum Operation { - READ, WRITE, SYNC, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, REKEY, EXTEND_VBD, - EXTEND_FT, RESUME_REKEYING, DEINITIALIZE, INITIALIZE, }; - - private: - - Operation _op; - Virtual_block_address const _vba; - Request_offset const _offset; - Number_of_blocks const _count; - Key_id const _key_id; - Request_tag const _tag; - Generation &_gen; - bool &_success; - - public: - - static char const *op_to_string(Operation); - - Request(Module_id, Module_channel_id, Operation, Virtual_block_address, Request_offset, - Number_of_blocks, Key_id, Request_tag, Generation &, bool &); - - void print(Output &) const override; -}; - -class Tresor::Request_pool_channel : public Module_channel -{ - private: - - enum State : State_uint { - INVALID, REQ_SUBMITTED, REQ_RESUMED, REQ_GENERATED, REKEY_INIT_SUCCEEDED, PREPONED_REQUESTS_COMPLETE, - TREE_EXTENSION_STEP_SUCCEEDED, FORWARD_TO_SB_CTRL_SUCCEEDED, ACCESS_VBA_AT_SB_CTRL_SUCCEEDED, - REKEY_VBA_SUCCEEDED, INITIALIZE_SB_CTRL_SUCCEEDED, DEINITIALIZE_SB_CTRL_SUCCEEDED, REQ_COMPLETE }; - - State _state { INVALID }; - Number_of_blocks _num_blks { 0 }; - Superblock::State _sb_state { Superblock::INVALID }; - uint32_t _num_requests_preponed { 0 }; - bool _request_finished { false }; - bool _generated_req_success { false }; - Request_pool_channel_queue &_chan_queue; - Request *_req_ptr { nullptr }; - - NONCOPYABLE(Request_pool_channel); - - void _generated_req_completed(State_uint) override; - - void _request_submitted(Module_request &req) override; - - bool _request_complete() override { return _state == REQ_COMPLETE; } - - void _access_vbas(bool &, Superblock_control_request::Type); - - void _forward_to_sb_ctrl(bool &, Superblock_control_request::Type); - - void _gen_sb_control_req(bool &, Superblock_control_request::Type, State, Virtual_block_address); - - void _rekey(bool &); - - void _mark_req_successful(bool &); - - void _reset(); - - void _try_prepone_requests(bool &); - - void _extend_tree(Superblock_control_request::Type, bool &); - - void _initialize(bool &); - - void _resume_request(bool &, Request::Operation); - - public: - - Request_pool_channel(Module_channel_id id, Request_pool_channel_queue &chan_queue) : Module_channel { REQUEST_POOL, id }, _chan_queue { chan_queue } { } - - void execute(bool &); -}; - - -class Tresor::Request_pool_channel_queue -{ - NONCOPYABLE(Request_pool_channel_queue); - - public: - - enum { NUM_SLOTS = 16 }; - - private: - - using Channel = Request_pool_channel; - using Slot_index = uint64_t; - using Number_of_slots = uint64_t; - - Slot_index _head { 0 }; - Slot_index _tail { 0 }; - Number_of_slots _num_used_slots { 0 }; - Channel *_slots[NUM_SLOTS] { 0 }; - - public: - - Request_pool_channel_queue() { } - - bool empty() const { return _num_used_slots == 0; } - - bool full() const { return _num_used_slots >= NUM_SLOTS; } - - Channel &head() const; - - void enqueue(Channel &); - - void move_one_slot_towards_tail(Channel const &); - - bool is_tail(Channel const &) const; - - Channel &next(Channel const &) const; - - void dequeue(Channel const &); -}; - - -class Tresor::Request_pool : public Module -{ - NONCOPYABLE(Request_pool); - - private: - - using Channel = Request_pool_channel; - - enum { NUM_CHANNELS = Request_pool_channel_queue::NUM_SLOTS }; - - bool _init_success { false }; - Generation _init_gen { INVALID_GENERATION }; - Request _init_req { INVALID_MODULE_ID, INVALID_MODULE_CHANNEL_ID, Request::INITIALIZE, 0, 0, 0, 0, 0, _init_gen, _init_success }; - Constructible _channels[NUM_CHANNELS] { }; - Request_pool_channel_queue _chan_queue { }; - - public: - - void execute(bool &) override; - - Request_pool(); -}; - -#endif /* _TRESOR__REQUEST_POOL_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/sb_check.h b/repos/gems/src/lib/tresor/include/tresor/sb_check.h index 76dad0a18a..1cace44139 100644 --- a/repos/gems/src/lib/tresor/include/tresor/sb_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/sb_check.h @@ -16,95 +16,60 @@ /* tresor includes */ #include +#include +#include +#include -namespace Tresor { +namespace Tresor { class Sb_check; } - class Sb_check; - class Sb_check_request; - class Sb_check_channel; -} - - -class Tresor::Sb_check_request : public Module_request +struct Tresor::Sb_check : Noncopyable { - friend class Sb_check_channel; + class Check : Noncopyable + { + public: - private: + using Module = Sb_check; - bool &_success; + private: - NONCOPYABLE(Sb_check_request); + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, CHECK_VBD, CHECK_VBD_SUCCEEDED, CHECK_FT, CHECK_FT_SUCCEEDED, + CHECK_MT, CHECK_MT_SUCCEEDED}; - public: + using Helper = Request_helper; - Sb_check_request(Module_id, Module_channel_id, bool &); + Helper _helper; + Generation _highest_gen { 0 }; + Superblock_index _highest_gen_sb_idx { 0 }; + bool _scan_for_highest_gen_sb_done { false }; + Superblock_index _sb_idx { 0 }; + Superblock _sb { }; + Snapshot_index _snap_idx { 0 }; + Constructible _tree_root { }; + Block _blk { }; + Generatable_request _check_vbd { }; + Generatable_request _check_ft { }; + Generatable_request _read_block { }; - void print(Output &out) const override { Genode::print(out, "check"); } -}; + public: + Check() : _helper(*this) { } -class Tresor::Sb_check_channel : public Module_channel -{ - private: + ~Check() { } - using Request = Sb_check_request; + void print(Output &out) const { Genode::print(out, "check"); } - enum State { REQ_SUBMITTED, REQ_COMPLETE, READ_BLK_SUCCESSFUL, REQ_GENERATED, CHECK_VBD_SUCCESSFUL, CHECK_FT_SUCCESSFUL, CHECK_MT_SUCCESSFUL}; + bool execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io); - State _state { REQ_COMPLETE }; - Request *_req_ptr { }; - Generation _highest_gen { 0 }; - Superblock_index _highest_gen_sb_idx { 0 }; - bool _scan_for_highest_gen_sb_done { false }; - Superblock_index _sb_idx { 0 }; - Superblock _sb { }; - Snapshot_index _snap_idx { 0 }; - Constructible _tree_root { }; - Block _blk { }; - bool _generated_req_success { false }; + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - NONCOPYABLE(Sb_check_channel); + Sb_check() { } - void _generated_req_completed(State_uint) override; + 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); }; - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == REQ_COMPLETE; } - - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) - { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); - } - - void _mark_req_failed(bool &, char const *); - - void _mark_req_successful(bool &); - - public: - - Sb_check_channel(Module_channel_id id) : Module_channel { SB_CHECK, id } { } - - void execute(bool &); -}; - - -class Tresor::Sb_check : public Module -{ - private: - - using Channel = Sb_check_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Sb_check); - - public: - - Sb_check(); - - void execute(bool &) override; + static constexpr char const *name() { return "sb_check"; } }; #endif /* _TRESOR__SB_CHECK_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h b/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h index c387ab0d0c..823875d6b0 100644 --- a/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h +++ b/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h @@ -17,107 +17,78 @@ /* tresor includes */ #include +#include +#include +#include +#include -namespace Tresor { +namespace Tresor { class Sb_initializer; } - class Sb_initializer; - class Sb_initializer_request; - class Sb_initializer_channel; -} - - -class Tresor::Sb_initializer_request : public Module_request +class Tresor::Sb_initializer : Noncopyable { - friend class Sb_initializer_channel; - - private: - - Tree_level_index _vbd_max_lvl; - Tree_degree _vbd_degree; - Number_of_leaves _vbd_num_leaves; - Tree_level_index _ft_max_lvl; - Tree_degree _ft_degree; - Number_of_leaves _ft_num_leaves; - Tree_level_index _mt_max_lvl; - Tree_degree _mt_degree; - Number_of_leaves _mt_num_leaves; - Pba_allocator &_pba_alloc; - bool &_success; - - NONCOPYABLE(Sb_initializer_request); - public: - Sb_initializer_request(Module_id, Module_channel_id, Tree_level_index, Tree_degree, Number_of_leaves, - Tree_level_index, Tree_degree, Number_of_leaves, Tree_level_index, Tree_degree, - Number_of_leaves, Pba_allocator &, bool &); - - void print(Output &out) const override { Genode::print(out, "init"); } -}; - - -class Tresor::Sb_initializer_channel : public Module_channel -{ - private: - - using Request = Sb_initializer_request; - - enum State { - REQ_SUBMITTED, START_NEXT_SB, SB_COMPLETE, REQ_COMPLETE, INIT_FT_SUCCEEDED, INIT_MT_SUCCEEDED, - WRITE_HASH_TO_TA, CREATE_KEY_SUCCEEDED, ENCRYPT_KEY_SUCCEEDED, SECURE_SB_SUCCEEDED, INIT_VBD_SUCCEEDED, - WRITE_BLK_SUCCEEDED, REQ_GENERATED }; - - State _state { REQ_COMPLETE }; - Request *_req_ptr { }; - Superblock_index _sb_idx { 0 }; - Superblock _sb { }; - Block _blk { }; - Hash _hash { }; - Constructible _vbd { }; - Constructible _mt { }; - Constructible _ft { }; - bool _generated_req_success { false }; - - NONCOPYABLE(Sb_initializer_channel); - - void _generated_req_completed(State_uint) override; - - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == REQ_COMPLETE; } - - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) + class Initialize : Noncopyable { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); + public: + + using Module = Sb_initializer; + + struct Attr + { + Tree_configuration const in_vbd_cfg; + Tree_configuration const in_ft_cfg; + Tree_configuration const in_mt_cfg; + Pba_allocator &in_out_pba_alloc; + }; + + private: + + enum State { + INIT, COMPLETE, START_NEXT_SB, SB_COMPLETE, INIT_FT, INIT_FT_SUCCEEDED, INIT_MT_SUCCEEDED, + WRITE_HASH_TO_TA, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, ENCRYPT_KEY, ENCRYPT_KEY_SUCCEEDED, + SECURE_SB_SUCCEEDED, INIT_VBD, INIT_VBD_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED, + SYNC_BLOCK_IO, WRITE_SB_HASH }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Superblock_index _sb_idx { 0 }; + Superblock _sb { }; + Block _blk { }; + Hash _hash { }; + Type_1_node _vbd_root { }; + Type_1_node _ft_root { }; + Type_1_node _mt_root { }; + Generatable_request _write_block { }; + Generatable_request _sync_block_io { }; + Generatable_request _generate_key { }; + Generatable_request _write_sb_hash { }; + Generatable_request _encrypt_key { }; + Generatable_request _init_ft { }; + Generatable_request _init_vbd { }; + + public: + + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Initialize() { } + + void print(Output &out) const { Genode::print(out, "initialize"); } + + bool execute(Block_io &, Trust_anchor &, Vbd_initializer &, Ft_initializer &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + bool execute(Initialize &req, Block_io &block_io, Trust_anchor &trust_anchor, Vbd_initializer &vbd_initializer, Ft_initializer &ft_initializer) + { + return req.execute(block_io, trust_anchor, vbd_initializer, ft_initializer); } - void _mark_req_successful(bool &); - - public: - - Sb_initializer_channel(Module_channel_id id) : Module_channel { SB_INITIALIZER, id } { } - - void execute(bool &); -}; - - -class Tresor::Sb_initializer : public Module -{ - private: - - using Channel = Sb_initializer_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Sb_initializer); - - public: - - Sb_initializer(); - - void execute(bool &) override; + static constexpr char const *name() { return "sb_initializer"; } }; #endif /* _TRESOR__SB_INITIALIZER_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/superblock_control.h b/repos/gems/src/lib/tresor/include/tresor/superblock_control.h index 09e2127525..31cf7db032 100644 --- a/repos/gems/src/lib/tresor/include/tresor/superblock_control.h +++ b/repos/gems/src/lib/tresor/include/tresor/superblock_control.h @@ -20,153 +20,558 @@ #include #include -namespace Tresor { +namespace Tresor { class Superblock_control; } - class Superblock_control; - class Superblock_control_request; - class Superblock_control_channel; -} - -class Tresor::Superblock_control_request : Module_request, Noncopyable -{ - friend class Superblock_control_channel; - - public: - - enum Type { - READ_VBA, WRITE_VBA, SYNC, INITIALIZE, DEINITIALIZE, VBD_EXTENSION_STEP, - FT_EXTENSION_STEP, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, INITIALIZE_REKEYING, - REKEY_VBA }; - - private: - - Type const _type; - Request_offset const _client_req_offset; - Request_tag const _client_req_tag; - Number_of_blocks _nr_of_blks; - Virtual_block_address const _vba; - bool &_success; - bool &_client_req_finished; - Superblock::State &_sb_state; - Generation &_gen; - - public: - - Superblock_control_request(Module_id, Module_channel_id, Type, Request_offset, - Request_tag, Number_of_blocks, Virtual_block_address, - bool &, bool &, Superblock::State &, Generation &); - - static char const *type_to_string(Type); - - void print(Output &) const override; -}; - - -class Tresor::Superblock_control_channel : public Module_channel +class Tresor::Superblock_control : Noncopyable { private: - using Request = Superblock_control_request; - - enum State : State_uint { - INACTIVE, REQ_SUBMITTED, ACCESS_VBA_AT_VBD_SUCCEEDED, - REKEY_VBA_AT_VBD_SUCCEEDED, CREATE_KEY_SUCCEEDED, - TREE_EXT_STEP_IN_TREE_SUCCEEDED, DECRYPT_CURR_KEY_SUCCEEDED, - DECRYPT_PREV_KEY_SUCCEEDED, READ_SB_HASH_SUCCEEDED, ADD_PREV_KEY_SUCCEEDED, - ADD_CURR_KEY_SUCCEEDED, REMOVE_PREV_KEY_SUCCEEDED, REMOVE_CURR_KEY_SUCCEEDED, - READ_SB_SUCCEEDED, REQ_COMPLETE, REQ_GENERATED, SECURE_SB, SECURE_SB_SUCCEEDED }; - - enum Secure_sb_state : State_uint { - SECURE_SB_INACTIVE, STARTED, ENCRYPT_CURR_KEY_SUCCEEDED, - SECURE_SB_REQ_GENERATED, ENCRYPT_PREV_KEY_SUCCEEDED, SYNC_CACHE_SUCCEEDED, - WRITE_SB_SUCCEEDED, SYNC_BLK_IO_SUCCEEDED, WRITE_SB_HASH_SUCCEEDED }; - - State _state { INACTIVE }; - Constructible _ft { }; - Constructible _mt { }; - Secure_sb_state _secure_sb_state { SECURE_SB_INACTIVE }; - Superblock _sb_ciphertext { }; - Block _blk { }; - Generation _gen { INVALID_GENERATION }; - Hash _hash { }; - Physical_block_address _pba { INVALID_PBA }; - Number_of_blocks _nr_of_leaves { 0 }; - Request *_req_ptr { nullptr }; - bool _gen_req_success { false }; - Superblock &_sb; - Superblock_index &_sb_idx; - Generation &_curr_gen; - - NONCOPYABLE(Superblock_control_channel); - - void _generated_req_completed(State_uint) override; - - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == REQ_COMPLETE; } - - void _mark_req_successful(bool &); - - void _mark_req_failed(bool &, char const *); - - void _access_vba(Virtual_block_device_request::Type, bool &); - - void _generate_vbd_req(Virtual_block_device_request::Type, State_uint, bool &, Key_id, Virtual_block_address); - - template - void _generate_req(State_uint complete_state, bool &progress, ARGS &&... args) + class Secure_superblock : Noncopyable { - generate_req(complete_state, progress, args..., _gen_req_success); - if (_state == SECURE_SB) - _secure_sb_state = SECURE_SB_REQ_GENERATED; - else - _state = REQ_GENERATED; - } + public: - void _start_secure_sb(bool &); + using Module = Superblock_control; - void _secure_sb(bool &); + struct Attr { }; - void _tree_ext_step(Superblock::State, bool, String<4>, bool &); + struct Execute_attr + { + Superblock &sb; + Superblock_index &sb_idx; + Generation &curr_gen; + Block_io &block_io; + Trust_anchor &trust_anchor; + }; - void _rekey_vba(bool &); + private: - void _init_rekeying(bool &); + enum State { + INIT, COMPLETE, WRITE_BLOCK, WRITE_BLOCK_SUCCEEDED, SYNC_BLOCK_IO, SYNC_BLOCK_IO_SUCCEEDED, + ENCRYPT_KEY, ENCRYPT_CURR_KEY_SUCCEEDED, ENCRYPT_PREV_KEY_SUCCEEDED, WRITE_SB_HASH, + WRITE_SB_HASH_SUCCEEDED }; - void _discard_snap(bool &); + using Helper = Request_helper; - void _create_snap(bool &); + Helper _helper; + Attr const _attr; + Superblock _sb_ciphertext { }; + Block _blk { }; + Hash _hash { }; + Generation _gen { }; + Generatable_request _write_block { }; + Generatable_request _sync_block_io { }; + Generatable_request _encrypt_key { }; + Generatable_request _write_sb_hash { }; - void _sync(bool &); + public: - void _initialize(bool &); + Secure_superblock(Attr const &attr) : _helper(*this), _attr(attr) { } - void _deinitialize(bool &); + ~Secure_superblock() { } - public: + void print(Output &out) const { Genode::print(out, "secure sb"); } - void execute(bool &); + bool execute(Execute_attr const &); - Superblock_control_channel(Module_channel_id, Superblock &, Superblock_index &, Generation &); -}; - -class Tresor::Superblock_control : public Module -{ - private: - - using Channel = Superblock_control_channel; - - enum { NUM_CHANNELS = 1 }; + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; Superblock _sb { }; - Superblock_index _sb_idx { INVALID_SB_IDX }; - Generation _curr_gen { INVALID_GENERATION }; - Constructible _channels[NUM_CHANNELS] { }; - - void execute(bool &) override; + Superblock_index _sb_idx { }; + Generation _curr_gen { }; public: + class Write_vbas : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr + { + Virtual_block_address const in_first_vba; + Number_of_blocks const in_num_vbas; + Request_offset const in_client_req_offset; + Request_tag const in_client_req_tag; + }; + + struct Execute_attr + { + Virtual_block_device &vbd; + Client_data_interface &client_data; + Block_io &block_io; + Free_tree &free_tree; + Meta_tree &meta_tree; + Crypto &crypto; + Superblock &sb; + Generation const &curr_gen; + }; + + private: + + enum State { INIT, COMPLETE, WRITE_VBA, WRITE_VBA_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_blocks _num_written_vbas { }; + Constructible _ft { }; + Constructible _mt { }; + Generatable_request _write_vba { }; + + void _start_write_vba(Execute_attr const &, bool &); + + public: + + Write_vbas(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Write_vbas() { } + + void print(Output &out) const { Genode::print(out, "write vba"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Extend_free_tree : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr + { + Number_of_blocks const in_num_pbas; + bool &out_extension_finished; + }; + + struct Execute_attr + { + Superblock_control &sb_control; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock &sb; + Generation const &curr_gen; + }; + + private: + + enum State { INIT, COMPLETE, EXTEND_FREE_TREE, EXTEND_FREE_TREE_SUCCEEDED, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_blocks _num_pbas { }; + Physical_block_address _pba { }; + Number_of_blocks _nr_of_leaves { }; + Constructible _ft { }; + Constructible _mt { }; + Generatable_request _secure_sb { }; + Generatable_request _extend_free_tree { }; + + public: + + Extend_free_tree(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Extend_free_tree() { } + + void print(Output &out) const { Genode::print(out, "rekey vba"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Extend_vbd : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr + { + Number_of_blocks const in_num_pbas; + bool &out_extension_finished; + }; + + struct Execute_attr + { + Superblock_control &sb_control; + Virtual_block_device &vbd; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock &sb; + Generation const &curr_gen; + }; + + private: + + enum State { INIT, COMPLETE, EXTEND_VBD, EXTEND_VBD_SUCCEEDED, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_blocks _num_pbas { }; + Physical_block_address _pba { }; + Number_of_blocks _nr_of_leaves { }; + Constructible _ft { }; + Constructible _mt { }; + Generatable_request _secure_sb { }; + Generatable_request _extend_vbd { }; + + public: + + Extend_vbd(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Extend_vbd() { } + + void print(Output &out) const { Genode::print(out, "extend vbd"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Rekey : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { bool &out_rekeying_finished; }; + + struct Execute_attr + { + Superblock &sb; + Generation const &curr_gen; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + Free_tree &free_tree; + Meta_tree &meta_tree; + Virtual_block_device &vbd; + Superblock_control &sb_control; + }; + + private: + + enum State { + INIT, COMPLETE, REKEY_VBA, REKEY_VBA_SUCCEEDED, SECURE_SB, SECURE_SB_SUCCEEDED, REMOVE_KEY, + REMOVE_KEY_SUCCEEDED, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, ADD_KEY, ADD_KEY_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Constructible _ft { }; + Constructible _mt { }; + Generation _gen { }; + Generatable_request _rekey_vba { }; + Generatable_request _remove_key { }; + Generatable_request _secure_sb { }; + Generatable_request _add_key { }; + Generatable_request _generate_key { }; + + public: + + Rekey(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Rekey() { } + + void print(Output &out) const { Genode::print(out, "continue rekeying"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Read_vbas : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr + { + Virtual_block_address const in_first_vba; + Number_of_blocks const in_num_vbas; + Request_offset const in_client_req_offset; + Request_tag const in_client_req_tag; + }; + + struct Execute_attr + { + Virtual_block_device &vbd; + Client_data_interface &client_data; + Block_io &block_io; + Crypto &crypto; + Superblock const &sb; + Generation const &curr_gen; + }; + + private: + + enum State { INIT, COMPLETE, READ_VBA, READ_VBA_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Number_of_blocks _num_read_vbas { }; + Generatable_request _read_vba { }; + + void _start_read_vba(Execute_attr const &, bool &progress); + + public: + + Read_vbas(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Read_vbas() { } + + void print(Output &out) const { Genode::print(out, "read vbas"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Create_snapshot : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { Generation &out_gen; }; + + struct Execute_attr + { + Superblock &sb; + Generation &curr_gen; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generation _gen { }; + Generatable_request _secure_sb { }; + + public: + + Create_snapshot(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Create_snapshot() { } + + void print(Output &out) const { Genode::print(out, "create snapshot"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Synchronize : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { }; + + struct Execute_attr + { + Superblock &sb; + Generation const &curr_gen; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generatable_request _secure_sb { }; + + public: + + Synchronize(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Synchronize() { } + + void print(Output &out) const { Genode::print(out, "sync"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Deinitialize : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { }; + + struct Execute_attr + { + Superblock &sb; + Generation const &curr_gen; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { + INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED, REMOVE_KEY, + REMOVE_CURR_KEY_SUCCEEDED, REMOVE_PREV_KEY_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generatable_request _secure_sb { }; + Generatable_request _remove_key { }; + + public: + + Deinitialize(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Deinitialize() { } + + void print(Output &out) const { Genode::print(out, "deinitialize"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Initialize : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { Superblock::State &out_sb_state; }; + + struct Execute_attr + { + Superblock &sb; + Superblock_index &sb_idx; + Generation &curr_gen; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { + INIT, COMPLETE, READ_SB_HASH, READ_SB_HASH_SUCCEEDED, READ_BLOCK, READ_BLOCK_SUCCEEDED, + DECRYPT_KEY, DECRYPT_CURR_KEY_SUCCEEDED, DECRYPT_PREV_KEY_SUCCEEDED, ADD_KEY, + ADD_CURR_KEY_SUCCEEDED, ADD_PREV_KEY_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generation _gen { }; + Hash _hash { }; + Block _blk { }; + Superblock _sb_ciphertext { }; + Generatable_request _read_block { }; + Generatable_request _read_sb_hash { }; + Generatable_request _decrypt_key { }; + Generatable_request _add_key { }; + + public: + + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Initialize() { } + + void print(Output &out) const { Genode::print(out, "initialize"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Discard_snapshot : Noncopyable + { + public: + + using Module = Superblock_control; + + struct Attr { Generation const in_gen; }; + + struct Execute_attr + { + Superblock &sb; + Generation &curr_gen; + Block_io &block_io; + Trust_anchor &trust_anchor; + Superblock_control &sb_control; + }; + + private: + + enum State { INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Generatable_request _secure_sb { }; + + public: + + Discard_snapshot(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Discard_snapshot() { } + + void print(Output &out) const { Genode::print(out, "discard snapshot"); } + + bool execute(Execute_attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + Virtual_block_address max_vba() const { return _sb.valid() ? _sb.max_vba() : 0; }; Virtual_block_address resizing_nr_of_pbas() const { return _sb.resizing_nr_of_pbas; } @@ -177,7 +582,62 @@ class Tresor::Superblock_control : public Module Superblock_info sb_info() const; - Superblock_control(); + bool execute(Extend_free_tree &req, Free_tree &free_tree, Meta_tree &meta_tree, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({ *this, free_tree, meta_tree, block_io, trust_anchor, _sb, _curr_gen }); + } + + bool execute(Extend_vbd &req, Virtual_block_device &vbd, Free_tree &free_tree, Meta_tree &meta_tree, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({ *this, vbd, free_tree, meta_tree, block_io, trust_anchor, _sb, _curr_gen }); + } + + bool execute(Rekey &req, Virtual_block_device &vbd, Free_tree &free_tree, Meta_tree &meta_tree, Block_io &block_io, Crypto &crypto, Trust_anchor &trust_anchor) + { + return req.execute({ _sb, _curr_gen, block_io, crypto, trust_anchor, free_tree, meta_tree, vbd, *this }); + } + + bool execute(Secure_superblock &req, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _sb_idx, _curr_gen, block_io, trust_anchor }); + } + + bool execute(Synchronize &req, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _curr_gen, block_io, trust_anchor, *this }); + } + + bool execute(Deinitialize &req, Block_io &block_io, Crypto &crypto, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _curr_gen, block_io, crypto, trust_anchor, *this }); + } + + bool execute(Initialize &req, Block_io &block_io, Crypto &crypto, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _sb_idx, _curr_gen, block_io, crypto, trust_anchor, *this }); + } + + bool execute(Create_snapshot &req, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _curr_gen, block_io, trust_anchor, *this }); + } + + bool execute(Discard_snapshot &req, Block_io &block_io, Trust_anchor &trust_anchor) + { + return req.execute({_sb, _curr_gen, block_io, trust_anchor, *this }); + } + + bool execute(Read_vbas &req, Virtual_block_device &vbd, Client_data_interface &client_data, Block_io &block_io, Crypto &crypto) + { + return req.execute({ vbd, client_data, block_io, crypto, _sb, _curr_gen }); + } + + bool execute(Write_vbas &req, Virtual_block_device &vbd, Client_data_interface &client_data, Block_io &block_io, Free_tree &free_tree, Meta_tree &meta_tree, Crypto &crypto) + { + return req.execute({ vbd, client_data, block_io, free_tree, meta_tree, crypto, _sb, _curr_gen }); + } + + static constexpr char const *name() { return "sb_control"; } }; #endif /* _TRESOR__SUPERBLOCK_CONTROL_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h b/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h index b9a08d8ed2..4a2c29133e 100644 --- a/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h +++ b/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h @@ -18,141 +18,232 @@ #include #include -namespace Tresor { +namespace Tresor { class Trust_anchor; } - class Trust_anchor; - class Trust_anchor_request; - class Trust_anchor_channel; -} - -class Tresor::Trust_anchor_request : public Module_request +class Tresor::Trust_anchor : Noncopyable { - friend class Trust_anchor_channel; - public: - enum Type { CREATE_KEY, ENCRYPT_KEY, DECRYPT_KEY, WRITE_HASH, READ_HASH, INITIALIZE }; + struct Attr + { + Vfs::Vfs_handle &decrypt_file; + Vfs::Vfs_handle &encrypt_file; + Vfs::Vfs_handle &generate_key_file; + Vfs::Vfs_handle &initialize_file; + Vfs::Vfs_handle &hash_file; + }; private: - Type const _type; - Key_value &_key_plaintext; - Key_value &_key_ciphertext; - Hash &_hash; - Passphrase const _pass; - bool &_success; - - NONCOPYABLE(Trust_anchor_request); + Attr const _attr; + addr_t _user { }; public: - Trust_anchor_request(Module_id src, Module_channel_id, Type, Key_value &, Key_value &, Hash &, Passphrase, bool &); + class Encrypt_key; + class Decrypt_key; + class Generate_key; + class Initialize; + class Read_hash; + class Write_hash; - static char const *type_to_string(Type); + Trust_anchor(Attr const &attr) : _attr(attr) { } - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } + template + bool execute(REQ &req) + { + if (!_user) + _user = (addr_t)&req; + + if (_user != (addr_t)&req) + return false; + + bool progress = req.execute(_attr); + if (req.complete()) + _user = 0; + + return progress; + } + + static constexpr char const *name() { return "trust_anchor"; } }; -class Tresor::Trust_anchor_channel : public Module_channel +class Tresor::Trust_anchor::Encrypt_key : Noncopyable { + public: + + using Module = Trust_anchor; + + struct Attr + { + Key_value &out_key_ciphertext; + Key_value const &in_key_plaintext; + }; + private: - using Request = Trust_anchor_request; + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; - enum State { REQ_SUBMITTED, REQ_COMPLETE, READ_OK, WRITE_OK, FILE_ERR }; + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; - State _state { REQ_COMPLETE }; - Vfs::Env &_vfs_env; + public: + + Encrypt_key(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "encrypt key"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Trust_anchor::Decrypt_key : Noncopyable +{ + public: + + using Module = Trust_anchor; + + struct Attr + { + Key_value &out_key_plaintext; + Key_value const &in_key_ciphertext; + }; + + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + + public: + + Decrypt_key(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "decrypt key"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Trust_anchor::Initialize : Noncopyable +{ + public: + + using Module = Trust_anchor; + + struct Attr { Passphrase const &in_passphrase; }; + + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; char _result_buf[3]; - Tresor::Path const _path; - Read_write_file _decrypt_file { _state, _vfs_env, { _path, "/decrypt" } }; - Read_write_file _encrypt_file { _state, _vfs_env, { _path, "/encrypt" } }; - Read_write_file _generate_key_file { _state, _vfs_env, { _path, "/generate_key" } }; - Read_write_file _initialize_file { _state, _vfs_env, { _path, "/initialize" } }; - Read_write_file _hashsum_file { _state, _vfs_env, { _path, "/hashsum" } }; - Trust_anchor_request *_req_ptr { nullptr }; - - NONCOPYABLE(Trust_anchor_channel); - - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == REQ_COMPLETE; } - - void _create_key(bool &); - - void _read_hash(bool &); - - void _initialize(bool &); - - void _write_hash(bool &); - - void _encrypt_key(bool &); - - void _decrypt_key(bool &); - - void _mark_req_failed(bool &, Error_string); - - void _mark_req_successful(bool &); public: - void execute(bool &); + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } - Trust_anchor_channel(Module_channel_id, Vfs::Env &, Xml_node const &); + void print(Output &out) const { Genode::print(out, "initialize"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; -class Tresor::Trust_anchor : public Module +class Tresor::Trust_anchor::Generate_key : Noncopyable { + public: + + using Module = Trust_anchor; + + struct Attr { Key_value &out_key_plaintext; }; + private: - using Request = Trust_anchor_request; - using Channel = Trust_anchor_channel; + enum State { INIT, COMPLETE, READ, READ_OK, FILE_ERR }; - Constructible _channels[1] { }; - - NONCOPYABLE(Trust_anchor); + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; public: - struct Create_key : Request - { - Create_key(Module_id m, Module_channel_id c, Key_value &k, bool &s) - : Request(m, c, Request::CREATE_KEY, k, *(Key_value*)0, *(Hash*)0, Passphrase(), s) { } - }; + Generate_key(Attr const &attr) : _helper(*this), _attr(attr) { } - struct Encrypt_key : Request - { - Encrypt_key(Module_id m, Module_channel_id c, Key_value const &kp, Key_value &kc, bool &s) - : Request(m, c, Request::ENCRYPT_KEY, *const_cast(&kp), kc, *(Hash*)0, Passphrase(), s) { } - }; + void print(Output &out) const { Genode::print(out, "generate key"); } - struct Decrypt_key : Request - { - Decrypt_key(Module_id m, Module_channel_id c, Key_value &kp, Key_value const &kc, bool &s) - : Request(m, c, Request::DECRYPT_KEY, kp, *const_cast(&kc), *(Hash*)0, Passphrase(), s) { } - }; + bool execute(Trust_anchor::Attr const &); - struct Write_hash : Request - { - Write_hash(Module_id m, Module_channel_id c, Hash const &h, bool &s) - : Request(m, c, Request::WRITE_HASH, *(Key_value*)0, *(Key_value*)0, *const_cast(&h), Passphrase(), s) { } - }; + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; - struct Read_hash : Request - { - Read_hash(Module_id m, Module_channel_id c, Hash &h, bool &s) - : Request(m, c, Request::READ_HASH, *(Key_value*)0, *(Key_value*)0, h, Passphrase(), s) { } - }; +class Tresor::Trust_anchor::Write_hash : Noncopyable +{ + public: - struct Initialize : Request - { - Initialize(Module_id src_mod, Module_channel_id src_chan, Passphrase pass, bool &succ) - : Request(src_mod, src_chan, Request::INITIALIZE, *(Key_value*)0, *(Key_value*)0, *(Hash*)0, pass, succ) { } - }; + using Module = Trust_anchor; - Trust_anchor(Vfs::Env &, Xml_node const &); + struct Attr { Hash const &in_hash; }; - void execute(bool &) override; + private: + + enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + char _result_buf[3]; + + public: + + Write_hash(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "write hash"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Trust_anchor::Read_hash : Noncopyable +{ + public: + + using Module = Trust_anchor; + + struct Attr { Hash &out_hash; }; + + private: + + enum State { INIT, COMPLETE, READ, READ_OK, FILE_ERR }; + + Request_helper _helper; + Attr const _attr; + Constructible > _file { }; + + public: + + Read_hash(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "read hash"); } + + bool execute(Trust_anchor::Attr const &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #endif /* _TRESOR__TRUST_ANCHOR_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/types.h b/repos/gems/src/lib/tresor/include/tresor/types.h index 9ad7c43a7d..db254df4d8 100644 --- a/repos/gems/src/lib/tresor/include/tresor/types.h +++ b/repos/gems/src/lib/tresor/include/tresor/types.h @@ -23,7 +23,7 @@ /* tresor includes */ #include -#include +#include namespace Tresor { @@ -101,8 +101,15 @@ namespace Tresor { struct Tree_walk_generations; struct Level_indent; struct Tree_root; + struct Tree_configuration; class Pba_allocator; + template + class Request_helper; + + template + class Generatable_request; + template class Fixed_length; @@ -124,8 +131,7 @@ namespace Tresor { return first_pba - 1; } - inline Tree_node_index - t1_node_idx_for_vba_typed(Virtual_block_address vba, Tree_level_index lvl, Tree_degree degr) + inline Tree_node_index tree_node_index(Virtual_block_address vba, Tree_level_index lvl, Tree_degree degr) { uint64_t const degr_log_2 { log2(degr) }; uint64_t const degr_mask { ((uint64_t)1 << degr_log_2) - 1 }; @@ -133,19 +139,6 @@ namespace Tresor { return (Tree_node_index)(degr_mask & (vba >> vba_rshift)); } - template - inline Tree_node_index t1_node_idx_for_vba(T1 vba, T2 lvl, T3 degr) - { - return t1_node_idx_for_vba_typed((Virtual_block_address)vba, (Tree_level_index)lvl, (Tree_degree)degr); - } - - inline Tree_node_index t2_node_idx_for_vba(Virtual_block_address vba, Tree_degree degr) - { - uint64_t const degr_log_2 { log2(degr) }; - uint64_t const degr_mask { ((uint64_t)1 << degr_log_2) - 1 }; - return (Tree_node_index)((uint64_t)vba & degr_mask); - } - inline Virtual_block_address vbd_node_min_vba(Tree_degree_log_2 vbd_degr_log_2, Tree_level_index vbd_lvl, Virtual_block_address vbd_leaf_vba) @@ -167,6 +160,120 @@ namespace Tresor { } +template +class Tresor::Request_helper : Noncopyable +{ + private: + + REQ const &_req; + bool _success { false }; + + public: + + using Module = REQ::Module; + + STATE state { STATE::INIT }; + + Request_helper(REQ &req) : _req(req) { } + + bool complete() const { return state == STATE::COMPLETE; } + + void mark_failed(bool &progress, Error_string const &err_str) + { + error(Module::name(), ": request (", _req, ") failed: ", err_str); + _success = false; + state = STATE::COMPLETE; + progress = true; + } + + void mark_succeeded(bool &progress) + { + _success = true; + state = STATE::COMPLETE; + progress = true; + } + + void generated_req_failed(bool &progress) { mark_failed(progress, "generated request failed"); } + + void generated_req_succeeded(STATE target_state, bool &progress) + { + state = target_state; + progress = true; + } + + void req_generated(STATE target_state, bool &progress) + { + state = target_state; + progress = true; + } + + bool success() const { return _success; } +}; + + +template +class Tresor::Generatable_request +{ + private: + + struct Generated_request + { + OWNER &owner; + OWNER_STATE succeeded_state; + REQUEST req; + + template + Generated_request(OWNER &owner, OWNER_STATE generated_state, OWNER_STATE succeeded_state, + bool &progress, ARGS &&... args) + : + owner(owner), succeeded_state(succeeded_state), req(typename REQUEST::Attr(args...)) + { + owner.req_generated(generated_state, progress); + if (VERBOSE_MODULE_COMMUNICATION) + log(OWNER::Module::name(), " --", req, "--> ", REQUEST::Module::name()); + } + + template + bool execute(REQUEST::Module &dst_mod, ARGS &&... args) + { + bool progress = false; + progress |= dst_mod.execute(req, args...); + if (req.complete()) { + if (VERBOSE_MODULE_COMMUNICATION) + log(OWNER::Module::name(), " <--", req, "-- ", REQUEST::Module::name()); + + if (!req.success()) { + owner.generated_req_failed(progress); + return progress; + } + owner.generated_req_succeeded(succeeded_state, progress); + } + return progress; + } + }; + + Constructible _generated_req { }; + + public: + + template + void generate(ARGS &&... args) + { + _generated_req.construct(args...); + } + + template + bool execute(REQUEST::Module &dst_mod, ARGS &&... args) + { + bool progress = _generated_req->execute(dst_mod, args...); + if (_generated_req->req.complete()) + _generated_req.destruct(); + + return progress; + } +}; + + class Tresor::Pba_allocator { private: @@ -176,7 +283,7 @@ class Tresor::Pba_allocator public: - Pba_allocator(Physical_block_address const first_pba) : _first_pba { first_pba } { } + Pba_allocator(Physical_block_address const first_pba) : _first_pba(first_pba) { } Number_of_blocks num_used_pbas() { return _num_used_pbas; } @@ -317,10 +424,7 @@ class Tresor::Block_scanner public: - Block_scanner(Block const &blk) - : - _blk { blk } - { } + Block_scanner(Block const &blk) : _blk(blk) { } template void fetch(T &dst); @@ -387,10 +491,7 @@ class Tresor::Block_generator public: - Block_generator(Block &blk) - : - _blk { blk } - { } + Block_generator(Block &blk) : _blk(blk) { } template void append(T const &src); @@ -503,6 +604,14 @@ struct Tresor::Tree_root }; +struct Tresor::Tree_configuration +{ + Tree_level_index max_lvl; + Tree_degree degree; + Number_of_leaves num_leaves; +}; + + struct Tresor::Type_1_node_block { Type_1_node nodes[NUM_NODES_PER_BLK] { }; @@ -526,6 +635,11 @@ struct Tresor::Type_1_node_block struct Tresor::Type_1_node_block_walk { Type_1_node_block items[TREE_MAX_NR_OF_LEVELS] { }; + + Type_1_node &node(Virtual_block_address vba, Tree_level_index lvl, Tree_degree degr) + { + return items[lvl].nodes[tree_node_index(vba, lvl, degr)]; + } }; @@ -685,8 +799,8 @@ struct Tresor::Snapshots snap.encode_to_blk(generator); } - void discard_disposable_snapshots(Generation curr_gen, - Generation last_secured_gen) + void discard_disposable_snapshots(Generation last_secured_gen, + Generation curr_gen) { for (Snapshot &snap : items) { @@ -752,31 +866,31 @@ struct Tresor::Superblock enum State { INVALID, NORMAL, REKEYING, EXTENDING_VBD, EXTENDING_FT }; - State state { INVALID }; // offset 0 - Virtual_block_address rekeying_vba { 0 }; // offset 1 - Number_of_blocks resizing_nr_of_pbas { 0 }; // offset 9 - Number_of_leaves resizing_nr_of_leaves { 0 }; // offset 17 - Key previous_key { }; // offset 25 - Key current_key { }; // offset 61 - Snapshots snapshots { }; // offset 97 - Generation last_secured_generation { 0 }; // offset 3553 - Snapshot_index curr_snap_idx { 0 }; // offset 3561 - Tree_degree degree { TREE_MIN_DEGREE }; // offset 3565 - Physical_block_address first_pba { 0 }; // offset 3569 - Number_of_blocks nr_of_pbas { 0 }; // offset 3577 - Generation free_gen { 0 }; // offset 3585 - Physical_block_address free_number { 0 }; // offset 3593 - Hash free_hash { }; // offset 3601 - Tree_level_index free_max_level { 0 }; // offset 3633 - Tree_degree free_degree { TREE_MIN_DEGREE }; // offset 3637 - Number_of_leaves free_leaves { 0 }; // offset 3641 - Generation meta_gen { 0 }; // offset 3649 - Physical_block_address meta_number { 0 }; // offset 3657 - Hash meta_hash { }; // offset 3665 - Tree_level_index meta_max_level { 0 }; // offset 3697 - Tree_degree meta_degree { TREE_MIN_DEGREE }; // offset 3701 - Number_of_leaves meta_leaves { 0 }; // offset 3705 - // offset 3713 + State state { INVALID }; /* offset 0 */ + Virtual_block_address rekeying_vba { 0 }; /* offset 1 */ + Number_of_blocks resizing_nr_of_pbas { 0 }; /* offset 9 */ + Number_of_leaves resizing_nr_of_leaves { 0 }; /* offset 17 */ + Key previous_key { }; /* offset 25 */ + Key current_key { }; /* offset 61 */ + Snapshots snapshots { }; /* offset 97 */ + Generation last_secured_generation { 0 }; /* offset 3553 */ + Snapshot_index curr_snap_idx { 0 }; /* offset 3561 */ + Tree_degree degree { TREE_MIN_DEGREE }; /* offset 3565 */ + Physical_block_address first_pba { 0 }; /* offset 3569 */ + Number_of_blocks nr_of_pbas { 0 }; /* offset 3577 */ + Generation free_gen { 0 }; /* offset 3585 */ + Physical_block_address free_number { 0 }; /* offset 3593 */ + Hash free_hash { }; /* offset 3601 */ + Tree_level_index free_max_level { 0 }; /* offset 3633 */ + Tree_degree free_degree { TREE_MIN_DEGREE }; /* offset 3637 */ + Number_of_leaves free_leaves { 0 }; /* offset 3641 */ + Generation meta_gen { 0 }; /* offset 3649 */ + Physical_block_address meta_number { 0 }; /* offset 3657 */ + Hash meta_hash { }; /* offset 3665 */ + Tree_level_index meta_max_level { 0 }; /* offset 3697 */ + Tree_degree meta_degree { TREE_MIN_DEGREE }; /* offset 3701 */ + Number_of_leaves meta_leaves { 0 }; /* offset 3705 */ + /* offset 3713 */ static State decode_state(On_disc_state val) { @@ -981,6 +1095,19 @@ struct Tresor::Snapshots_info for (Generation &gen : generations) gen = INVALID_GENERATION; } + + void print(Output &out) const + { + bool first { true }; + for (unsigned idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + + if (!generations[idx]) + continue; + + Genode::print(out, "snapshot ", first ? "" : "\n", idx, ": ", generations[idx]); + first = false; + } + } }; @@ -1028,8 +1155,7 @@ class Tresor::Pba_allocation { Pba_allocation(Type_1_node_walk const &t1_node_walk, Tree_walk_pbas const &new_pbas) : - _t1_node_walk { t1_node_walk }, - _new_pbas { new_pbas } + _t1_node_walk(t1_node_walk), _new_pbas(new_pbas) { } void print(Output &out) const diff --git a/repos/gems/src/lib/tresor/include/tresor/vbd_check.h b/repos/gems/src/lib/tresor/include/tresor/vbd_check.h index 5a23231c2c..d45bbd2d92 100644 --- a/repos/gems/src/lib/tresor/include/tresor/vbd_check.h +++ b/repos/gems/src/lib/tresor/include/tresor/vbd_check.h @@ -16,94 +16,51 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Vbd_check; } - class Vbd_check; - class Vbd_check_request; - class Vbd_check_channel; -} - - -class Tresor::Vbd_check_request : public Module_request +struct Tresor::Vbd_check : Noncopyable { - friend class Vbd_check_channel; + class Check : Noncopyable + { + public: - private: + using Module = Vbd_check; - Tree_root const &_vbd; - bool &_success; + struct Attr { Tree_root const &in_vbd; }; - NONCOPYABLE(Vbd_check_request); + private: - public: + enum State { INIT, IN_PROGRESS, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED }; - Vbd_check_request(Module_id, Module_channel_id, Tree_root const &, bool &); + Request_helper _helper; + Attr const _attr; + Type_1_node_block_walk _t1_blks { }; + bool _check_node[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { }; + Block _blk { }; + Number_of_leaves _num_remaining_leaves { 0 }; + Generatable_request, State, Block_io::Read> _read_block { }; - void print(Output &out) const override { Genode::print(out, "check ", _vbd); } -}; + bool _execute_node(Block_io &, Tree_level_index, Tree_node_index, bool &); + public: -class Tresor::Vbd_check_channel : public Module_channel -{ - private: + Check(Attr const &attr) : _helper(*this), _attr(attr) { } - using Request = Vbd_check_request; + void print(Output &out) const { Genode::print(out, "check ", _attr.in_vbd); } - enum State : State_uint { REQ_SUBMITTED, REQ_IN_PROGRESS, REQ_COMPLETE, REQ_GENERATED, READ_BLK_SUCCEEDED }; + bool execute(Block_io &); - State _state { REQ_COMPLETE }; - Type_1_node_block_walk _t1_blks { }; - bool _check_node[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { }; - Block _blk { }; - Request *_req_ptr { }; - Number_of_leaves _num_remaining_leaves { 0 }; - bool _generated_req_success { false }; + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - NONCOPYABLE(Vbd_check_channel); + Vbd_check() { } - void _generated_req_completed(State_uint) override; + bool execute(Check &req, Block_io &block_io) { return req.execute(block_io); } - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == REQ_COMPLETE; } - - void _mark_req_failed(bool &, Error_string); - - void _mark_req_successful(bool &); - - bool _execute_node(Tree_level_index, Tree_node_index, bool &); - - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) - { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); - } - - public: - - Vbd_check_channel(Module_channel_id id) : Module_channel { VBD_CHECK, id } { } - - void execute(bool &); -}; - - -class Tresor::Vbd_check : public Module -{ - private: - - using Channel = Vbd_check_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Vbd_check); - - public: - - Vbd_check(); - - void execute(bool &) override; + static constexpr char const *name() { return "vbd_check"; } }; #endif /* _TRESOR__VBD_CHECK_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h b/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h index ac8db70ca4..03e9f33b80 100644 --- a/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h +++ b/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h @@ -17,92 +17,65 @@ /* tresor includes */ #include +#include -namespace Tresor { +namespace Tresor { class Vbd_initializer; } - class Vbd_initializer; - class Vbd_initializer_request; - class Vbd_initializer_channel; -} - - -class Tresor::Vbd_initializer_request : public Module_request +class Tresor::Vbd_initializer : Noncopyable { - friend class Vbd_initializer_channel; - - private: - - Tree_root &_vbd; - Pba_allocator &_pba_alloc; - bool &_success; - - NONCOPYABLE(Vbd_initializer_request); - public: - Vbd_initializer_request(Module_id, Module_channel_id, Tree_root &, Pba_allocator &, bool &); + class Initialize : Noncopyable + { + public: - void print(Output &out) const override { Genode::print(out, "init"); } -}; + using Module = Vbd_initializer; + struct Attr + { + Tree_configuration const in_tree_cfg; + Type_1_node &out_tree_root; + Pba_allocator &in_out_pba_alloc; + }; -class Tresor::Vbd_initializer_channel : public Module_channel -{ - private: + private: - using Request = Vbd_initializer_request; + enum State { INIT, COMPLETE, WRITE_BLOCK, EXECUTE_NODES }; - enum State { REQ_GENERATED, SUBMITTED, COMPLETE, EXECUTE_NODES }; + enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITING_BLOCK }; - enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLOCK }; + using Helper = Request_helper; - State _state { COMPLETE }; - Vbd_initializer_request *_req_ptr { }; - Type_1_node_block_walk _t1_blks { }; - Node_state _node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { DONE }; - bool _generated_req_success { false }; - Block _blk { }; - Number_of_leaves _num_remaining_leaves { }; + Helper _helper; + Attr const _attr; + Type_1_node_block_walk _t1_blks { }; + Node_state _node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { DONE }; + bool _generated_req_success { false }; + Block _blk { }; + Number_of_leaves _num_remaining_leaves { }; + Generatable_request _write_block { }; - NONCOPYABLE(Vbd_initializer_channel); + void _reset_level(Tree_level_index, Node_state); - void _generated_req_completed(State_uint) override; + bool _execute_node(Tree_level_index, Tree_node_index, bool &); - bool _request_complete() override { return _state == COMPLETE; } + public: - void _request_submitted(Module_request &) override; + Initialize(Attr const &attr) : _helper(*this), _attr(attr) { } - void _reset_level(Tree_level_index, Node_state); + ~Initialize() { } - bool _execute_node(Tree_level_index, Tree_node_index, bool &); + void print(Output &out) const { Genode::print(out, "initialize"); } - void _mark_req_failed(bool &, char const *); + bool execute(Block_io &); - void _mark_req_successful(bool &); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; - public: + bool execute(Initialize &req, Block_io &block_io) { return req.execute(block_io); } - Vbd_initializer_channel(Module_channel_id id) : Module_channel { VBD_INITIALIZER, id } { } - - void execute(bool &); -}; - - -class Tresor::Vbd_initializer : public Module -{ - private: - - using Channel = Vbd_initializer_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Vbd_initializer); - - public: - - Vbd_initializer(); - - void execute(bool &) override; + static constexpr char const *name() { return "vbd_initializer"; } }; #endif /* _TRESOR__VBD_INITIALIZER_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/verbosity.h b/repos/gems/src/lib/tresor/include/tresor/verbosity.h index a9f32f1287..3b3ac5c05a 100644 --- a/repos/gems/src/lib/tresor/include/tresor/verbosity.h +++ b/repos/gems/src/lib/tresor/include/tresor/verbosity.h @@ -24,7 +24,6 @@ namespace Tresor { enum { VERBOSE_REKEYING = 0 }; enum { VERBOSE_READ_VBA = 0 }; enum { VERBOSE_WRITE_VBA = 0 }; - enum { VERBOSE_CRYPTO = 0 }; enum { VERBOSE_BLOCK_IO = 0 }; enum { VERBOSE_BLOCK_IO_PBA_FILTER = 0 }; enum { VERBOSE_BLOCK_IO_PBA = 0 }; diff --git a/repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h b/repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h index 0c9b6a44fd..b5df8f4655 100644 --- a/repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h +++ b/repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h @@ -17,134 +17,270 @@ /* tresor includes */ #include #include +#include +#include +#include -namespace Tresor { +namespace Tresor { class Virtual_block_device; } - class Virtual_block_device; - class Virtual_block_device_request; - class Virtual_block_device_channel; -} - -class Tresor::Virtual_block_device_request : public Module_request +class Tresor::Virtual_block_device : Noncopyable { - friend class Virtual_block_device_channel; - public: - enum Type { REKEY_VBA, READ_VBA, WRITE_VBA, EXTENSION_STEP }; - - private: - - Type const _type; - Virtual_block_address const _vba; - Snapshots &_snapshots; - Snapshot_index const _curr_snap_idx; - Tree_degree const _snap_degr; - Generation const _curr_gen; - Key_id const _curr_key_id; - Key_id const _prev_key_id; - Tree_root &_ft; - Tree_root &_mt; - Tree_degree const _vbd_degree; - Virtual_block_address const _vbd_highest_vba; - bool const _rekeying; - Request_offset const _client_req_offset; - Request_tag const _client_req_tag; - Generation const _last_secured_gen; - Physical_block_address &_pba; - Number_of_blocks &_num_pbas; - Number_of_leaves &_num_leaves; - Virtual_block_address const _rekeying_vba; - bool &_success; - - NONCOPYABLE(Virtual_block_device_request); - - public: - - Virtual_block_device_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Generation, - Tree_root &, Tree_root &, Tree_degree, Virtual_block_address, bool, - Virtual_block_address, Snapshot_index, Snapshots &, Tree_degree, Key_id, - Key_id, Generation, Physical_block_address &, bool &, Number_of_leaves &, - Number_of_blocks &, Virtual_block_address); - - static char const *type_to_string(Type); - - void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } -}; - -class Tresor::Virtual_block_device_channel : public Module_channel -{ - private: - - using Request = Virtual_block_device_request; - - enum State { - SUBMITTED, REQ_GENERATED, REQ_COMPLETE, READ_BLK_SUCCEEDED, WRITE_BLK_SUCCEEDED, - DECRYPT_LEAF_DATA_SUCCEEDED, ENCRYPT_LEAF_DATA_SUCCEEDED, ALLOC_PBAS_SUCCEEDED }; - - Request *_req_ptr { nullptr }; - State _state { REQ_COMPLETE }; - Snapshot_index _snap_idx { 0 }; - Type_1_node_block_walk _t1_blks { }; - Type_1_node_walk _t1_nodes { }; - Tree_level_index _lvl { 0 }; - Virtual_block_address _vba { 0 }; - Tree_walk_pbas _old_pbas { }; - Tree_walk_pbas _new_pbas { }; - Hash _hash { }; - Number_of_blocks _num_blks { 0 }; - Generation _free_gen { 0 }; - Block _encoded_blk { }; - Block _data_blk { }; - bool _first_snapshot { false }; - bool _gen_req_success { false }; - - NONCOPYABLE(Virtual_block_device_channel); + class Rekey_vba; + class Read_vba; + class Write_vba; + class Extend_tree; template - void _generate_req(State_uint complete_state, bool &progress, ARGS &&... args) + bool execute(REQUEST &req, ARGS &&... args) { return req.execute(args...); } + + static constexpr char const *name() { return "vbd"; } +}; + +class Tresor::Virtual_block_device::Rekey_vba : Noncopyable +{ + public: + + using Module = Virtual_block_device; + + struct Attr { - generate_req(complete_state, progress, args..., _gen_req_success); - _state = REQ_GENERATED; - } + Snapshots &in_out_snapshots; + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Virtual_block_address const in_vba; + Generation const in_curr_gen; + Generation const in_last_secured_gen; + Key_id const in_curr_key_id; + Key_id const in_prev_key_id; + Tree_degree const in_vbd_degree; + Virtual_block_address const in_vbd_highest_vba; + }; - void _request_submitted(Module_request &) override; + private: - bool _request_complete() override { return _state == REQ_COMPLETE; } + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED, + DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, + ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED }; - void _generated_req_completed(State_uint) override; + using Helper = Request_helper; - void _generate_ft_req(State, bool, Free_tree_request::Type); + Helper _helper; + Attr const _attr; + Tree_level_index _lvl { 0 }; + Type_1_node_block_walk _t1_blks { }; + Block _encoded_blk { }; + Block _data_blk { }; + Generation _free_gen { 0 }; + Tree_walk_pbas _old_pbas { }; + Tree_walk_pbas _new_pbas { }; + Snapshot_index _snap_idx { 0 }; + Type_1_node_walk _t1_nodes { }; + Number_of_blocks _num_blks { 0 }; + Hash _hash { }; + bool _first_snapshot { false }; + Generatable_request _read_block { }; + Generatable_request _write_block { }; + Generatable_request _encrypt_block { }; + Generatable_request _decrypt_block { }; + Generatable_request _alloc_pbas { }; - Snapshot &snap() { return _req_ptr->_snapshots.items[_snap_idx]; } + bool _check_and_decode_read_blk(bool &); + + void _start_alloc_pbas(bool &, Free_tree::Allocate_pbas::Application); void _generate_write_blk_req(bool &); bool _find_next_snap_to_rekey_vba_at(Snapshot_index &) const; - void _read_vba(bool &); + void _generate_ft_alloc_req_for_rekeying(Tree_level_index, bool &); + + public: + + Rekey_vba(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Rekey_vba() { } + + void print(Output &out) const { Genode::print(out, "rekey vba"); } + + bool execute(Block_io &, Crypto &, Free_tree &, Meta_tree &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Virtual_block_device::Read_vba : Noncopyable +{ + public: + + using Module = Virtual_block_device; + + struct Attr + { + Snapshot const &in_snap; + Virtual_block_address const in_vba; + Key_id const in_key_id; + Tree_degree const in_vbd_degree; + Request_offset const in_client_req_offset; + Request_tag const in_client_req_tag; + }; + + private: + + enum State { INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Tree_level_index _lvl { 0 }; + Type_1_node_block_walk _t1_blks { }; + Hash _hash { }; + Block _blk { }; + Tree_walk_pbas _new_pbas { }; + Generatable_request _read_block { }; + Generatable_request _decrypt_block { }; bool _check_and_decode_read_blk(bool &); - Tree_node_index _node_idx(Tree_level_index, Virtual_block_address) const; + public: - Type_1_node &_node(Tree_level_index, Virtual_block_address); + Read_vba(Attr const &attr) : _helper(*this), _attr(attr) { } - void _mark_req_successful(bool &); + ~Read_vba() { } - void _mark_req_failed(bool &, char const *); + void print(Output &out) const { Genode::print(out, "read vba"); } + + bool execute(Client_data_interface &, Block_io &, Crypto &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Virtual_block_device::Write_vba : Noncopyable +{ + public: + + using Module = Virtual_block_device; + + struct Attr + { + Snapshot &in_out_snap; + Snapshots const &in_snapshots; + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Virtual_block_address const in_vba; + Key_id const in_curr_key_id; + Key_id const in_prev_key_id; + Tree_degree const in_vbd_degree; + Virtual_block_address const in_vbd_highest_vba; + Request_offset const in_client_req_offset; + Request_tag const in_client_req_tag; + Generation const in_curr_gen; + Generation const in_last_secured_gen; + bool in_rekeying; + Virtual_block_address const in_rekeying_vba; + }; + + private: + + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED, + WRITE_BLK, WRITE_BLK_SUCCEEDED, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Tree_level_index _lvl { 0 }; + Type_1_node_block_walk _t1_blks { }; + Hash _hash { }; + Type_1_node_walk _t1_nodes { }; + Block _data_blk { }; + Block _encoded_blk { }; + Tree_walk_pbas _new_pbas { }; + Number_of_blocks _num_blks { 0 }; + Generation _free_gen { 0 }; + Generatable_request _read_block { }; + Generatable_request _decrypt_block { }; + Generatable_request _encrypt_block { }; + Generatable_request _alloc_pbas { }; + Generatable_request _write_block { }; + + bool _check_and_decode_read_blk(bool &); void _set_new_pbas_and_num_blks_for_alloc(); - void _generate_ft_alloc_req_for_write_vba(bool &); - - void _write_vba(bool &); - void _update_nodes_of_branch_of_written_vba(); - void _rekey_vba(bool &); + void _generate_ft_alloc_req_for_write_vba(bool &); - void _generate_ft_alloc_req_for_rekeying(Tree_level_index, bool &); + void _generate_write_blk_req(bool &); + + public: + + Write_vba(Attr const &attr) : _helper(*this), _attr(attr) { } + + ~Write_vba() { } + + void print(Output &out) const { Genode::print(out, "write vba"); } + + bool execute(Client_data_interface &, Block_io &, Free_tree &, Meta_tree &, Crypto &); + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } +}; + +class Tresor::Virtual_block_device::Extend_tree : Noncopyable +{ + public: + + using Module = Virtual_block_device; + + struct Attr + { + Number_of_leaves &out_num_leaves; + Snapshots &in_out_snapshots; + Tree_degree const in_snap_degr; + Generation const in_curr_gen; + Generation const in_last_secured_gen; + Physical_block_address &in_out_first_pba; + Number_of_blocks &in_out_num_pbas; + Tree_root &in_out_ft; + Tree_root &in_out_mt; + Tree_degree const in_vbd_degree; + Virtual_block_address const in_vbd_highest_vba; + Key_id const in_curr_key_id; + Key_id const in_prev_key_id; + bool in_rekeying; + Virtual_block_address const in_rekeying_vba; + }; + + private: + + enum State { + INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED }; + + using Helper = Request_helper; + + Helper _helper; + Attr const _attr; + Tree_level_index _lvl { 0 }; + Snapshot_index _snap_idx { 0 }; + Virtual_block_address _vba { 0 }; + Tree_walk_pbas _old_pbas { }; + Block _encoded_blk { }; + Tree_walk_pbas _new_pbas { }; + Type_1_node_block_walk _t1_blks { }; + Number_of_blocks _num_blks { 0 }; + Type_1_node_walk _t1_nodes { }; + Block _data_blk { }; + Generation _free_gen { 0 }; + Generatable_request _read_block { }; + Generatable_request _write_block { }; + Generatable_request _alloc_pbas { }; void _add_new_root_lvl_to_snap(); @@ -152,32 +288,22 @@ class Tresor::Virtual_block_device_channel : public Module_channel void _set_new_pbas_identical_to_curr_pbas(); + void _generate_write_blk_req(bool &); + void _generate_ft_alloc_req_for_resizing(Tree_level_index, bool &); - void _extension_step(bool &); - public: - Virtual_block_device_channel(Module_channel_id id) : Module_channel { VIRTUAL_BLOCK_DEVICE, id } { } + Extend_tree(Attr const &attr) : _helper(*this), _attr(attr) { } - void execute(bool &); -}; + ~Extend_tree() { } -class Tresor::Virtual_block_device : public Module -{ - private: + void print(Output &out) const { Genode::print(out, "extend tree"); } - using Channel = Virtual_block_device_channel; + bool execute(Block_io &, Free_tree &, Meta_tree &); - Constructible _channels[1] { }; - - NONCOPYABLE(Virtual_block_device); - - void execute(bool &) override; - - public: - - Virtual_block_device(); + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } }; #endif /* _TRESOR__VIRTUAL_BLOCK_DEVICE_H_ */ diff --git a/repos/gems/src/lib/tresor/meta_tree.cc b/repos/gems/src/lib/tresor/meta_tree.cc index 1bbe5512bf..b16c7d2662 100644 --- a/repos/gems/src/lib/tresor/meta_tree.cc +++ b/repos/gems/src/lib/tresor/meta_tree.cc @@ -1,5 +1,5 @@ /* - * \brief Module for doing VBD COW allocations on the meta tree + * \brief Module for doing PBA allocations for the Free Tree via the Meta Tree * \author Martin Stein * \date 2023-02-13 */ @@ -13,149 +13,32 @@ /* tresor includes */ #include -#include #include using namespace Tresor; -char const *Meta_tree_request::type_to_string(Type type) +bool Meta_tree::execute(Allocate_pba &req, Block_io &block_io) { return req.execute(block_io); } + + +void Meta_tree::Allocate_pba::_start_tree_traversal(bool &progress) { - switch (type) { - case ALLOC_PBA: return "alloc pba"; - } - ASSERT_NEVER_REACHED; -} - - -Meta_tree_request::Meta_tree_request(Module_id src_module_id, Module_channel_id src_channel_id, - Type type, Tree_root &mt, Generation curr_gen, - Physical_block_address &pba, bool &success) -: - Module_request { src_module_id, src_channel_id, META_TREE }, _type { type }, _mt { mt }, - _curr_gen { curr_gen }, _pba { pba }, _success { success } -{ } - - -void Meta_tree::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -bool Meta_tree_channel::_can_alloc_pba_of(Type_2_node &node) -{ - return node.valid() && node.alloc_gen != _req_ptr->_curr_gen; -} - - -void Meta_tree_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_generated_req_success) { - error("meta tree: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -void Meta_tree_channel::_alloc_pba_of(Type_2_node &t2_node, Physical_block_address &pba) -{ - Request &req { *_req_ptr }; - Physical_block_address old_pba { pba }; - pba = t2_node.pba; - t2_node.pba = old_pba; - t2_node.alloc_gen = req._curr_gen; - t2_node.free_gen = req._curr_gen; - t2_node.reserved = false; -} - - -void Meta_tree_channel::_mark_req_failed(bool &progress, char const *str) -{ - error(Request::type_to_string(_req_ptr->_type), " request failed, reason: \"", str, "\""); - _req_ptr->_success = false; - _state = COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Meta_tree_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Meta_tree_channel::_start_tree_traversal(bool &progress) -{ - Request &req { *_req_ptr }; - _lvl = req._mt.max_lvl; + _lvl = _attr.in_out_mt.max_lvl; _node_idx[_lvl] = 0; - _t1_blks[_lvl].nodes[_node_idx[_lvl]] = req._mt.t1_node(); - _generate_req(SEEK_DOWN, progress, req._mt.pba, _blk); + _t1_blks[_lvl].nodes[_node_idx[_lvl]] = _attr.in_out_mt.t1_node(); + _read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, _attr.in_out_mt.pba, _blk); } -void Meta_tree_channel::_traverse_curr_node(bool &progress) +bool Meta_tree::Allocate_pba::execute(Block_io &block_io) { - Request &req { *_req_ptr }; - if (_lvl) { - Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; - if (t1_node.pba) - _generate_req(SEEK_DOWN, progress, t1_node.pba, _blk); - else { - _state = SEEK_LEFT_OR_UP; - progress = true; - } - } else { - Type_2_node &t2_node { _t2_blk.nodes[_node_idx[_lvl]] }; - if (_can_alloc_pba_of(t2_node)) { - _alloc_pba_of(t2_node, _req_ptr->_pba); - for (Tree_level_index lvl { 1 }; lvl <= req._mt.max_lvl; lvl++) { - Type_1_node &t1_node { _t1_blks[lvl].nodes[_node_idx[lvl]] }; - if (!t1_node.is_volatile(req._curr_gen)) { - bool pba_allocated { false }; - for (Type_2_node &t2_node : _t2_blk.nodes) { - if (_can_alloc_pba_of(t2_node)) { - _alloc_pba_of(t2_node, t1_node.pba); - pba_allocated = true; - break; - } - } - ASSERT(pba_allocated); - } - } - _state = WRITE_BLK; - } else - _state = SEEK_LEFT_OR_UP; - progress = true; - } -} - - -void Meta_tree_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - _start_tree_traversal(progress); - break; - + bool progress = false; + switch (_helper.state) { + case INIT: _start_tree_traversal(progress); break; + case READ_BLK: progress |= _read_block.execute(block_io); break; case SEEK_DOWN: if (!check_hash(_blk, _t1_blks[_lvl].nodes[_node_idx[_lvl]].hash)) { - _mark_req_failed(progress, "hash mismatch"); + _helper.mark_failed(progress, "hash mismatch"); break; } _lvl--; @@ -169,54 +52,91 @@ void Meta_tree_channel::execute(bool &progress) case SEEK_LEFT_OR_UP: - if (_lvl < req._mt.max_lvl) { - if (_node_idx[_lvl] < req._mt.degree - 1) { + if (_lvl < _attr.in_out_mt.max_lvl) { + if (_node_idx[_lvl] < _attr.in_out_mt.degree - 1) { _node_idx[_lvl]++; _traverse_curr_node(progress); } else { _lvl++; - _state = SEEK_LEFT_OR_UP; + _helper.state = SEEK_LEFT_OR_UP; progress = true; } } else - _mark_req_failed(progress, "not enough free pbas"); + _helper.mark_failed(progress, "not enough free pbas"); break; - case WRITE_BLK: + case WRITE_BLK: progress |= _write_block.execute(block_io); break; + case WRITE_BLK_SUCCEEDED: - if (_lvl < req._mt.max_lvl) { + if (_lvl < _attr.in_out_mt.max_lvl) { if (_lvl) _t1_blks[_lvl].encode_to_blk(_blk); else _t2_blk.encode_to_blk(_blk); _lvl++; Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; - t1_node.gen = req._curr_gen; + t1_node.gen = _attr.in_curr_gen; calc_hash(_blk, t1_node.hash); - _generate_req(WRITE_BLK, progress, t1_node.pba, _blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, t1_node.pba, _blk); } else { - req._mt.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); - _mark_req_successful(progress); + _attr.in_out_mt.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]); + _helper.mark_succeeded(progress); } break; default: break; } + return progress; } -void Meta_tree_channel::_request_submitted(Module_request &mod_req) +bool Meta_tree::Allocate_pba::_can_alloc_pba_of(Type_2_node &node) { - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; + return node.valid() && node.alloc_gen != _attr.in_curr_gen; } -Meta_tree::Meta_tree() +void Meta_tree::Allocate_pba::_alloc_pba_of(Type_2_node &t2_node, Physical_block_address &pba) { - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); + Physical_block_address old_pba { pba }; + pba = t2_node.pba; + t2_node.pba = old_pba; + t2_node.alloc_gen = _attr.in_curr_gen; + t2_node.free_gen = _attr.in_curr_gen; + t2_node.reserved = false; +} + +void Meta_tree::Allocate_pba::_traverse_curr_node(bool &progress) +{ + if (_lvl) { + Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] }; + if (t1_node.pba) + _read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, t1_node.pba, _blk); + else { + _helper.state = SEEK_LEFT_OR_UP; + progress = true; + } + } else { + Type_2_node &t2_node { _t2_blk.nodes[_node_idx[_lvl]] }; + if (_can_alloc_pba_of(t2_node)) { + _alloc_pba_of(t2_node, _attr.in_out_pba); + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_out_mt.max_lvl; lvl++) { + Type_1_node &t1_node { _t1_blks[lvl].nodes[_node_idx[lvl]] }; + if (!t1_node.is_volatile(_attr.in_curr_gen)) { + bool pba_allocated { false }; + for (Type_2_node &t2_node : _t2_blk.nodes) { + if (_can_alloc_pba_of(t2_node)) { + _alloc_pba_of(t2_node, t1_node.pba); + pba_allocated = true; + break; + } + } + ASSERT(pba_allocated); + } + } + _helper.state = WRITE_BLK_SUCCEEDED; + } else + _helper.state = SEEK_LEFT_OR_UP; + progress = true; } } diff --git a/repos/gems/src/lib/tresor/module.cc b/repos/gems/src/lib/tresor/module.cc deleted file mode 100644 index 17bab9a658..0000000000 --- a/repos/gems/src/lib/tresor/module.cc +++ /dev/null @@ -1,145 +0,0 @@ -/* - * \brief Framework for component internal modularization - * \author Martin Stein - * \date 2023-02-13 - */ - -/* - * Copyright (C) 2023 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. - */ - -/* tresor includes */ -#include -#include - -using namespace Tresor; - - -Module_request::Module_request(Module_id src_module_id, Module_channel_id src_chan_id, Module_id dst_module_id) -: - _src_module_id { src_module_id }, _src_chan_id { src_chan_id }, _dst_module_id { dst_module_id } -{ } - - -char const *Tresor::module_name(Module_id id) -{ - switch (id) { - case CRYPTO: return "crypto"; - case BLOCK_IO: return "block_io"; - case CACHE: return "cache"; - case META_TREE: return "meta_tree"; - case FREE_TREE: return "free_tree"; - case VIRTUAL_BLOCK_DEVICE: return "vbd"; - case SUPERBLOCK_CONTROL: return "sb_control"; - case CLIENT_DATA: return "client_data"; - case TRUST_ANCHOR: return "trust_anchor"; - case COMMAND_POOL: return "command_pool"; - case VBD_INITIALIZER: return "vbd_initializer"; - case FT_INITIALIZER: return "ft_initializer"; - case SB_INITIALIZER: return "sb_initializer"; - case SB_CHECK: return "sb_check"; - case VBD_CHECK: return "vbd_check"; - case FT_CHECK: return "ft_check"; - case SPLITTER: return "splitter"; - case REQUEST_POOL: return "request_pool"; - default: break; - } - ASSERT_NEVER_REACHED; -} - - -void Module_channel::generated_req_completed() -{ - ASSERT(_gen_req_state == IN_PROGRESS); - _gen_req_state = NONE; - _generated_req_completed(_gen_req_complete_state); -} - - -bool Module_channel::try_submit_request(Module_request &req) -{ - if (_req_ptr) - return false; - - req.dst_chan_id(_id); - _req_ptr = &req; - _request_submitted(req); - return true; -} - - -bool Module::try_submit_request(Module_request &req) -{ - bool success { false }; - for_each_channel([&] (Module_channel &chan) { - if (success) - return; - - success = chan.try_submit_request(req); - }); - return success; -} - - -void Module_composition::execute_modules() -{ - bool progress { true }; - while (progress) { - - progress = false; - for (Module_id id { 0 }; id <= MAX_MODULE_ID; id++) { - if (!_module_ptrs[id]) - continue; - - Module &mod { *_module_ptrs[id] }; - mod.execute(progress); - mod.for_each_generated_request([&] (Module_request &req) { - ASSERT(req.dst_module_id() <= MAX_MODULE_ID); - ASSERT(_module_ptrs[req.dst_module_id()]); - Module &dst_module { *_module_ptrs[req.dst_module_id()] }; - if (dst_module.try_submit_request(req)) { - if (VERBOSE_MODULE_COMMUNICATION) - log(module_name(id), " ", req.src_chan_id(), " --", req, "--> ", - module_name(req.dst_module_id()), " ", req.dst_chan_id()); - - progress = true; - return true; - } - if (VERBOSE_MODULE_COMMUNICATION) - log(module_name(id), " ", req.src_chan_id(), " --", req, "-| ", module_name(req.dst_module_id())); - - return false; - }); - mod.for_each_completed_request([&] (Module_request &req) { - ASSERT(req.src_module_id() <= MAX_MODULE_ID); - if (VERBOSE_MODULE_COMMUNICATION) - log(module_name(req.src_module_id()), " ", req.src_chan_id(), " <--", req, - "-- ", module_name(id), " ", req.dst_chan_id()); - - Module &src_module { *_module_ptrs[req.src_module_id()] }; - src_module.with_channel(req.src_chan_id(), [&] (Module_channel &chan) { - chan.generated_req_completed(); }); - progress = true; - }); - } - }; -} - - -void Module_composition::add_module(Module_id module_id, Module &mod) -{ - ASSERT(module_id <= MAX_MODULE_ID); - ASSERT(!_module_ptrs[module_id]); - _module_ptrs[module_id] = &mod; -} - - -void Module_composition::remove_module(Module_id module_id) -{ - ASSERT(module_id <= MAX_MODULE_ID); - ASSERT(_module_ptrs[module_id]); - _module_ptrs[module_id] = nullptr; -} diff --git a/repos/gems/src/lib/tresor/request_pool.cc b/repos/gems/src/lib/tresor/request_pool.cc deleted file mode 100644 index aefba814c2..0000000000 --- a/repos/gems/src/lib/tresor/request_pool.cc +++ /dev/null @@ -1,381 +0,0 @@ -/* - * \brief Module for scheduling requests for processing - * \author Martin Stein - * \date 2023-03-17 - */ - -/* - * Copyright (C) 2023 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. - */ - -/* tresor includes */ -#include - -using namespace Tresor; - -Request::Request(Module_id src_module_id, Module_channel_id src_chan_id, Operation op, Virtual_block_address vba, - Request_offset offset, Number_of_blocks count, Key_id key_id, Request_tag tag, Generation &gen, bool &success) -: - Module_request { src_module_id, src_chan_id, REQUEST_POOL }, _op { op }, _vba { vba }, _offset { offset }, - _count { count }, _key_id { key_id }, _tag { tag }, _gen { gen }, _success { success } -{ } - - -void Request::print(Output &out) const -{ - Genode::print(out, op_to_string(_op)); - switch (_op) { - case READ: - case WRITE: - case SYNC: - if (_count > 1) - Genode::print(out, " vbas ", _vba, "..", _vba + _count - 1); - else - Genode::print(out, " vba ", _vba); - break; - default: break; - } -} - - -char const *Request::op_to_string(Operation op) -{ - switch (op) { - case Request::READ: return "read"; - case Request::WRITE: return "write"; - case Request::SYNC: return "sync"; - case Request::CREATE_SNAPSHOT: return "create_snapshot"; - case Request::DISCARD_SNAPSHOT: return "discard_snapshot"; - case Request::REKEY: return "rekey"; - case Request::EXTEND_VBD: return "extend_vbd"; - case Request::EXTEND_FT: return "extend_ft"; - case Request::RESUME_REKEYING: return "resume_rekeying"; - case Request::DEINITIALIZE: return "deinitialize"; - case Request::INITIALIZE: return "initialize"; - } - ASSERT_NEVER_REACHED; -} - - -void Request_pool_channel::_gen_sb_control_req(bool &progress, Superblock_control_request::Type type, - State complete_state, Virtual_block_address vba = 0) -{ - _state = REQ_GENERATED; - generate_req( - complete_state, progress, type, _req_ptr->_offset, _req_ptr->_tag, _req_ptr->_count, vba, _generated_req_success, - _request_finished, _sb_state, _req_ptr->_gen); -} - - -void Request_pool_channel::_access_vbas(bool &progress, Superblock_control_request::Type type) -{ - switch (_state) { - case REQ_SUBMITTED: - _gen_sb_control_req(progress, type, ACCESS_VBA_AT_SB_CTRL_SUCCEEDED, _req_ptr->_vba + _num_blks); - break; - case ACCESS_VBA_AT_SB_CTRL_SUCCEEDED: - if (++_num_blks < _req_ptr->_count) - _gen_sb_control_req(progress, type, ACCESS_VBA_AT_SB_CTRL_SUCCEEDED, _req_ptr->_vba + _num_blks); - else - _mark_req_successful(progress); - break; - default: break; - } -} - - -void Request_pool_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _chan_queue.dequeue(*this); - _req_ptr = nullptr; - progress = true; -} - - -void Request_pool_channel::_try_prepone_requests(bool &progress) -{ - enum { MAX_NUM_REQUESTS_PREPONED = 8 }; - bool requests_preponed { false }; - bool at_req_that_cannot_be_preponed { false }; - _num_requests_preponed = 0; - - while (_num_requests_preponed < MAX_NUM_REQUESTS_PREPONED && - !at_req_that_cannot_be_preponed && - !_chan_queue.is_tail(*this)) { - - switch (_chan_queue.next(*this)._req_ptr->_op) { - case Request::READ: - case Request::WRITE: - case Request::SYNC: - case Request::DISCARD_SNAPSHOT: - - _chan_queue.move_one_slot_towards_tail(*this); - _num_requests_preponed++; - requests_preponed = true; - progress = true; - break; - - default: - - at_req_that_cannot_be_preponed = true; - break; - } - } - if (!requests_preponed) { - _state = PREPONED_REQUESTS_COMPLETE; - progress = true; - } -} - - -void Request_pool_channel::_extend_tree(Superblock_control_request::Type type, bool &progress) -{ - switch (_state) { - case REQ_SUBMITTED: - - _gen_sb_control_req(progress, type, TREE_EXTENSION_STEP_SUCCEEDED); - break; - - case TREE_EXTENSION_STEP_SUCCEEDED: - - if (_request_finished) - _mark_req_successful(progress); - else - _try_prepone_requests(progress); - break; - - case PREPONED_REQUESTS_COMPLETE: - - _gen_sb_control_req(progress, type, TREE_EXTENSION_STEP_SUCCEEDED); - break; - - default: break; - } -} - - -void Request_pool_channel::_rekey(bool &progress) -{ - switch (_state) { - case REQ_SUBMITTED: - - _gen_sb_control_req(progress, Superblock_control_request::INITIALIZE_REKEYING, REKEY_INIT_SUCCEEDED); - break; - - case REQ_RESUMED: - case REKEY_INIT_SUCCEEDED: _try_prepone_requests(progress); break; - case REKEY_VBA_SUCCEEDED: - - if (_request_finished) - _mark_req_successful(progress); - else - _try_prepone_requests(progress); - break; - - case PREPONED_REQUESTS_COMPLETE: - - _gen_sb_control_req(progress, Superblock_control_request::REKEY_VBA, REKEY_VBA_SUCCEEDED); - break; - - default: break; - } -} - - -void Request_pool_channel::_resume_request(bool &progress, Request::Operation op) -{ - _state = REQ_RESUMED; - _req_ptr->_op = op; - progress = true; -} - - -void Request_pool_channel::_initialize(bool &progress) -{ - switch (_state) { - case REQ_SUBMITTED: - - _gen_sb_control_req(progress, Superblock_control_request::INITIALIZE, INITIALIZE_SB_CTRL_SUCCEEDED); - break; - - case INITIALIZE_SB_CTRL_SUCCEEDED: - - switch (_sb_state) { - case Superblock::INVALID: ASSERT_NEVER_REACHED; - case Superblock::NORMAL: - - _chan_queue.dequeue(*this); - _reset(); - progress = true; - break; - - case Superblock::REKEYING: _resume_request(progress, Request::REKEY); break; - case Superblock::EXTENDING_VBD: _resume_request(progress, Request::EXTEND_VBD); break; - case Superblock::EXTENDING_FT: _resume_request(progress, Request::EXTEND_FT); break; - } - break; - - default: break; - } -} - - -void Request_pool_channel::_forward_to_sb_ctrl(bool &progress, Superblock_control_request::Type type) -{ - switch (_state) { - case REQ_SUBMITTED: _gen_sb_control_req(progress, type, FORWARD_TO_SB_CTRL_SUCCEEDED); break; - case FORWARD_TO_SB_CTRL_SUCCEEDED: _mark_req_successful(progress); break; - default: break; - } -} - - -void Request_pool::execute(bool &progress) -{ - if (!_chan_queue.empty()) - _chan_queue.head().execute(progress); -} - - -void Request_pool_channel::execute(bool &progress) -{ - switch (_req_ptr->_op) { - case Request::READ: _access_vbas(progress, Superblock_control_request::READ_VBA); break; - case Request::WRITE: _access_vbas(progress, Superblock_control_request::WRITE_VBA); break; - case Request::SYNC: _forward_to_sb_ctrl(progress, Superblock_control_request::SYNC); break; - case Request::REKEY: _rekey(progress); break; - case Request::EXTEND_VBD: _extend_tree(Superblock_control_request::VBD_EXTENSION_STEP, progress); break; - case Request::EXTEND_FT: _extend_tree(Superblock_control_request::FT_EXTENSION_STEP, progress); break; - case Request::INITIALIZE: _initialize(progress); break; - case Request::DEINITIALIZE: _forward_to_sb_ctrl(progress, Superblock_control_request::DEINITIALIZE); break; - case Request::CREATE_SNAPSHOT: _forward_to_sb_ctrl(progress, Superblock_control_request::CREATE_SNAPSHOT); break; - case Request::DISCARD_SNAPSHOT: _forward_to_sb_ctrl(progress, Superblock_control_request::DISCARD_SNAPSHOT); break; - default: break; - } -} - - -Request_pool::Request_pool() -{ - for (Module_channel_id id { 0 }; id < NUM_CHANNELS; id++) { - _channels[id].construct(id, _chan_queue); - add_channel(*_channels[id]); - } - ASSERT(try_submit_request(_init_req)); -} - - -void Request_pool_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_generated_req_success) { - error("request_pool: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _chan_queue.dequeue(*this); - _req_ptr = nullptr; - } else - _state = (State)state_uint; -} - - -void Request_pool_channel::_reset() -{ - _state = INVALID; - _sb_state = Superblock::INVALID; - _num_blks = _num_requests_preponed = 0; - _request_finished = false; -} - - -Request_pool_channel &Request_pool_channel_queue::head() const -{ - ASSERT(!empty()); - return *_slots[_head]; -} - - -void Request_pool_channel_queue::enqueue(Channel &chan) -{ - ASSERT(!full()); - _slots[_tail] = &chan; - _tail = (_tail + 1) % NUM_SLOTS; - _num_used_slots++; -} - - -void Request_pool_channel_queue::move_one_slot_towards_tail(Channel const &chan) -{ - Slot_index slot_idx { _head }; - Slot_index next_slot_idx; - ASSERT(!empty()); - while (1) { - if (slot_idx < NUM_SLOTS - 1) - next_slot_idx = slot_idx + 1; - else - next_slot_idx = 0; - - ASSERT(next_slot_idx != _tail); - if (_slots[slot_idx] == &chan) { - Channel *chan_ptr = _slots[next_slot_idx]; - _slots[next_slot_idx] = _slots[slot_idx]; - _slots[slot_idx] = chan_ptr; - return; - } - slot_idx = next_slot_idx; - } -} - - -bool Request_pool_channel_queue::is_tail(Channel const &chan) const -{ - Slot_index slot_idx; - ASSERT(!empty()); - if (_tail) - slot_idx = _tail - 1; - else - slot_idx = NUM_SLOTS - 1; - - return _slots[slot_idx] == &chan; -} - - -Request_pool_channel &Request_pool_channel_queue::next(Channel const &chan) const -{ - Slot_index slot_idx { _head }; - Slot_index next_slot_idx; - ASSERT(!empty()); - while (1) { - if (slot_idx < NUM_SLOTS - 1) - next_slot_idx = slot_idx + 1; - else - next_slot_idx = 0; - - ASSERT(next_slot_idx != _tail); - if (_slots[slot_idx] == &chan) - return *_slots[next_slot_idx]; - else - slot_idx = next_slot_idx; - } -} - - -void Request_pool_channel_queue::dequeue(Channel const &chan) -{ - ASSERT(!empty() && &head() == &chan); - _head = (_head + 1) % NUM_SLOTS; - _num_used_slots--; -} - - -void Request_pool_channel::_request_submitted(Module_request &req) -{ - _reset(); - _req_ptr = static_cast(&req); - _state = REQ_SUBMITTED; - _chan_queue.enqueue(*this); -} diff --git a/repos/gems/src/lib/tresor/sb_check.cc b/repos/gems/src/lib/tresor/sb_check.cc index 74a4d09725..310d9e3fbc 100644 --- a/repos/gems/src/lib/tresor/sb_check.cc +++ b/repos/gems/src/lib/tresor/sb_check.cc @@ -13,64 +13,41 @@ /* tresor includes */ #include -#include -#include -#include using namespace Tresor; -Sb_check_request::Sb_check_request(Module_id src_mod, Module_channel_id src_chan, bool &success) -: - Module_request { src_mod, src_chan, SB_CHECK }, _success { success } -{ } - - -void Sb_check_channel::_generated_req_completed(State_uint state_uint) +bool Sb_check::Check::execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io) { - if (!_generated_req_success) { - error("sb check: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -void Sb_check_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - switch (_state) { - case REQ_SUBMITTED: + 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; - _generate_req(READ_BLK_SUCCESSFUL, progress, _sb_idx, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _sb_idx, _blk); break; - case READ_BLK_SUCCESSFUL: + 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 (!_sb.valid()) { - _mark_req_failed(progress, "no valid superblock");; + _helper.mark_failed(progress, "no valid superblock");; 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); - _generate_req(CHECK_VBD_SUCCESSFUL, progress, *_tree_root); + _check_vbd.generate(_helper, CHECK_VBD, CHECK_VBD_SUCCEEDED, progress, *_tree_root); if (VERBOSE_CHECK) log(" check snap ", _snap_idx, " (", snap, ")"); } else { - _state = CHECK_VBD_SUCCESSFUL; + _helper.state = CHECK_VBD_SUCCEEDED; progress = true; if (VERBOSE_CHECK) log(" skip snap ", _snap_idx, " as it is unused"); @@ -83,85 +60,45 @@ void Sb_check_channel::execute(bool &progress) } if (_sb_idx < MAX_SUPERBLOCK_INDEX) { _sb_idx++; - _generate_req(READ_BLK_SUCCESSFUL, progress, _sb_idx, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _sb_idx, _blk); progress = true; } else { _scan_for_highest_gen_sb_done = true; - _generate_req(READ_BLK_SUCCESSFUL, progress, _highest_gen_sb_idx, _blk); + _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"); } } break; - case CHECK_VBD_SUCCESSFUL: + case CHECK_VBD: progress |= _check_vbd.execute(vbd_check, block_io); break; + case CHECK_VBD_SUCCEEDED: if (_snap_idx < MAX_SNAP_IDX) { _snap_idx++; - _state = READ_BLK_SUCCESSFUL; + _helper.state = READ_BLK_SUCCEEDED; progress = true; } 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); - _generate_req(CHECK_FT_SUCCESSFUL, progress, *_tree_root); + _check_ft.generate(_helper, CHECK_FT, CHECK_FT_SUCCEEDED, progress, *_tree_root); if (VERBOSE_CHECK) log(" check free tree"); } break; - case CHECK_FT_SUCCESSFUL: + case CHECK_FT: progress |= _check_ft.execute(ft_check, block_io); break; + case CHECK_FT_SUCCEEDED: _tree_root.construct(_sb.meta_number, _sb.meta_gen, _sb.meta_hash, _sb.meta_max_level, _sb.meta_degree, _sb.meta_leaves); - _generate_req(CHECK_MT_SUCCESSFUL, progress, *_tree_root); + _check_ft.generate(_helper, CHECK_MT, CHECK_MT_SUCCEEDED, progress, *_tree_root); if (VERBOSE_CHECK) log(" check meta tree"); break; - case CHECK_MT_SUCCESSFUL: _mark_req_successful(progress); break; + case CHECK_MT: progress |= _check_ft.execute(ft_check, block_io); break; + case CHECK_MT_SUCCEEDED: _helper.mark_succeeded(progress); break; default: break; } -} - - -void Sb_check_channel::_mark_req_failed(bool &progress, char const *str) -{ - error("sb check: request (", *_req_ptr, ") failed at step \"", str, "\""); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Sb_check_channel::_mark_req_successful(bool &progress) -{ - Request &req { *_req_ptr }; - req._success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Sb_check_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Sb_check::Sb_check() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Sb_check::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + return progress; } diff --git a/repos/gems/src/lib/tresor/sb_initializer.cc b/repos/gems/src/lib/tresor/sb_initializer.cc index 5c7cfe1324..ada8d7410f 100644 --- a/repos/gems/src/lib/tresor/sb_initializer.cc +++ b/repos/gems/src/lib/tresor/sb_initializer.cc @@ -14,158 +14,100 @@ /* tresor includes */ #include -#include -#include -#include -#include #include using namespace Tresor; -Sb_initializer_request:: -Sb_initializer_request(Module_id src_mod, Module_channel_id src_chan, Tree_level_index vbd_max_lvl, - Tree_degree vbd_degree, Number_of_leaves vbd_num_leaves, Tree_level_index ft_max_lvl, - Tree_degree ft_degree, Number_of_leaves ft_num_leaves, Tree_level_index mt_max_lvl, - Tree_degree mt_degree, Number_of_leaves mt_num_leaves, Pba_allocator &pba_alloc, bool &success) -: - Module_request { src_mod, src_chan, SB_INITIALIZER }, _vbd_max_lvl { vbd_max_lvl }, - _vbd_degree { vbd_degree }, _vbd_num_leaves { vbd_num_leaves }, _ft_max_lvl { ft_max_lvl }, - _ft_degree { ft_degree }, _ft_num_leaves { ft_num_leaves }, _mt_max_lvl { mt_max_lvl }, - _mt_degree { mt_degree }, _mt_num_leaves { mt_num_leaves }, _pba_alloc { pba_alloc }, _success { success } -{ } - - -void Sb_initializer_channel::_generated_req_completed(State_uint state_uint) +bool Sb_initializer::Initialize::execute(Block_io &block_io, Trust_anchor &trust_anchor, Vbd_initializer &vbd_initializer, Ft_initializer &ft_initializer) { - if (!_generated_req_success) { - error("sb initializer: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -void Sb_initializer_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -void Sb_initializer_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Sb_initializer_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: { - _sb_idx = 0; - _sb = { }; - Snapshot &snap = _sb.snapshots.items[0]; - _vbd.construct(snap.pba, snap.gen, snap.hash, req._vbd_max_lvl, req._vbd_degree, req._vbd_num_leaves); - _generate_req(INIT_VBD_SUCCEEDED, progress, *_vbd, req._pba_alloc); - progress = true; + _init_vbd.generate(_helper, INIT_VBD, INIT_VBD_SUCCEEDED, progress, _attr.in_vbd_cfg, _vbd_root, _attr.in_out_pba_alloc); break; } + case INIT_VBD: progress |= _init_vbd.execute(vbd_initializer, block_io); break; case INIT_VBD_SUCCEEDED: - _ft.construct(_sb.free_number, _sb.free_gen, _sb.free_hash, req._ft_max_lvl, req._ft_degree, req._ft_num_leaves); - _generate_req(INIT_FT_SUCCEEDED, progress, *_ft, req._pba_alloc); + _init_ft.generate(_helper, INIT_FT, INIT_FT_SUCCEEDED, progress, _attr.in_ft_cfg, _ft_root, _attr.in_out_pba_alloc); break; + case INIT_FT: progress |= _init_ft.execute(ft_initializer, block_io); break; case INIT_FT_SUCCEEDED: - _mt.construct(_sb.meta_number, _sb.meta_gen, _sb.meta_hash, req._ft_max_lvl, req._ft_degree, req._ft_num_leaves); - _generate_req(INIT_MT_SUCCEEDED, progress, *_mt, req._pba_alloc); + _init_ft.generate(_helper, INIT_FT, INIT_MT_SUCCEEDED, progress, _attr.in_mt_cfg, _mt_root, _attr.in_out_pba_alloc); break; case INIT_MT_SUCCEEDED: - _generate_req(CREATE_KEY_SUCCEEDED, progress, _sb.current_key.value); + _generate_key.generate(_helper, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, progress, _sb.current_key.value); break; - case CREATE_KEY_SUCCEEDED: + case GENERATE_KEY: progress |= _generate_key.execute(trust_anchor); break; + case GENERATE_KEY_SUCCEEDED: - _generate_req(ENCRYPT_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb.current_key.value); + _encrypt_key.generate(_helper, ENCRYPT_KEY, ENCRYPT_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb.current_key.value); break; + case ENCRYPT_KEY: progress |= _encrypt_key.execute(trust_anchor); break; case ENCRYPT_KEY_SUCCEEDED: { Snapshot &snap = _sb.snapshots.items[0]; - snap.gen = 0; - snap.nr_of_leaves = req._vbd_num_leaves; - snap.max_level = req._vbd_max_lvl; + snap.pba = _vbd_root.pba; + snap.gen = _vbd_root.gen; + snap.hash = _vbd_root.hash; + snap.nr_of_leaves = _attr.in_vbd_cfg.num_leaves; + snap.max_level = _attr.in_vbd_cfg.max_lvl; snap.valid = true; snap.id = 0; _sb.current_key.id = 1; _sb.state = Superblock::NORMAL; - _sb.degree = req._vbd_degree; - _sb.first_pba = req._pba_alloc.first_pba() - NR_OF_SUPERBLOCK_SLOTS; - _sb.nr_of_pbas = req._pba_alloc.num_used_pbas() + NR_OF_SUPERBLOCK_SLOTS; - _sb.free_max_level = _ft->max_lvl; - _sb.free_degree = _ft->degree; - _sb.free_leaves = _ft->num_leaves; - _sb.meta_max_level = _mt->max_lvl; - _sb.meta_degree = _mt->degree; - _sb.meta_leaves = _mt->num_leaves; + _sb.degree = _attr.in_vbd_cfg.degree; + _sb.first_pba = _attr.in_out_pba_alloc.first_pba() - NR_OF_SUPERBLOCK_SLOTS; + _sb.nr_of_pbas = _attr.in_out_pba_alloc.num_used_pbas() + NR_OF_SUPERBLOCK_SLOTS; + _sb.free_number = _ft_root.pba; + _sb.free_gen = _ft_root.gen; + _sb.free_hash = _ft_root.hash; + _sb.free_max_level = _attr.in_ft_cfg.max_lvl; + _sb.free_degree = _attr.in_ft_cfg.degree; + _sb.free_leaves = _attr.in_ft_cfg.num_leaves; + _sb.meta_number = _mt_root.pba; + _sb.meta_gen = _mt_root.gen; + _sb.meta_hash = _mt_root.hash; + _sb.meta_max_level = _attr.in_mt_cfg.max_lvl; + _sb.meta_degree = _attr.in_mt_cfg.degree; + _sb.meta_leaves = _attr.in_mt_cfg.num_leaves; _sb.encode_to_blk(_blk); - _generate_req(WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk); break; } + case WRITE_BLK: progress |= _write_block.execute(block_io); break; case WRITE_BLK_SUCCEEDED: - _generate_req(_sb_idx ? SB_COMPLETE : WRITE_HASH_TO_TA, progress); - progress = true; + _sync_block_io.generate(_helper, SYNC_BLOCK_IO, _sb_idx ? SB_COMPLETE : WRITE_HASH_TO_TA, progress); break; + case SYNC_BLOCK_IO: progress |= _sync_block_io.execute(block_io); break; case WRITE_HASH_TO_TA: calc_hash(_blk, _hash); - _generate_req(SB_COMPLETE, progress, _hash); + _write_sb_hash.generate(_helper, WRITE_SB_HASH, SB_COMPLETE, progress, _hash); break; + case WRITE_SB_HASH: progress |= _write_sb_hash.execute(trust_anchor); break; case SB_COMPLETE: if (_sb_idx < NR_OF_SUPERBLOCK_SLOTS - 1) { _sb_idx++; _sb = { }; _sb.encode_to_blk(_blk); - _generate_req(WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk); } else - _mark_req_successful(progress); + _helper.mark_succeeded(progress); break; default: break; } -} - - -Sb_initializer::Sb_initializer() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Sb_initializer::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + return progress; } diff --git a/repos/gems/src/lib/tresor/superblock_control.cc b/repos/gems/src/lib/tresor/superblock_control.cc index c78c098103..1a5e673feb 100644 --- a/repos/gems/src/lib/tresor/superblock_control.cc +++ b/repos/gems/src/lib/tresor/superblock_control.cc @@ -19,585 +19,588 @@ using namespace Tresor; -Superblock_control_request:: -Superblock_control_request(Module_id src_module_id, Module_channel_id src_channel_id, - Type type, Request_offset client_req_offset, - Request_tag client_req_tag, Number_of_blocks nr_of_blks, - Virtual_block_address vba, bool &success, - bool &client_req_finished, Superblock::State &sb_state, - Generation &gen) -: - Module_request { src_module_id, src_channel_id, SUPERBLOCK_CONTROL }, _type { type }, - _client_req_offset { client_req_offset }, _client_req_tag { client_req_tag }, - _nr_of_blks { nr_of_blks }, _vba { vba }, _success { success }, - _client_req_finished { client_req_finished }, _sb_state { sb_state }, _gen { gen } -{ } - - -char const *Superblock_control_request::type_to_string(Type type) +void Superblock_control::Write_vbas::_start_write_vba(Execute_attr const &attr, bool &progress) { - switch (type) { - case READ_VBA: return "read_vba"; - case WRITE_VBA: return "write_vba"; - case SYNC: return "sync"; - case INITIALIZE: return "initialize"; - case DEINITIALIZE: return "deinitialize"; - case VBD_EXTENSION_STEP: return "vbd_ext_step"; - case FT_EXTENSION_STEP: return "ft_ext_step"; - case CREATE_SNAPSHOT: return "create_snap"; - case DISCARD_SNAPSHOT: return "discard_snap"; - case INITIALIZE_REKEYING: return "init_rekeying"; - case REKEY_VBA: return "rekey_vba"; + Virtual_block_address vba = _attr.in_first_vba + _num_written_vbas; + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + if (attr.sb.curr_snap().gen != attr.curr_gen) { + Snapshot &snap { attr.sb.curr_snap() }; + attr.sb.curr_snap_idx = attr.sb.snapshots.alloc_idx(attr.curr_gen, attr.sb.last_secured_generation); + attr.sb.curr_snap() = snap; + attr.sb.curr_snap().keep = false; } - ASSERT_NEVER_REACHED; + Key_id key_id { attr.sb.state == Superblock::REKEYING && vba >= attr.sb.rekeying_vba ? + attr.sb.previous_key.id : attr.sb.current_key.id }; + + _ft.construct(attr.sb.free_number, attr.sb.free_gen, attr.sb.free_hash, attr.sb.free_max_level, attr.sb.free_degree, attr.sb.free_leaves); + _mt.construct(attr.sb.meta_number, attr.sb.meta_gen, attr.sb.meta_hash, attr.sb.meta_max_level, attr.sb.meta_degree, attr.sb.meta_leaves); + _write_vba.generate( + _helper, WRITE_VBA, WRITE_VBA_SUCCEEDED, progress, attr.sb.snapshots.items[attr.sb.curr_snap_idx], attr.sb.snapshots, + *_ft, *_mt, vba, key_id, attr.sb.previous_key.id, attr.sb.degree, attr.sb.max_vba(), _attr.in_client_req_offset, + _attr.in_client_req_tag, attr.curr_gen, attr.sb.last_secured_generation, attr.sb.state == Superblock::REKEYING, + attr.sb.rekeying_vba); + + if (VERBOSE_WRITE_VBA) + log("write vba ", vba, ": snap ", attr.sb.curr_snap_idx, " key ", key_id, " gen ", attr.curr_gen); } -void Superblock_control_channel::_mark_req_failed(bool &progress, char const *str) +bool Superblock_control::Write_vbas::execute(Execute_attr const &attr) { - error("sb control: request (", *_req_ptr, ") failed at step \"", str, "\""); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} + bool progress = false; + switch (_helper.state) { + case INIT: - -void Superblock_control_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Superblock_control_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_gen_req_success) { - error("superblock control: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - if (_state == SECURE_SB) - _secure_sb_state = (Secure_sb_state)state_uint; - else - _state = (State)state_uint; -} - - -void Superblock_control_channel:: -_generate_vbd_req(Virtual_block_device_request::Type type, State_uint complete_state, bool - &progress, Key_id key_id, Virtual_block_address vba = INVALID_VBA) -{ - if (_state == SECURE_SB) - _secure_sb_state = SECURE_SB_REQ_GENERATED; - else - _state = REQ_GENERATED; - - _state = REQ_GENERATED; - _pba = _sb.first_pba + _sb.nr_of_pbas; - _ft.construct(_sb.free_number, _sb.free_gen, _sb.free_hash, _sb.free_max_level, _sb.free_degree, _sb.free_leaves); - _mt.construct(_sb.meta_number, _sb.meta_gen, _sb.meta_hash, _sb.meta_max_level, _sb.meta_degree, _sb.meta_leaves); - generate_req( - complete_state, progress, type, _req_ptr->_client_req_offset, _req_ptr->_client_req_tag, - _sb.last_secured_generation, *_ft, *_mt, _sb.degree, _sb.max_vba(), _sb.state == Superblock::REKEYING, - vba, _sb.curr_snap_idx, _sb.snapshots, _sb.degree, _sb.previous_key.id, key_id, - _curr_gen, _pba, _gen_req_success, _nr_of_leaves, _req_ptr->_nr_of_blks, _sb.rekeying_vba); -} - - -void Superblock_control_channel::_access_vba(Virtual_block_device_request::Type type, bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - { - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - if (req._vba > _sb.max_vba()) { - _mark_req_failed(progress, "VBA greater than max VBA"); + if (_attr.in_first_vba + _attr.in_num_vbas - 1 > attr.sb.max_vba()) { + _helper.mark_failed(progress, "invalid VBA range"); break; } - if (type == Virtual_block_device_request::WRITE_VBA && _sb.curr_snap().gen != _curr_gen) { - Snapshot &snap { _sb.curr_snap() }; - _sb.curr_snap_idx = _sb.snapshots.alloc_idx(_curr_gen, _sb.last_secured_generation); - _sb.curr_snap() = snap; - _sb.curr_snap().keep = false; - } - Key_id key_id { _sb.state == Superblock::REKEYING && req._vba >= _sb.rekeying_vba ? - _sb.previous_key.id : _sb.current_key.id }; - - _generate_vbd_req(type, ACCESS_VBA_AT_VBD_SUCCEEDED, progress, key_id, req._vba); - if (VERBOSE_READ_VBA) - log("read vba ", req._vba, ": snap ", _sb.curr_snap_idx, " key ", key_id, " gen ", _curr_gen); - + _start_write_vba(attr, progress); break; - } - case ACCESS_VBA_AT_VBD_SUCCEEDED: _mark_req_successful(progress); break; - default: break; - } -} + case WRITE_VBA: progress |= _write_vba.execute(attr.vbd, attr.client_data, attr.block_io, attr.free_tree, attr.meta_tree, attr.crypto); break; + case WRITE_VBA_SUCCEEDED: -void Superblock_control_channel::_tree_ext_step(Superblock::State sb_state, bool verbose, String<4> tree_name, bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - { - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - Physical_block_address const last_used_pba { _sb.first_pba + (_sb.nr_of_pbas - 1) }; - Number_of_blocks const nr_of_unused_pbas { MAX_PBA - last_used_pba }; - - if (req._nr_of_blks > nr_of_unused_pbas) { - _mark_req_failed(progress, "check number of unused blocks"); - break; - } - if (_sb.state == Superblock::NORMAL) { - - req._client_req_finished = false; - _sb.state = sb_state; - _sb.resizing_nr_of_pbas = req._nr_of_blks; - _sb.resizing_nr_of_leaves = 0; - _pba = last_used_pba + 1; - if (verbose) - log(tree_name, " ext init: pbas ", _pba, "..", - _pba + (Number_of_blocks)_sb.resizing_nr_of_pbas - 1, - " leaves ", (Number_of_blocks)_sb.resizing_nr_of_leaves); - - _start_secure_sb(progress); - break; - - } else if (_sb.state == sb_state) { - - _pba = last_used_pba + 1; - req._nr_of_blks = _sb.resizing_nr_of_pbas; - - if (verbose) - log(tree_name, " ext step: pbas ", _pba, "..", - _pba + (Number_of_blocks)_sb.resizing_nr_of_pbas - 1, - " leaves ", (Number_of_blocks)_sb.resizing_nr_of_leaves); - - req._nr_of_blks = _sb.resizing_nr_of_pbas; - _pba = _sb.first_pba + _sb.nr_of_pbas; - if (tree_name == "vbd") { - - _generate_vbd_req( - Virtual_block_device_request::EXTENSION_STEP, - TREE_EXT_STEP_IN_TREE_SUCCEEDED, progress, _sb.current_key.id); - - } else if (tree_name == "ft") { - - _mt.construct( - _sb.free_number, _sb.free_gen, _sb.free_hash, _sb.free_max_level, _sb.free_degree, - _sb.free_leaves); - - _mt.construct( - _sb.meta_number, _sb.meta_gen, _sb.meta_hash, _sb.meta_max_level, _sb.meta_degree, - _sb.meta_leaves); - - _generate_req( - TREE_EXT_STEP_IN_TREE_SUCCEEDED, progress, _curr_gen, *_ft, *_mt, _pba, req._nr_of_blks); - } + if (++_num_written_vbas < _attr.in_num_vbas) { + _start_write_vba(attr, progress); } else - _mark_req_failed(progress, "check superblock state"); - + _helper.mark_succeeded(progress); break; - } - case TREE_EXT_STEP_IN_TREE_SUCCEEDED: - { - if (req._nr_of_blks >= _sb.resizing_nr_of_pbas) { - _mark_req_failed(progress, "check number of pbas"); - break; - } - Number_of_blocks const nr_of_added_pbas { _sb.resizing_nr_of_pbas - req._nr_of_blks }; - Physical_block_address const new_first_unused_pba { _sb.first_pba + (_sb.nr_of_pbas + nr_of_added_pbas) }; - if (_pba != new_first_unused_pba) { - _mark_req_failed(progress, "check new first unused pba"); - break; - } - _sb.nr_of_pbas = _sb.nr_of_pbas + nr_of_added_pbas; - _sb.resizing_nr_of_pbas = req._nr_of_blks; - _sb.resizing_nr_of_leaves += _nr_of_leaves; - if (tree_name == "vbd") - _sb.curr_snap_idx = _sb.snapshots.newest_snap_idx(); - - if (!req._nr_of_blks) { - _sb.state = Superblock::NORMAL; - req._client_req_finished = true; - } - _start_secure_sb(progress); - break; - } - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_rekey_vba(bool &progress) +void Superblock_control::Read_vbas::_start_read_vba(Execute_attr const &attr, bool &progress) { - switch (_state) { - case REQ_SUBMITTED: + Virtual_block_address vba = _attr.in_first_vba + _num_read_vbas; + Key_id key_id { attr.sb.state == Superblock::REKEYING && vba >= attr.sb.rekeying_vba ? + attr.sb.previous_key.id : attr.sb.current_key.id }; - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - if (_sb.state != Superblock::REKEYING) { - _mark_req_failed(progress, "check superblock state"); + _read_vba.generate( + _helper, READ_VBA, READ_VBA_SUCCEEDED, progress, attr.sb.snapshots.items[attr.sb.curr_snap_idx], vba, key_id, + attr.sb.degree, _attr.in_client_req_offset, _attr.in_client_req_tag); + + if (VERBOSE_READ_VBA) + log("read vba ", vba, ": snap ", attr.sb.curr_snap_idx, " key ", key_id, " gen ", attr.curr_gen); +} + + +bool Superblock_control::Read_vbas::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + if (_attr.in_first_vba + _attr.in_num_vbas - 1 > attr.sb.max_vba()) { + _helper.mark_failed(progress, "invalid VBA range"); break; } - _generate_vbd_req( - Virtual_block_device_request::REKEY_VBA, REKEY_VBA_AT_VBD_SUCCEEDED, - progress, _sb.current_key.id, _sb.rekeying_vba); + _start_read_vba(attr, progress); + break; - _state = REQ_GENERATED; - if (VERBOSE_REKEYING) { - log("rekey vba ", _sb.rekeying_vba, ":"); - log(" update vbd: keys ", _sb.previous_key.id, ",", _sb.current_key.id, " generations ", _sb.last_secured_generation, ",", _curr_gen); + case READ_VBA: progress |= _read_vba.execute(attr.vbd, attr.client_data, attr.block_io, attr.crypto); break; + case READ_VBA_SUCCEEDED: + + if (++_num_read_vbas < _attr.in_num_vbas) { + _start_read_vba(attr, progress); + } else + _helper.mark_succeeded(progress); + break; + + default: break; + } + return progress; +} + + +bool Superblock_control::Extend_free_tree::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + { + _num_pbas = _attr.in_num_pbas; + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + Physical_block_address last_used_pba { attr.sb.first_pba + (attr.sb.nr_of_pbas - 1) }; + Number_of_blocks nr_of_unused_pbas { MAX_PBA - last_used_pba }; + + if (_num_pbas > nr_of_unused_pbas) { + _helper.mark_failed(progress, "check number of unused blocks"); + break; + } + if (attr.sb.state == Superblock::NORMAL) { + + _attr.out_extension_finished = false; + attr.sb.state = Superblock::EXTENDING_FT; + attr.sb.resizing_nr_of_pbas = _num_pbas; + attr.sb.resizing_nr_of_leaves = 0; + _pba = last_used_pba + 1; + if (VERBOSE_FT_EXTENSION) + log("free_tree ext init: pbas ", _pba, "..", + _pba + (Number_of_blocks)attr.sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)attr.sb.resizing_nr_of_leaves); + + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + + } else if (attr.sb.state == Superblock::EXTENDING_FT) { + + _pba = last_used_pba + 1; + _num_pbas = attr.sb.resizing_nr_of_pbas; + + if (VERBOSE_FT_EXTENSION) + log("free_tree ext step: pbas ", _pba, "..", + _pba + (Number_of_blocks)attr.sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)attr.sb.resizing_nr_of_leaves); + + _num_pbas = attr.sb.resizing_nr_of_pbas; + _pba = attr.sb.first_pba + attr.sb.nr_of_pbas; + + _ft.construct(attr.sb.free_number, attr.sb.free_gen, attr.sb.free_hash, attr.sb.free_max_level, attr.sb.free_degree, attr.sb.free_leaves); + _mt.construct(attr.sb.meta_number, attr.sb.meta_gen, attr.sb.meta_hash, attr.sb.meta_max_level, attr.sb.meta_degree, attr.sb.meta_leaves); + _extend_free_tree.generate(_helper, EXTEND_FREE_TREE, EXTEND_FREE_TREE_SUCCEEDED, progress, attr.curr_gen, *_ft, *_mt, _pba, _num_pbas); + + } else + _helper.mark_failed(progress, "check superblock state"); + + break; + } + case EXTEND_FREE_TREE: progress |= _extend_free_tree.execute(attr.free_tree, attr.block_io, attr.meta_tree); break; + case EXTEND_FREE_TREE_SUCCEEDED: + { + if (_num_pbas >= attr.sb.resizing_nr_of_pbas) { + _helper.mark_failed(progress, "check number of pbas"); + break; + } + Number_of_blocks const nr_of_added_pbas { attr.sb.resizing_nr_of_pbas - _num_pbas }; + Physical_block_address const new_first_unused_pba { attr.sb.first_pba + (attr.sb.nr_of_pbas + nr_of_added_pbas) }; + if (_pba != new_first_unused_pba) { + _helper.mark_failed(progress, "check new first unused pba"); + break; + } + attr.sb.nr_of_pbas = attr.sb.nr_of_pbas + nr_of_added_pbas; + attr.sb.resizing_nr_of_pbas = _num_pbas; + attr.sb.resizing_nr_of_leaves += _nr_of_leaves; + attr.sb.curr_snap_idx = attr.sb.snapshots.newest_snap_idx(); + + if (!_num_pbas) { + attr.sb.state = Superblock::NORMAL; + _attr.out_extension_finished = true; + } + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + } + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; + default: break; + } + return progress; +} + + +bool Superblock_control::Extend_vbd::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + { + _num_pbas = _attr.in_num_pbas; + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + Physical_block_address last_used_pba { attr.sb.first_pba + (attr.sb.nr_of_pbas - 1) }; + Number_of_blocks nr_of_unused_pbas { MAX_PBA - last_used_pba }; + + if (_num_pbas > nr_of_unused_pbas) { + _helper.mark_failed(progress, "check number of unused blocks"); + break; + } + if (attr.sb.state == Superblock::NORMAL) { + + _attr.out_extension_finished = false; + attr.sb.state = Superblock::EXTENDING_VBD; + attr.sb.resizing_nr_of_pbas = _num_pbas; + attr.sb.resizing_nr_of_leaves = 0; + _pba = last_used_pba + 1; + if (VERBOSE_VBD_EXTENSION) + log("vbd ext init: pbas ", _pba, "..", + _pba + (Number_of_blocks)attr.sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)attr.sb.resizing_nr_of_leaves); + + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + + } else if (attr.sb.state == Superblock::EXTENDING_VBD) { + + _pba = last_used_pba + 1; + _num_pbas = attr.sb.resizing_nr_of_pbas; + + if (VERBOSE_VBD_EXTENSION) + log("vbd ext step: pbas ", _pba, "..", + _pba + (Number_of_blocks)attr.sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)attr.sb.resizing_nr_of_leaves); + + _num_pbas = attr.sb.resizing_nr_of_pbas; + _pba = attr.sb.first_pba + attr.sb.nr_of_pbas; + + _ft.construct(attr.sb.free_number, attr.sb.free_gen, attr.sb.free_hash, attr.sb.free_max_level, attr.sb.free_degree, attr.sb.free_leaves); + _mt.construct(attr.sb.meta_number, attr.sb.meta_gen, attr.sb.meta_hash, attr.sb.meta_max_level, attr.sb.meta_degree, attr.sb.meta_leaves); + _extend_vbd.generate( + _helper, EXTEND_VBD, EXTEND_VBD_SUCCEEDED, progress, _nr_of_leaves, attr.sb.snapshots, + attr.sb.degree, attr.curr_gen, attr.sb.last_secured_generation, _pba, _num_pbas, *_ft, + *_mt, attr.sb.degree, attr.sb.max_vba(), attr.sb.previous_key.id, attr.sb.current_key.id, + attr.sb.state == Superblock::REKEYING, attr.sb.rekeying_vba); + + } else + _helper.mark_failed(progress, "check superblock state"); + + break; + } + case EXTEND_VBD: progress |= _extend_vbd.execute(attr.vbd, attr.block_io, attr.free_tree, attr.meta_tree); break; + case EXTEND_VBD_SUCCEEDED: + { + if (_num_pbas >= attr.sb.resizing_nr_of_pbas) { + _helper.mark_failed(progress, "check number of pbas"); + break; + } + Number_of_blocks const nr_of_added_pbas { attr.sb.resizing_nr_of_pbas - _num_pbas }; + Physical_block_address const new_first_unused_pba { attr.sb.first_pba + (attr.sb.nr_of_pbas + nr_of_added_pbas) }; + if (_pba != new_first_unused_pba) { + _helper.mark_failed(progress, "check new first unused pba"); + break; + } + attr.sb.nr_of_pbas = attr.sb.nr_of_pbas + nr_of_added_pbas; + attr.sb.resizing_nr_of_pbas = _num_pbas; + attr.sb.resizing_nr_of_leaves += _nr_of_leaves; + attr.sb.curr_snap_idx = attr.sb.snapshots.newest_snap_idx(); + + if (!_num_pbas) { + attr.sb.state = Superblock::NORMAL; + _attr.out_extension_finished = true; + } + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + } + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; + default: break; + } + return progress; +} + + +bool Superblock_control::Rekey::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + _attr.out_rekeying_finished = false; + switch (attr.sb.state) { + case Superblock::NORMAL: + + attr.sb.state = Superblock::REKEYING; + attr.sb.rekeying_vba = 0; + attr.sb.previous_key = attr.sb.current_key; + attr.sb.current_key.id++; + _generate_key.generate(_helper, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, progress, attr.sb.current_key.value); + break; + + case Superblock::REKEYING: + + _ft.construct(attr.sb.free_number, attr.sb.free_gen, attr.sb.free_hash, attr.sb.free_max_level, attr.sb.free_degree, attr.sb.free_leaves); + _mt.construct(attr.sb.meta_number, attr.sb.meta_gen, attr.sb.meta_hash, attr.sb.meta_max_level, attr.sb.meta_degree, attr.sb.meta_leaves); + _rekey_vba.generate( + _helper, REKEY_VBA, REKEY_VBA_SUCCEEDED, progress, attr.sb.snapshots, *_ft, *_mt, attr.sb.rekeying_vba, + attr.curr_gen, attr.sb.last_secured_generation, attr.sb.current_key.id, attr.sb.previous_key.id, attr.sb.degree, attr.sb.max_vba()); + + if (VERBOSE_REKEYING) + log("rekey vba ", attr.sb.rekeying_vba, ":\n update vbd: keys ", attr.sb.previous_key.id, ",", attr.sb.current_key.id, + " generations ", attr.sb.last_secured_generation, ",", attr.curr_gen); + break; + + default: + + _helper.mark_failed(progress, "bad superblock state"); + break; } break; - case REKEY_VBA_AT_VBD_SUCCEEDED: + case GENERATE_KEY: progress |= _generate_key.execute(attr.trust_anchor); break; + case GENERATE_KEY_SUCCEEDED: + + _add_key.generate(_helper, ADD_KEY, ADD_KEY_SUCCEEDED, progress, attr.sb.current_key); + if (VERBOSE_REKEYING) + log("start rekeying:\n update sb: keys ", attr.sb.previous_key.id, ",", attr.sb.current_key.id); + break; + + case ADD_KEY: progress |= _add_key.execute(attr.crypto); break; + case ADD_KEY_SUCCEEDED: + + if (VERBOSE_REKEYING) + log(" secure sb: gen ", attr.curr_gen); + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); + break; + + case REKEY_VBA: progress |= _rekey_vba.execute(attr.vbd, attr.block_io, attr.crypto, attr.free_tree, attr.meta_tree); break; + case REKEY_VBA_SUCCEEDED: { Number_of_leaves max_nr_of_leaves { 0 }; - for (Snapshot const &snap : _sb.snapshots.items) { + for (Snapshot const &snap : attr.sb.snapshots.items) { if (snap.valid && max_nr_of_leaves < snap.nr_of_leaves) max_nr_of_leaves = snap.nr_of_leaves; } - if (_sb.rekeying_vba < max_nr_of_leaves - 1) { - _sb.rekeying_vba++; - _req_ptr->_client_req_finished = false; - _start_secure_sb(progress); + if (attr.sb.rekeying_vba < max_nr_of_leaves - 1) { + attr.sb.rekeying_vba++; + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); if (VERBOSE_REKEYING) - log(" secure sb: gen ", _curr_gen); + log(" secure sb: gen ", attr.curr_gen); } else { - _generate_req(REMOVE_PREV_KEY_SUCCEEDED, progress, _sb.previous_key.id); + _remove_key.generate(_helper, REMOVE_KEY, REMOVE_KEY_SUCCEEDED, progress, attr.sb.previous_key.id); if (VERBOSE_REKEYING) - log(" remove key ", _sb.previous_key.id); + log(" remove key ", attr.sb.previous_key.id); } break; } - case REMOVE_PREV_KEY_SUCCEEDED: + case REMOVE_KEY: progress |= _remove_key.execute(attr.crypto); break; + case REMOVE_KEY_SUCCEEDED: - _sb.previous_key = { }; - _sb.state = Superblock::NORMAL; - _req_ptr->_client_req_finished = true; - _start_secure_sb(progress); + attr.sb.previous_key = { }; + attr.sb.state = Superblock::NORMAL; + _attr.out_rekeying_finished = true; + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); if (VERBOSE_REKEYING) - log(" secure sb: gen ", _curr_gen); + log(" secure sb: gen ", attr.curr_gen); break; - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_start_secure_sb(bool &progress) +bool Superblock_control::Secure_superblock::execute(Execute_attr const &attr) { - _state = SECURE_SB; - _secure_sb_state = STARTED; - progress = true; -} + bool progress = false; + switch (_helper.state) { + case INIT: - -void Superblock_control_channel::_secure_sb(bool &progress) -{ - switch (_secure_sb_state) { - case STARTED: - - _sb.curr_snap().gen = _curr_gen; - _sb_ciphertext.copy_all_but_key_values_from(_sb); - _generate_req( - ENCRYPT_CURR_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb_ciphertext.current_key.value); + attr.sb.curr_snap().gen = attr.curr_gen; + _sb_ciphertext.copy_all_but_key_values_from(attr.sb); + _encrypt_key.generate( + _helper, ENCRYPT_KEY, ENCRYPT_CURR_KEY_SUCCEEDED, progress, _sb_ciphertext.current_key.value, attr.sb.current_key.value); break; + case ENCRYPT_KEY: progress |= _encrypt_key.execute(attr.trust_anchor); break; case ENCRYPT_CURR_KEY_SUCCEEDED: - if (_sb.state == Superblock::REKEYING) - _generate_req( - ENCRYPT_PREV_KEY_SUCCEEDED, progress, _sb.previous_key.value, _sb_ciphertext.previous_key.value); - else - _generate_req(SYNC_CACHE_SUCCEEDED, progress); + if (attr.sb.state == Superblock::REKEYING) + _encrypt_key.generate( + _helper, ENCRYPT_KEY, ENCRYPT_PREV_KEY_SUCCEEDED, progress, attr.sb.previous_key.value, _sb_ciphertext.previous_key.value); + else { + _sb_ciphertext.encode_to_blk(_blk); + _write_block.generate(_helper, WRITE_BLOCK, WRITE_BLOCK_SUCCEEDED, progress, attr.sb_idx, _blk); + } break; - case ENCRYPT_PREV_KEY_SUCCEEDED: _generate_req(SYNC_CACHE_SUCCEEDED, progress); break; - case SYNC_CACHE_SUCCEEDED: + case ENCRYPT_PREV_KEY_SUCCEEDED: _sb_ciphertext.encode_to_blk(_blk); - _generate_req(WRITE_SB_SUCCEEDED, progress, _sb_idx, _blk); + _write_block.generate(_helper, WRITE_BLOCK, WRITE_BLOCK_SUCCEEDED, progress, attr.sb_idx, _blk); break; - case WRITE_SB_SUCCEEDED: _generate_req(SYNC_BLK_IO_SUCCEEDED, progress); break; - case SYNC_BLK_IO_SUCCEEDED: + case WRITE_BLOCK: progress |= _write_block.execute(attr.block_io); break; + case WRITE_BLOCK_SUCCEEDED: _sync_block_io.generate(_helper, SYNC_BLOCK_IO, SYNC_BLOCK_IO_SUCCEEDED, progress); break; + case SYNC_BLOCK_IO: progress |= _sync_block_io.execute(attr.block_io); break; + case SYNC_BLOCK_IO_SUCCEEDED: { _sb_ciphertext.encode_to_blk(_blk); calc_hash(_blk, _hash); - _generate_req(WRITE_SB_HASH_SUCCEEDED, progress, _hash); - if (_sb_idx < MAX_SUPERBLOCK_INDEX) - _sb_idx++; + _write_sb_hash.generate(_helper, WRITE_SB_HASH, WRITE_SB_HASH_SUCCEEDED, progress, _hash); + if (attr.sb_idx < MAX_SUPERBLOCK_INDEX) + attr.sb_idx++; else - _sb_idx = 0; + attr.sb_idx = 0; - _gen = _curr_gen; - _curr_gen++; + _gen = attr.curr_gen; + attr.curr_gen++; break; } + case WRITE_SB_HASH: progress |= _write_sb_hash.execute(attr.trust_anchor); break; case WRITE_SB_HASH_SUCCEEDED: - _sb.last_secured_generation = _gen; - _state = SECURE_SB_SUCCEEDED; + attr.sb.last_secured_generation = _gen; + _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_init_rekeying(bool &progress) +bool Superblock_control::Discard_snapshot::execute(Execute_attr const &attr) { - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - if (_sb.state != Superblock::NORMAL) { - _mark_req_failed(progress, "check superblock state"); - break; - } - _sb.state = Superblock::REKEYING; - _sb.rekeying_vba = 0; - _sb.previous_key = _sb.current_key; - _sb.current_key.id++; - _generate_req(CREATE_KEY_SUCCEEDED, progress, _sb.current_key.value); - break; - - case CREATE_KEY_SUCCEEDED: - - _generate_req(ADD_CURR_KEY_SUCCEEDED, progress, _sb.current_key); - if (VERBOSE_REKEYING) - log("start rekeying:\n update sb: keys ", _sb.previous_key.id, ",", _sb.current_key.id); - break; - - case ADD_CURR_KEY_SUCCEEDED: - - if (VERBOSE_REKEYING) - log(" secure sb: gen ", _curr_gen); - _start_secure_sb(progress); - break; - - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; - default: break; - } -} - - -void Superblock_control_channel::_discard_snap(bool &progress) -{ - switch (_state) { - case REQ_SUBMITTED: - - for (Snapshot &snap : _sb.snapshots.items) - if (snap.valid && snap.gen == _req_ptr->_gen && snap.keep) + for (Snapshot &snap : attr.sb.snapshots.items) + if (snap.valid && snap.gen == _attr.in_gen && snap.keep) snap.keep = false; - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _start_secure_sb(progress); - break; - - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: - - _req_ptr->_gen = _gen; - _mark_req_successful(progress); + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); break; + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_create_snap(bool &progress) +bool Superblock_control::Create_snapshot::execute(Execute_attr const &attr) { - switch (_state) { - case REQ_SUBMITTED: - - if (_sb.curr_snap().keep) { - _req_ptr->_gen = _sb.curr_snap().gen; - _mark_req_successful(progress); + bool progress = false; + switch (_helper.state) { + case INIT: + { + Snapshot &snap = attr.sb.curr_snap(); + if (snap.keep) { + _attr.out_gen = snap.gen; + _helper.mark_succeeded(progress); } else { - _sb.curr_snap().keep = true; - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _start_secure_sb(progress); + snap.keep = true; + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); } break; - - case SECURE_SB: _secure_sb(progress); break; + } + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; case SECURE_SB_SUCCEEDED: - _req_ptr->_gen = _gen; - _mark_req_successful(progress); + _attr.out_gen = attr.sb.curr_snap().gen; + _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_sync(bool &progress) +bool Superblock_control::Synchronize::execute(Execute_attr const &attr) { - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _sb.last_secured_generation = _curr_gen; - _start_secure_sb(progress); + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + attr.sb.last_secured_generation = attr.curr_gen; + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); break; - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: _mark_req_successful(progress); break; + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_request::print(Output &out) const +bool Superblock_control::Initialize::execute(Execute_attr const &attr) { - Genode::print(out, type_to_string(_type)); - switch (_type) { - case REKEY_VBA: - case READ_VBA: - case WRITE_VBA: Genode::print(out, " ", _vba); break; - default: break; - } -} - - -void Superblock_control_channel::_initialize(bool &progress) -{ - switch (_state) { - case REQ_SUBMITTED: - - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _generate_req(READ_SB_HASH_SUCCEEDED, progress, _hash); - break; - + bool progress = false; + switch (_helper.state) { + case INIT: _read_sb_hash.generate(_helper, READ_SB_HASH, READ_SB_HASH_SUCCEEDED, progress, _hash); break; + case READ_SB_HASH: progress |= _read_sb_hash.execute(attr.trust_anchor); break; case READ_SB_HASH_SUCCEEDED: - _sb_idx = 0; - _generate_req(READ_SB_SUCCEEDED, progress, _sb_idx, _blk); + attr.sb_idx = 0; + _read_block.generate(_helper, READ_BLOCK, READ_BLOCK_SUCCEEDED, progress, attr.sb_idx, _blk); break; - case READ_SB_SUCCEEDED: + case READ_BLOCK: progress |= _read_block.execute(attr.block_io); break; + case READ_BLOCK_SUCCEEDED: _sb_ciphertext.decode_from_blk(_blk); if (check_hash(_blk, _hash)) { _gen = _sb_ciphertext.snapshots.items[_sb_ciphertext.snapshots.newest_snap_idx()].gen; - _sb.copy_all_but_key_values_from(_sb_ciphertext); - _generate_req( - DECRYPT_CURR_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb_ciphertext.current_key.value); + attr.sb.copy_all_but_key_values_from(_sb_ciphertext); + _decrypt_key.generate(_helper, DECRYPT_KEY, DECRYPT_CURR_KEY_SUCCEEDED, progress, attr.sb.current_key.value, _sb_ciphertext.current_key.value); } else - if (_sb_idx < MAX_SUPERBLOCK_INDEX) { - _sb_idx++; - _generate_req(READ_SB_SUCCEEDED, progress, _sb_idx, _blk); + if (attr.sb_idx < MAX_SUPERBLOCK_INDEX) { + attr.sb_idx++; + _read_block.generate(_helper, READ_BLOCK, READ_BLOCK_SUCCEEDED, progress, attr.sb_idx, _blk); } else - _mark_req_failed(progress, "superblock not found"); - break; - - case DECRYPT_CURR_KEY_SUCCEEDED: - - _generate_req(ADD_CURR_KEY_SUCCEEDED, progress, _sb.current_key); + _helper.mark_failed(progress, "superblock not found"); break; + case DECRYPT_KEY: progress |= _decrypt_key.execute(attr.trust_anchor); break; + case DECRYPT_CURR_KEY_SUCCEEDED: _add_key.generate(_helper, ADD_KEY, ADD_CURR_KEY_SUCCEEDED, progress, attr.sb.current_key); break; + case ADD_KEY: progress |= _add_key.execute(attr.crypto); break; case ADD_CURR_KEY_SUCCEEDED: if (_sb_ciphertext.state == Superblock::REKEYING) - _generate_req( - DECRYPT_PREV_KEY_SUCCEEDED, progress, _sb.previous_key.value, _sb_ciphertext.previous_key.value); + _decrypt_key.generate(_helper, DECRYPT_KEY, DECRYPT_PREV_KEY_SUCCEEDED, progress, attr.sb.previous_key.value, _sb_ciphertext.previous_key.value); else { - _curr_gen = _gen + 1; - _req_ptr->_sb_state = _sb.state; - _mark_req_successful(progress); + attr.curr_gen = _gen + 1; + _attr.out_sb_state = attr.sb.state; + _helper.mark_succeeded(progress); } break; - case DECRYPT_PREV_KEY_SUCCEEDED: - - _generate_req(ADD_PREV_KEY_SUCCEEDED, progress, _sb.previous_key); - break; - + case DECRYPT_PREV_KEY_SUCCEEDED: _add_key.generate(_helper, ADD_KEY, ADD_PREV_KEY_SUCCEEDED, progress, attr.sb.previous_key); break; case ADD_PREV_KEY_SUCCEEDED: - _curr_gen = _gen + 1; - _req_ptr->_sb_state = _sb.state; - _mark_req_successful(progress); + attr.curr_gen = _gen + 1; + _attr.out_sb_state = attr.sb.state; + _helper.mark_succeeded(progress); break; default: break; } + return progress; } -void Superblock_control_channel::_deinitialize(bool &progress) +bool Superblock_control::Deinitialize::execute(Execute_attr const &attr) { - switch (_state) { - case REQ_SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: - _sb.snapshots.discard_disposable_snapshots(_sb.last_secured_generation, _curr_gen); - _sb.last_secured_generation = _curr_gen; - _start_secure_sb(progress); + attr.sb.snapshots.discard_disposable_snapshots(attr.sb.last_secured_generation, attr.curr_gen); + attr.sb.last_secured_generation = attr.curr_gen; + _secure_sb.generate(_helper, SECURE_SB, SECURE_SB_SUCCEEDED, progress); break; - case SECURE_SB: _secure_sb(progress); break; - case SECURE_SB_SUCCEEDED: _generate_req(REMOVE_CURR_KEY_SUCCEEDED, progress, _sb.current_key.id); break; + case SECURE_SB: progress |= _secure_sb.execute(attr.sb_control, attr.block_io, attr.trust_anchor); break; + case SECURE_SB_SUCCEEDED: _remove_key.generate(_helper, REMOVE_KEY, REMOVE_CURR_KEY_SUCCEEDED, progress, attr.sb.current_key.id); break; case REMOVE_CURR_KEY_SUCCEEDED: - if (_sb.state == Superblock::REKEYING) - _generate_req(REMOVE_CURR_KEY_SUCCEEDED, progress, _sb.previous_key.id); + if (attr.sb.state == Superblock::REKEYING) + _remove_key.generate(_helper, REMOVE_KEY, REMOVE_PREV_KEY_SUCCEEDED, progress, attr.sb.previous_key.id); else - _mark_req_successful(progress); + _helper.mark_succeeded(progress); break; + case REMOVE_KEY: progress |= _remove_key.execute(attr.crypto); break; case REMOVE_PREV_KEY_SUCCEEDED: - _sb.state = Superblock::INVALID; - _mark_req_successful(progress); + attr.sb.state = Superblock::INVALID; + _helper.mark_succeeded(progress); break; default: break; } -} - - -void Superblock_control_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - switch (_req_ptr->_type) { - case Request::READ_VBA: _access_vba(Virtual_block_device_request::READ_VBA, progress); break; - case Request::WRITE_VBA: _access_vba(Virtual_block_device_request::WRITE_VBA, progress); break; - case Request::SYNC: _sync(progress); break; - case Request::INITIALIZE_REKEYING: _init_rekeying(progress); break; - case Request::REKEY_VBA: _rekey_vba(progress); break; - case Request::VBD_EXTENSION_STEP: _tree_ext_step(Superblock::EXTENDING_VBD, VERBOSE_VBD_EXTENSION, "vbd", progress); break; - case Request::FT_EXTENSION_STEP: _tree_ext_step(Superblock::EXTENDING_FT, VERBOSE_FT_EXTENSION, "ft", progress); break; - case Request::CREATE_SNAPSHOT: _create_snap(progress); break; - case Request::DISCARD_SNAPSHOT: _discard_snap(progress); break; - case Request::INITIALIZE: _initialize(progress); break; - case Request::DEINITIALIZE: _deinitialize (progress); break; - } -} - - -void Superblock_control::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + return progress; } @@ -624,26 +627,3 @@ Superblock_info Superblock_control::sb_info() const true, _sb.state == Superblock::REKEYING, _sb.state == Superblock::EXTENDING_FT, _sb.state == Superblock::EXTENDING_VBD }; } - - -void Superblock_control_channel::_request_submitted(Module_request &req) -{ - _req_ptr = static_cast(&req); - _state = REQ_SUBMITTED; -} - - -Superblock_control::Superblock_control() -{ - for (Module_channel_id id { 0 }; id < NUM_CHANNELS; id++) { - _channels[id].construct(id, _sb, _sb_idx, _curr_gen); - add_channel(*_channels[id]); - } -} - - -Superblock_control_channel:: -Superblock_control_channel(Module_channel_id id, Superblock &sb, Superblock_index &sb_idx, Generation &curr_gen) -: - Module_channel { SUPERBLOCK_CONTROL, id }, _sb { sb }, _sb_idx { sb_idx }, _curr_gen { curr_gen } -{ } diff --git a/repos/gems/src/lib/tresor/trust_anchor.cc b/repos/gems/src/lib/tresor/trust_anchor.cc index d3a8cb17c2..aeb2d547da 100644 --- a/repos/gems/src/lib/tresor/trust_anchor.cc +++ b/repos/gems/src/lib/tresor/trust_anchor.cc @@ -16,174 +16,132 @@ using namespace Tresor; -Trust_anchor_request::Trust_anchor_request(Module_id src_module_id, Module_channel_id src_chan_id, - Type type, Key_value &key_plaintext, Key_value &key_ciphertext, - Hash &hash, Passphrase passphrase, bool &success) -: - Module_request { src_module_id, src_chan_id, TRUST_ANCHOR }, _type { type }, _key_plaintext { key_plaintext }, - _key_ciphertext { key_ciphertext }, _hash { hash }, _pass { passphrase }, _success { success } -{ } - - -char const *Trust_anchor_request::type_to_string(Type type) +bool Trust_anchor::Encrypt_key::execute(Trust_anchor::Attr const &ta_attr) { - switch (type) { - case CREATE_KEY: return "create_key"; - case ENCRYPT_KEY: return "encrypt_key"; - case DECRYPT_KEY: return "decrypt_key"; - case WRITE_HASH: return "write_hash"; - case READ_HASH: return "read_hash"; - case INITIALIZE: return "initialize"; - } - ASSERT_NEVER_REACHED; -} + bool progress = false; + switch (_helper.state) { + case INIT: + _file.construct(_helper.state, ta_attr.encrypt_file); + _helper.state = WRITE; + progress = true; + break; -void Trust_anchor_channel::_mark_req_failed(bool &progress, Error_string str) -{ - error("trust_anchor: request (", *_req_ptr, ") failed: ", str); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Trust_anchor_channel::_mark_req_successful(bool &progress) -{ - Request &req { *_req_ptr }; - req._success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Trust_anchor_channel::_read_hash(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _hashsum_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._hash, HASH_SIZE }, progress); break; - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_key_plaintext, KEY_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_key_ciphertext, KEY_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Trust_anchor_channel::_create_key(bool &progress) +bool Trust_anchor::Decrypt_key::execute(Trust_anchor::Attr const &ta_attr) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _generate_key_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._key_plaintext, KEY_SIZE }, progress); break; - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.decrypt_file); + _helper.state = WRITE; + progress = true; + break; + + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_key_ciphertext, KEY_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_key_plaintext, KEY_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } + return progress; } -void Trust_anchor_channel::_initialize(bool &progress) +bool Trust_anchor::Write_hash::execute(Trust_anchor::Attr const &ta_attr) { - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _initialize_file.write(WRITE_OK, FILE_ERR, 0, { req._pass.string(), req._pass.length() - 1 }, progress); break; - case WRITE_OK: _initialize_file.read(READ_OK, FILE_ERR, 0, { _result_buf, sizeof(_result_buf) }, progress); break; + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.hash_file); + _helper.state = WRITE; + progress = true; + break; + + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_hash, HASH_SIZE }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { _result_buf, sizeof(_result_buf) }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; + default: break; + } + return progress; +} + + +bool Trust_anchor::Read_hash::execute(Trust_anchor::Attr const &ta_attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.hash_file); + _helper.state = READ; + progress = true; + break; + + case READ: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_hash, HASH_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; + default: break; + } + return progress; +} + + +bool Trust_anchor::Generate_key::execute(Trust_anchor::Attr const &ta_attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.generate_key_file); + _helper.state = READ; + progress = true; + break; + + case READ: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_key_plaintext, KEY_SIZE }, progress); break; + case READ_OK: _helper.mark_succeeded(progress); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; + default: break; + } + return progress; +} + + +bool Trust_anchor::Initialize::execute(Trust_anchor::Attr const &ta_attr) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _file.construct(_helper.state, ta_attr.initialize_file); + _helper.state = WRITE; + progress = true; + break; + + case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { _attr.in_passphrase.string(), _attr.in_passphrase.length() - 1 }, progress); break; + case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { _result_buf, sizeof(_result_buf) }, progress); break; case READ_OK: if (strcmp(_result_buf, "ok", sizeof(_result_buf))) - _mark_req_failed(progress, { "trust anchor did not return \"ok\""}); + _helper.mark_failed(progress, {"trust anchor did not return \"ok\""}); else - _mark_req_successful(progress); + _helper.mark_succeeded(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; + case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break; default: break; } -} - - -void Trust_anchor_channel::_write_hash(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _hashsum_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._hash, HASH_SIZE }, progress); break; - case WRITE_OK: _hashsum_file.read(READ_OK, FILE_ERR, 0, { _result_buf, 0 }, progress); break; - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: break; - } -} - - -void Trust_anchor_channel::_encrypt_key(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _encrypt_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._key_plaintext, KEY_SIZE }, progress); break; - case WRITE_OK: _encrypt_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._key_ciphertext, KEY_SIZE }, progress); break; - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: break; - } -} - - -void Trust_anchor_channel::_decrypt_key(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: _decrypt_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._key_ciphertext, KEY_SIZE }, progress); break; - case WRITE_OK: _decrypt_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._key_plaintext, KEY_SIZE }, progress); break; - case READ_OK: _mark_req_successful(progress); break; - case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break; - default: break; - } -} - - -void Trust_anchor_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - Request &req { *_req_ptr }; - switch (req._type) { - case Request::INITIALIZE: _initialize(progress); break; - case Request::WRITE_HASH: _write_hash(progress); break; - case Request::READ_HASH: _read_hash(progress); break; - case Request::CREATE_KEY: _create_key(progress); break; - case Request::ENCRYPT_KEY: _encrypt_key(progress); break; - case Request::DECRYPT_KEY: _decrypt_key(progress); break; - } -} - - -Trust_anchor_channel::Trust_anchor_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node) -: - Module_channel { TRUST_ANCHOR, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) } -{ } - - -Trust_anchor::Trust_anchor(Vfs::Env &vfs_env, Xml_node const &xml_node) -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++, vfs_env, xml_node); - add_channel(*chan); - } -} - - -void Trust_anchor_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -void Trust_anchor::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + return progress; } diff --git a/repos/gems/src/lib/tresor/vbd_check.cc b/repos/gems/src/lib/tresor/vbd_check.cc index 2a7f539477..cfbb7e9ed4 100644 --- a/repos/gems/src/lib/tresor/vbd_check.cc +++ b/repos/gems/src/lib/tresor/vbd_check.cc @@ -13,52 +13,31 @@ /* tresor includes */ #include -#include #include using namespace Tresor; -Vbd_check_request::Vbd_check_request(Module_id src_mod, Module_channel_id src_chan, Tree_root const &vbd, bool &success) -: - Module_request { src_mod, src_chan, VBD_CHECK }, _vbd { vbd }, _success { success } -{ } - - -void Vbd_check_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_generated_req_success) { - error("vbd check: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) +bool Vbd_check::Check::_execute_node(Block_io &block_io, Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { bool &check_node = _check_node[lvl][node_idx]; if (!check_node) return false; - Request &req { *_req_ptr }; Type_1_node const &node = _t1_blks.items[lvl].nodes[node_idx]; - switch (_state) { - case REQ_IN_PROGRESS: + switch (_helper.state) { + case IN_PROGRESS: if (lvl == 1) { if (!_num_remaining_leaves) { if (node.valid()) { - _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, - ") valid but no leaves remaining" }); + _helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, + ") valid but no leaves remaining" }); break; } check_node = false; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid"); + log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid"); break; } if (node.gen == INITIAL_GENERATION) { @@ -66,33 +45,34 @@ bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node check_node = false; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": uninitialized"); + log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": uninitialized"); break; } } else { if (!node.valid()) { if (_num_remaining_leaves) { - _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ", - _num_remaining_leaves, " leaves remaining" }); + _helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ", + _num_remaining_leaves, " leaves remaining" }); break; } check_node = false; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid"); + log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid"); break; } } - _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _blk); if (VERBOSE_CHECK) - log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, " (", node, + log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, " (", node, "): load to lvl ", lvl - 1); break; + case READ_BLK: progress |= _read_block.execute(block_io); break; case READ_BLK_SUCCEEDED: if (!(lvl > 1 && node.gen == INITIAL_GENERATION) && !check_hash(_blk, node.hash)) { - _mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" }); + _helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" }); break; } if (lvl == 1) @@ -103,10 +83,10 @@ bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node cn = true; } check_node = false; - _state = REQ_IN_PROGRESS; + _helper.state = IN_PROGRESS; progress = true; if (VERBOSE_CHECK) - log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": good hash"); + log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": good hash"); break; default: break; @@ -115,69 +95,24 @@ bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node } -void Vbd_check_channel::execute(bool &progress) +bool Vbd_check::Check::execute(Block_io &block_io) { - if (!_req_ptr) - return; - - Request &req { *_req_ptr }; - if (_state == REQ_SUBMITTED) { - for (Tree_level_index lvl { 1 }; lvl <= req._vbd.max_lvl + 1; lvl++) - for (Tree_node_index node_idx { 0 }; node_idx < req._vbd.degree; node_idx++) + bool progress = false; + if (_helper.state == INIT) { + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_vbd.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_vbd.degree; node_idx++) _check_node[lvl][node_idx] = false; - _num_remaining_leaves = req._vbd.num_leaves; - _t1_blks.items[req._vbd.max_lvl + 1].nodes[0] = req._vbd.t1_node(); - _check_node[req._vbd.max_lvl + 1][0] = true; - _state = REQ_IN_PROGRESS; + _num_remaining_leaves = _attr.in_vbd.num_leaves; + _t1_blks.items[_attr.in_vbd.max_lvl + 1].nodes[0] = _attr.in_vbd.t1_node(); + _check_node[_attr.in_vbd.max_lvl + 1][0] = true; + _helper.state = IN_PROGRESS; } - for (Tree_level_index lvl { 1 }; lvl <= req._vbd.max_lvl + 1; lvl++) - for (Tree_node_index node_idx { 0 }; node_idx < req._vbd.degree; node_idx++) - if (_execute_node(lvl, node_idx, progress)) - return; + for (Tree_level_index lvl { 1 }; lvl <= _attr.in_vbd.max_lvl + 1; lvl++) + for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_vbd.degree; node_idx++) + if (_execute_node(block_io, lvl, node_idx, progress)) + return progress; - _mark_req_successful(progress); -} - - -void Vbd_check_channel::_mark_req_failed(bool &progress, Error_string str) -{ - error("vbd check request (", *_req_ptr, ") failed: ", str); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Vbd_check_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Vbd_check_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = REQ_SUBMITTED; -} - - -Vbd_check::Vbd_check() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Vbd_check::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); + _helper.mark_succeeded(progress); + return progress; } diff --git a/repos/gems/src/lib/tresor/vbd_initializer.cc b/repos/gems/src/lib/tresor/vbd_initializer.cc index 192036fcdf..3d8dee368b 100644 --- a/repos/gems/src/lib/tresor/vbd_initializer.cc +++ b/repos/gems/src/lib/tresor/vbd_initializer.cc @@ -13,20 +13,12 @@ */ /* tresor includes */ -#include #include #include using namespace Tresor; -Vbd_initializer_request::Vbd_initializer_request(Module_id src_mod, Module_channel_id src_chan, Tree_root &vbd, - Pba_allocator &pba_alloc, bool &success) -: - Module_request { src_mod, src_chan, VBD_INITIALIZER }, _vbd { vbd }, _pba_alloc { pba_alloc }, _success { success } -{ } - - -bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) +bool Vbd_initializer::Initialize::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress) { Type_1_node &node = _t1_blks.items[lvl].nodes[node_idx]; Node_state &node_state = _node_states[lvl][node_idx]; @@ -58,8 +50,8 @@ bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_inde if (lvl == 1) if (_num_remaining_leaves) { node = { }; - if (!_req_ptr->_pba_alloc.alloc(node.pba)) { - _mark_req_failed(progress, "allocate pba"); + if (!_attr.in_out_pba_alloc.alloc(node.pba)) { + _helper.mark_failed(progress, "allocate pba"); break; } node_state = DONE; @@ -76,21 +68,20 @@ bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_inde } else { node = { }; - if (!_req_ptr->_pba_alloc.alloc(node.pba)) { - _mark_req_failed(progress, "allocate pba"); + if (!_attr.in_out_pba_alloc.alloc(node.pba)) { + _helper.mark_failed(progress, "allocate pba"); break; } _t1_blks.items[lvl - 1].encode_to_blk(_blk); calc_hash(_blk, node.hash); - node_state = WRITE_BLOCK; - generate_req(EXECUTE_NODES, progress, node.pba, _blk, _generated_req_success); - _state = REQ_GENERATED; + _write_block.generate(_helper, WRITE_BLOCK, EXECUTE_NODES, progress, node.pba, _blk); + node_state = WRITING_BLOCK; if (VERBOSE_VBD_INIT) log("[vbd_init] node: ", lvl, " ", node_idx, " assign pba: ", node.pba); } break; - case WRITE_BLOCK: + case WRITING_BLOCK: ASSERT(lvl > 1); node_state = DONE; @@ -103,103 +94,47 @@ bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_inde } -void Vbd_initializer_channel::_generated_req_completed(State_uint state_uint) +bool Vbd_initializer::Initialize::execute(Block_io &block_io) { - if (!_generated_req_success) { - error("vbd initializer: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} + bool progress = false; + switch (_helper.state) { + case INIT: - -void Vbd_initializer_channel::_mark_req_failed(bool &progress, char const *str) -{ - error("vbd_initializer request (", *_req_ptr, ") failed because: ", str); - _req_ptr->_success = false; - _state = COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Vbd_initializer_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_vbd.t1_node(_t1_blks.items[_req_ptr->_vbd.max_lvl + 1].nodes[0]); - _req_ptr->_success = true; - _state = COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Vbd_initializer_channel::_request_submitted(Module_request &mod_req) -{ - _req_ptr = static_cast(&mod_req); - _state = SUBMITTED; -} - - -void Vbd_initializer_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - Request &req { *_req_ptr }; - switch (_state) { - case SUBMITTED: - - _num_remaining_leaves = req._vbd.num_leaves; + _num_remaining_leaves = _attr.in_tree_cfg.num_leaves; for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++) - _reset_level(lvl, Vbd_initializer_channel::DONE); + _reset_level(lvl, Vbd_initializer::Initialize::DONE); - _node_states[req._vbd.max_lvl + 1][0] = Vbd_initializer_channel::INIT_BLOCK; - _state = EXECUTE_NODES; + _node_states[_attr.in_tree_cfg.max_lvl + 1][0] = Vbd_initializer::Initialize::INIT_BLOCK; + _helper.state = EXECUTE_NODES; progress = true; - return; + break; case EXECUTE_NODES: - for (Tree_level_index lvl = 0; lvl <= req._vbd.max_lvl + 1; lvl++) - for (Tree_node_index node_idx = 0; node_idx < req._vbd.degree; node_idx++) + for (Tree_level_index lvl = 0; lvl <= _attr.in_tree_cfg.max_lvl + 1; lvl++) + for (Tree_node_index node_idx = 0; node_idx < _attr.in_tree_cfg.degree; node_idx++) if (_execute_node(lvl, node_idx, progress)) - return; + return progress; if (_num_remaining_leaves) - _mark_req_failed(progress, "leaves remaining"); - else - _mark_req_successful(progress); - return; + _helper.mark_failed(progress, "leaves remaining"); + else { + _attr.out_tree_root = _t1_blks.items[_attr.in_tree_cfg.max_lvl + 1].nodes[0]; + _helper.mark_succeeded(progress); + } + break; - default: return; + case WRITE_BLOCK: progress |= _write_block.execute(block_io); break; + default: break; } + return progress; } -void Vbd_initializer_channel::_reset_level(Tree_level_index lvl, Node_state state) +void Vbd_initializer::Initialize::_reset_level(Tree_level_index lvl, Node_state state) { for (unsigned int idx = 0; idx < NUM_NODES_PER_BLK; idx++) { _t1_blks.items[lvl].nodes[idx] = { }; _node_states[lvl][idx] = state; } } - - -Vbd_initializer::Vbd_initializer() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Vbd_initializer::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} diff --git a/repos/gems/src/lib/tresor/virtual_block_device.cc b/repos/gems/src/lib/tresor/virtual_block_device.cc index 035247e95b..2ffdb87a1b 100644 --- a/repos/gems/src/lib/tresor/virtual_block_device.cc +++ b/repos/gems/src/lib/tresor/virtual_block_device.cc @@ -14,161 +14,167 @@ /* tresor includes */ #include #include -#include -#include -#include using namespace Tresor; -Virtual_block_device_request:: -Virtual_block_device_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type, - Request_offset client_req_offset, Request_tag client_req_tag, - Generation last_secured_gen, Tree_root &ft, Tree_root &mt, - Tree_degree vbd_degree, Virtual_block_address vbd_highest_vba, bool rekeying, - Virtual_block_address vba, Snapshot_index curr_snap_idx, Snapshots &snapshots, - Tree_degree snap_degr, Key_id prev_key_id, Key_id curr_key_id, - Generation curr_gen, Physical_block_address &pba, bool &success, - Number_of_leaves &num_leaves, Number_of_blocks &num_pbas, Virtual_block_address rekeying_vba) -: - Module_request { src_module_id, src_chan_id, VIRTUAL_BLOCK_DEVICE }, _type { type }, _vba { vba }, - _snapshots { snapshots }, _curr_snap_idx { curr_snap_idx }, _snap_degr { snap_degr }, _curr_gen { curr_gen }, - _curr_key_id { curr_key_id }, _prev_key_id { prev_key_id }, _ft { ft }, _mt { mt }, _vbd_degree { vbd_degree }, - _vbd_highest_vba { vbd_highest_vba }, _rekeying { rekeying }, _client_req_offset { client_req_offset }, - _client_req_tag { client_req_tag }, _last_secured_gen { last_secured_gen }, _pba { pba }, - _num_pbas { num_pbas }, _num_leaves { num_leaves }, _rekeying_vba { rekeying_vba }, _success { success } -{ } - - -char const *Virtual_block_device_request::type_to_string(Type op) -{ - switch (op) { - case READ_VBA: return "read_vba"; - case WRITE_VBA: return "write_vba"; - case REKEY_VBA: return "rekey_vba"; - case EXTENSION_STEP: return "extension_step"; - } - ASSERT_NEVER_REACHED; -} - - -void Virtual_block_device_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_gen_req_success) { - error("virtual block device: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -void Virtual_block_device_channel::_generate_write_blk_req(bool &progress) +bool Virtual_block_device::Read_vba::_check_and_decode_read_blk(bool &progress) { + Hash const *node_hash_ptr; + calc_hash(_blk, _hash); if (_lvl) { - _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); - _generate_req(WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _encoded_blk); - } else - _generate_req(WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _data_blk); + if (_lvl < _attr.in_snap.max_level) + node_hash_ptr = &_t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree).hash; + else + node_hash_ptr = &_attr.in_snap.hash; + } else { + Type_1_node &node = _t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree); + if (node.gen == INITIAL_GENERATION) + return true; + + node_hash_ptr = &node.hash; + } + if (_hash != *node_hash_ptr) { + _helper.mark_failed(progress, "check hash of read block"); + return false; + } + if (_lvl) + _t1_blks.items[_lvl].decode_from_blk(_blk); + + return true; } -void Virtual_block_device_channel::_read_vba(bool &progress) +bool Virtual_block_device::Read_vba::execute(Client_data_interface &client_data, Block_io &block_io, Crypto &crypto) { - Request &req { *_req_ptr }; - switch (_state) { - case SUBMITTED: + bool progress = false; + switch (_helper.state) { + case INIT: - _snap_idx = req._curr_snap_idx; - _vba = req._vba; - _lvl = snap().max_level; - _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + _lvl = _attr.in_snap.max_level; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _attr.in_snap.pba, _blk); if (VERBOSE_READ_VBA) - log(" load branch:\n ", Branch_lvl_prefix("root: "), snap()); + log(" load branch:\n ", Branch_lvl_prefix("root: "), _attr.in_snap); break; + case READ_BLK: progress |= _read_block.execute(block_io); break; case READ_BLK_SUCCEEDED: { if (!_check_and_decode_read_blk(progress)) break; if (!_lvl) { - _mark_req_successful(progress); + if (VERBOSE_READ_VBA) + log(" ", Branch_lvl_prefix("ciphertext: "), _blk, " ", hash(_blk)); + + _decrypt_block.generate( + _helper, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED, progress, _attr.in_key_id, _new_pbas.pbas[_lvl], _blk); break; } - Type_1_node &node { _node(_lvl, req._vba) }; + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl, _attr.in_vbd_degree) }; if (VERBOSE_READ_VBA) - log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl, req._vba), ": "), node); + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", tree_node_index(_attr.in_vba, _lvl, _attr.in_vbd_degree), ": "), node); - if (_lvl > 1) - _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _encoded_blk); + _lvl--; + _new_pbas.pbas[_lvl] = node.pba; + if (_lvl) + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _blk); else if (node.gen == INITIAL_GENERATION) { - memset(&_data_blk, 0, BLOCK_SIZE); - _generate_req( - READ_BLK_SUCCEEDED, progress, Client_data_request::SUPPLY_PLAINTEXT_BLK, - req._client_req_offset, req._client_req_tag, node.pba, _vba, _data_blk); + memset(&_blk, 0, BLOCK_SIZE); + _helper.state = DECRYPT_BLOCK_SUCCEEDED; + progress = true; } else - _generate_req( - READ_BLK_SUCCEEDED, progress, node.pba, _vba, req._curr_key_id, - req._client_req_tag, req._client_req_offset, _hash); - _lvl--; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _blk); break; } + case DECRYPT_BLOCK: progress |= _decrypt_block.execute(crypto); break; + case DECRYPT_BLOCK_SUCCEEDED: + + if (VERBOSE_READ_VBA) + log(" ", Branch_lvl_prefix("plaintext: "), _blk, " ", hash(_blk)); + + client_data.supply_data( + {_attr.in_client_req_offset, _attr.in_client_req_tag, _new_pbas.pbas[_lvl], _attr.in_vba, _blk}); + + _helper.mark_succeeded(progress); + break; + default: break; } + return progress; } -void Virtual_block_device_channel::_update_nodes_of_branch_of_written_vba() +void Virtual_block_device::Rekey_vba::_start_alloc_pbas(bool &progress, Free_tree::Allocate_pbas::Application application) { - Request &req { *_req_ptr }; - Type_1_node &node { _node(1, _vba) }; - node = Type_1_node { _new_pbas.pbas[0], req._curr_gen, _hash }; - if (VERBOSE_WRITE_VBA) - log(" ", Branch_lvl_prefix("lvl 1 node ", _node_idx(1, _vba), ": "), node); - - for (Tree_level_index lvl = 1; lvl < snap().max_level; lvl++) { - Type_1_node &node { _node(lvl + 1, _vba) }; - node.pba = _new_pbas.pbas[lvl]; - node.gen = req._curr_gen; - _t1_blks.items[lvl].encode_to_blk(_encoded_blk); - calc_hash(_encoded_blk, node.hash); - if (VERBOSE_WRITE_VBA) - log(" ", Branch_lvl_prefix("lvl ", lvl + 1, " node ", _node_idx(lvl + 1, _vba), ": "), node); - } - snap().pba = _new_pbas.pbas[snap().max_level]; - snap().gen = req._curr_gen; - _t1_blks.items[snap().max_level].encode_to_blk(_encoded_blk); - calc_hash(_encoded_blk, snap().hash); - if (VERBOSE_WRITE_VBA) - log(" ", Branch_lvl_prefix("root: "), snap()); + _alloc_pbas.generate( + _helper, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED, progress, _attr.in_out_ft, _attr.in_out_mt, _attr.in_out_snapshots, + _attr.in_last_secured_gen, _attr.in_curr_gen, _free_gen, _num_blks, _new_pbas, _t1_nodes, + _attr.in_out_snapshots.items[_snap_idx].max_level, _attr.in_vba, _attr.in_vbd_degree, _attr.in_vbd_highest_vba, true, + _attr.in_prev_key_id, _attr.in_curr_key_id, _attr.in_vba, application); } -bool Virtual_block_device_channel::_check_and_decode_read_blk(bool &progress) +void Virtual_block_device::Rekey_vba::_generate_write_blk_req(bool &progress) { - Request &req { *_req_ptr }; - Hash *node_hash_ptr; + if (_lvl) { + _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _encoded_blk); + } else + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _data_blk); +} + + +void Virtual_block_device::Rekey_vba::_generate_ft_alloc_req_for_rekeying(Tree_level_index min_lvl, bool &progress) +{ + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + ASSERT(min_lvl <= snap.max_level); + _num_blks = 0; + if (_first_snapshot) + _free_gen = _attr.in_curr_gen; + else + _free_gen = snap.gen + 1; + + for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) + if (lvl > snap.max_level) { + _t1_nodes.nodes[lvl] = { }; + _new_pbas.pbas[lvl] = 0; + } else if (lvl == snap.max_level) { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + _t1_nodes.nodes[lvl] = { snap.pba, snap.gen, snap.hash }; + } else if (lvl >= min_lvl) { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + _t1_nodes.nodes[lvl] = _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree); + } else { + Type_1_node &node { _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree) }; + _t1_nodes.nodes[lvl] = { _new_pbas.pbas[lvl], node.gen, node.hash}; + } + + _start_alloc_pbas(progress, _first_snapshot ? + Free_tree::Allocate_pbas::REKEYING_IN_CURRENT_GENERATION : + Free_tree::Allocate_pbas::REKEYING_IN_OLDER_GENERATION); +} + + +bool Virtual_block_device::Rekey_vba::_check_and_decode_read_blk(bool &progress) +{ + Hash const *node_hash_ptr; if (_lvl) { calc_hash(_encoded_blk, _hash); - if (_lvl < snap().max_level) - node_hash_ptr = &_node(_lvl + 1, _vba).hash; + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + if (_lvl < snap.max_level) + node_hash_ptr = &_t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree).hash; else - node_hash_ptr = &snap().hash; + 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); - + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree) }; + calc_hash(_data_blk, _hash); node_hash_ptr = &node.hash; } if (_hash != *node_hash_ptr) { - _mark_req_failed(progress, "check hash of read block"); + _helper.mark_failed(progress, "check hash of read block"); return false; } if (_lvl) @@ -178,230 +184,33 @@ bool Virtual_block_device_channel::_check_and_decode_read_blk(bool &progress) } -Tree_node_index Virtual_block_device_channel::_node_idx(Tree_level_index lvl, Virtual_block_address vba) const +bool Virtual_block_device::Rekey_vba::execute(Block_io &block_io, Crypto &crypto, Free_tree &free_tree, Meta_tree &meta_tree) { - return t1_node_idx_for_vba(vba, lvl, _req_ptr->_snap_degr); -} - - -Type_1_node &Virtual_block_device_channel::_node(Tree_level_index lvl, Virtual_block_address vba) -{ - return _t1_blks.items[lvl].nodes[_node_idx(lvl, vba)]; -} - - -void Virtual_block_device_channel::_set_new_pbas_and_num_blks_for_alloc() -{ - Request &req { *_req_ptr }; - _num_blks = 0; - for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) { - if (lvl > snap().max_level) - _new_pbas.pbas[lvl] = 0; - else if (lvl == snap().max_level) { - if (snap().gen < req._curr_gen) { - _num_blks++; - _new_pbas.pbas[lvl] = 0; - } else if (snap().gen == req._curr_gen) - _new_pbas.pbas[lvl] = snap().pba; - else - ASSERT_NEVER_REACHED; - } else { - Type_1_node const &node { _node(lvl + 1, _vba) }; - if (node.gen < req._curr_gen) { - if (lvl == 0 && node.gen == INVALID_GENERATION) - _new_pbas.pbas[lvl] = node.pba; - else { - _num_blks++; - _new_pbas.pbas[lvl] = 0; - } - } else if (node.gen == req._curr_gen) - _new_pbas.pbas[lvl] = node.pba; - else - ASSERT_NEVER_REACHED; - } - } -} - - -void Virtual_block_device_channel::_generate_ft_alloc_req_for_write_vba(bool &progress) -{ - for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) - if (lvl > snap().max_level) - _t1_nodes.nodes[lvl] = Type_1_node { }; - else if (lvl == snap().max_level) - _t1_nodes.nodes[lvl] = Type_1_node { snap().pba, snap().gen, snap().hash }; - else - _t1_nodes.nodes[lvl] = _node(lvl + 1, _vba); - - _free_gen = _req_ptr->_curr_gen; - _generate_ft_req(ALLOC_PBAS_SUCCEEDED, progress, Free_tree_request::ALLOC_FOR_NON_RKG); -} - - -void Virtual_block_device_channel::_write_vba(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case SUBMITTED: - - _snap_idx = req._curr_snap_idx; - _vba = req._vba; - _lvl = snap().max_level; - _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); - if (VERBOSE_WRITE_VBA) - log(" load branch:\n ", Branch_lvl_prefix("root: "), snap()); - break; - - case READ_BLK_SUCCEEDED: - - if (!_check_and_decode_read_blk(progress)) - break; - - if (VERBOSE_WRITE_VBA) - log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl, _vba), ": "), _node(_lvl, _vba)); - - if (_lvl > 1) - _generate_req(READ_BLK_SUCCEEDED, progress, _node(_lvl, _vba).pba, _encoded_blk); - else { - _set_new_pbas_and_num_blks_for_alloc(); - if (_num_blks) - _generate_ft_alloc_req_for_write_vba(progress); - else - _generate_req( - WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[0], _vba, - req._curr_key_id, req._client_req_tag, req._client_req_offset, _hash); - } - _lvl--; - break; - - case ALLOC_PBAS_SUCCEEDED: - - if (VERBOSE_WRITE_VBA) - log(" alloc pba", _num_blks > 1 ? "s" : "", ": ", Pba_allocation(_t1_nodes, _new_pbas)); - - _generate_req( - WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[0], _vba, req._curr_key_id, - req._client_req_tag, req._client_req_offset, _hash); - - break; - - case WRITE_BLK_SUCCEEDED: - - if (!_lvl) - _update_nodes_of_branch_of_written_vba(); - - if (_lvl < snap().max_level) { - _lvl++; - _generate_write_blk_req(progress); - } else - _mark_req_successful(progress); - break; - - default: break; - } -} - - -void Virtual_block_device_channel::_mark_req_failed(bool &progress, char const *str) -{ - error(Request::type_to_string(_req_ptr->_type), " request failed at step \"", str, "\""); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Virtual_block_device_channel::_mark_req_successful(bool &progress) -{ - _req_ptr->_success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -bool Virtual_block_device_channel::_find_next_snap_to_rekey_vba_at(Snapshot_index &result) const -{ - bool result_valid { false }; - Request &req { *_req_ptr }; - Snapshot &curr_snap { req._snapshots.items[_snap_idx] }; - for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { - Snapshot &snap { req._snapshots.items[idx] }; - if (snap.valid && snap.contains_vba(req._vba)) { - if (result_valid) { - if (snap.gen < curr_snap.gen && snap.gen > req._snapshots.items[result].gen) - result = idx; - } else - if (snap.gen < curr_snap.gen) { - result = idx; - result_valid = true; - } - } - } - return result_valid; -} - - -void Virtual_block_device_channel::_generate_ft_alloc_req_for_rekeying(Tree_level_index min_lvl, bool &progress) -{ - Request &req { *_req_ptr }; - ASSERT(min_lvl <= snap().max_level); - _num_blks = 0; - if (_first_snapshot) - _free_gen = req._curr_gen; - else - _free_gen = snap().gen + 1; - - for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) - if (lvl > snap().max_level) { - _t1_nodes.nodes[lvl] = { }; - _new_pbas.pbas[lvl] = 0; - } else if (lvl == snap().max_level) { - _num_blks++; - _new_pbas.pbas[lvl] = 0; - _t1_nodes.nodes[lvl] = { snap().pba, snap().gen, snap().hash }; - } else if (lvl >= min_lvl) { - _num_blks++; - _new_pbas.pbas[lvl] = 0; - _t1_nodes.nodes[lvl] = _node(lvl + 1, req._vba); - } else { - Type_1_node &node { _node(lvl + 1, req._vba) }; - _t1_nodes.nodes[lvl] = { _new_pbas.pbas[lvl], node.gen, node.hash}; - } - - _generate_ft_req(ALLOC_PBAS_SUCCEEDED, progress, _first_snapshot ? - Free_tree_request::ALLOC_FOR_RKG_CURR_GEN_BLKS : - Free_tree_request::ALLOC_FOR_RKG_OLD_GEN_BLKS); -} - - -void Virtual_block_device_channel::_rekey_vba(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case SUBMITTED: - - _vba = req._vba; - _snap_idx = req._snapshots.newest_snap_idx(); + bool progress = false; + switch (_helper.state) { + case INIT: + { + _snap_idx = _attr.in_out_snapshots.newest_snap_idx(); + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; _first_snapshot = true; - _lvl = snap().max_level; - _old_pbas.pbas[_lvl] = snap().pba; - _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + _lvl = snap.max_level; + _old_pbas.pbas[_lvl] = snap.pba; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, snap.pba, _encoded_blk); if (VERBOSE_REKEYING) log(" snapshot ", _snap_idx, ":\n load branch:\n ", - Branch_lvl_prefix("root: "), snap()); + Branch_lvl_prefix("root: "), snap); break; - + } + case READ_BLK: progress |= _read_block.execute(block_io); break; case READ_BLK_SUCCEEDED: if (!_check_and_decode_read_blk(progress)) break; if (_lvl) { - Type_1_node &node { _node(_lvl, req._vba) }; + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl, _attr.in_vbd_degree) }; if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl, req._vba), ": "), node); + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", tree_node_index(_attr.in_vba, _lvl, _attr.in_vbd_degree), ": "), node); if (!_first_snapshot && _old_pbas.pbas[_lvl - 1] == node.pba) { @@ -420,23 +229,24 @@ void Virtual_block_device_channel::_rekey_vba(bool &progress) } else { _lvl--; _old_pbas.pbas[_lvl] = node.pba; - _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _lvl ? _encoded_blk : _data_blk); + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _lvl ? _encoded_blk : _data_blk); } } else { - _generate_req( - DECRYPT_LEAF_DATA_SUCCEEDED, progress, req._prev_key_id, _old_pbas.pbas[_lvl], _data_blk); + _decrypt_block.generate(_helper, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED, progress, _attr.in_prev_key_id, _old_pbas.pbas[_lvl], _data_blk); if (VERBOSE_REKEYING) log(" ", Branch_lvl_prefix("leaf data: "), _data_blk); } break; - case DECRYPT_LEAF_DATA_SUCCEEDED: + case DECRYPT_BLOCK: progress |= _decrypt_block.execute(crypto); break; + case DECRYPT_BLOCK_SUCCEEDED: _generate_ft_alloc_req_for_rekeying(_lvl, progress); if (VERBOSE_REKEYING) log(" re-encrypt leaf data: plaintext ", _data_blk, " hash ", hash(_data_blk)); break; + case ALLOC_PBAS: progress |= _alloc_pbas.execute(free_tree, block_io, meta_tree); break; case ALLOC_PBAS_SUCCEEDED: if (VERBOSE_REKEYING) @@ -447,80 +257,400 @@ void Virtual_block_device_channel::_rekey_vba(bool &progress) log(" update branch:"); _lvl--; - _state = WRITE_BLK_SUCCEEDED; + _helper.state = WRITE_BLK_SUCCEEDED; progress = true; if (_lvl) _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); } else - _generate_req( - ENCRYPT_LEAF_DATA_SUCCEEDED, progress, req._curr_key_id, _new_pbas.pbas[0], _data_blk); + _encrypt_block.generate( + _helper, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, progress, _attr.in_curr_key_id, _new_pbas.pbas[0], _data_blk); break; - case ENCRYPT_LEAF_DATA_SUCCEEDED: + case ENCRYPT_BLOCK: progress |= _encrypt_block.execute(crypto); break; + case ENCRYPT_BLOCK_SUCCEEDED: _generate_write_blk_req(progress); if (VERBOSE_REKEYING) log(" update branch:\n ", Branch_lvl_prefix("leaf data: "), _data_blk); break; + case WRITE_BLK: progress |= _write_block.execute(block_io); break; case WRITE_BLK_SUCCEEDED: - - if (_lvl < snap().max_level) { - Type_1_node &node { _node(_lvl + 1, req._vba) }; + { + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + if (_lvl < snap.max_level) { + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree) }; node.pba = _new_pbas.pbas[_lvl]; calc_hash(_lvl ? _encoded_blk : _data_blk, node.hash); _lvl++; _generate_write_blk_req(progress); if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", _node_idx(_lvl + 1, req._vba), ": "), node); + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", tree_node_index(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree), ": "), node); } else { - snap().pba = _new_pbas.pbas[_lvl]; - calc_hash(_encoded_blk, snap().hash); + snap.pba = _new_pbas.pbas[_lvl]; + calc_hash(_encoded_blk, snap.hash); if (VERBOSE_REKEYING) - log(" ", Branch_lvl_prefix("root: "), snap()); + log(" ", Branch_lvl_prefix("root: "), snap); Snapshot_index snap_idx; if (_find_next_snap_to_rekey_vba_at(snap_idx)) { _snap_idx = snap_idx; + Snapshot &next_snap = _attr.in_out_snapshots.items[_snap_idx]; _first_snapshot = false; - _lvl = snap().max_level; - if (_old_pbas.pbas[_lvl] == snap().pba) + _lvl = next_snap.max_level; + if (_old_pbas.pbas[_lvl] == next_snap.pba) progress = true; else { - _old_pbas.pbas[_lvl] = snap().pba; - _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); + _old_pbas.pbas[_lvl] = next_snap.pba; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, next_snap.pba, _encoded_blk); if (VERBOSE_REKEYING) log(" snapshot ", _snap_idx, ":\n load branch:\n ", - Branch_lvl_prefix("root: "), snap()); + Branch_lvl_prefix("root: "), next_snap); } } else - _mark_req_successful(progress); + _helper.mark_succeeded(progress); } break; - + } default: break; } + return progress; +} + + +bool Virtual_block_device::Rekey_vba::_find_next_snap_to_rekey_vba_at(Snapshot_index &result) const +{ + bool result_valid { false }; + Snapshot &curr_snap { _attr.in_out_snapshots.items[_snap_idx] }; + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) { + Snapshot const &snap { _attr.in_out_snapshots.items[idx] }; + if (snap.valid && snap.contains_vba(_attr.in_vba)) { + if (result_valid) { + if (snap.gen < curr_snap.gen && snap.gen > _attr.in_out_snapshots.items[result].gen) + result = idx; + } else + if (snap.gen < curr_snap.gen) { + result = idx; + result_valid = true; + } + } + } + return result_valid; +} + + +void Virtual_block_device::Write_vba::_update_nodes_of_branch_of_written_vba() +{ + Type_1_node &node { _t1_blks.node(_attr.in_vba, 1, _attr.in_vbd_degree) }; + node = Type_1_node { _new_pbas.pbas[0], _attr.in_curr_gen, _hash }; + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("lvl 1 node ", tree_node_index(_attr.in_vba, 1, _attr.in_vbd_degree), ": "), node); + + for (Tree_level_index lvl = 1; lvl < _attr.in_out_snap.max_level; lvl++) { + Type_1_node &node { _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree) }; + node.pba = _new_pbas.pbas[lvl]; + node.gen = _attr.in_curr_gen; + _t1_blks.items[lvl].encode_to_blk(_encoded_blk); + calc_hash(_encoded_blk, node.hash); + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("lvl ", lvl + 1, " node ", tree_node_index(_attr.in_vba, lvl + 1, _attr.in_vbd_degree), ": "), node); + } + _attr.in_out_snap.pba = _new_pbas.pbas[_attr.in_out_snap.max_level]; + _attr.in_out_snap.gen = _attr.in_curr_gen; + _t1_blks.items[_attr.in_out_snap.max_level].encode_to_blk(_encoded_blk); + calc_hash(_encoded_blk, _attr.in_out_snap.hash); + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("root: "), _attr.in_out_snap); +} + + +bool Virtual_block_device::Write_vba::_check_and_decode_read_blk(bool &progress) +{ + Hash *node_hash_ptr; + if (_lvl) { + calc_hash(_encoded_blk, _hash); + if (_lvl < _attr.in_out_snap.max_level) + node_hash_ptr = &_t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree).hash; + else + node_hash_ptr = &_attr.in_out_snap.hash; + } else { + Type_1_node &node { _t1_blks.node(_attr.in_vba, _lvl + 1, _attr.in_vbd_degree) }; + calc_hash(_data_blk, _hash); + node_hash_ptr = &node.hash; + } + if (_hash != *node_hash_ptr) { + _helper.mark_failed(progress, "check hash of read block"); + return false; + } + if (_lvl) + _t1_blks.items[_lvl].decode_from_blk(_encoded_blk); + + return true; +} + + +void Virtual_block_device::Write_vba::_set_new_pbas_and_num_blks_for_alloc() +{ + _num_blks = 0; + for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) { + if (lvl > _attr.in_out_snap.max_level) + _new_pbas.pbas[lvl] = 0; + else if (lvl == _attr.in_out_snap.max_level) { + if (_attr.in_out_snap.gen < _attr.in_curr_gen) { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + } else if (_attr.in_out_snap.gen == _attr.in_curr_gen) + _new_pbas.pbas[lvl] = _attr.in_out_snap.pba; + else + ASSERT_NEVER_REACHED; + } else { + Type_1_node const &node { _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree) }; + if (node.gen < _attr.in_curr_gen) { + if (lvl == 0 && node.gen == INVALID_GENERATION) + _new_pbas.pbas[lvl] = node.pba; + else { + _num_blks++; + _new_pbas.pbas[lvl] = 0; + } + } else if (node.gen == _attr.in_curr_gen) + _new_pbas.pbas[lvl] = node.pba; + else + ASSERT_NEVER_REACHED; + } + } } -void Virtual_block_device_channel::_add_new_root_lvl_to_snap() +bool Virtual_block_device::Write_vba::execute(Client_data_interface &client_data, Block_io &block_io, Free_tree &free_tree, Meta_tree &meta_tree, Crypto &crypto) +{ + bool progress = false; + switch (_helper.state) { + case INIT: + + _lvl = _attr.in_out_snap.max_level; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _attr.in_out_snap.pba, _encoded_blk); + if (VERBOSE_WRITE_VBA) + log(" load branch:\n ", Branch_lvl_prefix("root: "), _attr.in_out_snap); + break; + + case READ_BLK: progress |= _read_block.execute(block_io); break; + case READ_BLK_SUCCEEDED: + { + if (!_check_and_decode_read_blk(progress)) + break; + + Type_1_node &node = _t1_blks.node(_attr.in_vba, _lvl, _attr.in_vbd_degree); + if (VERBOSE_WRITE_VBA) + log(" ", Branch_lvl_prefix("lvl ", _lvl, " node ", tree_node_index(_attr.in_vba, _lvl, _attr.in_vbd_degree), ": "), node); + + if (_lvl > 1) + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _encoded_blk); + else { + _set_new_pbas_and_num_blks_for_alloc(); + if (_num_blks) + _generate_ft_alloc_req_for_write_vba(progress); + else { + client_data.obtain_data({_attr.in_client_req_offset, _attr.in_client_req_tag, _new_pbas.pbas[0], _attr.in_vba, _data_blk}); + _encrypt_block.generate( + _helper, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, progress, _attr.in_curr_key_id, _new_pbas.pbas[0], _data_blk); + } + } + _lvl--; + break; + } + case ALLOC_PBAS: progress |= _alloc_pbas.execute(free_tree, block_io, meta_tree); break; + case ALLOC_PBAS_SUCCEEDED: + + if (VERBOSE_WRITE_VBA) + log(" alloc pba", _num_blks > 1 ? "s" : "", ": ", Pba_allocation(_t1_nodes, _new_pbas)); + + client_data.obtain_data({_attr.in_client_req_offset, _attr.in_client_req_tag, _new_pbas.pbas[0], _attr.in_vba, _data_blk}); + _encrypt_block.generate( + _helper, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, progress, _attr.in_curr_key_id, _new_pbas.pbas[0], _data_blk); + break; + + case ENCRYPT_BLOCK: progress |= _encrypt_block.execute(crypto); break; + case ENCRYPT_BLOCK_SUCCEEDED: + + calc_hash(_data_blk, _hash); + _generate_write_blk_req(progress); + break; + + case WRITE_BLK: progress |= _write_block.execute(block_io); break; + case WRITE_BLK_SUCCEEDED: + + if (!_lvl) + _update_nodes_of_branch_of_written_vba(); + + if (_lvl < _attr.in_out_snap.max_level) { + _lvl++; + _generate_write_blk_req(progress); + } else + _helper.mark_succeeded(progress); + break; + + default: break; + } + return progress; +} + + +void Virtual_block_device::Write_vba::_generate_ft_alloc_req_for_write_vba(bool &progress) +{ + for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) + if (lvl > _attr.in_out_snap.max_level) + _t1_nodes.nodes[lvl] = Type_1_node { }; + else if (lvl == _attr.in_out_snap.max_level) + _t1_nodes.nodes[lvl] = Type_1_node { _attr.in_out_snap.pba, _attr.in_out_snap.gen, _attr.in_out_snap.hash }; + else + _t1_nodes.nodes[lvl] = _t1_blks.node(_attr.in_vba, lvl + 1, _attr.in_vbd_degree); + + _free_gen = _attr.in_curr_gen; + _alloc_pbas.generate( + _helper, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED, progress, _attr.in_out_ft, _attr.in_out_mt, _attr.in_snapshots, + _attr.in_last_secured_gen, _attr.in_curr_gen, _free_gen, _num_blks, _new_pbas, _t1_nodes, + _attr.in_out_snap.max_level, _attr.in_vba, _attr.in_vbd_degree, _attr.in_vbd_highest_vba, _attr.in_rekeying, + _attr.in_prev_key_id, 0, _attr.in_rekeying_vba, Free_tree::Allocate_pbas::NON_REKEYING); +} + + +void Virtual_block_device::Write_vba::_generate_write_blk_req(bool &progress) +{ + if (_lvl) { + _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _encoded_blk); + } else + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _data_blk); +} + + +bool Virtual_block_device::Extend_tree::execute(Block_io &block_io, Free_tree &free_tree, Meta_tree &meta_tree) +{ + bool progress = false; + switch (_helper.state) { + case State::INIT: + { + _attr.out_num_leaves = 0; + _snap_idx = _attr.in_out_snapshots.newest_snap_idx(); + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + _vba = snap.nr_of_leaves; + _lvl = snap.max_level; + _old_pbas.pbas[_lvl] = snap.pba; + if (_vba <= tree_max_max_vba(_attr.in_snap_degr, snap.max_level)) { + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, snap.pba, _encoded_blk); + if (VERBOSE_VBD_EXTENSION) + log(" read lvl ", _lvl, " parent snap ", _snap_idx, " ", snap); + } else { + _add_new_root_lvl_to_snap(); + _add_new_branch_to_snap(_attr.in_out_snapshots.items[_snap_idx].max_level, 1); + _set_new_pbas_identical_to_curr_pbas(); + _generate_write_blk_req(progress); + if (VERBOSE_VBD_EXTENSION) + log(" write 1 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); + } + break; + } + case READ_BLK: progress |= _read_block.execute(block_io); break; + case READ_BLK_SUCCEEDED: + { + _t1_blks.items[_lvl].decode_from_blk(_encoded_blk); + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + if (_lvl == snap.max_level) { + if (!check_hash(_encoded_blk, snap.hash)) { + _helper.mark_failed(progress, "check root node hash"); + break; + } + } else { + if (!check_hash(_encoded_blk, _t1_blks.node(_vba, _lvl + 1, _attr.in_vbd_degree).hash)) { + _helper.mark_failed(progress, "check inner node hash"); + break; + } + } + Tree_node_index node_idx { tree_node_index(_vba, _lvl, _attr.in_vbd_degree) }; + if (_lvl > 1) { + Type_1_node &node { _t1_blks.node(_vba, _lvl, _attr.in_vbd_degree) }; + if (node.valid()) { + _old_pbas.pbas[_lvl - 1] = node.pba; + _read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _encoded_blk); + if (VERBOSE_VBD_EXTENSION) + log(" read lvl ", _lvl - 1, " parent lvl ", _lvl, " node ", node_idx, " ", node); + _lvl--; + } else { + _add_new_branch_to_snap(_lvl, node_idx); + _generate_ft_alloc_req_for_resizing(_lvl, progress); + } + } else { + _add_new_branch_to_snap(_lvl, node_idx); + _generate_ft_alloc_req_for_resizing(_lvl, progress); + } + break; + } + case ALLOC_PBAS: progress |= _alloc_pbas.execute(free_tree, block_io, meta_tree); break; + case ALLOC_PBAS_SUCCEEDED: + { + if (VERBOSE_VBD_EXTENSION) { + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + log(" allocated ", _num_blks, " pbas"); + for (Tree_level_index lvl { 0 }; lvl < snap.max_level; lvl++) + log(" lvl ", lvl, " ", _t1_nodes.nodes[lvl], " -> pba ", _new_pbas.pbas[lvl]); + + log(" write 1 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); + } + _generate_write_blk_req(progress); + break; + } + case WRITE_BLK: progress |= _write_block.execute(block_io); break; + case WRITE_BLK_SUCCEEDED: + { + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; + if (_lvl < snap.max_level) { + _lvl++; + Type_1_node &node { _t1_blks.node(_vba, _lvl, _attr.in_vbd_degree) }; + calc_hash(_encoded_blk, node.hash); + node.pba = _new_pbas.pbas[_lvl - 1]; + _generate_write_blk_req(progress); + if (VERBOSE_VBD_EXTENSION) + log(" update lvl ", _lvl, " node ", tree_node_index(_vba, _lvl, _attr.in_vbd_degree), " ", node, + "\n write 2 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); + } else { + if (snap.gen < _attr.in_curr_gen) { + _snap_idx = _attr.in_out_snapshots.alloc_idx(_attr.in_curr_gen, _attr.in_last_secured_gen); + if (VERBOSE_VBD_EXTENSION) + log(" new snap ", _snap_idx); + } + Snapshot &new_snap = _attr.in_out_snapshots.items[_snap_idx]; + Number_of_leaves num_leaves { snap.nr_of_leaves + _attr.out_num_leaves }; + new_snap = { { }, _new_pbas.pbas[_lvl], _attr.in_curr_gen, num_leaves, snap.max_level, true, 0, false }; + calc_hash(_encoded_blk, new_snap.hash); + _helper.mark_succeeded(progress); + if (VERBOSE_VBD_EXTENSION) + log(" update snap ", _snap_idx, " ", new_snap); + } + break; + } + default: break; + } + return progress; +} + + +void Virtual_block_device::Extend_tree::_add_new_root_lvl_to_snap() { - Request &req { *_req_ptr }; Snapshot_index old_idx { _snap_idx }; Snapshot_index &idx { _snap_idx }; - Snapshot *snap { req._snapshots.items }; + Snapshot *snap { _attr.in_out_snapshots.items }; ASSERT(snap[idx].max_level < TREE_MAX_LEVEL); Tree_level_index new_lvl { snap[old_idx].max_level + 1 }; _t1_blks.items[new_lvl] = { }; _t1_blks.items[new_lvl].nodes[0] = { snap[idx].pba, snap[idx].gen, snap[idx].hash }; - if (snap[idx].gen < req._curr_gen) { - idx = req._snapshots.alloc_idx(req._curr_gen, req._last_secured_gen); + if (snap[idx].gen < _attr.in_curr_gen) { + idx = _attr.in_out_snapshots.alloc_idx(_attr.in_curr_gen, _attr.in_last_secured_gen); if (VERBOSE_VBD_EXTENSION) log(" new snap ", idx); } snap[idx] = { - { }, alloc_pba_from_range(req._pba, req._num_pbas), req._curr_gen, snap[old_idx].nr_of_leaves, + { }, alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas), _attr.in_curr_gen, snap[old_idx].nr_of_leaves, new_lvl, true, 0, false }; if (VERBOSE_VBD_EXTENSION) @@ -528,27 +658,26 @@ void Virtual_block_device_channel::_add_new_root_lvl_to_snap() } -void Virtual_block_device_channel::_add_new_branch_to_snap(Tree_level_index mount_lvl, Tree_node_index mount_node_idx) +void Virtual_block_device::Extend_tree::_add_new_branch_to_snap(Tree_level_index mount_lvl, Tree_node_index mount_node_idx) { - Request &req { *_req_ptr }; - req._num_leaves = 0; + _attr.out_num_leaves = 0; _lvl = mount_lvl; if (mount_lvl > 1) for (Tree_level_index lvl { 1 }; lvl < mount_lvl; lvl++) _t1_blks.items[lvl] = { }; - if (!req._num_pbas) + if (!_attr.in_out_num_pbas) return; for (Tree_level_index lvl { mount_lvl }; lvl > 0; lvl--) { _lvl = lvl; Tree_node_index node_idx { lvl == mount_lvl ? mount_node_idx : 0 }; auto try_add_node_at_lvl_and_node_idx = [&] () { - if (!req._num_pbas) + if (!_attr.in_out_num_pbas) return false; Type_1_node &node { _t1_blks.items[lvl].nodes[node_idx] }; - node = { alloc_pba_from_range(req._pba, req._num_pbas), INITIAL_GENERATION, { } }; + node = { alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas), INITIAL_GENERATION, { } }; if (VERBOSE_VBD_EXTENSION) log(" update lvl ", lvl, " node ", node_idx, " ", node); @@ -558,38 +687,48 @@ void Virtual_block_device_channel::_add_new_branch_to_snap(Tree_level_index moun if (!try_add_node_at_lvl_and_node_idx()) return; } else - for (; node_idx < req._snap_degr; node_idx++) { + for (; node_idx < _attr.in_snap_degr; node_idx++) { if (!try_add_node_at_lvl_and_node_idx()) return; - req._num_leaves++; + _attr.out_num_leaves++; } } } -void Virtual_block_device_channel::_set_new_pbas_identical_to_curr_pbas() +void Virtual_block_device::Extend_tree::_set_new_pbas_identical_to_curr_pbas() { + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; for (Tree_level_index lvl { 0 }; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) - if (lvl > snap().max_level) + if (lvl > snap.max_level) _new_pbas.pbas[lvl] = 0; - else if (lvl == snap().max_level) - _new_pbas.pbas[lvl] = snap().pba; + else if (lvl == snap.max_level) + _new_pbas.pbas[lvl] = snap.pba; else - _new_pbas.pbas[lvl] = _node(lvl + 1, _vba).pba; + _new_pbas.pbas[lvl] = _t1_blks.node(_vba, lvl + 1, _attr.in_vbd_degree).pba; } -void Virtual_block_device_channel::_generate_ft_alloc_req_for_resizing(Tree_level_index min_lvl, bool &progress) +void Virtual_block_device::Extend_tree::_generate_write_blk_req(bool &progress) { - Request &req { *_req_ptr }; - Snapshot &snap { req._snapshots.items[_snap_idx] }; + if (_lvl) { + _t1_blks.items[_lvl].encode_to_blk(_encoded_blk); + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _encoded_blk); + } else + _write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _data_blk); +} + + +void Virtual_block_device::Extend_tree::_generate_ft_alloc_req_for_resizing(Tree_level_index min_lvl, bool &progress) +{ + Snapshot &snap = _attr.in_out_snapshots.items[_snap_idx]; if (min_lvl > snap.max_level) { - _mark_req_failed(progress, "check parent lvl for alloc"); + _helper.mark_failed(progress, "check parent lvl for alloc"); return; } _num_blks = 0; - _free_gen = req._curr_gen; + _free_gen = _attr.in_curr_gen; for (Tree_level_index lvl = 0; lvl < TREE_MAX_NR_OF_LEVELS; lvl++) { if (lvl > snap.max_level) { @@ -600,7 +739,7 @@ void Virtual_block_device_channel::_generate_ft_alloc_req_for_resizing(Tree_leve _new_pbas.pbas[lvl] = 0; _t1_nodes.nodes[lvl] = { snap.pba, snap.gen, snap.hash }; } else { - Type_1_node &node { _node(lvl + 1, _vba) }; + Type_1_node &node { _t1_blks.node(_vba, lvl + 1, _attr.in_vbd_degree) }; if (lvl >= min_lvl) { _num_blks++; _new_pbas.pbas[lvl] = 0; @@ -622,155 +761,9 @@ void Virtual_block_device_channel::_generate_ft_alloc_req_for_resizing(Tree_leve } } } - _generate_ft_req(ALLOC_PBAS_SUCCEEDED, progress, Free_tree_request::ALLOC_FOR_NON_RKG); -} - - -void Virtual_block_device_channel::_request_submitted(Module_request &req) -{ - _req_ptr = static_cast(&req); - _state = SUBMITTED; -} - - -void Virtual_block_device_channel::_extension_step(bool &progress) -{ - Request &req { *_req_ptr }; - switch (_state) { - case State::SUBMITTED: - - req._num_leaves = 0; - _snap_idx = req._snapshots.newest_snap_idx(); - _vba = snap().nr_of_leaves; - _lvl = snap().max_level; - _old_pbas.pbas[_lvl] = snap().pba; - if (_vba <= tree_max_max_vba(req._snap_degr, snap().max_level)) { - _generate_req(READ_BLK_SUCCEEDED, progress, snap().pba, _encoded_blk); - if (VERBOSE_VBD_EXTENSION) - log(" read lvl ", _lvl, " parent snap ", _snap_idx, " ", snap()); - } else { - _add_new_root_lvl_to_snap(); - _add_new_branch_to_snap(req._snapshots.items[_snap_idx].max_level, 1); - _set_new_pbas_identical_to_curr_pbas(); - _generate_write_blk_req(progress); - if (VERBOSE_VBD_EXTENSION) - log(" write 1 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); - } - break; - - case READ_BLK_SUCCEEDED: - { - _t1_blks.items[_lvl].decode_from_blk(_encoded_blk); - if (_lvl == snap().max_level) { - if (!check_hash(_encoded_blk, snap().hash)) { - _mark_req_failed(progress, "check root node hash"); - break; - } - } else { - if (!check_hash(_encoded_blk, _node(_lvl + 1, _vba).hash)) { - _mark_req_failed(progress, "check inner node hash"); - break; - } - } - Tree_node_index node_idx { _node_idx(_lvl, _vba) }; - if (_lvl > 1) { - Type_1_node &node { _node(_lvl, _vba) }; - if (node.valid()) { - _old_pbas.pbas[_lvl - 1] = node.pba; - _generate_req(READ_BLK_SUCCEEDED, progress, node.pba, _encoded_blk); - if (VERBOSE_VBD_EXTENSION) - log(" read lvl ", _lvl - 1, " parent lvl ", _lvl, " node ", node_idx, " ", node); - _lvl--; - } else { - _add_new_branch_to_snap(_lvl, node_idx); - _generate_ft_alloc_req_for_resizing(_lvl, progress); - } - } else { - _add_new_branch_to_snap(_lvl, node_idx); - _generate_ft_alloc_req_for_resizing(_lvl, progress); - } - break; - } - case ALLOC_PBAS_SUCCEEDED: - { - if (VERBOSE_VBD_EXTENSION) { - log(" allocated ", _num_blks, " pbas"); - for (Tree_level_index lvl { 0 }; lvl < snap().max_level; lvl++) - log(" lvl ", lvl, " ", _t1_nodes.nodes[lvl], " -> pba ", _new_pbas.pbas[lvl]); - - log(" write 1 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); - } - _generate_write_blk_req(progress); - break; - } - case WRITE_BLK_SUCCEEDED: - { - if (_lvl < snap().max_level) { - _lvl++; - Type_1_node &node { _node(_lvl, _vba) }; - calc_hash(_encoded_blk, node.hash); - node.pba = _new_pbas.pbas[_lvl - 1]; - _generate_write_blk_req(progress); - if (VERBOSE_VBD_EXTENSION) - log(" update lvl ", _lvl, " node ", _node_idx(_lvl, _vba), " ", node, "\n write 2 lvl ", _lvl, " pba ", _new_pbas.pbas[_lvl]); - } else { - Snapshot &old_snap { snap() }; - if (snap().gen < req._curr_gen) { - _snap_idx = req._snapshots.alloc_idx(req._curr_gen, req._last_secured_gen); - if (VERBOSE_VBD_EXTENSION) - log(" new snap ", _snap_idx); - } - Number_of_leaves num_leaves { old_snap.nr_of_leaves + req._num_leaves }; - snap() = { { }, _new_pbas.pbas[_lvl], req._curr_gen, num_leaves, old_snap.max_level, true, 0, false }; - calc_hash(_encoded_blk, snap().hash); - _mark_req_successful(progress); - if (VERBOSE_VBD_EXTENSION) - log(" update snap ", _snap_idx, " ", snap()); - } - break; - } - default: break; - } -} - - -void Virtual_block_device_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - switch (_req_ptr->_type) { - case Request::READ_VBA: _read_vba(progress); break; - case Request::WRITE_VBA: _write_vba(progress); break; - case Request::REKEY_VBA: _rekey_vba(progress); break; - case Request::EXTENSION_STEP: _extension_step(progress); break; - } -} - - -void Virtual_block_device::execute(bool &progress) -{ - for_each_channel([&] (Channel &chan) { - chan.execute(progress); }); -} - - -void Virtual_block_device_channel::_generate_ft_req(State complete_state, bool progress, Free_tree_request::Type type) -{ - Request &req { *_req_ptr }; - _generate_req( - complete_state, progress, type, req._ft, req._mt, req._snapshots, req._last_secured_gen, req._curr_gen, - _free_gen, _num_blks, _new_pbas, _t1_nodes, req._snapshots.items[_snap_idx].max_level, _vba, req._vbd_degree, - req._vbd_highest_vba, req._rekeying, req._prev_key_id, req._curr_key_id, req._rekeying_vba, *(Physical_block_address*)0, - *(Number_of_blocks*)0); -} - - -Virtual_block_device::Virtual_block_device() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } + _alloc_pbas.generate( + _helper, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED, progress, _attr.in_out_ft, _attr.in_out_mt, _attr.in_out_snapshots, + _attr.in_last_secured_gen, _attr.in_curr_gen, _free_gen, _num_blks, _new_pbas, _t1_nodes, + snap.max_level, _vba, _attr.in_vbd_degree, _attr.in_vbd_highest_vba, _attr.in_rekeying, + _attr.in_prev_key_id, 0, _attr.in_rekeying_vba, Free_tree::Allocate_pbas::NON_REKEYING); } diff --git a/repos/gems/src/lib/vfs/tresor/splitter.cc b/repos/gems/src/lib/vfs/tresor/splitter.cc deleted file mode 100644 index caabf35828..0000000000 --- a/repos/gems/src/lib/vfs/tresor/splitter.cc +++ /dev/null @@ -1,225 +0,0 @@ -/* - * \brief Module for splitting unaligned/uneven I/O requests - * \author Martin Stein - * \author Josef Soentgen - * \date 2023-09-11 - */ - -/* - * Copyright (C) 2023 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. - */ - -/* vfs tresor includes */ -#include - -using namespace Tresor; - -Splitter_request::Splitter_request(Module_id src_mod, Module_channel_id src_chan, Operation op, bool &success, - Request_offset off, Byte_range_ptr const &buf, Key_id key_id, Generation gen) -: - Module_request { src_mod, src_chan, SPLITTER }, _op { op }, _off { off }, _key_id { key_id }, _gen { gen }, - _buf { buf.start, buf.num_bytes }, _success { success } -{ } - - -char const *Splitter_request::op_to_string(Operation op) -{ - switch (op) { - case Operation::READ: return "read"; - case Operation::WRITE: return "write"; - } - ASSERT_NEVER_REACHED; -} - - -void Splitter_channel::_generated_req_completed(State_uint state_uint) -{ - if (!_generated_req_success) { - error("splitter: request (", *_req_ptr, ") failed because generated request failed)"); - _req_ptr->_success = false; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - return; - } - _state = (State)state_uint; -} - - -void Splitter_channel::_mark_req_successful(bool &progress) -{ - Request &req { *_req_ptr }; - req._success = true; - _state = REQ_COMPLETE; - _req_ptr = nullptr; - progress = true; -} - - -void Splitter_channel::_request_submitted(Module_request &req) -{ - _req_ptr = static_cast(&req); - _state = REQ_SUBMITTED; -} - - -void Splitter_channel::_advance_curr_off(addr_t advance, Tresor::Request::Operation op, bool &progress) -{ - Splitter_request &req { *_req_ptr }; - _curr_off += advance; - if (!_num_remaining_bytes()) { - _mark_req_successful(progress); - } else if (_curr_off % BLOCK_SIZE) { - _curr_buf_addr = (addr_t)&_blk; - _generate_req( - PROTRUDING_FIRST_BLK_READ, progress, Tresor::Request::READ, _curr_vba(), 0, 1, req._key_id, id(), _gen); - } else if (_num_remaining_bytes() < BLOCK_SIZE) { - _curr_buf_addr = (addr_t)&_blk; - _generate_req( - PROTRUDING_LAST_BLK_READ, progress, Tresor::Request::READ, _curr_vba(), 0, 1, req._key_id, id(), _gen); - } else { - _curr_buf_addr = (addr_t)req._buf.start + _curr_buf_off(); - _generate_req( - INSIDE_BLKS_ACCESSED, progress, op, _curr_vba(), 0, _num_remaining_bytes() / BLOCK_SIZE, req._key_id, id(), _gen); - } -} - - -void Splitter_channel::_write(bool &progress) -{ - Splitter_request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - _curr_off = 0; - _gen = req._gen; - _advance_curr_off(req._off, Tresor::Request::WRITE, progress); - break; - - case PROTRUDING_FIRST_BLK_READ: - { - size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; - size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; - memcpy((void *)((addr_t)&_blk + num_outside_bytes), req._buf.start, num_inside_bytes); - _curr_buf_addr = (addr_t)&_blk; - _generate_req( - PROTRUDING_FIRST_BLK_WRITTEN, progress, Tresor::Request::WRITE, _curr_vba(), 0, 1, req._key_id, id(), _gen); - break; - } - case PROTRUDING_FIRST_BLK_WRITTEN: - { - size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; - size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; - _advance_curr_off(num_inside_bytes, Tresor::Request::WRITE, progress); - break; - } - case INSIDE_BLKS_ACCESSED: - - _advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, Tresor::Request::WRITE, progress); - break; - - case PROTRUDING_LAST_BLK_READ: - - memcpy(&_blk, (void *)((addr_t)req._buf.start + _curr_buf_off()), _num_remaining_bytes()); - _curr_buf_addr = (addr_t)&_blk; - _generate_req( - PROTRUDING_LAST_BLK_WRITTEN, progress, Tresor::Request::WRITE, _curr_vba(), 0, 1, req._key_id, id(), _gen); - break; - - case PROTRUDING_LAST_BLK_WRITTEN: _advance_curr_off(_num_remaining_bytes(), Tresor::Request::WRITE, progress); break; - default: break; - } -} - - -void Splitter_channel::_read(bool &progress) -{ - Splitter_request &req { *_req_ptr }; - switch (_state) { - case REQ_SUBMITTED: - - _curr_off = 0; - _gen = req._gen; - _advance_curr_off(req._off, Tresor::Request::READ, progress); - break; - - case PROTRUDING_FIRST_BLK_READ: - { - size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; - size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; - memcpy(req._buf.start, (void *)((addr_t)&_blk + num_outside_bytes), num_inside_bytes); - _advance_curr_off(num_inside_bytes, Tresor::Request::READ, progress); - break; - } - case INSIDE_BLKS_ACCESSED: - - _advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, Tresor::Request::READ, progress); - break; - - case PROTRUDING_LAST_BLK_READ: - - memcpy((void *)((addr_t)req._buf.start + _curr_buf_off()), &_blk, _num_remaining_bytes()); - _advance_curr_off(_num_remaining_bytes(), Tresor::Request::READ, progress); - break; - - default: break; - } -} - - -void Splitter_channel::execute(bool &progress) -{ - if (!_req_ptr) - return; - - switch (_req_ptr->_op) { - case Request::READ: _read(progress); break; - case Request::WRITE: _write(progress); break; - } -} - - -Block &Splitter_channel::_blk_buf_for_vba(Virtual_block_address vba) -{ - ASSERT(_state == REQ_GENERATED); - return *(Block *)(_curr_buf_addr + (vba - _curr_vba()) * BLOCK_SIZE); -} - - -Block const &Splitter::src_for_writing_vba(Request_tag tag, Virtual_block_address vba) -{ - Block const *blk_ptr { }; - with_channel(tag, [&] (Splitter_channel &chan) { - blk_ptr = &chan.src_for_writing_vba(vba); }); - ASSERT(blk_ptr); - return *blk_ptr; -} - - -Block &Splitter::dst_for_reading_vba(Request_tag tag, Virtual_block_address vba) -{ - Block *blk_ptr { }; - with_channel(tag, [&] (Splitter_channel &chan) { - blk_ptr = &chan.dst_for_reading_vba(vba); }); - ASSERT(blk_ptr); - return *blk_ptr; -} - - -Splitter::Splitter() -{ - Module_channel_id id { 0 }; - for (Constructible &chan : _channels) { - chan.construct(id++); - add_channel(*chan); - } -} - - -void Splitter::execute(bool &progress) -{ - for_each_channel([&] (Splitter_channel &chan) { - chan.execute(progress); }); -} diff --git a/repos/gems/src/lib/vfs/tresor/splitter.h b/repos/gems/src/lib/vfs/tresor/splitter.h index bf244687b9..ff6fd528e0 100644 --- a/repos/gems/src/lib/vfs/tresor/splitter.h +++ b/repos/gems/src/lib/vfs/tresor/splitter.h @@ -16,141 +16,393 @@ #define _TRESOR__IO_SPLITTER_H_ /* tresor includes */ -#include +#include -namespace Tresor { +namespace Tresor { class Splitter; } - struct Lookup_buffer : Genode::Interface - { - virtual Block const &src_for_writing_vba(Request_tag, Virtual_block_address) = 0; - virtual Block &dst_for_reading_vba(Request_tag, Virtual_block_address) = 0; - }; - - class Splitter_request; - class Splitter_channel; - class Splitter; -} - - -class Tresor::Splitter_request : public Tresor::Module_request +struct Tresor::Splitter : Noncopyable { - friend class Splitter_channel; - public: - enum Operation { READ, WRITE }; + class Read : Noncopyable + { + public: + + using Module = Splitter; + + struct Attr + { + Request_offset const in_off; + Generation const in_gen; + char *const in_buf_start; + size_t const in_buf_num_bytes; + }; + + struct Execute_attr + { + Superblock_control &sb_control; + Virtual_block_device &vbd; + Client_data_interface &client_data; + Block_io &block_io; + Crypto &crypto; + }; + + private: + + enum State { + INIT, COMPLETE, READ_FIRST_VBA, READ_FIRST_VBA_SUCCEEDED, READ_LAST_VBA, READ_LAST_VBA_SUCCEEDED, + READ_MIDDLE_VBAS, READ_MIDDLE_VBAS_SUCCEEDED }; + + Request_helper _helper; + Attr const _attr; + addr_t _curr_off { }; + addr_t _curr_buf_addr { }; + Block _blk { }; + Generation _gen { }; + Constructible _read_vbas { }; + + Virtual_block_address _curr_vba() const { return (Virtual_block_address)(_curr_off / BLOCK_SIZE); } + + void _generate_read(State target_state, bool &progress) + { + Number_of_blocks num_blocks = + target_state == READ_MIDDLE_VBAS ? _num_remaining_bytes() / BLOCK_SIZE : 1; + + _read_vbas.construct(Superblock_control::Read_vbas::Attr{_curr_vba(), num_blocks, 0, 0}); + _helper.state = target_state; + progress = true; + } + + bool _execute_read(State succeeded_state, Execute_attr const &attr) + { + bool progress = attr.sb_control.execute(*_read_vbas, attr.vbd, attr.client_data, attr.block_io, attr.crypto); + if (_read_vbas->complete()) { + if (_read_vbas->success()) + _helper.generated_req_succeeded(succeeded_state, progress); + else + _helper.generated_req_failed(progress); + } + return progress; + } + + addr_t _curr_buf_off() const + { + ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes); + return _curr_off - _attr.in_off; + } + + addr_t _num_remaining_bytes() const + { + ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes); + return _attr.in_off + _attr.in_buf_num_bytes - _curr_off; + } + + void _advance_curr_off(size_t advance, bool &progress) + { + _curr_off += advance; + if (!_num_remaining_bytes()) { + _helper.mark_succeeded(progress); + } else if (_curr_off % BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_read(READ_FIRST_VBA, progress); + } else if (_num_remaining_bytes() < BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_read(READ_LAST_VBA, progress); + } else { + _curr_buf_addr = (addr_t)_attr.in_buf_start + _curr_buf_off(); + _generate_read(READ_MIDDLE_VBAS, progress); + } + } + + public: + + Read(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "read"); } + + bool execute(Execute_attr const &attr) + { + bool progress = false; + switch (_helper.state) { + case INIT: + + _gen = _attr.in_gen; + _advance_curr_off(_attr.in_off, progress); + break; + + case READ_FIRST_VBA: progress |= _execute_read(READ_FIRST_VBA_SUCCEEDED, attr); break; + case READ_FIRST_VBA_SUCCEEDED: + { + size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; + size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; + memcpy(_attr.in_buf_start, (void *)((addr_t)&_blk + num_outside_bytes), num_inside_bytes); + _advance_curr_off(num_inside_bytes, progress); + break; + } + case READ_MIDDLE_VBAS: progress |= _execute_read(READ_MIDDLE_VBAS_SUCCEEDED, attr); break; + case READ_MIDDLE_VBAS_SUCCEEDED: + + _advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, progress); + break; + + case READ_LAST_VBA: progress |= _execute_read(READ_LAST_VBA_SUCCEEDED, attr); break; + case READ_LAST_VBA_SUCCEEDED: + + memcpy((void *)((addr_t)_attr.in_buf_start + _curr_buf_off()), &_blk, _num_remaining_bytes()); + _advance_curr_off(_num_remaining_bytes(), progress); + break; + + default: break; + } + return progress; + } + + Block &destination_buffer(Virtual_block_address vba) + { + return *(Block *)(_curr_buf_addr + (vba - _curr_vba()) * BLOCK_SIZE); + } + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; + + class Write : Noncopyable + { + public: + + using Module = Splitter; + + struct Attr + { + Request_offset const in_off; + Generation const in_gen; + char const *const in_buf_start; + size_t const in_buf_num_bytes; + }; + + struct Execute_attr + { + Superblock_control &sb_control; + Virtual_block_device &vbd; + Client_data_interface &client_data; + Block_io &block_io; + Free_tree &free_tree; + Meta_tree &meta_tree; + Crypto &crypto; + }; + + private: + + enum State { + INIT, COMPLETE, READ_FIRST_VBA, READ_FIRST_VBA_SUCCEEDED, READ_LAST_VBA, READ_LAST_VBA_SUCCEEDED, + WRITE_FIRST_VBA, WRITE_FIRST_VBA_SUCCEEDED, WRITE_LAST_VBA, WRITE_LAST_VBA_SUCCEEDED, + WRITE_MIDDLE_VBAS, WRITE_MIDDLE_VBAS_SUCCEEDED }; + + + Request_helper _helper; + Attr const _attr; + addr_t _curr_off { }; + addr_t _curr_buf_addr { }; + Block _blk { }; + Generation _gen { }; + Constructible _read_vbas { }; + Constructible _write_vbas { }; + + Virtual_block_address _curr_vba() const { return (Virtual_block_address)(_curr_off / BLOCK_SIZE); } + + addr_t _curr_buf_off() const + { + ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes); + return _curr_off - _attr.in_off; + } + + addr_t _num_remaining_bytes() const + { + ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes); + return _attr.in_off + _attr.in_buf_num_bytes - _curr_off; + } + + void _generate_sb_control_request(State target_state, bool &progress) + { + Number_of_blocks num_blocks = + target_state == WRITE_MIDDLE_VBAS ? _num_remaining_bytes() / BLOCK_SIZE : 1; + + switch (target_state) { + case READ_FIRST_VBA: + case READ_LAST_VBA: _read_vbas.construct(Superblock_control::Read_vbas::Attr{_curr_vba(), num_blocks, 0, 0}); break; + case WRITE_FIRST_VBA: + case WRITE_MIDDLE_VBAS: + case WRITE_LAST_VBA: _write_vbas.construct(Superblock_control::Write_vbas::Attr{_curr_vba(), num_blocks, 0, 0}); break; + default: ASSERT_NEVER_REACHED; + } + _helper.state = target_state; + progress = true; + } + + void _advance_curr_off(size_t advance, bool &progress) + { + _curr_off += advance; + if (!_num_remaining_bytes()) { + _helper.mark_succeeded(progress); + } else if (_curr_off % BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_sb_control_request(READ_FIRST_VBA, progress); + } else if (_num_remaining_bytes() < BLOCK_SIZE) { + _curr_buf_addr = (addr_t)&_blk; + _generate_sb_control_request(READ_LAST_VBA, progress); + } else { + _curr_buf_addr = (addr_t)_attr.in_buf_start + _curr_buf_off(); + _generate_sb_control_request(WRITE_MIDDLE_VBAS, progress); + } + } + + bool _execute_read(State succeeded_state, Execute_attr const &attr) + { + bool progress = attr.sb_control.execute(*_read_vbas, attr.vbd, attr.client_data, attr.block_io, attr.crypto); + if (_read_vbas->complete()) { + if (_read_vbas->success()) + _helper.generated_req_succeeded(succeeded_state, progress); + else + _helper.generated_req_failed(progress); + } + return progress; + } + + bool _execute_write(State succeeded_state, Execute_attr const &attr) + { + bool progress = attr.sb_control.execute(*_write_vbas, attr.vbd, attr.client_data, attr.block_io, attr.free_tree, attr.meta_tree, attr.crypto); + if (_write_vbas->complete()) { + if (_write_vbas->success()) + _helper.generated_req_succeeded(succeeded_state, progress); + else + _helper.generated_req_failed(progress); + } + return progress; + } + + public: + + Write(Attr const &attr) : _helper(*this), _attr(attr) { } + + void print(Output &out) const { Genode::print(out, "write"); } + + bool execute(Execute_attr const &attr) + { + bool progress = false; + switch (_helper.state) { + case INIT: + + _gen = _attr.in_gen; + _advance_curr_off(_attr.in_off, progress); + break; + + case READ_FIRST_VBA: progress |= _execute_read(READ_FIRST_VBA_SUCCEEDED, attr); break; + case READ_FIRST_VBA_SUCCEEDED: + { + size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; + size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; + memcpy((void *)((addr_t)&_blk + num_outside_bytes), _attr.in_buf_start, num_inside_bytes); + _curr_buf_addr = (addr_t)&_blk; + _generate_sb_control_request(WRITE_FIRST_VBA, progress); + break; + } + case WRITE_FIRST_VBA: progress |= _execute_write(WRITE_FIRST_VBA_SUCCEEDED, attr); break; + case WRITE_FIRST_VBA_SUCCEEDED: + { + size_t num_outside_bytes { _curr_off % BLOCK_SIZE }; + size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) }; + _advance_curr_off(num_inside_bytes, progress); + break; + } + case WRITE_MIDDLE_VBAS: progress |= _execute_write(WRITE_MIDDLE_VBAS_SUCCEEDED, attr); break; + case WRITE_MIDDLE_VBAS_SUCCEEDED: + + _advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, progress); + break; + + case READ_LAST_VBA: progress |= _execute_read(READ_LAST_VBA_SUCCEEDED, attr); break; + case READ_LAST_VBA_SUCCEEDED: + + memcpy(&_blk, (void *)((addr_t)_attr.in_buf_start + _curr_buf_off()), _num_remaining_bytes()); + _curr_buf_addr = (addr_t)&_blk; + _generate_sb_control_request(WRITE_LAST_VBA, progress); + break; + + case WRITE_LAST_VBA: progress |= _execute_write(WRITE_LAST_VBA_SUCCEEDED, attr); break; + case WRITE_LAST_VBA_SUCCEEDED: _advance_curr_off(_num_remaining_bytes(), progress); break; + default: break; + } + return progress; + } + + Block const &source_buffer(Virtual_block_address vba) + { + return *(Block *)(_curr_buf_addr + (vba - _curr_vba()) * BLOCK_SIZE); + } + + Block &destination_buffer() + { + ASSERT(_helper.state == READ_FIRST_VBA || _helper.state == READ_LAST_VBA); + return _blk; + } + + bool complete() const { return _helper.complete(); } + bool success() const { return _helper.success(); } + }; private: - Operation const _op; - Request_offset const _off; - Key_id const _key_id; - Generation const _gen; - Byte_range_ptr const _buf; - bool &_success; - - NONCOPYABLE(Splitter_request); + Read *_read_ptr { }; + Write *_write_ptr { }; public: - Splitter_request(Module_id, Module_channel_id, Operation, bool &, Request_offset, Byte_range_ptr const &, Key_id, Generation); - - static char const *op_to_string(Operation); - - void print(Genode::Output &out) const override { Genode::print(out, op_to_string(_op), " off ", _off, " size ", _buf.num_bytes); } -}; - - -class Tresor::Splitter_channel : public Tresor::Module_channel -{ - private: - - using Request = Splitter_request; - - - enum State : State_uint { - PROTRUDING_FIRST_BLK_WRITTEN, PROTRUDING_LAST_BLK_WRITTEN, PROTRUDING_FIRST_BLK_READ, PROTRUDING_LAST_BLK_READ, INSIDE_BLKS_ACCESSED, - REQ_SUBMITTED, REQ_GENERATED, REQ_COMPLETE }; - - State _state { }; - Request *_req_ptr { }; - addr_t _curr_off { }; - addr_t _curr_buf_addr { }; - Block _blk { }; - Generation _gen { }; - bool _generated_req_success { }; - - NONCOPYABLE(Splitter_channel); - - void _generated_req_completed(State_uint) override; - - void _request_submitted(Module_request &) override; - - bool _request_complete() override { return _state == REQ_COMPLETE; } - - Virtual_block_address _curr_vba() const { return (Virtual_block_address)(_curr_off / BLOCK_SIZE); } - - addr_t _curr_buf_off() const + bool execute(Read &req, Read::Execute_attr const &attr) { - ASSERT(_curr_off >= _req_ptr->_off && _curr_off <= _req_ptr->_off + _req_ptr->_buf.num_bytes); - return _curr_off - _req_ptr->_off; + if (!_read_ptr && !_write_ptr) + _read_ptr = &req; + + if (_read_ptr != &req) + return false; + + bool progress = req.execute(attr); + if (req.complete()) + _read_ptr = nullptr; + + return progress; } - addr_t _num_remaining_bytes() const + bool execute(Write &req, Write::Execute_attr const &attr) { - ASSERT(_curr_off >= _req_ptr->_off && _curr_off <= _req_ptr->_off + _req_ptr->_buf.num_bytes); - return _req_ptr->_off + _req_ptr->_buf.num_bytes - _curr_off; + if (!_write_ptr && !_write_ptr) + _write_ptr = &req; + + if (_write_ptr != &req) + return false; + + bool progress = req.execute(attr); + if (req.complete()) + _write_ptr = nullptr; + + return progress; } - template - void _generate_req(State_uint state, bool &progress, ARGS &&... args) + Block const &source_buffer(Virtual_block_address vba) { - _state = REQ_GENERATED; - generate_req(state, progress, args..., _generated_req_success); + ASSERT(_write_ptr); + return _write_ptr->source_buffer(vba); } - void _mark_req_successful(bool &); + Block &destination_buffer(Virtual_block_address vba) + { + if (_read_ptr) + return _read_ptr->destination_buffer(vba); + if (_write_ptr) + return _write_ptr->destination_buffer(); + ASSERT_NEVER_REACHED; + } - void _advance_curr_off(addr_t, Tresor::Request::Operation, bool &); - - void _read(bool &progress); - - void _write(bool &progress); - - Block &_blk_buf_for_vba(Virtual_block_address); - - public: - - Splitter_channel(Module_channel_id id) : Module_channel { SPLITTER, id } { } - - void execute(bool &progress); - - Block const &src_for_writing_vba(Virtual_block_address vba) { return _blk_buf_for_vba(vba); } - - Block &dst_for_reading_vba(Virtual_block_address vba) { return _blk_buf_for_vba(vba); } + static constexpr char const *name() { return "sb_control"; } }; - -class Tresor::Splitter : public Tresor::Module, public Tresor::Lookup_buffer -{ - private: - - using Channel = Splitter_channel; - - Constructible _channels[1] { }; - - NONCOPYABLE(Splitter); - - public: - - Splitter(); - - void execute(bool &) override; - - Block const &src_for_writing_vba(Request_tag, Virtual_block_address) override; - - Block &dst_for_reading_vba(Request_tag, Virtual_block_address) override; -}; - - #endif /* _TRESOR__IO_SPLITTER_H_ */ diff --git a/repos/gems/src/lib/vfs/tresor/vfs.cc b/repos/gems/src/lib/vfs/tresor/vfs.cc index 87474c3f49..e918404e87 100644 --- a/repos/gems/src/lib/vfs/tresor/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor/vfs.cc @@ -21,2370 +21,1517 @@ /* tresor includes */ #include -#include +#include #include #include #include -#include #include #include #include -#include "splitter.h" +/* vfs tresor includes */ +#include + +using namespace Genode; +using namespace Vfs; +using namespace Tresor; namespace Vfs_tresor { - using namespace Vfs; - using namespace Genode; - using namespace Tresor; + class Request_interface; + class Data_operation; class Data_file_system; - + class Extend_operation; class Extend_file_system; - class Extend_progress_file_system; + class Rekey_operation; class Rekey_file_system; - class Rekey_progress_file_system; + class Deinitialize_operation; class Deinitialize_file_system; - class Create_snapshot_file_system; - class Discard_snapshot_file_system; + class Control_local_factory; + class Control_file_system; + class Current_local_factory; + class Current_file_system; + class Local_factory; + class File_system; + class Plugin; +} - struct Control_local_factory; - class Control_file_system; - - struct Snapshot_local_factory; - class Snapshot_file_system; - - struct Snapshots_local_factory; - class Snapshots_file_system; - - struct Local_factory; - class File_system; - - class Client_data; - class Wrapper; - - template - class Pointer - { - private: - - T *_obj; - - public: - - struct Invalid : Genode::Exception { }; - - Pointer() : _obj(nullptr) { } - - Pointer(T &obj) : _obj(&obj) { } - - T &obj() const - { - if (_obj == nullptr) - throw Invalid(); - - return *_obj; - } - - bool valid() const { return _obj != nullptr; } - }; -} /* namespace Vfs_tresor */ - - -class Vfs_tresor::Client_data : public Tresor::Module, public Tresor::Module_channel +class Vfs_tresor::Data_operation : private Noncopyable { + public: + + enum Result { PENDING, SUCCEEDED, FAILED }; + + struct Execute_attr + { + Splitter &splitter; + Superblock_control &sb_control; + Client_data_interface &client_data; + Virtual_block_device &vbd; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + }; + private: - using Request = Client_data_request; + enum State { + INIT, READ_REQUESTED, READ_STARTED, READ, READ_COMPLETE, WRITE_REQUESTED, WRITE_STARTED, WRITE, + WRITE_COMPLETE, SYNC_REQUESTED, SYNC_STARTED, SYNC, SYNC_COMPLETE }; - Lookup_buffer &_lookup; + State _state { INIT }; + bool const _verbose; + Generation _generation { }; + addr_t _seek { }; + bool _success { }; + Constructible _dst { }; + Constructible _src { }; + Constructible _write { }; + Constructible _read { }; + Constructible _sync { }; - NONCOPYABLE(Client_data); - - void _request_submitted(Module_request &mod_req) override + bool _range_violation(Superblock_control &sb_control, addr_t start, size_t num_bytes) const { - Request &req { *static_cast(&mod_req) }; - switch (req._type) { - case Request::OBTAIN_PLAINTEXT_BLK: - { - req._blk = _lookup.src_for_writing_vba(req._req_tag, req._vba); - req._success = true; - break; - } - case Request::SUPPLY_PLAINTEXT_BLK: - { - _lookup.dst_for_reading_vba(req._req_tag, req._vba) = req._blk; - req._success = true; - break; - } } + addr_t last_byte = num_bytes ? start - 1 + num_bytes : start; + addr_t last_file_byte = (sb_control.max_vba() * BLOCK_SIZE) + (BLOCK_SIZE - 1); + return last_byte > last_file_byte; } - bool _request_complete() override { return true; } - public: - Client_data(Lookup_buffer &lb) : Module_channel { CLIENT_DATA, 0 }, _lookup { lb } { add_channel(*this);} + Data_operation(bool verbose) : _verbose(verbose) { } + + Result write(addr_t seek, Const_byte_range_ptr const &src) + { + switch (_state) { + case INIT: + + _seek = seek; + _src.construct(src.start, src.num_bytes); + _state = WRITE_REQUESTED; + if (_verbose) + log("write (seek ", _seek, " num_bytes ", _src->num_bytes, ") requested"); + return PENDING; + + case WRITE_REQUESTED: + case WRITE_STARTED: + case WRITE: return PENDING; + case WRITE_COMPLETE: + + _src.destruct(); + _state = INIT; + return _success ? SUCCEEDED : FAILED; + + default: break; + } + ASSERT_NEVER_REACHED; + } + + Result read(addr_t seek, Byte_range_ptr const &dst) + { + switch (_state) { + case INIT: + + _seek = seek; + _dst.construct(dst.start, dst.num_bytes); + _state = READ_REQUESTED; + if (_verbose) + log("read (seek ", _seek, " num_bytes ", _dst->num_bytes, ") requested"); + return PENDING; + + case READ_REQUESTED: + case READ_STARTED: + case READ: return PENDING; + case READ_COMPLETE: + + _dst.destruct(); + _state = INIT; + return _success ? SUCCEEDED : FAILED; + + default: break; + } + ASSERT_NEVER_REACHED; + } + + Result sync() + { + switch (_state) { + case INIT: + + _state = SYNC_REQUESTED; + if (_verbose) + log("sync requested"); + return PENDING; + + case SYNC_REQUESTED: + case SYNC_STARTED: + case SYNC: return PENDING; + case SYNC_COMPLETE: + + _state = INIT; + return _success ? SUCCEEDED : FAILED; + + default: break; + } + ASSERT_NEVER_REACHED; + } + + bool complete() const { return _state == WRITE_COMPLETE || _state == READ_COMPLETE || _state == SYNC_COMPLETE; } + + bool requested() const { return _state == WRITE_REQUESTED || _state == READ_REQUESTED || _state == SYNC_REQUESTED; } + + void start() + { + switch (_state) { + case WRITE_REQUESTED: _state = WRITE_STARTED; break; + case READ_REQUESTED: _state = READ_STARTED; break; + case SYNC_REQUESTED: _state = SYNC_STARTED; break; + default: ASSERT_NEVER_REACHED; + } + } + + bool execute(Execute_attr const &attr) + { + bool progress = false; + switch (_state) { + case WRITE_STARTED: + + if (_range_violation(attr.sb_control, _seek, _src->num_bytes)) { + _success = false; + _state = WRITE_COMPLETE; + progress = true; + if (_verbose) + log("write (seek ", _seek, " num_bytes ", _src->num_bytes, ") failed: range violation"); + break; + } + _write.construct(Splitter::Write::Attr{_seek, _generation, _src->start, _src->num_bytes}); + _state = WRITE; + progress = true; + if (_verbose) + log("write (seek ", _seek, " num_bytes ", _src->num_bytes, ") started"); + break; + + case WRITE: + + progress |= attr.splitter.execute( + *_write, {attr.sb_control, attr.vbd, attr.client_data, attr.block_io, + attr.free_tree, attr.meta_tree, attr.crypto}); + + if (_write->complete()) { + _success = _write->success(); + _write.destruct(); + _state = WRITE_COMPLETE; + progress = true; + if (_verbose) + log("write (seek ", _seek, " num_bytes ", _src->num_bytes, ") ", _success ? "succeeded" : "failed"); + } + break; + + case READ_STARTED: + + if (_range_violation(attr.sb_control, _seek, _dst->num_bytes)) { + _success = false; + _state = READ_COMPLETE; + progress = true; + if (_verbose) + log("read (seek ", _seek, " num_bytes ", _dst->num_bytes, ") failed: range violation"); + break; + } + _read.construct(Splitter::Read::Attr{_seek, _generation, _dst->start, _dst->num_bytes}); + _state = READ; + progress = true; + if (_verbose) + log("read (seek ", _seek, " num_bytes ", _dst->num_bytes, ") started"); + break; + + case READ: + + progress |= attr.splitter.execute( + *_read, {attr.sb_control, attr.vbd, attr.client_data, attr.block_io, attr.crypto}); + + if (_read->complete()) { + _success = _read->success(); + _read.destruct(); + _state = READ_COMPLETE; + progress = true; + if (_verbose) + log("read (seek ", _seek, " num_bytes ", _dst->num_bytes, ") ", _success ? "succeeded" : "failed"); + } + break; + + case SYNC_STARTED: + + _sync.construct(Superblock_control::Synchronize::Attr{}); + _state = SYNC; + progress = true; + if (_verbose) + log("sync started"); + break; + + case SYNC: + + progress |= attr.sb_control.execute(*_sync, attr.block_io, attr.trust_anchor); + if (_sync->complete()) { + _success = _sync->success(); + _sync.destruct(); + _state = SYNC_COMPLETE; + progress = true; + if (_verbose) + log("sync ", _success ? "succeeded" : "failed"); + } + break; + + default: break; + } + return progress; + } }; +class Vfs_tresor::Rekey_operation : private Noncopyable +{ + public: -class Vfs_tresor::Wrapper -: - private Tresor::Module_composition, - public Tresor::Module + enum Result { NONE, SUCCEEDED, FAILED, PENDING }; + + struct Execute_attr + { + Rekey_file_system *rekey_fs_ptr; + Superblock_control &sb_control; + Virtual_block_device &vbd; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + }; + + private: + + enum State { INIT, REQUESTED, STARTED, REKEY, PAUSED, RESUMED, COMPLETE }; + + State _state { INIT }; + bool const _verbose; + bool _success { }; + bool _complete { }; + Constructible _rekey { }; + + public: + + Rekey_operation(bool verbose) : _verbose(verbose) { } + + bool request() + { + switch (_state) { + case INIT: + case COMPLETE: + + _state = REQUESTED; + if (_verbose) + log("rekey requested"); + return true; + + default: return false; + } + ASSERT_NEVER_REACHED; + } + + Result result() const + { + switch (_state) { + case INIT: return NONE; + case COMPLETE: return _success ? SUCCEEDED : FAILED; + default: return PENDING; + } + ASSERT_NEVER_REACHED; + } + + bool execute(Execute_attr const &attr); + + void resume() + { + switch (_state) { + case PAUSED: _state = RESUMED; break; + default: ASSERT_NEVER_REACHED; + } + } + + void start() + { + switch (_state) { + case REQUESTED: _state = STARTED; break; + default: ASSERT_NEVER_REACHED; + } + } + + bool complete() const { return _state == COMPLETE; } + + bool paused() const { return _state == PAUSED; } + + bool requested() const { return _state == REQUESTED; } +}; + +class Vfs_tresor::Deinitialize_operation : private Noncopyable +{ + public: + + enum Result { NONE, SUCCEEDED, FAILED, PENDING }; + + struct Execute_attr + { + Deinitialize_file_system *deinit_fs_ptr; + Superblock_control &sb_control; + Block_io &block_io; + Crypto &crypto; + Trust_anchor &trust_anchor; + }; + + private: + + enum State { INIT, REQUESTED, STARTED, DEINIT_SB_CONTROL, COMPLETE }; + + State _state { INIT }; + bool const _verbose; + bool _success { }; + Constructible _deinit_sb_control { }; + + public: + + Deinitialize_operation(bool verbose) : _verbose(verbose) { } + + bool request() + { + switch (_state) { + case INIT: + case COMPLETE: + + _state = REQUESTED; + if (_verbose) + log("deinitialize requested"); + return true; + + default: return false; + } + ASSERT_NEVER_REACHED; + } + + void start() + { + switch (_state) { + case REQUESTED: _state = STARTED; break; + default: ASSERT_NEVER_REACHED; + } + } + + Result result() const + { + switch (_state) { + case INIT: return NONE; + case COMPLETE: return _success ? SUCCEEDED : FAILED; + default: return PENDING; + } + ASSERT_NEVER_REACHED; + } + + bool complete() const { return _state == COMPLETE; } + + bool requested() const { return _state == REQUESTED; } + + bool execute(Execute_attr const &attr); +}; + +class Vfs_tresor::Extend_operation : private Noncopyable +{ + public: + + enum Result { NONE, SUCCEEDED, FAILED, PENDING }; + + struct Execute_attr + { + Extend_file_system *extend_fs_ptr; + Superblock_control &sb_control; + Virtual_block_device &vbd; + Free_tree &free_tree; + Meta_tree &meta_tree; + Block_io &block_io; + Trust_anchor &trust_anchor; + }; + + private: + + enum State { + INIT, EXTEND_FT_REQUESTED, EXTEND_FT_STARTED, EXTEND_FT, EXTEND_FT_PAUSED, EXTEND_FT_RESUMED, + EXTEND_VBD_REQUESTED, EXTEND_VBD_STARTED, EXTEND_VBD, EXTEND_VBD_PAUSED, EXTEND_VBD_RESUMED, COMPLETE }; + + State _state { INIT }; + bool const _verbose; + bool _success { }; + bool _complete { }; + Number_of_blocks _num_blocks { }; + Constructible _extend_ft { }; + Constructible _extend_vbd { }; + + public: + + Extend_operation(bool verbose) : _verbose(verbose) { } + + bool request_for_free_tree(Number_of_blocks num_blocks) + { + switch (_state) { + case INIT: + case COMPLETE: + + _num_blocks = num_blocks; + _state = EXTEND_FT_REQUESTED; + if (_verbose) + log("extend free tree requested"); + return true; + + default: break; + } + return false; + } + + bool request_for_vbd(Number_of_blocks num_blocks) + { + switch (_state) { + case INIT: + case COMPLETE: + + _num_blocks = num_blocks; + _state = EXTEND_VBD_REQUESTED; + if (_verbose) + log("extend virtual block device requested"); + return true; + + default: return false; + } + ASSERT_NEVER_REACHED; + } + + Result result() const + { + switch (_state) { + case INIT: return NONE; + case COMPLETE: return _success ? SUCCEEDED : FAILED; + default: return PENDING; + } + ASSERT_NEVER_REACHED; + } + + bool execute(Execute_attr const &attr); + + void resume() + { + switch (_state) { + case EXTEND_FT_PAUSED: _state = EXTEND_FT_RESUMED; break; + case EXTEND_VBD_PAUSED: _state = EXTEND_VBD_RESUMED; break; + default: ASSERT_NEVER_REACHED; + } + } + + void start() + { + switch (_state) { + case EXTEND_FT_REQUESTED: _state = EXTEND_FT_STARTED; break; + case EXTEND_VBD_REQUESTED: _state = EXTEND_VBD_STARTED; break; + default: ASSERT_NEVER_REACHED; + } + } + + bool complete() const { return _state == COMPLETE; } + + bool paused() const { return _state == EXTEND_FT_PAUSED || _state == EXTEND_VBD_PAUSED; } + + bool requested() const { return _state == EXTEND_FT_REQUESTED || _state == EXTEND_VBD_REQUESTED; } +}; + +class Vfs_tresor::Plugin : private Noncopyable, private Client_data_interface, private Crypto_key_files_interface { private: - NONCOPYABLE(Wrapper); - - Vfs::Env &_vfs_env; - - Constructible _request_pool { }; - Constructible _free_tree { }; - Constructible _vbd { }; - Constructible _sb_control { }; - Tresor::Meta_tree _meta_tree { }; - Constructible _trust_anchor { }; - Constructible _crypto { }; - Constructible _block_io { }; - - Constructible _splitter { }; - Constructible _client_data { }; - - - public: - - enum class Result { UNKNOWN, OK, ERROR, EOF }; - - - private: - - class Command : public Module_channel - { - public: - - using Operation = Tresor::Request::Operation; - - enum State { IDLE, PENDING, IN_PROGRESS, COMPLETED }; - - static char const *op_to_string(Command::Operation op) { - return Tresor::Request::op_to_string(op); } - - private: - - NONCOPYABLE(Command); - - Vfs_tresor::Wrapper &_main; - - State _state { IDLE }; - bool _success { false }; - - void _generated_req_completed(State_uint) override { _main.mark_command_completed(id()); } - - public: - - Result result { Result::UNKNOWN }; - Operation op { Operation::READ }; - Number_of_blocks count { 0 }; - Generation gen { 0 }; - Key_id key_id { 0 }; - - /* for READ/WRITE */ - Genode::uint64_t offset { 0 }; - char *buffer_start { nullptr }; - size_t buffer_num_bytes { 0 }; - - Command(Vfs_tresor::Wrapper &main, Module_channel_id id) - : Module_channel { COMMAND_POOL, id }, _main { main } { } - - void reset() - { - _success = false; - - result = Result::UNKNOWN; - op = Operation::READ; - count = 0; - gen = 0; - key_id = 0; - offset = 0; - buffer_start = nullptr; - buffer_num_bytes = 0; - } - - bool success() const { return _success; } - - bool eof(Virtual_block_address max) const { - return offset / Tresor::BLOCK_SIZE > max; } - - bool synchronize() const { return op == Operation::SYNC; } - - State state() const { return _state; } - - void state(State state) - { - ASSERT(state != _state); - _state = state; - } - - void execute(bool verbose, bool &progress) - { - ASSERT(_state == State::PENDING); - - if (verbose) - log("Execute request ", *this); - - switch (op) { - case Command::Operation::READ: - generate_req(State::COMPLETED, - progress, Splitter_request::Operation::READ, _success, - offset, Byte_range_ptr(buffer_start, buffer_num_bytes), key_id, gen); - break; - case Command::Operation::WRITE: - generate_req(State::COMPLETED, - progress, Splitter_request::Operation::WRITE, _success, - offset, Byte_range_ptr(buffer_start, buffer_num_bytes), key_id, gen); - break; - default: - generate_req(State::COMPLETED, - progress, op, 0, 0, count, key_id, id(), gen, _success); - break; - } - - _main.mark_command_in_progress(id()); - } - - void print(Genode::Output &out) const - { - Genode::print(out, "op: ", op_to_string(op), " " - "count: ", count, " " - "gen: ", gen, " " - "key_id: ", key_id, " " - "offset: ", offset, " " - "buffer_start: ", (void*)buffer_start, " " - "buffer_num_bytes: ", buffer_num_bytes); - } - }; - - template - void _with_first_processable_cmd(FUNC && func) - { - bool first_uncompleted_cmd { true }; - bool done { false }; - for_each_channel([&] (Command &cmd) { - - if (done) - return; - - if (cmd.state() == Command::PENDING) { - done = true; - if (first_uncompleted_cmd || !cmd.synchronize()) - func(cmd); - } - - if (cmd.state() == Command::IN_PROGRESS) { - if (cmd.synchronize()) - done = true; - else - first_uncompleted_cmd = false; - } - }); - } - - template - bool _with_first_idle_cmd(FUNC && func) - { - bool done { false }; - for_each_channel([&] (Command &cmd) { - if (done) - return; - - if (cmd.state() == Command::IDLE) { - done = true; - /* - * Always provide a fresh Command to ease burden on - * the callee and set it PENDING afterwards as - * 'func' may not fail. - */ - cmd.reset(); - func(cmd); - cmd.state(Command::PENDING); - } - }); - return done; - } + enum State { + INIT_SB_CONTROL, NO_OPERATION, DATA_OPERATION, REKEY_OPERATION, EXTEND_OPERATION, + DEINITIALIZE_OPERATION, DEINITIALIZED }; enum { MAX_NUM_COMMANDS = 16 }; - Constructible _commands[MAX_NUM_COMMANDS] { }; - bool ready_to_submit_request() + struct Crypto_key { - bool result = false; - for_each_channel([&] (Command const &cmd) { - if (cmd.state() == Command::State::IDLE) - result = true; - }); - return result; - } - - public: - - struct Control_request - { - enum State { UNKNOWN, IDLE, IN_PROGRESS, }; - enum Result { NONE, SUCCESS, FAILED, }; - - State state; - Result last_result; - - Control_request() : state { State::UNKNOWN }, last_result { Result::NONE } { } - - bool idle() const { return state == IDLE; } - bool in_progress() const { return state == IN_PROGRESS; } - - bool success() const { return last_result == SUCCESS; } - - void mark_in_progress() - { - state = State::IN_PROGRESS; - last_result = Result::NONE; - } - - static char const *state_to_cstring(State const s) - { - switch (s) { - case State::UNKNOWN: return "unknown"; - case State::IDLE: return "idle"; - case State::IN_PROGRESS: return "in-progress"; - } - return "-"; - } + Key_id const key_id; + Vfs_handle &encrypt_file; + Vfs_handle &decrypt_file; }; - struct Rekeying : Control_request - { - uint32_t key_id; - Virtual_block_address max_vba; - Virtual_block_address rekeying_vba; - uint64_t percent_done; - - Rekeying() : Control_request { }, key_id { 0 }, max_vba { 0 }, - rekeying_vba { 0 }, percent_done { 0 } { } - - void mark_in_progress(Virtual_block_address max, - Virtual_block_address rekeying) - { - max_vba = max; - rekeying_vba = rekeying; - Control_request::mark_in_progress(); - } - }; - - struct Deinitialize : Control_request - { - uint32_t key_id; - - Deinitialize() : Control_request { }, key_id { 0 } - { - state = State::IDLE; - } - }; - - struct Extending : Control_request - { - enum Type { INVALID, VBD, FT }; - - Type type; - Virtual_block_address resizing_nr_of_pbas; - uint64_t percent_done; - - Extending() : Control_request { }, type { Type::INVALID}, - resizing_nr_of_pbas { 0 }, percent_done { 0 } { } - - void mark_in_progress(Type type, Virtual_block_address resizing_nr_of_pbas) - { - type = type; - resizing_nr_of_pbas = resizing_nr_of_pbas; - Control_request::mark_in_progress(); - } - - static Type string_to_type(char const *s) - { - if (Genode::strcmp("vbd", s, 3) == 0) { - return Type::VBD; - } else - - if (Genode::strcmp("ft", s, 2) == 0) { - return Type::FT; - } - - return Type::INVALID; - } - - static char const *type_to_string(Type type) - { - switch (type) { - case Type::VBD: return "vbd"; - case Type::FT: return "ft"; - case Type::INVALID: return "invalid"; - } - return nullptr; - } - }; - - private: + Vfs::Env &_vfs_env; + bool const _verbose; + Tresor::Path const _crypto_path; + Tresor::Path const _block_io_path; + Tresor::Path const _trust_anchor_path; + Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_crypto_add_key_file { open_file(_vfs_env, { _crypto_path, "/add_key" }, Directory_service::OPEN_MODE_WRONLY) }; + Vfs_handle &_crypto_remove_key_file { open_file(_vfs_env, { _crypto_path, "/remove_key" }, Directory_service::OPEN_MODE_WRONLY) }; + Vfs_handle &_ta_decrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/decrypt" }, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_ta_encrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/encrypt" }, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_ta_generate_key_file { open_file(_vfs_env, { _trust_anchor_path, "/generate_key" }, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_ta_initialize_file { open_file(_vfs_env, { _trust_anchor_path, "/initialize" }, Directory_service::OPEN_MODE_RDWR) }; + Vfs_handle &_ta_hash_file { open_file(_vfs_env, { _trust_anchor_path, "/hash" }, Directory_service::OPEN_MODE_RDWR) }; + Tresor::Free_tree _free_tree { }; + Tresor::Virtual_block_device _vbd { }; + Superblock_control _sb_control { }; + Meta_tree _meta_tree { }; + Trust_anchor _trust_anchor { { _ta_decrypt_file, _ta_encrypt_file, _ta_generate_key_file, _ta_initialize_file, _ta_hash_file } }; + Crypto _crypto { {*this, _crypto_add_key_file, _crypto_remove_key_file} }; + Block_io _block_io { _block_io_file }; + Splitter _splitter { }; + Extend_file_system * _extend_fs_ptr { }; + Rekey_file_system * _rekey_fs_ptr { }; + Deinitialize_file_system *_deinit_fs_ptr { }; + Constructible _crypto_keys[2] { }; + Superblock_control::Initialize *_init_sb_control_ptr { }; + Superblock::State _sb_state { Superblock::INVALID }; + Data_operation _data_operation { _verbose }; + Rekey_operation _rekey_operation { _verbose }; + Extend_operation _extend_operation { _verbose }; + Deinitialize_operation _deinit_operation { _verbose }; + State _state { INIT_SB_CONTROL }; /* - * XXX The initial object state of Rekeying and - * Extending relies on 'execute()' querying - * the Superblock_info to switch from UNKNOWN - * to the current state and could therefore - * deny attempts. + * Noncopyable */ - Rekeying _rekey_obj { }; - Extending _extend_obj { }; - Deinitialize _deinit_obj { }; + Plugin(Plugin const &) = delete; + Plugin &operator = (Plugin const &) = delete; - Genode::Mutex _io_mutex { }; - Vfs_handle const *_io_handle_ptr { nullptr }; - Command *_io_cmd_ptr { nullptr }; - - bool _active_io_cmd_for_handle(Vfs_handle const &handle) const { - return _io_handle_ptr == &handle; } - - template - bool _setup_io_cmd_for_handle(Vfs_handle const &handle, - SETUP_FN const &setup_fn) + Constructible &_crypto_key(Key_id key_id) { - ASSERT(_io_handle_ptr == nullptr); - - bool done = _with_first_idle_cmd([&] (Command &cmd) { - setup_fn(cmd); - - _io_cmd_ptr = &cmd; - _io_handle_ptr = &handle; - }); - return done; + for (Constructible &key : _crypto_keys) + if (key.constructed() && key->key_id == key_id) + return key; + ASSERT_NEVER_REACHED; } - template - bool _with_io_active_cmd_for_handle(Vfs_handle const &handle, - PENDING_FN const &pending_fn, - COMPLETE_FN const &complete_fn) + bool _try_start_operation() { - bool found = false; - if (_io_handle_ptr && _io_handle_ptr == &handle) { - if (_io_cmd_ptr) { - Command &cmd = *_io_cmd_ptr; + if (_deinit_operation.requested()) { + _deinit_operation.start(); + _state = DEINITIALIZE_OPERATION; + return true; + } + if (_data_operation.requested()) { + _data_operation.start(); + _state = DATA_OPERATION; + return true; + } + if (_extend_operation.requested()) { + _extend_operation.start(); + _state = EXTEND_OPERATION; + return true; + } + if (_rekey_operation.requested()) { + _rekey_operation.start(); + _state = REKEY_OPERATION; + return true; + } + return false; + } - switch (cmd.state()) { - case Command::State::IDLE: - /* should never happen */ - break; - case Command::State::PENDING: [[fallthrough]]; - case Command::State::IN_PROGRESS: - pending_fn(); - break; - case Command::State::COMPLETED: - complete_fn(*_io_cmd_ptr); - cmd.state(Command::IDLE); + bool _try_resume_operation() + { + if (_extend_operation.paused()) { + _extend_operation.resume(); + _state = EXTEND_OPERATION; + return true; + } + if (_rekey_operation.paused()) { + _rekey_operation.resume(); + _state = REKEY_OPERATION; + return true; + } + return false; + } - _io_cmd_ptr = nullptr; - _io_handle_ptr = nullptr; - break; - } - found = true; + bool _execute_operations() + { + bool progress = false; + switch (_state) { + case INIT_SB_CONTROL: + + progress |= _sb_control.execute(*_init_sb_control_ptr, _block_io, _crypto, _trust_anchor) ; + if (_init_sb_control_ptr->complete()) { + + ASSERT(_init_sb_control_ptr->success()); + destroy(_vfs_env.alloc(), _init_sb_control_ptr); + _init_sb_control_ptr = nullptr; + if (_verbose) + log("initialize succeeded"); + + if (!_try_start_operation()) + _state = NO_OPERATION; + progress = true; } + break; + + case DATA_OPERATION: + + progress |= _data_operation.execute({_splitter, _sb_control, *this, _vbd, _free_tree, _meta_tree, _block_io, _crypto, _trust_anchor}) ; + if (_data_operation.complete()) { + if (!_try_resume_operation()) + if (!_try_start_operation()) + _state = NO_OPERATION; + progress = true; + } + break; + + case DEINITIALIZE_OPERATION: + + progress |= _deinit_operation.execute({_deinit_fs_ptr, _sb_control, _block_io, _crypto, _trust_anchor}) ; + if (_deinit_operation.complete()) { + _state = DEINITIALIZED; + progress = true; + } + break; + + case EXTEND_OPERATION: + + progress |= _extend_operation.execute({_extend_fs_ptr, _sb_control, _vbd, _free_tree, _meta_tree, _block_io, _trust_anchor}) ; + if (_extend_operation.complete()) { + if (!_try_start_operation()) + _state = NO_OPERATION; + progress = true; + } + if (_extend_operation.paused()) { + if (_data_operation.requested()) { + _data_operation.start(); + _state = DATA_OPERATION; + } else + _extend_operation.resume(); + progress = true; + } + break; + + case REKEY_OPERATION: + + progress |= _rekey_operation.execute({_rekey_fs_ptr, _sb_control, _vbd, _free_tree, _meta_tree, _block_io, _crypto, _trust_anchor}) ; + if (_rekey_operation.complete()) { + if (!_try_start_operation()) + _state = NO_OPERATION; + progress = true; + } + if (_rekey_operation.paused()) { + if (_data_operation.requested()) { + _data_operation.start(); + _state = DATA_OPERATION; + } else + _rekey_operation.resume(); + progress = true; + } + break; + + case NO_OPERATION: progress |= _try_start_operation(); break; + default: break; } - return found; + return progress; } - Pointer _snapshots_fs { }; - Pointer _extend_fs { }; - Pointer _extend_progress_fs { }; - Pointer _rekey_fs { }; - Pointer _rekey_progress_fs { }; - Pointer _deinit_fs { }; - - /* configuration options */ - bool _verbose { false }; - bool _debug { false }; - - void _read_config(Xml_node config) + void _execute() { - _verbose = config.attribute_value("verbose", _verbose); - _debug = config.attribute_value("debug", _debug); + while (_execute_operations()) ; + _wakeup_back_end_services(); } - struct Could_not_open_block_backend : Genode::Exception { }; - struct No_valid_superblock_found : Genode::Exception { }; + void _wakeup_back_end_services() { _vfs_env.io().commit(); } - void _initialize_tresor() + size_t _data_file_size() const { return (_sb_control.max_vba() + 1) * BLOCK_SIZE; } + + /******************************** + ** Crypto_key_files_interface ** + ********************************/ + + void add_crypto_key(Key_id key_id) override { - _free_tree.construct(); - _vbd.construct(); - _sb_control.construct(); - _request_pool.construct(); - - add_module(FREE_TREE, *_free_tree); - add_module(VIRTUAL_BLOCK_DEVICE, *_vbd); - add_module(SUPERBLOCK_CONTROL, *_sb_control); - add_module(REQUEST_POOL, *_request_pool); - - Module_channel_id id = 0; - for (auto & cmd : _commands) { - cmd.construct(*this, id++); - add_channel(*cmd); - } - } - - void _process_completed(Command &cmd) - { - using R = Result; - - bool const success = cmd.success(); - - if (_verbose) - log("Completed request ", cmd, " ", - success ? "successfull" : "failed"); - - switch (cmd.op) { - case Command::Operation::REKEY: - { - _rekey_obj.state = Rekeying::State::IDLE; - _rekey_obj.last_result = success ? Rekeying::Result::SUCCESS - : Rekeying::Result::FAILED; - - _rekey_fs_trigger_watch_response(); - _rekey_progress_fs_trigger_watch_response(); - - cmd.state(Command::IDLE); - break; - } - case Command::Operation::DEINITIALIZE: - { - _deinit_obj.state = Deinitialize::State::IDLE; - _deinit_obj.last_result = success ? Deinitialize::Result::SUCCESS - : Deinitialize::Result::FAILED; - - _deinit_fs_trigger_watch_response(); - - cmd.state(Command::IDLE); - break; - } - case Command::Operation::EXTEND_VBD: - { - _extend_obj.state = Extending::State::IDLE; - _extend_obj.last_result = - success ? Extending::Result::SUCCESS - : Extending::Result::FAILED; - - _extend_fs_trigger_watch_response(); - _extend_progress_fs_trigger_watch_response(); - - cmd.state(Command::IDLE); - break; - } - case Command::Operation::EXTEND_FT: - { - _extend_obj.state = Extending::State::IDLE; - _extend_obj.last_result = - success ? Extending::Result::SUCCESS - : Extending::Result::FAILED; - - _extend_fs_trigger_watch_response(); - - cmd.state(Command::IDLE); - break; - } - case Command::Operation::CREATE_SNAPSHOT: - { - // FIXME more TODO here? - _snapshots_fs_update_snapshot_registry(); - - cmd.state(Command::IDLE); - break; - } - case Command::Operation::DISCARD_SNAPSHOT: - { - // FIXME more TODO here? - _snapshots_fs_update_snapshot_registry(); - - cmd.state(Command::IDLE); - break; - } - case Command::Operation::READ: [[fallthrough]]; - case Command::Operation::WRITE: - { - bool const eof = cmd.eof(_sb_control->max_vba()); - - cmd.result = success ? R::OK - : eof ? R::EOF - : R::ERROR; - break; - } - case Command::Operation::SYNC: - cmd.result = success ? R::OK : R::ERROR; - break; - /* not handled here */ - case Command::Operation::RESUME_REKEYING: - cmd.result = success ? R::OK : R::ERROR; - break; - case Command::Operation::INITIALIZE: - cmd.result = success ? R::OK : R::ERROR; - break; - } /* switch */ - } - - void _snapshots_fs_update_snapshot_registry(); - - void _extend_fs_trigger_watch_response(); - - void _extend_progress_fs_trigger_watch_response(); - - void _rekey_fs_trigger_watch_response(); - - void _rekey_progress_fs_trigger_watch_response(); - - void _deinit_fs_trigger_watch_response(); - - template - void _with_node(char const *name, char const *path, FN const &fn) - { - char xml_buffer[128] { }; - - Genode::Xml_generator xml { - xml_buffer, sizeof(xml_buffer), name, - [&] { xml.attribute("path", path); } - }; - - Genode::Xml_node node { xml_buffer, sizeof(xml_buffer) }; - fn(node); - } - - public: - - Wrapper(Vfs::Env &vfs_env, Xml_node config) : _vfs_env { vfs_env } - { - _read_config(config); - - using S = Genode::String<32>; - - S const block_path = - config.attribute_value("block", S()); - if (block_path.valid()) - _with_node("block_io", block_path.string(), - [&] (Xml_node const &node) { - _block_io.construct(vfs_env, node); - }); - - S const trust_anchor_path = - config.attribute_value("trust_anchor", S()); - if (trust_anchor_path.valid()) - _with_node("trust_anchor", trust_anchor_path.string(), - [&] (Xml_node const &node) { - _trust_anchor.construct(vfs_env, node); - }); - - S const crypto_path = - config.attribute_value("crypto", S()); - if (crypto_path.valid()) - _with_node("crypto", crypto_path.string(), - [&] (Xml_node const &node) { - _crypto.construct(vfs_env, node); - }); - - _splitter.construct(); - _client_data.construct(*_splitter); - - add_module(COMMAND_POOL, *this); - add_module(META_TREE, _meta_tree); - add_module(CRYPTO, *_crypto); - add_module(TRUST_ANCHOR, *_trust_anchor); - add_module(CLIENT_DATA, *_client_data); - add_module(BLOCK_IO, *_block_io); - add_module(SPLITTER, *_splitter); - - _initialize_tresor(); - } - - void mark_command_in_progress(Module_channel_id cmd_id) - { - with_channel(cmd_id, [&] (Command &cmd) { - cmd.state(Command::IN_PROGRESS); - }); - } - - void mark_command_completed(Module_channel_id cmd_id) - { - with_channel(cmd_id, [&] (Command &cmd) { - cmd.state(Command::COMPLETED); - _process_completed(cmd); - }); - } - - void execute(bool &progress) override - { - _with_first_processable_cmd([&] (Command &cmd) { - cmd.execute(_verbose, progress); - }); - } - - Genode::uint64_t max_vba() - { - return _sb_control->max_vba(); - } - - /* - * Handle a I/O request - * - * We rely on the 'handle' as well as the memory covered by - * 'data' being valid throughout the processing of the pending - * request. - */ - template - void handle_io_request(Vfs_handle const &handle, - Byte_range_ptr const &data, - Tresor::Request::Operation op, - Generation gen, - PENDING_FN const &pending_fn, - COMPLETE_FN const &complete_fn) - { - - Genode::Mutex::Guard guard { _io_mutex }; - - /* queue new I/O request */ - if (!_active_io_cmd_for_handle(handle)) { - bool const done = - _setup_io_cmd_for_handle(handle, [&] (Command &cmd) { - - cmd.op = op; - cmd.gen = gen; - cmd.offset = handle.seek(); - /* make a copy as the object may be dynamic */ - cmd.buffer_start = data.start; - cmd.buffer_num_bytes = data.num_bytes; - }); - - if (!done) { - pending_fn(); + for (Constructible &key : _crypto_keys) + if (!key.constructed()) { + key.construct(key_id, + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/encrypt" }, Directory_service::OPEN_MODE_RDWR), + open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/decrypt" }, Directory_service::OPEN_MODE_RDWR) + ); return; } - } - - execute(); - - _with_io_active_cmd_for_handle(handle, - [&] { pending_fn(); }, - [&] (Command const &cmd) { - complete_fn(cmd.result, - cmd.buffer_num_bytes); - }); + ASSERT_NEVER_REACHED; } - void execute() + void remove_crypto_key(Key_id key_id) override { - execute_modules(); - _vfs_env.io().commit(); - - Tresor::Superblock_info const sb_info { - _sb_control->sb_info() }; - - using ES = Extending::State; - if (_extend_obj.state == ES::UNKNOWN && sb_info.valid) { - if (sb_info.extending_ft) { - - _extend_obj.state = ES::IN_PROGRESS; - _extend_obj.type = Extending::Type::FT; - } else - - if (sb_info.extending_vbd) { - - _extend_obj.state = ES::IN_PROGRESS; - _extend_obj.type = Extending::Type::VBD; - } else { - - _extend_obj.state = ES::IDLE; - } - _extend_fs_trigger_watch_response(); - } - - if (_extend_obj.in_progress()) { - - Virtual_block_address const current_nr_of_pbas = - _sb_control->resizing_nr_of_pbas(); - - /* initial query */ - if (_extend_obj.resizing_nr_of_pbas == 0) - _extend_obj.resizing_nr_of_pbas = current_nr_of_pbas; - - /* update user-facing state */ - uint64_t const last_percent_done = _extend_obj.percent_done; - _extend_obj.percent_done = - (_extend_obj.resizing_nr_of_pbas - current_nr_of_pbas) - * 100 / _extend_obj.resizing_nr_of_pbas; - - if (last_percent_done != _extend_obj.percent_done) - _extend_progress_fs_trigger_watch_response(); - } - - using RS = Rekeying::State; - if (_rekey_obj.state == RS::UNKNOWN && sb_info.valid) { - _rekey_obj.state = - sb_info.rekeying ? RS::IN_PROGRESS : RS::IDLE; - - _rekey_fs_trigger_watch_response(); - } - - if (_rekey_obj.in_progress()) { - _rekey_obj.rekeying_vba = _sb_control->rekeying_vba(); - - /* update user-facing state */ - uint64_t const last_percent_done = _rekey_obj.percent_done; - _rekey_obj.percent_done = - _rekey_obj.rekeying_vba * 100 / _rekey_obj.max_vba; - - if (last_percent_done != _rekey_obj.percent_done) - _rekey_progress_fs_trigger_watch_response(); - } + Constructible &crypto_key = _crypto_key(key_id); + _vfs_env.root_dir().close(&crypto_key->encrypt_file); + _vfs_env.root_dir().close(&crypto_key->decrypt_file); + crypto_key.destruct(); } - bool start_rekeying() + Vfs_handle &encrypt_file(Key_id key_id) override { return _crypto_key(key_id)->encrypt_file; } + Vfs_handle &decrypt_file(Key_id key_id) override { return _crypto_key(key_id)->decrypt_file; } + + /*************************** + ** Client_data_interface ** + ***************************/ + + void obtain_data(Obtain_data_attr const &attr) override { - if (!ready_to_submit_request()) - return false; - - bool result = _with_first_idle_cmd([&] (Command &cmd) { - - cmd.op = Command::Operation::REKEY; - cmd.key_id = _rekey_obj.key_id; - - _rekey_obj.mark_in_progress(_sb_control->max_vba(), - _sb_control->rekeying_vba()); - - _rekey_fs_trigger_watch_response(); - _rekey_progress_fs_trigger_watch_response(); - }); - - execute(); - return result; + attr.out_blk = _splitter.source_buffer(attr.in_vba); } - Rekeying const rekeying_progress() const { - return _rekey_obj; } - - bool start_deinitialize() + void supply_data(Supply_data_attr const &attr) override { - if (!ready_to_submit_request()) - return false; - - bool result = _with_first_idle_cmd([&] (Command &cmd) { - - cmd.op = Command::Operation::DEINITIALIZE; - - _deinit_obj.mark_in_progress(); - _deinit_fs_trigger_watch_response(); - }); - - execute(); - return result; + _splitter.destination_buffer(attr.in_vba) = attr.in_blk; } - Deinitialize const deinitialize_progress() const { - return _deinit_obj; } + public: - bool start_extending(Extending::Type type, - Tresor::Number_of_blocks blocks) + Plugin(Vfs::Env &vfs_env, Xml_node const &config) + : + _vfs_env(vfs_env), + _verbose(config.attribute_value("verbose", _verbose)), + _crypto_path(config.attribute_value("crypto", Tresor::Path())), + _block_io_path(config.attribute_value("block", Tresor::Path())), + _trust_anchor_path(config.attribute_value("trust_anchor", Tresor::Path())) { - if (!ready_to_submit_request() || type == Extending::Type::INVALID) - return false; - - Command::Operation op = Command::Operation::EXTEND_VBD; - - switch (type) { - case Extending::Type::VBD: - op = Command::Operation::EXTEND_VBD; - break; - case Extending::Type::FT: - op = Command::Operation::EXTEND_FT; - break; - case Extending::Type::INVALID: - /* never reached */ - return false; - } - - bool result = _with_first_idle_cmd([&] (Command &cmd) { - - cmd.op = op; - cmd.count = blocks; - - _extend_obj.mark_in_progress(type, 0); - - _extend_fs_trigger_watch_response(); - _extend_progress_fs_trigger_watch_response(); - }); - - execute(); - return result; + _init_sb_control_ptr = new (_vfs_env.alloc()) Superblock_control::Initialize({_sb_state}); + if (_verbose) + log("initialize started"); } - Extending const extending_progress() const { - return _extend_obj; } - - void snapshots_info(Tresor::Snapshots_info &info) + template + void with_data_file_size(FUNC && func) { - info = _sb_control->snapshots_info(); - execute(); + _execute(); + if (_state != INIT_SB_CONTROL) + func(_data_file_size()); } - bool create_snapshot() + template + void with_data_operation(FUNC && func) { - if (!ready_to_submit_request()) - return false; - - bool result = _with_first_idle_cmd([&] (Command &cmd) { - cmd.op = Command::Operation::CREATE_SNAPSHOT; }); - - execute(); - return result; + _execute(); + func(_data_operation); + _execute(); } - bool discard_snapshot(Generation snap_gen) + template + void with_rekey_operation(FUNC && func) { - if (!ready_to_submit_request()) - return false; - - bool result = _with_first_idle_cmd([&] (Command &cmd) { - cmd.op = Command::Operation::DISCARD_SNAPSHOT; - cmd.gen = snap_gen; - }); - - execute(); - return result; + _execute(); + func(_rekey_operation); + _execute(); } - /*********************************************************** - ** Manange/Disolve interface needed for FS notifications ** - ***********************************************************/ - - void manage_snapshots_file_system(Snapshots_file_system &snapshots_fs) + template + void with_extend_operation(FUNC && func) { - if (_snapshots_fs.valid()) { - - class Already_managing_an_snapshots_file_system { }; - throw Already_managing_an_snapshots_file_system { }; - } - _snapshots_fs = snapshots_fs; + _execute(); + func(_extend_operation); + _execute(); } - void dissolve_snapshots_file_system(Snapshots_file_system &snapshots_fs) + template + void with_deinit_operation(FUNC && func) { - if (_snapshots_fs.valid()) { - - if (&_snapshots_fs.obj() != &snapshots_fs) { - - class Snapshots_file_system_not_managed { }; - throw Snapshots_file_system_not_managed { }; - } - _snapshots_fs = Pointer { }; - - } else { - - class No_snapshots_file_system_managed { }; - throw No_snapshots_file_system_managed { }; - } + _execute(); + func(_deinit_operation); + _execute(); } void manage_extend_file_system(Extend_file_system &extend_fs) { - if (_extend_fs.valid()) { - - class Already_managing_an_extend_file_system { }; - throw Already_managing_an_extend_file_system { }; - } - _extend_fs = extend_fs; + ASSERT(!_extend_fs_ptr); + _extend_fs_ptr = &extend_fs; } void dissolve_extend_file_system(Extend_file_system &extend_fs) { - if (_extend_fs.valid()) { - - if (&_extend_fs.obj() != &extend_fs) { - - class Extend_file_system_not_managed { }; - throw Extend_file_system_not_managed { }; - } - _extend_fs = Pointer { }; - - } else { - - class No_extend_file_system_managed { }; - throw No_extend_file_system_managed { }; - } - } - - void manage_extend_progress_file_system(Extend_progress_file_system &extend_progress_fs) - { - if (_extend_progress_fs.valid()) { - - class Already_managing_an_extend_progres_file_system { }; - throw Already_managing_an_extend_progres_file_system { }; - } - _extend_progress_fs = extend_progress_fs; - } - - void dissolve_extend_progress_file_system(Extend_progress_file_system &extend_progress_fs) - { - if (_extend_progress_fs.valid()) { - - if (&_extend_progress_fs.obj() != &extend_progress_fs) { - - class Extend_file_system_not_managed { }; - throw Extend_file_system_not_managed { }; - } - _extend_progress_fs = Pointer { }; - - } else { - - class No_extend_file_system_managed { }; - throw No_extend_file_system_managed { }; - } + ASSERT(_extend_fs_ptr == &extend_fs); + _extend_fs_ptr = nullptr; } void manage_rekey_file_system(Rekey_file_system &rekey_fs) { - if (_rekey_fs.valid()) { - - class Already_managing_an_rekey_file_system { }; - throw Already_managing_an_rekey_file_system { }; - } - _rekey_fs = rekey_fs; + ASSERT(!_rekey_fs_ptr); + _rekey_fs_ptr = &rekey_fs; } void dissolve_rekey_file_system(Rekey_file_system &rekey_fs) { - if (_rekey_fs.valid()) { - - if (&_rekey_fs.obj() != &rekey_fs) { - - class Rekey_file_system_not_managed { }; - throw Rekey_file_system_not_managed { }; - } - _rekey_fs = Pointer { }; - - } else { - - class No_rekey_file_system_managed { }; - throw No_rekey_file_system_managed { }; - } - } - - void manage_rekey_progress_file_system(Rekey_progress_file_system &rekey_progress_fs) - { - if (_rekey_progress_fs.valid()) { - - class Already_managing_an_rekey_progress_file_system { }; - throw Already_managing_an_rekey_progress_file_system { }; - } - _rekey_progress_fs = rekey_progress_fs; - } - - void dissolve_rekey_progress_file_system(Rekey_progress_file_system &rekey_progress_fs) - { - if (_rekey_progress_fs.valid()) { - - if (&_rekey_progress_fs.obj() != &rekey_progress_fs) { - - class Rekey_progress_file_system_not_managed { }; - throw Rekey_progress_file_system_not_managed { }; - } - _rekey_progress_fs = Pointer { }; - - } else { - - class No_rekey_progress_file_system_managed { }; - throw No_rekey_progress_file_system_managed { }; - } + ASSERT(_rekey_fs_ptr == &rekey_fs); + _rekey_fs_ptr = nullptr; } void manage_deinit_file_system(Deinitialize_file_system &deinit_fs) { - if (_deinit_fs.valid()) { - - class Already_managing_an_deinit_file_system { }; - throw Already_managing_an_deinit_file_system { }; - } - _deinit_fs = deinit_fs; + ASSERT(!_deinit_fs_ptr); + _deinit_fs_ptr = &deinit_fs; } void dissolve_deinit_file_system(Deinitialize_file_system &deinit_fs) { - if (_deinit_fs.valid()) { - - if (&_deinit_fs.obj() != &deinit_fs) { - - class Deinitialize_file_system_not_managed { }; - throw Deinitialize_file_system_not_managed { }; - } - _deinit_fs = Pointer { }; - - } else { - - class No_deinit_file_system_managed { }; - throw No_deinit_file_system_managed { }; - } + ASSERT(_deinit_fs_ptr == &deinit_fs); + _deinit_fs_ptr = nullptr; } + bool verbose() const { return _verbose; } }; -class Vfs_tresor::Data_file_system : public Single_file_system +class Vfs_tresor::Data_file_system : private Noncopyable, public Single_file_system { private: - Wrapper &_w; - Generation _snap_gen; - - using OP = Tresor::Request::Operation; - using FR = Wrapper::Result; - using RR = Vfs::File_io_service::Read_result; - using SR = Vfs::File_io_service::Sync_result; - using WR = Vfs::File_io_service::Write_result; - - static RR read_result(FR r) + class Vfs_handle : private Noncopyable, public Single_vfs_handle { - switch (r) { - case FR::OK: return RR::READ_OK; - case FR::EOF: return RR::READ_OK; - case FR::ERROR: return RR::READ_ERR_IO; - case FR::UNKNOWN: return RR::READ_ERR_INVALID; - } - return RR::READ_ERR_INVALID; - } + private: - static SR sync_result(FR r) - { - switch (r) { - case FR::OK: return SR::SYNC_OK; - case FR::EOF: return SR::SYNC_ERR_INVALID; - case FR::ERROR: return SR::SYNC_ERR_INVALID; - case FR::UNKNOWN: return SR::SYNC_ERR_INVALID; - } - return SR::SYNC_ERR_INVALID; - } + Plugin &_plugin; - static WR write_result(FR r) - { - switch (r) { - case FR::OK: return WR::WRITE_OK; - case FR::EOF: return WR::WRITE_OK; - case FR::ERROR: return WR::WRITE_ERR_IO; - case FR::UNKNOWN: return WR::WRITE_ERR_INVALID; - } - return WR::WRITE_ERR_INVALID; - } + public: + Vfs_handle(Directory_service &dir_service, File_io_service &file_io_service, + Allocator &alloc, Plugin &plugin) + : + Single_vfs_handle(dir_service, file_io_service, alloc, 0), _plugin(plugin) + { } + + /*********************** + ** Single_vfs_handle ** + ***********************/ + + Read_result read(Byte_range_ptr const &dst, size_t &out_count) override + { + out_count = 0; + Read_result result = READ_QUEUED; + _plugin.with_data_operation([&] (Data_operation &data_operation) { + + switch (data_operation.read(seek(), dst)) { + case Data_operation::PENDING: break; + case Data_operation::SUCCEEDED: + + out_count = dst.num_bytes; + result = READ_OK; + break; + + case Data_operation::FAILED: result = READ_ERR_IO; break; + }; + }); + return result; + } + + Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override + { + out_count = 0; + Write_result result = WRITE_ERR_WOULD_BLOCK; + _plugin.with_data_operation([&] (Data_operation &data_operation) { + + switch (data_operation.write(seek(), src)) { + case Data_operation::PENDING: break; + case Data_operation::SUCCEEDED: + + out_count = src.num_bytes; + result = WRITE_OK; + break; + + case Data_operation::FAILED: result = WRITE_ERR_IO; break; + }; + }); + return result; + } + + Sync_result sync() override + { + Sync_result result = SYNC_QUEUED; + _plugin.with_data_operation([&] (Data_operation &data_operation) { + + switch (data_operation.sync()) { + case Data_operation::PENDING: break; + case Data_operation::SUCCEEDED: + + result = SYNC_OK; + break; + + case Data_operation::FAILED: result = SYNC_ERR_INVALID; break; + }; + }); + return result; + } + + bool read_ready() const override { return true; } + bool write_ready() const override { return true; } + }; + + Plugin &_plugin; public: - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - Generation _snap_gen { INVALID_GENERATION }; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w, - Generation snap_gen) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w), _snap_gen(snap_gen) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - RR result = RR::READ_ERR_INVALID; - _w.handle_io_request(*this, dst, OP::READ, _snap_gen, - [&] { result = READ_QUEUED; }, - [&] (FR fresult, size_t count) { - result = read_result(fresult); - out_count = count; - } - ); - return result; - } - - Write_result write(Const_byte_range_ptr const &src, - size_t &out_count) override - { - WR result = WR::WRITE_ERR_INVALID; - _w.handle_io_request(*this, - Byte_range_ptr(const_cast(src.start), - src.num_bytes), - OP::WRITE, _snap_gen, - [&] { result = WRITE_ERR_WOULD_BLOCK; }, - [&] (FR fresult, size_t count) { - result = write_result(fresult); - out_count = count; - } - ); - return result; - } - - Sync_result sync() override - { - SR result = SR::SYNC_ERR_INVALID; - _w.handle_io_request(*this, - Byte_range_ptr(nullptr, 0), - OP::SYNC, 0, - [&] { result = SYNC_QUEUED; }, - [&] (FR fresult, size_t) { - result = sync_result(fresult); - } - ); - return result; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; - - Data_file_system(Wrapper &w, Generation snap_gen) + Data_file_system(Plugin &plugin) : - Single_file_system(Node_type::CONTINUOUS_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w), _snap_gen(snap_gen) + Single_file_system(Node_type::CONTINUOUS_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _plugin(plugin) { } - ~Data_file_system() - { - /* XXX sync on close */ - /* XXX invalidate any still pending request */ - } + static char const *type_name() { return "data"; } - /********************************* - ** Directory-service interface ** - *********************************/ + /************************ + ** Single_file_system ** + ************************/ Stat_result stat(char const *path, Stat &out) override { - Stat_result result = Single_file_system::stat(path, out); - - /* max_vba range is from 0 ... N - 1 */ - out.size = (_w.max_vba() + 1) * Tresor::BLOCK_SIZE; + Stat_result result = STAT_ERR_NO_ENTRY; + _plugin.with_data_file_size([&] (size_t size) { + result = Single_file_system::stat(path, out); + out.size = size; + }); return result; } - /******************************** - ** File I/O service interface ** - ********************************/ + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { return FTRUNCATE_OK; } - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } - - /*************************** - ** File-system interface ** - ***************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Allocator &alloc) override + Open_result open(char const *path, unsigned, Vfs::Vfs_handle **out_handle, Allocator &alloc) override { if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w, _snap_gen); - + *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, _plugin); return OPEN_OK; } - static char const *type_name() { return "data"; } char const *type() override { return type_name(); } }; -class Vfs_tresor::Extend_file_system : public Vfs::Single_file_system +class Vfs_tresor::Extend_file_system : private Noncopyable, public Single_file_system { private: - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; + using Registered_watch_handle = Registered; + using Watch_handle_registry = Registry; + using Content_string = String<11>; - Watch_handle_registry _handle_registry { }; - - Wrapper &_w; - - using Content_string = String<32>; - - static file_size copy_content(Content_string const &content, - char *dst, size_t const count) + class Vfs_handle : private Noncopyable, public Single_vfs_handle { - copy_cstring(dst, content.string(), count); - size_t const length_without_nul = content.length() - 1; - return count > length_without_nul - 1 ? length_without_nul - : count; - } + private: - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; + Plugin &_plugin; - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - /* EOF */ - if (seek() != 0) { - out_count = 0; - return READ_OK; - } - - /* - * For now trigger extending execution via this hook - * like we do in the Data_file_system. - */ - _w.execute(); - - Wrapper::Extending const & extending { - _w.extending_progress() }; - - if (extending.in_progress()) - return READ_QUEUED; - - if (extending.idle()) { - Content_string const content { - extending.success() ? "successful" - : "failed" }; - copy_content(content, dst.start, dst.num_bytes); + static Read_result _read_ok(Content_string const &content, Byte_range_ptr const &dst, size_t &out_count) + { + copy_cstring(dst.start, content.string(), dst.num_bytes); out_count = dst.num_bytes; return READ_OK; } - return READ_ERR_IO; - } + public: - Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override - { - using Type = Wrapper::Extending::Type; - if (!_w.extending_progress().idle()) { - return WRITE_ERR_IO; + Vfs_handle(Directory_service &dir_service, File_io_service &file_io_service, + Allocator &alloc, Plugin &plugin) + : + Single_vfs_handle(dir_service, file_io_service, alloc, 0), _plugin(plugin) + { } + + /*********************** + ** Single_vfs_handle ** + ***********************/ + + Read_result read(Byte_range_ptr const &dst, size_t &out_count) override + { + out_count = 0; + if (seek() == dst.num_bytes) { + return READ_OK; + } + if (seek() || dst.num_bytes < Content_string::capacity()) { + if (_plugin.verbose()) + log("reading extend file failed: malformed arguments"); + return READ_ERR_IO; + } + Read_result result = READ_QUEUED; + _plugin.with_extend_operation([&] (Extend_operation &extend_operation) { + + switch (extend_operation.result()) { + case Extend_operation::NONE: result = _read_ok("none", dst, out_count); break; + case Extend_operation::SUCCEEDED: result = _read_ok("succeeded", dst, out_count); break; + case Extend_operation::FAILED: result = _read_ok("failed", dst, out_count); break; + case Extend_operation::PENDING: break; + } + }); + return result; } - char tree[16]; - Arg_string::find_arg(src.start, "tree").string(tree, sizeof (tree), "-"); - Type type = Wrapper::Extending::string_to_type(tree); - if (type == Type::INVALID) { - return WRITE_ERR_IO; + Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override + { + out_count = 0; + char tree_arg[16]; + Arg_string::find_arg(src.start, "tree").string(tree_arg, sizeof(tree_arg), "-"); + unsigned long blocks_arg = Arg_string::find_arg(src.start, "blocks").ulong_value(0); + if (seek() || !blocks_arg) { + if (_plugin.verbose()) + log("writing extend file failed: malformed arguments"); + return WRITE_ERR_IO; + } + Write_result result = WRITE_ERR_IO; + _plugin.with_extend_operation([&] (Extend_operation &extend_operation) { + + if (!strcmp("ft", tree_arg, 2)) { + + if (!extend_operation.request_for_free_tree(blocks_arg)) { + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing extend file failed: failed to request operation"); + return; + } + + } else if (!strcmp("vbd", tree_arg, 3)) { + + if (!extend_operation.request_for_vbd(blocks_arg)) { + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing extend file failed: failed to request operation"); + return; + } + + } else { + + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing extend file failed: malformed tree argument"); + return; + } + out_count = src.num_bytes; + result = WRITE_OK; + }); + return result; } - unsigned long blocks = Arg_string::find_arg(src.start, "blocks").ulong_value(0); - if (blocks == 0) { - return WRITE_ERR_IO; - } - - bool const okay = _w.start_extending(type, blocks); - if (!okay) { - return WRITE_ERR_IO; - } - - out_count = src.num_bytes; - return WRITE_OK; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } + bool read_ready() const override { return true; } + bool write_ready() const override { return true; } }; + Watch_handle_registry _handle_registry { }; + Plugin &_plugin; + public: - Extend_file_system(Wrapper &w) + Extend_file_system(Plugin &plugin) : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _plugin(plugin) { - _w.manage_extend_file_system(*this); + _plugin.manage_extend_file_system(*this); } static char const *type_name() { return "extend"; } - char const *type() override { return type_name(); } - void trigger_watch_response() { _handle_registry.for_each([this] (Registered_watch_handle &handle) { handle.watch_response(); }); } - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override + /************************ + ** Single_file_system ** + ************************/ + + Watch_result watch(char const *path, Vfs_watch_handle **handle, Allocator &alloc) override { if (!_single_file(path)) return WATCH_ERR_UNACCESSIBLE; try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - + *handle = new (alloc) Registered_watch_handle(_handle_registry, *this, alloc); return WATCH_OK; } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } } void close(Vfs_watch_handle *handle) override { - destroy(handle->alloc(), - static_cast(handle)); + destroy(handle->alloc(), static_cast(handle)); } - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override - { - if (!_single_file(path)) - return OPEN_ERR_UNACCESSIBLE; - - try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); - return OPEN_OK; - } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } - } - - Stat_result stat(char const *path, Stat &out) override - { - Stat_result result = Single_file_system::stat(path, out); - out.size = Content_string::size(); - return result; - } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } -}; - - -class Vfs_tresor::Extend_progress_file_system : public Vfs::Single_file_system -{ - private: - - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; - - Watch_handle_registry _handle_registry { }; - - Wrapper &_w; - - using Content_string = String<32>; - - static file_size copy_content(Content_string const &content, - char *dst, size_t const count) - { - copy_cstring(dst, content.string(), count); - size_t const length_without_nul = content.length() - 1; - return count > length_without_nul - 1 ? length_without_nul - : count; - } - - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &dst, - size_t &out_count) override - { - /* EOF */ - if (seek() != 0) { - out_count = 0; - return READ_OK; - } - - /* - * For now trigger extending execution via this hook - * like we do in the Data_file_system. - */ - _w.execute(); - - Wrapper::Extending const & extending { - _w.extending_progress() }; - - if (extending.idle()) { - Content_string const content { "idle" }; - copy_content(content, dst.start, dst.num_bytes); - out_count = dst.num_bytes; - return READ_OK; - } - - if (extending.in_progress()) { - char const * const type = - Wrapper::Extending::type_to_string(extending.type); - Content_string const content { type, " at ", extending.percent_done, "%" }; - copy_content(content, dst.start, dst.num_bytes); - out_count = dst.num_bytes; - return READ_OK; - } - - return READ_ERR_IO; - } - - Write_result write(Const_byte_range_ptr const &, - size_t &) override - { - return WRITE_ERR_IO; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; - - public: - - Extend_progress_file_system(Wrapper &w) - : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) - { - _w.manage_extend_progress_file_system(*this); - } - - static char const *type_name() { return "extend_progress"; } - char const *type() override { return type_name(); } - void trigger_watch_response() - { - _handle_registry.for_each([this] (Registered_watch_handle &handle) { - handle.watch_response(); }); - } - - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override - { - if (!_single_file(path)) - return WATCH_ERR_UNACCESSIBLE; - - try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - - return WATCH_OK; - } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } - catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } - } - - void close(Vfs_watch_handle *handle) override - { - destroy(handle->alloc(), - static_cast(handle)); - } - - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override + Open_result open(char const *path, unsigned, Vfs::Vfs_handle **out_handle, Allocator &alloc) override { if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); + *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, _plugin); return OPEN_OK; } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } + catch (Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } + catch (Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } } Stat_result stat(char const *path, Stat &out) override { Stat_result result = Single_file_system::stat(path, out); - out.size = Content_string::size(); + out.size = Content_string::capacity(); return result; } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_tresor::Rekey_file_system : public Vfs::Single_file_system +class Vfs_tresor::Rekey_file_system : private Noncopyable, public Single_file_system { private: - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; + using Registered_watch_handle = Registered; + using Watch_handle_registry = Registry; Watch_handle_registry _handle_registry { }; - Wrapper &_w; + Plugin &_plugin; - using Content_string = String<32>; + using Content_string = String<11>; - static file_size copy_content(Content_string const &content, - char *dst, size_t const count) + class Vfs_handle : private Noncopyable, public Single_vfs_handle { - copy_cstring(dst, content.string(), count); - size_t const length_without_nul = content.length() - 1; - return count > length_without_nul - 1 ? length_without_nul - : count; - } + private: - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; + Plugin &_plugin; - /* store VBA in case the handle is kept open */ - Virtual_block_address _last_rekeying_vba; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w), - _last_rekeying_vba(_w.rekeying_progress().rekeying_vba) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - /* EOF */ - if (seek() != 0) { - out_count = 0; - return READ_OK; - } - - /* - * For now trigger rekeying execution via this hook - * like we do in the Data_file_system. - */ - _w.execute(); - - Wrapper::Rekeying const & rekeying { - _w.rekeying_progress() }; - - if (rekeying.in_progress()) - return READ_QUEUED; - - if (rekeying.idle()) { - Content_string const content { - rekeying.success() ? "successful" - : "failed" }; - copy_content(content, dst.start, dst.num_bytes); + static Read_result _read_ok(Content_string const &content, Byte_range_ptr const &dst, size_t &out_count) + { + copy_cstring(dst.start, content.string(), dst.num_bytes); out_count = dst.num_bytes; return READ_OK; } - return READ_ERR_IO; - } + public: - Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override - { - if (!_w.rekeying_progress().idle()) { - return WRITE_ERR_IO; + Vfs_handle(Directory_service &dir_service, File_io_service &file_io_service, + Allocator &alloc, Plugin &plugin) + : + Single_vfs_handle(dir_service, file_io_service, alloc, 0), _plugin(plugin) + { } + + /*********************** + ** Single_vfs_handle ** + ***********************/ + + Read_result read(Byte_range_ptr const &dst, size_t &out_count) override + { + out_count = 0; + if (seek() == dst.num_bytes) { + return READ_OK; + } + if (seek() || dst.num_bytes < Content_string::capacity()) { + if (_plugin.verbose()) + log("reading rekey file failed: malformed arguments"); + return READ_ERR_IO; + } + Read_result result = READ_QUEUED; + _plugin.with_rekey_operation([&] (Rekey_operation &rekey_operation) { + + switch (rekey_operation.result()) { + case Rekey_operation::NONE: result = _read_ok("none", dst, out_count); break; + case Rekey_operation::SUCCEEDED: result = _read_ok("succeeded", dst, out_count); break; + case Rekey_operation::FAILED: result = _read_ok("failed", dst, out_count); break; + case Rekey_operation::PENDING: break; + } + }); + return result; } - bool start_rekeying { false }; - Genode::ascii_to(src.start, start_rekeying); + Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override + { + out_count = 0; + bool rekey_arg { false }; + Genode::ascii_to(src.start, rekey_arg); + if (seek() || !rekey_arg) { + if (_plugin.verbose()) + log("writing rekey file failed: malformed arguments"); + return WRITE_ERR_IO; + } + Write_result result = WRITE_ERR_IO; + _plugin.with_rekey_operation([&] (Rekey_operation &rekey_operation) { - if (!start_rekeying) { - return WRITE_ERR_IO; + if (!rekey_operation.request()) { + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing rekey file failed: failed to request operation"); + return; + } + out_count = src.num_bytes; + result = WRITE_OK; + }); + return result; } - if (!_w.start_rekeying()) { - return WRITE_ERR_IO; - } - - out_count = src.num_bytes; - return WRITE_OK; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } + bool read_ready() const override { return true; } + bool write_ready() const override { return true; } }; public: - Rekey_file_system(Wrapper &w) + Rekey_file_system(Plugin &plugin) : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _plugin(plugin) { - _w.manage_rekey_file_system(*this); + _plugin.manage_rekey_file_system(*this); } static char const *type_name() { return "rekey"; } - char const *type() override { return type_name(); } - void trigger_watch_response() { _handle_registry.for_each([this] (Registered_watch_handle &handle) { handle.watch_response(); }); } - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override - { - if (!_single_file(path)) - return WATCH_ERR_UNACCESSIBLE; - - try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - - return WATCH_OK; - } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } - catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } - } - - void close(Vfs_watch_handle *handle) override - { - destroy(handle->alloc(), - static_cast(handle)); - } - - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override - { - if (!_single_file(path)) - return OPEN_ERR_UNACCESSIBLE; - - try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); - return OPEN_OK; - } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } - } - - Stat_result stat(char const *path, Stat &out) override - { - Stat_result result = Single_file_system::stat(path, out); - out.size = Content_string::size(); - return result; - } - - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } -}; - - -class Vfs_tresor::Rekey_progress_file_system : public Vfs::Single_file_system -{ - private: - - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; - - Watch_handle_registry _handle_registry { }; - - Wrapper &_w; - - using Content_string = String<32>; - - static file_size copy_content(Content_string const &content, - char *dst, size_t const count) - { - copy_cstring(dst, content.string(), count); - size_t const length_without_nul = content.length() - 1; - return count > length_without_nul - 1 ? length_without_nul - : count; - } - - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &dst, - size_t &out_count) override - { - /* EOF */ - if (seek() != 0) { - out_count = 0; - return READ_OK; - } - - /* - * For now trigger rekeying execution via this hook - * like we do in the Data_file_system. - */ - _w.execute(); - - Wrapper::Rekeying const & rekeying { - _w.rekeying_progress() }; - - if (rekeying.idle()) { - Content_string const content { "idle" }; - copy_content(content, dst.start, dst.num_bytes); - out_count = dst.num_bytes; - return READ_OK; - } - - if (rekeying.in_progress()) { - Content_string const content { "at ", rekeying.percent_done, "%" }; - copy_content(content, dst.start, dst.num_bytes); - out_count = dst.num_bytes; - return READ_OK; - } - - return READ_ERR_IO; - } - - Write_result write(Const_byte_range_ptr const &, - size_t &) override - { - return WRITE_ERR_IO; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; - - public: - - Rekey_progress_file_system(Wrapper &w) - : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) - { - _w.manage_rekey_progress_file_system(*this); - } - - static char const *type_name() { return "rekey_progress"; } + /************************ + ** Single_file_system ** + ************************/ char const *type() override { return type_name(); } - void trigger_watch_response() - { - _handle_registry.for_each([this] (Registered_watch_handle &handle) { - handle.watch_response(); }); - } - - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override + Watch_result watch(char const *path, Vfs_watch_handle **handle, Allocator &alloc) override { if (!_single_file(path)) return WATCH_ERR_UNACCESSIBLE; try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - + *handle = new (alloc) Registered_watch_handle(_handle_registry, *this, alloc); return WATCH_OK; } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } } void close(Vfs_watch_handle *handle) override { - destroy(handle->alloc(), - static_cast(handle)); + destroy(handle->alloc(), static_cast(handle)); } - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override + Open_result open(char const *path, unsigned, Vfs::Vfs_handle **out_handle, Allocator &alloc) override { if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); + *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, _plugin); return OPEN_OK; } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } + catch (Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } + catch (Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } } Stat_result stat(char const *path, Stat &out) override { Stat_result result = Single_file_system::stat(path, out); - out.size = Content_string::size(); + out.size = Content_string::capacity(); return result; } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_tresor::Deinitialize_file_system : public Vfs::Single_file_system +class Vfs_tresor::Deinitialize_file_system : private Noncopyable, public Single_file_system { private: - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; + using Registered_watch_handle = Registered; + using Watch_handle_registry = Registry; + using Content_string = String<11>; Watch_handle_registry _handle_registry { }; + Plugin &_plugin; - Wrapper &_w; - - using Content_string = String<32>; - - static Content_string content_string(Wrapper const &wrapper) + class Vfs_handle : public Single_vfs_handle { - Wrapper::Deinitialize const & deinitialize_progress { - wrapper.deinitialize_progress() }; + private: - bool const in_progress { deinitialize_progress.in_progress() }; + Plugin &_plugin; - bool const last_result { - !in_progress && - deinitialize_progress.last_result != - Wrapper::Deinitialize::Result::NONE }; - - bool const success { deinitialize_progress.success() }; - - Content_string const result { - Wrapper::Deinitialize::state_to_cstring(deinitialize_progress.state), - " last-result:", - last_result ? success ? "success" : "failed" : "none", - "\n" }; - - return result; - } - - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - if (seek() != 0) { - out_count = 0; + static Read_result _read_ok(Content_string const &content, Byte_range_ptr const &dst, size_t &out_count) + { + copy_cstring(dst.start, content.string(), dst.num_bytes); + out_count = dst.num_bytes; return READ_OK; } - _w.execute(); - Wrapper::Deinitialize const & deinitialize_progress { - _w.deinitialize_progress() }; + public: - if (deinitialize_progress.in_progress()) - return READ_QUEUED; + Vfs_handle(Directory_service &dir_service, File_io_service &file_io_service, + Allocator &alloc, Plugin &plugin) + : + Single_vfs_handle(dir_service, file_io_service, alloc, 0), _plugin(plugin) + { } - Content_string const result { content_string(_w) }; - copy_cstring(dst.start, result.string(), dst.num_bytes); - out_count = dst.num_bytes; + /*********************** + ** Single_vfs_handle ** + ***********************/ - return READ_OK; - } + Read_result read(Byte_range_ptr const &dst, size_t &out_count) override + { + out_count = 0; + if (seek() == dst.num_bytes) { + return READ_OK; + } + if (seek() || dst.num_bytes < Content_string::capacity()) { + if (_plugin.verbose()) + log("reading deinitialize file failed: malformed arguments"); + return READ_ERR_IO; + } + Read_result result = READ_QUEUED; + _plugin.with_deinit_operation([&] (Deinitialize_operation &deinit_operation) { - Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override - { - if (!_w.deinitialize_progress().idle()) { - return WRITE_ERR_IO; + switch (deinit_operation.result()) { + case Deinitialize_operation::NONE: result = _read_ok("none", dst, out_count); break; + case Deinitialize_operation::SUCCEEDED: result = _read_ok("succeeded", dst, out_count); break; + case Deinitialize_operation::FAILED: result = _read_ok("failed", dst, out_count); break; + case Deinitialize_operation::PENDING: break; + } + }); + return result; } - bool start_deinitialize { false }; - Genode::ascii_to(src.start, start_deinitialize); + Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override + { + out_count = 0; + bool deinitialize_arg { false }; + Genode::ascii_to(src.start, deinitialize_arg); + if (seek() || !deinitialize_arg) { + if (_plugin.verbose()) + log("writing deinitialize file failed: malformed arguments"); - if (!start_deinitialize) { - return WRITE_ERR_IO; + return WRITE_ERR_IO; + } + Write_result result = WRITE_ERR_IO; + _plugin.with_deinit_operation([&] (Deinitialize_operation &deinit_operation) { + + if (!deinit_operation.request()) { + result = WRITE_ERR_IO; + if (_plugin.verbose()) + log("writing deinitialize file failed: failed to request operation"); + return; + } + out_count = src.num_bytes; + result = WRITE_OK; + }); + return result; } - if (!_w.start_deinitialize()) { - return WRITE_ERR_IO; - } - - out_count = src.num_bytes; - return WRITE_OK; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } + bool read_ready() const override { return true; } + bool write_ready() const override { return true; } }; public: - Deinitialize_file_system(Wrapper &w) + Deinitialize_file_system(Plugin &plugin) : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("")), - _w(w) + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _plugin(plugin) { - _w.manage_deinit_file_system(*this); + _plugin.manage_deinit_file_system(*this); } static char const *type_name() { return "deinitialize"; } - char const *type() override { return type_name(); } - void trigger_watch_response() { _handle_registry.for_each([this] (Registered_watch_handle &handle) { handle.watch_response(); }); } - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override + /************************ + ** Single_file_system ** + ************************/ + + char const *type() override { return type_name(); } + + Watch_result watch(char const *path, Vfs_watch_handle **handle, Allocator &alloc) override { if (!_single_file(path)) return WATCH_ERR_UNACCESSIBLE; try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - + *handle = new (alloc) Registered_watch_handle(_handle_registry, *this, alloc); return WATCH_OK; } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } + catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } } void close(Vfs_watch_handle *handle) override { - destroy(handle->alloc(), - static_cast(handle)); + destroy(handle->alloc(), static_cast(handle)); } - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override + Open_result open(char const *path, unsigned, Vfs::Vfs_handle **out_handle, Allocator &alloc) override { if (!_single_file(path)) return OPEN_ERR_UNACCESSIBLE; try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); + *out_handle = new (alloc) Vfs_handle(*this, *this, alloc, _plugin); return OPEN_OK; } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } + catch (Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } + catch (Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } } Stat_result stat(char const *path, Stat &out) override { Stat_result result = Single_file_system::stat(path, out); - out.size = content_string(_w).length() - 1; + out.size = Content_string::capacity(); return result; } - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } + Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_tresor::Create_snapshot_file_system : public Vfs::Single_file_system +class Vfs_tresor::Current_local_factory : private Noncopyable, public File_system_factory { private: - Wrapper &_w; + Data_file_system _data_fs; - struct Vfs_handle : Single_vfs_handle + /************************* + ** File_system_factory ** + *************************/ + + Vfs::File_system *create(Vfs::Env&, Xml_node node) override { - Wrapper &_w; + if (node.has_type(Data_file_system::type_name())) + return &_data_fs; - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &, size_t &) override - { - return READ_ERR_IO; - } - - Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override - { - bool create_snapshot { false }; - Genode::ascii_to(src.start, create_snapshot); - Genode::String<64> str(Genode::Cstring(src.start, src.num_bytes)); - if (!create_snapshot) - return WRITE_ERR_IO; - - if (!_w.create_snapshot()) { - out_count = 0; - return WRITE_OK; - } - out_count = src.num_bytes; - return WRITE_OK; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; + return nullptr; + } public: - Create_snapshot_file_system(Wrapper &w) - : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::wo(), Xml_node("")), - _w(w) - { } - - static char const *type_name() { return "create_snapshot"; } - - char const *type() override { return type_name(); } - - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override - { - if (!_single_file(path)) - return OPEN_ERR_UNACCESSIBLE; - - try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); - return OPEN_OK; - } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } - } - - Stat_result stat(char const *path, Stat &out) override - { - Stat_result result = Single_file_system::stat(path, out); - return result; - } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } + Current_local_factory(Vfs::Env &, Plugin &plugin) : _data_fs(plugin) { } }; -class Vfs_tresor::Discard_snapshot_file_system : public Vfs::Single_file_system +class Vfs_tresor::Current_file_system : private Current_local_factory, public Dir_file_system { private: - Wrapper &_w; + using Config = String<128>; - struct Vfs_handle : Single_vfs_handle - { - Wrapper &_w; - - Vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Wrapper &w) - : - Single_vfs_handle(ds, fs, alloc, 0), - _w(w) - { } - - Read_result read(Byte_range_ptr const &, size_t &) override - { - return READ_ERR_IO; - } - - Write_result write(Const_byte_range_ptr const &src, - size_t &out_count) override - { - out_count = 0; - Generation snap_gen { INVALID_GENERATION }; - Genode::ascii_to(src.start, snap_gen); - if (snap_gen == INVALID_GENERATION) - return WRITE_ERR_IO; - - if (!_w.discard_snapshot(snap_gen)) { - out_count = 0; - return WRITE_OK; - } - return WRITE_ERR_IO; - } - - bool read_ready() const override { return true; } - bool write_ready() const override { return true; } - }; - - public: - - Discard_snapshot_file_system(Wrapper &w) - : - Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::wo(), Xml_node("")), - _w(w) - { } - - static char const *type_name() { return "discard_snapshot"; } - - char const *type() override { return type_name(); } - - - /********************************* - ** Directory-service interface ** - *********************************/ - - Open_result open(char const *path, unsigned, - Vfs::Vfs_handle **out_handle, - Genode::Allocator &alloc) override - { - if (!_single_file(path)) - return OPEN_ERR_UNACCESSIBLE; - - try { - *out_handle = - new (alloc) Vfs_handle(*this, *this, alloc, _w); - return OPEN_OK; - } - catch (Genode::Out_of_ram) { return OPEN_ERR_OUT_OF_RAM; } - catch (Genode::Out_of_caps) { return OPEN_ERR_OUT_OF_CAPS; } - } - - Stat_result stat(char const *path, Stat &out) override - { - Stat_result result = Single_file_system::stat(path, out); - return result; - } - - /******************************** - ** File I/O service interface ** - ********************************/ - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } -}; - - -struct Vfs_tresor::Snapshot_local_factory : File_system_factory -{ - Data_file_system _block_fs; - - Snapshot_local_factory(Vfs::Env & /* env */, - Wrapper &tresor, - Generation snap_gen) - : _block_fs(tresor, snap_gen) { } - - Vfs::File_system *create(Vfs::Env&, Xml_node node) override - { - if (node.has_type(Data_file_system::type_name())) - return &_block_fs; - - return nullptr; - } -}; - - -class Vfs_tresor::Snapshot_file_system : private Snapshot_local_factory, - public Vfs::Dir_file_system -{ - private: - - Generation _snap_gen; - - typedef String<128> Config; - - static Config _config(Generation snap_gen, bool readonly) + static Config _config() { char buf[Config::capacity()] { }; - - Xml_generator xml(buf, sizeof(buf), "dir", [&] () { - - xml.attribute("name", !readonly ? String<16>("current") : String<16>(snap_gen)); + Xml_generator xml(buf, sizeof(buf), "dir", [&] () + { + xml.attribute("name", String<16>("current")); xml.node("data", [&] () { - xml.attribute("readonly", readonly); + xml.attribute("readonly", false); }); }); @@ -2393,895 +1540,397 @@ class Vfs_tresor::Snapshot_file_system : private Snapshot_local_factory, public: - Snapshot_file_system(Vfs::Env &vfs_env, - Wrapper &tresor, - Generation snap_gen, - bool readonly = false) + Current_file_system(Vfs::Env &vfs_env, Plugin &plugin) : - Snapshot_local_factory(vfs_env, tresor, snap_gen), - Vfs::Dir_file_system(vfs_env, Xml_node(_config(snap_gen, readonly).string()), *this), - _snap_gen(snap_gen) + Current_local_factory(vfs_env, plugin), + Dir_file_system(vfs_env, Xml_node(_config().string()), *this) { } - static char const *type_name() { return "snapshot"; } + static char const *type_name() { return "current"; } + + /********************* + ** Dir_file_system ** + *********************/ char const *type() override { return type_name(); } - - Generation snap_gen() const { return _snap_gen; } }; -class Vfs_tresor::Snapshots_file_system : public Vfs::File_system +class Vfs_tresor::Control_local_factory : private Noncopyable, public File_system_factory { private: - typedef Registered Registered_watch_handle; - typedef Registry Watch_handle_registry; - - Watch_handle_registry _handle_registry { }; - - Vfs::Env &_vfs_env; - - bool _root_dir(char const *path) { return strcmp(path, "/snapshots") == 0; } - bool _top_dir(char const *path) { return strcmp(path, "/") == 0; } - - struct Snapshot_registry - { - Genode::Allocator &_alloc; - Wrapper &_wrapper; - Snapshots_file_system &_snapshots_fs; - uint32_t _number_of_snapshots { 0 }; - Genode::Registry> _registry { }; - - struct Invalid_index : Genode::Exception { }; - struct Invalid_path : Genode::Exception { }; - - - - Snapshot_registry(Genode::Allocator &alloc, - Wrapper &wrapper, - Snapshots_file_system &snapshots_fs) - : - _alloc { alloc }, - _wrapper { wrapper }, - _snapshots_fs { snapshots_fs } - { } - - void update(Vfs::Env &vfs_env); - - uint32_t number_of_snapshots() const { return _number_of_snapshots; } - - Snapshot_file_system const &by_index(uint64_t idx) const - { - uint64_t i = 0; - Snapshot_file_system const *fsp { nullptr }; - auto lookup = [&] (Snapshot_file_system const &fs) { - if (i == idx) { - fsp = &fs; - } - ++i; - }; - _registry.for_each(lookup); - if (fsp == nullptr) { - throw Invalid_index(); - } - return *fsp; - } - - Snapshot_file_system &_by_gen(Generation snap_gen) - { - Snapshot_file_system *fsp { nullptr }; - auto lookup = [&] (Snapshot_file_system &fs) { - if (fs.snap_gen() == snap_gen) { - fsp = &fs; - } - }; - _registry.for_each(lookup); - if (fsp == nullptr) - throw Invalid_path(); - - return *fsp; - } - - Snapshot_file_system &by_path(char const *path) - { - if (!path) - throw Invalid_path(); - - if (path[0] == '/') - path++; - - Generation snap_gen { INVALID_GENERATION }; - Genode::ascii_to(path, snap_gen); - return _by_gen(snap_gen); - } - }; + Plugin &_plugin; + Rekey_file_system _rekey_fs; + Deinitialize_file_system _deinitialize_fs; + Extend_file_system _extend_fs; public: - void update_snapshot_registry() - { - _snap_reg.update(_vfs_env); - } - - void trigger_watch_response() - { - _handle_registry.for_each([this] (Registered_watch_handle &handle) { - handle.watch_response(); }); - } - - Watch_result watch(char const *path, - Vfs_watch_handle **handle, - Allocator &alloc) override - { - if (!_root_dir(path)) - return WATCH_ERR_UNACCESSIBLE; - - try { - *handle = new (alloc) - Registered_watch_handle(_handle_registry, *this, alloc); - - return WATCH_OK; - } - catch (Out_of_ram) { return WATCH_ERR_OUT_OF_RAM; } - catch (Out_of_caps) { return WATCH_ERR_OUT_OF_CAPS; } - } - - void close(Vfs_watch_handle *handle) override - { - destroy(handle->alloc(), - static_cast(handle)); - } - - struct Snap_vfs_handle : Vfs::Vfs_handle - { - using Vfs_handle::Vfs_handle; - - virtual Read_result read(Byte_range_ptr const &, size_t &out_count) = 0; - - virtual Write_result write(Const_byte_range_ptr const &, size_t &out_count) = 0; - - virtual Sync_result sync() - { - return SYNC_OK; - } - - virtual bool read_ready() const = 0; - }; - - - struct Dir_vfs_handle : Snap_vfs_handle - { - Snapshot_registry const &_snap_reg; - - bool const _root_dir { false }; - - Read_result _query_snapshots(size_t index, - size_t &out_count, - Dirent &out) - { - if (index >= _snap_reg.number_of_snapshots()) { - out_count = sizeof(Dirent); - out.type = Dirent_type::END; - return READ_OK; - } - - try { - Snapshot_file_system const &fs = _snap_reg.by_index(index); - Genode::String<32> name { fs.snap_gen() }; - - out = { - .fileno = (Genode::addr_t)this | index, - .type = Dirent_type::DIRECTORY, - .rwx = Node_rwx::rx(), - .name = { name.string() }, - }; - out_count = sizeof(Dirent); - return READ_OK; - } catch (Snapshot_registry::Invalid_index) { - return READ_ERR_INVALID; - } - } - - Read_result _query_root(size_t index, - size_t &out_count, - Dirent &out) - { - if (index == 0) { - out = { - .fileno = (Genode::addr_t)this, - .type = Dirent_type::DIRECTORY, - .rwx = Node_rwx::rx(), - .name = { "snapshots" } - }; - } else { - out.type = Dirent_type::END; - } - - out_count = sizeof(Dirent); - return READ_OK; - } - - Dir_vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Snapshot_registry const &snap_reg, - bool root_dir) - : - Snap_vfs_handle(ds, fs, alloc, 0), - _snap_reg(snap_reg), _root_dir(root_dir) - { } - - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override - { - out_count = 0; - - if (dst.num_bytes < sizeof(Dirent)) - return READ_ERR_INVALID; - - size_t index = size_t(seek() / sizeof(Dirent)); - - Dirent &out = *(Dirent*)dst.start; - - if (!_root_dir) { - - /* opended as "/snapshots" */ - return _query_snapshots(index, out_count, out); - - } else { - /* opened as "/" */ - return _query_root(index, out_count, out); - } - } - - Write_result write(Const_byte_range_ptr const &, size_t &) override - { - return WRITE_ERR_INVALID; - } - - bool read_ready() const override { return true; } - }; - - struct Dir_snap_vfs_handle : Vfs::Vfs_handle - { - Vfs_handle &vfs_handle; - - Dir_snap_vfs_handle(Directory_service &ds, - File_io_service &fs, - Genode::Allocator &alloc, - Vfs::Vfs_handle &vfs_handle) - : Vfs_handle(ds, fs, alloc, 0), vfs_handle(vfs_handle) { } - - ~Dir_snap_vfs_handle() - { - vfs_handle.close(); - } - }; - - Snapshot_registry _snap_reg; - Wrapper &_wrapper; - - char const *_sub_path(char const *path) const - { - /* skip heading slash in path if present */ - if (path[0] == '/') { - path++; - } - - Genode::size_t const name_len = strlen(type_name()); - if (strcmp(path, type_name(), name_len) != 0) { - return nullptr; - } - - path += name_len; - - /* - * The first characters of the first path element are equal to - * the current directory name. Let's check if the length of the - * first path element matches the name length. - */ - if (*path != 0 && *path != '/') { - return 0; - } - - return path; - } - - - Snapshots_file_system(Vfs::Env &vfs_env, - Genode::Xml_node /* node */, - Wrapper &wrapper) + Control_local_factory(Vfs::Env &, Xml_node, Plugin &plugin) : - _vfs_env { vfs_env }, - _snap_reg { vfs_env.alloc(), wrapper, *this }, - _wrapper { wrapper } + _plugin(plugin), _rekey_fs(plugin), _deinitialize_fs(plugin), _extend_fs(plugin) + { } + + ~Control_local_factory() { - _wrapper.manage_snapshots_file_system(*this); + _plugin.dissolve_rekey_file_system(_rekey_fs); + _plugin.dissolve_deinit_file_system(_deinitialize_fs); + _plugin.dissolve_extend_file_system(_extend_fs); } - static char const *type_name() { return "snapshots"; } + /************************* + ** File_system_factory ** + *************************/ - char const *type() override { return type_name(); } - - - /********************************* - ** Directory service interface ** - *********************************/ - - Dataspace_capability dataspace(char const * /* path */) override + Vfs::File_system *create(Vfs::Env&, Xml_node node) override { - return Genode::Dataspace_capability(); - } + if (node.has_type(Rekey_file_system::type_name())) + return &_rekey_fs; - void release(char const * /* path */, Dataspace_capability) override - { - } + if (node.has_type(Deinitialize_file_system::type_name())) + return &_deinitialize_fs; - Open_result open(char const *path, - unsigned mode, - Vfs::Vfs_handle **out_handle, - Allocator &alloc) override - { - path = _sub_path(path); - if (!path || path[0] != '/') { - return OPEN_ERR_UNACCESSIBLE; - } - - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - return fs.open(path, mode, out_handle, alloc); - } catch (Snapshot_registry::Invalid_path) { } - - return OPEN_ERR_UNACCESSIBLE; - } - - Opendir_result opendir(char const *path, - bool create, - Vfs::Vfs_handle **out_handle, - Allocator &alloc) override - { - if (create) { - return OPENDIR_ERR_PERMISSION_DENIED; - } - - bool const top = _top_dir(path); - if (_root_dir(path) || top) { - _snap_reg.update(_vfs_env); - - *out_handle = new (alloc) Dir_vfs_handle(*this, *this, alloc, - _snap_reg, top); - return OPENDIR_OK; - } else { - char const *sub_path = _sub_path(path); - if (!sub_path) { - return OPENDIR_ERR_LOOKUP_FAILED; - } - try { - Snapshot_file_system &fs = _snap_reg.by_path(sub_path); - Vfs::Vfs_handle *handle = nullptr; - Opendir_result const res = fs.opendir(sub_path, create, &handle, alloc); - if (res != OPENDIR_OK) { - return OPENDIR_ERR_LOOKUP_FAILED; - } - *out_handle = new (alloc) Dir_snap_vfs_handle(*this, *this, - alloc, *handle); - return OPENDIR_OK; - } catch (Snapshot_registry::Invalid_path) { } - } - return OPENDIR_ERR_LOOKUP_FAILED; - } - - void close(Vfs_handle *handle) override - { - if (handle && (&handle->ds() == this)) - destroy(handle->alloc(), handle); - } - - Stat_result stat(char const *path, Stat &out_stat) override - { - out_stat = Stat { }; - path = _sub_path(path); - - /* path does not match directory name */ - if (!path) { - return STAT_ERR_NO_ENTRY; - } - - /* - * If path equals directory name, return information about the - * current directory. - */ - if (strlen(path) == 0 || _top_dir(path)) { - - out_stat.type = Node_type::DIRECTORY; - out_stat.inode = 1; - out_stat.device = (Genode::addr_t)this; - return STAT_OK; - } - - if (!path || path[0] != '/') { - return STAT_ERR_NO_ENTRY; - } - - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - Stat_result const res = fs.stat(path, out_stat); - return res; - } catch (Snapshot_registry::Invalid_path) { } - - return STAT_ERR_NO_ENTRY; - } - - Unlink_result unlink(char const * /* path */) override - { - return UNLINK_ERR_NO_PERM; - } - - Rename_result rename(char const * /* from */, char const * /* to */) override - { - return RENAME_ERR_NO_PERM; - } - - file_size num_dirent(char const *path) override - { - if (_top_dir(path)) { - return 1; - } - if (_root_dir(path)) { - _snap_reg.update(_vfs_env); - file_size const num = _snap_reg.number_of_snapshots(); - return num; - } - _snap_reg.update(_vfs_env); - - path = _sub_path(path); - if (!path) { - return 0; - } - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - file_size const num = fs.num_dirent(path); - return num; - } catch (Snapshot_registry::Invalid_path) { - return 0; - } - } - - bool directory(char const *path) override - { - if (_root_dir(path)) { - return true; - } - - path = _sub_path(path); - if (!path) { - return false; - } - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - return fs.directory(path); - } catch (Snapshot_registry::Invalid_path) { } - - return false; - } - - char const *leaf_path(char const *path) override - { - path = _sub_path(path); - if (!path) { - return nullptr; - } - - if (strlen(path) == 0 || strcmp(path, "") == 0) { - return path; - } - - try { - Snapshot_file_system &fs = _snap_reg.by_path(path); - char const *leaf_path = fs.leaf_path(path); - if (leaf_path) { - return leaf_path; - } - } catch (Snapshot_registry::Invalid_path) { } + if (node.has_type(Extend_file_system::type_name())) + return &_extend_fs; return nullptr; } - - - /******************************** - ** File I/O service interface ** - ********************************/ - - Write_result write(Vfs::Vfs_handle * /* vfs_handle */, - Const_byte_range_ptr const &, size_t & /* out_count */) override - { - return WRITE_ERR_IO; - } - - bool queue_read(Vfs::Vfs_handle *vfs_handle, size_t size) override - { - Dir_snap_vfs_handle *dh = - dynamic_cast(vfs_handle); - if (dh) { - return dh->vfs_handle.fs().queue_read(&dh->vfs_handle, size); - } - - return true; - } - - Read_result complete_read(Vfs::Vfs_handle *vfs_handle, - Byte_range_ptr const &dst, - size_t & out_count) override - { - Snap_vfs_handle *sh = - dynamic_cast(vfs_handle); - if (sh) { - Read_result const res = sh->read(dst, out_count); - return res; - } - - Dir_snap_vfs_handle *dh = - dynamic_cast(vfs_handle); - if (dh) { - return dh->vfs_handle.fs().complete_read(&dh->vfs_handle, - dst, out_count); - } - - return READ_ERR_IO; - } - - bool read_ready(Vfs::Vfs_handle const &) const override { - return true; } - - bool write_ready(Vfs::Vfs_handle const &) const override { - return false; } - - Ftruncate_result ftruncate(Vfs::Vfs_handle *, file_size) override { - return FTRUNCATE_OK; } }; -struct Vfs_tresor::Control_local_factory : File_system_factory -{ - Wrapper &_wrapper; - Rekey_file_system _rekeying_fs; - Rekey_progress_file_system _rekeying_progress_fs; - Deinitialize_file_system _deinitialize_fs; - Create_snapshot_file_system _create_snapshot_fs; - Discard_snapshot_file_system _discard_snapshot_fs; - Extend_file_system _extend_fs; - Extend_progress_file_system _extend_progress_fs; - - Control_local_factory(Vfs::Env & /* env */, - Xml_node /* config */, - Wrapper & wrapper) - : - _wrapper(wrapper), - _rekeying_fs(wrapper), - _rekeying_progress_fs(wrapper), - _deinitialize_fs(wrapper), - _create_snapshot_fs(wrapper), - _discard_snapshot_fs(wrapper), - _extend_fs(wrapper), - _extend_progress_fs(wrapper) - { } - - ~Control_local_factory() - { - _wrapper.dissolve_rekey_file_system(_rekeying_fs); - _wrapper.dissolve_rekey_progress_file_system(_rekeying_progress_fs); - _wrapper.dissolve_deinit_file_system(_deinitialize_fs); - _wrapper.dissolve_extend_file_system(_extend_fs); - _wrapper.dissolve_extend_progress_file_system(_extend_progress_fs); - } - - Vfs::File_system *create(Vfs::Env&, Xml_node node) override - { - if (node.has_type(Rekey_file_system::type_name())) { - return &_rekeying_fs; - } - - if (node.has_type(Rekey_progress_file_system::type_name())) { - return &_rekeying_progress_fs; - } - - if (node.has_type(Deinitialize_file_system::type_name())) { - return &_deinitialize_fs; - } - - if (node.has_type(Create_snapshot_file_system::type_name())) { - return &_create_snapshot_fs; - } - - if (node.has_type(Discard_snapshot_file_system::type_name())) { - return &_discard_snapshot_fs; - } - - if (node.has_type(Extend_file_system::type_name())) { - return &_extend_fs; - } - - if (node.has_type(Extend_progress_file_system::type_name())) { - return &_extend_progress_fs; - } - - return nullptr; - } -}; - - -class Vfs_tresor::Control_file_system : private Control_local_factory, - public Vfs::Dir_file_system +class Vfs_tresor::Control_file_system : private Control_local_factory, public Dir_file_system { private: - typedef String<256> Config; + using Config = String<256>; - static Config _config(Xml_node /* node */) + static Config _config() { char buf[Config::capacity()] { }; - Xml_generator xml(buf, sizeof(buf), "dir", [&] () { xml.attribute("name", "control"); xml.node("rekey", [&] () { }); - xml.node("rekey_progress", [&] () { }); xml.node("extend", [&] () { }); - xml.node("extend_progress", [&] () { }); - xml.node("create_snapshot", [&] () { }); - xml.node("discard_snapshot", [&] () { }); xml.node("deinitialize", [&] () { }); }); - return Config(Cstring(buf)); } public: - Control_file_system(Vfs::Env &vfs_env, - Genode::Xml_node node, - Wrapper &tresor) + Control_file_system(Vfs::Env &vfs_env, Xml_node node, Plugin &plugin) : - Control_local_factory(vfs_env, node, tresor), - Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), - *this) + Control_local_factory(vfs_env, node, plugin), + Dir_file_system(vfs_env, Xml_node(_config().string()), *this) { } static char const *type_name() { return "control"; } + /********************* + ** Dir_file_system ** + *********************/ + char const *type() override { return type_name(); } }; -struct Vfs_tresor::Local_factory : File_system_factory -{ - Wrapper &_wrapper; - Snapshot_file_system _current_snapshot_fs; - Snapshots_file_system _snapshots_fs; - Control_file_system _control_fs; - - Local_factory(Vfs::Env &env, Xml_node config, - Wrapper &wrapper) - : - _wrapper(wrapper), - _current_snapshot_fs(env, wrapper, 0, false), - _snapshots_fs(env, config, wrapper), - _control_fs(env, config, wrapper) - { } - - ~Local_factory() - { - _wrapper.dissolve_snapshots_file_system(_snapshots_fs); - } - - Vfs::File_system *create(Vfs::Env&, Xml_node node) override - { - using Name = String<64>; - if (node.has_type(Snapshot_file_system::type_name()) - && node.attribute_value("name", Name()) == "current") - return &_current_snapshot_fs; - - if (node.has_type(Control_file_system::type_name())) - return &_control_fs; - - if (node.has_type(Snapshots_file_system::type_name())) - return &_snapshots_fs; - - return nullptr; - } -}; - - -class Vfs_tresor::File_system : private Local_factory, - public Vfs::Dir_file_system +class Vfs_tresor::Local_factory : private Noncopyable, public File_system_factory { private: - Wrapper &_wrapper; + Plugin &_plugin; + Current_file_system _current_fs; + Control_file_system _control_fs; - typedef String<256> Config; + public: + + Local_factory(Vfs::Env &vfs_env, Xml_node config, Plugin &plugin) + : + _plugin(plugin), _current_fs(vfs_env, plugin), _control_fs(vfs_env, config, plugin) + { } + + /************************* + ** File_system_factory ** + *************************/ + + Vfs::File_system *create(Vfs::Env&, Xml_node node) override + { + if (node.has_type(Current_file_system::type_name())) + return &_current_fs; + + if (node.has_type(Control_file_system::type_name())) + return &_control_fs; + + return nullptr; + } +}; + + +class Vfs_tresor::File_system : private Local_factory, public Dir_file_system +{ + private: + + using Config = String<256>; + + Plugin &_plugin; static Config _config(Xml_node node) { char buf[Config::capacity()] { }; - - Xml_generator xml(buf, sizeof(buf), "dir", [&] () { - typedef String<64> Name; - - xml.attribute("name", - node.attribute_value("name", - Name("tresor"))); - + Xml_generator xml(buf, sizeof(buf), "dir", [&] () + { + xml.attribute("name", node.attribute_value("name", String<64>("tresor"))); xml.node("control", [&] () { }); - - xml.node("snapshot", [&] () { - xml.attribute("name", "current"); - }); - - xml.node("snapshots", [&] () { }); + xml.node("current", [&] () { }); }); - return Config(Cstring(buf)); } public: - File_system(Vfs::Env &vfs_env, Genode::Xml_node node, - Wrapper &wrapper) + File_system(Vfs::Env &vfs_env, Xml_node node, Plugin &plugin) : - Local_factory(vfs_env, node, wrapper), - Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), - *this), - _wrapper(wrapper) + Local_factory(vfs_env, node, plugin), + Dir_file_system(vfs_env, Xml_node(_config(node).string()), *this), + _plugin(plugin) { } - - ~File_system() - { - // XXX rather then destroying the wrapper here, it should be - // done on the out-side where it was allocated in the first - // place but the factory interface does not support that yet - // destroy(vfs_env.alloc().alloc()), &_wrapper); - } }; -/************************** - ** VFS plugin interface ** - **************************/ - -extern "C" Vfs::File_system_factory *vfs_file_system_factory(void) +bool Vfs_tresor::Rekey_operation::execute(Execute_attr const &attr) { - struct Factory : Vfs::File_system_factory - { - Vfs::File_system *create(Vfs::Env &vfs_env, - Genode::Xml_node node) override - { - try { - /* XXX wrapper is not managed and will leak */ - Vfs_tresor::Wrapper *wrapper = - new (vfs_env.alloc()) Vfs_tresor::Wrapper { vfs_env, node }; - return new (vfs_env.alloc()) - Vfs_tresor::File_system(vfs_env, node, *wrapper); - } catch (...) { - Genode::error("could not create 'tresor_fs' "); + bool progress = false; + switch (_state) { + case STARTED: + + _rekey.construct(Superblock_control::Rekey::Attr{_complete}); + _state = REKEY; + progress = true; + if (_verbose) + log("rekey started"); + break; + + case REKEY: + + progress |= attr.sb_control.execute( + *_rekey, attr.vbd, attr.free_tree, attr.meta_tree, attr.block_io, attr.crypto, attr.trust_anchor); + + if (_rekey->complete()) { + if (_rekey->success()) { + if (_complete) { + _success = true; + _state = COMPLETE; + if (attr.rekey_fs_ptr) + attr.rekey_fs_ptr->trigger_watch_response(); + if (_verbose) + log("rekey succeeded"); + } else + _state = PAUSED; + } else { + _success = false; + _state = COMPLETE; + if (attr.rekey_fs_ptr) + attr.rekey_fs_ptr->trigger_watch_response(); + if (_verbose) + log("rekey failed"); } - return nullptr; + _rekey.destruct(); + progress = true; } + break; + + case RESUMED: + + _rekey.construct(Superblock_control::Rekey::Attr{_complete}); + _state = REKEY; + progress = true; + break; + + default: break; + } + return progress; +} + + +bool Vfs_tresor::Extend_operation::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_state) { + case EXTEND_FT_STARTED: + + _extend_ft.construct(Superblock_control::Extend_free_tree::Attr{_num_blocks, _complete}); + _state = EXTEND_FT; + progress = true; + if (_verbose) + log("extend free tree started"); + break; + + case EXTEND_FT: + + progress |= attr.sb_control.execute( + *_extend_ft, attr.free_tree, attr.meta_tree, attr.block_io, attr.trust_anchor); + + if (_extend_ft->complete()) { + if (_extend_ft->success()) { + if (_complete) { + _success = true; + _state = COMPLETE; + if (attr.extend_fs_ptr) + attr.extend_fs_ptr->trigger_watch_response(); + if (_verbose) + log("extend free tree succeeded"); + } else + _state = EXTEND_FT_PAUSED; + } else { + _success = false; + _state = COMPLETE; + if (attr.extend_fs_ptr) + attr.extend_fs_ptr->trigger_watch_response(); + if (_verbose) + log("extend free tree failed"); + } + _extend_ft.destruct(); + progress = true; + } + break; + + case EXTEND_FT_RESUMED: + + _extend_ft.construct(Superblock_control::Extend_free_tree::Attr{_num_blocks, _complete}); + _state = EXTEND_FT; + progress = true; + break; + + case EXTEND_VBD_STARTED: + + _extend_vbd.construct(Superblock_control::Extend_vbd::Attr{_num_blocks, _complete}); + _state = EXTEND_VBD; + progress = true; + if (_verbose) + log("extend virtual block device started"); + break; + + case EXTEND_VBD: + + progress |= attr.sb_control.execute( + *_extend_vbd, attr.vbd, attr.free_tree, attr.meta_tree, attr.block_io, attr.trust_anchor); + + if (_extend_vbd->complete()) { + if (_extend_vbd->success()) { + if (_complete) { + _success = true; + _state = COMPLETE; + if (attr.extend_fs_ptr) + attr.extend_fs_ptr->trigger_watch_response(); + if (_verbose) + log("extend virtual block device succeeded"); + } else + _state = EXTEND_VBD_PAUSED; + } else { + _success = false; + _state = COMPLETE; + if (attr.extend_fs_ptr) + attr.extend_fs_ptr->trigger_watch_response(); + if (_verbose) + log("extend virtual block device failed"); + } + _extend_vbd.destruct(); + progress = true; + } + break; + + case EXTEND_VBD_RESUMED: + + _extend_vbd.construct(Superblock_control::Extend_vbd::Attr{_num_blocks, _complete}); + _state = EXTEND_VBD; + progress = true; + break; + + default: break; + } + return progress; +} + + +bool Vfs_tresor::Deinitialize_operation::execute(Execute_attr const &attr) +{ + bool progress = false; + switch (_state) { + case STARTED: + + _deinit_sb_control.construct(Superblock_control::Deinitialize::Attr{}); + _state = DEINIT_SB_CONTROL; + progress = true; + if (_verbose) + log("deinitialize started"); + break; + + case DEINIT_SB_CONTROL: + + progress |= attr.sb_control.execute( + *_deinit_sb_control, attr.block_io, attr.crypto, attr.trust_anchor); + + if (_deinit_sb_control->complete()) { + if (_deinit_sb_control->success()) { + _success = true; + _state = COMPLETE; + if (_verbose) + log("deinitialize succeeded"); + } else { + _success = false; + _state = DEINIT_SB_CONTROL; + if (_verbose) + log("deinitialize failed"); + } + _deinit_sb_control.destruct(); + if (attr.deinit_fs_ptr) + attr.deinit_fs_ptr->trigger_watch_response(); + progress = true; + } + break; + + default: break; + } + return progress; +} + + +extern "C" File_system_factory *vfs_file_system_factory(void) +{ + class Factory : public File_system_factory + { + private: + + Allocator *_plugin_alloc_ptr { }; + Vfs_tresor::Plugin *_plugin_ptr { }; + + public: + + ~Factory() + { + if (_plugin_ptr) + destroy(_plugin_alloc_ptr, _plugin_ptr); + } + + /************************* + ** File_system_factory ** + *************************/ + + Vfs::File_system *create(Vfs::Env &vfs_env, Xml_node node) override + { + try { + if (!_plugin_ptr) { + _plugin_alloc_ptr = &vfs_env.alloc(); + _plugin_ptr = new (_plugin_alloc_ptr) Vfs_tresor::Plugin { vfs_env, node }; + } + return new (vfs_env.alloc()) Vfs_tresor::File_system(vfs_env, node, *_plugin_ptr); + + } catch (...) { error("could not create 'tresor_fs' "); } + return nullptr; + } }; - static Factory factory; + static Factory factory { }; return &factory; } - - -/********************** - ** Vfs_tresor::Wrapper ** - **********************/ - -void Vfs_tresor::Wrapper::_snapshots_fs_update_snapshot_registry() -{ - if (_snapshots_fs.valid()) { - _snapshots_fs.obj().update_snapshot_registry(); - } -} - - -void Vfs_tresor::Wrapper::_extend_fs_trigger_watch_response() -{ - if (_extend_fs.valid()) { - _extend_fs.obj().trigger_watch_response(); - } -} - - -void Vfs_tresor::Wrapper::_extend_progress_fs_trigger_watch_response() -{ - if (_extend_progress_fs.valid()) { - _extend_progress_fs.obj().trigger_watch_response(); - } -} - - -void Vfs_tresor::Wrapper::_rekey_fs_trigger_watch_response() -{ - if (_rekey_fs.valid()) { - _rekey_fs.obj().trigger_watch_response(); - } -} - - -void Vfs_tresor::Wrapper::_rekey_progress_fs_trigger_watch_response() -{ - if (_rekey_progress_fs.valid()) { - _rekey_progress_fs.obj().trigger_watch_response(); - } -} - - -void Vfs_tresor::Wrapper::_deinit_fs_trigger_watch_response() -{ - if (_deinit_fs.valid()) { - _deinit_fs.obj().trigger_watch_response(); - } -} - - -/******************************************************* - ** Vfs_tresor::Snapshots_file_system::Snapshot_registry ** - *******************************************************/ - -void Vfs_tresor::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_env) -{ - Tresor::Snapshots_info snap_info { }; - _wrapper.snapshots_info(snap_info); - bool trigger_watch_response { false }; - - /* alloc new */ - for (size_t i = 0; i < MAX_NR_OF_SNAPSHOTS; i++) { - - Generation const snap_gen = snap_info.generations[i]; - if (snap_gen == INVALID_GENERATION) - continue; - - bool is_old = false; - auto find_old = [&] (Snapshot_file_system const &fs) { - is_old |= (fs.snap_gen() == snap_gen); - }; - _registry.for_each(find_old); - - if (!is_old) { - - new (_alloc) - Genode::Registered { - _registry, vfs_env, _wrapper, snap_gen, true }; - - ++_number_of_snapshots; - trigger_watch_response = true; - } - } - - /* destroy old */ - auto find_stale = [&] (Snapshot_file_system const &fs) - { - bool is_stale = true; - for (size_t i = 0; i < MAX_NR_OF_SNAPSHOTS; i++) { - Generation const snap_gen = snap_info.generations[i]; - if (snap_gen == INVALID_GENERATION) - continue; - - if (fs.snap_gen() == snap_gen) { - is_stale = false; - break; - } - } - - if (is_stale) { - destroy(&_alloc, &const_cast(fs)); - --_number_of_snapshots; - trigger_watch_response = true; - } - }; - _registry.for_each(find_stale); - if (trigger_watch_response) { - _snapshots_fs.trigger_watch_response(); - } -} diff --git a/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc b/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc index 6c82931dc8..053fd27b0f 100644 --- a/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc @@ -65,10 +65,7 @@ class Vfs_tresor_crypto::Encrypt_file_system : public Vfs::Single_file_system Tresor_crypto::Interface &crypto, uint32_t key_id) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _crypto { crypto }, - _key_id { key_id }, - _state { State::NONE } + Single_vfs_handle(ds, fs, alloc, 0), _crypto(crypto), _key_id(key_id), _state(State::NONE) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -130,10 +127,8 @@ class Vfs_tresor_crypto::Encrypt_file_system : public Vfs::Single_file_system Encrypt_file_system(Tresor_crypto::Interface &crypto, uint32_t key_id) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _crypto { crypto }, - _key_id { key_id } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _crypto(crypto), _key_id(key_id) { } static char const *type_name() { return "encrypt"; } @@ -199,10 +194,7 @@ class Vfs_tresor_crypto::Decrypt_file_system : public Vfs::Single_file_system Tresor_crypto::Interface &crypto, uint32_t key_id) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _crypto { crypto }, - _key_id { key_id }, - _state { State::NONE } + Single_vfs_handle(ds, fs, alloc, 0), _crypto(crypto), _key_id(key_id), _state(State::NONE) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -261,10 +253,8 @@ class Vfs_tresor_crypto::Decrypt_file_system : public Vfs::Single_file_system Decrypt_file_system(Tresor_crypto::Interface &crypto, uint32_t key_id) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _crypto { crypto }, - _key_id { key_id } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _crypto(crypto), _key_id(key_id) { } static char const *type_name() { return "decrypt"; } @@ -317,8 +307,7 @@ struct Vfs_tresor_crypto::Key_local_factory : File_system_factory Key_local_factory(Tresor_crypto::Interface &crypto, uint32_t key_id) : - _encrypt_fs { crypto, key_id }, - _decrypt_fs { crypto, key_id } + _encrypt_fs(crypto, key_id), _decrypt_fs(crypto, key_id) { } Vfs::File_system *create(Vfs::Env&, Xml_node node) override @@ -364,11 +353,8 @@ class Vfs_tresor_crypto::Key_file_system : private Key_local_factory, Tresor_crypto::Interface &crypto, uint32_t key_id) : - Key_local_factory { crypto, key_id }, - Vfs::Dir_file_system { vfs_env, - Xml_node(_config(key_id).string()), - *this }, - _key_id { key_id } + Key_local_factory(crypto, key_id), + Vfs::Dir_file_system(vfs_env, Xml_node(_config(key_id).string()), *this), _key_id(key_id) { } static char const *type_name() { return "keys"; } @@ -405,8 +391,7 @@ class Vfs_tresor_crypto::Keys_file_system : public Vfs::File_system Key_registry(Genode::Allocator &alloc, Tresor_crypto::Interface &crypto) : - _alloc { alloc }, - _crypto { crypto } + _alloc(alloc), _crypto(crypto) { } void update(Vfs::Env &vfs_env) @@ -652,8 +637,7 @@ class Vfs_tresor_crypto::Keys_file_system : public Vfs::File_system Keys_file_system(Vfs::Env &vfs_env, Tresor_crypto::Interface &crypto) : - _vfs_env { vfs_env }, - _key_reg { vfs_env.alloc(), crypto } + _vfs_env(vfs_env), _key_reg(vfs_env.alloc(), crypto) { } static char const *type_name() { return "keys"; } @@ -940,9 +924,7 @@ class Vfs_tresor_crypto::Management_file_system : public Vfs::Single_file_system Type type, Tresor_crypto::Interface &crypto) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _type { type }, - _crypto { crypto } + Single_vfs_handle(ds, fs, alloc, 0), _type(type), _crypto(crypto) { } Read_result read(Byte_range_ptr const &, size_t &) override @@ -1010,11 +992,8 @@ class Vfs_tresor_crypto::Management_file_system : public Vfs::Single_file_system Management_file_system(Tresor_crypto::Interface &crypto, Type type, char const *type_name) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name, - Node_rwx::wo(), Xml_node("") }, - _type { type }, - _crypto { crypto }, - _type_name { type_name } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name, Node_rwx::wo(), Xml_node("")), + _type(type), _crypto(crypto), _type_name(type_name) { } char const *type() override { return _type_name; } @@ -1090,9 +1069,7 @@ struct Vfs_tresor_crypto::Local_factory : File_system_factory Local_factory(Vfs::Env &env, Tresor_crypto::Interface &crypto) : - _keys_fs { env, crypto }, - _add_key_fs { crypto }, - _remove_key_fs { crypto } + _keys_fs(env, crypto), _add_key_fs(crypto), _remove_key_fs(crypto) { } Vfs::File_system *create(Vfs::Env&, Xml_node node) override @@ -1142,9 +1119,8 @@ class Vfs_tresor_crypto::File_system : private Local_factory, File_system(Vfs::Env &vfs_env, Genode::Xml_node node) : - Local_factory { vfs_env, Tresor_crypto::get_interface() }, - Vfs::Dir_file_system { vfs_env, Xml_node(_config(node).string()), - *this } + Local_factory(vfs_env, Tresor_crypto::get_interface()), + Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), *this) { } ~File_system() { } diff --git a/repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h b/repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h index a04a53354d..5e87ebb3fa 100644 --- a/repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h +++ b/repos/gems/src/lib/vfs/tresor_trust_anchor/io_job.h @@ -257,16 +257,10 @@ namespace Util { Vfs::file_offset base_offset, Partial_result partial_result = Partial_result::DENY) : - _handle { handle }, - _op { op }, - _state { _initial_state(op) }, - _data { buffer.base }, - _base_offset { base_offset }, - _current_offset { 0 }, - _current_count { buffer.size }, - _allow_partial { partial_result == Partial_result::ALLOW }, - _success { false }, - _complete { false } + _handle(handle), _op(op), _state(_initial_state(op)), _data(buffer.base), + _base_offset(base_offset), _current_offset(0), _current_count(buffer.size), + _allow_partial(partial_result == Partial_result::ALLOW), _success(false), + _complete(false) { } bool completed() const { return _complete; } diff --git a/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc b/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc index ba36c540b5..08151c9c75 100644 --- a/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc @@ -712,7 +712,7 @@ class Trust_anchor return true; } - // XXX trigger sync + /* XXX trigger sync */ bool const progress = _private_key_io_job->execute(); bool const completed = _private_key_io_job->completed(); @@ -731,7 +731,7 @@ class Trust_anchor return true; } - // XXX trigger sync + /* XXX trigger sync */ bool const progress = _jitterentropy_io_job->execute(); bool const completed = _jitterentropy_io_job->completed(); @@ -750,7 +750,7 @@ class Trust_anchor return true; } - // XXX trigger sync + /* XXX trigger sync */ bool const progress = _key_io_job->execute(); bool const completed = _key_io_job->completed(); @@ -960,10 +960,7 @@ class Trust_anchor public: - Trust_anchor(Vfs::Env &vfs_env, Path const &path) - : - _vfs_env { vfs_env }, - _base_path { path } + Trust_anchor(Vfs::Env &vfs_env, Path const &path) : _vfs_env(vfs_env), _base_path(path) { if (_check_key_file(_base_path)) { @@ -1275,8 +1272,7 @@ class Vfs_tresor_trust_anchor::Hashsum_file_system : public Vfs::Single_file_sys Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta) { } Read_result read(Byte_range_ptr const &src, size_t &out_count) override @@ -1367,12 +1363,11 @@ class Vfs_tresor_trust_anchor::Hashsum_file_system : public Vfs::Single_file_sys Hashsum_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::ro(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::ro(), Xml_node("")), + _trust_anchor(ta) { } - static char const *type_name() { return "hashsum"; } + static char const *type_name() { return "hash"; } char const *type() override { return type_name(); } @@ -1433,8 +1428,7 @@ class Vfs_tresor_trust_anchor::Generate_key_file_system : public Vfs::Single_fil Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -1473,9 +1467,8 @@ class Vfs_tresor_trust_anchor::Generate_key_file_system : public Vfs::Single_fil Generate_key_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::ro(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::ro(), Xml_node("")), + _trust_anchor(ta) { } static char const *type_name() { return "generate_key"; } @@ -1539,9 +1532,7 @@ class Vfs_tresor_trust_anchor::Encrypt_file_system : public Vfs::Single_file_sys Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta }, - _state { State::NONE } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta), _state(State::NONE) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -1600,9 +1591,8 @@ class Vfs_tresor_trust_anchor::Encrypt_file_system : public Vfs::Single_file_sys Encrypt_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _trust_anchor(ta) { } static char const *type_name() { return "encrypt"; } @@ -1665,9 +1655,7 @@ class Vfs_tresor_trust_anchor::Decrypt_file_system : public Vfs::Single_file_sys Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta }, - _state { State::NONE } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta), _state(State::NONE) { } Read_result read(Byte_range_ptr const &dst, size_t &out_count) override @@ -1726,9 +1714,8 @@ class Vfs_tresor_trust_anchor::Decrypt_file_system : public Vfs::Single_file_sys Decrypt_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _trust_anchor(ta) { } static char const *type_name() { return "decrypt"; } @@ -1793,8 +1780,7 @@ class Vfs_tresor_trust_anchor::Initialize_file_system : public Vfs::Single_file_ Genode::Allocator &alloc, Trust_anchor &ta) : - Single_vfs_handle { ds, fs, alloc, 0 }, - _trust_anchor { ta } + Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta) { } Read_result read(Byte_range_ptr const &buf, @@ -1867,9 +1853,8 @@ class Vfs_tresor_trust_anchor::Initialize_file_system : public Vfs::Single_file_ Initialize_file_system(Trust_anchor &ta) : - Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(), - Node_rwx::rw(), Xml_node("") }, - _trust_anchor { ta } + Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("")), + _trust_anchor(ta) { } static char const *type_name() { return "initialize"; } @@ -1938,12 +1923,9 @@ struct Vfs_tresor_trust_anchor::Local_factory : File_system_factory Local_factory(Vfs::Env &vfs_env, Xml_node config) : - _trust_anchor { vfs_env, _storage_path(config).string() }, - _decrypt_fs { _trust_anchor }, - _encrypt_fs { _trust_anchor }, - _gen_key_fs { _trust_anchor }, - _hash_fs { _trust_anchor }, - _init_fs { _trust_anchor } + _trust_anchor(vfs_env, _storage_path(config).string()), + _decrypt_fs(_trust_anchor), _encrypt_fs(_trust_anchor), + _gen_key_fs(_trust_anchor), _hash_fs(_trust_anchor), _init_fs(_trust_anchor) { } Vfs::File_system *create(Vfs::Env&, Xml_node node) override @@ -1990,7 +1972,7 @@ class Vfs_tresor_trust_anchor::File_system : private Local_factory, xml.node("decrypt", [&] () { }); xml.node("encrypt", [&] () { }); xml.node("generate_key", [&] () { }); - xml.node("hashsum", [&] () { }); + xml.node("hash", [&] () { }); xml.node("initialize", [&] () { }); }); @@ -2001,8 +1983,7 @@ class Vfs_tresor_trust_anchor::File_system : private Local_factory, File_system(Vfs::Env &vfs_env, Genode::Xml_node node) : - Local_factory { vfs_env, node }, - Vfs::Dir_file_system { vfs_env, Xml_node(_config(node).string()), *this } + Local_factory(vfs_env, node), Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), *this) { } ~File_system() { } diff --git a/tool/autopilot.list b/tool/autopilot.list index 8223345fdd..2e463eb8fd 100644 --- a/tool/autopilot.list +++ b/tool/autopilot.list @@ -97,6 +97,7 @@ vbox5_win7_64_share verify vfs_cfg vfs_import +vfs_tresor vm_stress_seoul-debian32 vm_stress_vbox5-debian32 vm_stress_vbox5-debian64