From aeb65d6b1b87ca8bedb9bf37ca280e43bbfb2ffb Mon Sep 17 00:00:00 2001 From: Martin Stein Date: Mon, 22 May 2023 14:37:13 +0200 Subject: [PATCH] file_vault: version 23.05 * ARM support and detaching from Ada/SPARK * Remove all CBE-related code - especially the Ada/SPARK-based CBE library. * We have no means or motivation of further maintaining big projects in Ada/SPARK (the core Genode team is native to C++). * The Genode Ada/SPARK toolchain and runtime don't support ARM so far - an important architecture for Genode. This would mean extra commitment in Ada/SPARK. * We realize that block encryption more and more becomes a fundamental feature of Genode systems. * Implement a new block encryption library named Tresor that is inspired by the design and feature set of the former CBE library and that is entirely C++ and part of the Genode gems repository. * The Tresor block encryption is backwards-compatible with the on-disk data layout of the former CBE block encryption. * Except from the snapshot management and the "dump" tool, the Tresor block encryption provides the same feature set as the former CBE block encryption and accepts the same user requests at the level of the Tresor library API. * So far, the Tresor block encryption does not support the creation of user-defined snapshots. * In contrast to the former CBE, the Tresor ecosystem has no "dump" tool beause with the CBE library it turned out to be rarely of use. * In contrast to the Block back-end of the CBE "init" tool, the Tresor "init" tool uses a File System back-end. * The former CBE VFS-plugin is replaced with a new Tresor VFS-Plugin. * The Tresor-VFS plugin in general is similar to the former CBE VFS but has a slightly different API when it comes to re-keying and re-sizing. Each of these operations now is controlled via two files. The first file is named and the user writes the start command to it. The user must then read this file once in order to drive the operation. The read returns the result of the operation, once it is finished. The second file is named _progress and can be watched and read for obtaining the progress of the operation as percentage. * The file vault is adapted to use the new Tresor ecosystem instead of the former CBE ecosystem and thereby also gains ARM support. * The former CBE tester and CBE VFS-tests are replaced by equivalent Tresor variants and are now run on ARM as well (testing with a persistent storage back-end is supported only when running on Linux). * So far, the new Tresor block encryption has no internal cache for meta data blocks like the former CBE. * Add config/report user interface * Add a second option for the administration front end to the file vault named "config and report". With this front end the File Vault communicates with the user via XML strings. A ROM session is requested for user input and a Report session for user output. The front end type must be set at startup via the component config and is a static setting. The graphical front end that was used up to now is named "menu view" and remains the default. * The File Vault can now reflect its internal state and user input ("config and report" mode only) at the LOG session via two new static config attributes "verbose_state" and "verbose_ui_config" (both defaulting to "no"). * The Shutdown button in "menu view" mode is replaced with a Lock button. The new button doesn't terminate the File Vault but merely lock the encrypted container and return to a cleared passphrase input. The same transition is also provided in "config and report" mode. * The file_vault.run script is replaced with file_vault_menu_view.run and file_vault_cfg_report.run that address the two front end modes. In contrast to the former script, which is interactive, the latter script is suitable for automatic testing. * There is a new recipe/pkg/test-file_vault_cfg_report that essentially does the same as file_vault_cfg_report.run but uses the File Vault package and can be executed with the Depot Autopilot. The new test package is added to the default test list of depot_autopilot.run * The File Vault README is updated to the new version of the component and has gained a chapter "functional description". * Fixes a regression with the cbe_init_trust_anchor component that prevented reacting to a failed unlock attempt in the File Vault. * The new Tresor software Trust Anchor has an optional deterministic mode in which it replaces the normally randomized symmetric keys with 0. This mode comes in handy for debugging. However, it should never be activated in productive systems. When activated, the user is warned extensively on the LOG that this system mode is insecure. Ref #4819 --- repos/gems/include/cbe/check/library.h | 59 - repos/gems/include/cbe/dump/configuration.h | 101 - repos/gems/include/cbe/dump/library.h | 63 - repos/gems/include/cbe/init/configuration.h | 100 - repos/gems/include/cbe/init/library.h | 124 - repos/gems/include/cbe/library.h | 412 --- repos/gems/include/cbe/spark_object.h | 65 - repos/gems/include/cbe/types.h | 451 --- repos/gems/include/cbe/vfs/trust_anchor_vfs.h | 728 ----- repos/gems/lib/import/import-cbe.mk | 3 - repos/gems/lib/import/import-cbe_check.mk | 2 - repos/gems/lib/import/import-cbe_common.mk | 3 - repos/gems/lib/import/import-cbe_dump.mk | 2 - repos/gems/lib/import/import-cbe_init.mk | 2 - repos/gems/lib/import/import-sha256_4k.mk | 4 +- repos/gems/lib/import/import-tresor.mk | 1 + repos/gems/lib/mk/sha256_4k.mk | 12 - repos/gems/lib/mk/spec/x86_64/cbe.mk | 23 - repos/gems/lib/mk/spec/x86_64/cbe_check.mk | 14 - .../gems/lib/mk/spec/x86_64/cbe_check_cxx.mk | 17 - repos/gems/lib/mk/spec/x86_64/cbe_common.mk | 17 - repos/gems/lib/mk/spec/x86_64/cbe_cxx.mk | 16 - .../gems/lib/mk/spec/x86_64/cbe_cxx_common.mk | 12 - repos/gems/lib/mk/spec/x86_64/cbe_dump.mk | 14 - repos/gems/lib/mk/spec/x86_64/cbe_dump_cxx.mk | 17 - repos/gems/lib/mk/spec/x86_64/cbe_init.mk | 15 - repos/gems/lib/mk/spec/x86_64/cbe_init_cxx.mk | 17 - repos/gems/lib/mk/spec/x86_64/vfs_cbe.mk | 11 - .../mk/spec/x86_64/vfs_cbe_crypto_aes_cbc.mk | 9 - .../mk/spec/x86_64/vfs_cbe_crypto_memcopy.mk | 9 - repos/gems/lib/mk/tresor.mk | 28 + repos/gems/lib/mk/vfs_tresor.mk | 11 + .../gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk | 11 + .../gems/lib/mk/vfs_tresor_crypto_memcopy.mk | 9 + ...t_anchor.mk => vfs_tresor_trust_anchor.mk} | 5 +- repos/gems/lib/symbols/cbe_check_cxx | 14 - repos/gems/lib/symbols/cbe_cxx | 44 - repos/gems/lib/symbols/cbe_dump_cxx | 14 - repos/gems/lib/symbols/cbe_init_cxx | 25 - repos/gems/ports/cbe.hash | 1 - repos/gems/ports/cbe.port | 12 - .../recipes/api/{cbe => tresor}/content.mk | 3 +- repos/gems/recipes/api/{cbe => tresor}/hash | 0 .../recipes/api/{cbe => tresor}/used_apis | 2 - repos/gems/recipes/pkg/cbe_check/README | 1 - repos/gems/recipes/pkg/cbe_check/archives | 6 - repos/gems/recipes/pkg/cbe_check/hash | 1 - repos/gems/recipes/pkg/cbe_check/runtime | 63 - repos/gems/recipes/pkg/cbe_demo/README | 1 - repos/gems/recipes/pkg/cbe_demo/archives | 10 - repos/gems/recipes/pkg/cbe_demo/hash | 1 - repos/gems/recipes/pkg/cbe_fs/README | 2 - repos/gems/recipes/pkg/cbe_fs/archives | 1 - repos/gems/recipes/pkg/cbe_fs/hash | 1 - repos/gems/recipes/pkg/cbe_fs/runtime | 15 - repos/gems/recipes/pkg/cbe_init/README | 1 - repos/gems/recipes/pkg/cbe_init/archives | 6 - repos/gems/recipes/pkg/cbe_init/hash | 1 - repos/gems/recipes/pkg/cbe_init/runtime | 71 - repos/gems/recipes/pkg/cbe_shell/README | 1 - repos/gems/recipes/pkg/cbe_shell/archives | 10 - repos/gems/recipes/pkg/cbe_shell/hash | 1 - repos/gems/recipes/pkg/cbe_shell/runtime | 126 - repos/gems/recipes/pkg/cbe_ta_fs/README | 2 - repos/gems/recipes/pkg/cbe_ta_fs/archives | 1 - repos/gems/recipes/pkg/cbe_ta_fs/hash | 1 - repos/gems/recipes/pkg/cbe_ta_fs/runtime | 15 - repos/gems/recipes/pkg/cbe_ta_vfs/README | 1 - repos/gems/recipes/pkg/cbe_ta_vfs/archives | 2 - repos/gems/recipes/pkg/cbe_ta_vfs/hash | 1 - repos/gems/recipes/pkg/cbe_ta_vfs/runtime | 23 - repos/gems/recipes/pkg/cbe_vbox5-nova/README | 2 - .../gems/recipes/pkg/cbe_vbox5-nova/archives | 9 - repos/gems/recipes/pkg/cbe_vbox5-nova/hash | 1 - repos/gems/recipes/pkg/cbe_vbox5-nova/runtime | 104 - repos/gems/recipes/pkg/cbe_vfs/README | 2 - repos/gems/recipes/pkg/cbe_vfs/archives | 4 - repos/gems/recipes/pkg/cbe_vfs/hash | 1 - repos/gems/recipes/pkg/cbe_vfs/runtime | 30 - repos/gems/recipes/pkg/cbe_vm_fs/README | 2 - repos/gems/recipes/pkg/cbe_vm_fs/archives | 1 - repos/gems/recipes/pkg/cbe_vm_fs/hash | 1 - repos/gems/recipes/pkg/cbe_vm_fs/runtime | 15 - .../gems/recipes/pkg/download_coreplus/README | 1 - .../recipes/pkg/download_coreplus/archives | 18 - repos/gems/recipes/pkg/download_coreplus/hash | 1 - .../recipes/pkg/download_coreplus/runtime | 39 - repos/gems/recipes/pkg/file_vault/archives | 4 +- repos/gems/recipes/pkg/file_vault/runtime | 30 +- .../pkg/file_vault_config_report/README | 1 + .../pkg/file_vault_config_report/archives | 15 + .../recipes/pkg/file_vault_config_report/hash | 1 + .../pkg/file_vault_config_report/runtime | 98 + repos/gems/recipes/pkg/sculpt/README | 4 +- .../pkg/test-file_vault_config_report/README | 1 + .../test-file_vault_config_report/archives | 4 + .../pkg/test-file_vault_config_report/hash | 1 + .../pkg/test-file_vault_config_report/runtime | 232 ++ .../recipes/raw/download_coreplus/disk0.vmdk | 2 +- repos/gems/recipes/src/cbe/content.mk | 70 - repos/gems/recipes/src/cbe/hash | 1 - repos/gems/recipes/src/file_vault/content.mk | 10 + repos/gems/recipes/src/file_vault/used_apis | 2 +- repos/gems/recipes/src/tresor/content.mk | 24 + repos/gems/recipes/src/tresor/hash | 1 + .../recipes/src/{cbe => tresor}/used_apis | 2 - repos/gems/run/cbe_tester.run | 1068 ------- repos/gems/run/depot_autopilot.run | 3 +- repos/gems/run/file_vault.inc | 463 +++ repos/gems/run/file_vault.run | 302 +- repos/gems/run/file_vault_config_report.run | 2 + repos/gems/run/tresor_tester.run | 1078 +++++++ .../gems/run/{vfs_cbe.run => vfs_tresor.run} | 89 +- repos/gems/run/{vfs_cbe.sh => vfs_tresor.sh} | 178 +- .../{vfs_cbe_init.run => vfs_tresor_init.run} | 85 +- repos/gems/src/app/cbe_check/target.mk | 9 - repos/gems/src/app/cbe_dump/README | 72 - repos/gems/src/app/cbe_dump/config.xsd | 44 - repos/gems/src/app/cbe_dump/main.cc | 231 -- repos/gems/src/app/cbe_init/main.cc | 379 --- repos/gems/src/app/cbe_init/target.mk | 9 - .../src/app/cbe_init_trust_anchor/target.mk | 8 - repos/gems/src/app/cbe_tester/README | 35 - repos/gems/src/app/cbe_tester/crypto.h | 118 - repos/gems/src/app/cbe_tester/main.cc | 2551 ---------------- repos/gems/src/app/cbe_tester/target.mk | 13 - repos/gems/src/app/cbe_tester/trust_anchor.cc | 586 ---- repos/gems/src/app/cbe_tester/trust_anchor.h | 123 - repos/gems/src/app/cbe_tester/util.h | 155 - repos/gems/src/app/file_vault/README | 238 +- repos/gems/src/app/file_vault/input.h | 10 - repos/gems/src/app/file_vault/main.cc | 1056 ++++--- .../src/app/file_vault/menu_view_dialog.cc | 12 +- .../src/app/file_vault/menu_view_dialog.h | 6 +- .../app/file_vault/report_session_component.h | 2 +- repos/gems/src/app/file_vault/sandbox.h | 176 +- .../file_vault/sync_to_cbe_vfs_init/target.mk | 3 - .../main.cc | 4 +- .../sync_to_tresor_vfs_init/target.mk | 3 + repos/gems/src/app/file_vault/target.mk | 10 +- .../src/app/file_vault/truncate_file/main.cc | 2 +- repos/gems/src/app/file_vault/types.h | 5 +- .../app/{cbe_check => tresor_check}/README | 6 +- .../{cbe_check => tresor_check}/config.xsd | 0 .../app/{cbe_check => tresor_check}/main.cc | 72 +- .../app/{cbe_dump => tresor_check}/target.mk | 4 +- .../src/app/{cbe_init => tresor_init}/README | 12 +- .../app/{cbe_init => tresor_init}/config.xsd | 0 repos/gems/src/app/tresor_init/main.cc | 236 ++ repos/gems/src/app/tresor_init/target.mk | 10 + .../component.cc | 6 +- .../app/tresor_init_trust_anchor/target.mk | 7 + .../{cbe_tester => tresor_tester}/crypto.cc | 34 +- repos/gems/src/app/tresor_tester/main.cc | 1495 ++++++++++ .../module_type.h | 23 +- repos/gems/src/app/tresor_tester/target.mk | 8 + .../verbose_node.h | 14 +- repos/gems/src/app/vfs_replay/target.mk | 2 +- repos/gems/src/lib/tresor/block_allocator.cc | 197 ++ repos/gems/src/lib/tresor/block_io.cc | 687 +++++ repos/gems/src/lib/tresor/crypto.cc | 732 +++++ repos/gems/src/lib/tresor/free_tree.cc | 993 +++++++ repos/gems/src/lib/tresor/ft_check.cc | 496 ++++ repos/gems/src/lib/tresor/ft_initializer.cc | 749 +++++ repos/gems/src/lib/tresor/ft_resizing.cc | 858 ++++++ .../tresor/include/tresor/block_allocator.h | 141 + .../src/lib/tresor/include/tresor/block_io.h | 178 ++ .../lib/tresor/include/tresor/client_data.h | 104 + .../tresor/include/tresor/construct_in_buf.h | 38 + .../src/lib/tresor/include/tresor/crypto.h | 205 ++ .../tresor/include/tresor}/crypto/interface.h | 44 +- .../src/lib/tresor/include/tresor/free_tree.h | 488 ++++ .../src/lib/tresor/include/tresor/ft_check.h | 211 ++ .../tresor/include/tresor/ft_initializer.h | 260 ++ .../lib/tresor/include/tresor/ft_resizing.h | 256 ++ .../include/tresor/init/configuration.h | 105 + .../gems/src/lib/tresor/include/tresor/math.h | 37 + .../src/lib/tresor/include/tresor/meta_tree.h | 252 ++ .../src/lib/tresor/include/tresor/module.h | 291 ++ .../lib/tresor/include/tresor/request_pool.h | 478 +++ .../src/lib/tresor/include/tresor/sb_check.h | 166 ++ .../tresor/include/tresor/sb_initializer.h | 219 ++ .../tresor/include/tresor/sha256_4k_hash.h | 27 + .../include/tresor/superblock_control.h | 393 +++ .../lib/tresor/include/tresor/trust_anchor.h | 175 ++ .../src/lib/tresor/include/tresor/types.h | 528 ++++ .../src/lib/tresor/include/tresor/vbd_check.h | 196 ++ .../tresor/include/tresor/vbd_initializer.h | 221 ++ .../src/lib/tresor/include/tresor/verbosity.h | 29 + .../lib/tresor/include/tresor}/vfs/io_job.h | 58 +- .../tresor/include/tresor}/vfs_utilities.h | 11 +- .../include/tresor/virtual_block_device.h | 400 +++ repos/gems/src/lib/tresor/meta_tree.cc | 683 +++++ repos/gems/src/lib/tresor/module.cc | 80 + repos/gems/src/lib/tresor/request_pool.cc | 803 +++++ repos/gems/src/lib/tresor/sb_check.cc | 505 ++++ repos/gems/src/lib/tresor/sb_initializer.cc | 725 +++++ repos/gems/src/lib/tresor/sha256_4k_hash.cc | 52 + .../gems/src/lib/tresor/superblock_control.cc | 2051 +++++++++++++ repos/gems/src/lib/tresor/trust_anchor.cc | 556 ++++ repos/gems/src/lib/tresor/vbd_check.cc | 458 +++ repos/gems/src/lib/tresor/vbd_initializer.cc | 602 ++++ .../tresor}/vfs_utilities.cc | 10 +- .../src/lib/tresor/virtual_block_device.cc | 2064 +++++++++++++ repos/gems/src/lib/vfs/cbe/io_job.h | 293 -- .../src/lib/vfs/cbe_crypto/aes_cbc/dummy.ads | 17 - repos/gems/src/lib/vfs/{cbe => tresor}/vfs.cc | 2594 ++++++++--------- .../aes_cbc/aes_cbc.cc | 47 +- .../{cbe => tresor_crypto/aes_cbc}/dummy.ads | 2 +- .../memcopy/memcopy.cc | 12 +- .../vfs/{cbe_crypto => tresor_crypto}/vfs.cc | 92 +- .../aes_256.cc | 0 .../aes_256.h | 0 .../integer.cc | 0 .../integer.h | 0 .../vfs.cc | 62 +- 216 files changed, 25067 insertions(+), 11522 deletions(-) delete mode 100644 repos/gems/include/cbe/check/library.h delete mode 100644 repos/gems/include/cbe/dump/configuration.h delete mode 100644 repos/gems/include/cbe/dump/library.h delete mode 100644 repos/gems/include/cbe/init/configuration.h delete mode 100644 repos/gems/include/cbe/init/library.h delete mode 100644 repos/gems/include/cbe/library.h delete mode 100644 repos/gems/include/cbe/spark_object.h delete mode 100644 repos/gems/include/cbe/types.h delete mode 100644 repos/gems/include/cbe/vfs/trust_anchor_vfs.h delete mode 100644 repos/gems/lib/import/import-cbe.mk delete mode 100644 repos/gems/lib/import/import-cbe_check.mk delete mode 100644 repos/gems/lib/import/import-cbe_common.mk delete mode 100644 repos/gems/lib/import/import-cbe_dump.mk delete mode 100644 repos/gems/lib/import/import-cbe_init.mk create mode 100644 repos/gems/lib/import/import-tresor.mk delete mode 100644 repos/gems/lib/mk/sha256_4k.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe_check.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe_check_cxx.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe_common.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe_cxx.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe_cxx_common.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe_dump.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe_dump_cxx.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe_init.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/cbe_init_cxx.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/vfs_cbe.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/vfs_cbe_crypto_aes_cbc.mk delete mode 100644 repos/gems/lib/mk/spec/x86_64/vfs_cbe_crypto_memcopy.mk create mode 100644 repos/gems/lib/mk/tresor.mk create mode 100644 repos/gems/lib/mk/vfs_tresor.mk create mode 100644 repos/gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk create mode 100644 repos/gems/lib/mk/vfs_tresor_crypto_memcopy.mk rename repos/gems/lib/mk/{spec/x86_64/vfs_cbe_trust_anchor.mk => vfs_tresor_trust_anchor.mk} (54%) delete mode 100644 repos/gems/lib/symbols/cbe_check_cxx delete mode 100644 repos/gems/lib/symbols/cbe_cxx delete mode 100644 repos/gems/lib/symbols/cbe_dump_cxx delete mode 100644 repos/gems/lib/symbols/cbe_init_cxx delete mode 100644 repos/gems/ports/cbe.hash delete mode 100644 repos/gems/ports/cbe.port rename repos/gems/recipes/api/{cbe => tresor}/content.mk (73%) rename repos/gems/recipes/api/{cbe => tresor}/hash (100%) rename repos/gems/recipes/api/{cbe => tresor}/used_apis (71%) delete mode 100644 repos/gems/recipes/pkg/cbe_check/README delete mode 100644 repos/gems/recipes/pkg/cbe_check/archives delete mode 100644 repos/gems/recipes/pkg/cbe_check/hash delete mode 100644 repos/gems/recipes/pkg/cbe_check/runtime delete mode 100644 repos/gems/recipes/pkg/cbe_demo/README delete mode 100644 repos/gems/recipes/pkg/cbe_demo/archives delete mode 100644 repos/gems/recipes/pkg/cbe_demo/hash delete mode 100644 repos/gems/recipes/pkg/cbe_fs/README delete mode 100644 repos/gems/recipes/pkg/cbe_fs/archives delete mode 100644 repos/gems/recipes/pkg/cbe_fs/hash delete mode 100644 repos/gems/recipes/pkg/cbe_fs/runtime delete mode 100644 repos/gems/recipes/pkg/cbe_init/README delete mode 100644 repos/gems/recipes/pkg/cbe_init/archives delete mode 100644 repos/gems/recipes/pkg/cbe_init/hash delete mode 100644 repos/gems/recipes/pkg/cbe_init/runtime delete mode 100644 repos/gems/recipes/pkg/cbe_shell/README delete mode 100644 repos/gems/recipes/pkg/cbe_shell/archives delete mode 100644 repos/gems/recipes/pkg/cbe_shell/hash delete mode 100644 repos/gems/recipes/pkg/cbe_shell/runtime delete mode 100644 repos/gems/recipes/pkg/cbe_ta_fs/README delete mode 100644 repos/gems/recipes/pkg/cbe_ta_fs/archives delete mode 100644 repos/gems/recipes/pkg/cbe_ta_fs/hash delete mode 100644 repos/gems/recipes/pkg/cbe_ta_fs/runtime delete mode 100644 repos/gems/recipes/pkg/cbe_ta_vfs/README delete mode 100644 repos/gems/recipes/pkg/cbe_ta_vfs/archives delete mode 100644 repos/gems/recipes/pkg/cbe_ta_vfs/hash delete mode 100644 repos/gems/recipes/pkg/cbe_ta_vfs/runtime delete mode 100644 repos/gems/recipes/pkg/cbe_vbox5-nova/README delete mode 100644 repos/gems/recipes/pkg/cbe_vbox5-nova/archives delete mode 100644 repos/gems/recipes/pkg/cbe_vbox5-nova/hash delete mode 100644 repos/gems/recipes/pkg/cbe_vbox5-nova/runtime delete mode 100644 repos/gems/recipes/pkg/cbe_vfs/README delete mode 100644 repos/gems/recipes/pkg/cbe_vfs/archives delete mode 100644 repos/gems/recipes/pkg/cbe_vfs/hash delete mode 100644 repos/gems/recipes/pkg/cbe_vfs/runtime delete mode 100644 repos/gems/recipes/pkg/cbe_vm_fs/README delete mode 100644 repos/gems/recipes/pkg/cbe_vm_fs/archives delete mode 100644 repos/gems/recipes/pkg/cbe_vm_fs/hash delete mode 100644 repos/gems/recipes/pkg/cbe_vm_fs/runtime delete mode 100644 repos/gems/recipes/pkg/download_coreplus/README delete mode 100644 repos/gems/recipes/pkg/download_coreplus/archives delete mode 100644 repos/gems/recipes/pkg/download_coreplus/hash delete mode 100644 repos/gems/recipes/pkg/download_coreplus/runtime create mode 100644 repos/gems/recipes/pkg/file_vault_config_report/README create mode 100644 repos/gems/recipes/pkg/file_vault_config_report/archives create mode 100644 repos/gems/recipes/pkg/file_vault_config_report/hash create mode 100644 repos/gems/recipes/pkg/file_vault_config_report/runtime create mode 100644 repos/gems/recipes/pkg/test-file_vault_config_report/README create mode 100644 repos/gems/recipes/pkg/test-file_vault_config_report/archives create mode 100644 repos/gems/recipes/pkg/test-file_vault_config_report/hash create mode 100644 repos/gems/recipes/pkg/test-file_vault_config_report/runtime delete mode 100644 repos/gems/recipes/src/cbe/content.mk delete mode 100644 repos/gems/recipes/src/cbe/hash create mode 100644 repos/gems/recipes/src/tresor/content.mk create mode 100644 repos/gems/recipes/src/tresor/hash rename repos/gems/recipes/src/{cbe => tresor}/used_apis (71%) delete mode 100644 repos/gems/run/cbe_tester.run create mode 100644 repos/gems/run/file_vault.inc create mode 100644 repos/gems/run/file_vault_config_report.run create mode 100644 repos/gems/run/tresor_tester.run rename repos/gems/run/{vfs_cbe.run => vfs_tresor.run} (83%) rename repos/gems/run/{vfs_cbe.sh => vfs_tresor.sh} (57%) rename repos/gems/run/{vfs_cbe_init.run => vfs_tresor_init.run} (62%) delete mode 100644 repos/gems/src/app/cbe_check/target.mk delete mode 100644 repos/gems/src/app/cbe_dump/README delete mode 100644 repos/gems/src/app/cbe_dump/config.xsd delete mode 100644 repos/gems/src/app/cbe_dump/main.cc delete mode 100644 repos/gems/src/app/cbe_init/main.cc delete mode 100644 repos/gems/src/app/cbe_init/target.mk delete mode 100644 repos/gems/src/app/cbe_init_trust_anchor/target.mk delete mode 100644 repos/gems/src/app/cbe_tester/README delete mode 100644 repos/gems/src/app/cbe_tester/crypto.h delete mode 100644 repos/gems/src/app/cbe_tester/main.cc delete mode 100644 repos/gems/src/app/cbe_tester/target.mk delete mode 100644 repos/gems/src/app/cbe_tester/trust_anchor.cc delete mode 100644 repos/gems/src/app/cbe_tester/trust_anchor.h delete mode 100644 repos/gems/src/app/cbe_tester/util.h delete mode 100644 repos/gems/src/app/file_vault/sync_to_cbe_vfs_init/target.mk rename repos/gems/src/app/file_vault/{sync_to_cbe_vfs_init => sync_to_tresor_vfs_init}/main.cc (86%) create mode 100644 repos/gems/src/app/file_vault/sync_to_tresor_vfs_init/target.mk rename repos/gems/src/app/{cbe_check => tresor_check}/README (62%) rename repos/gems/src/app/{cbe_check => tresor_check}/config.xsd (100%) rename repos/gems/src/app/{cbe_check => tresor_check}/main.cc (71%) rename repos/gems/src/app/{cbe_dump => tresor_check}/target.mk (60%) rename repos/gems/src/app/{cbe_init => tresor_init}/README (83%) rename repos/gems/src/app/{cbe_init => tresor_init}/config.xsd (100%) create mode 100644 repos/gems/src/app/tresor_init/main.cc create mode 100644 repos/gems/src/app/tresor_init/target.mk rename repos/gems/src/app/{cbe_init_trust_anchor => tresor_init_trust_anchor}/component.cc (97%) create mode 100644 repos/gems/src/app/tresor_init_trust_anchor/target.mk rename repos/gems/src/app/{cbe_tester => tresor_tester}/crypto.cc (89%) create mode 100644 repos/gems/src/app/tresor_tester/main.cc rename repos/gems/src/app/{cbe_tester => tresor_tester}/module_type.h (73%) create mode 100644 repos/gems/src/app/tresor_tester/target.mk rename repos/gems/src/app/{cbe_tester => tresor_tester}/verbose_node.h (80%) create mode 100644 repos/gems/src/lib/tresor/block_allocator.cc create mode 100644 repos/gems/src/lib/tresor/block_io.cc create mode 100644 repos/gems/src/lib/tresor/crypto.cc create mode 100644 repos/gems/src/lib/tresor/free_tree.cc create mode 100644 repos/gems/src/lib/tresor/ft_check.cc create mode 100644 repos/gems/src/lib/tresor/ft_initializer.cc create mode 100644 repos/gems/src/lib/tresor/ft_resizing.cc create mode 100644 repos/gems/src/lib/tresor/include/tresor/block_allocator.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/block_io.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/client_data.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/construct_in_buf.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/crypto.h rename repos/gems/{include/cbe => src/lib/tresor/include/tresor}/crypto/interface.h (62%) create mode 100644 repos/gems/src/lib/tresor/include/tresor/free_tree.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/ft_check.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/ft_initializer.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/ft_resizing.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/init/configuration.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/math.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/meta_tree.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/module.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/request_pool.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/sb_check.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/sb_initializer.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/sha256_4k_hash.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/superblock_control.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/trust_anchor.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/types.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/vbd_check.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h create mode 100644 repos/gems/src/lib/tresor/include/tresor/verbosity.h rename repos/gems/{include/cbe => src/lib/tresor/include/tresor}/vfs/io_job.h (84%) rename repos/gems/src/{app/cbe_tester => lib/tresor/include/tresor}/vfs_utilities.h (80%) create mode 100644 repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h create mode 100644 repos/gems/src/lib/tresor/meta_tree.cc create mode 100644 repos/gems/src/lib/tresor/module.cc create mode 100644 repos/gems/src/lib/tresor/request_pool.cc create mode 100644 repos/gems/src/lib/tresor/sb_check.cc create mode 100644 repos/gems/src/lib/tresor/sb_initializer.cc create mode 100644 repos/gems/src/lib/tresor/sha256_4k_hash.cc create mode 100644 repos/gems/src/lib/tresor/superblock_control.cc create mode 100644 repos/gems/src/lib/tresor/trust_anchor.cc create mode 100644 repos/gems/src/lib/tresor/vbd_check.cc create mode 100644 repos/gems/src/lib/tresor/vbd_initializer.cc rename repos/gems/src/{app/cbe_tester => lib/tresor}/vfs_utilities.cc (83%) create mode 100644 repos/gems/src/lib/tresor/virtual_block_device.cc delete mode 100644 repos/gems/src/lib/vfs/cbe/io_job.h delete mode 100644 repos/gems/src/lib/vfs/cbe_crypto/aes_cbc/dummy.ads rename repos/gems/src/lib/vfs/{cbe => tresor}/vfs.cc (58%) rename repos/gems/src/lib/vfs/{cbe_crypto => tresor_crypto}/aes_cbc/aes_cbc.cc (81%) rename repos/gems/src/lib/vfs/{cbe => tresor_crypto/aes_cbc}/dummy.ads (82%) rename repos/gems/src/lib/vfs/{cbe_crypto => tresor_crypto}/memcopy/memcopy.cc (90%) rename repos/gems/src/lib/vfs/{cbe_crypto => tresor_crypto}/vfs.cc (90%) rename repos/gems/src/lib/vfs/{cbe_trust_anchor => tresor_trust_anchor}/aes_256.cc (100%) rename repos/gems/src/lib/vfs/{cbe_trust_anchor => tresor_trust_anchor}/aes_256.h (100%) rename repos/gems/src/lib/vfs/{cbe_trust_anchor => tresor_trust_anchor}/integer.cc (100%) rename repos/gems/src/lib/vfs/{cbe_trust_anchor => tresor_trust_anchor}/integer.h (100%) rename repos/gems/src/lib/vfs/{cbe_trust_anchor => tresor_trust_anchor}/vfs.cc (96%) diff --git a/repos/gems/include/cbe/check/library.h b/repos/gems/include/cbe/check/library.h deleted file mode 100644 index 3eae15d292..0000000000 --- a/repos/gems/include/cbe/check/library.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE__CHECK__LIBRARY_H_ -#define _CBE__CHECK__LIBRARY_H_ - -/* CBE includes */ -#include -#include - - -extern "C" void cbe_check_cxx_init(); -extern "C" void cbe_check_cxx_final(); - - -namespace Cbe_check { - - class Library; - - Genode::uint32_t object_size(Library const &); - -} - -struct Cbe_check::Library : Cbe::Spark_object<46160> -{ - Library(); - - bool client_request_acceptable() const; - - void submit_client_request(Cbe::Request const &request); - - Cbe::Request peek_completed_client_request() const; - - void drop_completed_client_request(Cbe::Request const &req); - - void execute(Cbe::Io_buffer const &io_buf); - - bool execute_progress() const; - - void io_request_completed(Cbe::Io_buffer::Index const &data_index, - bool const success); - - void has_io_request(Cbe::Request &, Cbe::Io_buffer::Index &) const; - - void io_request_in_progress(Cbe::Io_buffer::Index const &data_index); -}; - -#endif /* _CBE__CHECK__LIBRARY_H_ */ diff --git a/repos/gems/include/cbe/dump/configuration.h b/repos/gems/include/cbe/dump/configuration.h deleted file mode 100644 index e21705e67e..0000000000 --- a/repos/gems/include/cbe/dump/configuration.h +++ /dev/null @@ -1,101 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE__DUMP__CONFIGURATION_H_ -#define _CBE__DUMP__CONFIGURATION_H_ - -/* Genode includes */ -#include - -namespace Cbe_dump { class Configuration; } - -class Cbe_dump::Configuration -{ - private: - - bool _unused_nodes; - Genode::uint32_t _max_superblocks; - Genode::uint32_t _max_snapshots; - bool _vbd; - bool _vbd_pba_filter_enabled; - Genode::uint64_t _vbd_pba_filter; - bool _vbd_vba_filter_enabled; - Genode::uint64_t _vbd_vba_filter; - bool _free_tree; - bool _meta_tree; - bool _hashes; - - public: - - Configuration (Genode::Xml_node const &node) - : - _unused_nodes { node.attribute_value("unused_nodes", true) }, - _max_superblocks { node.attribute_value("max_superblocks", ~(Genode::uint32_t)0) }, - _max_snapshots { node.attribute_value("max_snapshots", ~(Genode::uint32_t)0) }, - _vbd { node.attribute_value("vbd", true) }, - _vbd_pba_filter_enabled { node.attribute_value("vbd_pba_filter_enabled", false) }, - _vbd_pba_filter { node.attribute_value("vbd_pba_filter", (Genode::uint64_t)0) }, - _vbd_vba_filter_enabled { node.attribute_value("vbd_vba_filter_enabled", false) }, - _vbd_vba_filter { node.attribute_value("vbd_vba_filter", (Genode::uint64_t)0) }, - _free_tree { node.attribute_value("free_tree", true) }, - _meta_tree { node.attribute_value("meta_tree", true) }, - _hashes { node.attribute_value("hashes", true) } - { } - - Configuration (Configuration const &other) - : - _unused_nodes { other._unused_nodes }, - _max_superblocks { other._max_superblocks }, - _max_snapshots { other._max_snapshots }, - _vbd { other._vbd }, - _vbd_pba_filter_enabled { other._vbd_pba_filter_enabled }, - _vbd_pba_filter { other._vbd_pba_filter }, - _vbd_vba_filter_enabled { other._vbd_vba_filter_enabled }, - _vbd_vba_filter { other._vbd_vba_filter }, - _free_tree { other._free_tree }, - _meta_tree { other._meta_tree }, - _hashes { other._hashes } - { } - - bool unused_nodes() const { return _unused_nodes; } - Genode::uint32_t max_superblocks() const { return _max_superblocks; } - Genode::uint32_t max_snapshots() const { return _max_snapshots; } - bool vbd() const { return _vbd; } - bool vbd_pba_filter_enabled() const { return _vbd_pba_filter_enabled; } - Genode::uint64_t vbd_pba_filter() const { return _vbd_pba_filter; } - bool vbd_vba_filter_enabled() const { return _vbd_vba_filter_enabled; } - Genode::uint64_t vbd_vba_filter() const { return _vbd_vba_filter; } - bool free_tree() const { return _free_tree; } - bool meta_tree() const { return _meta_tree; } - bool hashes() const { return _hashes; } - - void print(Genode::Output &out) const - { - Genode::print(out, - "unused_nodes=", _unused_nodes , - " max_superblocks=", _max_superblocks , - " max_snapshots=", _max_snapshots , - " vbd=", _vbd , - " vbd_pba_filter_enabled=", _vbd_pba_filter_enabled, - " vbd_pba_filter=", _vbd_pba_filter , - " vbd_vba_filter_enabled=", _vbd_vba_filter_enabled, - " vbd_vba_filter=", _vbd_vba_filter , - " free_tree=", _free_tree , - " meta_tree=", _meta_tree , - " hashes=", _hashes ); - } - -} __attribute__((packed)); - -#endif /* _CBE__DUMP__CONFIGURATION_H_ */ diff --git a/repos/gems/include/cbe/dump/library.h b/repos/gems/include/cbe/dump/library.h deleted file mode 100644 index adf3c6d59f..0000000000 --- a/repos/gems/include/cbe/dump/library.h +++ /dev/null @@ -1,63 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE__DUMP__LIBRARY_H_ -#define _CBE__DUMP__LIBRARY_H_ - -/* CBE includes */ -#include -#include - -/* CBE dump includes */ -#include - - -extern "C" void cbe_dump_cxx_init(); -extern "C" void cbe_dump_cxx_final(); - - -namespace Cbe_dump { - - class Library; - - Genode::uint32_t object_size(Library const &); - -} - -struct Cbe_dump::Library : Cbe::Spark_object<49240> -{ - Library(); - - bool client_request_acceptable() const; - - void submit_client_request(Cbe::Request const &request, - Configuration const &cfg); - - Cbe::Request peek_completed_client_request() const; - - void drop_completed_client_request(Cbe::Request const &req); - - void execute(Cbe::Io_buffer const &io_buf); - - bool execute_progress() const; - - void io_request_completed(Cbe::Io_buffer::Index const &data_index, - bool const success); - - void has_io_request(Cbe::Request &, Cbe::Io_buffer::Index &) const; - - void io_request_in_progress(Cbe::Io_buffer::Index const &data_index); -}; - -#endif /* _CBE__DUMP__LIBRARY_H_ */ diff --git a/repos/gems/include/cbe/init/configuration.h b/repos/gems/include/cbe/init/configuration.h deleted file mode 100644 index 5a5428d6b5..0000000000 --- a/repos/gems/include/cbe/init/configuration.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE__INIT__CONFIGURATION_H_ -#define _CBE__INIT__CONFIGURATION_H_ - -/* Genode includes */ -#include - -namespace Cbe_init { class Configuration; } - -class Cbe_init::Configuration -{ - private: - - Genode::uint64_t _vbd_nr_of_lvls { 0 }; - Genode::uint64_t _vbd_nr_of_children { 0 }; - Genode::uint64_t _vbd_nr_of_leafs { 0 }; - Genode::uint64_t _ft_nr_of_lvls { 0 }; - Genode::uint64_t _ft_nr_of_children { 0 }; - Genode::uint64_t _ft_nr_of_leafs { 0 }; - - public: - - struct Invalid : Genode::Exception { }; - - Configuration (Genode::Xml_node const &node) - { - node.with_optional_sub_node("virtual-block-device", - [&] (Genode::Xml_node const &vbd) - { - _vbd_nr_of_lvls = - vbd.attribute_value("nr_of_levels", (Genode::uint64_t)0); - _vbd_nr_of_children = - vbd.attribute_value("nr_of_children", (Genode::uint64_t)0); - _vbd_nr_of_leafs = - vbd.attribute_value("nr_of_leafs", (Genode::uint64_t)0); - }); - node.with_optional_sub_node("free-tree", - [&] (Genode::Xml_node const &ft) - { - _ft_nr_of_lvls = - ft.attribute_value("nr_of_levels", (Genode::uint64_t)0); - _ft_nr_of_children = - ft.attribute_value("nr_of_children", (Genode::uint64_t)0); - _ft_nr_of_leafs = - ft.attribute_value("nr_of_leafs", (Genode::uint64_t)0); - }); - if (_vbd_nr_of_lvls == 0 || - _vbd_nr_of_children == 0 || - _vbd_nr_of_leafs == 0 || - _ft_nr_of_lvls == 0 || - _ft_nr_of_children == 0 || - _ft_nr_of_leafs == 0) - { - throw Invalid(); - } - } - - Configuration (Configuration const &other) - { - _vbd_nr_of_lvls = other._vbd_nr_of_lvls ; - _vbd_nr_of_children = other._vbd_nr_of_children; - _vbd_nr_of_leafs = other._vbd_nr_of_leafs ; - _ft_nr_of_lvls = other._ft_nr_of_lvls ; - _ft_nr_of_children = other._ft_nr_of_children ; - _ft_nr_of_leafs = other._ft_nr_of_leafs ; - } - - Genode::uint64_t vbd_nr_of_lvls () const { return _vbd_nr_of_lvls ; } - Genode::uint64_t vbd_nr_of_children () const { return _vbd_nr_of_children; } - Genode::uint64_t vbd_nr_of_leafs () const { return _vbd_nr_of_leafs ; } - Genode::uint64_t ft_nr_of_lvls () const { return _ft_nr_of_lvls ; } - Genode::uint64_t ft_nr_of_children () const { return _ft_nr_of_children ; } - Genode::uint64_t ft_nr_of_leafs () const { return _ft_nr_of_leafs ; } - - void print(Genode::Output &out) const - { - Genode::print(out, - "vbd=(lvls=", _vbd_nr_of_lvls, - " children=", _vbd_nr_of_children, - " leafs=", _vbd_nr_of_leafs, ")", - " ft=(lvls=", _ft_nr_of_lvls, - " children=", _ft_nr_of_children, - " leafs=", _ft_nr_of_leafs, ")"); - } -}; - -#endif /* _CBE__INIT__CONFIGURATION_H_ */ diff --git a/repos/gems/include/cbe/init/library.h b/repos/gems/include/cbe/init/library.h deleted file mode 100644 index 0251988d53..0000000000 --- a/repos/gems/include/cbe/init/library.h +++ /dev/null @@ -1,124 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE__INIT__LIBRARY_H_ -#define _CBE__INIT__LIBRARY_H_ - -/* CBE includes */ -#include -#include - - -extern "C" void cbe_init_cxx_init(); -extern "C" void cbe_init_cxx_final(); - - -namespace Cbe_init { - - class Library; - - Genode::uint32_t object_size(Library const &); - -} - -struct Cbe_init::Library : Cbe::Spark_object<60960> -{ - /* - * Ada/SPARK compatible bindings - */ - - void _peek_generated_ta_request(Cbe::Trust_anchor_request &) const; - void _peek_generated_ta_sb_hash(Cbe::Trust_anchor_request const &, Cbe::Hash &) const; - void _peek_generated_ta_key_value_plaintext(Cbe::Trust_anchor_request const &, - Cbe::Key_plaintext_value &) const; - void _peek_generated_ta_key_value_ciphertext(Cbe::Trust_anchor_request const &, - Cbe::Key_ciphertext_value &) const; - - Library(); - - bool client_request_acceptable() const; - - void submit_client_request(Cbe::Request const &request, - Genode::uint64_t vbd_max_lvl_idx, - Genode::uint64_t vbd_degree, - Genode::uint64_t vbd_nr_of_leafs, - Genode::uint64_t ft_max_lvl_idx, - Genode::uint64_t ft_degree, - Genode::uint64_t ft_nr_of_leafs); - - Cbe::Request peek_completed_client_request() const; - - void drop_completed_client_request(Cbe::Request const &req); - - void execute(Cbe::Io_buffer &io_buf); - - bool execute_progress() const; - - void io_request_completed(Cbe::Io_buffer::Index const &data_index, - bool const success); - - void has_io_request(Cbe::Request &, Cbe::Io_buffer::Index &) const; - - void io_request_in_progress(Cbe::Io_buffer::Index const &data_index); - - Cbe::Trust_anchor_request peek_generated_ta_request() const - { - Cbe::Trust_anchor_request request { }; - _peek_generated_ta_request(request); - return request; - } - - void drop_generated_ta_request(Cbe::Trust_anchor_request const &request); - - Cbe::Hash peek_generated_ta_sb_hash(Cbe::Trust_anchor_request const &request) const - { - Cbe::Hash hash { }; - _peek_generated_ta_sb_hash(request, hash); - return hash; - } - - void mark_generated_ta_secure_sb_request_complete(Cbe::Trust_anchor_request const &request); - - void mark_generated_ta_create_key_request_complete(Cbe::Trust_anchor_request const &request, - Cbe::Key_plaintext_value const &key); - - Cbe::Key_ciphertext_value peek_generated_ta_key_value_ciphertext(Cbe::Trust_anchor_request const &request) const - { - Cbe::Key_ciphertext_value ck { }; - _peek_generated_ta_key_value_ciphertext(request, ck); - return ck; - } - - Cbe::Key_plaintext_value peek_generated_ta_key_value_plaintext(Cbe::Trust_anchor_request const &request) const - { - Cbe::Key_plaintext_value pk { }; - _peek_generated_ta_key_value_plaintext(request, pk); - return pk; - } - - void mark_generated_ta_decrypt_key_request_complete(Cbe::Trust_anchor_request const &reference, - Cbe::Key_plaintext_value const &key); - - void mark_generated_ta_encrypt_key_request_complete(Cbe::Trust_anchor_request const &request, - Cbe::Key_ciphertext_value const &key); - - void mark_generated_ta_last_sb_hash_request_complete(Cbe::Trust_anchor_request const &, - Cbe::Hash const &) - { - struct Not_supported { }; - throw Not_supported(); - } -}; - -#endif /* _CBE__INIT__LIBRARY_H_ */ diff --git a/repos/gems/include/cbe/library.h b/repos/gems/include/cbe/library.h deleted file mode 100644 index 2b8449be66..0000000000 --- a/repos/gems/include/cbe/library.h +++ /dev/null @@ -1,412 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE_LIBRARY_H_ -#define _CBE_LIBRARY_H_ - -/* Genode includes */ -#include -#include - -/* CBE includes */ -#include -#include - - -extern "C" void cbe_cxx_init(); -extern "C" void cbe_cxx_final(); - - -namespace Cbe { - - using namespace Genode; - - class Library; - - Genode::uint32_t object_size(Library const &); - -} /* namespace Cbe */ - - -class Cbe::Library : public Cbe::Spark_object<353944> -{ - private: - - /* - * Ada/SPARK compatible bindings - * - * Ada functions cannot have out parameters. Hence we call Ada - * procedures that return the 'progress' result as last out parameter. - */ - - void _has_io_request(Request &, Io_buffer::Index &) const; - - void _crypto_add_key_required(Request &, Key &) const; - void _crypto_remove_key_required(Request &, Key::Id &) const; - - void _crypto_cipher_data_required(Request &, Crypto_plain_buffer::Index &) const; - void _crypto_plain_data_required(Request &, Crypto_cipher_buffer::Index &) const; - - void _info(Info &) const; - - void _peek_generated_ta_request(Trust_anchor_request &) const; - void _peek_generated_ta_sb_hash(Trust_anchor_request const &, Hash &) const; - void _peek_generated_ta_key_value_plaintext(Trust_anchor_request const &, Key_plaintext_value &) const; - void _peek_generated_ta_key_value_ciphertext(Trust_anchor_request const &, Key_ciphertext_value &) const; - - public: - - Library(); - - /** - * Get highest virtual-block-address useable by the current active snapshot - * - * \return highest addressable virtual-block-address - */ - Virtual_block_address max_vba() const; - - /** - * Get information about the CBE - * - * \return information structure - */ - Info info() const - { - Info inf { }; - _info(inf); - return inf; - } - - void execute(Io_buffer &io_buf, - Crypto_plain_buffer &crypto_plain_buf, - Crypto_cipher_buffer &crypto_cipher_buf); - - /** - * Return whether the last call to 'execute' has made progress or not - */ - bool execute_progress() const; - - /** - * Check if the CBE can accept a new requeust - * - * \return true if a request can be accepted, otherwise false - */ - bool client_request_acceptable() const; - - /** - * Submit a new request - * - * This method must only be called after executing 'request_acceptable' - * returned true. - * - * \param request block request - */ - void submit_client_request(Request const &request, uint32_t id); - - /** - * Check for any completed request - * - * \return a valid block request will be returned if there is an - * completed request, otherwise an invalid one - */ - Request peek_completed_client_request() const; - - /** - * Drops the completed request - * - * This method must only be called after executing - * 'peek_completed_request' returned a valid request. - * - */ - void drop_completed_client_request(Request const &req); - - /* - * Backend block I/O - */ - - /** - * Submit read request data from the backend block session to the CBE - * - * The given data will be transfered to the CBE. - * - * \param request reference to the request from the CBE - * \param data reference to the data associated with the - * request - * - * \return true if the CBE acknowledged the request - */ - void io_request_completed(Io_buffer::Index const &data_index, - bool const success); - - /** - * Return a write request for the backend block session - * - * \param result valid request in case the is one pending that - * needs data, otherwise an invalid one is returned - */ - Request has_io_request(Io_buffer::Index &data_index) const - { - Request result { }; - _has_io_request(result, data_index); - return result; - } - void has_io_request(Request &req, Io_buffer::Index &data_index) const - { - _has_io_request(req, data_index); - } - - /** - * Obtain data for write request for the backend block session - * - * The CBE will transfer the payload to the given data. - * - * \param request reference to the Block::Request processed - * by the CBE - * \param data reference to the data associated with the - * Request - * - * \return true if the CBE could process the request - */ - void io_request_in_progress(Io_buffer::Index const &data_index); - - void client_transfer_read_data_required(Request &, - uint64_t &, - Crypto_plain_buffer::Index &) const; - - void client_transfer_read_data_in_progress(Crypto_plain_buffer::Index const &); - - void client_transfer_read_data_completed(Crypto_plain_buffer::Index const &, bool); - - void client_transfer_write_data_required(Request &, - uint64_t &, - Crypto_plain_buffer::Index &) const; - - void client_transfer_write_data_in_progress(Crypto_plain_buffer::Index const &); - - void client_transfer_write_data_completed(Crypto_plain_buffer::Index const &, bool); - - /** - * Query list of active snapshots - * - * \param ids reference to destination buffer - */ - void active_snapshot_ids(Active_snapshot_ids &ids) const; - - Request crypto_add_key_required(Key &key) const - { - Request result { }; - _crypto_add_key_required(result, key); - return result; - } - - void crypto_add_key_requested(Request const &req); - - void crypto_add_key_completed(Request const &req); - - Request crypto_remove_key_required(Key::Id &key_id) const - { - Request result { }; - _crypto_remove_key_required(result, key_id); - return result; - } - - void crypto_remove_key_requested(Request const &req); - - void crypto_remove_key_completed(Request const &req); - - /** - * CBE requests encrytion - * - * \param result valid request in case the is one pending that - * needs encrytion, otherwise an invalid one is - * returned - */ - Request crypto_cipher_data_required(Crypto_plain_buffer::Index &data_index) const - { - Request result { }; - _crypto_cipher_data_required(result, data_index); - return result; - } - - /** - * Return plain data for given encryption request - * - * \param request reference to the Block::Request processed - * by the CBE - * \param data reference to the data associated with the - * Block::Request - */ - void crypto_cipher_data_requested( - Crypto_plain_buffer::Index const &data_index); - - /** - * Collect cipher data for given completed encryption request - * - * \param request reference to the Block::Request processed - * by the CBE - * \param data reference to the data associated with the - * Block::Request - * - * \return true if the CBE could obtain the encrypted data, - * otherwise false - */ - void supply_crypto_cipher_data(Crypto_cipher_buffer::Index const &data_index, - bool const data_valid); - - /** - * CBE requests decryption - * - * \param result valid request in case the is one pending that - * needs decrytion, otherwise an invalid one is - * returned - */ - Request crypto_plain_data_required(Crypto_cipher_buffer::Index &data_index) const - { - Request result { }; - _crypto_plain_data_required(result, data_index); - return result; - } - - /** - * Return cipher data for given decryption request - * - * \param request reference to the Block::Request processed - * by the CBE - * \param data reference to the data associated with the - * Block::Request - * - * \return true if the CBE could supply the ciphr data, - * otherwise false - */ - void crypto_plain_data_requested( - Crypto_cipher_buffer::Index const &data_index); - - /** - * Collect plain data for given completed decryption request - * - * \param request reference to the Block::Request processed - * by the CBE - * \param data reference to the data associated with the - * Block::Request - * - * \return true if the CBE could obtain the decrypted data, - * otherwise false - */ - void supply_crypto_plain_data(Crypto_plain_buffer::Index const &data_index, - bool const data_valid); - - /** - * CBE trust anchor request - * - * \return valid TA request in case there is one pending, otherwise an - * invalid one is returned - */ - Trust_anchor_request peek_generated_ta_request() const - { - Trust_anchor_request request { }; - _peek_generated_ta_request(request); - return request; - } - - /** - * Drop generated TA request - * - * \param request reference to the request processed by the TA - */ - void drop_generated_ta_request(Trust_anchor_request const &request); - - /** - * Peek generated TA superblock hash - * - * \param request reference to the request - * \return superblock hash - */ - Hash peek_generated_ta_sb_hash(Trust_anchor_request const &request) const - { - Cbe::Hash hash { }; - _peek_generated_ta_sb_hash(request, hash); - return hash; - } - - /** - * Mark generated TA secure superblock request complete - * - * \param request reference to the request completed by the TA - */ - void mark_generated_ta_secure_sb_request_complete(Trust_anchor_request const &request); - - /** - * Mark generated TA create key request complete - * - * \param request reference to the request completed by the TA - * \param key reference to the key plaintext created by the TA - */ - void mark_generated_ta_create_key_request_complete(Trust_anchor_request const &request, - Key_plaintext_value const &key); - - /** - * Peek generated TA key ciphertext - * - * \param request reference to the request - * \return key ciphertext - */ - Key_ciphertext_value peek_generated_ta_key_value_ciphertext(Trust_anchor_request const &request) const - { - Cbe::Key_ciphertext_value ck { }; - _peek_generated_ta_key_value_ciphertext(request, ck); - return ck; - } - - /** - * Peek generated TA key plaintext - * - * \param request reference to the request - * \return key plaintext - */ - Key_plaintext_value peek_generated_ta_key_value_plaintext(Trust_anchor_request const &request) const - { - Cbe::Key_plaintext_value pk { }; - _peek_generated_ta_key_value_plaintext(request, pk); - return pk; - } - - /** - * Mark generated TA decrypt key request complete - * - * \param request reference to the request completed by the TA - * \param key reference to the key plaintext decrypted by the TA - */ - void mark_generated_ta_decrypt_key_request_complete(Trust_anchor_request const &reference, - Key_plaintext_value const &key); - - /** - * Mark generated TA encrypt key request complete - * - * \param request reference to the request completed by the TA - * \param key reference to the key ciphertext encrypted by the TA - */ - void mark_generated_ta_encrypt_key_request_complete(Trust_anchor_request const &request, - Key_ciphertext_value const &key); - - /** - * Mark generated TA last superblock hash request complete - * - * \param request reference to the request completed by the TA - * \param hash reference to the superblock hash stored in the TA - */ - void mark_generated_ta_last_sb_hash_request_complete(Trust_anchor_request const &request, - Hash const &hash); -}; - -#endif /* _CBE_LIBRARY_H_ */ diff --git a/repos/gems/include/cbe/spark_object.h b/repos/gems/include/cbe/spark_object.h deleted file mode 100644 index 540e5812dd..0000000000 --- a/repos/gems/include/cbe/spark_object.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE_SPARK_OBJECT_H_ -#define _CBE_SPARK_OBJECT_H_ - -/* Genode includes */ -#include -#include -#include - -namespace Cbe { - - /** - * Opaque object that contains the space needed to store a SPARK record. - * - * \param BYTES size of the SPARK record in bytes - */ - template - struct Spark_object - { - /** - * Exception type - */ - struct Object_size_mismatch { }; - - static constexpr Genode::uint32_t bytes() { return BYTES; } - - long _space[(BYTES + sizeof(long) - 1)/sizeof(long)] { }; - }; - - template - static inline void assert_valid_object_size() - { - if (object_size(*(T *)nullptr) > T::bytes()) { - Genode::error("need ", object_size(*(T *)nullptr), - " bytes, got ", T::bytes(), " bytes"); - throw typename T::Object_size_mismatch(); - } - } - - template - static inline void assert_same_object_size() - { - if (object_size(*(T *)nullptr) != T::bytes()) { - Genode::error("need ", object_size(*(T *)nullptr), - " bytes, got ", T::bytes(), " bytes"); - throw typename T::Object_size_mismatch(); - } - } - -} /* namespace Cbe */ - -#endif /* _CBE_SPARK_OBJECT_H_ */ diff --git a/repos/gems/include/cbe/types.h b/repos/gems/include/cbe/types.h deleted file mode 100644 index 4639741c43..0000000000 --- a/repos/gems/include/cbe/types.h +++ /dev/null @@ -1,451 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE_TYPES_H_ -#define _CBE_TYPES_H_ - -/* Genode includes */ -#include -#include -#include -#include - -namespace Cbe { - - enum { INVALID_GENERATION = 0 }; - - using namespace Genode; - using Number_of_primitives = size_t; - using Physical_block_address = uint64_t; - using Virtual_block_address = uint64_t; - using Generation = uint64_t; - using Generation_string = String<21>; - using Height = uint32_t; - using Number_of_leaves = uint64_t; - using Number_of_leafs = uint64_t; - using Number_of_blocks = uint64_t; - using Degree = uint32_t; - - static constexpr uint32_t BLOCK_SIZE = 4096; - static constexpr uint32_t NR_OF_SNAPSHOTS = 48; - - - class Request - { - public: - - enum class Operation : uint32_t { - INVALID = 0, - READ = 1, - WRITE = 2, - SYNC = 3, - CREATE_SNAPSHOT = 4, - DISCARD_SNAPSHOT = 5, - REKEY = 6, - EXTEND_VBD = 7, - EXTEND_FT = 8, - RESUME_REKEYING = 10, - DEINITIALIZE = 11, - INITIALIZE = 12, - }; - - private: - - Operation _operation; - bool _success; - uint64_t _block_number; - uint64_t _offset; - Number_of_blocks _count; - uint32_t _key_id; - uint32_t _tag; - - public: - - Request(Operation operation, - bool success, - uint64_t block_number, - uint64_t offset, - Number_of_blocks count, - uint32_t key_id, - uint32_t tag) - : - _operation { operation }, - _success { success }, - _block_number { block_number }, - _offset { offset }, - _count { count }, - _key_id { key_id }, - _tag { tag } - { } - - Request() - : - _operation { Operation::INVALID }, - _success { false }, - _block_number { 0 }, - _offset { 0 }, - _count { 0 }, - _key_id { 0 }, - _tag { 0 } - { } - - bool valid() const - { - return _operation != Operation::INVALID; - } - - void print(Genode::Output &out) const; - - - /*************** - ** Accessors ** - ***************/ - - bool read() const { return _operation == Operation::READ; } - bool write() const { return _operation == Operation::WRITE; } - bool sync() const { return _operation == Operation::SYNC; } - bool create_snapshot() const { return _operation == Operation::CREATE_SNAPSHOT; } - bool discard_snapshot() const { return _operation == Operation::DISCARD_SNAPSHOT; } - bool rekey() const { return _operation == Operation::REKEY; } - bool extend_vbd() const { return _operation == Operation::EXTEND_VBD; } - bool extend_ft() const { return _operation == Operation::EXTEND_FT; } - bool resume_rekeying() const { return _operation == Operation::RESUME_REKEYING; } - bool deinitialize() const { return _operation == Operation::DEINITIALIZE; } - bool initialize() const { return _operation == Operation::INITIALIZE; } - - Operation operation() const { return _operation; } - bool success() const { return _success; } - uint64_t block_number() const { return _block_number; } - uint64_t offset() const { return _offset; } - Number_of_blocks count() const { return _count; } - uint32_t key_id() const { return _key_id; } - uint32_t tag() const { return _tag; } - - void success(bool arg) { _success = arg; } - void tag(uint32_t arg) { _tag = arg; } - - } __attribute__((packed)); - - class Trust_anchor_request - { - public: - - enum class Operation : uint32_t { - INVALID = 0, - CREATE_KEY = 1, - SECURE_SUPERBLOCK = 2, - ENCRYPT_KEY = 3, - DECRYPT_KEY = 4, - LAST_SB_HASH = 5, - INITIALIZE = 6, - }; - - private: - - Operation _operation; - bool _success; - uint32_t _tag; - - public: - - Trust_anchor_request() - : - _operation { Operation::INVALID }, - _success { false }, - _tag { 0 } - { } - - Trust_anchor_request(Operation operation, - bool success, - uint32_t tag) - : - _operation { operation }, - _success { success }, - _tag { tag } - { } - - void print(Genode::Output &out) const; - - bool valid() const { return _operation != Operation::INVALID; } - bool create_key() const { return _operation == Operation::CREATE_KEY; } - bool secure_superblock() const { return _operation == Operation::SECURE_SUPERBLOCK; } - bool encrypt_key() const { return _operation == Operation::ENCRYPT_KEY; } - bool decrypt_key() const { return _operation == Operation::DECRYPT_KEY; } - bool last_sb_hash() const { return _operation == Operation::LAST_SB_HASH; } - bool initialize() const { return _operation == Operation::INITIALIZE; } - - Operation operation() const { return _operation; } - bool success() const { return _success; } - uint32_t tag() const { return _tag; } - - void tag(uint32_t arg) { _tag = arg; } - void success(bool arg) { _success = arg; } - - } __attribute__((packed)); - - - struct Block_data - { - char values[BLOCK_SIZE]; - - void print(Genode::Output &out) const - { - using namespace Genode; - for (char const c : values) { - Genode::print(out, Hex(c, Hex::OMIT_PREFIX, Hex::PAD), " "); - } - Genode::print(out, "\n"); - } - } __attribute__((packed)); - - - class Io_buffer - { - private: - - Block_data items[1]; - - public: - - struct Bad_index : Genode::Exception { }; - - struct Index - { - uint32_t value; - - explicit Index(uint32_t value) : value(value) { } - - } __attribute__((packed)); - - Block_data &item(Index const idx) - { - if (idx.value >= sizeof(items) / sizeof(items[0])) { - throw Bad_index(); - } - return items[idx.value]; - } - - } __attribute__((packed)); - - - class Crypto_plain_buffer - { - private: - - Block_data items[1]; - - public: - - struct Bad_index : Genode::Exception { }; - - struct Index - { - uint32_t value; - - explicit Index(uint32_t value) : value(value) { } - - } __attribute__((packed)); - - Block_data &item(Index const idx) - { - if (idx.value >= sizeof(items) / sizeof(items[0])) { - throw Bad_index(); - } - return items[idx.value]; - } - - } __attribute__((packed)); - - - class Crypto_cipher_buffer - { - private: - - Block_data items[1]; - - public: - - struct Bad_index : Genode::Exception { }; - - struct Index - { - uint32_t value; - - explicit Index(uint32_t value) : value(value) { } - - } __attribute__((packed)); - - Block_data &item(Index const idx) - { - if (idx.value >= sizeof(items) / sizeof(items[0])) { - throw Bad_index(); - } - return items[idx.value]; - } - } __attribute__((packed)); - - - /* - * The Hash contains the hash of a node. - */ - struct Hash - { - enum { MAX_LENGTH = 32, }; - char values[MAX_LENGTH]; - - /* hash as hex value plus "0x" prefix and terminating null */ - using String = Genode::String; - - /* debug */ - void print(Genode::Output &out) const - { - using namespace Genode; - Genode::print(out, "0x"); - bool leading_zero = true; - for (char const c : values) { - if (leading_zero) { - if (c) { - leading_zero = false; - Genode::print(out, Hex(c, Hex::OMIT_PREFIX)); - } - } else { - Genode::print(out, Hex(c, Hex::OMIT_PREFIX, Hex::PAD)); - } - } - if (leading_zero) { - Genode::print(out, "0"); - } - } - }; - - struct Key_plaintext_value - { - enum { KEY_SIZE = 32 }; - char value[KEY_SIZE]; - }; - - struct Key_ciphertext_value - { - enum { KEY_SIZE = 32 }; - char value[KEY_SIZE]; - }; - - /* - * The Key contains the key-material that is used to - * process cipher-blocks. - * - * (For now it is not used but the ID field is already referenced - * by type 2 nodes.) - */ - struct Key - { - enum { KEY_SIZE = 32 }; - char value[KEY_SIZE]; - - struct Id { uint32_t value; }; - Id id; - - using String = Genode::String; - - void print(Genode::Output &out) const - { - using namespace Genode; - Genode::print(out, "[", id.value, ", "); - for (uint32_t i = 0; i < 4; i++) { - Genode::print(out, Hex(value[i], Hex::OMIT_PREFIX, Hex::PAD)); - } - Genode::print(out, "...]"); - } - } __attribute__((packed)); - - - struct Active_snapshot_ids - { - uint64_t values[NR_OF_SNAPSHOTS]; - } __attribute__((packed)); - - - struct Info - { - bool valid; - bool rekeying; - bool extending_vbd; - bool extending_ft; - } __attribute__((packed)); -} - - -inline char const *to_string(Cbe::Request::Operation op) -{ - struct Unknown_operation_type : Genode::Exception { }; - switch (op) { - case Cbe::Request::Operation::INVALID: return "invalid"; - case Cbe::Request::Operation::READ: return "read"; - case Cbe::Request::Operation::WRITE: return "write"; - case Cbe::Request::Operation::SYNC: return "sync"; - case Cbe::Request::Operation::CREATE_SNAPSHOT: return "create_snapshot"; - case Cbe::Request::Operation::DISCARD_SNAPSHOT: return "discard_snapshot"; - case Cbe::Request::Operation::REKEY: return "rekey"; - case Cbe::Request::Operation::EXTEND_VBD: return "extend_vbd"; - case Cbe::Request::Operation::EXTEND_FT: return "extend_ft"; - case Cbe::Request::Operation::RESUME_REKEYING: return "resume_rekeying"; - case Cbe::Request::Operation::DEINITIALIZE: return "deinitialize"; - case Cbe::Request::Operation::INITIALIZE: return "initialize"; - } - throw Unknown_operation_type(); -} - - -inline char const *to_string(Cbe::Trust_anchor_request::Operation op) -{ - struct Unknown_operation_type : Genode::Exception { }; - switch (op) { - case Cbe::Trust_anchor_request::Operation::INVALID: return "invalid"; - case Cbe::Trust_anchor_request::Operation::CREATE_KEY: return "create_key"; - case Cbe::Trust_anchor_request::Operation::INITIALIZE: return "initialize"; - case Cbe::Trust_anchor_request::Operation::SECURE_SUPERBLOCK: return "secure_superblock"; - case Cbe::Trust_anchor_request::Operation::ENCRYPT_KEY: return "encrypt_key"; - case Cbe::Trust_anchor_request::Operation::DECRYPT_KEY: return "decrypt_key"; - case Cbe::Trust_anchor_request::Operation::LAST_SB_HASH: return "last_sb_hash"; - } - throw Unknown_operation_type(); -} - - -inline void Cbe::Request::print(Genode::Output &out) const -{ - if (!valid()) { - Genode::print(out, ""); - return; - } - Genode::print(out, "op=", to_string (_operation)); - Genode::print(out, " vba=", _block_number); - Genode::print(out, " cnt=", _count); - Genode::print(out, " tag=", _tag); - Genode::print(out, " key=", _key_id); - Genode::print(out, " off=", _offset); - Genode::print(out, " succ=", _success); -} - -inline void Cbe::Trust_anchor_request::print(Genode::Output &out) const -{ - if (!valid()) { - Genode::print(out, ""); - return; - } - Genode::print(out, "op=", to_string (_operation)); - Genode::print(out, " tag=", _tag); - Genode::print(out, " succ=", _success); -} -#endif /* _CBE_TYPES_H_ */ diff --git a/repos/gems/include/cbe/vfs/trust_anchor_vfs.h b/repos/gems/include/cbe/vfs/trust_anchor_vfs.h deleted file mode 100644 index 487d36128f..0000000000 --- a/repos/gems/include/cbe/vfs/trust_anchor_vfs.h +++ /dev/null @@ -1,728 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE__VFS__TRUST_ANCHOR_VFS_H_ -#define _CBE__VFS__TRUST_ANCHOR_VFS_H_ - -/* local includes */ -#include - -namespace Util { - - using namespace Genode; - - struct Trust_anchor_vfs; - -}; /* namespace Util */ - - -struct Util::Trust_anchor_vfs -{ - struct Invalid_request : Genode::Exception { }; - - using Path = Genode::Path<256>; - - Vfs::File_system &_vfs; - Allocator &_alloc; - - struct File - { - struct Could_not_open_file : Genode::Exception { }; - struct Io_job_already_constructed : Genode::Exception { }; - struct Cannot_drop_unconstructed_io_job : Genode::Exception { }; - - struct Completed_io_job - { - bool completed; - bool success; - }; - - File(File const &) = delete; - File &operator=(File const&) = delete; - - Vfs::File_system &_vfs; - Vfs::Vfs_handle *_vfs_handle; - - Genode::Constructible _io_job { }; - - File(Path const &base_path, - char const *name, - Vfs::File_system &vfs, - Genode::Allocator &alloc) - : - _vfs { vfs }, - _vfs_handle { nullptr } - { - using Result = Vfs::Directory_service::Open_result; - - Path file_path = base_path; - file_path.append_element(name); - - Result const res = - _vfs.open(file_path.string(), - Vfs::Directory_service::OPEN_MODE_RDWR, - (Vfs::Vfs_handle **)&_vfs_handle, alloc); - if (res != Result::OPEN_OK) { - error("could not open '", file_path.string(), "'"); - throw Could_not_open_file(); - } - } - - ~File() - { - _vfs.close(_vfs_handle); - } - - bool submit_io_job(Util::Io_job::Buffer &buffer, - Util::Io_job::Operation op) - { - if (_io_job.constructed()) { - // throw Io_job_already_constructed(); - return false; - } - - _io_job.construct(*_vfs_handle, op, buffer, 0); - return true; - } - - bool execute_io_job() - { - if (!_io_job.constructed()) { - return false; - } - return _io_job->execute(); - } - - void drop_io_job() - { - if (!_io_job.constructed()) { - throw Cannot_drop_unconstructed_io_job(); - } - _io_job.destruct(); - } - - Completed_io_job completed_io_job() - { - if (!_io_job.constructed()) { - return { false, false }; - } - - return { _io_job->completed(), _io_job->succeeded() }; - } - }; - - Path const _ta_dir; - - Util::Io_job::Buffer _init_io_buffer { }; - Util::Io_job::Buffer _encrypt_io_buffer { }; - Util::Io_job::Buffer _decrypt_io_buffer { }; - Util::Io_job::Buffer _generate_key_io_buffer { }; - Util::Io_job::Buffer _last_hash_io_buffer { }; - - File _init_file { _ta_dir, "initialize", _vfs, _alloc }; - File _encrypt_file { _ta_dir, "encrypt", _vfs, _alloc }; - File _decrypt_file { _ta_dir, "decrypt", _vfs, _alloc }; - File _generate_key_file { _ta_dir, "generate_key", _vfs, _alloc }; - File _last_hash_file { _ta_dir, "hashsum", _vfs, _alloc }; - - struct Job - { - enum class Type { - NONE, - DECRYPT_WRITE, - DECRYPT_READ, - ENCRYPT_WRITE, - ENCRYPT_READ, - GENERATE, - INIT_WRITE, - INIT_READ, - HASH_READ, - HASH_UPDATE_WRITE, - HASH_UPDATE_READ, - }; - Type type { Type::NONE }; - - static char const *to_string(Type const type) - { - switch (type) { - case Type::NONE: return "NONE"; - case Type::DECRYPT_WRITE: return "DECRYPT_WRITE"; - case Type::DECRYPT_READ: return "DECRYPT_READ"; - case Type::ENCRYPT_WRITE: return "ENCRYPT_WRITE"; - case Type::ENCRYPT_READ: return "ENCRYPT_READ"; - case Type::GENERATE: return "GENERATE"; - case Type::INIT_WRITE: return "INIT_WRITE"; - case Type::INIT_READ: return "INIT_READ"; - case Type::HASH_READ: return "HASH_READ"; - case Type::HASH_UPDATE_WRITE: return "HASH_UPDATE_WRITE"; - case Type::HASH_UPDATE_READ: return "HASH_UPDATE_READ"; - } - return nullptr; - } - - enum class State { - NONE, - PENDING, - IN_PROGRESS, - COMPLETE - }; - State state { State::NONE }; - - static char const *to_string(State const state) - { - switch (state) { - case State::NONE: return "NONE"; - case State::PENDING: return "PENDING"; - case State::IN_PROGRESS: return "IN_PROGRESS"; - case State::COMPLETE: return "COMPLETE"; - } - return nullptr; - } - - Cbe::Hash hash; - Cbe::Key_plaintext_value plain; - Cbe::Key_ciphertext_value cipher; - - Cbe::Trust_anchor_request request { }; - bool success { false }; - - void reset() - { - type = Type::NONE; - state = State::NONE; - request = Cbe::Trust_anchor_request(); - } - - bool valid() const { return state != State::NONE; } - - bool completed() const { return state == State::COMPLETE; } - - bool equals(Cbe::Trust_anchor_request const &other) const - { - return request.operation() == other.operation() - && request.tag() == other.tag(); - } - - void print(Genode::Output &out) const - { - if (!valid()) { - Genode::print(out, ""); - return; - } - - Genode::print(out, "type: ", to_string(type)); - Genode::print(out, " state: ", to_string(state)); - Genode::print(out, " request: ", request); - } - }; - - Job _job { }; - - bool _execute_decrypt(Job &job, bool write) - { - bool progress = false; - File::Completed_io_job completed_io_job { false, false }; - - switch (job.state) { - case Job::State::PENDING: - { - using Op = Util::Io_job::Operation; - - Op const op = write ? Op::WRITE : Op::READ; - if (!_decrypt_file.submit_io_job(_decrypt_io_buffer, op)) { - break; - } - job.state = Job::State::IN_PROGRESS; - progress |= true; - } - [[fallthrough]]; - case Job::State::IN_PROGRESS: - if (!_decrypt_file.execute_io_job()) { - break; - } - - progress |= true; - - completed_io_job = _decrypt_file.completed_io_job(); - if (!completed_io_job.completed) { - break; - } - _decrypt_file.drop_io_job(); - - /* setup second phase */ - if (write) { - - /* - * In case the write request was not successful it - * is not needed to try to read the result. - */ - if (!completed_io_job.success) { - job.state = Job::State::COMPLETE; - job.request.success(false); - break; - } - - _decrypt_io_buffer = { - .base = _job.plain.value, - .size = sizeof (_job.plain) - }; - - job.type = Job::Type::DECRYPT_READ; - job.state = Job::State::PENDING; - break; - } - - job.state = Job::State::COMPLETE; - job.success = completed_io_job.success; - job.request.success(job.success); - [[fallthrough]]; - case Job::State::COMPLETE: break; - case Job::State::NONE: break; - } - return progress; - } - - bool _execute_encrypt(Job &job, bool write) - { - bool progress = false; - File::Completed_io_job completed_io_job { false, false }; - - switch (job.state) { - case Job::State::PENDING: - { - using Op = Util::Io_job::Operation; - - Op const op = write ? Op::WRITE : Op::READ; - if (!_encrypt_file.submit_io_job(_encrypt_io_buffer, op)) { - break; - } - job.state = Job::State::IN_PROGRESS; - progress |= true; - } - [[fallthrough]]; - case Job::State::IN_PROGRESS: - if (!_encrypt_file.execute_io_job()) { - break; - } - - progress |= true; - - completed_io_job = _encrypt_file.completed_io_job(); - if (!completed_io_job.completed) { - break; - } - _encrypt_file.drop_io_job(); - - /* setup second phase */ - if (write) { - - /* - * In case the write request was not successful it - * is not needed to try to read the result. - */ - if (!completed_io_job.success) { - job.state = Job::State::COMPLETE; - job.request.success(false); - break; - } - - _encrypt_io_buffer = { - .base = _job.cipher.value, - .size = sizeof (_job.cipher) - }; - - job.type = Job::Type::ENCRYPT_READ; - job.state = Job::State::PENDING; - break; - } - - job.state = Job::State::COMPLETE; - job.success = completed_io_job.success; - job.request.success(job.success); - [[fallthrough]]; - case Job::State::COMPLETE: break; - case Job::State::NONE: break; - } - return progress; - } - - bool _execute_generate(Job &job) - { - bool progress = false; - File::Completed_io_job completed_io_job { false, false }; - - switch (job.state) { - case Job::State::PENDING: - if (!_generate_key_file.submit_io_job(_generate_key_io_buffer, - Util::Io_job::Operation::READ)) { - break; - } - job.state = Job::State::IN_PROGRESS; - progress |= true; - [[fallthrough]]; - case Job::State::IN_PROGRESS: - if (!_generate_key_file.execute_io_job()) { - break; - } - - progress |= true; - - completed_io_job = _generate_key_file.completed_io_job(); - if (!completed_io_job.completed) { - break; - } - _generate_key_file.drop_io_job(); - - job.state = Job::State::COMPLETE; - job.success = completed_io_job.success; - job.request.success(job.success); - [[fallthrough]]; - case Job::State::COMPLETE: break; - case Job::State::NONE: break; - } - return progress; - } - - bool _execute_init(Job &job, bool write) - { - bool progress = false; - File::Completed_io_job completed_io_job { false, false }; - - switch (job.state) { - case Job::State::PENDING: - { - using Op = Util::Io_job::Operation; - - Op const op = write ? Op::WRITE : Op::READ; - if (!_init_file.submit_io_job(_init_io_buffer, op)) { - break; - } - job.state = Job::State::IN_PROGRESS; - progress |= true; - } - [[fallthrough]]; - case Job::State::IN_PROGRESS: - if (!_init_file.execute_io_job()) { - break; - } - - progress |= true; - - completed_io_job = _init_file.completed_io_job(); - if (!completed_io_job.completed) { - break; - } - _init_file.drop_io_job(); - - /* setup second phase */ - if (write) { - - /* - * In case the write request was not successful it - * is not needed to try to read the result. - */ - if (!completed_io_job.success) { - job.state = Job::State::COMPLETE; - job.request.success(false); - break; - } - - _init_io_buffer = { - .base = _job.cipher.value, - .size = sizeof (_job.cipher) - }; - - job.type = Job::Type::INIT_READ; - job.state = Job::State::PENDING; - break; - } - - job.state = Job::State::COMPLETE; - job.success = completed_io_job.success; - job.request.success(job.success); - [[fallthrough]]; - case Job::State::COMPLETE: break; - case Job::State::NONE: break; - } - return progress; - } - - bool _execute_read_hash(Job &job) - { - bool progress = false; - File::Completed_io_job completed_io_job { false, false }; - - switch (job.state) { - case Job::State::PENDING: - if (!_last_hash_file.submit_io_job(_last_hash_io_buffer, - Util::Io_job::Operation::READ)) { - break; - } - job.state = Job::State::IN_PROGRESS; - progress |= true; - [[fallthrough]]; - case Job::State::IN_PROGRESS: - if (!_last_hash_file.execute_io_job()) { - break; - } - - progress |= true; - - completed_io_job = _last_hash_file.completed_io_job(); - if (!completed_io_job.completed) { - break; - } - _last_hash_file.drop_io_job(); - - job.state = Job::State::COMPLETE; - job.success = completed_io_job.success; - job.request.success(job.success); - [[fallthrough]]; - case Job::State::COMPLETE: break; - case Job::State::NONE: break; - } - return progress; - } - - bool _execute_update_hash(Job &job, bool write) - { - bool progress = false; - File::Completed_io_job completed_io_job { false, false }; - - switch (job.state) { - case Job::State::PENDING: - { - using Op = Util::Io_job::Operation; - - Op const op = write ? Op::WRITE : Op::READ; - if (!_last_hash_file.submit_io_job(_last_hash_io_buffer, op)) { - break; - } - job.state = Job::State::IN_PROGRESS; - progress |= true; - } - [[fallthrough]]; - case Job::State::IN_PROGRESS: - if (!_last_hash_file.execute_io_job()) { - break; - } - - progress |= true; - - completed_io_job = _last_hash_file.completed_io_job(); - if (!completed_io_job.completed) { - break; - } - _last_hash_file.drop_io_job(); - - /* setup second phase */ - if (write) { - - /* - * In case the write request was not successful it - * is not needed to try to read the result. - */ - if (!completed_io_job.success) { - job.state = Job::State::COMPLETE; - job.request.success(false); - break; - } - - _last_hash_io_buffer = { - .base = _job.hash.values, - .size = sizeof (_job.hash) - }; - - job.type = Job::Type::HASH_UPDATE_READ; - job.state = Job::State::PENDING; - break; - } - - job.state = Job::State::COMPLETE; - job.success = completed_io_job.success; - job.request.success(job.success); - [[fallthrough]]; - case Job::State::COMPLETE: break; - case Job::State::NONE: break; - } - return progress; - } - - Trust_anchor_vfs(Vfs::File_system &vfs, - Genode::Allocator &alloc, - Path const &path) - : - _vfs(vfs), _alloc(alloc), _ta_dir(path) - { } - - bool request_acceptable() const - { - return !_job.valid(); - } - - void submit_create_key_request(Cbe::Trust_anchor_request const &request) - { - _job = { - .type = Job::Type::GENERATE, - .state = Job::State::PENDING, - .hash = Cbe::Hash(), - .plain = Cbe::Key_plaintext_value(), - .cipher = Cbe::Key_ciphertext_value(), - .request = request, - .success = false, - }; - - _generate_key_io_buffer = { - .base = _job.plain.value, - .size = sizeof (_job.plain) - }; - } - - void submit_superblock_hash_request(Cbe::Trust_anchor_request const &request) - { - _job = { - .type = Job::Type::HASH_READ, - .state = Job::State::PENDING, - .hash = Cbe::Hash(), - .plain = Cbe::Key_plaintext_value(), - .cipher = Cbe::Key_ciphertext_value(), - .request = request, - .success = false, - }; - - _last_hash_io_buffer = { - .base = _job.hash.values, - .size = sizeof (_job.hash) - }; - } - - void submit_secure_superblock_request(Cbe::Trust_anchor_request const &request, - Cbe::Hash const &hash) - { - _job = { - .type = Job::Type::HASH_UPDATE_WRITE, - .state = Job::State::PENDING, - .hash = hash, - .plain = Cbe::Key_plaintext_value(), - .cipher = Cbe::Key_ciphertext_value(), - .request = request, - .success = false, - }; - - _last_hash_io_buffer = { - .base = _job.hash.values, - .size = sizeof (_job.hash) - }; - } - - void submit_encrypt_key_request(Cbe::Trust_anchor_request const &request, - Cbe::Key_plaintext_value const &plain) - { - _job = { - .type = Job::Type::ENCRYPT_WRITE, - .state = Job::State::PENDING, - .hash = Cbe::Hash(), - .plain = plain, - .cipher = Cbe::Key_ciphertext_value(), - .request = request, - .success = false, - }; - - _encrypt_io_buffer = { - .base = _job.plain.value, - .size = sizeof (_job.plain) - }; - } - - void submit_decrypt_key_request(Cbe::Trust_anchor_request const &request, - Cbe::Key_ciphertext_value const &cipher) - { - _job = { - .type = Job::Type::DECRYPT_WRITE, - .state = Job::State::PENDING, - .hash = Cbe::Hash(), - .plain = Cbe::Key_plaintext_value(), - .cipher = cipher, - .request = request, - .success = false, - }; - - _decrypt_io_buffer = { - .base = _job.cipher.value, - .size = sizeof (_job.cipher) - }; - } - - Cbe::Trust_anchor_request peek_completed_request() - { - return _job.completed() ? _job.request : Cbe::Trust_anchor_request(); - } - - void drop_completed_request(Cbe::Trust_anchor_request const &request) - { - if (!_job.equals(request)) { - throw Invalid_request(); - } - - _job.reset(); - } - - Cbe::Hash peek_completed_superblock_hash(Cbe::Trust_anchor_request const &request) - { - if (!_job.equals(request) || !_job.completed()) { - throw Invalid_request(); - } - - return _job.hash; - } - - Cbe::Key_plaintext_value peek_completed_key_value_plaintext(Cbe::Trust_anchor_request const &request) - { - if (!_job.equals(request) || !_job.completed()) { - throw Invalid_request(); - } - - return _job.plain; - } - - Cbe::Key_ciphertext_value peek_completed_key_value_ciphertext(Cbe::Trust_anchor_request const &request) - { - if (!_job.equals(request) || !_job.completed()) { - throw Invalid_request(); - } - return _job.cipher; - } - - bool execute() - { - bool progress = false; - - switch (_job.type) { - case Job::Type::NONE: break; - case Job::Type::DECRYPT_WRITE: progress |= _execute_decrypt(_job, true); break; - case Job::Type::DECRYPT_READ: progress |= _execute_decrypt(_job, false); break; - case Job::Type::ENCRYPT_WRITE: progress |= _execute_encrypt(_job, true); break; - case Job::Type::ENCRYPT_READ: progress |= _execute_encrypt(_job, false); break; - case Job::Type::GENERATE: progress |= _execute_generate(_job); break; - case Job::Type::INIT_WRITE: progress |= _execute_init(_job, true); break; - case Job::Type::INIT_READ: progress |= _execute_init(_job, false); break; - case Job::Type::HASH_READ: progress |= _execute_read_hash(_job); break; - case Job::Type::HASH_UPDATE_WRITE: progress |= _execute_update_hash(_job, true); break; - case Job::Type::HASH_UPDATE_READ: progress |= _execute_update_hash(_job, false); break; - } - return progress; - } -}; - -#endif /* _CBE__VFS__TRUST_ANCHOR_VFS_H_ */ diff --git a/repos/gems/lib/import/import-cbe.mk b/repos/gems/lib/import/import-cbe.mk deleted file mode 100644 index 17cbac9eed..0000000000 --- a/repos/gems/lib/import/import-cbe.mk +++ /dev/null @@ -1,3 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -INC_DIR += $(CBE_DIR)/src/lib/cbe diff --git a/repos/gems/lib/import/import-cbe_check.mk b/repos/gems/lib/import/import-cbe_check.mk deleted file mode 100644 index 63b108607d..0000000000 --- a/repos/gems/lib/import/import-cbe_check.mk +++ /dev/null @@ -1,2 +0,0 @@ - -INC_DIR += $(call select_from_repositories,src/lib/cbe_check) diff --git a/repos/gems/lib/import/import-cbe_common.mk b/repos/gems/lib/import/import-cbe_common.mk deleted file mode 100644 index 9470566f9e..0000000000 --- a/repos/gems/lib/import/import-cbe_common.mk +++ /dev/null @@ -1,3 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -INC_DIR += $(CBE_DIR)/src/lib/cbe_common diff --git a/repos/gems/lib/import/import-cbe_dump.mk b/repos/gems/lib/import/import-cbe_dump.mk deleted file mode 100644 index 7bfdc02eb7..0000000000 --- a/repos/gems/lib/import/import-cbe_dump.mk +++ /dev/null @@ -1,2 +0,0 @@ - -INC_DIR += $(call select_from_repositories,src/lib/cbe_dump) diff --git a/repos/gems/lib/import/import-cbe_init.mk b/repos/gems/lib/import/import-cbe_init.mk deleted file mode 100644 index 5c2e60c212..0000000000 --- a/repos/gems/lib/import/import-cbe_init.mk +++ /dev/null @@ -1,2 +0,0 @@ - -INC_DIR += $(call select_from_repositories,src/lib/cbe_init) diff --git a/repos/gems/lib/import/import-sha256_4k.mk b/repos/gems/lib/import/import-sha256_4k.mk index 70ad128dc4..79d13851b4 100644 --- a/repos/gems/lib/import/import-sha256_4k.mk +++ b/repos/gems/lib/import/import-sha256_4k.mk @@ -1,3 +1,3 @@ -CBE_DIR := $(call select_from_ports,cbe) +TRESOR_DIR := $(call select_from_ports,tresor) -INC_DIR += $(CBE_DIR)/src/lib/sha256_4k +INC_DIR += $(TRESOR_DIR)/src/lib/sha256_4k diff --git a/repos/gems/lib/import/import-tresor.mk b/repos/gems/lib/import/import-tresor.mk new file mode 100644 index 0000000000..a72808d510 --- /dev/null +++ b/repos/gems/lib/import/import-tresor.mk @@ -0,0 +1 @@ +INC_DIR += $(REP_DIR)/src/lib/tresor/include diff --git a/repos/gems/lib/mk/sha256_4k.mk b/repos/gems/lib/mk/sha256_4k.mk deleted file mode 100644 index 51b8cb1fbc..0000000000 --- a/repos/gems/lib/mk/sha256_4k.mk +++ /dev/null @@ -1,12 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -SRC_ADB := sha256_4k.adb -LIBS += spark libsparkcrypto - -CC_ADA_OPT += -gnatec=$(CBE_DIR)/src/lib/sha256_4k/spark.adc - -INC_DIR += $(CBE_DIR)/src/lib/sha256_4k - -sha256_4k.o : $(CBE_DIR)/src/lib/sha256_4k/sha256_4k.ads - -vpath % $(CBE_DIR)/src/lib/sha256_4k diff --git a/repos/gems/lib/mk/spec/x86_64/cbe.mk b/repos/gems/lib/mk/spec/x86_64/cbe.mk deleted file mode 100644 index b4a6747079..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe.mk +++ /dev/null @@ -1,23 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark sha256_4k cbe_common - -INC_DIR += $(CBE_DIR)/src/lib/cbe - -SRC_ADB += cbe-library.adb -SRC_ADB += cbe-request_pool.adb -SRC_ADB += cbe-crypto.adb -SRC_ADB += cbe-tree_helper.adb -SRC_ADB += cbe-translation.adb -SRC_ADB += cbe-cache.adb -SRC_ADB += cbe-new_free_tree.adb -SRC_ADB += cbe-ft_resizing.adb -SRC_ADB += cbe-mt_resizing.adb -SRC_ADB += cbe-meta_tree.adb -SRC_ADB += cbe-generic_index_queue.adb -SRC_ADB += cbe-superblock_control.adb -SRC_ADB += cbe-vbd_rekeying.adb - -vpath % $(CBE_DIR)/src/lib/cbe - -CC_ADA_OPT += -gnatec=$(CBE_DIR)/src/lib/cbe/pragmas.adc diff --git a/repos/gems/lib/mk/spec/x86_64/cbe_check.mk b/repos/gems/lib/mk/spec/x86_64/cbe_check.mk deleted file mode 100644 index c0bbaaba0d..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe_check.mk +++ /dev/null @@ -1,14 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark sha256_4k cbe_common - -INC_DIR += $(CBE_DIR)/src/lib/cbe_check - -SRC_ADB += cbe-check_library.adb -SRC_ADB += cbe-superblock_check.adb -SRC_ADB += cbe-vbd_check.adb -SRC_ADB += cbe-free_tree_check.adb - -vpath % $(CBE_DIR)/src/lib/cbe_check - -CC_ADA_OPT += -gnatec=$(CBE_DIR)/src/lib/cbe_check/pragmas.adc diff --git a/repos/gems/lib/mk/spec/x86_64/cbe_check_cxx.mk b/repos/gems/lib/mk/spec/x86_64/cbe_check_cxx.mk deleted file mode 100644 index 67b0d32f94..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe_check_cxx.mk +++ /dev/null @@ -1,17 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark libsparkcrypto sha256_4k cbe_common cbe_cxx_common -LIBS += cbe_check - -INC_DIR += $(CBE_DIR)/src/lib/cbe_check -INC_DIR += $(CBE_DIR)/src/lib/cbe_common -INC_DIR += $(CBE_DIR)/src/lib/cbe_check_cxx -INC_DIR += $(CBE_DIR)/src/lib/cbe_cxx_common - -SRC_ADB += cbe-cxx-cxx_check_library.adb - -vpath % $(CBE_DIR)/src/lib/cbe_check_cxx - -SHARED_LIB := yes - -include $(REP_DIR)/lib/mk/generate_ada_main_pkg.inc diff --git a/repos/gems/lib/mk/spec/x86_64/cbe_common.mk b/repos/gems/lib/mk/spec/x86_64/cbe_common.mk deleted file mode 100644 index 75720e7c51..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe_common.mk +++ /dev/null @@ -1,17 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark sha256_4k - -INC_DIR += $(CBE_DIR)/src/lib/cbe_common - -SRC_ADB += cbe.adb -SRC_ADB += cbe-debug.adb -SRC_ADB += cbe-request.adb -SRC_ADB += cbe-primitive.adb -SRC_ADB += cbe-block_io.adb -SRC_ADB += cbe-ta_request.adb -SRC_ADB += cbe-trust_anchor.adb - -vpath % $(CBE_DIR)/src/lib/cbe_common - -CC_ADA_OPT += -gnatec=$(CBE_DIR)/src/lib/cbe_common/pragmas.adc diff --git a/repos/gems/lib/mk/spec/x86_64/cbe_cxx.mk b/repos/gems/lib/mk/spec/x86_64/cbe_cxx.mk deleted file mode 100644 index def599094c..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe_cxx.mk +++ /dev/null @@ -1,16 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark libsparkcrypto sha256_4k cbe cbe_common cbe_cxx_common - -INC_DIR += $(CBE_DIR)/src/lib/cbe -INC_DIR += $(CBE_DIR)/src/lib/cbe_common -INC_DIR += $(CBE_DIR)/src/lib/cbe_cxx -INC_DIR += $(CBE_DIR)/src/lib/cbe_cxx_common - -SRC_ADB += cbe-cxx-cxx_library.adb - -vpath % $(CBE_DIR)/src/lib/cbe_cxx - -SHARED_LIB := yes - -include $(REP_DIR)/lib/mk/generate_ada_main_pkg.inc diff --git a/repos/gems/lib/mk/spec/x86_64/cbe_cxx_common.mk b/repos/gems/lib/mk/spec/x86_64/cbe_cxx_common.mk deleted file mode 100644 index 42df4ec892..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe_cxx_common.mk +++ /dev/null @@ -1,12 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark cbe_common - -INC_DIR += $(CBE_DIR)/src/lib/cbe_common -INC_DIR += $(CBE_DIR)/src/lib/cbe_cxx_common - -SRC_ADB += cbe-cxx.adb - -SRC_CC += print_cstring.cc - -vpath % $(CBE_DIR)/src/lib/cbe_cxx_common diff --git a/repos/gems/lib/mk/spec/x86_64/cbe_dump.mk b/repos/gems/lib/mk/spec/x86_64/cbe_dump.mk deleted file mode 100644 index 43fbaa662f..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe_dump.mk +++ /dev/null @@ -1,14 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark sha256_4k cbe_common - -INC_DIR += $(CBE_DIR)/src/lib/cbe_dump - -SRC_ADB += cbe-dump_library.adb -SRC_ADB += cbe-superblock_dump.adb -SRC_ADB += cbe-vbd_dump.adb -SRC_ADB += cbe-free_tree_dump.adb - -vpath % $(CBE_DIR)/src/lib/cbe_dump - -CC_ADA_OPT += -gnatec=$(CBE_DIR)/src/lib/cbe_dump/pragmas.adc diff --git a/repos/gems/lib/mk/spec/x86_64/cbe_dump_cxx.mk b/repos/gems/lib/mk/spec/x86_64/cbe_dump_cxx.mk deleted file mode 100644 index 7af5498569..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe_dump_cxx.mk +++ /dev/null @@ -1,17 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark libsparkcrypto sha256_4k cbe_common cbe_cxx_common -LIBS += cbe_dump - -INC_DIR += $(CBE_DIR)/src/lib/cbe_dump -INC_DIR += $(CBE_DIR)/src/lib/cbe_common -INC_DIR += $(CBE_DIR)/src/lib/cbe_dump_cxx -INC_DIR += $(CBE_DIR)/src/lib/cbe_cxx_common - -SRC_ADB += cbe-cxx-cxx_dump_library.adb - -vpath % $(CBE_DIR)/src/lib/cbe_dump_cxx - -SHARED_LIB := yes - -include $(REP_DIR)/lib/mk/generate_ada_main_pkg.inc diff --git a/repos/gems/lib/mk/spec/x86_64/cbe_init.mk b/repos/gems/lib/mk/spec/x86_64/cbe_init.mk deleted file mode 100644 index 6523133d25..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe_init.mk +++ /dev/null @@ -1,15 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark sha256_4k cbe_common cbe_cxx_common - -INC_DIR += $(CBE_DIR)/src/lib/cbe_init - -SRC_ADB += cbe-init_library.adb -SRC_ADB += cbe-block_allocator.adb -SRC_ADB += cbe-superblock_initializer.adb -SRC_ADB += cbe-vbd_initializer.adb -SRC_ADB += cbe-free_tree_initializer.adb - -vpath % $(CBE_DIR)/src/lib/cbe_init - -CC_ADA_OPT += -gnatec=$(CBE_DIR)/src/lib/cbe_init/pragmas.adc diff --git a/repos/gems/lib/mk/spec/x86_64/cbe_init_cxx.mk b/repos/gems/lib/mk/spec/x86_64/cbe_init_cxx.mk deleted file mode 100644 index 6940a693d1..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/cbe_init_cxx.mk +++ /dev/null @@ -1,17 +0,0 @@ -CBE_DIR := $(call select_from_ports,cbe) - -LIBS += spark libsparkcrypto sha256_4k cbe_common cbe_cxx_common -LIBS += cbe_init - -INC_DIR += $(CBE_DIR)/src/lib/cbe_init -INC_DIR += $(CBE_DIR)/src/lib/cbe_common -INC_DIR += $(CBE_DIR)/src/lib/cbe_init_cxx -INC_DIR += $(CBE_DIR)/src/lib/cbe_cxx_common - -SRC_ADB += cbe-cxx-cxx_init_library.adb - -vpath % $(CBE_DIR)/src/lib/cbe_init_cxx - -SHARED_LIB := yes - -include $(REP_DIR)/lib/mk/generate_ada_main_pkg.inc diff --git a/repos/gems/lib/mk/spec/x86_64/vfs_cbe.mk b/repos/gems/lib/mk/spec/x86_64/vfs_cbe.mk deleted file mode 100644 index 24c12acf27..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/vfs_cbe.mk +++ /dev/null @@ -1,11 +0,0 @@ -SRC_CC = vfs.cc - -INC_DIR += $(REP_DIR)/src/lib/vfs/cbe - -LIBS += cbe_cxx - -vpath % $(REP_DIR)/src/lib/vfs/cbe - -SHARED_LIB := yes - -CC_CXX_WARN_STRICT := diff --git a/repos/gems/lib/mk/spec/x86_64/vfs_cbe_crypto_aes_cbc.mk b/repos/gems/lib/mk/spec/x86_64/vfs_cbe_crypto_aes_cbc.mk deleted file mode 100644 index ee780287e2..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/vfs_cbe_crypto_aes_cbc.mk +++ /dev/null @@ -1,9 +0,0 @@ -SRC_CC := vfs.cc -SRC_CC += aes_cbc.cc - -LIBS += aes_cbc_4k - -vpath vfs.cc $(REP_DIR)/src/lib/vfs/cbe_crypto/ -vpath % $(REP_DIR)/src/lib/vfs/cbe_crypto/aes_cbc - -SHARED_LIB = yes diff --git a/repos/gems/lib/mk/spec/x86_64/vfs_cbe_crypto_memcopy.mk b/repos/gems/lib/mk/spec/x86_64/vfs_cbe_crypto_memcopy.mk deleted file mode 100644 index 0427316618..0000000000 --- a/repos/gems/lib/mk/spec/x86_64/vfs_cbe_crypto_memcopy.mk +++ /dev/null @@ -1,9 +0,0 @@ -SRC_CC := vfs.cc -SRC_CC += memcopy.cc - -vpath vfs.cc $(REP_DIR)/src/lib/vfs/cbe_crypto/ -vpath %.cc $(REP_DIR)/src/lib/vfs/cbe_crypto/memcopy - -SHARED_LIB = yes - -CC_CXX_WARN_STRICT_CONVERSION = diff --git a/repos/gems/lib/mk/tresor.mk b/repos/gems/lib/mk/tresor.mk new file mode 100644 index 0000000000..819df67069 --- /dev/null +++ b/repos/gems/lib/mk/tresor.mk @@ -0,0 +1,28 @@ +TRESOR_DIR := $(REP_DIR)/src/lib/tresor + +SRC_CC += crypto.cc +SRC_CC += request_pool.cc +SRC_CC += sha256_4k_hash.cc +SRC_CC += trust_anchor.cc +SRC_CC += block_io.cc +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 += block_allocator.cc +SRC_CC += vbd_initializer.cc +SRC_CC += ft_initializer.cc +SRC_CC += sb_initializer.cc +SRC_CC += vfs_utilities.cc +SRC_CC += ft_resizing.cc +SRC_CC += sb_check.cc +SRC_CC += vbd_check.cc +SRC_CC += ft_check.cc + +vpath % $(TRESOR_DIR) + +INC_DIR += $(TRESOR_DIR)/include + +LIBS += libcrypto +LIBS += vfs diff --git a/repos/gems/lib/mk/vfs_tresor.mk b/repos/gems/lib/mk/vfs_tresor.mk new file mode 100644 index 0000000000..549024bf5c --- /dev/null +++ b/repos/gems/lib/mk/vfs_tresor.mk @@ -0,0 +1,11 @@ +LIB_DIR := $(REP_DIR)/src/lib/vfs/tresor + +SRC_CC := vfs.cc + +INC_DIR += $(LIB_DIR) + +vpath % $(LIB_DIR) + +LIBS += tresor + +SHARED_LIB := yes diff --git a/repos/gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk b/repos/gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk new file mode 100644 index 0000000000..b534ccdf57 --- /dev/null +++ b/repos/gems/lib/mk/vfs_tresor_crypto_aes_cbc.mk @@ -0,0 +1,11 @@ +SRC_CC := vfs.cc +SRC_CC += aes_cbc.cc + +INC_DIR += $(REP_DIR)/src/lib/tresor/include + +LIBS += aes_cbc_4k + +vpath vfs.cc $(REP_DIR)/src/lib/vfs/tresor_crypto/ +vpath % $(REP_DIR)/src/lib/vfs/tresor_crypto/aes_cbc + +SHARED_LIB = yes diff --git a/repos/gems/lib/mk/vfs_tresor_crypto_memcopy.mk b/repos/gems/lib/mk/vfs_tresor_crypto_memcopy.mk new file mode 100644 index 0000000000..e1afc52178 --- /dev/null +++ b/repos/gems/lib/mk/vfs_tresor_crypto_memcopy.mk @@ -0,0 +1,9 @@ +SRC_CC := vfs.cc +SRC_CC += memcopy.cc + +INC_DIR += $(REP_DIR)/src/lib/tresor/include + +vpath vfs.cc $(REP_DIR)/src/lib/vfs/tresor_crypto/ +vpath %.cc $(REP_DIR)/src/lib/vfs/tresor_crypto/memcopy + +SHARED_LIB = yes diff --git a/repos/gems/lib/mk/spec/x86_64/vfs_cbe_trust_anchor.mk b/repos/gems/lib/mk/vfs_tresor_trust_anchor.mk similarity index 54% rename from repos/gems/lib/mk/spec/x86_64/vfs_cbe_trust_anchor.mk rename to repos/gems/lib/mk/vfs_tresor_trust_anchor.mk index b3eacfa58a..858d921fc3 100644 --- a/repos/gems/lib/mk/spec/x86_64/vfs_cbe_trust_anchor.mk +++ b/repos/gems/lib/mk/vfs_tresor_trust_anchor.mk @@ -4,11 +4,12 @@ SRC_CC += vfs.cc SRC_CC += aes_256.cc SRC_CC += integer.cc -INC_DIR += $(REP_DIR)/src/lib/vfs/cbe_trust_anchor +INC_DIR += $(REP_DIR)/src/lib/vfs/tresor_trust_anchor +INC_DIR += $(REP_DIR)/src/lib/tresor/include INC_DIR += $(OPENSSL_DIR)/include LIBS += libcrypto -vpath % $(REP_DIR)/src/lib/vfs/cbe_trust_anchor +vpath % $(REP_DIR)/src/lib/vfs/tresor_trust_anchor SHARED_LIB := yes diff --git a/repos/gems/lib/symbols/cbe_check_cxx b/repos/gems/lib/symbols/cbe_check_cxx deleted file mode 100644 index 7b86a6742d..0000000000 --- a/repos/gems/lib/symbols/cbe_check_cxx +++ /dev/null @@ -1,14 +0,0 @@ -_ZN9Cbe_check11object_sizeERKNS_7LibraryE T -_ZN9Cbe_check7Library20io_request_completedERKN3Cbe9Io_buffer5IndexEb T -_ZN9Cbe_check7Library21submit_client_requestERKN3Cbe7RequestE T -_ZN9Cbe_check7Library22io_request_in_progressERKN3Cbe9Io_buffer5IndexE T -_ZN9Cbe_check7Library29drop_completed_client_requestERKN3Cbe7RequestE T -_ZN9Cbe_check7Library7executeERKN3Cbe9Io_bufferE T -_ZN9Cbe_check7LibraryC1Ev T -_ZN9Sha256_4k4hashERKNS_4DataERNS_4HashE T -_ZNK9Cbe_check7Library14has_io_requestERN3Cbe7RequestERNS1_9Io_buffer5IndexE T -_ZNK9Cbe_check7Library16execute_progressEv T -_ZNK9Cbe_check7Library25client_request_acceptableEv T -_ZNK9Cbe_check7Library29peek_completed_client_requestEv T -cbe_check_cxx_final T -cbe_check_cxx_init T diff --git a/repos/gems/lib/symbols/cbe_cxx b/repos/gems/lib/symbols/cbe_cxx deleted file mode 100644 index e91982deba..0000000000 --- a/repos/gems/lib/symbols/cbe_cxx +++ /dev/null @@ -1,44 +0,0 @@ -_ZN3Cbe11object_sizeERKNS_7LibraryE T -_ZN3Cbe7Library20io_request_completedERKNS_9Io_buffer5IndexEb T -_ZN3Cbe7Library21submit_client_requestERKNS_7RequestEj T -_ZN3Cbe7Library22io_request_in_progressERKNS_9Io_buffer5IndexE T -_ZN3Cbe7Library24crypto_add_key_completedERKNS_7RequestE T -_ZN3Cbe7Library24crypto_add_key_requestedERKNS_7RequestE T -_ZN3Cbe7Library24supply_crypto_plain_dataERKNS_19Crypto_plain_buffer5IndexEb T -_ZN3Cbe7Library25drop_generated_ta_requestERKNS_20Trust_anchor_requestE T -_ZN3Cbe7Library25supply_crypto_cipher_dataERKNS_20Crypto_cipher_buffer5IndexEb T -_ZN3Cbe7Library27crypto_plain_data_requestedERKNS_20Crypto_cipher_buffer5IndexE T -_ZN3Cbe7Library27crypto_remove_key_completedERKNS_7RequestE T -_ZN3Cbe7Library27crypto_remove_key_requestedERKNS_7RequestE T -_ZN3Cbe7Library28crypto_cipher_data_requestedERKNS_19Crypto_plain_buffer5IndexE T -_ZN3Cbe7Library29drop_completed_client_requestERKNS_7RequestE T -_ZN3Cbe7Library35client_transfer_read_data_completedERKNS_19Crypto_plain_buffer5IndexEb T -_ZN3Cbe7Library36client_transfer_write_data_completedERKNS_19Crypto_plain_buffer5IndexEb T -_ZN3Cbe7Library37client_transfer_read_data_in_progressERKNS_19Crypto_plain_buffer5IndexE T -_ZN3Cbe7Library38client_transfer_write_data_in_progressERKNS_19Crypto_plain_buffer5IndexE T -_ZN3Cbe7Library44mark_generated_ta_secure_sb_request_completeERKNS_20Trust_anchor_requestE T -_ZN3Cbe7Library45mark_generated_ta_create_key_request_completeERKNS_20Trust_anchor_requestERKNS_19Key_plaintext_valueE T -_ZN3Cbe7Library46mark_generated_ta_decrypt_key_request_completeERKNS_20Trust_anchor_requestERKNS_19Key_plaintext_valueE T -_ZN3Cbe7Library46mark_generated_ta_encrypt_key_request_completeERKNS_20Trust_anchor_requestERKNS_20Key_ciphertext_valueE T -_ZN3Cbe7Library47mark_generated_ta_last_sb_hash_request_completeERKNS_20Trust_anchor_requestERKNS_4HashE T -_ZN3Cbe7Library7executeERNS_9Io_bufferERNS_19Crypto_plain_bufferERNS_20Crypto_cipher_bufferE T -_ZN3Cbe7LibraryC2Ev T -_ZNK3Cbe7Library15_has_io_requestERNS_7RequestERNS_9Io_buffer5IndexE T -_ZNK3Cbe7Library16execute_progressEv T -_ZNK3Cbe7Library19active_snapshot_idsERNS_19Active_snapshot_idsE T -_ZNK3Cbe7Library24_crypto_add_key_requiredERNS_7RequestERNS_3KeyE T -_ZNK3Cbe7Library25client_request_acceptableEv T -_ZNK3Cbe7Library26_peek_generated_ta_requestERNS_20Trust_anchor_requestE T -_ZNK3Cbe7Library26_peek_generated_ta_sb_hashERKNS_20Trust_anchor_requestERNS_4HashE T -_ZNK3Cbe7Library27_crypto_plain_data_requiredERNS_7RequestERNS_20Crypto_cipher_buffer5IndexE T -_ZNK3Cbe7Library27_crypto_remove_key_requiredERNS_7RequestERNS_3Key2IdE T -_ZNK3Cbe7Library28_crypto_cipher_data_requiredERNS_7RequestERNS_19Crypto_plain_buffer5IndexE T -_ZNK3Cbe7Library29peek_completed_client_requestEv T -_ZNK3Cbe7Library34client_transfer_read_data_requiredERNS_7RequestERyRNS_19Crypto_plain_buffer5IndexE T -_ZNK3Cbe7Library35client_transfer_write_data_requiredERNS_7RequestERyRNS_19Crypto_plain_buffer5IndexE T -_ZNK3Cbe7Library38_peek_generated_ta_key_value_plaintextERKNS_20Trust_anchor_requestERNS_19Key_plaintext_valueE T -_ZNK3Cbe7Library39_peek_generated_ta_key_value_ciphertextERKNS_20Trust_anchor_requestERNS_20Key_ciphertext_valueE T -_ZNK3Cbe7Library5_infoERNS_4InfoE T -_ZNK3Cbe7Library7max_vbaEv T -cbe_cxx_final T -cbe_cxx_init T diff --git a/repos/gems/lib/symbols/cbe_dump_cxx b/repos/gems/lib/symbols/cbe_dump_cxx deleted file mode 100644 index 218a8d7184..0000000000 --- a/repos/gems/lib/symbols/cbe_dump_cxx +++ /dev/null @@ -1,14 +0,0 @@ -_ZN8Cbe_dump11object_sizeERKNS_7LibraryE T -_ZN8Cbe_dump7Library20io_request_completedERKN3Cbe9Io_buffer5IndexEb T -_ZN8Cbe_dump7Library21submit_client_requestERKN3Cbe7RequestERKNS_13ConfigurationE T -_ZN8Cbe_dump7Library22io_request_in_progressERKN3Cbe9Io_buffer5IndexE T -_ZN8Cbe_dump7Library29drop_completed_client_requestERKN3Cbe7RequestE T -_ZN8Cbe_dump7Library7executeERKN3Cbe9Io_bufferE T -_ZN8Cbe_dump7LibraryC1Ev T -_ZN9Sha256_4k4hashERKNS_4DataERNS_4HashE T -_ZNK8Cbe_dump7Library14has_io_requestERN3Cbe7RequestERNS1_9Io_buffer5IndexE T -_ZNK8Cbe_dump7Library16execute_progressEv T -_ZNK8Cbe_dump7Library25client_request_acceptableEv T -_ZNK8Cbe_dump7Library29peek_completed_client_requestEv T -cbe_dump_cxx_final T -cbe_dump_cxx_init T diff --git a/repos/gems/lib/symbols/cbe_init_cxx b/repos/gems/lib/symbols/cbe_init_cxx deleted file mode 100644 index bd19268849..0000000000 --- a/repos/gems/lib/symbols/cbe_init_cxx +++ /dev/null @@ -1,25 +0,0 @@ -_ZN10Aes_cbc_4k7decryptERKNS_3KeyENS_12Block_numberERKNS_10CiphertextERNS_9PlaintextE T -_ZN10Aes_cbc_4k7encryptERKNS_3KeyENS_12Block_numberERKNS_9PlaintextERNS_10CiphertextE T -_ZN8Cbe_init11object_sizeERKNS_7LibraryE T -_ZN8Cbe_init7Library20io_request_completedERKN3Cbe9Io_buffer5IndexEb T -_ZN8Cbe_init7Library21submit_client_requestERKN3Cbe7RequestEyyyyyy T -_ZN8Cbe_init7Library22io_request_in_progressERKN3Cbe9Io_buffer5IndexE T -_ZN8Cbe_init7Library25drop_generated_ta_requestERKN3Cbe20Trust_anchor_requestE T -_ZN8Cbe_init7Library29drop_completed_client_requestERKN3Cbe7RequestE T -_ZN8Cbe_init7Library44mark_generated_ta_secure_sb_request_completeERKN3Cbe20Trust_anchor_requestE T -_ZN8Cbe_init7Library45mark_generated_ta_create_key_request_completeERKN3Cbe20Trust_anchor_requestERKNS1_19Key_plaintext_valueE T -_ZN8Cbe_init7Library46mark_generated_ta_decrypt_key_request_completeERKN3Cbe20Trust_anchor_requestERKNS1_19Key_plaintext_valueE T -_ZN8Cbe_init7Library46mark_generated_ta_encrypt_key_request_completeERKN3Cbe20Trust_anchor_requestERKNS1_20Key_ciphertext_valueE T -_ZN8Cbe_init7Library7executeERN3Cbe9Io_bufferE T -_ZN8Cbe_init7LibraryC1Ev T -_ZN9Sha256_4k4hashERKNS_4DataERNS_4HashE T -_ZNK8Cbe_init7Library14has_io_requestERN3Cbe7RequestERNS1_9Io_buffer5IndexE T -_ZNK8Cbe_init7Library16execute_progressEv T -_ZNK8Cbe_init7Library25client_request_acceptableEv T -_ZNK8Cbe_init7Library26_peek_generated_ta_requestERN3Cbe20Trust_anchor_requestE T -_ZNK8Cbe_init7Library26_peek_generated_ta_sb_hashERKN3Cbe20Trust_anchor_requestERNS1_4HashE T -_ZNK8Cbe_init7Library29peek_completed_client_requestEv T -_ZNK8Cbe_init7Library38_peek_generated_ta_key_value_plaintextERKN3Cbe20Trust_anchor_requestERNS1_19Key_plaintext_valueE T -_ZNK8Cbe_init7Library39_peek_generated_ta_key_value_ciphertextERKN3Cbe20Trust_anchor_requestERNS1_20Key_ciphertext_valueE T -cbe_init_cxx_final T -cbe_init_cxx_init T diff --git a/repos/gems/ports/cbe.hash b/repos/gems/ports/cbe.hash deleted file mode 100644 index e4fd330e7d..0000000000 --- a/repos/gems/ports/cbe.hash +++ /dev/null @@ -1 +0,0 @@ -56ab06c33f61345797baa22c8720e45212b4cb2c diff --git a/repos/gems/ports/cbe.port b/repos/gems/ports/cbe.port deleted file mode 100644 index b8d2569c66..0000000000 --- a/repos/gems/ports/cbe.port +++ /dev/null @@ -1,12 +0,0 @@ -LICENSE := AGPLv3 -VERSION := git -DOWNLOADS := cbe.git - -URL(cbe) := https://github.com/m-stein/cbe.git -DIR(cbe) := cbe -REV(cbe) := 805b0942fb0b34464354e59366ed23b412da2126 - -default: symlinks - -symlinks: $(DOWNLOADS) - ln -s cbe/src src diff --git a/repos/gems/recipes/api/cbe/content.mk b/repos/gems/recipes/api/tresor/content.mk similarity index 73% rename from repos/gems/recipes/api/cbe/content.mk rename to repos/gems/recipes/api/tresor/content.mk index 195f54be48..5b30393253 100644 --- a/repos/gems/recipes/api/cbe/content.mk +++ b/repos/gems/recipes/api/tresor/content.mk @@ -1,5 +1,6 @@ MIRROR_FROM_REP_DIR := \ - include/cbe/types.h + src/lib/tresor/include \ + lib/import/import-tresor.mk content: $(MIRROR_FROM_REP_DIR) LICENSE diff --git a/repos/gems/recipes/api/cbe/hash b/repos/gems/recipes/api/tresor/hash similarity index 100% rename from repos/gems/recipes/api/cbe/hash rename to repos/gems/recipes/api/tresor/hash diff --git a/repos/gems/recipes/api/cbe/used_apis b/repos/gems/recipes/api/tresor/used_apis similarity index 71% rename from repos/gems/recipes/api/cbe/used_apis rename to repos/gems/recipes/api/tresor/used_apis index fcdc7f1050..02144b4883 100644 --- a/repos/gems/recipes/api/cbe/used_apis +++ b/repos/gems/recipes/api/tresor/used_apis @@ -2,9 +2,7 @@ aes_cbc_4k base block_session libc -libsparkcrypto openssl os so -spark vfs diff --git a/repos/gems/recipes/pkg/cbe_check/README b/repos/gems/recipes/pkg/cbe_check/README deleted file mode 100644 index 67a67f5a3b..0000000000 --- a/repos/gems/recipes/pkg/cbe_check/README +++ /dev/null @@ -1 +0,0 @@ -Runtime for deploying cbe_check component from the depot. diff --git a/repos/gems/recipes/pkg/cbe_check/archives b/repos/gems/recipes/pkg/cbe_check/archives deleted file mode 100644 index 9427399ae6..0000000000 --- a/repos/gems/recipes/pkg/cbe_check/archives +++ /dev/null @@ -1,6 +0,0 @@ -_/src/cbe -_/src/libsparkcrypto -_/src/spark -_/src/init -_/src/vfs -_/src/vfs_block diff --git a/repos/gems/recipes/pkg/cbe_check/hash b/repos/gems/recipes/pkg/cbe_check/hash deleted file mode 100644 index 1b969353ce..0000000000 --- a/repos/gems/recipes/pkg/cbe_check/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-27 9877b3a22e52463bfbbe9758642759532503e89f diff --git a/repos/gems/recipes/pkg/cbe_check/runtime b/repos/gems/recipes/pkg/cbe_check/runtime deleted file mode 100644 index 324ffda1c2..0000000000 --- a/repos/gems/recipes/pkg/cbe_check/runtime +++ /dev/null @@ -1,63 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/cbe_demo/README b/repos/gems/recipes/pkg/cbe_demo/README deleted file mode 100644 index 63d57a8be9..0000000000 --- a/repos/gems/recipes/pkg/cbe_demo/README +++ /dev/null @@ -1 +0,0 @@ -CBE meta package diff --git a/repos/gems/recipes/pkg/cbe_demo/archives b/repos/gems/recipes/pkg/cbe_demo/archives deleted file mode 100644 index 11d3a277c5..0000000000 --- a/repos/gems/recipes/pkg/cbe_demo/archives +++ /dev/null @@ -1,10 +0,0 @@ -_/pkg/cbe_check -_/pkg/cbe_fs -_/pkg/cbe_ta_fs -_/pkg/cbe_init -_/pkg/cbe_shell -_/pkg/cbe_vbox5-nova -_/pkg/cbe_vfs -_/pkg/cbe_ta_vfs -_/pkg/cbe_vm_fs -_/pkg/download_coreplus diff --git a/repos/gems/recipes/pkg/cbe_demo/hash b/repos/gems/recipes/pkg/cbe_demo/hash deleted file mode 100644 index 8c90e79ff2..0000000000 --- a/repos/gems/recipes/pkg/cbe_demo/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-27 9e98d42c5faeda078acd475c3e85998087cababc diff --git a/repos/gems/recipes/pkg/cbe_fs/README b/repos/gems/recipes/pkg/cbe_fs/README deleted file mode 100644 index 468fa0442d..0000000000 --- a/repos/gems/recipes/pkg/cbe_fs/README +++ /dev/null @@ -1,2 +0,0 @@ -Runtime for deploying the chroot component configured for the CBE from -the depot. diff --git a/repos/gems/recipes/pkg/cbe_fs/archives b/repos/gems/recipes/pkg/cbe_fs/archives deleted file mode 100644 index 380ffb610d..0000000000 --- a/repos/gems/recipes/pkg/cbe_fs/archives +++ /dev/null @@ -1 +0,0 @@ -_/src/chroot diff --git a/repos/gems/recipes/pkg/cbe_fs/hash b/repos/gems/recipes/pkg/cbe_fs/hash deleted file mode 100644 index ccb102d465..0000000000 --- a/repos/gems/recipes/pkg/cbe_fs/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-25 4ce6ffd14a3bbfc7f59416b6e3c2bf4e92d034ab diff --git a/repos/gems/recipes/pkg/cbe_fs/runtime b/repos/gems/recipes/pkg/cbe_fs/runtime deleted file mode 100644 index f85e905eae..0000000000 --- a/repos/gems/recipes/pkg/cbe_fs/runtime +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/cbe_init/README b/repos/gems/recipes/pkg/cbe_init/README deleted file mode 100644 index 9420631387..0000000000 --- a/repos/gems/recipes/pkg/cbe_init/README +++ /dev/null @@ -1 +0,0 @@ -Runtime for deploying cbe_init component from the depot. diff --git a/repos/gems/recipes/pkg/cbe_init/archives b/repos/gems/recipes/pkg/cbe_init/archives deleted file mode 100644 index 9427399ae6..0000000000 --- a/repos/gems/recipes/pkg/cbe_init/archives +++ /dev/null @@ -1,6 +0,0 @@ -_/src/cbe -_/src/libsparkcrypto -_/src/spark -_/src/init -_/src/vfs -_/src/vfs_block diff --git a/repos/gems/recipes/pkg/cbe_init/hash b/repos/gems/recipes/pkg/cbe_init/hash deleted file mode 100644 index 3b3d3193a6..0000000000 --- a/repos/gems/recipes/pkg/cbe_init/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-27 8586c3f481575817c7822c2d82675a61d9797ae6 diff --git a/repos/gems/recipes/pkg/cbe_init/runtime b/repos/gems/recipes/pkg/cbe_init/runtime deleted file mode 100644 index f6ee91ac50..0000000000 --- a/repos/gems/recipes/pkg/cbe_init/runtime +++ /dev/null @@ -1,71 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/cbe_shell/README b/repos/gems/recipes/pkg/cbe_shell/README deleted file mode 100644 index 959626248e..0000000000 --- a/repos/gems/recipes/pkg/cbe_shell/README +++ /dev/null @@ -1 +0,0 @@ -Unix runtime that allows the user to interact with the CBE. diff --git a/repos/gems/recipes/pkg/cbe_shell/archives b/repos/gems/recipes/pkg/cbe_shell/archives deleted file mode 100644 index 3dbd837cd5..0000000000 --- a/repos/gems/recipes/pkg/cbe_shell/archives +++ /dev/null @@ -1,10 +0,0 @@ -_/src/bash-minimal -_/src/coreutils -_/src/libc -_/src/posix -_/src/ncurses -_/src/terminal -_/src/init -_/src/vfs -_/src/vfs_pipe -_/src/cached_fs_rom diff --git a/repos/gems/recipes/pkg/cbe_shell/hash b/repos/gems/recipes/pkg/cbe_shell/hash deleted file mode 100644 index fcab2fe017..0000000000 --- a/repos/gems/recipes/pkg/cbe_shell/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-27 68a36802cd97b17f22737a674c5f8c089a307314 diff --git a/repos/gems/recipes/pkg/cbe_shell/runtime b/repos/gems/recipes/pkg/cbe_shell/runtime deleted file mode 100644 index 67c5cb4f58..0000000000 --- a/repos/gems/recipes/pkg/cbe_shell/runtime +++ /dev/null @@ -1,126 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2018-01-01 00:01 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/cbe_ta_fs/README b/repos/gems/recipes/pkg/cbe_ta_fs/README deleted file mode 100644 index e68c3b7efb..0000000000 --- a/repos/gems/recipes/pkg/cbe_ta_fs/README +++ /dev/null @@ -1,2 +0,0 @@ -Runtime for deploying the chroot component configured for the CBE -trust-anchor from the depot. diff --git a/repos/gems/recipes/pkg/cbe_ta_fs/archives b/repos/gems/recipes/pkg/cbe_ta_fs/archives deleted file mode 100644 index 380ffb610d..0000000000 --- a/repos/gems/recipes/pkg/cbe_ta_fs/archives +++ /dev/null @@ -1 +0,0 @@ -_/src/chroot diff --git a/repos/gems/recipes/pkg/cbe_ta_fs/hash b/repos/gems/recipes/pkg/cbe_ta_fs/hash deleted file mode 100644 index 0aa69bacf0..0000000000 --- a/repos/gems/recipes/pkg/cbe_ta_fs/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-25 4580d6a6ca8f082447fdcdb7e3339687e3bbd013 diff --git a/repos/gems/recipes/pkg/cbe_ta_fs/runtime b/repos/gems/recipes/pkg/cbe_ta_fs/runtime deleted file mode 100644 index 484fbb8a07..0000000000 --- a/repos/gems/recipes/pkg/cbe_ta_fs/runtime +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/cbe_ta_vfs/README b/repos/gems/recipes/pkg/cbe_ta_vfs/README deleted file mode 100644 index 8a166ccc73..0000000000 --- a/repos/gems/recipes/pkg/cbe_ta_vfs/README +++ /dev/null @@ -1 +0,0 @@ -Runtime for deploying the CBE trust-anchor vfs component from the depot. diff --git a/repos/gems/recipes/pkg/cbe_ta_vfs/archives b/repos/gems/recipes/pkg/cbe_ta_vfs/archives deleted file mode 100644 index d9dc16e34b..0000000000 --- a/repos/gems/recipes/pkg/cbe_ta_vfs/archives +++ /dev/null @@ -1,2 +0,0 @@ -_/src/vfs -_/src/cbe diff --git a/repos/gems/recipes/pkg/cbe_ta_vfs/hash b/repos/gems/recipes/pkg/cbe_ta_vfs/hash deleted file mode 100644 index e45399804e..0000000000 --- a/repos/gems/recipes/pkg/cbe_ta_vfs/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-27 c13b59b705a0a8b56c1873bb0af3c2a7de6609ff diff --git a/repos/gems/recipes/pkg/cbe_ta_vfs/runtime b/repos/gems/recipes/pkg/cbe_ta_vfs/runtime deleted file mode 100644 index ac277ba040..0000000000 --- a/repos/gems/recipes/pkg/cbe_ta_vfs/runtime +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/cbe_vbox5-nova/README b/repos/gems/recipes/pkg/cbe_vbox5-nova/README deleted file mode 100644 index a8f0d16a46..0000000000 --- a/repos/gems/recipes/pkg/cbe_vbox5-nova/README +++ /dev/null @@ -1,2 +0,0 @@ - - VirtualBox runtime for using a VM with Block session disk access diff --git a/repos/gems/recipes/pkg/cbe_vbox5-nova/archives b/repos/gems/recipes/pkg/cbe_vbox5-nova/archives deleted file mode 100644 index 9e565f4c16..0000000000 --- a/repos/gems/recipes/pkg/cbe_vbox5-nova/archives +++ /dev/null @@ -1,9 +0,0 @@ -_/src/vbox5-nova -_/src/base-nova -_/src/libc -_/src/init -_/src/posix -_/src/zlib -_/src/libiconv -_/src/stdcxx -_/src/vfs diff --git a/repos/gems/recipes/pkg/cbe_vbox5-nova/hash b/repos/gems/recipes/pkg/cbe_vbox5-nova/hash deleted file mode 100644 index 249f4b4594..0000000000 --- a/repos/gems/recipes/pkg/cbe_vbox5-nova/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-27 51d4d436f52e3614ef2000125a647a6e9768dbce diff --git a/repos/gems/recipes/pkg/cbe_vbox5-nova/runtime b/repos/gems/recipes/pkg/cbe_vbox5-nova/runtime deleted file mode 100644 index 1f2c893130..0000000000 --- a/repos/gems/recipes/pkg/cbe_vbox5-nova/runtime +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/cbe_vfs/README b/repos/gems/recipes/pkg/cbe_vfs/README deleted file mode 100644 index 46f2c42b33..0000000000 --- a/repos/gems/recipes/pkg/cbe_vfs/README +++ /dev/null @@ -1,2 +0,0 @@ -Runtime for deploying the vfs component configured for the CBE from -the depot. diff --git a/repos/gems/recipes/pkg/cbe_vfs/archives b/repos/gems/recipes/pkg/cbe_vfs/archives deleted file mode 100644 index 0dc778fbe6..0000000000 --- a/repos/gems/recipes/pkg/cbe_vfs/archives +++ /dev/null @@ -1,4 +0,0 @@ -_/src/vfs -_/src/cbe -_/src/spark -_/src/openssl diff --git a/repos/gems/recipes/pkg/cbe_vfs/hash b/repos/gems/recipes/pkg/cbe_vfs/hash deleted file mode 100644 index 8da49b5d33..0000000000 --- a/repos/gems/recipes/pkg/cbe_vfs/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-27 53d46fa42938230c007f2c52e9cefdfb9d7d7748 diff --git a/repos/gems/recipes/pkg/cbe_vfs/runtime b/repos/gems/recipes/pkg/cbe_vfs/runtime deleted file mode 100644 index ae8c8a4683..0000000000 --- a/repos/gems/recipes/pkg/cbe_vfs/runtime +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/cbe_vm_fs/README b/repos/gems/recipes/pkg/cbe_vm_fs/README deleted file mode 100644 index e7ef7938d8..0000000000 --- a/repos/gems/recipes/pkg/cbe_vm_fs/README +++ /dev/null @@ -1,2 +0,0 @@ -Runtime for deploying the chroot component configured for the VM -running on top the CBE from the depot. diff --git a/repos/gems/recipes/pkg/cbe_vm_fs/archives b/repos/gems/recipes/pkg/cbe_vm_fs/archives deleted file mode 100644 index 380ffb610d..0000000000 --- a/repos/gems/recipes/pkg/cbe_vm_fs/archives +++ /dev/null @@ -1 +0,0 @@ -_/src/chroot diff --git a/repos/gems/recipes/pkg/cbe_vm_fs/hash b/repos/gems/recipes/pkg/cbe_vm_fs/hash deleted file mode 100644 index d44362d861..0000000000 --- a/repos/gems/recipes/pkg/cbe_vm_fs/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-25 6253f2ce75fb58e57dad9199e0f57ecc484792a2 diff --git a/repos/gems/recipes/pkg/cbe_vm_fs/runtime b/repos/gems/recipes/pkg/cbe_vm_fs/runtime deleted file mode 100644 index 71b6f40a51..0000000000 --- a/repos/gems/recipes/pkg/cbe_vm_fs/runtime +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/download_coreplus/README b/repos/gems/recipes/pkg/download_coreplus/README deleted file mode 100644 index 26aefef574..0000000000 --- a/repos/gems/recipes/pkg/download_coreplus/README +++ /dev/null @@ -1 +0,0 @@ -This package is used to prepare the assets for the TinyCore+ VM. diff --git a/repos/gems/recipes/pkg/download_coreplus/archives b/repos/gems/recipes/pkg/download_coreplus/archives deleted file mode 100644 index b729d6ac6e..0000000000 --- a/repos/gems/recipes/pkg/download_coreplus/archives +++ /dev/null @@ -1,18 +0,0 @@ -_/raw/download_coreplus -_/src/libc -_/src/vfs_lxip -_/src/bash-minimal -_/src/coreutils-minimal -_/src/curl -_/src/fetchurl -_/src/init -_/src/libssh -_/src/openssl -_/src/ncurses -_/src/posix -_/src/report_rom -_/src/terminal -_/src/terminal_log -_/src/vfs -_/src/zlib -_/src/cached_fs_rom diff --git a/repos/gems/recipes/pkg/download_coreplus/hash b/repos/gems/recipes/pkg/download_coreplus/hash deleted file mode 100644 index 2c840d1352..0000000000 --- a/repos/gems/recipes/pkg/download_coreplus/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-27 c73cf6ceef8aad65bfac745611188efa1f560c61 diff --git a/repos/gems/recipes/pkg/download_coreplus/runtime b/repos/gems/recipes/pkg/download_coreplus/runtime deleted file mode 100644 index 6d40087146..0000000000 --- a/repos/gems/recipes/pkg/download_coreplus/runtime +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/gems/recipes/pkg/file_vault/archives b/repos/gems/recipes/pkg/file_vault/archives index f29ca16179..bdc56dbaff 100644 --- a/repos/gems/recipes/pkg/file_vault/archives +++ b/repos/gems/recipes/pkg/file_vault/archives @@ -4,9 +4,7 @@ _/src/libpng _/src/zlib _/src/fs_query _/src/menu_view -_/src/cbe -_/src/spark -_/src/libsparkcrypto +_/src/tresor _/src/vfs_block _/src/vfs_jitterentropy _/src/vfs diff --git a/repos/gems/recipes/pkg/file_vault/runtime b/repos/gems/recipes/pkg/file_vault/runtime index a6e0a1cdad..8f26701f7b 100644 --- a/repos/gems/recipes/pkg/file_vault/runtime +++ b/repos/gems/recipes/pkg/file_vault/runtime @@ -26,26 +26,22 @@ - - - - - - - + + + + + - - - + @@ -74,21 +70,21 @@ - + - - + + - + - + - - + + diff --git a/repos/gems/recipes/pkg/file_vault_config_report/README b/repos/gems/recipes/pkg/file_vault_config_report/README new file mode 100644 index 0000000000..a88de3a2e1 --- /dev/null +++ b/repos/gems/recipes/pkg/file_vault_config_report/README @@ -0,0 +1 @@ +See repos/gems/src/app/file_vault/README. diff --git a/repos/gems/recipes/pkg/file_vault_config_report/archives b/repos/gems/recipes/pkg/file_vault_config_report/archives new file mode 100644 index 0000000000..a96843d2e0 --- /dev/null +++ b/repos/gems/recipes/pkg/file_vault_config_report/archives @@ -0,0 +1,15 @@ +_/src/init +_/src/libc +_/src/zlib +_/src/fs_query +_/src/tresor +_/src/vfs_block +_/src/vfs_jitterentropy +_/src/vfs +_/src/openssl +_/src/fs_tool +_/src/fs_utils +_/src/posix +_/src/rump +_/src/sandbox +_/src/file_vault diff --git a/repos/gems/recipes/pkg/file_vault_config_report/hash b/repos/gems/recipes/pkg/file_vault_config_report/hash new file mode 100644 index 0000000000..993f5d0456 --- /dev/null +++ b/repos/gems/recipes/pkg/file_vault_config_report/hash @@ -0,0 +1 @@ +2023-03-31-f e133ec19fdfb9ab03e5aa985db926ff807ca1505 diff --git a/repos/gems/recipes/pkg/file_vault_config_report/runtime b/repos/gems/recipes/pkg/file_vault_config_report/runtime new file mode 100644 index 0000000000..e69c1a947f --- /dev/null +++ b/repos/gems/recipes/pkg/file_vault_config_report/runtime @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/repos/gems/recipes/pkg/sculpt/README b/repos/gems/recipes/pkg/sculpt/README index e968583268..daf0eec14e 100644 --- a/repos/gems/recipes/pkg/sculpt/README +++ b/repos/gems/recipes/pkg/sculpt/README @@ -359,7 +359,7 @@ For inspiration, please follow the postings at :Encrypted file store: The file-vault package provides Sculpt users with an easy way to set - up and use an encrypted file store using Genode's custom CBE block + up and use an encrypted file store using Genode's custom Tresor block encrypter. [https://genodians.org/m-stein/2021-05-17-introducing-the-file-vault] @@ -1557,7 +1557,7 @@ Before building the packages, various ports of 3rd-party software need to be prepared. The following command prepares all of them at once: ! /tool/ports/prepare_port \ -! acpica ada-runtime bash cbe coreutils curl \ +! acpica ada-runtime bash tresor coreutils curl \ ! dde_bsd dde_ipxe dde_linux dde_rump e2fsprogs-lib \ ! expat freetype gnupg grub2 jitterentropy jpeg \ ! libarchive libc libdrm libgcrypt libiconv libnl libpng \ diff --git a/repos/gems/recipes/pkg/test-file_vault_config_report/README b/repos/gems/recipes/pkg/test-file_vault_config_report/README new file mode 100644 index 0000000000..15d76d5aef --- /dev/null +++ b/repos/gems/recipes/pkg/test-file_vault_config_report/README @@ -0,0 +1 @@ +Test for the fs_tool component diff --git a/repos/gems/recipes/pkg/test-file_vault_config_report/archives b/repos/gems/recipes/pkg/test-file_vault_config_report/archives new file mode 100644 index 0000000000..aee3408e2c --- /dev/null +++ b/repos/gems/recipes/pkg/test-file_vault_config_report/archives @@ -0,0 +1,4 @@ +_/pkg/file_vault_config_report +_/src/report_rom +_/src/dynamic_rom +_/src/vfs diff --git a/repos/gems/recipes/pkg/test-file_vault_config_report/hash b/repos/gems/recipes/pkg/test-file_vault_config_report/hash new file mode 100644 index 0000000000..a60b9ca0ef --- /dev/null +++ b/repos/gems/recipes/pkg/test-file_vault_config_report/hash @@ -0,0 +1 @@ +2023-03-31-j 57b14d73d7dfb8a25d18394bc2119bfd1ea07844 diff --git a/repos/gems/recipes/pkg/test-file_vault_config_report/runtime b/repos/gems/recipes/pkg/test-file_vault_config_report/runtime new file mode 100644 index 0000000000..d0f0de6a70 --- /dev/null +++ b/repos/gems/recipes/pkg/test-file_vault_config_report/runtime @@ -0,0 +1,232 @@ + + + + + + + + + + <ui_report version="step_*" state="uninitialized"/>* + <ui_report version="step_*" state="initializing"/>* + <ui_report version="step_*" state="unlocked"/>* + <ui_report version="step_*" state="locking"/>* + <ui_report version="step_*" state="locked"/>* + <ui_report version="step_*" state="unlocking"/>* + <ui_report version="step_*" state="unlocked"/>* + <ui_report version="step_*" state="locking"/>* + <ui_report version="step_*" state="locked"/>* + <ui_report version="step_*" state="unlocking"/>* + <ui_report version="step_*" state="locked"/>* + <ui_report version="step_*" state="unlocking"/>* + <ui_report version="step_*" state="unlocked"/>* + <ui_report version="step_*" state="locking"/>* + <ui_report version="step_*" state="locked"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + label="ui_report" + + + + + + + + + + + + + + + + + + + diff --git a/repos/gems/recipes/raw/download_coreplus/disk0.vmdk b/repos/gems/recipes/raw/download_coreplus/disk0.vmdk index a01b0f261b..857e34986a 100644 --- a/repos/gems/recipes/raw/download_coreplus/disk0.vmdk +++ b/repos/gems/recipes/raw/download_coreplus/disk0.vmdk @@ -5,7 +5,7 @@ parentCID=ffffffff createType="fullDevice" # Extent description -RW 2097152 FLAT "/dev/cbe/data" 0 +RW 2097152 FLAT "/dev/tresor/data" 0 # The disk Data Base #DDB diff --git a/repos/gems/recipes/src/cbe/content.mk b/repos/gems/recipes/src/cbe/content.mk deleted file mode 100644 index c5272afb2f..0000000000 --- a/repos/gems/recipes/src/cbe/content.mk +++ /dev/null @@ -1,70 +0,0 @@ -BUILD_LIBS := \ - cbe_cxx \ - cbe_init_cxx \ - cbe_dump_cxx \ - cbe_check_cxx - -MIRROR_FROM_CBE_DIR := \ - src/lib/cbe \ - src/lib/cbe_common \ - src/lib/cbe_cxx \ - src/lib/cbe_cxx_common \ - src/lib/cbe_init \ - src/lib/cbe_init_cxx \ - src/lib/cbe_dump \ - src/lib/cbe_dump_cxx \ - src/lib/cbe_check \ - src/lib/cbe_check_cxx \ - src/lib/sha256_4k - -MIRROR_FROM_REP_DIR := \ - lib/import/import-cbe.mk \ - lib/import/import-cbe_common.mk \ - lib/import/import-cbe_init.mk \ - lib/import/import-cbe_dump.mk \ - lib/import/import-cbe_check.mk \ - lib/import/import-sha256_4k.mk \ - lib/mk/spec/x86_64/cbe.mk \ - lib/mk/spec/x86_64/cbe_common.mk \ - lib/mk/spec/x86_64/cbe_cxx.mk \ - lib/mk/spec/x86_64/cbe_cxx_common.mk \ - lib/mk/spec/x86_64/cbe_init.mk \ - lib/mk/spec/x86_64/cbe_init_cxx.mk \ - lib/mk/spec/x86_64/cbe_dump.mk \ - lib/mk/spec/x86_64/cbe_dump_cxx.mk \ - lib/mk/spec/x86_64/cbe_check.mk \ - lib/mk/spec/x86_64/cbe_check_cxx.mk \ - lib/mk/spec/x86_64/vfs_cbe.mk \ - lib/mk/spec/x86_64/vfs_cbe_crypto_aes_cbc.mk \ - lib/mk/spec/x86_64/vfs_cbe_crypto_memcopy.mk \ - lib/mk/spec/x86_64/vfs_cbe_trust_anchor.mk \ - lib/mk/generate_ada_main_pkg.inc \ - lib/mk/sha256_4k.mk \ - lib/symbols/cbe_check_cxx \ - lib/symbols/cbe_dump_cxx \ - lib/symbols/cbe_init_cxx \ - src/lib/vfs/cbe \ - src/lib/vfs/cbe_crypto/vfs.cc \ - src/lib/vfs/cbe_crypto/aes_cbc \ - src/lib/vfs/cbe_crypto/memcopy \ - src/lib/vfs/cbe_trust_anchor \ - src/app/cbe_check \ - src/app/cbe_dump \ - src/app/cbe_init \ - src/app/cbe_init_trust_anchor \ - src/app/cbe_tester \ - include/cbe - -CBE_DIR := $(call port_dir,$(REP_DIR)/ports/cbe) - -content: $(MIRROR_FROM_REP_DIR) $(MIRROR_FROM_CBE_DIR) LICENSE - -$(MIRROR_FROM_REP_DIR): - $(mirror_from_rep_dir) - -$(MIRROR_FROM_CBE_DIR): - mkdir -p $(dir $@) - cp -r $(CBE_DIR)/$@ $(dir $@) - -LICENSE: - cp $(GENODE_DIR)/LICENSE $@ diff --git a/repos/gems/recipes/src/cbe/hash b/repos/gems/recipes/src/cbe/hash deleted file mode 100644 index 2a2bb4e8c6..0000000000 --- a/repos/gems/recipes/src/cbe/hash +++ /dev/null @@ -1 +0,0 @@ -2023-04-25 8a778936b989e4e142c9eab25e7bccb743962e36 diff --git a/repos/gems/recipes/src/file_vault/content.mk b/repos/gems/recipes/src/file_vault/content.mk index d1d6afb128..4c46012021 100644 --- a/repos/gems/recipes/src/file_vault/content.mk +++ b/repos/gems/recipes/src/file_vault/content.mk @@ -1,3 +1,13 @@ SRC_DIR := src/app/file_vault +MIRROR_FROM_REP_DIR := \ + src/lib/tresor/include/tresor/types.h \ + src/lib/tresor/include/tresor/math.h \ + src/lib/tresor/include/tresor/verbosity.h + +content: $(MIRROR_FROM_REP_DIR) + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) + include $(GENODE_DIR)/repos/base/recipes/src/content.inc diff --git a/repos/gems/recipes/src/file_vault/used_apis b/repos/gems/recipes/src/file_vault/used_apis index 92bbf66f96..9ddc7cf49e 100644 --- a/repos/gems/recipes/src/file_vault/used_apis +++ b/repos/gems/recipes/src/file_vault/used_apis @@ -1,6 +1,6 @@ base os -cbe +tresor vfs report_session gui_session diff --git a/repos/gems/recipes/src/tresor/content.mk b/repos/gems/recipes/src/tresor/content.mk new file mode 100644 index 0000000000..346d7c720d --- /dev/null +++ b/repos/gems/recipes/src/tresor/content.mk @@ -0,0 +1,24 @@ +MIRROR_FROM_REP_DIR := \ + src/lib/tresor \ + lib/import/import-tresor.mk \ + lib/mk/tresor.mk \ + lib/mk/vfs_tresor.mk \ + lib/mk/vfs_tresor_crypto_aes_cbc.mk \ + lib/mk/vfs_tresor_crypto_memcopy.mk \ + lib/mk/vfs_tresor_trust_anchor.mk \ + src/lib/vfs/tresor \ + src/lib/vfs/tresor_crypto/vfs.cc \ + src/lib/vfs/tresor_crypto/aes_cbc \ + src/lib/vfs/tresor_crypto/memcopy \ + src/lib/vfs/tresor_trust_anchor \ + src/app/tresor_init \ + src/app/tresor_init_trust_anchor \ + src/app/tresor_tester + +content: $(MIRROR_FROM_REP_DIR) LICENSE + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) + +LICENSE: + cp $(GENODE_DIR)/LICENSE $@ diff --git a/repos/gems/recipes/src/tresor/hash b/repos/gems/recipes/src/tresor/hash new file mode 100644 index 0000000000..c7e184b094 --- /dev/null +++ b/repos/gems/recipes/src/tresor/hash @@ -0,0 +1 @@ +2023-05-12 e4c840218c17700fb69b744c1adf42a80c816dc2 diff --git a/repos/gems/recipes/src/cbe/used_apis b/repos/gems/recipes/src/tresor/used_apis similarity index 71% rename from repos/gems/recipes/src/cbe/used_apis rename to repos/gems/recipes/src/tresor/used_apis index fcdc7f1050..02144b4883 100644 --- a/repos/gems/recipes/src/cbe/used_apis +++ b/repos/gems/recipes/src/tresor/used_apis @@ -2,9 +2,7 @@ aes_cbc_4k base block_session libc -libsparkcrypto openssl os so -spark vfs diff --git a/repos/gems/run/cbe_tester.run b/repos/gems/run/cbe_tester.run deleted file mode 100644 index d9baf910ea..0000000000 --- a/repos/gems/run/cbe_tester.run +++ /dev/null @@ -1,1068 +0,0 @@ - -assert_spec linux -assert_spec x86_64 - -exec rm -rf var/libcache/cbe -exec rm -rf var/libcache/cbe_cxx -exec rm -rf var/libcache/cbe_common -exec rm -rf var/libcache/cbe_common_cxx -exec rm -rf var/libcache/cbe_init -exec rm -rf var/libcache/cbe_init_cxx -exec rm -rf var/libcache/cbe_check -exec rm -rf var/libcache/cbe_check_cxx -exec rm -rf var/libcache/cbe_dump -exec rm -rf var/libcache/cbe_dump_cxx - -set dd [installed_command dd] - -proc cbe_image_name { } { - return "cbe_block.img" -} - -proc local_cbe_image { } { - return bin/[cbe_image_name] -} - -proc autopilot_cbe_image { } { - return /tmp/[cbe_image_name].[exec id -un] -} - -set image_size 1024 -if {[info exists ::env(CBE_IMAGE_SIZE)]} { - set image_size $::env(CBE_IMAGE_SIZE) -} - -proc cbe_image_size_mb { } { - global image_size - return $image_size -} - -proc cbe_vbd_size_mb { } { - return [expr [cbe_image_size_mb] / 2] -} - -proc cbe_ft_size_mb { } { - return [expr [cbe_image_size_mb] / 8] -} - -append build_components { - core - init - timer - server/vfs - app/cbe_tester - server/log_terminal - server/report_rom - server/lx_fs - server/lx_block - lib/vfs_cbe_crypto_aes_cbc - lib/vfs_cbe_trust_anchor - lib/vfs_import - lib/vfs_jitterentropy -} - -build $build_components - -create_boot_directory - -append config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} - -install_config $config - -exec rm -rf [local_cbe_image] -if { [get_cmd_switch --autopilot] } { - - exec rm -rf [autopilot_cbe_image] - catch { exec $dd if=/dev/urandom of=[autopilot_cbe_image] bs=1M count=[cbe_image_size_mb] } - exec ln -sf -T [autopilot_cbe_image] [local_cbe_image] - -} else { - - catch { exec $dd if=/dev/urandom of=[local_cbe_image] bs=1M count=[cbe_image_size_mb] } -} - -append boot_modules { - core - init - timer - cbe_tester - ld.lib.so spark.lib.so - libsparkcrypto.lib.so - cbe_cxx.lib.so - cbe_check_cxx.lib.so - cbe_dump_cxx.lib.so - cbe_init_cxx.lib.so - log_terminal - report_rom - lx_fs - vfs - lx_block - libc.lib.so - libcrypto.lib.so - vfs.lib.so - vfs_cbe_trust_anchor.lib.so - vfs_cbe_crypto_aes_cbc.lib.so - vfs_import.lib.so - vfs_jitterentropy.lib.so -} - -append boot_modules [cbe_image_name] - -build_boot_image $boot_modules - -append qemu_args " -nographic -m 1280 " - -run_genode_until "child \"test\" exited with exit value.*\n" 360 - -if { [get_cmd_switch --autopilot] } { - - exec rm -rf [local_cbe_image] - exec rm -rf [autopilot_cbe_image] -} - -grep_output {\[init\] child "test" exited with exit value} -compare_output_to {[init] child "test" exited with exit value 0} diff --git a/repos/gems/run/depot_autopilot.run b/repos/gems/run/depot_autopilot.run index 1a84d0a02e..0f2c1a0729 100644 --- a/repos/gems/run/depot_autopilot.run +++ b/repos/gems/run/depot_autopilot.run @@ -342,7 +342,7 @@ proc prepare_to_run_genode { } { - + @@ -658,6 +658,7 @@ set default_test_pkgs { test-entrypoint test-expat test-fault_detection + test-file_vault_config_report test-fs_packet test-fs_report test-fs_rom_update diff --git a/repos/gems/run/file_vault.inc b/repos/gems/run/file_vault.inc new file mode 100644 index 0000000000..3c61181884 --- /dev/null +++ b/repos/gems/run/file_vault.inc @@ -0,0 +1,463 @@ +proc ui_is { arg } { + + global ui + return [string equal $arg $ui ] +} + +build { app/file_vault } + +create_boot_directory + +append archives " + [depot_user]/src/[base_src] + [depot_user]/src/init + [depot_user]/src/libc + [depot_user]/src/zlib + [depot_user]/src/fs_query + [depot_user]/src/tresor + [depot_user]/src/vfs_block + [depot_user]/src/vfs_jitterentropy + [depot_user]/src/vfs + [depot_user]/src/openssl + [depot_user]/src/fs_tool + [depot_user]/src/fs_utils + [depot_user]/src/posix + [depot_user]/src/rump + [depot_user]/src/sandbox +" + +lappend_if [ui_is menu_view] archives [depot_user]/src/nitpicker +lappend_if [ui_is menu_view] archives [depot_user]/src/menu_view +lappend_if [ui_is menu_view] archives [depot_user]/src/libpng +lappend_if [ui_is menu_view] archives [depot_user]/pkg/fonts_fs +lappend_if [ui_is menu_view] archives [depot_user]/pkg/[drivers_interactive_pkg] + +lappend_if [ui_is config_and_report] archives [depot_user]/src/report_rom +lappend_if [ui_is config_and_report] archives [depot_user]/src/dynamic_rom + +lappend_if [have_board linux] archives [depot_user]/src/lx_fs + +import_from_depot $archives + +append config { + + + + + + + + + + + + + + + + + + + + + + + + +} +append_if [ui_is menu_view] config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +append_if [ui_is config_and_report] config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +if {[have_board linux]} { + + append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } + +} else { + + append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + } +} +append config { + + + + + + + + + + + +} +append_if [ui_is menu_view] config { + + + +} +append_if [ui_is config_and_report] config { + + + +} +append config { + + + + + + + + + + + + + + + + + +} + +install_config $config + +if {[have_board linux]} { + + if {[ui_is config_and_report]} { + + exec rm -rf bin/file_vault_dir + } + exec mkdir -p bin/file_vault_dir/data + exec mkdir -p bin/file_vault_dir/trust_anchor +} + +append boot_modules { + + file_vault + file_vault-sync_to_tresor_vfs_init + file_vault-truncate_file +} + +lappend_if [have_board linux] boot_modules file_vault_dir + +if {[ui_is menu_view]} { + + set fd [open [run_dir]/genode/focus w] + puts $fd " \"/>" + close $fd + + append qemu_args " -display gtk " + build_boot_image $boot_modules + run_genode_until forever +} + +if {[ui_is config_and_report]} { + + build_boot_image $boot_modules + + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + append exp_output {.*.*\n} + + append qemu_args " -display none " + run_genode_until $exp_output 120 +} diff --git a/repos/gems/run/file_vault.run b/repos/gems/run/file_vault.run index 6b1ea79f54..0116aa796f 100644 --- a/repos/gems/run/file_vault.run +++ b/repos/gems/run/file_vault.run @@ -1,300 +1,2 @@ -assert_spec x86_64 - -build { app/file_vault } - -create_boot_directory - -append archives " - [depot_user]/src/[base_src] - [depot_user]/pkg/[drivers_interactive_pkg] - [depot_user]/pkg/fonts_fs - [depot_user]/src/init - [depot_user]/src/nitpicker - [depot_user]/src/libc - [depot_user]/src/libpng - [depot_user]/src/zlib - [depot_user]/src/fs_query - [depot_user]/src/menu_view - [depot_user]/src/cbe - [depot_user]/src/spark - [depot_user]/src/libsparkcrypto - [depot_user]/src/vfs_block - [depot_user]/src/vfs_jitterentropy - [depot_user]/src/vfs - [depot_user]/src/openssl - [depot_user]/src/fs_tool - [depot_user]/src/fs_utils - [depot_user]/src/posix - [depot_user]/src/rump - [depot_user]/src/sandbox -" - -append_if [have_board linux] archives [depot_user]/src/lx_fs - -import_from_depot $archives - -append config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} -if {[have_board linux]} { - - append config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } - -} else { - - append config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - } -} -append config { - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -} - -install_config $config - -set fd [open [run_dir]/genode/focus w] -puts $fd " \"/>" -close $fd - -if {[have_board linux]} { - exec mkdir -p bin/file_vault_dir/data - exec mkdir -p bin/file_vault_dir/trust_anchor -} - -append boot_modules { - file_vault - file_vault-sync_to_cbe_vfs_init - file_vault-truncate_file -} - -append qemu_args " -display gtk " - -append_if [have_board linux] boot_modules file_vault_dir - -build_boot_image $boot_modules - -run_genode_until forever +set ui "menu_view" +source ${genode_dir}/repos/gems/run/file_vault.inc diff --git a/repos/gems/run/file_vault_config_report.run b/repos/gems/run/file_vault_config_report.run new file mode 100644 index 0000000000..675721dc29 --- /dev/null +++ b/repos/gems/run/file_vault_config_report.run @@ -0,0 +1,2 @@ +set ui "config_and_report" +source ${genode_dir}/repos/gems/run/file_vault.inc diff --git a/repos/gems/run/tresor_tester.run b/repos/gems/run/tresor_tester.run new file mode 100644 index 0000000000..cb2e41e1b9 --- /dev/null +++ b/repos/gems/run/tresor_tester.run @@ -0,0 +1,1078 @@ +set dd [installed_command dd] + +proc tresor_image_name { } { + return "tresor_block.img" +} + +proc local_tresor_image { } { + return bin/[tresor_image_name] +} + +proc autopilot_tresor_image { } { + return /tmp/[tresor_image_name].[exec id -un] +} + +set image_size 1024 +if {[info exists ::env(tresor_IMAGE_SIZE)]} { + set image_size $::env(tresor_IMAGE_SIZE) +} + +proc tresor_image_size_mb { } { + global image_size + return $image_size +} + +proc tresor_vbd_size_mb { } { + return [expr [tresor_image_size_mb] / 2] +} + +proc tresor_ft_size_mb { } { + return [expr [tresor_image_size_mb] / 8] +} + +proc benchmark_blk_count_base { } { + + if {[have_board virt_qemu_arm_v8a]} { + return 6400; + } else { + return 12800; + } +} + +append build_components { + core + init + timer + server/vfs + app/tresor_tester + server/log_terminal + server/report_rom + lib/vfs_tresor_crypto_aes_cbc + lib/vfs_tresor_trust_anchor + lib/vfs_import + lib/vfs_jitterentropy +} + +append_if [have_board linux] build_components { server/lx_fs } +append_if [have_board linux] build_components { server/lx_block } + +build $build_components + +create_boot_directory + +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} +if {[have_board linux]} { + + append config { + + + + + + + + + + } +} else { + + append config { + + + + + + + + + + + + + + + + + + + + + + + + + + } +} +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +if {[have_board linux]} { + + 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] } + } +} + +append boot_modules { + core + init + timer + tresor_tester + ld.lib.so + log_terminal + report_rom + vfs + libc.lib.so + libcrypto.lib.so + vfs.lib.so + vfs_tresor_trust_anchor.lib.so + vfs_tresor_crypto_aes_cbc.lib.so + vfs_import.lib.so + vfs_jitterentropy.lib.so +} + +append_if [have_board linux] boot_modules { lx_fs } +append_if [have_board linux] boot_modules [tresor_image_name] + +build_boot_image $boot_modules + +append qemu_args " -nographic -m 512 " + +run_genode_until "child \"test\" exited with exit value.*\n" 500 + +if { [get_cmd_switch --autopilot] } { + + exec rm -rf [local_tresor_image] + exec rm -rf [autopilot_tresor_image] +} + +grep_output {\[init\] child "test" exited with exit value} +compare_output_to {[init] child "test" exited with exit value 0} diff --git a/repos/gems/run/vfs_cbe.run b/repos/gems/run/vfs_tresor.run similarity index 83% rename from repos/gems/run/vfs_cbe.run rename to repos/gems/run/vfs_tresor.run index 4d44fdb21e..1b0b0d8bd2 100644 --- a/repos/gems/run/vfs_cbe.run +++ b/repos/gems/run/vfs_tresor.run @@ -1,22 +1,9 @@ assert_spec linux -if {[expr ![info exists ::env(CBE_KEEP)]]} { -exec rm -rf var/libcache/cbe -exec rm -rf var/libcache/cbe_cxx -exec rm -rf var/libcache/cbe_common -exec rm -rf var/libcache/cbe_common_cxx -exec rm -rf var/libcache/cbe_init -exec rm -rf var/libcache/cbe_init_cxx -exec rm -rf var/libcache/cbe_check -exec rm -rf var/libcache/cbe_check_cxx -exec rm -rf var/libcache/cbe_dump -exec rm -rf var/libcache/cbe_dump_cxx -} - create_boot_directory -proc cbe_image_file { } { - return "vfs_cbe_block.img" +proc tresor_image_file { } { + return "vfs_tresor_block.img" } set use_interactively [expr ![get_cmd_switch --autopilot]] @@ -34,18 +21,20 @@ build { timer init server/lx_fs - lib/vfs_cbe - lib/vfs_cbe_crypto_aes_cbc - lib/vfs_cbe_crypto_memcopy - lib/vfs_cbe_trust_anchor + lib/vfs_tresor + lib/vfs_tresor_crypto_aes_cbc + lib/vfs_tresor_crypto_memcopy + lib/vfs_tresor_trust_anchor lib/vfs_import + lib/vfs_jitterentropy lib/vfs_pipe test/vfs_stress test/libc server/log_terminal server/report_rom server/fs_rom - app/cbe_init_trust_anchor + app/tresor_init_trust_anchor + app/sequence } set config { @@ -81,9 +70,7 @@ set config { - } - -append_if $use_interactively config { + @@ -100,7 +87,9 @@ append_if $use_interactively config { - + } + +append_if $use_interactively config { @@ -132,7 +121,7 @@ append config { - + @@ -145,24 +134,25 @@ append config { - + - + - + - + @@ -193,19 +183,19 @@ append config { - + - + - @@ -266,18 +256,19 @@ append config { - + - + + - + @@ -290,7 +281,7 @@ append config { - + @@ -300,23 +291,21 @@ append config { install_config $config -set shell_script "run/vfs_cbe.sh" +set shell_script "run/vfs_tresor.sh" set repo "[repository_contains $shell_script]" exec cp $repo/$shell_script bin/ append boot_modules { lx_fs - cbe_init_trust_anchor - spark.lib.so - libsparkcrypto.lib.so - cbe_cxx.lib.so - vfs_cbe.lib.so - vfs_cbe_crypto_aes_cbc.lib.so - vfs_cbe_crypto_memcopy.lib.so - vfs_cbe_trust_anchor.lib.so - vfs_cbe.sh + tresor_init_trust_anchor + vfs_tresor.lib.so + vfs_tresor_crypto_aes_cbc.lib.so + vfs_tresor_crypto_memcopy.lib.so + vfs_tresor_trust_anchor.lib.so + vfs_tresor.sh vfs.lib.so vfs_import.lib.so + vfs_jitterentropy.lib.so vfs_pipe.lib.so posix.lib.so libc.lib.so @@ -334,7 +323,7 @@ append boot_modules { append boot_modules { encrypted_private_key superblock_hash } -append boot_modules [cbe_image_file] +append boot_modules [tresor_image_file] set fd [open [run_dir]/genode/focus w] puts $fd " \" domain=\"default\"/>" @@ -345,5 +334,5 @@ build_boot_image $boot_modules if {$use_interactively} { run_genode_until forever } else { - run_genode_until {.*--- Automated CBE testing finished.*} 1800 + run_genode_until {.*--- Automated Tresor testing finished.*} 1800 } diff --git a/repos/gems/run/vfs_cbe.sh b/repos/gems/run/vfs_tresor.sh similarity index 57% rename from repos/gems/run/vfs_cbe.sh rename to repos/gems/run/vfs_tresor.sh index e333fcb4d3..bfc4f955eb 100644 --- a/repos/gems/run/vfs_cbe.sh +++ b/repos/gems/run/vfs_tresor.sh @@ -1,6 +1,6 @@ #!/bin/bash -echo "--- Automated CBE testing ---" +echo "--- Automated Tresor testing ---" produce_pattern() { local pattern="$1" @@ -23,6 +23,12 @@ test_write_1() { dd bs=4096 count=1 if=$pattern_file of=$data_file seek=$offset 2>/dev/null || exit 1 } +test_read_seq_unaligned_512() { + local data_file="$1" + local length="$2" + dd bs=512 count=$((length / 512)) if=$data_file of=/dev/null +} + test_read_compare_1() { local data_file="$1" local offset=$2 @@ -50,125 +56,171 @@ test_read_compare_1() { } test_create_snapshot() { - local cbe_dir="$1" + local tresor_dir="$1" echo "Create snapshot" - echo true > $cbe_dir/control/create_snapshot + echo true > $tresor_dir/control/create_snapshot } test_list_snapshots() { - local cbe_dir="$1" + local tresor_dir="$1" - echo "List content of '$cbe_dir'" - ls -l $cbe_dir/snapshots + echo "List content of '$tresor_dir'" + ls -l $tresor_dir/snapshots } test_discard_snapshot() { - local cbe_dir="$1" + local tresor_dir="$1" local snap_id=$2 echo "Discard snapshot with id: $snap_id" - echo $snap_id > $cbe_dir/control/discard_snapshot + echo $snap_id > $tresor_dir/control/discard_snapshot } -test_rekey() { - local cbe_dir="$1" +test_rekey_start() { + local tresor_dir="$1" echo "Start rekeying" - echo on > $cbe_dir/control/rekey + echo on > $tresor_dir/control/rekey echo "Reykeying started" } test_vbd_extension() { - local cbe_dir="$1" + local tresor_dir="$1" local nr_of_phys_blocks="$2" echo "Start extending VBD" - echo tree=vbd, blocks=$nr_of_phys_blocks > $cbe_dir/control/extend + echo tree=vbd, blocks=$nr_of_phys_blocks > $tresor_dir/control/extend echo "VBD extension started" } test_ft_extension() { - local cbe_dir="$1" + local tresor_dir="$1" local nr_of_phys_blocks="$2" echo "Start extending FT" - echo tree=ft, blocks=$nr_of_phys_blocks > $cbe_dir/control/extend + echo tree=ft, blocks=$nr_of_phys_blocks > $tresor_dir/control/extend echo "FT extension started" } test_rekey_state() { - local cbe_dir="$1" - local state="$(< $cbe_dir/control/rekey)" + local tresor_dir="$1" + local state="$(< $tresor_dir/control/rekey)" + local progress="$(< $tresor_dir/control/rekey_progress)" - echo "Rekeying state: $state" + local result="unknown" + case "$progress" in + *at*) + result="$progress" + ;; + *idle*) + result="done" + ;; + esac + + echo "Rekeying state: $state progress: $result" } -test_rekey_state() { - local cbe_dir="$1" - local state="$(< $cbe_dir/control/rekey)" +test_rekey() { + local tresor_dir="$1" - echo "Rekeying state: $state" + test_rekey_start "$tresor_dir" + + wait_for_rekeying "$tresor_dir" "yes" } wait_for_rekeying() { - local cbe_dir="$1" + local tresor_dir="$1" + local verbose="$2" + local result="unknown" echo "Wait for rekeying to finish..." while : ; do - local file_content="$(< $cbe_dir/control/rekey)" - local state="${file_content:0:4}" - if [ "$state" = "idle" ]; then - local result="${file_content:5}" - echo "Reykeying done: $result" - break; + local done=0 + local file_content="$(< $tresor_dir/control/rekey_progress)" + # XXX remove later + echo "file_content: ${file_content}" + case "$file_content" in + *at*) + if [ "$verbose" = "yes" ]; then + echo "Rekeying: $file_content" + fi + ;; + *idle*) + done=1; + ;; + esac + if [ $done -gt 0 ]; then + break fi - sleep 2 done + echo "Rekeying done" } wait_for_vbd_extension() { - local cbe_dir="$1" + local tresor_dir="$1" echo "Wait for VBD extension to finish..." while : ; do - local file_content="$(< $cbe_dir/control/extend)" - local state="${file_content:0:4}" - if [ "$state" = "idle" ]; then - local result="${file_content:5}" - echo "VBD extension done: $result" - break; + local done=0 + local file_content="$(< $tresor_dir/control/extend_progress)" + # XXX remove later + echo "file_content: ${file_content}" + case "$file_content" in + *at*) + if [ "$verbose" = "yes" ]; then + echo "Extending VBD: $file_content" + fi + ;; + *idle*) + done=1; + ;; + esac + if [ $done -gt 0 ]; then + break fi - sleep 2 done + echo "VBD extension done" } wait_for_ft_extension() { - local cbe_dir="$1" + local tresor_dir="$1" echo "Wait for FT extension to finish..." while : ; do - local file_content="$(< $cbe_dir/control/extend)" - local state="${file_content:0:4}" - if [ "$state" = "idle" ]; then - local result="${file_content:5}" - echo "VBD extension done: $result" - break; + local done=0 + local file_content="$(< $tresor_dir/control/extend_progress)" + # XXX remove later + echo "file_content: ${file_content}" + case "$file_content" in + *at*) + if [ "$verbose" = "yes" ]; then + echo "Extending FT: $file_content" + fi + ;; + *idle*) + done=1; + ;; + esac + if [ $done -gt 0 ]; then + break fi - sleep 2 done + echo "FT extension done" } main() { - local cbe_dir="/dev/cbe" - local data_file="$cbe_dir/current/data" + local tresor_dir="/dev/tresor" + local data_file="$tresor_dir/current/data" - ls -l $cbe_dir + 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 @@ -176,7 +228,7 @@ main() { test_write_1 "$data_file" "63" test_write_1 "$data_file" "333" - test_vbd_extension "$cbe_dir" "1000" + 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" @@ -184,13 +236,13 @@ main() { 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 "$cbe_dir" + 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 "$cbe_dir" "1000" + #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" @@ -198,7 +250,7 @@ main() { 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 "$cbe_dir" + #wait_for_ft_extension "$tresor_dir" test_write_1 "$data_file" "0" test_write_1 "$data_file" "8" @@ -211,25 +263,27 @@ main() { test_read_compare_1 "$data_file" "16" test_read_compare_1 "$data_file" "490" - test_rekey "$cbe_dir" + #test_rekey "$tresor_dir" + + test_rekey_start "$tresor_dir" test_write_1 "$data_file" "0" - test_rekey_state "$cbe_dir" + test_rekey_state "$tresor_dir" test_read_compare_1 "$data_file" "490" - test_rekey_state "$cbe_dir" + test_rekey_state "$tresor_dir" test_write_1 "$data_file" "16" - test_rekey_state "$cbe_dir" + test_rekey_state "$tresor_dir" test_read_compare_1 "$data_file" "468" - test_rekey_state "$cbe_dir" + test_rekey_state "$tresor_dir" test_read_compare_1 "$data_file" "8" - test_rekey_state "$cbe_dir" + test_rekey_state "$tresor_dir" test_read_compare_1 "$data_file" "16" - test_rekey_state "$cbe_dir" + 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 "$cbe_dir" + wait_for_rekeying "$tresor_dir" "yes" echo "--> Run $i done" @@ -243,7 +297,7 @@ main() { test_read_compare_1 "$data_file" "16" echo "--> Read/Compare test done" - echo "--- Automated CBE testing finished, shell is yours ---" + echo "--- Automated Tresor testing finished, shell is yours ---" } main "$@" diff --git a/repos/gems/run/vfs_cbe_init.run b/repos/gems/run/vfs_tresor_init.run similarity index 62% rename from repos/gems/run/vfs_cbe_init.run rename to repos/gems/run/vfs_tresor_init.run index c126dab84e..67cf44e1f0 100644 --- a/repos/gems/run/vfs_cbe_init.run +++ b/repos/gems/run/vfs_tresor_init.run @@ -1,25 +1,12 @@ assert_spec linux -if {[expr ![info exists ::env(CBE_KEEP)]]} { -exec rm -rf var/libcache/cbe -exec rm -rf var/libcache/cbe_cxx -exec rm -rf var/libcache/cbe_common -exec rm -rf var/libcache/cbe_common_cxx -exec rm -rf var/libcache/cbe_init -exec rm -rf var/libcache/cbe_init_cxx -exec rm -rf var/libcache/cbe_check -exec rm -rf var/libcache/cbe_check_cxx -exec rm -rf var/libcache/cbe_dump -exec rm -rf var/libcache/cbe_dump_cxx -} - -proc cbe_image_file { } { - return "vfs_cbe_block.img" +proc tresor_image_file { } { + return "vfs_tresor_block.img" } set image_size 32 -proc cbe_image_size_mb { } { +proc tresor_image_size_mb { } { global image_size return $image_size } @@ -31,9 +18,10 @@ append build_components { server/vfs app/sequence - app/cbe_init_trust_anchor - app/cbe_init - lib/vfs_cbe_trust_anchor + 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 @@ -66,12 +54,6 @@ append config { - - - - - - @@ -92,12 +74,12 @@ append config { - - + @@ -105,12 +87,12 @@ append config { - + - + @@ -121,16 +103,22 @@ append config { - + - + + + + + + + + - - + @@ -156,24 +144,33 @@ append config { install_config $config -exec rm -rf bin/[cbe_image_file] -exec truncate -s [cbe_image_size_mb]M bin/[cbe_image_file] +exec rm -rf bin/[tresor_image_file] +exec truncate -s [tresor_image_size_mb]M bin/[tresor_image_file] append boot_modules { - core init timer lx_block lx_fs sequence - vfs vfs.lib.so vfs_jitterentropy.lib.so - ld.lib.so spark.lib.so libsparkcrypto.lib.so libcrypto.lib.so libc.lib.so - - cbe_init_trust_anchor - cbe_init cbe_init_cxx.lib.so - vfs_cbe_trust_anchor.lib.so + core + init + timer + lx_block + lx_fs + sequence + vfs + vfs.lib.so + vfs_jitterentropy.lib.so + ld.lib.so + libcrypto.lib.so + libc.lib.so + tresor_init_trust_anchor + tresor_init + vfs_tresor_trust_anchor.lib.so + vfs_tresor_crypto_aes_cbc.lib.so } -append boot_modules [cbe_image_file] +append boot_modules [tresor_image_file] build_boot_image $boot_modules -run_genode_until {.*child "initialize_cbe" exited with exit value 0.*\n} 240 +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/cbe_check/target.mk b/repos/gems/src/app/cbe_check/target.mk deleted file mode 100644 index 5cff2a6914..0000000000 --- a/repos/gems/src/app/cbe_check/target.mk +++ /dev/null @@ -1,9 +0,0 @@ -REQUIRES += x86_64 - -TARGET := cbe_check - -SRC_CC += main.cc -INC_DIR += $(PRG_DIR) -LIBS += base cbe_check_cxx - -CONFIG_XSD = config.xsd diff --git a/repos/gems/src/app/cbe_dump/README b/repos/gems/src/app/cbe_dump/README deleted file mode 100644 index 9abf54e2b1..0000000000 --- a/repos/gems/src/app/cbe_dump/README +++ /dev/null @@ -1,72 +0,0 @@ -The cbe_dump component dumps the meta-data of a CBE device (virtual block -device, free tree and meta tree) according to the configured parameters. -On success, the component exits with exit value 0, otherwise with exit -value -1. - - -Configuration -~~~~~~~~~~~~~ - -This is an example configuration of the component that will dump the -last valid superblock and the its last valid snapshot: - -! -! -! - -This is a short description of the tags and attributes: - -:config.free_tree: - Dump free tree nodes. - -:config.meta_tree: - Dump meta tree nodes. - -:config.hashes: - Show hashes in all tree dumps. - -:config.max_superblocks: - Max number of superblocks to dump. - -:config.max_snapshots: - Max number of snapshot to dump per superblock. - -:config.unused_nodes: - Show unused nodes in all tree dumps. - -:config.vbd: - Dump virtual block device tree nodes. - -:config.vbd_pba_filter: - Only show sub-tree where the PBA matches. - -:config.vbd_pba_filter_enabled: - Enable PBA filter. - -:config.vbd_vba_filter: - Only show sub-tree where the VBA matches. - -:config.vbd_vba_filter_enabled: - Enable VBA filter. - - -Sessions -~~~~~~~~ - -This is an overview of the sessions required and provided by the -component apart from the environment sessions: - -* Requires one Block session. - - -Examples -~~~~~~~~ - -An example of how to use the cbe_dump component can be found in the test script -'cbe/run/cbe_dump.run'. diff --git a/repos/gems/src/app/cbe_dump/config.xsd b/repos/gems/src/app/cbe_dump/config.xsd deleted file mode 100644 index 5740405e35..0000000000 --- a/repos/gems/src/app/cbe_dump/config.xsd +++ /dev/null @@ -1,44 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/repos/gems/src/app/cbe_dump/main.cc b/repos/gems/src/app/cbe_dump/main.cc deleted file mode 100644 index 7ce1722ebf..0000000000 --- a/repos/gems/src/app/cbe_dump/main.cc +++ /dev/null @@ -1,231 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include - -/* CBE-dump includes */ -#include - -using namespace Genode; - - -class Main -{ - private: - - enum { TX_BUF_SIZE = Block::Session::TX_QUEUE_SIZE * Cbe::BLOCK_SIZE }; - - Env &_env; - Heap _heap { _env.ram(), _env.rm() }; - Allocator_avl _blk_alloc { &_heap }; - Block::Connection<> _blk { _env, &_blk_alloc, TX_BUF_SIZE }; - Signal_handler
_blk_handler { _env.ep(), *this, &Main::_execute }; - Cbe::Request _blk_req { }; - Cbe::Io_buffer _blk_buf { }; - Cbe_dump::Library _cbe_dump { }; - - Genode::size_t _blk_ratio { - Cbe::BLOCK_SIZE / _blk.info().block_size }; - - void _execute() - { - for (bool progress { true }; progress; ) { - - progress = false; - - _cbe_dump.execute(_blk_buf); - if (_cbe_dump.execute_progress()) { - progress = true; - } - - Cbe::Request const req { - _cbe_dump.peek_completed_client_request() }; - - if (req.valid()) { - _cbe_dump.drop_completed_client_request(req); - if (req.success()) { - _env.parent().exit(0); - } else { - error("request was not successful");; - _env.parent().exit(-1); - } - } - - struct Invalid_io_request : Exception { }; - - while (_blk.tx()->ready_to_submit()) { - - Cbe::Io_buffer::Index data_index { 0 }; - Cbe::Request request { }; - _cbe_dump.has_io_request(request, data_index); - - if (!request.valid()) { - break; - } - if (_blk_req.valid()) { - break; - } - try { - request.tag(data_index.value); - Block::Packet_descriptor::Opcode op; - switch (request.operation()) { - case Cbe::Request::Operation::READ: - op = Block::Packet_descriptor::READ; - break; - case Cbe::Request::Operation::WRITE: - op = Block::Packet_descriptor::WRITE; - break; - default: - throw Invalid_io_request(); - } - Block::Packet_descriptor packet { - _blk.alloc_packet(Cbe::BLOCK_SIZE), op, - request.block_number() * _blk_ratio, - request.count() * _blk_ratio }; - - if (request.operation() == Cbe::Request::Operation::WRITE) { - *reinterpret_cast( - _blk.tx()->packet_content(packet)) = - _blk_buf.item(data_index); - } - _blk.tx()->try_submit_packet(packet); - _blk_req = request; - _cbe_dump.io_request_in_progress(data_index); - progress = true; - } - catch (Block::Session::Tx::Source::Packet_alloc_failed) { - break; - } - } - - while (_blk.tx()->ack_avail()) { - - Block::Packet_descriptor packet = - _blk.tx()->try_get_acked_packet(); - - if (!_blk_req.valid()) { - break; - } - - bool const read = - packet.operation() == Block::Packet_descriptor::READ; - - bool const write = - packet.operation() == Block::Packet_descriptor::WRITE; - - bool const op_match = - (read && _blk_req.read()) || - (write && _blk_req.write()); - - bool const bn_match = - packet.block_number() / _blk_ratio == _blk_req.block_number(); - - if (!bn_match || !op_match) { - break; - } - - _blk_req.success(packet.succeeded()); - - Cbe::Io_buffer::Index const data_index { _blk_req.tag() }; - bool const success { _blk_req.success() }; - - if (read && success) { - _blk_buf.item(data_index) = - *reinterpret_cast( - _blk.tx()->packet_content(packet)); - } - _cbe_dump.io_request_completed(data_index, success); - _blk.tx()->release_packet(packet); - _blk_req = Cbe::Request { }; - progress = true; - } - } - _blk.tx()->wakeup(); - } - - public: - - Main(Env &env) - : - _env { env } - { - if (_blk_ratio == 0) { - error("backend block size not supported"); - _env.parent().exit(-1); - return; - } - - if (!_cbe_dump.client_request_acceptable()) { - error("failed to submit request"); - _env.parent().exit(-1); - } - - Attached_rom_dataspace config_rom { _env, "config" }; - - try { - Xml_node const &config { - config_rom.xml().sub_node("dump") }; - - Cbe_dump::Configuration const cfg { config }; - - _cbe_dump.submit_client_request( - Cbe::Request { Cbe::Request::Operation::READ, - false, 0, 0, 0, 0, 0 }, - cfg); - } - catch (Xml_node::Nonexistent_sub_node) { - error("missing 'dump' config node"); - _env.parent().exit(1); - return; - } - - _blk.tx_channel()->sigh_ack_avail(_blk_handler); - _blk.tx_channel()->sigh_ready_to_submit(_blk_handler); - - _execute(); - } - - ~Main() - { - _blk.tx_channel()->sigh_ack_avail(Signal_context_capability()); - _blk.tx_channel()->sigh_ready_to_submit(Signal_context_capability()); - } -}; - - -extern "C" int memcmp(const void *p0, const void *p1, Genode::size_t size) -{ - return Genode::memcmp(p0, p1, size); -} - - -extern "C" void adainit(); - - -void Component::construct(Genode::Env &env) -{ - env.exec_static_constructors(); - Timer::Connection timer { env }; - - Cbe::assert_valid_object_size(); - - cbe_dump_cxx_init(); - - static Main main(env); -} diff --git a/repos/gems/src/app/cbe_init/main.cc b/repos/gems/src/app/cbe_init/main.cc deleted file mode 100644 index f707fae6f9..0000000000 --- a/repos/gems/src/app/cbe_init/main.cc +++ /dev/null @@ -1,379 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* CBE includes */ -#include -#include -#include - -enum { VERBOSE = 0 }; - -using namespace Genode; - -class Main : Vfs::Env::User -{ - private: - - enum { TX_BUF_SIZE = Block::Session::TX_QUEUE_SIZE * Cbe::BLOCK_SIZE }; - - Env &_env; - Heap _heap { _env.ram(), _env.rm() }; - - Attached_rom_dataspace _config_rom { _env, "config" }; - - Allocator_avl _blk_alloc { &_heap }; - Block::Connection<> _blk { _env, &_blk_alloc, TX_BUF_SIZE }; - Signal_handler
_blk_handler { _env.ep(), *this, &Main::_execute }; - Cbe::Request _blk_req { }; - Cbe::Io_buffer _blk_buf { }; - Cbe_init::Library _cbe_init { }; - - Genode::size_t _blk_ratio { - Cbe::BLOCK_SIZE / _blk.info().block_size }; - - Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; - Vfs::File_system &_vfs { _vfs_env.root_dir() }; - - /** - * Vfs::Env::User interface - */ - void wakeup_vfs_user() override { _blk_handler.local_submit(); } - - static Util::Trust_anchor_vfs::Path _config_ta_dir(Xml_node const &node) - { - using String_path = Genode::String<1024>; - String_path const path = - node.attribute_value("trust_anchor_dir", String_path()); - - if (!path.valid()) { - - error("missing mandatory 'trust_anchor_dir' config attribute"); - struct Missing_config_attribute { }; - throw Missing_config_attribute(); - } - - return Util::Trust_anchor_vfs::Path { path.string() }; - } - - Util::Trust_anchor_vfs _trust_anchor { - _vfs, _vfs_env.alloc(), _config_ta_dir(_config_rom.xml()) }; - - bool _execute_trust_anchor() - { - bool progress = _trust_anchor.execute(); - - using Op = Cbe::Trust_anchor_request::Operation; - - while (true) { - - Cbe::Trust_anchor_request const request = - _cbe_init.peek_generated_ta_request(); - - if (!request.valid()) { break; } - if (!_trust_anchor.request_acceptable()) { break; } - - switch (request.operation()) { - case Op::CREATE_KEY: - _trust_anchor.submit_create_key_request(request); - break; - case Op::SECURE_SUPERBLOCK: - { - Cbe::Hash const sb_hash = _cbe_init.peek_generated_ta_sb_hash(request); - _trust_anchor.submit_secure_superblock_request(request, sb_hash); - break; - } - case Op::ENCRYPT_KEY: - { - Cbe::Key_plaintext_value const pk = - _cbe_init.peek_generated_ta_key_value_plaintext(request); - - _trust_anchor.submit_encrypt_key_request(request, pk); - break; - } - case Op::DECRYPT_KEY: - { - Cbe::Key_ciphertext_value const ck = - _cbe_init.peek_generated_ta_key_value_ciphertext(request); - - _trust_anchor.submit_decrypt_key_request(request, ck); - break; - } - case Op::LAST_SB_HASH: - break; - case Op::INITIALIZE: - class Bad_operation { }; - throw Bad_operation { }; - case Op::INVALID: - /* never reached */ - break; - } - _cbe_init.drop_generated_ta_request(request); - progress |= true; - } - - while (true) { - - Cbe::Trust_anchor_request const request = - _trust_anchor.peek_completed_request(); - - if (!request.valid()) { break; } - - switch (request.operation()) { - case Op::CREATE_KEY: - { - Cbe::Key_plaintext_value const pk = - _trust_anchor.peek_completed_key_value_plaintext(request); - - _cbe_init.mark_generated_ta_create_key_request_complete(request, pk); - break; - } - case Op::SECURE_SUPERBLOCK: - { - _cbe_init.mark_generated_ta_secure_sb_request_complete(request); - break; - } - case Op::ENCRYPT_KEY: - { - Cbe::Key_ciphertext_value const ck = - _trust_anchor.peek_completed_key_value_ciphertext(request); - - _cbe_init.mark_generated_ta_encrypt_key_request_complete(request, ck); - break; - } - case Op::DECRYPT_KEY: - { - Cbe::Key_plaintext_value const pk = - _trust_anchor.peek_completed_key_value_plaintext(request); - - _cbe_init.mark_generated_ta_decrypt_key_request_complete(request, pk); - break; - } - case Op::LAST_SB_HASH: - break; - case Op::INITIALIZE: - class Bad_operation { }; - throw Bad_operation { }; - case Op::INVALID: - /* never reached */ - break; - } - _trust_anchor.drop_completed_request(request); - progress |= true; - } - - return progress; - } - - void _execute() - { - for (bool progress { true }; progress; ) { - - progress = false; - - _cbe_init.execute(_blk_buf); - if (_cbe_init.execute_progress()) { - progress = true; - } - - Cbe::Request const req { - _cbe_init.peek_completed_client_request() }; - - if (req.valid()) { - _cbe_init.drop_completed_client_request(req); - if (req.success()) { - if (VERBOSE) { - log("CBE initialization finished"); - } - _env.parent().exit(0); - } else { - error("request was not successful");; - _env.parent().exit(-1); - } - } - - progress |= _execute_trust_anchor(); - - struct Invalid_io_request : Exception { }; - - while (_blk.tx()->ready_to_submit()) { - - Cbe::Io_buffer::Index data_index { 0 }; - Cbe::Request request { }; - _cbe_init.has_io_request(request, data_index); - - if (!request.valid()) { - break; - } - if (_blk_req.valid()) { - break; - } - try { - request.tag(data_index.value); - Block::Packet_descriptor::Opcode op; - switch (request.operation()) { - case Cbe::Request::Operation::READ: - op = Block::Packet_descriptor::READ; - break; - case Cbe::Request::Operation::WRITE: - op = Block::Packet_descriptor::WRITE; - break; - case Cbe::Request::Operation::SYNC: - op = Block::Packet_descriptor::SYNC; - break; - default: - throw Invalid_io_request(); - } - Block::Packet_descriptor packet { - _blk.alloc_packet(Cbe::BLOCK_SIZE), op, - request.block_number() * _blk_ratio, - request.count() * _blk_ratio }; - - if (request.operation() == Cbe::Request::Operation::WRITE) { - *reinterpret_cast( - _blk.tx()->packet_content(packet)) = - _blk_buf.item(data_index); - } - _blk.tx()->try_submit_packet(packet); - _blk_req = request; - _cbe_init.io_request_in_progress(data_index); - progress = true; - } - catch (Block::Session::Tx::Source::Packet_alloc_failed) { - break; - } - } - - while (_blk.tx()->ack_avail()) { - - Block::Packet_descriptor packet = - _blk.tx()->try_get_acked_packet(); - - if (!_blk_req.valid()) { - break; - } - - bool const read = - packet.operation() == Block::Packet_descriptor::READ; - - bool const write = - packet.operation() == Block::Packet_descriptor::WRITE; - - bool const sync = - packet.operation() == Block::Packet_descriptor::SYNC; - - bool const op_match = - (read && _blk_req.read()) || - (write && _blk_req.write()) || - (sync && _blk_req.sync()); - - bool const bn_match = - packet.block_number() / _blk_ratio == _blk_req.block_number(); - - if (!bn_match || !op_match) { - break; - } - - _blk_req.success(packet.succeeded()); - - Cbe::Io_buffer::Index const data_index { _blk_req.tag() }; - bool const success { _blk_req.success() }; - - if (read && success) { - _blk_buf.item(data_index) = - *reinterpret_cast( - _blk.tx()->packet_content(packet)); - } - _cbe_init.io_request_completed(data_index, success); - _blk.tx()->release_packet(packet); - _blk_req = Cbe::Request(); - progress = true; - } - } - _blk.tx()->wakeup(); - _vfs_env.io().commit(); - } - - public: - - Main(Env &env) : _env { env } - { - if (_blk_ratio == 0) { - error("backend block size not supported"); - _env.parent().exit(-1); - return; - } - - Xml_node const &config { _config_rom.xml() }; - try { - Cbe_init::Configuration const cfg { config }; - if (!_cbe_init.client_request_acceptable()) { - error("failed to submit request"); - _env.parent().exit(-1); - } - _cbe_init.submit_client_request( - Cbe::Request( - Cbe::Request::Operation::READ, - false, 0, 0, 0, 0, 0), - cfg.vbd_nr_of_lvls() - 1, - cfg.vbd_nr_of_children(), - cfg.vbd_nr_of_leafs(), - cfg.ft_nr_of_lvls() - 1, - cfg.ft_nr_of_children(), - cfg.ft_nr_of_leafs()); - - _blk.tx_channel()->sigh_ack_avail(_blk_handler); - _blk.tx_channel()->sigh_ready_to_submit(_blk_handler); - - _execute(); - } - catch (Cbe_init::Configuration::Invalid) { - error("bad configuration"); - _env.parent().exit(-1); - } - } - - ~Main() - { - _blk.tx_channel()->sigh_ack_avail(Signal_context_capability()); - _blk.tx_channel()->sigh_ready_to_submit(Signal_context_capability()); - } -}; - -extern "C" int memcmp(const void *p0, const void *p1, Genode::size_t size) -{ - return Genode::memcmp(p0, p1, size); -} - -extern "C" void adainit(); - -void Component::construct(Genode::Env &env) -{ - env.exec_static_constructors(); - - Cbe::assert_valid_object_size(); - - cbe_init_cxx_init(); - - static Main main(env); -} diff --git a/repos/gems/src/app/cbe_init/target.mk b/repos/gems/src/app/cbe_init/target.mk deleted file mode 100644 index 13efefc8e0..0000000000 --- a/repos/gems/src/app/cbe_init/target.mk +++ /dev/null @@ -1,9 +0,0 @@ -REQUIRES += x86_64 - -TARGET := cbe_init - -SRC_CC += main.cc -INC_DIR += $(PRG_DIR) -LIBS += base vfs cbe_init_cxx - -CONFIG_XSD = config.xsd diff --git a/repos/gems/src/app/cbe_init_trust_anchor/target.mk b/repos/gems/src/app/cbe_init_trust_anchor/target.mk deleted file mode 100644 index 96355216cc..0000000000 --- a/repos/gems/src/app/cbe_init_trust_anchor/target.mk +++ /dev/null @@ -1,8 +0,0 @@ -REQUIRES += x86_64 - -TARGET:= cbe_init_trust_anchor - -SRC_CC := component.cc -INC_DIR := $(PRG_DIR) - -LIBS := base vfs diff --git a/repos/gems/src/app/cbe_tester/README b/repos/gems/src/app/cbe_tester/README deleted file mode 100644 index f44ec33c2f..0000000000 --- a/repos/gems/src/app/cbe_tester/README +++ /dev/null @@ -1,35 +0,0 @@ - - ================================== - Reference manual of the CBE tester - ================================== - - Martin Stein - - - +--------------+ +----------+ - | Command Pool |<--->| Main | - +--------------+ | | - | | - +--------------+ | | - | CBE |<--->| | - +--------------+ | | - | | - +--------------+ | | - | CBE Init |<--->| | - +--------------+ | | - | | - +--------------+ | | - | CBE Dump |<--->| | - +--------------+ | | - | | - +--------------+ | | - | Block IO |<--->| | - +--------------+ | | - | | - +--------------+ | | - | Crypto |<--->| | - +--------------+ | | - | | - +--------------+ | | - | Trust Anchor |<--->| | - +--------------+ +----------+ diff --git a/repos/gems/src/app/cbe_tester/crypto.h b/repos/gems/src/app/cbe_tester/crypto.h deleted file mode 100644 index c3247581c7..0000000000 --- a/repos/gems/src/app/cbe_tester/crypto.h +++ /dev/null @@ -1,118 +0,0 @@ -/* - * \brief Implementation of the Crypto module API using the Crypto VFS API - * \author Martin Stein - * \date 2020-10-29 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE_TESTER__CRYPTO_H_ -#define _CBE_TESTER__CRYPTO_H_ - -/* CBE includes */ -#include - -/* CBE tester includes */ -#include - -class Crypto -{ - public: - - enum class Operation - { - INVALID, - DECRYPT_BLOCK, - ENCRYPT_BLOCK - }; - - enum class Result - { - SUCCEEDED, - FAILED, - RETRY_LATER - }; - - private: - - using Read_result = Vfs::File_io_service::Read_result; - using Open_result = Vfs::Directory_service::Open_result; - - struct Key_directory - { - Vfs::Vfs_handle *encrypt_handle { nullptr }; - Vfs::Vfs_handle *decrypt_handle { nullptr }; - Genode::uint32_t key_id { 0 }; - }; - - enum class Job_state - { - SUBMITTED, - OP_WRITTEN_TO_VFS_HANDLE, - READING_VFS_HANDLE_SUCCEEDED, - COMPLETE - }; - - struct Job - { - Cbe::Request request { }; - Vfs::Vfs_handle *handle { nullptr }; - Job_state state { Job_state::SUBMITTED }; - Operation op { Operation::INVALID }; - Cbe::Crypto_cipher_buffer::Index cipher_buf_idx { 0 }; - Cbe::Crypto_plain_buffer::Index plain_buf_idx { 0 }; - }; - - Vfs::Env &_env; - Genode::String<32> const _path; - Vfs::Vfs_handle &_add_key_handle; - Vfs::Vfs_handle &_remove_key_handle; - Key_directory _key_dirs[2] { { }, { } }; - Job _job { }; - - Key_directory &_get_unused_key_dir(); - - Key_directory &_lookup_key_dir(Genode::uint32_t key_id); - - void _execute_decrypt_block(Job &job, - Cbe::Crypto_plain_buffer &plain_buf, - Cbe::Crypto_cipher_buffer &cipher_buf, - bool &progress); - - void _execute_encrypt_block(Job &job, - Cbe::Crypto_plain_buffer &plain_buf, - Cbe::Crypto_cipher_buffer &cipher_buf, - bool &progress); - - public: - - Crypto(Vfs::Env &env, Genode::Xml_node const &crypto); - - bool request_acceptable() const; - - Result add_key(Cbe::Key const &key); - - Result remove_key(Cbe::Key::Id key_id); - - void submit_request(Cbe::Request const &request, - Operation op, - Cbe::Crypto_plain_buffer::Index plain_buf_idx, - Cbe::Crypto_cipher_buffer::Index cipher_buf_idx); - - Cbe::Request peek_completed_encryption_request() const; - - Cbe::Request peek_completed_decryption_request() const; - - void drop_completed_request(); - - void execute(Cbe::Crypto_plain_buffer &plain_buf, - Cbe::Crypto_cipher_buffer &cipher_buf, - bool &progress); -}; - -#endif /* _CBE_TESTER__CRYPTO_H_ */ diff --git a/repos/gems/src/app/cbe_tester/main.cc b/repos/gems/src/app/cbe_tester/main.cc deleted file mode 100644 index e6b5069827..0000000000 --- a/repos/gems/src/app/cbe_tester/main.cc +++ /dev/null @@ -1,2551 +0,0 @@ -/* - * \brief Tool for running tests and benchmarks on the CBE - * \author Martin Stein - * \date 2020-08-26 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* Genode includes */ -#include -#include -#include -#include -#include -#include - -/* CBE includes */ -#include -#include -#include -#include -#include -#include - -/* CBE tester includes */ -#include -#include -#include - -using namespace Genode; -using namespace Cbe; -using namespace Vfs; - - -enum class Module_type : uint8_t -{ - CBE_INIT, - CBE_DUMP, - CBE_CHECK, - CBE, - CMD_POOL, -}; - - -static Module_type module_type_from_uint32(uint32_t uint32) -{ - class Bad_tag { }; - switch (uint32) { - case 1: return Module_type::CBE_INIT; - case 2: return Module_type::CBE; - case 3: return Module_type::CBE_DUMP; - case 4: return Module_type::CBE_CHECK; - case 5: return Module_type::CMD_POOL; - default: throw Bad_tag { }; - } -} - - -static uint32_t module_type_to_uint32(Module_type type) -{ - class Bad_type { }; - switch (type) { - case Module_type::CBE_INIT : return 1; - case Module_type::CBE : return 2; - case Module_type::CBE_DUMP : return 3; - case Module_type::CBE_CHECK: return 4; - case Module_type::CMD_POOL : return 5; - } - throw Bad_type { }; -} - - -static Module_type tag_get_module_type(uint32_t tag) -{ - return module_type_from_uint32((tag >> 24) & 0xff); -} - - -static uint32_t tag_set_module_type(uint32_t tag, - Module_type type) -{ - if (tag >> 24) { - - class Bad_tag { }; - throw Bad_tag { }; - } - return tag | (module_type_to_uint32(type) << 24); -} - - -static uint32_t tag_unset_module_type(uint32_t tag) -{ - return tag & 0xffffff; -} - - -static char const *blk_pkt_op_to_string(Block::Packet_descriptor::Opcode op) -{ - switch (op) { - case Block::Packet_descriptor::READ: return "read"; - case Block::Packet_descriptor::WRITE: return "write"; - case Block::Packet_descriptor::SYNC: return "sync"; - case Block::Packet_descriptor::TRIM: return "trim"; - case Block::Packet_descriptor::END: return "end"; - }; - return "?"; -} - - -static String<128> blk_pkt_to_string(Block::Packet_descriptor const &packet) -{ - return - String<128>( - "op=", blk_pkt_op_to_string(packet.operation()), - " vba=", packet.block_number(), - " cnt=", packet.block_count(), - " succ=", packet.succeeded(), - " tag=", Hex(packet.tag().value)); -} - - -template -T read_attribute(Xml_node const &node, - char const *attr) -{ - T value { }; - - if (!node.has_attribute(attr)) { - - error("<", node.type(), "> node misses attribute '", attr, "'"); - class Attribute_missing { }; - throw Attribute_missing { }; - } - if (!node.attribute(attr).value(value)) { - - error("<", node.type(), "> node has malformed '", attr, "' attribute"); - class Malformed_attribute { }; - throw Malformed_attribute { }; - } - return value; -} - - -static void print_blk_data(Block_data const &blk_data) -{ - for(unsigned long idx = 0; idx < Cbe::BLOCK_SIZE; idx += 64) { - log( - " ", idx, ": ", - Hex(blk_data.values[idx + 0], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 1], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 2], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 3], Hex::OMIT_PREFIX, Hex::PAD), " ", - Hex(blk_data.values[idx + 4], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 5], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 6], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 7], Hex::OMIT_PREFIX, Hex::PAD), " ", - Hex(blk_data.values[idx + 8], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 9], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 10], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 11], Hex::OMIT_PREFIX, Hex::PAD), " ", - Hex(blk_data.values[idx + 12], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 13], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 14], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 15], Hex::OMIT_PREFIX, Hex::PAD), " ", - Hex(blk_data.values[idx + 16], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 17], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 18], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 19], Hex::OMIT_PREFIX, Hex::PAD), " ", - Hex(blk_data.values[idx + 20], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 21], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 22], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 23], Hex::OMIT_PREFIX, Hex::PAD), " ", - Hex(blk_data.values[idx + 24], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 25], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 26], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 27], Hex::OMIT_PREFIX, Hex::PAD), " ", - Hex(blk_data.values[idx + 28], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 29], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 30], Hex::OMIT_PREFIX, Hex::PAD), - Hex(blk_data.values[idx + 31], Hex::OMIT_PREFIX, Hex::PAD)); - } -} - - -class Block_io : public Interface -{ - public: - - virtual bool request_acceptable() = 0; - - virtual void submit_request(Cbe::Request const &cbe_req, - Block_data &data) = 0; - - virtual void execute(Constructible &cbe, - Cbe_init::Library &cbe_init, - Cbe_dump::Library &cbe_dump, - Cbe_check::Library &cbe_check, - Verbose_node const &verbose_node, - Io_buffer &blk_buf, - bool &progress) = 0; -}; - - -class Vfs_block_io_job -{ - private: - - using file_size = Vfs::file_size; - using file_offset = Vfs::file_offset; - - enum State { PENDING, IN_PROGRESS, COMPLETE }; - - Vfs::Vfs_handle &_handle; - Cbe::Request _cbe_req; - State _state; - file_offset _nr_of_processed_bytes; - file_size _nr_of_remaining_bytes; - - Cbe::Io_buffer::Index _cbe_req_io_buf_idx(Cbe::Request const &cbe_req) - { - return - Cbe::Io_buffer::Index { - (uint32_t)cbe_req.tag() & 0xffffff }; - } - - void - _mark_req_completed_at_module(Constructible &cbe, - Cbe_init::Library &cbe_init, - Cbe_dump::Library &cbe_dump, - Cbe_check::Library &cbe_check, - Verbose_node const &verbose_node, - bool &progress) - { - Cbe::Io_buffer::Index const data_index { - _cbe_req_io_buf_idx(_cbe_req) }; - - switch (tag_get_module_type(_cbe_req.tag())) { - case Module_type::CBE_INIT: - - cbe_init.io_request_completed(data_index, _cbe_req.success()); - break; - - case Module_type::CBE: - - cbe->io_request_completed(data_index, _cbe_req.success()); - break; - - case Module_type::CBE_DUMP: - - cbe_dump.io_request_completed(data_index, _cbe_req.success()); - break; - - case Module_type::CBE_CHECK: - - cbe_check.io_request_completed(data_index, _cbe_req.success()); - break; - - case Module_type::CMD_POOL: - - class Bad_module_type { }; - throw Bad_module_type { }; - } - progress = true; - - if (verbose_node.blk_io_req_completed()) { - log("blk req completed: ", _cbe_req); - } - } - - - void _execute_read(Constructible &cbe, - Cbe_init::Library &cbe_init, - Cbe_dump::Library &cbe_dump, - Cbe_check::Library &cbe_check, - Verbose_node const &verbose_node, - Io_buffer &io_data, - bool &progress) - { - using Result = Vfs::File_io_service::Read_result; - - switch (_state) { - case State::PENDING: - - _handle.seek(_cbe_req.block_number() * Cbe::BLOCK_SIZE + - _nr_of_processed_bytes); - - if (!_handle.fs().queue_read(&_handle, _nr_of_remaining_bytes)) { - return; - } - _state = State::IN_PROGRESS; - progress = true; - return; - - case State::IN_PROGRESS: - { - size_t read_bytes = 0; - - char *const data { - reinterpret_cast( - &io_data.item(_cbe_req_io_buf_idx(_cbe_req))) }; - - Byte_range_ptr const dst(data + _nr_of_processed_bytes, - _nr_of_remaining_bytes); - - Result const result = - _handle.fs().complete_read(&_handle, dst, read_bytes); - - switch (result) { - case Result::READ_QUEUED: - case Result::READ_ERR_WOULD_BLOCK: - - return; - - case Result::READ_OK: - - _nr_of_processed_bytes += read_bytes; - _nr_of_remaining_bytes -= read_bytes; - - if (_nr_of_remaining_bytes == 0) { - - _state = State::COMPLETE; - _cbe_req.success(true); - - _mark_req_completed_at_module( - cbe, cbe_init, cbe_dump, cbe_check, - verbose_node, progress); - - progress = true; - return; - - } else { - - _state = State::PENDING; - progress = true; - return; - } - - case Result::READ_ERR_IO: - case Result::READ_ERR_INVALID: - - _state = State::COMPLETE; - _cbe_req.success(false); - - _mark_req_completed_at_module( - cbe, cbe_init, cbe_dump, cbe_check, - verbose_node, progress); - - progress = true; - return; - - default: - - class Bad_complete_read_result { }; - throw Bad_complete_read_result { }; - } - } - default: return; - } - } - - void _execute_write(Constructible &cbe, - Cbe_init::Library &cbe_init, - Cbe_dump::Library &cbe_dump, - Cbe_check::Library &cbe_check, - Verbose_node const &verbose_node, - Io_buffer &io_data, - bool &progress) - { - using Result = Vfs::File_io_service::Write_result; - - switch (_state) { - case State::PENDING: - - _handle.seek(_cbe_req.block_number() * Cbe::BLOCK_SIZE + - _nr_of_processed_bytes); - - _state = State::IN_PROGRESS; - progress = true; - break; - - case State::IN_PROGRESS: - { - size_t written_bytes = 0; - - char const *const data { - reinterpret_cast( - &io_data.item(_cbe_req_io_buf_idx(_cbe_req))) }; - - Const_byte_range_ptr const src(data + _nr_of_processed_bytes, - _nr_of_remaining_bytes); - - Result const result = - _handle.fs().write(&_handle, src, written_bytes); - - switch (result) { - case Result::WRITE_ERR_WOULD_BLOCK: - return; - - case Result::WRITE_OK: - - _nr_of_processed_bytes += written_bytes; - _nr_of_remaining_bytes -= written_bytes; - - if (_nr_of_remaining_bytes == 0) { - - _state = State::COMPLETE; - _cbe_req.success(true); - - _mark_req_completed_at_module( - cbe, cbe_init, cbe_dump, cbe_check, - verbose_node, progress); - - progress = true; - return; - - } else { - - _state = State::PENDING; - progress = true; - return; - } - - case Result::WRITE_ERR_IO: - case Result::WRITE_ERR_INVALID: - - _state = State::COMPLETE; - _cbe_req.success(false); - - _mark_req_completed_at_module( - cbe, cbe_init, cbe_dump, cbe_check, - verbose_node, progress); - - progress = true; - return; - - default: - - class Bad_write_result { }; - throw Bad_write_result { }; - } - - } - default: return; - } - } - - void _execute_sync(Constructible &cbe, - Cbe_init::Library &cbe_init, - Cbe_dump::Library &cbe_dump, - Cbe_check::Library &cbe_check, - Verbose_node const &verbose_node, - bool &progress) - { - using Result = Vfs::File_io_service::Sync_result; - - switch (_state) { - case State::PENDING: - - if (!_handle.fs().queue_sync(&_handle)) { - return; - } - _state = State::IN_PROGRESS; - progress = true; - break;; - - case State::IN_PROGRESS: - - switch (_handle.fs().complete_sync(&_handle)) { - case Result::SYNC_QUEUED: - - return; - - case Result::SYNC_ERR_INVALID: - - _cbe_req.success(false); - _mark_req_completed_at_module( - cbe, cbe_init, cbe_dump, cbe_check, verbose_node, - progress); - - _state = State::COMPLETE; - progress = true; - return; - - case Result::SYNC_OK: - - _cbe_req.success(true); - _mark_req_completed_at_module( - cbe, cbe_init, cbe_dump, cbe_check, verbose_node, - progress); - - _state = State::COMPLETE; - progress = true; - return; - - default: - - class Bad_sync_result { }; - throw Bad_sync_result { }; - } - - default: return; - } - } - - public: - - Vfs_block_io_job(Vfs::Vfs_handle &handle, - Cbe::Request cbe_req) - : - _handle { handle }, - _cbe_req { cbe_req }, - _state { State::PENDING }, - _nr_of_processed_bytes { 0 }, - _nr_of_remaining_bytes { _cbe_req.count() * Cbe::BLOCK_SIZE } - { } - - bool complete() const - { - return _state == COMPLETE; - } - - void execute(Constructible &cbe, - Cbe_init::Library &cbe_init, - Cbe_dump::Library &cbe_dump, - Cbe_check::Library &cbe_check, - Verbose_node const &verbose_node, - Io_buffer &blk_buf, - bool &progress) - { - using Cbe_operation = Cbe::Request::Operation; - - switch (_cbe_req.operation()) { - case Cbe_operation::READ: - - _execute_read(cbe, cbe_init, cbe_dump, cbe_check, verbose_node, - blk_buf, progress); - - break; - - case Cbe_operation::WRITE: - - _execute_write(cbe, cbe_init, cbe_dump, cbe_check, verbose_node, - blk_buf, progress); - - break; - - case Cbe_operation::SYNC: - - _execute_sync(cbe, cbe_init, cbe_dump, cbe_check, verbose_node, - progress); - - break; - - default: - - class Bad_cbe_operation { }; - throw Bad_cbe_operation { }; - } - } -}; - - -class Vfs_block_io : public Block_io -{ - private: - - String<32> const _path; - Vfs::Env &_vfs_env; - Vfs::Vfs_handle &_vfs_handle { *_init_vfs_handle(_vfs_env, _path) }; - Constructible _job { }; - - Vfs_block_io(const Vfs_block_io&); - - const Vfs_block_io& operator=(const Vfs_block_io&); - - static Vfs::Vfs_handle *_init_vfs_handle(Vfs::Env &vfs_env, - String<32> const &path) - { - using Result = Vfs::Directory_service::Open_result; - - Vfs::Vfs_handle *vfs_handle { nullptr }; - Result const result { - vfs_env.root_dir().open( - path.string(), Vfs::Directory_service::OPEN_MODE_RDWR, - &vfs_handle, vfs_env.alloc()) }; - - if (result != Result::OPEN_OK) { - - class Open_failed { }; - throw Open_failed { }; - } - return vfs_handle; - } - - public: - - Vfs_block_io(Vfs::Env &vfs_env, - Xml_node const &block_io) - : - _path { block_io.attribute_value( - "path", String<32> { "" } ) }, - _vfs_env { vfs_env } - { } - - - /************** - ** Block_io ** - **************/ - - bool request_acceptable() override - { - return !_job.constructed(); - } - - void submit_request(Cbe::Request const &cbe_req, - Block_data &) override - { - _job.construct(_vfs_handle, cbe_req); - } - - void execute(Constructible &cbe, - Cbe_init::Library &cbe_init, - Cbe_dump::Library &cbe_dump, - Cbe_check::Library &cbe_check, - Verbose_node const &verbose_node, - Io_buffer &blk_buf, - bool &progress) override - { - if (!_job.constructed()) { - return; - } - _job->execute( - cbe, cbe_init, cbe_dump, cbe_check, verbose_node, blk_buf, - progress); - - if (_job->complete()) { - _job.destruct(); - } - } -}; - - -class Block_connection_block_io : public Block_io -{ - private: - - enum { TX_BUF_SIZE = Block::Session::TX_QUEUE_SIZE * BLOCK_SIZE, }; - - Genode::Env &_env; - Heap &_heap; - Allocator_avl _blk_alloc { &_heap }; - Block::Connection<> _blk { _env, &_blk_alloc, TX_BUF_SIZE }; - - Cbe::Io_buffer::Index _packet_io_buf_idx(Block::Packet_descriptor const & pkt) - { - return - Cbe::Io_buffer::Index { - (uint32_t)pkt.tag().value & 0xffffff }; - } - - static Block::Packet_descriptor::Opcode - _cbe_op_to_block_op(Cbe::Request::Operation cbe_op) - { - switch (cbe_op) { - case Cbe::Request::Operation::READ: return Block::Packet_descriptor::READ; - case Cbe::Request::Operation::WRITE: return Block::Packet_descriptor::WRITE; - case Cbe::Request::Operation::SYNC: return Block::Packet_descriptor::SYNC; - default: - class Bad_cbe_op { }; - throw Bad_cbe_op { }; - } - } - - public: - - Block_connection_block_io(Genode::Env &env, - Heap &heap, - Signal_context_capability sigh) - : - _env { env }, - _heap { heap } - { - _blk.tx_channel()->sigh_ack_avail(sigh); - _blk.tx_channel()->sigh_ready_to_submit(sigh); - } - - ~Block_connection_block_io() - { - _blk.tx_channel()->sigh_ack_avail(Signal_context_capability()); - _blk.tx_channel()->sigh_ready_to_submit(Signal_context_capability()); - } - - - /************** - ** Block_io ** - **************/ - - bool request_acceptable() override - { - return _blk.tx()->ready_to_submit(); - } - - void submit_request(Cbe::Request const &cbe_req, - Block_data &data) override - { - Block::Packet_descriptor::Opcode const blk_op { - _cbe_op_to_block_op(cbe_req.operation()) }; - - Block::Packet_descriptor const packet { - _blk.alloc_packet(Cbe::BLOCK_SIZE), - blk_op, - cbe_req.block_number(), - cbe_req.count(), - Block::Packet_descriptor::Tag { cbe_req.tag() } }; - if (cbe_req.operation() == Cbe::Request::Operation::WRITE) { - - *reinterpret_cast( - _blk.tx()->packet_content(packet)) = data; - } - _blk.tx()->try_submit_packet(packet); - } - - void execute(Constructible &cbe, - Cbe_init::Library &cbe_init, - Cbe_dump::Library &cbe_dump, - Cbe_check::Library &cbe_check, - Verbose_node const &verbose_node, - Io_buffer &blk_buf, - bool &progress) override - { - while (_blk.tx()->ack_avail()) { - - Block::Packet_descriptor packet { - _blk.tx()->try_get_acked_packet() }; - - Cbe::Io_buffer::Index const data_index { - _packet_io_buf_idx(packet) }; - - if (packet.operation() == Block::Packet_descriptor::READ && - packet.succeeded()) - { - blk_buf.item(data_index) = - *reinterpret_cast( - _blk.tx()->packet_content(packet)); - } - switch (tag_get_module_type(packet.tag().value)) { - case Module_type::CBE_INIT: - - cbe_init.io_request_completed(data_index, - packet.succeeded()); - break; - - case Module_type::CBE: - - cbe->io_request_completed(data_index, - packet.succeeded()); - break; - - case Module_type::CBE_DUMP: - - cbe_dump.io_request_completed(data_index, - packet.succeeded()); - break; - - case Module_type::CBE_CHECK: - - cbe_check.io_request_completed(data_index, - packet.succeeded()); - break; - - case Module_type::CMD_POOL: - - class Bad_module_type { }; - throw Bad_module_type { }; - } - _blk.tx()->release_packet(packet); - progress = true; - - if (verbose_node.blk_io_req_completed()) { - log("blk pkt completed: ", blk_pkt_to_string(packet)); - } - } - _blk.tx()->wakeup(); - } -}; - - -class Log_node -{ - private: - - String<128> const _string; - - public: - - Log_node(Xml_node const &node) - : - _string { node.attribute_value("string", String<128> { }) } - { } - - String<128> const &string() const { return _string; } - - void print(Genode::Output &out) const - { - Genode::print(out, "string=\"", _string, "\""); - } -}; - - -class Benchmark_node -{ - public: - - using Label = String<128>; - - enum Operation { START, STOP }; - - private: - - Operation const _op; - bool const _label_avail; - Label const _label; - - Operation _read_op_attr(Xml_node const &node) - { - class Attribute_missing { }; - if (!node.has_attribute("op")) { - throw Attribute_missing { }; - } - if (node.attribute("op").has_value("start")) { - return Operation::START; - } - if (node.attribute("op").has_value("stop")) { - return Operation::STOP; - } - class Malformed_attribute { }; - throw Malformed_attribute { }; - } - - static char const *_op_to_string(Operation op) - { - switch (op) { - case START: return "start"; - case STOP: return "stop"; - } - return "?"; - } - - public: - - bool has_attr_label() const - { - return _op == Operation::START; - } - - Benchmark_node(Xml_node const &node) - : - _op { _read_op_attr(node) }, - _label_avail { has_attr_label() && node.has_attribute("label") }, - _label { _label_avail ? - node.attribute_value("label", Label { }) : - Label { } } - { } - - Operation op() const { return _op; } - bool label_avail() const { return _label_avail; } - Label const &label() const { return _label; } - - void print(Genode::Output &out) const - { - Genode::print(out, "op=", _op_to_string(_op)); - if (_label_avail) { - Genode::print(out, " label=", _label); - } - } -}; - - -class Benchmark -{ - private: - - enum State { STARTED, STOPPED }; - - Genode::Env &_env; - Timer::Connection _timer { _env }; - State _state { STOPPED }; - Microseconds _start_time { 0 }; - uint64_t _nr_of_virt_blks_read { 0 }; - uint64_t _nr_of_virt_blks_written { 0 }; - Constructible _start_node { }; - uint64_t _id { 0 }; - - public: - - Benchmark(Genode::Env &env) : _env { env } { } - - void submit_request(Benchmark_node const &node) - { - switch (node.op()) { - case Benchmark_node::START: - - if (_state != STOPPED) { - class Bad_state_to_start { }; - throw Bad_state_to_start { }; - } - _id++; - _nr_of_virt_blks_read = 0; - _nr_of_virt_blks_written = 0; - _state = STARTED; - _start_node.construct(node); - _start_time = _timer.curr_time().trunc_to_plain_us(); - break; - - case Benchmark_node::STOP: - - if (_state != STARTED) { - class Bad_state_to_stop { }; - throw Bad_state_to_stop { }; - } - uint64_t const stop_time_us { - _timer.curr_time().trunc_to_plain_us().value }; - - log(""); - if (_start_node->label_avail()) { - log("Benchmark result \"", _start_node->label(), "\""); - } else { - log("Benchmark result (command ID ", _id, ")"); - } - - double const passed_time_sec { - (double)(stop_time_us - _start_time.value) / - (double)(1000 * 1000) }; - - log(" Ran ", passed_time_sec, " seconds."); - - if (_nr_of_virt_blks_read != 0) { - - uint64_t const bytes_read { - _nr_of_virt_blks_read * Cbe::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 (_nr_of_virt_blks_written != 0) { - - uint64_t bytes_written { - _nr_of_virt_blks_written * Cbe::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(""); - _state = STOPPED; - break; - } - } - - void raise_nr_of_virt_blks_read() { _nr_of_virt_blks_read++; } - void raise_nr_of_virt_blks_written() { _nr_of_virt_blks_written++; } -}; - - -class Trust_anchor_node -{ - private: - - using Operation = Trust_anchor_request::Operation; - - Operation const _op; - String<64> const _passphrase; - - Operation _read_op_attr(Xml_node const &node) - { - class Attribute_missing { }; - if (!node.has_attribute("op")) { - throw Attribute_missing { }; - } - if (node.attribute("op").has_value("initialize")) { - return Operation::INITIALIZE; - } - class Malformed_attribute { }; - throw Malformed_attribute { }; - } - - public: - - Trust_anchor_node(Xml_node const &node) - : - _op { _read_op_attr(node) }, - _passphrase { has_attr_passphrase() ? - node.attribute_value("passphrase", String<64>()) : - String<64>() } - { } - - Operation op() const { return _op; } - String<64> const &passphrase() const { return _passphrase; } - - bool has_attr_passphrase() const - { - return _op == Operation::INITIALIZE; - } - - void print(Genode::Output &out) const - { - Genode::print(out, "op=", to_string(_op)); - if (has_attr_passphrase()) { - Genode::print(out, " passphrase=", _passphrase); - } - } -}; - - -class Request_node -{ - private: - - using Operation = Cbe::Request::Operation; - - Operation const _op; - Virtual_block_address const _vba; - Number_of_blocks const _count; - bool const _sync; - bool const _salt_avail; - uint64_t const _salt; - - Operation _read_op_attr(Xml_node const &node) - { - class Attribute_missing { }; - if (!node.has_attribute("op")) { - throw Attribute_missing { }; - } - if (node.attribute("op").has_value("read")) { - return Operation::READ; - } - if (node.attribute("op").has_value("write")) { - return Operation::WRITE; - } - 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("extend_ft")) { - return Operation::EXTEND_FT; - } - 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; - } - class Malformed_attribute { }; - throw Malformed_attribute { }; - } - - public: - - Request_node(Xml_node const &node) - : - _op { _read_op_attr(node) }, - _vba { has_attr_vba() ? - read_attribute(node, "vba") : 0 }, - _count { has_attr_count() ? - read_attribute(node, "count") : 0 }, - _sync { read_attribute(node, "sync") }, - _salt_avail { has_attr_salt() ? - node.has_attribute("salt") : false }, - _salt { has_attr_salt() && _salt_avail ? - read_attribute(node, "salt") : 0 } - { } - - Operation op() const { return _op; } - Virtual_block_address vba() const { return _vba; } - Number_of_blocks count() const { return _count; } - bool sync() const { return _sync; } - bool salt_avail() const { return _salt_avail; } - uint64_t salt() const { return _salt; } - - bool has_attr_vba() const - { - return _op == Operation::READ || - _op == Operation::WRITE || - _op == Operation::SYNC; - } - - bool has_attr_salt() const - { - return _op == Operation::READ || - _op == Operation::WRITE; - } - - bool has_attr_count() const - { - return _op == Operation::READ || - _op == Operation::WRITE || - _op == Operation::SYNC || - _op == Operation::EXTEND_FT || - _op == Operation::EXTEND_VBD; - } - - void print(Genode::Output &out) const - { - Genode::print(out, "op=", to_string(_op)); - if (has_attr_vba()) { - Genode::print(out, " vba=", _vba); - } - if (has_attr_count()) { - Genode::print(out, " count=", _count); - } - Genode::print(out, " sync=", _sync); - if (_salt_avail) { - Genode::print(out, " salt=", _salt); - } - } -}; - - -class Command : public Fifo::Element -{ - public: - - enum Type - { - INVALID, - REQUEST, - TRUST_ANCHOR, - BENCHMARK, - CONSTRUCT, - DESTRUCT, - INITIALIZE, - CHECK, - DUMP, - LIST_SNAPSHOTS, - LOG - }; - - enum State - { - PENDING, - IN_PROGRESS, - COMPLETED - }; - - private: - - Type _type { INVALID }; - uint32_t _id { 0 }; - State _state { PENDING }; - bool _success { false }; - bool _data_mismatch { false }; - Constructible _request_node { }; - Constructible _trust_anchor_node { }; - Constructible _benchmark_node { }; - Constructible _log_node { }; - Constructible _initialize { }; - Constructible _dump { }; - - char const *_state_to_string() const - { - switch (_state) { - case PENDING: return "pending"; - case IN_PROGRESS: return "in_progress"; - case COMPLETED: return "completed"; - } - return "?"; - } - - char const *_type_to_string() const - { - switch (_type) { - case INITIALIZE: return "initialize"; - case INVALID: return "invalid"; - case DUMP: return "dump"; - 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 LIST_SNAPSHOTS: return "list_snapshots"; - case LOG: return "log"; - } - return "?"; - } - - public: - - Command() { } - - Command(Type type, - Xml_node const &node, - uint32_t id) - : - _type { type }, - _id { id } - { - switch (_type) { - case INITIALIZE: _initialize.construct(node); break; - case DUMP: _dump.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; - } - } - - Command(Command &other) - : - _type { other._type }, - _id { other._id }, - _state { other._state }, - _success { other._success } - { - switch (_type) { - case INITIALIZE: _initialize.construct(*other._initialize); break; - case DUMP: _dump.construct(*other._dump); break; - case REQUEST: _request_node.construct(*other._request_node); break; - case TRUST_ANCHOR: _trust_anchor_node.construct(*other._trust_anchor_node); break; - case BENCHMARK: _benchmark_node.construct(*other._benchmark_node); break; - case LOG: _log_node.construct(*other._log_node); break; - default: break; - } - } - - bool has_attr_data_mismatch() const - { - return - _type == REQUEST && - _request_node->op() == Cbe::Request::Operation::READ && - _request_node->salt_avail(); - } - - bool synchronize() const - { - class Bad_type { }; - switch (_type) { - case INITIALIZE: return true; - case BENCHMARK: return true; - case CONSTRUCT: return true; - case DESTRUCT: return true; - case DUMP: return true; - case CHECK: return true; - case TRUST_ANCHOR: return true; - case LIST_SNAPSHOTS: return true; - case LOG: return true; - case REQUEST: return _request_node->sync(); - case INVALID: throw Bad_type { }; - } - throw Bad_type { }; - } - - static Type type_from_string(String<64> 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 == "dump") { return DUMP; } - if (str == "list-snapshots") { return LIST_SNAPSHOTS; } - if (str == "log") { return LOG; } - class Bad_string { }; - throw Bad_string { }; - } - - void print(Genode::Output &out) const - { - Genode::print(out, "id=", _id, " type=", _type_to_string()); - class Bad_type { }; - switch (_type) { - case INITIALIZE: Genode::print(out, " cfg=(", *_initialize, ")"); break; - case REQUEST: Genode::print(out, " cfg=(", *_request_node, ")"); break; - case TRUST_ANCHOR: Genode::print(out, " cfg=(", *_trust_anchor_node, ")"); break; - case BENCHMARK: Genode::print(out, " cfg=(", *_benchmark_node, ")"); break; - case DUMP: Genode::print(out, " cfg=(", *_dump, ")"); break; - case LOG: Genode::print(out, " cfg=(", *_log_node, ")"); break; - case INVALID: break; - case CHECK: break; - case CONSTRUCT: break; - case DESTRUCT: break; - case LIST_SNAPSHOTS: break; - } - Genode::print(out, " succ=", _success); - if (has_attr_data_mismatch()) { - Genode::print(out, " bad_data=", _data_mismatch); - } - Genode::print(out, " state=", _state_to_string()); - } - - Type type () const { return _type ; } - State state () const { return _state ; } - uint32_t 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 ; } - Cbe_init::Configuration const &initialize () const { return *_initialize ; } - Cbe_dump::Configuration const &dump () const { return *_dump ; } - - void state (State state) { _state = state; } - void success (bool success) { _success = success; } - void data_mismatch (bool data_mismatch) { _data_mismatch = data_mismatch; } - -}; - - -class Command_pool { - - private: - - Allocator &_alloc; - Verbose_node const &_verbose_node; - Fifo _cmd_queue { }; - uint32_t _next_command_id { 0 }; - unsigned long _nr_of_uncompleted_cmds { 0 }; - unsigned long _nr_of_errors { 0 }; - Block_data _blk_data { }; - - void _read_cmd_node(Xml_node const &node, - Command::Type cmd_type) - { - Command &cmd { - *new (_alloc) Command(cmd_type, node, _next_command_id++) }; - - _nr_of_uncompleted_cmds++; - _cmd_queue.enqueue(cmd); - - if (_verbose_node.cmd_pool_cmd_pending()) { - log("cmd pending: ", cmd); - } - } - - static void _generate_blk_data(Block_data &blk_data, - Virtual_block_address vba, - uint64_t salt) - { - for (uint64_t idx { 0 }; - idx + sizeof(vba) + sizeof(salt) <= - sizeof(blk_data.values) / sizeof(blk_data.values[0]); ) - { - memcpy(&blk_data.values[idx], &vba, sizeof(vba)); - idx += sizeof(vba); - memcpy(&blk_data.values[idx], &salt, sizeof(salt)); - idx += sizeof(salt); - vba += idx + salt; - salt += idx + vba; - } - } - - public: - - Command_pool(Allocator &alloc, - Xml_node const &config_xml, - Verbose_node const &verbose_node) - : - _alloc { alloc }, - _verbose_node { verbose_node } - { - config_xml.sub_node("commands").for_each_sub_node( - [&] (Xml_node const &node) - { - _read_cmd_node(node, Command::type_from_string(node.type())); - }); - } - - Command peek_pending_command(Command::Type type) const - { - Reconstructible resulting_cmd { }; - bool first_uncompleted_cmd { true }; - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &curr_cmd) - { - if (exit_loop) { - return; - } - switch (curr_cmd.state()) { - case Command::PENDING: - - /* - * Stop iterating at the first uncompleted command - * that needs to be synchronized. - */ - if (curr_cmd.synchronize()) { - if (curr_cmd.type() == type && first_uncompleted_cmd) { - resulting_cmd.construct(curr_cmd); - } - exit_loop = true; - return; - } - /* - * Select command and stop iterating if the command is of - * the desired type. - */ - if (curr_cmd.type() == type) { - resulting_cmd.construct(curr_cmd); - exit_loop = true; - } - first_uncompleted_cmd = false; - return; - - case Command::IN_PROGRESS: - - /* - * Stop iterating at the first uncompleted command - * that needs to be synchronized. - */ - if (curr_cmd.synchronize()) { - exit_loop = true; - return; - } - first_uncompleted_cmd = false; - return; - - case Command::COMPLETED: - - return; - } - }); - return *resulting_cmd; - } - - void mark_command_in_progress(unsigned long cmd_id) - { - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &cmd) - { - if (exit_loop) { - return; - } - if (cmd.id() == cmd_id) { - if (cmd.state() != Command::PENDING) { - class Bad_state { }; - throw Bad_state { }; - } - cmd.state(Command::IN_PROGRESS); - exit_loop = true; - - if (_verbose_node.cmd_pool_cmd_in_progress()) { - log("cmd in progress: ", cmd); - } - } - }); - } - - void mark_command_completed(unsigned long cmd_id, - bool success) - { - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &cmd) - { - if (exit_loop) { - return; - } - if (cmd.id() == cmd_id) { - - if (cmd.state() != Command::IN_PROGRESS) { - - class Bad_state { }; - throw Bad_state { }; - } - cmd.state(Command::COMPLETED); - _nr_of_uncompleted_cmds--; - cmd.success(success); - if (!cmd.success()) { - _nr_of_errors++; - } - exit_loop = true; - - if (_verbose_node.cmd_pool_cmd_completed()) { - log("cmd completed: ", cmd); - } - } - }); - } - - void generate_blk_data(Cbe::Request cbe_req, - Virtual_block_address vba, - Block_data &blk_data) const - { - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &cmd) - { - if (exit_loop) { - return; - } - if (cmd.id() != cbe_req.tag()) { - return; - } - if (cmd.type() != Command::REQUEST) { - class Bad_command_type { }; - throw Bad_command_type { }; - } - Request_node const &req_node { cmd.request_node() }; - if (req_node.salt_avail()) { - - _generate_blk_data(blk_data, vba, req_node.salt()); - } - exit_loop = true; - }); - } - - void verify_blk_data(Cbe::Request cbe_req, - Virtual_block_address vba, - Block_data const &blk_data) - { - bool exit_loop { false }; - _cmd_queue.for_each([&] (Command &cmd) - { - if (exit_loop) { - return; - } - if (cmd.id() != cbe_req.tag()) { - return; - } - if (cmd.type() != Command::REQUEST) { - class Bad_command_type { }; - throw Bad_command_type { }; - } - Request_node const &req_node { cmd.request_node() }; - if (req_node.salt_avail()) { - - Block_data gen_blk_data { }; - _generate_blk_data(gen_blk_data, vba, req_node.salt()); - - if (memcmp(blk_data.values, gen_blk_data.values, - sizeof(blk_data.values) / - sizeof(blk_data.values[0]))) { - - cmd.data_mismatch(true); - _nr_of_errors++; - - if (_verbose_node.client_data_mismatch()) { - log("client data mismatch: vba=", vba, - " req=(", cbe_req, ")"); - log("client data should be:"); - print_blk_data(gen_blk_data); - log("client data is:"); - print_blk_data(blk_data); - class Client_data_mismatch { }; - throw Client_data_mismatch { }; - } - } - } - exit_loop = true; - }); - } - - void print_failed_cmds() const - { - _cmd_queue.for_each([&] (Command &cmd) - { - if (cmd.state() != Command::COMPLETED) { - return; - } - if (cmd.success() && - (!cmd.has_attr_data_mismatch() || !cmd.data_mismatch())) { - - return; - } - log("cmd failed: ", cmd); - }); - } - - unsigned long nr_of_uncompleted_cmds() { return _nr_of_uncompleted_cmds; } - unsigned long nr_of_errors() { return _nr_of_errors; } -}; - - -class Main : Vfs::Env::User -{ - private: - - Genode::Env &_env; - Attached_rom_dataspace _config_rom { _env, "config" }; - Verbose_node _verbose_node { _config_rom.xml() }; - Heap _heap { _env.ram(), _env.rm() }; - Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; - Signal_handler
_sigh { _env.ep(), *this, &Main::_execute }; - Block_io &_blk_io { _init_blk_io(_config_rom.xml(), _heap, _env, _vfs_env, _sigh) }; - Io_buffer _blk_buf { }; - Command_pool _cmd_pool { _heap, _config_rom.xml(), _verbose_node }; - Constructible _cbe { }; - Cbe_check::Library _cbe_check { }; - Cbe_dump::Library _cbe_dump { }; - Cbe_init::Library _cbe_init { }; - Benchmark _benchmark { _env }; - Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") }; - Crypto_plain_buffer _crypto_plain_buf { }; - Crypto_cipher_buffer _crypto_cipher_buf { }; - Crypto _crypto { _vfs_env, - _config_rom.xml().sub_node("crypto") }; - - Block_io &_init_blk_io(Xml_node const &config, - Heap &heap, - Genode::Env &env, - Vfs::Env &vfs_env, - Signal_context_capability sigh) - { - Xml_node const &block_io { config.sub_node("block-io") }; - if (block_io.attribute("type").has_value("block_connection")) { - return *new (heap) - Block_connection_block_io { env, heap, sigh }; - } - if (block_io.attribute("type").has_value("vfs")) { - return *new (heap) - Vfs_block_io { vfs_env, block_io }; - } - class Malformed_attribute { }; - throw Malformed_attribute { }; - } - - /** - * Vfs::Env::User interface - */ - void wakeup_vfs_user() override { _sigh.local_submit(); } - - template - void _handle_pending_blk_io_requests_of_module(MODULE &module, - Module_type module_type, - bool &progress) - { - while (true) { - - if (!_blk_io.request_acceptable()) { - break; - } - Cbe::Io_buffer::Index data_index { 0 }; - Cbe::Request cbe_req { }; - module.has_io_request(cbe_req, data_index); - if (!cbe_req.valid()) { - break; - } - if (data_index.value & 0xff000000) { - class Bad_data_index { }; - throw Bad_data_index { }; - } - cbe_req.tag( - tag_set_module_type(data_index.value, module_type)); - - _blk_io.submit_request(cbe_req, _blk_buf.item(data_index)); - - if (_verbose_node.blk_io_req_in_progress()) { - log("blk req in progress: ", cbe_req); - } - module.io_request_in_progress(data_index); - progress = true; - } - } - - template - void _handle_completed_client_requests_of_module(MODULE &module, - bool &progress) - { - while (true) { - - Cbe::Request const cbe_req { - module.peek_completed_client_request() }; - - if (!cbe_req.valid()) { - break; - } - _cmd_pool.mark_command_completed(cbe_req.tag(), - cbe_req.success()); - - module.drop_completed_client_request(cbe_req); - progress = true; - } - } - - void _execute_cbe_dump (bool &progress) - { - _cbe_dump.execute(_blk_buf); - if (_cbe_dump.execute_progress()) { - progress = true; - } - _handle_pending_blk_io_requests_of_module( - _cbe_dump, Module_type::CBE_DUMP, progress); - - _handle_completed_client_requests_of_module(_cbe_dump, progress); - } - - template - void _handle_pending_ta_requests_of_module(MODULE &module, - Module_type module_type, - bool &progress) - { - using Ta_operation = Cbe::Trust_anchor_request::Operation; - while (true) { - - if (!_trust_anchor.request_acceptable()) { - break; - } - Cbe::Trust_anchor_request ta_req = - module.peek_generated_ta_request(); - - if (ta_req.operation() == Ta_operation::INVALID) { - return; - } - Cbe::Trust_anchor_request typed_ta_req { ta_req }; - typed_ta_req.tag( - tag_set_module_type(typed_ta_req.tag(), module_type)); - - if (_verbose_node.ta_req_in_progress()) { - log("ta req in progress: ", typed_ta_req); - } - switch (ta_req.operation()) { - case Ta_operation::CREATE_KEY: - - _trust_anchor.submit_request(typed_ta_req); - module.drop_generated_ta_request(ta_req); - progress = true; - break; - - case Ta_operation::SECURE_SUPERBLOCK: - - _trust_anchor.submit_request_hash( - typed_ta_req, - module.peek_generated_ta_sb_hash(ta_req)); - - module.drop_generated_ta_request(ta_req); - progress = true; - break; - - case Ta_operation::ENCRYPT_KEY: - - _trust_anchor.submit_request_key_plaintext_value( - typed_ta_req, - module.peek_generated_ta_key_value_plaintext(ta_req)); - - module.drop_generated_ta_request(ta_req); - progress = true; - break; - - case Ta_operation::DECRYPT_KEY: - - _trust_anchor.submit_request_key_ciphertext_value( - typed_ta_req, - module.peek_generated_ta_key_value_ciphertext(ta_req)); - - module.drop_generated_ta_request(ta_req); - progress = true; - break; - - case Ta_operation::LAST_SB_HASH: - - _trust_anchor.submit_request(typed_ta_req); - module.drop_generated_ta_request(ta_req); - progress = true; - break; - - default: - - class Bad_operation { }; - throw Bad_operation { }; - } - } - } - - void _execute_cbe_init(bool &progress) - { - _cbe_init.execute(_blk_buf); - if (_cbe_init.execute_progress()) { - progress = true; - } - _handle_pending_blk_io_requests_of_module( - _cbe_init, Module_type::CBE_INIT, progress); - - _handle_pending_ta_requests_of_module( - _cbe_init, Module_type::CBE_INIT, progress); - - _handle_completed_client_requests_of_module(_cbe_init, progress); - } - - void _cbe_transfer_client_data_that_was_read(bool &progress) - { - while (true) { - - Cbe::Request request { }; - uint64_t vba { 0 }; - Crypto_plain_buffer::Index plain_buf_idx { 0 }; - _cbe->client_transfer_read_data_required( - request, vba, plain_buf_idx); - - if (!request.valid()) { - break; - } - _cmd_pool.verify_blk_data( - request, vba, _crypto_plain_buf.item(plain_buf_idx)); - - _cbe->client_transfer_read_data_in_progress(plain_buf_idx); - _cbe->client_transfer_read_data_completed(plain_buf_idx, true); - _benchmark.raise_nr_of_virt_blks_read(); - progress = true; - - if (_verbose_node.client_data_transferred()) { - log("client data: vba=", vba, " req=(", request, ")"); - } - } - } - - void _cbe_transfer_client_data_that_will_be_written(bool &progress) - { - while (true) { - - Cbe::Request request { }; - uint64_t vba { 0 }; - Crypto_plain_buffer::Index plain_buf_idx { 0 }; - _cbe->client_transfer_write_data_required( - request, vba, plain_buf_idx); - - if (!request.valid()) { - return; - } - _cmd_pool.generate_blk_data( - request, vba, _crypto_plain_buf.item(plain_buf_idx)); - - _cbe->client_transfer_write_data_in_progress(plain_buf_idx); - _cbe->client_transfer_write_data_completed( - plain_buf_idx, true); - - _benchmark.raise_nr_of_virt_blks_written(); - progress = true; - - if (_verbose_node.client_data_transferred()) { - log("client data: vba=", vba, " req=(", request, ")"); - } - } - } - - void _cbe_handle_crypto_add_key_requests(bool &progress) - { - while (true) { - - Key key; - Cbe::Request request { _cbe->crypto_add_key_required(key) }; - if (!request.valid()) { - return; - } - switch (_crypto.add_key(key)) { - case Crypto::Result::SUCCEEDED: - - if (_verbose_node.crypto_req_in_progress()) { - log("crypto req in progress: ", request); - } - _cbe->crypto_add_key_requested(request); - - if (_verbose_node.crypto_req_completed()) { - log("crypto req completed: ", request); - } - request.success(true); - _cbe->crypto_add_key_completed(request); - progress = true; - break; - - case Crypto::Result::FAILED: - - class Add_key_failed { }; - throw Add_key_failed { }; - - case Crypto::Result::RETRY_LATER: - - return; - } - } - } - - void _cbe_handle_crypto_remove_key_requests(bool &progress) - { - while (true) { - - Key::Id key_id; - Cbe::Request request { - _cbe->crypto_remove_key_required(key_id) }; - - if (!request.valid()) { - break; - } - switch (_crypto.remove_key(key_id)) { - case Crypto::Result::SUCCEEDED: - - if (_verbose_node.crypto_req_in_progress()) { - log("crypto req in progress: ", request); - } - _cbe->crypto_remove_key_requested(request); - - if (_verbose_node.crypto_req_completed()) { - log("crypto req completed: ", request); - } - request.success(true); - _cbe->crypto_remove_key_completed(request); - progress = true; - break; - - case Crypto::Result::FAILED: - - class Remove_key_failed { }; - throw Remove_key_failed { }; - - case Crypto::Result::RETRY_LATER: - - return; - } - } - } - - void _cbe_handle_crypto_encrypt_requests(bool &progress) - { - while (true) { - - if (!_crypto.request_acceptable()) { - break; - } - Crypto_plain_buffer::Index data_index { 0 }; - Cbe::Request request { - _cbe->crypto_cipher_data_required(data_index) }; - - if (!request.valid()) { - break; - } - request.tag(data_index.value); - _crypto.submit_request( - request, Crypto::Operation::ENCRYPT_BLOCK, - data_index, - Crypto_cipher_buffer::Index { data_index.value }); - - _cbe->crypto_cipher_data_requested(data_index); - if (_verbose_node.crypto_req_in_progress()) { - log("crypto req in progress: ", request); - } - progress = true; - } - } - - void _cbe_handle_crypto_decrypt_requests(bool &progress) - { - while (true) { - - if (!_crypto.request_acceptable()) { - break; - } - Crypto_cipher_buffer::Index data_index { 0 }; - Cbe::Request request { - _cbe->crypto_plain_data_required(data_index) }; - - if (!request.valid()) { - break; - } - request.tag(data_index.value); - _crypto.submit_request( - request, Crypto::Operation::DECRYPT_BLOCK, - Crypto_plain_buffer::Index { data_index.value }, - data_index); - - _cbe->crypto_plain_data_requested(data_index); - if (_verbose_node.crypto_req_in_progress()) { - log("crypto req in progress: ", request); - } - progress = true; - } - } - - void _cbe_handle_crypto_requests(bool &progress) - { - _cbe_handle_crypto_add_key_requests(progress); - _cbe_handle_crypto_remove_key_requests(progress); - _cbe_handle_crypto_encrypt_requests(progress); - _cbe_handle_crypto_decrypt_requests(progress); - } - - void _execute_cbe(bool &progress) - { - _cbe->execute(_blk_buf, _crypto_plain_buf, _crypto_cipher_buf); - if (_cbe->execute_progress()) { - progress = true; - } - _handle_pending_blk_io_requests_of_module( - *_cbe, Module_type::CBE, progress); - - _handle_pending_ta_requests_of_module( - *_cbe, Module_type::CBE, progress); - - _cbe_handle_crypto_requests(progress); - _cbe_transfer_client_data_that_was_read(progress); - _cbe_transfer_client_data_that_will_be_written(progress); - _handle_completed_client_requests_of_module(*_cbe, progress); - } - - void _cmd_pool_handle_pending_cbe_init_cmds(bool &progress) - { - while (true) { - - if (!_cbe_init.client_request_acceptable()) { - break; - } - Command const cmd { - _cmd_pool.peek_pending_command(Command::INITIALIZE) }; - - if (cmd.type() == Command::INVALID) { - break; - } - Cbe_init::Configuration const &cfg { cmd.initialize() }; - - _cbe_init.submit_client_request( - Cbe::Request( - Cbe::Request::Operation::READ, - false, 0, 0, 0, 0, cmd.id()), - cfg.vbd_nr_of_lvls() - 1, - cfg.vbd_nr_of_children(), - cfg.vbd_nr_of_leafs(), - cfg.ft_nr_of_lvls() - 1, - cfg.ft_nr_of_children(), - cfg.ft_nr_of_leafs()); - - _cmd_pool.mark_command_in_progress(cmd.id()); - progress = true; - } - } - - void _cmd_pool_handle_pending_check_cmds(bool &progress) - { - while (true) { - - if (!_cbe_check.client_request_acceptable()) { - break; - } - Command const cmd { - _cmd_pool.peek_pending_command(Command::CHECK) }; - - if (cmd.type() == Command::INVALID) { - break; - } - _cbe_check.submit_client_request( - Cbe::Request { - Cbe::Request::Operation::READ, - false, - 0, - 0, - 0, - 0, - cmd.id() - } - ); - _cmd_pool.mark_command_in_progress(cmd.id()); - progress = true; - } - } - - void _cmd_pool_handle_pending_cbe_cmds(bool &progress) - { - while (true) { - - if (!_cbe->client_request_acceptable()) { - break; - } - Command const cmd { - _cmd_pool.peek_pending_command(Command::REQUEST) }; - - if (cmd.type() == Command::INVALID) { - break; - } - Request_node const &req_node { cmd.request_node() }; - Cbe::Request const &cbe_req { - cmd.request_node().op(), - false, - req_node.has_attr_vba() ? req_node.vba() : 0, - 0, - req_node.has_attr_count() ? req_node.count() : 0, - 0, - cmd.id() }; - - _cbe->submit_client_request(cbe_req, 0); - _cmd_pool.mark_command_in_progress(cmd.id()); - progress = true; - } - } - - void _cmd_pool_handle_pending_ta_cmds(bool &progress) - { - while (true) { - - if (!_trust_anchor.request_acceptable()) { - break; - } - Command const cmd { - _cmd_pool.peek_pending_command(Command::TRUST_ANCHOR) }; - - if (cmd.type() == Command::INVALID) { - break; - } - Trust_anchor_node const &node { cmd.trust_anchor_node() }; - Trust_anchor_request const &ta_req { - node.op(), false, cmd.id() }; - - Trust_anchor_request typed_ta_req { ta_req }; - typed_ta_req.tag( - tag_set_module_type( - typed_ta_req.tag(), Module_type::CMD_POOL)); - - switch (node.op()) { - case Trust_anchor_request::Operation::INITIALIZE: - - _trust_anchor.submit_request_passphrase( - typed_ta_req, node.passphrase()); - - _cmd_pool.mark_command_in_progress(cmd.id()); - progress = true; - - break; - - default: - - class Bad_operation { }; - throw Bad_operation { }; - } - } - } - - void _cmd_pool_handle_pending_dump_cmds(bool &progress) - { - while (true) { - - if (!_cbe_dump.client_request_acceptable()) { - break; - } - Command const cmd { - _cmd_pool.peek_pending_command(Command::DUMP) }; - - if (cmd.type() == Command::INVALID) { - break; - } - Cbe_dump::Configuration const &cfg { cmd.dump() }; - _cbe_dump.submit_client_request( - Cbe::Request( - Cbe::Request::Operation::READ, - false, 0, 0, 0, 0, cmd.id()), - cfg); - - _cmd_pool.mark_command_in_progress(cmd.id()); - progress = true; - } - } - - void _cmd_pool_handle_pending_construct_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::CONSTRUCT) }; - - if (cmd.type() == Command::INVALID) { - break; - } - _cbe.construct(); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _cmd_pool_handle_pending_destruct_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::DESTRUCT) }; - - if (cmd.type() == Command::INVALID) { - break; - } - _cbe.destruct(); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _cmd_pool_handle_pending_list_snapshots_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::LIST_SNAPSHOTS) }; - - if (cmd.type() == Command::INVALID) { - break; - } - Active_snapshot_ids ids; - _cbe->active_snapshot_ids(ids); - unsigned snap_nr { 0 }; - log(""); - log("List snapshots (command ID ", cmd.id(), ")"); - for (unsigned idx { 0 }; idx < sizeof(ids.values) / sizeof(ids.values[0]); idx++) { - if (ids.values[idx] != 0) { - log(" Snapshot #", snap_nr, " is generation ", - (uint64_t)ids.values[idx]); - - snap_nr++; - } - } - log(""); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _cmd_pool_handle_pending_log_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::LOG) }; - - if (cmd.type() == Command::INVALID) { - break; - } - log("\n", cmd.log_node().string(), "\n"); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _cmd_pool_handle_pending_benchmark_cmds(bool &progress) - { - while (true) { - - Command const cmd { - _cmd_pool.peek_pending_command(Command::BENCHMARK) }; - - if (cmd.type() == Command::INVALID) { - break; - } - _benchmark.submit_request(cmd.benchmark_node()); - _cmd_pool.mark_command_in_progress(cmd.id()); - _cmd_pool.mark_command_completed(cmd.id(), true); - progress = true; - } - } - - void _execute_cbe_check (bool &progress) - { - _cbe_check.execute(_blk_buf); - if (_cbe_check.execute_progress()) { - progress = true; - } - _handle_pending_blk_io_requests_of_module( - _cbe_check, Module_type::CBE_CHECK, progress); - - _handle_completed_client_requests_of_module(_cbe_check, progress); - } - - void _execute_command_pool(bool &progress) - { - if (_cbe.constructed()) { - _cmd_pool_handle_pending_cbe_cmds(progress); - _cmd_pool_handle_pending_list_snapshots_cmds(progress); - } - _cmd_pool_handle_pending_log_cmds(progress); - _cmd_pool_handle_pending_ta_cmds(progress); - _cmd_pool_handle_pending_cbe_init_cmds(progress); - _cmd_pool_handle_pending_benchmark_cmds(progress); - _cmd_pool_handle_pending_construct_cmds(progress); - _cmd_pool_handle_pending_destruct_cmds(progress); - _cmd_pool_handle_pending_dump_cmds(progress); - _cmd_pool_handle_pending_check_cmds(progress); - - if (_cmd_pool.nr_of_uncompleted_cmds() == 0) { - - if (_cmd_pool.nr_of_errors() > 0) { - - _cmd_pool.print_failed_cmds(); - _env.parent().exit(-1); - - } else { - - _env.parent().exit(0); - } - } - } - - template - void - _trust_anchor_handle_completed_requests_of_module(MODULE &module, - Trust_anchor_request const &typed_ta_req, - bool &progress) - { - using Ta_operation = Cbe::Trust_anchor_request::Operation; - - Trust_anchor_request ta_req { typed_ta_req }; - ta_req.tag(tag_unset_module_type(ta_req.tag())); - - if (_verbose_node.ta_req_completed()) { - log("ta req completed: ", typed_ta_req); - } - switch (ta_req.operation()) { - case Ta_operation::CREATE_KEY: - - module.mark_generated_ta_create_key_request_complete( - ta_req, - _trust_anchor.peek_completed_key_plaintext_value()); - - _trust_anchor.drop_completed_request(); - progress = true; - break; - - case Ta_operation::SECURE_SUPERBLOCK: - - module.mark_generated_ta_secure_sb_request_complete( - ta_req); - - _trust_anchor.drop_completed_request(); - progress = true; - break; - - case Ta_operation::LAST_SB_HASH: - - module.mark_generated_ta_last_sb_hash_request_complete( - ta_req, - _trust_anchor.peek_completed_hash()); - - _trust_anchor.drop_completed_request(); - progress = true; - break; - - case Ta_operation::ENCRYPT_KEY: - - module.mark_generated_ta_encrypt_key_request_complete( - ta_req, - _trust_anchor.peek_completed_key_ciphertext_value()); - - _trust_anchor.drop_completed_request(); - progress = true; - break; - - case Ta_operation::DECRYPT_KEY: - - module.mark_generated_ta_decrypt_key_request_complete( - ta_req, - _trust_anchor.peek_completed_key_plaintext_value()); - - _trust_anchor.drop_completed_request(); - progress = true; - break; - - default: - - class Bad_ta_operation { }; - throw Bad_ta_operation { }; - } - } - - void _trust_anchor_handle_completed_requests(bool &progress) - { - while (true) { - - Trust_anchor_request const typed_ta_req { - _trust_anchor.peek_completed_request() }; - - if (!typed_ta_req.valid()) { - break; - } - switch (tag_get_module_type(typed_ta_req.tag())) { - case Module_type::CMD_POOL: - { - Trust_anchor_request ta_req { typed_ta_req }; - ta_req.tag(tag_unset_module_type(ta_req.tag())); - - using Ta_operation = Trust_anchor_request::Operation; - if (ta_req.operation() == Ta_operation::INITIALIZE) { - - _cmd_pool.mark_command_completed(ta_req.tag(), - ta_req.success()); - - _trust_anchor.drop_completed_request(); - progress = true; - continue; - - } else { - - class Bad_operation { }; - throw Bad_operation { }; - } - break; - } - case Module_type::CBE_INIT: - - _trust_anchor_handle_completed_requests_of_module( - _cbe_init, typed_ta_req, progress); - - break; - - case Module_type::CBE: - - _trust_anchor_handle_completed_requests_of_module( - *_cbe, typed_ta_req, progress); - - break; - - default: - - class Bad_module_type { }; - throw Bad_module_type { }; - } - } - } - - void _execute_trust_anchor(bool &progress) - { - _trust_anchor.execute(progress); - _trust_anchor_handle_completed_requests(progress); - } - - void _crypto_handle_completed_encrypt_requests(bool &progress) - { - while (true) { - - Cbe::Request const request { - _crypto.peek_completed_encryption_request() }; - - if (!request.valid()) { - break; - } - Crypto_cipher_buffer::Index const data_idx { request.tag() }; - _cbe->supply_crypto_cipher_data(data_idx, request.success()); - - _crypto.drop_completed_request(); - progress = true; - - if (_verbose_node.crypto_req_completed()) { - log("crypto req completed: ", request); - } - } - } - - void _crypto_handle_completed_decrypt_requests(bool &progress) - { - while (true) { - - Cbe::Request const request { - _crypto.peek_completed_decryption_request() }; - - if (!request.valid()) { - break; - } - Crypto_plain_buffer::Index const data_idx { request.tag() }; - _cbe->supply_crypto_plain_data(data_idx, request.success()); - - _crypto.drop_completed_request(); - progress = true; - - if (_verbose_node.crypto_req_completed()) { - log("crypto req completed: ", request); - } - } - } - - void _execute_crypto(bool &progress) - { - _crypto.execute(_crypto_plain_buf, _crypto_cipher_buf, progress); - _crypto_handle_completed_encrypt_requests(progress); - _crypto_handle_completed_decrypt_requests(progress); - } - - void _execute() - { - bool progress { true }; - while (progress) { - - progress = false; - _execute_command_pool(progress); - _execute_cbe_init(progress); - - _blk_io.execute( - _cbe, _cbe_init, _cbe_dump, _cbe_check, _verbose_node, - _blk_buf, progress); - - _execute_trust_anchor(progress); - _execute_cbe_check(progress); - _execute_cbe_dump(progress); - _execute_crypto(progress); - if (_cbe.constructed()) { - _execute_cbe(progress); - } - } - _vfs_env.io().commit(); - } - - public: - - Main(Genode::Env &env) - : - _env { env } - { - _execute(); - } -}; - -void Component::construct(Genode::Env &env) -{ - env.exec_static_constructors(); - - Cbe::assert_valid_object_size(); - cbe_cxx_init(); - - Cbe::assert_valid_object_size(); - cbe_init_cxx_init(); - - Cbe::assert_valid_object_size(); - cbe_check_cxx_init(); - - Cbe::assert_valid_object_size(); - cbe_dump_cxx_init(); - - static Main main(env); -} - -extern "C" int memcmp(const void *p0, const void *p1, Genode::size_t size) -{ - return Genode::memcmp(p0, p1, size); -} diff --git a/repos/gems/src/app/cbe_tester/target.mk b/repos/gems/src/app/cbe_tester/target.mk deleted file mode 100644 index cef3fcb7c6..0000000000 --- a/repos/gems/src/app/cbe_tester/target.mk +++ /dev/null @@ -1,13 +0,0 @@ -REQUIRES := x86_64 - -TARGET := cbe_tester -SRC_CC += main.cc -SRC_CC += crypto.cc -SRC_CC += trust_anchor.cc -SRC_CC += vfs_utilities.cc - -INC_DIR := $(PRG_DIR) -LIBS += base cbe_cxx cbe_init_cxx cbe_check_cxx cbe_dump_cxx vfs -LIBS += spark libsparkcrypto - -CC_CXX_WARN_STRICT_CONVERSION = diff --git a/repos/gems/src/app/cbe_tester/trust_anchor.cc b/repos/gems/src/app/cbe_tester/trust_anchor.cc deleted file mode 100644 index 96f209aca5..0000000000 --- a/repos/gems/src/app/cbe_tester/trust_anchor.cc +++ /dev/null @@ -1,586 +0,0 @@ -/* - * \brief Implementation of the TA module API using the TA VFS API - * \author Martin Stein - * \date 2020-10-29 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -/* local includes */ -#include - -using namespace Genode; -using namespace Cbe; -using namespace Vfs; - - -void Trust_anchor::_execute_write_read_operation(Vfs_handle &file, - String<128> const &file_path, - char const *write_buf, - char *read_buf, - file_size read_size, - bool &progress) -{ - switch (_job.state) { - case Job_state::WRITE_PENDING: - - file.seek(_job.fl_offset); - _job.state = Job_state::WRITE_IN_PROGRESS; - progress = true; - return; - - case Job_state::WRITE_IN_PROGRESS: - { - size_t written_bytes { 0 }; - - Const_byte_range_ptr const src(write_buf + _job.fl_offset, _job.fl_size); - - Write_result const result = file.fs().write(&file, src, written_bytes); - - switch (result) { - - case Write_result::WRITE_ERR_WOULD_BLOCK: - return; - - case Write_result::WRITE_OK: - - _job.fl_offset += written_bytes; - _job.fl_size -= written_bytes; - - if (_job.fl_size > 0) { - - _job.state = Job_state::WRITE_PENDING; - progress = true; - return; - } - _job.state = Job_state::READ_PENDING; - _job.fl_offset = 0; - _job.fl_size = read_size; - progress = true; - return; - - default: - - _job.request.success(false); - error("failed to write file ", file_path); - _job.state = Job_state::COMPLETE; - progress = true; - return; - } - } - case Job_state::READ_PENDING: - - file.seek(_job.fl_offset); - - if (!file.fs().queue_read(&file, _job.fl_size)) { - return; - } - _job.state = Job_state::READ_IN_PROGRESS; - progress = true; - return; - - case Job_state::READ_IN_PROGRESS: - { - size_t read_bytes = 0; - - Byte_range_ptr const dst(read_buf + _job.fl_offset, _job.fl_size); - - Read_result const result = file.fs().complete_read( &file, dst, read_bytes); - - switch (result) { - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_OK: - - _job.fl_offset += read_bytes; - _job.fl_size -= read_bytes; - _job.request.success(true); - - if (_job.fl_size > 0) { - - _job.state = Job_state::READ_PENDING; - progress = true; - return; - } - _job.state = Job_state::COMPLETE; - progress = true; - return; - - default: - - _job.request.success(false); - error("failed to read file ", file_path); - _job.state = Job_state::COMPLETE; - return; - } - } - default: - - return; - } -} - - -void Trust_anchor::_execute_write_operation(Vfs_handle &file, - String<128> const &file_path, - char const *write_buf, - bool &progress, - bool result_via_read) -{ - switch (_job.state) { - case Job_state::WRITE_PENDING: - - file.seek(_job.fl_offset); - _job.state = Job_state::WRITE_IN_PROGRESS; - progress = true; - return; - - case Job_state::WRITE_IN_PROGRESS: - { - size_t written_bytes = 0; - - Const_byte_range_ptr const src(write_buf + _job.fl_offset, _job.fl_size); - - Write_result const result = file.fs().write( &file, src, written_bytes); - - switch (result) { - - case Write_result::WRITE_ERR_WOULD_BLOCK: - return; - - case Write_result::WRITE_OK: - - _job.fl_offset += written_bytes; - _job.fl_size -= written_bytes; - - if (_job.fl_size > 0) { - - _job.state = Job_state::WRITE_PENDING; - progress = true; - return; - } - _job.state = Job_state::READ_PENDING; - _job.fl_offset = 0; - - if (result_via_read) - _job.fl_size = sizeof(_read_buf); - else - _job.fl_size = 0; - - progress = true; - return; - - default: - - _job.request.success(false); - error("failed to write file ", file_path); - _job.state = Job_state::COMPLETE; - progress = true; - return; - } - } - case Job_state::READ_PENDING: - - file.seek(_job.fl_offset); - - if (!file.fs().queue_read(&file, _job.fl_size)) { - return; - } - _job.state = Job_state::READ_IN_PROGRESS; - progress = true; - return; - - case Job_state::READ_IN_PROGRESS: - { - size_t read_bytes = 0; - - Byte_range_ptr const dst(_read_buf + _job.fl_offset, _job.fl_size); - - Read_result const result = file.fs().complete_read(&file, dst, read_bytes); - - switch (result) { - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_OK: - - _job.fl_offset += read_bytes; - _job.fl_size -= read_bytes; - - if (_job.fl_size > 0) { - - _job.state = Job_state::READ_PENDING; - progress = true; - return; - } - if (result_via_read) { - _job.request.success(!strcmp(_read_buf, "ok", 3)); - } else - _job.request.success(true); - - _job.state = Job_state::COMPLETE; - progress = true; - return; - - default: - - _job.request.success(false); - error("failed to read file ", file_path); - _job.state = Job_state::COMPLETE; - return; - } - } - default: - - return; - } -} - - -void Trust_anchor::_execute_read_operation(Vfs_handle &file, - String<128> const &file_path, - char *read_buf, - bool &progress) -{ - switch (_job.state) { - case Job_state::READ_PENDING: - - file.seek(_job.fl_offset); - - if (!file.fs().queue_read(&file, _job.fl_size)) { - return; - } - _job.state = Job_state::READ_IN_PROGRESS; - progress = true; - return; - - case Job_state::READ_IN_PROGRESS: - { - size_t read_bytes = 0; - - Byte_range_ptr const dst(read_buf + _job.fl_offset, _job.fl_size); - - Read_result const result = file.fs().complete_read(&file, dst, read_bytes); - - switch (result) { - case Read_result::READ_QUEUED: - case Read_result::READ_ERR_WOULD_BLOCK: - - return; - - case Read_result::READ_OK: - - _job.fl_offset += read_bytes; - _job.fl_size -= read_bytes; - _job.request.success(true); - - if (_job.fl_size > 0) { - - _job.state = Job_state::READ_PENDING; - progress = true; - return; - } - _job.state = Job_state::COMPLETE; - progress = true; - return; - - default: - - _job.request.success(false); - error("failed to read file ", file_path); - _job.state = Job_state::COMPLETE; - return; - } - } - default: - - return; - } -} - - -Trust_anchor::Trust_anchor(Vfs::Env &vfs_env, - Xml_node const &xml_node) -: - _vfs_env { vfs_env }, - _path { xml_node.attribute_value("path", String<128>()) } -{ } - - -bool Trust_anchor::request_acceptable() const -{ - return _job.request.operation() == Operation::INVALID; -} - - -void -Trust_anchor::submit_request_passphrase(Trust_anchor_request const &request, - String<64> const &passphrase) -{ - switch (request.operation()) { - case Operation::INITIALIZE: - - _job.request = request; - _job.passphrase = passphrase; - _job.state = Job_state::WRITE_PENDING; - _job.fl_offset = 0; - _job.fl_size = _job.passphrase.length(); - break; - - default: - - class Bad_operation { }; - throw Bad_operation { }; - } -} - - -void -Trust_anchor:: -submit_request_key_plaintext_value(Trust_anchor_request const &request, - Key_plaintext_value const &key_plaintext_value) -{ - switch (request.operation()) { - case Operation::ENCRYPT_KEY: - - _job.request = request; - _job.key_plaintext_value = key_plaintext_value; - _job.state = Job_state::WRITE_PENDING; - _job.fl_offset = 0; - _job.fl_size = sizeof(_job.key_plaintext_value.value) / - sizeof(_job.key_plaintext_value.value[0]); - break; - - default: - - class Bad_operation { }; - throw Bad_operation { }; - } -} - - -void -Trust_anchor:: -submit_request_key_ciphertext_value(Trust_anchor_request const &request, - Key_ciphertext_value const &key_ciphertext_value) -{ - switch (request.operation()) { - case Operation::DECRYPT_KEY: - - _job.request = request; - _job.key_ciphertext_value = key_ciphertext_value; - _job.state = Job_state::WRITE_PENDING; - _job.fl_offset = 0; - _job.fl_size = sizeof(_job.key_ciphertext_value.value) / - sizeof(_job.key_ciphertext_value.value[0]); - break; - - default: - - class Bad_operation { }; - throw Bad_operation { }; - } -} - - -void Trust_anchor::submit_request_hash(Trust_anchor_request const &request, - Hash const &hash) -{ - switch (request.operation()) { - case Operation::SECURE_SUPERBLOCK: - - _job.request = request; - _job.hash = hash; - _job.state = Job_state::WRITE_PENDING; - _job.fl_offset = 0; - _job.fl_size = sizeof(_job.hash.values) / - sizeof(_job.hash.values[0]); - break; - - default: - - class Bad_operation { }; - throw Bad_operation { }; - } -} - -void Trust_anchor::submit_request(Trust_anchor_request const &request) -{ - switch (request.operation()) { - case Operation::LAST_SB_HASH: - - _job.request = request; - _job.state = Job_state::READ_PENDING; - _job.fl_offset = 0; - _job.fl_size = sizeof(_job.hash.values) / - sizeof(_job.hash.values[0]); - break; - - case Operation::CREATE_KEY: - - _job.request = request; - _job.state = Job_state::READ_PENDING; - _job.fl_offset = 0; - _job.fl_size = sizeof(_job.key_plaintext_value.value) / - sizeof(_job.key_plaintext_value.value[0]); - break; - - default: - - class Bad_operation { }; - throw Bad_operation { }; - } -} - - -void Trust_anchor::execute(bool &progress) -{ - switch (_job.request.operation()) { - case Operation::INITIALIZE: - - _execute_write_operation( - _initialize_file, _initialize_path, - _job.passphrase.string(), progress, true); - - break; - - case Operation::SECURE_SUPERBLOCK: - - _execute_write_operation( - _hashsum_file, _hashsum_path, - _job.hash.values, progress, false); - - break; - - case Operation::LAST_SB_HASH: - - _execute_read_operation( - _hashsum_file, _hashsum_path, - _job.hash.values, progress); - - break; - - case Operation::CREATE_KEY: - - _execute_read_operation( - _generate_key_file, _generate_key_path, - _job.key_plaintext_value.value, progress); - - break; - - case Operation::ENCRYPT_KEY: - - _execute_write_read_operation( - _encrypt_file, _encrypt_path, - _job.key_plaintext_value.value, - _job.key_ciphertext_value.value, - sizeof(_job.key_ciphertext_value.value) / - sizeof(_job.key_ciphertext_value.value[0]), - progress); - - break; - - case Operation::DECRYPT_KEY: - - _execute_write_read_operation( - _decrypt_file, _decrypt_path, - _job.key_ciphertext_value.value, - _job.key_plaintext_value.value, - sizeof(_job.key_plaintext_value.value) / - sizeof(_job.key_plaintext_value.value[0]), - progress); - - break; - - case Operation::INVALID: - - break; - - default: - - class Bad_operation { }; - throw Bad_operation { }; - } -} - - -Trust_anchor_request Trust_anchor::peek_completed_request() const -{ - if (_job.state != Job_state::COMPLETE) { - - return Trust_anchor_request { }; - } - return _job.request; -} - - -Hash const &Trust_anchor::peek_completed_hash() const -{ - if (_job.request.operation() != Operation::LAST_SB_HASH) { - - class Bad_operation { }; - throw Bad_operation { }; - } - if (_job.state != Job_state::COMPLETE) { - - class Bad_state { }; - throw Bad_state { }; - } - return _job.hash; -} - - -Key_plaintext_value const & -Trust_anchor::peek_completed_key_plaintext_value() const -{ - if (_job.request.operation() != Operation::CREATE_KEY && - _job.request.operation() != Operation::DECRYPT_KEY) { - - class Bad_operation { }; - throw Bad_operation { }; - } - if (_job.state != Job_state::COMPLETE) { - - class Bad_state { }; - throw Bad_state { }; - } - return _job.key_plaintext_value; -} - - -Key_ciphertext_value const & -Trust_anchor::peek_completed_key_ciphertext_value() const -{ - if (_job.request.operation() != Operation::ENCRYPT_KEY) { - - class Bad_operation { }; - throw Bad_operation { }; - } - if (_job.state != Job_state::COMPLETE) { - - class Bad_state { }; - throw Bad_state { }; - } - return _job.key_ciphertext_value; -} - - -void Trust_anchor::drop_completed_request() -{ - if (_job.state != Job_state::COMPLETE) { - - class Bad_state { }; - throw Bad_state { }; - } - _job.request = Trust_anchor_request { }; -} diff --git a/repos/gems/src/app/cbe_tester/trust_anchor.h b/repos/gems/src/app/cbe_tester/trust_anchor.h deleted file mode 100644 index 4cea4aa41b..0000000000 --- a/repos/gems/src/app/cbe_tester/trust_anchor.h +++ /dev/null @@ -1,123 +0,0 @@ -/* - * \brief Implementation of the TA module API using the TA VFS API - * \author Martin Stein - * \date 2020-10-29 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE_TESTER__TRUST_ANCHOR_H_ -#define _CBE_TESTER__TRUST_ANCHOR_H_ - -/* CBE includes */ -#include - -/* CBE tester includes */ -#include - -class Trust_anchor -{ - private: - - using Read_result = Vfs::File_io_service::Read_result; - using Write_result = Vfs::File_io_service::Write_result; - using Operation = Cbe::Trust_anchor_request::Operation; - - enum Job_state - { - WRITE_PENDING, - WRITE_IN_PROGRESS, - READ_PENDING, - READ_IN_PROGRESS, - COMPLETE - }; - - struct Job - { - Cbe::Trust_anchor_request request { }; - Job_state state { Job_state::COMPLETE }; - Genode::String<64> passphrase { }; - Cbe::Hash hash { }; - Cbe::Key_plaintext_value key_plaintext_value { }; - Cbe::Key_ciphertext_value key_ciphertext_value { }; - Vfs::file_offset fl_offset { 0 }; - Vfs::file_size fl_size { 0 }; - }; - - Vfs::Env &_vfs_env; - char _read_buf[64]; - Genode::String<128> const _path; - Genode::String<128> const _decrypt_path { _path, "/decrypt" }; - Vfs::Vfs_handle &_decrypt_file { vfs_open_rw(_vfs_env, { _decrypt_path }) }; - Genode::String<128> const _encrypt_path { _path, "/encrypt" }; - Vfs::Vfs_handle &_encrypt_file { vfs_open_rw(_vfs_env, { _encrypt_path }) }; - Genode::String<128> const _generate_key_path { _path, "/generate_key" }; - Vfs::Vfs_handle &_generate_key_file { vfs_open_rw(_vfs_env, { _generate_key_path }) }; - Genode::String<128> const _initialize_path { _path, "/initialize" }; - Vfs::Vfs_handle &_initialize_file { vfs_open_rw(_vfs_env, { _initialize_path }) }; - Genode::String<128> const _hashsum_path { _path, "/hashsum" }; - Vfs::Vfs_handle &_hashsum_file { vfs_open_rw(_vfs_env, { _hashsum_path }) }; - Job _job { }; - - void _execute_write_read_operation(Vfs::Vfs_handle &file, - Genode::String<128> const &file_path, - char const *write_buf, - char *read_buf, - Vfs::file_size read_size, - bool &progress); - - void _execute_write_operation(Vfs::Vfs_handle &file, - Genode::String<128> const &file_path, - char const *write_buf, - bool &progress, - bool result_via_read); - - void _execute_read_operation(Vfs::Vfs_handle &file, - Genode::String<128> const &file_path, - char *read_buf, - bool &progress); - - public: - - Trust_anchor(Vfs::Env &vfs_env, - Genode::Xml_node const &xml_node); - - bool request_acceptable() const; - - void submit_request_passphrase(Cbe::Trust_anchor_request const &request, - Genode::String<64> const &passphrase); - - void - submit_request_key_plaintext_value(Cbe::Trust_anchor_request const &request, - Cbe::Key_plaintext_value const &key_plaintext_value); - - void - submit_request_key_ciphertext_value(Cbe::Trust_anchor_request const &request, - Cbe::Key_ciphertext_value const &key_ciphertext_value); - - void submit_request_hash(Cbe::Trust_anchor_request const &request, - Cbe::Hash const &hash); - - void submit_request(Cbe::Trust_anchor_request const &request); - - void execute(bool &progress); - - Cbe::Trust_anchor_request peek_completed_request() const; - - Cbe::Hash const &peek_completed_hash() const; - - Cbe::Key_plaintext_value const & - peek_completed_key_plaintext_value() const; - - Cbe::Key_ciphertext_value const & - peek_completed_key_ciphertext_value() const; - - void drop_completed_request(); -}; - -#endif /* _CBE_TESTER__TRUST_ANCHOR_H_ */ diff --git a/repos/gems/src/app/cbe_tester/util.h b/repos/gems/src/app/cbe_tester/util.h deleted file mode 100644 index 7bec415742..0000000000 --- a/repos/gems/src/app/cbe_tester/util.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _UTIL_H_ -#define _UTIL_H_ - -/* Genode includes */ -#include -#include -#include -#include - - -namespace Util { - - using namespace Genode; - - using sector_t = Block::sector_t; - - struct Block_io; - - /* - * Wrapper to get suffixed uint64_t values - */ - class Number_of_bytes - { - uint64_t _n; - - public: - - /** - * Default constructor - */ - Number_of_bytes() : _n(0) { } - - /** - * Constructor, to be used implicitly via assignment operator - */ - Number_of_bytes(Genode::uint64_t n) : _n(n) { } - - /** - * Convert number of bytes to 'size_t' value - */ - operator Genode::uint64_t() const { return _n; } - - void print(Output &output) const - { - using Genode::print; - - enum { KB = 1024UL, MB = KB*1024UL, GB = MB*1024UL }; - - if (_n == 0) print(output, 0); - else if (_n % GB == 0) print(output, _n/GB, "G"); - else if (_n % MB == 0) print(output, _n/MB, "M"); - else if (_n % KB == 0) print(output, _n/KB, "K"); - else print(output, _n); - } - }; - - inline size_t ascii_to(const char *s, Number_of_bytes &result) - { - unsigned long res = 0; - - /* convert numeric part of string */ - int i = ascii_to_unsigned(s, res, 0); - - /* handle suffixes */ - if (i > 0) - switch (s[i]) { - case 'G': res *= 1024; - case 'M': res *= 1024; - case 'K': res *= 1024; i++; - default: break; - } - - result = res; - return i; - } -}; - - -/* - * Block_io wraps a Block::Connection for synchronous operations - */ -struct Util::Block_io -{ - struct Io_error : Genode::Exception { }; - - using Packet_descriptor = Block::Packet_descriptor; - - Block::Connection<> &_block; - Packet_descriptor _p; - - /** - * Constructor - * - * \param block reference to underlying Block::Connection - * \param block_size logical block size of the Block::Connection - * \param lba LBA to start access from - * \param count number of LBAs to access - * \param write set type of operation, write if true, read - * if false - * - * \throw Io_error - */ - Block_io(Block::Connection<> &block, size_t block_size, - sector_t lba, size_t count, - bool write = false, void const *data = nullptr, size_t len = 0) - : - _block(block), - _p(_block.alloc_packet(block_size * count), - write ? Packet_descriptor::WRITE - : Packet_descriptor::READ, lba, count) - { - if (write) { - if (data && len) { - void *p = addr(); - Genode::memcpy(p, data, len); - } else { - Genode::error("invalid data for write"); - throw Io_error(); - } - } - - _block.tx()->submit_packet(_p); - _p = _block.tx()->get_acked_packet(); - if (!_p.succeeded()) { - Genode::error("could not ", write ? "write" : "read", - " block-range [", _p.block_number(), ",", - _p.block_number() + count, ")"); - _block.tx()->release_packet(_p); - throw Io_error(); - } - } - - ~Block_io() { _block.tx()->release_packet(_p); } - - template T addr() - { - return reinterpret_cast(_block.tx()->packet_content(_p)); - } -}; - -#endif /* _UTIL_H_ */ diff --git a/repos/gems/src/app/file_vault/README b/repos/gems/src/app/file_vault/README index c1c75fda85..16d0832ad0 100644 --- a/repos/gems/src/app/file_vault/README +++ b/repos/gems/src/app/file_vault/README @@ -1,128 +1,168 @@ - The file vault + The File Vault Martin Stein Warning ~~~~~~~ -The current version of the file vault is not thought for productive use but +The current version of the File Vault is not thought for productive use but for mere demonstrational purpose! Please refrain from storing sensitive data with it! -Brief -~~~~~ +Functional description +~~~~~~~~~~~~~~~~~~~~~~ -The file vault is a graphical front end for creating and controlling a virtual -encrypted block device using Genodes Consistent Block Encrypter (CBE). The -vault also takes care of creating and managing a Trust Anchor for securing -the block device and formatting the block device with the ext2 file system -which is then provided to clients through Genodes File System service. +The File Vault is a front end for creating and controlling a block-encrypted +ext2 file system inside a file (furthermore called encrypted container) using +Genodes Tresor block encryption library and the Rump ext2 driver. That +means it uses a file system back end for the encrypted container file and also +provides a file-system front-end for access to the file system inside the +encrypted container file. +Beside the file system front end, the File Vault also has a dedicated front end +for administrating the encrypted container. Regarding this front end, the File +Vault can be driven in one of two available modes: "menu view" or "config and +report". In the "menu view" mode, the vault is controlled via a graphical +dialog provided through an instance of Genodes Menu View component. In "config +and report" mode, the vault communicates with the user via XML strings by +requesting a ROM session labelled "ui_config" for user input and a Report +session labelled "ui_report" for user output. -Internal structure -~~~~~~~~~~~~~~~~~~ +The file vault doesn't consider runtime modifications to its "normal" +configuration (in contrast to modifications to the UI configuration in "config +and report" mode). This is an example File Vault configuration: -The file vault uses the Sandbox library to spawn child components according to -its needs. It starts, closes or adapts children by re-writing the Sandbox -configuration and listens to the Sandbox state report in order to wait for a -specific child to finish or recognize resource requests. - -One child that is always present is an instance of the Menu View component used -by the vault to display its dialog window. The user input however is received -and handled by the vault itself, which, if necessary, then adapts the -graphical output accordingly by re-writing the Menu View configuration. In -order to correlate input events to GUI changes, the vault always keeps track -of the currently hovered GUI element by listening to the hover report of the -Menu View child. - -Whenever possible, the vault doesn't access the back end file systems itself -but instead spawns helper components like fs_tool or fs_query. This allows the -vault to remain simple and protected against problems during file system -access. - -In general, the implementation of the file vault tries to set the focus on -state-driven decisions. The internal state machine of the vault is divided -into 4 major steps: Setup, Startup, Controls, and Shutdown. - -Setup means creating a new Trust Anchor and CBE device as well as formatting -the CBE device. Startup means bringing up an already existing Trust Anchor -and CBE device for use. Controls means showing the main window that allows -manipulating a running CBE device (snapshot management, rekeying, resizing). -Consequently, the Controls step follows after a successful Setup or Startup -step. From the Controls step, the user can trigger a transition to the Shutdown -step. Shutdown means gracefully terminating the use of a running CBE device and -closing the file vault. - -Each of these major steps is subdivided into smaller steps. For instance, the -startup consists of requesting the user to input the device passphrase, -unlocking the trust anchor, and starting the CBE device driver. Examining all -minor steps would be to much in the context of this document but the class -_File_vault::Main::State_ in _gems/src/app/file_vault/main.cc_ lists them in -very descriptive way. - -When the vault is started, it will first try to read the initial state from -the _/file_vault/state_ file in the back-end file system. There are basically -only two results to this: If the file doesn't exist, the Setup step is startet. -If the file exists, however, it's expected to yield the initial state of the -Startup step indicating that the Setup step has already been done on this back -end during a former run of the file vault. - -Once the CBE device is up and running, the file vault enters the Controls -step. This step has several sub-states, for instance the states of rekeying or -creating a snapshot (_File_vault::Main::Rekeying_state_, -_File_vault::Main::Create_snapshot_state_, ...). This is because each of these -operations can be executed independent from each other and in parallel. In -order to execute the operations, the vault accesses the VFS control interface -of the CBE (the CBE VFS plugin) spawned in a dedicated VFS server child. - -Like with the back-end file systems, the vault doesn't access the CBE VFS -itself when executing a device operation. It rather spawns an fs_tool instance -to write to the file that starts the operation and an fs_query instance to -watch the file that provides the operation progress. - - -Configuration -~~~~~~~~~~~~~ - -The file vault should always have the following configuration: - -! +! +! ! -! -! +! +! ! ! ! -The vault doesn't consider any further user configuration. +The "user_interface" attribute knows the two values "config_and_report" and +"menu_view" with the latter being the default. The verbosity attributes are all +set to "no" by default. If "verbose_state" is set to "yes" the vault will +reflect its internal state at the LOG session. If "verbose_ui_config" is set to +"yes" the vault will reflect the state of the applied UI config at the LOG +session (user passphrases are not exposed to the LOG session). + +The vault currently still requires a directory named "tresor" to be present in its +local VFS. The vault will store a very small file "./file_vault/state" inside +this directory in order to keep track of the state it was terminated in last +time. This is what the tag in the example configuration is for. + +This is an example UI report generated in "config and report" mode: + +! + +For the "version" attribute see the description of the UI configuration format +below. The "state" attribute is a simplified reflection of the internal state +of the vault and can contain one of the following values: + +:invalid: +The File Vault is still determining its internal state. This occurs currently +only on component startup and leads either to the "uninitialized" or the +"locked" state without any user interaction. + +:uninitialized: +There is yet no encrypted container in the file system that the File Vault is +seeing. As soon as the File Vault receives suitable user input for creating a +new encrypted container, it transitions to the "initializing" state. + +:initializing: +The file vault has received suitable user input for creating a new encrypted +container and is in the process of doing so. If successful, the File Vault will +transition to the "unlocked" state. If unsuccessful, the File Vault will +discard the current UI configuration and transition to the "uninitialized" +state. + +:locked: There is an encrypted container in the file system that the File Vault +is seeing but it's not accessible for the user yet. As soon as the File Vault +receives suitable user input for unlocking the encrypted container, it +transitions to the "unlocking" state. + +:unlocking: +The file vault has received suitable user input for unlocking the encrypted +container and is in the process of doing so. If successful, the File Vault will +transition to the "unlocked" state. If unsuccessful, the File Vault will +discard the current UI configuration, wait for 3 seconds, and transition to the +"locked" state. + +:unlocked: +The encrypted container was unlocked and is now accessible via a File System +service provided by the File Vault. As soon as the File Vault receives +user input that is unsuitable for keeping the encrypted container unlocked, +it transitions to the "locking" state. + +:locking: +The file vault has received user input unsuitable for keeping the encrypted +container unlocked and is in the process of locking it. The File Vault will +transition to the "locked" state without any user interaction. + +This is an example UI configuration in "config and report" mode: + +! + +The version attribute can be any string. The vault doesn't use this string +itself but merely adds it to UI reports to allow users identifying the UI +configuration that was active when a report was generated. + +When the File Vault reports to be in the "uninitialized" state, and the UI +configuration contains suitable "passphrase", "client_fs_size" and +"journaling_buf_size" attributes, the File Vault starts initializing a new +encrypted container. The "passphrase" is an arbitrary string and must have at +least 8 characters while "client_fs_size" and "journaling_buf_size" each are a +number of bytes (number with no suffix or suffix K, M, G). Each must denote a +size of 100K at least. + +When the File Vault reports to be in the "locked" state, and the UI config +contains a suitable "passphrase" attribute, the File Vault starts unlocking the +encrypted container. When the File Vault reports to be in the "unlocked" state, +and the UI config does not contain a suitable "passphrase" attribute, the File +Vault starts locking the encrypted container. -Provided service and session requests -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Provided services and session requests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -The vault provides a File System service to the ext2 file system once a CBE -device was successfully created and formatted respectively unlocked. Besides -the common Genode environment sessions, the vault requests one File System -session to a fonts file system, one File System session for the back-end -storage of the Trust Anchor, several File System session for the file system -that holds the CBE image file and the persistent vault data, one Gui session, -several timer sessions and an RM session for the Rump kernel it spawns. +The vault provides a File System service to the ext2 file system once an +encrypted container was successfully created and formatted respectively +unlocked. Besides the common Genode environment sessions, the vault requests +one File System session for the back-end storage of the Trust Anchor, +several File System session to the file system that holds the encrypted +container file and a small amount of File Vault data, several timer sessions +and an RM session for the Rump kernel it spawns. + +Only in "menu view" mode, the File Vault additionally requests one Gui session +and one File System session to a fonts file system. Only in "config and report" +mode, the File Vault additionally requests a ROM session to the UI +configuration and one Report session for UI reports. Further resources ~~~~~~~~~~~~~~~~~ -The _gems/run/file_vault.run_ provides an example on how to manually integrate -the file vault. It can also be used for analyzing and developing the vault - -when targeting native Linux execution even with a persistent storage back-end. -The file vault was also packaged in _gems/recipes/pkg/file_vault_ and can be -deployed in Sculpt via _+ -> depot -> mstein -> Tools -> File Vault_. +The test scripts _gems/recipes/pkg/test-file_vault_config_report_, +_gems/run/file_vault.run_, and_gems/run/file_vault_config_report.run_ +provide examples on how to manually integrate the file vault. The latter can +also be used for analyzing and developing the vault - when targeting native +Linux execution even with a persistent storage back-end. The file vault was +also packaged in _gems/recipes/pkg/file_vault_ and can be deployed in Sculpt +via _+ -> depot -> mstein -> Tools -> File Vault_. Open issues ~~~~~~~~~~~ -* The vault should show the percantage of used and free blocks in the CBE trees +* The vault should show the percentage of used and free blocks in the Tresor trees in order to enable the user to resize or sync to prevent an out-of-resource situation. * Although the Trust Anchor data (private key and superblock hash) can @@ -134,14 +174,14 @@ Open issues the vault only in a serial way (the button only shows up again as soon as the operation is done) creating and discarding snapshots is controlled in a fire-and-forget fashion (the button immediately shows up again). This is - because the CBE VFS yet doesn't fully propagate the completely asynchronous - way of handling requests of the CBE. -* The creation of the CBE image file is done yet in serial inside the vault + because the Tresor VFS yet doesn't fully propagate the completely asynchronous + way of handling requests of the Tresor. +* The creation of the Tresor image file is done yet in serial inside the vault itself which causes the GUI to hang till the image creation is done. * Shrinking the client FS or the journaling buffer is not yet supported. * Creating, discarding, and accessing snapshots isn't supported by now in the - file vault, although the underlying CBE and its VFS plugin have full support. -* The CBE might run into a ressource limit when writing block data or replacing + file vault, although the underlying Tresor and its VFS plugin have full support. +* The Tresor might run into a ressource limit when writing block data or replacing the block encryption key. This is because it doesn't take care yet whether its Free Tree has enough free blocks left for finishing an operation. It will just through an exception in the middle of the operation. This won't affect diff --git a/repos/gems/src/app/file_vault/input.h b/repos/gems/src/app/file_vault/input.h index 3fe598e662..c203713bdb 100644 --- a/repos/gems/src/app/file_vault/input.h +++ b/repos/gems/src/app/file_vault/input.h @@ -135,16 +135,6 @@ class File_vault::Input_passphrase : public Input_single_line public: - bool suitable() const - { - return _length >= 8; - } - - char const *not_suitable_text() const - { - return "Must have at least 8 characters!"; - } - void print(Output &out) const { if (_hide) { diff --git a/repos/gems/src/app/file_vault/main.cc b/repos/gems/src/app/file_vault/main.cc index e20ebd6bda..6158becbb0 100644 --- a/repos/gems/src/app/file_vault/main.cc +++ b/repos/gems/src/app/file_vault/main.cc @@ -1,5 +1,5 @@ /* - * \brief Graphical front end for controlling CBE devices + * \brief Graphical front end for controlling Tresor devices * \author Martin Stein * \author Norman Feske * \date 2021-02-24 @@ -43,9 +43,39 @@ namespace File_vault { enum { SHOW_CONTROLS_SECURITY_USER_PASSPHRASE = 0 }; enum { RENAME_SNAPSHOT_BUFFER_JOURNALING_BUFFER = 1 }; + class Ui_config; class Main; } +struct File_vault::Ui_config +{ + using Version_string = String<80>; + + Version_string const version { }; + Passphrase_string const passphrase { }; + Number_of_bytes const client_fs_size { 0 }; + Number_of_bytes const journaling_buf_size { 0 }; + + Ui_config() { } + + Ui_config(Xml_node const &node, + bool verbose) + : + version { node.attribute_value("version", Version_string { }) }, + passphrase { node.attribute_value("passphrase", Passphrase_string { }) }, + client_fs_size { node.attribute_value("client_fs_size", Number_of_bytes { 0 }) }, + journaling_buf_size { node.attribute_value("journaling_buf_size", Number_of_bytes { 0 }) } + { + if (verbose) + log("ui_config: version \"", version, + "\" passphrase ", passphrase_suitable() ? "<" : " client_fs_size ", client_fs_size, + " journaling_buf_size ", journaling_buf_size); + } + + bool passphrase_suitable() const { return passphrase.length() >= 8; } +}; + class File_vault::Main : private Sandbox::Local_service_base::Wakeup, @@ -58,28 +88,29 @@ class File_vault::Main enum { MIN_CLIENT_FS_SIZE = 100 * 1024, STATE_STRING_CAPACITY = 64, - CBE_BLOCK_SIZE = 4096, + TRESOR_BLOCK_SIZE = 4096, MAIN_FRAME_WIDTH = 46, - CBE_VBD_TREE_NR_OF_LEVELS = 6, - CBE_VBD_TREE_NR_OF_CHILDREN = 64, - CBE_FREE_TREE_NR_OF_LEVELS = 6, - CBE_FREE_TREE_NR_OF_CHILDREN = 64, - CBE_NR_OF_SUPERBLOCKS = 8, + TRESOR_VBD_TREE_NR_OF_LEVELS = 6, + TRESOR_VBD_TREE_NR_OF_CHILDREN = 64, + TRESOR_FREE_TREE_NR_OF_LEVELS = 6, + TRESOR_FREE_TREE_NR_OF_CHILDREN = 64, + TRESOR_NR_OF_SUPERBLOCKS = 8, }; enum class State { INVALID, SETUP_OBTAIN_PARAMETERS, - SETUP_CREATE_CBE_IMAGE_FILE, - SETUP_RUN_CBE_INIT_TRUST_ANCHOR, - SETUP_RUN_CBE_INIT, - SETUP_START_CBE_VFS, - SETUP_FORMAT_CBE, - STARTUP_OBTAIN_PARAMETERS, - STARTUP_RUN_CBE_INIT_TRUST_ANCHOR, - STARTUP_START_CBE_VFS, - STARTUP_DETERMINE_CLIENT_FS_SIZE, + SETUP_CREATE_TRESOR_IMAGE_FILE, + SETUP_RUN_TRESOR_INIT_TRUST_ANCHOR, + SETUP_RUN_TRESOR_INIT, + SETUP_START_TRESOR_VFS, + SETUP_FORMAT_TRESOR, + SETUP_DETERMINE_CLIENT_FS_SIZE, + UNLOCK_OBTAIN_PARAMETERS, + UNLOCK_RUN_TRESOR_INIT_TRUST_ANCHOR, + UNLOCK_START_TRESOR_VFS, + UNLOCK_DETERMINE_CLIENT_FS_SIZE, CONTROLS_ROOT, CONTROLS_SNAPSHOTS, CONTROLS_DIMENSIONS, @@ -89,8 +120,19 @@ class File_vault::Main CONTROLS_SECURITY_BLOCK_ENCRYPTION_KEY, CONTROLS_SECURITY_MASTER_KEY, CONTROLS_SECURITY_USER_PASSPHRASE, - SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE, - SHUTDOWN_WAIT_TILL_DEINIT_REQUEST_IS_DONE + LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR, + LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE + }; + + enum class Reported_state + { + INVALID, + UNINITIALIZED, + INITIALIZING, + LOCKED, + UNLOCKING, + UNLOCKED, + LOCKING }; enum class Setup_obtain_params_hover @@ -116,7 +158,7 @@ class File_vault::Main enum class Controls_root_select { NONE, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_root_hover @@ -125,13 +167,13 @@ class File_vault::Main SNAPSHOTS_EXPAND_BUTTON, DIMENSIONS_BUTTON, SECURITY_EXPAND_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_snapshots_select { NONE, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, CREATE_BUTTON, GENERATION_DISCARD_BUTTON, }; @@ -139,7 +181,7 @@ class File_vault::Main enum class Controls_snapshots_hover { NONE, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, LEAVE_BUTTON, CREATE_BUTTON, GENERATION_LEAVE_BUTTON, @@ -151,7 +193,7 @@ class File_vault::Main NONE, EXPAND_CLIENT_FS_EXPAND_BUTTON, EXPAND_SNAP_BUF_EXPAND_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Dimensions_hover @@ -160,7 +202,7 @@ class File_vault::Main LEAVE_BUTTON, EXPAND_CLIENT_FS_BUTTON, EXPAND_SNAPSHOT_BUF_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Expand_client_fs_select @@ -168,7 +210,7 @@ class File_vault::Main NONE, CONTINGENT_INPUT, START_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Expand_client_fs_hover @@ -177,7 +219,7 @@ class File_vault::Main LEAVE_BUTTON, CONTINGENT_INPUT, START_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Expand_snapshot_buf_select @@ -185,7 +227,7 @@ class File_vault::Main NONE, CONTINGENT_INPUT, START_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Expand_snapshot_buf_hover @@ -194,14 +236,14 @@ class File_vault::Main LEAVE_BUTTON, CONTINGENT_INPUT, START_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_security_block_encryption_key_select { NONE, REPLACE_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_security_block_encryption_key_hover @@ -209,33 +251,33 @@ class File_vault::Main NONE, LEAVE_BUTTON, REPLACE_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_security_master_key_select { NONE, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_security_master_key_hover { NONE, LEAVE_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_security_user_passphrase_select { NONE, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_security_user_passphrase_hover { NONE, LEAVE_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_security_select @@ -244,7 +286,7 @@ class File_vault::Main BLOCK_ENCRYPTION_KEY_EXPAND_BUTTON, MASTER_KEY_EXPAND_BUTTON, USER_PASSPHRASE_EXPAND_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Controls_security_hover @@ -254,7 +296,7 @@ class File_vault::Main BLOCK_ENCRYPTION_KEY_EXPAND_BUTTON, MASTER_KEY_EXPAND_BUTTON, USER_PASSPHRASE_EXPAND_BUTTON, - SHUT_DOWN_BUTTON, + LOCK_BUTTON, }; enum class Resizing_type @@ -267,7 +309,7 @@ class File_vault::Main enum class Resizing_state { INACTIVE, - ADAPT_CBE_IMAGE_SIZE, + ADAPT_TRESOR_IMAGE_SIZE, WAIT_TILL_DEVICE_IS_READY, ISSUE_REQUEST_AT_DEVICE, IN_PROGRESS_AT_DEVICE, @@ -295,6 +337,12 @@ class File_vault::Main ISSUE_REQUEST_AT_DEVICE, }; + enum User_interface + { + MENU_VIEW, + CONFIG_AND_REPORT, + }; + using Report_service = Sandbox::Local_service; using Gui_service = Sandbox::Local_service; using Rom_service = Sandbox::Local_service; @@ -307,31 +355,33 @@ class File_vault::Main State _state { State::INVALID }; Heap _heap { _env.ram(), _env.rm() }; Timer::Connection _timer { _env }; - Attached_rom_dataspace _config { _env, "config" }; - Root_directory _vfs { _env, _heap, _config.xml().sub_node("vfs") }; + Attached_rom_dataspace _config_rom { _env, "config" }; + User_interface _user_interface { _user_interface_from_config(_config_rom.xml()) }; + bool _verbose_state { _config_rom.xml().attribute_value("verbose_state", false) }; + bool _verbose_ui_config { _config_rom.xml().attribute_value("verbose_ui_config", false) }; + Root_directory _vfs { _env, _heap, _config_rom.xml().sub_node("vfs") }; Registry _children { }; Child_state _menu_view { _children, "menu_view", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 200 } }; Child_state _mke2fs { _children, "mke2fs", Ram_quota { 100 * 1024 * 1024 }, Cap_quota { 500 } }; Child_state _resize2fs { _children, "resize2fs", Ram_quota { 100 * 1024 * 1024 }, Cap_quota { 500 } }; - Child_state _cbe_vfs { _children, "cbe_vfs", "vfs", Ram_quota { 64 * 1024 * 1024 }, Cap_quota { 200 } }; - Child_state _cbe_trust_anchor_vfs { _children, "cbe_trust_anchor_vfs", "vfs", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; - Child_state _rump_vfs { _children, "rump_vfs", "vfs", Ram_quota { 16 * 1024 * 1024 }, Cap_quota { 200 } }; - Child_state _sync_to_cbe_vfs_init { _children, "sync_to_cbe_vfs_init", "file_vault-sync_to_cbe_vfs_init", Ram_quota { 8 * 1024 * 1024 }, Cap_quota { 100 } }; + Child_state _tresor_vfs { _children, "tresor_vfs", "vfs", Ram_quota { 64 * 1024 * 1024 }, Cap_quota { 200 } }; + Child_state _tresor_trust_anchor_vfs { _children, "tresor_trust_anchor_vfs", "vfs", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; + Child_state _rump_vfs { _children, "rump_vfs", "vfs", Ram_quota { 32 * 1024 * 1024 }, Cap_quota { 200 } }; + Child_state _sync_to_tresor_vfs_init { _children, "sync_to_tresor_vfs_init", "file_vault-sync_to_tresor_vfs_init", Ram_quota { 8 * 1024 * 1024 }, Cap_quota { 100 } }; Child_state _truncate_file { _children, "truncate_file", "file_vault-truncate_file", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; - Child_state _cbe_vfs_block { _children, "vfs_block", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; + Child_state _tresor_vfs_block { _children, "vfs_block", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; Child_state _fs_query { _children, "fs_query", Ram_quota { 1 * 1024 * 1024 }, Cap_quota { 100 } }; Child_state _image_fs_query { _children, "image_fs_query", "fs_query", Ram_quota { 1 * 1024 * 1024 }, Cap_quota { 100 } }; Child_state _client_fs_fs_query { _children, "client_fs_fs_query", "fs_query", Ram_quota { 1 * 1024 * 1024 }, Cap_quota { 100 } }; - Child_state _cbe_init_trust_anchor { _children, "cbe_init_trust_anchor", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; - Child_state _cbe_image_vfs_block { _children, "vfs_block", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; - Child_state _cbe_init { _children, "cbe_init", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; + Child_state _tresor_init_trust_anchor { _children, "tresor_init_trust_anchor", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; + Child_state _tresor_init { _children, "tresor_init", Ram_quota { 4 * 1024 * 1024 }, Cap_quota { 100 } }; Child_state _snapshots_fs_query { _children, "snapshots_fs_query", "fs_query", Ram_quota { 1 * 1024 * 1024 }, Cap_quota { 100 } }; Child_state _resizing_fs_tool { _children, "resizing_fs_tool", "fs_tool", Ram_quota { 5 * 1024 * 1024 }, Cap_quota { 200 } }; Child_state _resizing_fs_query { _children, "resizing_fs_query", "fs_query", Ram_quota { 1 * 1024 * 1024 }, Cap_quota { 100 } }; Child_state _rekeying_fs_tool { _children, "rekeying_fs_tool", "fs_tool", Ram_quota { 5 * 1024 * 1024 }, Cap_quota { 200 } }; Child_state _rekeying_fs_query { _children, "rekeying_fs_query", "fs_query", Ram_quota { 1 * 1024 * 1024 }, Cap_quota { 100 } }; - Child_state _shut_down_fs_tool { _children, "shut_down_fs_tool", "fs_tool", Ram_quota { 5 * 1024 * 1024 }, Cap_quota { 200 } }; - Child_state _shut_down_fs_query { _children, "shut_down_fs_query", "fs_query", Ram_quota { 1 * 1024 * 1024 }, Cap_quota { 100 } }; + Child_state _lock_fs_tool { _children, "lock_fs_tool", "fs_tool", Ram_quota { 5 * 1024 * 1024 }, Cap_quota { 200 } }; + Child_state _lock_fs_query { _children, "lock_fs_query", "fs_query", Ram_quota { 1 * 1024 * 1024 }, Cap_quota { 100 } }; Child_state _create_snap_fs_tool { _children, "create_snap_fs_tool", "fs_tool", Ram_quota { 5 * 1024 * 1024 }, Cap_quota { 200 } }; Child_state _discard_snap_fs_tool { _children, "discard_snap_fs_tool", "fs_tool", Ram_quota { 5 * 1024 * 1024 }, Cap_quota { 200 } }; Xml_report_handler _fs_query_listing_handler { *this, &Main::_handle_fs_query_listing }; @@ -340,7 +390,7 @@ class File_vault::Main Xml_report_handler _snapshots_fs_query_listing_handler { *this, &Main::_handle_snapshots_fs_query_listing }; Xml_report_handler _resizing_fs_query_listing_handler { *this, &Main::_handle_resizing_fs_query_listing }; Xml_report_handler _rekeying_fs_query_listing_handler { *this, &Main::_handle_rekeying_fs_query_listing }; - Xml_report_handler _shut_down_fs_query_listing_handler { *this, &Main::_handle_shut_down_fs_query_listing }; + Xml_report_handler _lock_fs_query_listing_handler { *this, &Main::_handle_lock_fs_query_listing }; Sandbox _sandbox { _env, *this }; Gui_service _gui_service { _sandbox, *this }; Rom_service _rom_service { _sandbox, *this }; @@ -355,7 +405,7 @@ class File_vault::Main Dynamic_rom_session _dialog { _env.ep(), _env.ram(), _env.rm(), *this }; Input_passphrase _setup_obtain_params_passphrase { }; Input_number_of_bytes _client_fs_size_input { }; - Input_number_of_bytes _snapshot_buf_size_input { }; + Input_number_of_bytes _journaling_buf_size_input { }; Setup_obtain_params_hover _setup_obtain_params_hover { Setup_obtain_params_hover::NONE }; Setup_obtain_params_select _setup_obtain_params_select { Setup_obtain_params_select::PASSPHRASE_INPUT }; Controls_root_hover _controls_root_hover { Controls_root_hover::NONE }; @@ -391,10 +441,64 @@ class File_vault::Main Snapshot_pointer _snapshots_select { }; bool _snapshots_expanded { false }; bool _dimensions_expanded { false }; - Timer::One_shot_timeout
_startup_retry_delay { _timer, *this, &Main::_handle_startup_retry_delay }; - size_t _cbe_image_size { 0 }; + Timer::One_shot_timeout
_unlock_retry_delay { _timer, *this, &Main::_handle_unlock_retry_delay }; + size_t _tresor_image_size { 0 }; size_t _client_fs_size { 0 }; bool _nr_of_clients { 0 }; + Constructible _ui_config_rom { }; + Signal_handler
_ui_config_handler { _env.ep(), *this, &Main::_handle_ui_config }; + Constructible _ui_config { }; + Constructible _ui_report { }; + + static User_interface + _user_interface_from_config(Xml_node const &config) + { + using Ui_string = String<32>; + + Ui_string const ui_str { + config.attribute_value("user_interface", Ui_string { }) }; + + if (ui_str == "config_and_report") + return CONFIG_AND_REPORT; + + return MENU_VIEW; + } + + void _gen_menu_view_start_node_if_required(Xml_generator &xml) const + { + if (_user_interface == MENU_VIEW) + gen_menu_view_start_node(xml, _menu_view); + } + + size_t _ui_client_fs_size() const + { + switch (_user_interface) { + case MENU_VIEW: return _client_fs_size_input.value(); + case CONFIG_AND_REPORT: return _ui_config->client_fs_size; + } + class Exception_1 { }; + throw Exception_1 { }; + } + + size_t _ui_journaling_buf_size() const + { + switch (_user_interface) { + case MENU_VIEW: return _journaling_buf_size_input.value(); + case CONFIG_AND_REPORT: return _ui_config->journaling_buf_size; + } + class Exception_1 { }; + throw Exception_1 { }; + } + + Passphrase_string _ui_setup_obtain_params_passphrase() const + { + switch (_user_interface) { + case MENU_VIEW: return _setup_obtain_params_passphrase.plaintext().string(); + case CONFIG_AND_REPORT: return _ui_config->passphrase; + } + class Exception_1 { }; + throw Exception_1 { }; + } static bool _has_name(Xml_node const &node, Node_name const &name) @@ -402,15 +506,28 @@ class File_vault::Main return node.attribute_value("name", Node_name { }) == name; } - size_t _min_snapshot_buf_size() const + size_t _min_journaling_buf_size() const { - size_t result { _client_fs_size_input.value() >> 8 }; + size_t result { _ui_client_fs_size() >> 8 }; if (result < MIN_CLIENT_FS_SIZE) { result = MIN_CLIENT_FS_SIZE; } return result; } + bool _ui_setup_obtain_params_passphrase_suitable() const + { + return _ui_setup_obtain_params_passphrase().length() >= 8; + } + + bool _ui_setup_obtain_params_suitable() const + { + return + _ui_client_fs_size() >= MIN_CLIENT_FS_SIZE && + _ui_journaling_buf_size() >= _min_journaling_buf_size() && + _ui_setup_obtain_params_passphrase_suitable(); + } + template static void _if_child_exited(Xml_node const &sandbox_state, Child_state const &child_state, @@ -435,7 +552,7 @@ class File_vault::Main Child_state const &child_state, String<64> const &service_name); - void _handle_startup_retry_delay(Duration); + void _handle_unlock_retry_delay(Duration); static State _state_from_string(State_string const &str); @@ -459,26 +576,53 @@ class File_vault::Main void _handle_rekeying_fs_query_listing(Xml_node const &node); - void _handle_shut_down_fs_query_listing(Xml_node const &node); + void _handle_lock_fs_query_listing(Xml_node const &node); void _handle_hover(Xml_node const &node); void _handle_config(); + void _handle_ui_config(); + + void _handle_ui_config_and_report(); + void _handle_state(); void _update_sandbox_config(); - static size_t _cbe_tree_nr_of_leaves(size_t payload_size); + Reported_state _reported_state() const; + + static char const *_reported_state_to_string(Reported_state state); + + void _set_state(State state) + { + Reported_state old_reported_state { _reported_state() }; + _state = state; + Reported_state new_reported_state { _reported_state() }; + + if (_verbose_state) + log("state: ", _state_to_string(_state), " ", old_reported_state != new_reported_state, " ", _user_interface == CONFIG_AND_REPORT); + + if (old_reported_state != new_reported_state && + _user_interface == CONFIG_AND_REPORT) { + + _ui_report->generate([&] (Xml_generator &xml) { + xml.attribute("version", _ui_config->version); + xml.attribute("state", _reported_state_to_string(new_reported_state)); + }); + } + } + + static size_t _tresor_tree_nr_of_leaves(size_t payload_size); static size_t _tree_nr_of_blocks(size_t nr_of_lvls, size_t nr_of_children, size_t nr_of_leafs); - size_t _cbe_size() const; + size_t _tresor_size() const; - static size_t _cbe_nr_of_blocks(size_t nr_of_superblocks, + static size_t _tresor_nr_of_blocks(size_t nr_of_superblocks, size_t nr_of_vbd_lvls, size_t nr_of_vbd_children, size_t nr_of_vbd_leafs, @@ -486,7 +630,7 @@ class File_vault::Main size_t nr_of_ft_children, size_t nr_of_ft_leafs); - static bool cbe_control_file_yields_state_idle(Xml_node const &fs_query_listing, + static bool tresor_control_file_yields_state_idle(Xml_node const &fs_query_listing, char const *file_name); @@ -531,12 +675,20 @@ using namespace File_vault; void Main::_handle_config() { - _config.update(); + _config_rom.update(); _initial_config = false; } -bool Main::cbe_control_file_yields_state_idle(Xml_node const &fs_query_listing, +void Main::_handle_ui_config() +{ + _ui_config_rom->update(); + _ui_config.construct(_ui_config_rom->xml(), _verbose_ui_config); + _handle_ui_config_and_report(); +} + + +bool Main::tresor_control_file_yields_state_idle(Xml_node const &fs_query_listing, char const *file_name) { bool result { false }; @@ -572,11 +724,12 @@ Main::State Main::_state_from_string(State_string const &str) { if (str == "invalid") { return State::INVALID; } if (str == "setup_obtain_parameters") { return State::SETUP_OBTAIN_PARAMETERS; } - if (str == "setup_run_cbe_init_trust_anchor") { return State::SETUP_RUN_CBE_INIT_TRUST_ANCHOR; } - if (str == "setup_create_cbe_image_file") { return State::SETUP_CREATE_CBE_IMAGE_FILE; } - if (str == "setup_run_cbe_init") { return State::SETUP_RUN_CBE_INIT; } - if (str == "setup_start_cbe_vfs") { return State::SETUP_START_CBE_VFS; } - if (str == "setup_format_cbe") { return State::SETUP_FORMAT_CBE; } + if (str == "setup_run_tresor_init_trust_anchor") { return State::SETUP_RUN_TRESOR_INIT_TRUST_ANCHOR; } + if (str == "setup_create_tresor_image_file") { return State::SETUP_CREATE_TRESOR_IMAGE_FILE; } + if (str == "setup_run_tresor_init") { return State::SETUP_RUN_TRESOR_INIT; } + if (str == "setup_start_tresor_vfs") { return State::SETUP_START_TRESOR_VFS; } + if (str == "setup_format_tresor") { return State::SETUP_FORMAT_TRESOR; } + if (str == "setup_determine_client_fs_size") { return State::SETUP_DETERMINE_CLIENT_FS_SIZE; } if (str == "controls_root") { return State::CONTROLS_ROOT; } if (str == "controls_snapshots") { return State::CONTROLS_SNAPSHOTS; } if (str == "controls_dimensions") { return State::CONTROLS_DIMENSIONS; } @@ -586,12 +739,12 @@ Main::State Main::_state_from_string(State_string const &str) if (str == "controls_security_block_encryption_key") { return State::CONTROLS_SECURITY_BLOCK_ENCRYPTION_KEY; } if (str == "controls_security_master_key") { return State::CONTROLS_SECURITY_MASTER_KEY; } if (str == "controls_security_user_passphrase") { return State::CONTROLS_SECURITY_USER_PASSPHRASE; } - if (str == "startup_obtain_parameters") { return State::STARTUP_OBTAIN_PARAMETERS; } - if (str == "startup_run_cbe_init_trust_anchor") { return State::STARTUP_RUN_CBE_INIT_TRUST_ANCHOR; } - if (str == "startup_start_cbe_vfs") { return State::STARTUP_START_CBE_VFS; } - if (str == "startup_determine_client_fs_size") { return State::STARTUP_DETERMINE_CLIENT_FS_SIZE; } - if (str == "shutdown_issue_deinit_request_at_cbe") { return State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; } - if (str == "shutdown_wait_till_deinit_request_is_done") { return State::SHUTDOWN_WAIT_TILL_DEINIT_REQUEST_IS_DONE; } + if (str == "unlock_obtain_parameters") { return State::UNLOCK_OBTAIN_PARAMETERS; } + if (str == "unlock_run_tresor_init_trust_anchor") { return State::UNLOCK_RUN_TRESOR_INIT_TRUST_ANCHOR; } + if (str == "unlock_start_tresor_vfs") { return State::UNLOCK_START_TRESOR_VFS; } + if (str == "unlock_determine_client_fs_size") { return State::UNLOCK_DETERMINE_CLIENT_FS_SIZE; } + if (str == "lock_issue_deinit_request_at_tresor") { return State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR; } + if (str == "lock_wait_till_deinit_request_is_done") { return State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE; } class Invalid_state_string { }; throw Invalid_state_string { }; } @@ -600,28 +753,77 @@ Main::State Main::_state_from_string(State_string const &str) Main::State_string Main::_state_to_string(State state) { switch (state) { - case State::INVALID: return "invalid"; - case State::SETUP_OBTAIN_PARAMETERS: return "setup_obtain_parameters"; - case State::SETUP_RUN_CBE_INIT_TRUST_ANCHOR: return "setup_run_cbe_init_trust_anchor"; - case State::SETUP_CREATE_CBE_IMAGE_FILE: return "setup_create_cbe_image_file"; - case State::SETUP_RUN_CBE_INIT: return "setup_run_cbe_init"; - case State::SETUP_START_CBE_VFS: return "setup_start_cbe_vfs"; - case State::SETUP_FORMAT_CBE: return "setup_format_cbe"; - case State::CONTROLS_ROOT: return "controls_root"; - case State::CONTROLS_SNAPSHOTS: return "controls_snapshots"; - case State::CONTROLS_DIMENSIONS: return "controls_dimensions"; - case State::CONTROLS_EXPAND_CLIENT_FS: return "controls_expand_client_fs"; - case State::CONTROLS_EXPAND_SNAPSHOT_BUF: return "controls_expand_snapshot_buf"; - case State::CONTROLS_SECURITY: return "controls_security"; - case State::CONTROLS_SECURITY_BLOCK_ENCRYPTION_KEY: return "controls_security_block_encryption_key"; - case State::CONTROLS_SECURITY_MASTER_KEY: return "controls_security_master_key"; - case State::CONTROLS_SECURITY_USER_PASSPHRASE: return "controls_security_user_passphrase"; - case State::STARTUP_OBTAIN_PARAMETERS: return "startup_obtain_parameters"; - case State::STARTUP_RUN_CBE_INIT_TRUST_ANCHOR: return "startup_run_cbe_init_trust_anchor"; - case State::STARTUP_START_CBE_VFS: return "startup_start_cbe_vfs"; - case State::STARTUP_DETERMINE_CLIENT_FS_SIZE: return "startup_determine_client_fs_size"; - case State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE: return "shutdown_issue_deinit_request_at_cbe"; - case State::SHUTDOWN_WAIT_TILL_DEINIT_REQUEST_IS_DONE: return "shutdown_wait_till_deinit_request_is_done"; + case State::INVALID: return "invalid"; + case State::SETUP_OBTAIN_PARAMETERS: return "setup_obtain_parameters"; + case State::SETUP_RUN_TRESOR_INIT_TRUST_ANCHOR: return "setup_run_tresor_init_trust_anchor"; + case State::SETUP_CREATE_TRESOR_IMAGE_FILE: return "setup_create_tresor_image_file"; + case State::SETUP_RUN_TRESOR_INIT: return "setup_run_tresor_init"; + case State::SETUP_START_TRESOR_VFS: return "setup_start_tresor_vfs"; + case State::SETUP_FORMAT_TRESOR: return "setup_format_tresor"; + case State::SETUP_DETERMINE_CLIENT_FS_SIZE: return "setup_determine_client_fs_size"; + case State::CONTROLS_ROOT: return "controls_root"; + case State::CONTROLS_SNAPSHOTS: return "controls_snapshots"; + case State::CONTROLS_DIMENSIONS: return "controls_dimensions"; + case State::CONTROLS_EXPAND_CLIENT_FS: return "controls_expand_client_fs"; + case State::CONTROLS_EXPAND_SNAPSHOT_BUF: return "controls_expand_snapshot_buf"; + case State::CONTROLS_SECURITY: return "controls_security"; + case State::CONTROLS_SECURITY_BLOCK_ENCRYPTION_KEY: return "controls_security_block_encryption_key"; + case State::CONTROLS_SECURITY_MASTER_KEY: return "controls_security_master_key"; + case State::CONTROLS_SECURITY_USER_PASSPHRASE: return "controls_security_user_passphrase"; + case State::UNLOCK_OBTAIN_PARAMETERS: return "unlock_obtain_parameters"; + case State::UNLOCK_RUN_TRESOR_INIT_TRUST_ANCHOR: return "unlock_run_tresor_init_trust_anchor"; + case State::UNLOCK_START_TRESOR_VFS: return "unlock_start_tresor_vfs"; + case State::UNLOCK_DETERMINE_CLIENT_FS_SIZE: return "unlock_determine_client_fs_size"; + case State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR: return "lock_issue_deinit_request_at_tresor"; + case State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE: return "lock_wait_till_deinit_request_is_done"; + } + class Invalid_state { }; + throw Invalid_state { }; +} + + +char const *Main::_reported_state_to_string(Reported_state state) +{ + switch (state) { + case Reported_state::INVALID: return "invalid"; + case Reported_state::UNINITIALIZED: return "uninitialized"; + case Reported_state::INITIALIZING: return "initializing"; + case Reported_state::LOCKED: return "locked"; + case Reported_state::UNLOCKING: return "unlocking"; + case Reported_state::UNLOCKED: return "unlocked"; + case Reported_state::LOCKING: return "locking"; + } + class Invalid_state { }; + throw Invalid_state { }; +} + + +Main::Reported_state Main::_reported_state() const +{ + switch (_state) { + case State::INVALID: return Reported_state::INVALID; + case State::SETUP_OBTAIN_PARAMETERS: return Reported_state::UNINITIALIZED; + case State::SETUP_CREATE_TRESOR_IMAGE_FILE: return Reported_state::INITIALIZING; + case State::SETUP_RUN_TRESOR_INIT_TRUST_ANCHOR: return Reported_state::INITIALIZING; + case State::SETUP_RUN_TRESOR_INIT: return Reported_state::INITIALIZING; + case State::SETUP_START_TRESOR_VFS: return Reported_state::INITIALIZING; + case State::SETUP_FORMAT_TRESOR: return Reported_state::INITIALIZING; + case State::SETUP_DETERMINE_CLIENT_FS_SIZE: return Reported_state::INITIALIZING; + case State::CONTROLS_ROOT: return Reported_state::UNLOCKED; + case State::CONTROLS_SNAPSHOTS: return Reported_state::UNLOCKED; + case State::CONTROLS_DIMENSIONS: return Reported_state::UNLOCKED; + case State::CONTROLS_EXPAND_CLIENT_FS: return Reported_state::UNLOCKED; + case State::CONTROLS_EXPAND_SNAPSHOT_BUF: return Reported_state::UNLOCKED; + case State::CONTROLS_SECURITY: return Reported_state::UNLOCKED; + case State::CONTROLS_SECURITY_BLOCK_ENCRYPTION_KEY: return Reported_state::UNLOCKED; + case State::CONTROLS_SECURITY_MASTER_KEY: return Reported_state::UNLOCKED; + case State::CONTROLS_SECURITY_USER_PASSPHRASE: return Reported_state::UNLOCKED; + case State::UNLOCK_OBTAIN_PARAMETERS: return Reported_state::LOCKED; + case State::UNLOCK_RUN_TRESOR_INIT_TRUST_ANCHOR: return Reported_state::UNLOCKING; + case State::UNLOCK_START_TRESOR_VFS: return Reported_state::UNLOCKING; + case State::UNLOCK_DETERMINE_CLIENT_FS_SIZE: return Reported_state::UNLOCKING; + case State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR: return Reported_state::LOCKING; + case State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE: return Reported_state::LOCKING; } class Invalid_state { }; throw Invalid_state { }; @@ -647,7 +849,7 @@ void Main::_write_to_state_file(State state) { bool write_error = false; try { - New_file new_file(_vfs, Directory::Path("/cbe/file_vault/state")); + New_file new_file(_vfs, Directory::Path("/tresor/file_vault/state")); auto write = [&] (char const *str) { switch (new_file.append(str, strlen(str))) { @@ -693,7 +895,7 @@ void Main::_handle_resizing_fs_query_listing(Xml_node const &node) switch (_resizing_state) { case Resizing_state::WAIT_TILL_DEVICE_IS_READY: - if (cbe_control_file_yields_state_idle(node, "extend")) { + if (tresor_control_file_yields_state_idle(node, "extend_progress")) { _resizing_state = Resizing_state::ISSUE_REQUEST_AT_DEVICE; Signal_transmitter(_state_handler).submit(); @@ -702,7 +904,7 @@ void Main::_handle_resizing_fs_query_listing(Xml_node const &node) case Resizing_state::IN_PROGRESS_AT_DEVICE: - if (cbe_control_file_yields_state_idle(node, "extend")) { + if (tresor_control_file_yields_state_idle(node, "extend_progress")) { switch (_resizing_type) { case Resizing_type::EXPAND_CLIENT_FS: @@ -740,14 +942,17 @@ void Main::_handle_resizing_fs_query_listing(Xml_node const &node) } -void Main::_handle_shut_down_fs_query_listing(Xml_node const &node) +void Main::_handle_lock_fs_query_listing(Xml_node const &node) { switch (_state) { - case State::SHUTDOWN_WAIT_TILL_DEINIT_REQUEST_IS_DONE: + case State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE: - if (cbe_control_file_yields_state_idle(node, "deinitialize")) { + if (tresor_control_file_yields_state_idle(node, "deinitialize")) { - _env.parent().exit(0); + _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(); } break; @@ -774,7 +979,7 @@ void Main::_handle_rekeying_fs_query_listing(Xml_node const &node) switch (_rekeying_state) { case Rekeying_state::WAIT_TILL_DEVICE_IS_READY: - if (cbe_control_file_yields_state_idle(node, "rekey")) { + if (tresor_control_file_yields_state_idle(node, "rekey_progress")) { _rekeying_state = Rekeying_state::ISSUE_REQUEST_AT_DEVICE; Signal_transmitter(_state_handler).submit(); @@ -783,7 +988,7 @@ void Main::_handle_rekeying_fs_query_listing(Xml_node const &node) case Rekeying_state::IN_PROGRESS_AT_DEVICE: - if (cbe_control_file_yields_state_idle(node, "rekey")) { + if (tresor_control_file_yields_state_idle(node, "rekey_progress")) { _rekeying_state = Rekeying_state::INACTIVE; Signal_transmitter(_state_handler).submit(); @@ -902,13 +1107,13 @@ void Main::_handle_fs_query_listing(Xml_node const &node) switch (state) { case State::INVALID: - _state = State::SETUP_OBTAIN_PARAMETERS; + _set_state(State::SETUP_OBTAIN_PARAMETERS); Signal_transmitter(_state_handler).submit(); break; - case State::STARTUP_OBTAIN_PARAMETERS: + case State::UNLOCK_OBTAIN_PARAMETERS: - _state = State::STARTUP_OBTAIN_PARAMETERS; + _set_state(State::UNLOCK_OBTAIN_PARAMETERS); Signal_transmitter(_state_handler).submit(); break; @@ -929,7 +1134,8 @@ void Main::_handle_fs_query_listing(Xml_node const &node) void Main::_handle_client_fs_fs_query_listing(Xml_node const &node) { switch (_state) { - case State::STARTUP_DETERMINE_CLIENT_FS_SIZE: + case State::SETUP_DETERMINE_CLIENT_FS_SIZE: + case State::UNLOCK_DETERMINE_CLIENT_FS_SIZE: node.with_optional_sub_node("dir", [&] (Xml_node const &node_0) { node_0.with_optional_sub_node("file", [&] (Xml_node const &node_1) { @@ -937,7 +1143,7 @@ void Main::_handle_client_fs_fs_query_listing(Xml_node const &node) if (_has_name(node_1, "data")) { _client_fs_size = node_1.attribute_value("size", (size_t)0); - _state = State::CONTROLS_ROOT; + _set_state(State::CONTROLS_ROOT); Signal_transmitter(_state_handler).submit(); } }); @@ -1012,14 +1218,14 @@ void Main::_handle_image_fs_query_listing(Xml_node const &node) size_t size { 0 }; node.with_optional_sub_node("dir", [&] (Xml_node const &node_0) { node_0.with_optional_sub_node("file", [&] (Xml_node const &node_1) { - if (_has_name(node_1, "cbe.img")) { + if (_has_name(node_1, "tresor.img")) { size = node_1.attribute_value("size", (size_t)0); } }); }); - if (_cbe_image_size != size) { + if (_tresor_image_size != size) { - _cbe_image_size = size; + _tresor_image_size = size; update_dialog = true; } break; @@ -1037,7 +1243,59 @@ void Main::_handle_image_fs_query_listing(Xml_node const &node) void Main::_handle_state() { _update_sandbox_config(); - _dialog.trigger_update(); + + switch (_user_interface) { + case MENU_VIEW: _dialog.trigger_update(); break; + case CONFIG_AND_REPORT: _handle_ui_config_and_report(); break; + } +} + + +void Main::_handle_ui_config_and_report() +{ + bool update_sandbox_config { false }; + + switch (_state) { + case State::SETUP_OBTAIN_PARAMETERS: + + if(_ui_setup_obtain_params_suitable()) { + + _set_state(State::SETUP_CREATE_TRESOR_IMAGE_FILE); + update_sandbox_config = true; + } + break; + + case State::UNLOCK_OBTAIN_PARAMETERS: + + if (_ui_setup_obtain_params_passphrase_suitable()) { + + _set_state(State::UNLOCK_RUN_TRESOR_INIT_TRUST_ANCHOR); + update_sandbox_config = true; + } + break; + + case State::CONTROLS_ROOT: + case State::CONTROLS_SNAPSHOTS: + case State::CONTROLS_DIMENSIONS: + case State::CONTROLS_EXPAND_CLIENT_FS: + case State::CONTROLS_EXPAND_SNAPSHOT_BUF: + case State::CONTROLS_SECURITY: + case State::CONTROLS_SECURITY_BLOCK_ENCRYPTION_KEY: + case State::CONTROLS_SECURITY_MASTER_KEY: + case State::CONTROLS_SECURITY_USER_PASSPHRASE: + + if (!_ui_setup_obtain_params_passphrase_suitable()) { + + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); + update_sandbox_config = true; + } + break; + + default: break; + } + if (update_sandbox_config) { + _update_sandbox_config(); + } } @@ -1046,9 +1304,17 @@ Main::Main(Env &env) Xml_producer { "dialog" }, _env { env } { - _config.sigh(_config_handler); + _config_rom.sigh(_config_handler); _handle_config(); _update_sandbox_config(); + + if (_user_interface == CONFIG_AND_REPORT) { + _ui_config_rom.construct(_env, "ui_config"); + _ui_config_rom->sigh(_ui_config_handler); + _ui_report.construct(_env, "ui_report", "ui_report"); + _handle_ui_config(); + _set_state(State::INVALID); + } } @@ -1097,13 +1363,13 @@ bool File_vault::Main::_child_succeeded(Xml_node const &sandbox_state, return false; } -void File_vault::Main::_handle_startup_retry_delay(Duration) +void File_vault::Main::_handle_unlock_retry_delay(Duration) { - _state = State::STARTUP_OBTAIN_PARAMETERS; + _set_state(State::UNLOCK_OBTAIN_PARAMETERS); + _ui_config.construct(); _setup_obtain_params_passphrase = Input_passphrase { }; _setup_obtain_params_select = Setup_obtain_params_select::PASSPHRASE_INPUT; - _dialog.trigger_update(); - _update_sandbox_config(); + Signal_transmitter(_state_handler).submit(); } @@ -1121,79 +1387,79 @@ void File_vault::Main::handle_sandbox_state() sandbox_state.with_xml_node([&] (Xml_node const &sandbox_state) { switch (_state) { - case State::SETUP_RUN_CBE_INIT_TRUST_ANCHOR: + case State::SETUP_RUN_TRESOR_INIT_TRUST_ANCHOR: - if (_child_succeeded(sandbox_state, _cbe_init_trust_anchor)) { + if (_child_succeeded(sandbox_state, _tresor_init_trust_anchor)) { - _state = State::SETUP_RUN_CBE_INIT; + _set_state(State::SETUP_RUN_TRESOR_INIT); update_dialog = true; update_sandbox = true; } break; - case State::SETUP_CREATE_CBE_IMAGE_FILE: + case State::SETUP_CREATE_TRESOR_IMAGE_FILE: if (_child_succeeded(sandbox_state, _truncate_file)) { - _state = State::SETUP_RUN_CBE_INIT_TRUST_ANCHOR; + _set_state(State::SETUP_RUN_TRESOR_INIT_TRUST_ANCHOR); update_dialog = true; update_sandbox = true; } break; - case State::STARTUP_RUN_CBE_INIT_TRUST_ANCHOR: + case State::UNLOCK_RUN_TRESOR_INIT_TRUST_ANCHOR: - _if_child_exited(sandbox_state, _cbe_init_trust_anchor, [&] (int exit_code) { + _if_child_exited(sandbox_state, _tresor_init_trust_anchor, [&] (int exit_code) { if (exit_code == 0) { - _state = State::STARTUP_START_CBE_VFS; + _set_state(State::UNLOCK_START_TRESOR_VFS); update_dialog = true; update_sandbox = true; } else { - _startup_retry_delay.schedule(Microseconds { 3000000 }); + _unlock_retry_delay.schedule(Microseconds { 3000000 }); } }); break; - case State::SETUP_RUN_CBE_INIT: + case State::SETUP_RUN_TRESOR_INIT: - if (_child_succeeded(sandbox_state, _cbe_init)) { + if (_child_succeeded(sandbox_state, _tresor_init)) { - _state = State::SETUP_START_CBE_VFS; + _set_state(State::SETUP_START_TRESOR_VFS); update_dialog = true; update_sandbox = true; } break; - case State::SETUP_START_CBE_VFS: + case State::SETUP_START_TRESOR_VFS: - if (_child_succeeded(sandbox_state, _sync_to_cbe_vfs_init)) { + if (_child_succeeded(sandbox_state, _sync_to_tresor_vfs_init)) { - _state = State::SETUP_FORMAT_CBE; + _set_state(State::SETUP_FORMAT_TRESOR); update_dialog = true; update_sandbox = true; } break; - case State::STARTUP_START_CBE_VFS: + case State::UNLOCK_START_TRESOR_VFS: - if (_child_succeeded(sandbox_state, _sync_to_cbe_vfs_init)) { + if (_child_succeeded(sandbox_state, _sync_to_tresor_vfs_init)) { - _state = State::STARTUP_DETERMINE_CLIENT_FS_SIZE; + _set_state(State::UNLOCK_DETERMINE_CLIENT_FS_SIZE); update_dialog = true; update_sandbox = true; } break; - case State::SETUP_FORMAT_CBE: + case State::SETUP_FORMAT_TRESOR: if (_child_succeeded(sandbox_state, _mke2fs)) { - _write_to_state_file(State::STARTUP_OBTAIN_PARAMETERS); - _state = State::STARTUP_DETERMINE_CLIENT_FS_SIZE; + _write_to_state_file(State::UNLOCK_OBTAIN_PARAMETERS); + _set_state(State::SETUP_DETERMINE_CLIENT_FS_SIZE); update_dialog = true; update_sandbox = true; } @@ -1217,7 +1483,7 @@ void File_vault::Main::handle_sandbox_state() sandbox_state, _rump_vfs, "File_system"); } switch (_resizing_state) { - case Resizing_state::ADAPT_CBE_IMAGE_SIZE: + case Resizing_state::ADAPT_TRESOR_IMAGE_SIZE: if (_child_succeeded(sandbox_state, _truncate_file)) { @@ -1303,11 +1569,11 @@ void File_vault::Main::handle_sandbox_state() break; - case State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE: + case State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR: - if (_child_succeeded(sandbox_state, _shut_down_fs_tool)) { + if (_child_succeeded(sandbox_state, _lock_fs_tool)) { - _state = State::SHUTDOWN_WAIT_TILL_DEINIT_REQUEST_IS_DONE; + _set_state(State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE); update_dialog = true; update_sandbox = true; } @@ -1362,7 +1628,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) _setup_obtain_params_hover == Setup_obtain_params_hover::PASSPHRASE_SHOW_HIDE_BUTTON, _setup_obtain_params_select == Setup_obtain_params_select::PASSPHRASE_SHOW_HIDE_BUTTON); - if (!_setup_obtain_params_passphrase.suitable()) { + if (!_ui_setup_obtain_params_passphrase_suitable()) { gen_start_button = false; gen_info_line(xml, "info_1", "Must have at least 8 characters"); @@ -1373,7 +1639,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) _client_fs_size_input, _setup_obtain_params_select == Setup_obtain_params_select::CLIENT_FS_SIZE_INPUT); - if (_client_fs_size_input.value() < MIN_CLIENT_FS_SIZE) { + if (_ui_client_fs_size() < MIN_CLIENT_FS_SIZE) { gen_image_size_info = false; gen_start_button = false; @@ -1389,24 +1655,24 @@ void File_vault::Main::produce_xml(Xml_generator &xml) RENAME_SNAPSHOT_BUFFER_JOURNALING_BUFFER ? "Journaling buffer size" : "Snapshot buffer size", - _snapshot_buf_size_input, + _journaling_buf_size_input, _setup_obtain_params_select == Setup_obtain_params_select::SNAPSHOT_BUFFER_SIZE_INPUT); - if (_snapshot_buf_size_input.value() < _min_snapshot_buf_size()) { + if (_ui_journaling_buf_size() < _min_journaling_buf_size()) { gen_image_size_info = false; gen_start_button = false; gen_info_line(xml, "info_3", String<128> { "Must be at least ", - Number_of_bytes { _min_snapshot_buf_size() } }.string()); + Number_of_bytes { _min_journaling_buf_size() } }.string()); } if (gen_image_size_info) { gen_info_line(xml, "pad_3", ""); gen_info_line( xml, "info_4", - String<256> { "Image size: ", Capacity { _cbe_size() }}.string()); + String<256> { "Image size: ", Capacity { _tresor_size() }}.string()); } gen_info_line(xml, "pad_4", ""); if (gen_start_button) { @@ -1419,7 +1685,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); break; - case State::STARTUP_OBTAIN_PARAMETERS: + case State::UNLOCK_OBTAIN_PARAMETERS: gen_main_frame(xml, "1", MAIN_FRAME_WIDTH, [&] (Xml_generator &xml) { @@ -1431,7 +1697,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) _setup_obtain_params_hover == Setup_obtain_params_hover::PASSPHRASE_SHOW_HIDE_BUTTON, _setup_obtain_params_select == Setup_obtain_params_select::PASSPHRASE_SHOW_HIDE_BUTTON); - if (!_setup_obtain_params_passphrase.suitable()) { + if (!_ui_setup_obtain_params_passphrase_suitable()) { gen_start_button = false; } @@ -1439,21 +1705,22 @@ void File_vault::Main::produce_xml(Xml_generator &xml) if (gen_start_button) { gen_action_button_at_bottom( - xml, "ok", "Start", + xml, "ok", "Unlock", _setup_obtain_params_hover == Setup_obtain_params_hover::START_BUTTON, _setup_obtain_params_select == Setup_obtain_params_select::START_BUTTON); } }); break; - case State::SETUP_RUN_CBE_INIT_TRUST_ANCHOR: - case State::SETUP_CREATE_CBE_IMAGE_FILE: - case State::SETUP_RUN_CBE_INIT: - case State::SETUP_START_CBE_VFS: - case State::SETUP_FORMAT_CBE: - case State::STARTUP_RUN_CBE_INIT_TRUST_ANCHOR: - case State::STARTUP_START_CBE_VFS: - case State::STARTUP_DETERMINE_CLIENT_FS_SIZE: + case State::SETUP_RUN_TRESOR_INIT_TRUST_ANCHOR: + case State::SETUP_CREATE_TRESOR_IMAGE_FILE: + case State::SETUP_RUN_TRESOR_INIT: + case State::SETUP_START_TRESOR_VFS: + case State::SETUP_FORMAT_TRESOR: + case State::SETUP_DETERMINE_CLIENT_FS_SIZE: + case State::UNLOCK_RUN_TRESOR_INIT_TRUST_ANCHOR: + case State::UNLOCK_START_TRESOR_VFS: + case State::UNLOCK_DETERMINE_CLIENT_FS_SIZE: gen_info_frame(xml, "1", "Please wait...", MAIN_FRAME_WIDTH); break; @@ -1482,9 +1749,9 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); }); gen_global_controls( - xml, MAIN_FRAME_WIDTH, _cbe_image_size, _client_fs_size, _nr_of_clients, - _controls_root_hover == Controls_root_hover::SHUT_DOWN_BUTTON, - _controls_root_select == Controls_root_select::SHUT_DOWN_BUTTON); + xml, MAIN_FRAME_WIDTH, _tresor_image_size, _client_fs_size, _nr_of_clients, + _controls_root_hover == Controls_root_hover::LOCK_BUTTON, + _controls_root_select == Controls_root_select::LOCK_BUTTON); }); break; @@ -1574,9 +1841,9 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); }); gen_global_controls( - xml, MAIN_FRAME_WIDTH, _cbe_image_size, _client_fs_size, _nr_of_clients, - _controls_snapshots_hover == Controls_snapshots_hover::SHUT_DOWN_BUTTON, - _controls_snapshots_select == Controls_snapshots_select::SHUT_DOWN_BUTTON); + xml, MAIN_FRAME_WIDTH, _tresor_image_size, _client_fs_size, _nr_of_clients, + _controls_snapshots_hover == Controls_snapshots_hover::LOCK_BUTTON, + _controls_snapshots_select == Controls_snapshots_select::LOCK_BUTTON); }); break; @@ -1605,9 +1872,9 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); }); gen_global_controls( - xml, MAIN_FRAME_WIDTH, _cbe_image_size, _client_fs_size, _nr_of_clients, - _dimensions_hover == Dimensions_hover::SHUT_DOWN_BUTTON, - _dimensions_select == Dimensions_select::SHUT_DOWN_BUTTON); + xml, MAIN_FRAME_WIDTH, _tresor_image_size, _client_fs_size, _nr_of_clients, + _dimensions_hover == Dimensions_hover::LOCK_BUTTON, + _dimensions_select == Dimensions_select::LOCK_BUTTON); }); break; @@ -1645,7 +1912,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) _expand_client_fs_contingent.value() }; size_t const effective_bytes { - bytes - (bytes % CBE_BLOCK_SIZE) }; + bytes - (bytes % TRESOR_BLOCK_SIZE) }; if (effective_bytes > 0) { @@ -1653,7 +1920,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) xml, "inf_2", String<128> { "New image size: ", - Capacity { _cbe_image_size + effective_bytes } + Capacity { _tresor_image_size + effective_bytes } }.string()); } else { @@ -1661,7 +1928,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) gen_info_line(xml, "info_1", String<128> { "Must be at least ", - Number_of_bytes { CBE_BLOCK_SIZE } }.string()); + Number_of_bytes { TRESOR_BLOCK_SIZE } }.string()); gen_start_button = false; } @@ -1676,7 +1943,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) } break; } - case Resizing_state::ADAPT_CBE_IMAGE_SIZE: + case Resizing_state::ADAPT_TRESOR_IMAGE_SIZE: case Resizing_state::WAIT_TILL_DEVICE_IS_READY: case Resizing_state::ISSUE_REQUEST_AT_DEVICE: case Resizing_state::IN_PROGRESS_AT_DEVICE: @@ -1691,9 +1958,9 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); }); gen_global_controls( - xml, MAIN_FRAME_WIDTH, _cbe_image_size, _client_fs_size, _nr_of_clients, - _expand_client_fs_hover == Expand_client_fs_hover::SHUT_DOWN_BUTTON, - _expand_client_fs_select == Expand_client_fs_select::SHUT_DOWN_BUTTON); + xml, MAIN_FRAME_WIDTH, _tresor_image_size, _client_fs_size, _nr_of_clients, + _expand_client_fs_hover == Expand_client_fs_hover::LOCK_BUTTON, + _expand_client_fs_select == Expand_client_fs_select::LOCK_BUTTON); }); break; @@ -1728,7 +1995,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) _expand_snapshot_buf_contingent.value() }; size_t const effective_bytes { - bytes - (bytes % CBE_BLOCK_SIZE) }; + bytes - (bytes % TRESOR_BLOCK_SIZE) }; if (effective_bytes > 0) { @@ -1736,7 +2003,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) xml, "inf_2", String<128> { "New image size: ", - Capacity { _cbe_image_size + effective_bytes } + Capacity { _tresor_image_size + effective_bytes } }.string()); } else { @@ -1745,7 +2012,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) gen_info_line(xml, "info_1", String<128> { "Must be at least ", - Number_of_bytes { CBE_BLOCK_SIZE } }.string()); + Number_of_bytes { TRESOR_BLOCK_SIZE } }.string()); } gen_info_line(xml, "pad_2", ""); if (gen_start_button) { @@ -1757,7 +2024,7 @@ void File_vault::Main::produce_xml(Xml_generator &xml) } break; } - case Resizing_state::ADAPT_CBE_IMAGE_SIZE: + case Resizing_state::ADAPT_TRESOR_IMAGE_SIZE: case Resizing_state::WAIT_TILL_DEVICE_IS_READY: case Resizing_state::ISSUE_REQUEST_AT_DEVICE: case Resizing_state::IN_PROGRESS_AT_DEVICE: @@ -1772,9 +2039,9 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); }); gen_global_controls( - xml, MAIN_FRAME_WIDTH, _cbe_image_size, _client_fs_size, _nr_of_clients, - _expand_snapshot_buf_hover == Expand_snapshot_buf_hover::SHUT_DOWN_BUTTON, - _expand_snapshot_buf_select == Expand_snapshot_buf_select::SHUT_DOWN_BUTTON); + xml, MAIN_FRAME_WIDTH, _tresor_image_size, _client_fs_size, _nr_of_clients, + _expand_snapshot_buf_hover == Expand_snapshot_buf_hover::LOCK_BUTTON, + _expand_snapshot_buf_select == Expand_snapshot_buf_select::LOCK_BUTTON); }); break; @@ -1808,9 +2075,9 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); }); gen_global_controls( - xml, MAIN_FRAME_WIDTH, _cbe_image_size, _client_fs_size, _nr_of_clients, - _controls_security_hover == Controls_security_hover::SHUT_DOWN_BUTTON, - _controls_security_select == Controls_security_select::SHUT_DOWN_BUTTON); + xml, MAIN_FRAME_WIDTH, _tresor_image_size, _client_fs_size, _nr_of_clients, + _controls_security_hover == Controls_security_hover::LOCK_BUTTON, + _controls_security_select == Controls_security_select::LOCK_BUTTON); }); break; @@ -1847,9 +2114,9 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); }); gen_global_controls( - xml, MAIN_FRAME_WIDTH, _cbe_image_size, _client_fs_size, _nr_of_clients, - _controls_security_block_encryption_key_hover == Controls_security_block_encryption_key_hover::SHUT_DOWN_BUTTON, - _controls_security_block_encryption_key_select == Controls_security_block_encryption_key_select::SHUT_DOWN_BUTTON); + xml, MAIN_FRAME_WIDTH, _tresor_image_size, _client_fs_size, _nr_of_clients, + _controls_security_block_encryption_key_hover == Controls_security_block_encryption_key_hover::LOCK_BUTTON, + _controls_security_block_encryption_key_select == Controls_security_block_encryption_key_select::LOCK_BUTTON); }); break; @@ -1870,9 +2137,9 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); }); gen_global_controls( - xml, MAIN_FRAME_WIDTH, _cbe_image_size, _client_fs_size, _nr_of_clients, - _controls_security_master_key_hover == Controls_security_master_key_hover::SHUT_DOWN_BUTTON, - _controls_security_master_key_select == Controls_security_master_key_select::SHUT_DOWN_BUTTON); + xml, MAIN_FRAME_WIDTH, _tresor_image_size, _client_fs_size, _nr_of_clients, + _controls_security_master_key_hover == Controls_security_master_key_hover::LOCK_BUTTON, + _controls_security_master_key_select == Controls_security_master_key_select::LOCK_BUTTON); }); break; @@ -1893,14 +2160,14 @@ void File_vault::Main::produce_xml(Xml_generator &xml) }); }); gen_global_controls( - xml, MAIN_FRAME_WIDTH, _cbe_image_size, _client_fs_size, _nr_of_clients, - _controls_security_user_passphrase_hover == Controls_security_user_passphrase_hover::SHUT_DOWN_BUTTON, - _controls_security_user_passphrase_select == Controls_security_user_passphrase_select::SHUT_DOWN_BUTTON); + xml, MAIN_FRAME_WIDTH, _tresor_image_size, _client_fs_size, _nr_of_clients, + _controls_security_user_passphrase_hover == Controls_security_user_passphrase_hover::LOCK_BUTTON, + _controls_security_user_passphrase_select == Controls_security_user_passphrase_select::LOCK_BUTTON); }); break; - case State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE: - case State::SHUTDOWN_WAIT_TILL_DEINIT_REQUEST_IS_DONE: + case State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR: + case State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE: gen_info_frame(xml, "1", "Please wait...", MAIN_FRAME_WIDTH); break; @@ -1974,18 +2241,18 @@ void File_vault::Main::wakeup_local_service() request.deliver_session(session); - } else if (request.label == "shut_down_fs_query -> listing") { + } else if (request.label == "lock_fs_query -> listing") { Report::Session_component &session { *new (_heap) Report::Session_component( - _env, _shut_down_fs_query_listing_handler, _env.ep(), + _env, _lock_fs_query_listing_handler, _env.ep(), request.resources, "", request.diag) }; request.deliver_session(session); } else { - error("failed to deliver Report session"); + error("failed to deliver Report session with label ", request.label); } }); @@ -2029,10 +2296,10 @@ void File_vault::Main::wakeup_local_service() } -size_t Main::_cbe_tree_nr_of_leaves(size_t payload_size) +size_t Main::_tresor_tree_nr_of_leaves(size_t payload_size) { - size_t nr_of_leaves { payload_size / CBE_BLOCK_SIZE }; - if (payload_size % CBE_BLOCK_SIZE) { + size_t nr_of_leaves { payload_size / TRESOR_BLOCK_SIZE }; + if (payload_size % TRESOR_BLOCK_SIZE) { nr_of_leaves++; } return nr_of_leaves; @@ -2045,114 +2312,114 @@ void File_vault::Main::_generate_sandbox_config(Xml_generator &xml) const case State::INVALID: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); + _gen_menu_view_start_node_if_required(xml); gen_fs_query_start_node(xml, _fs_query); break; case State::SETUP_OBTAIN_PARAMETERS: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); + _gen_menu_view_start_node_if_required(xml); break; - case State::STARTUP_OBTAIN_PARAMETERS: + case State::UNLOCK_OBTAIN_PARAMETERS: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); + _gen_menu_view_start_node_if_required(xml); break; - case State::SETUP_RUN_CBE_INIT_TRUST_ANCHOR: + case State::SETUP_RUN_TRESOR_INIT_TRUST_ANCHOR: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_init_trust_anchor_start_node( - xml, _cbe_init_trust_anchor, _setup_obtain_params_passphrase); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_init_trust_anchor_start_node( + xml, _tresor_init_trust_anchor, _ui_setup_obtain_params_passphrase()); break; - case State::STARTUP_RUN_CBE_INIT_TRUST_ANCHOR: + case State::UNLOCK_RUN_TRESOR_INIT_TRUST_ANCHOR: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_init_trust_anchor_start_node( - xml, _cbe_init_trust_anchor, _setup_obtain_params_passphrase); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_init_trust_anchor_start_node( + xml, _tresor_init_trust_anchor, _ui_setup_obtain_params_passphrase()); break; - case State::STARTUP_START_CBE_VFS: + case State::UNLOCK_START_TRESOR_VFS: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_vfs_start_node(xml, _cbe_vfs); - gen_sync_to_cbe_vfs_init_start_node(xml, _sync_to_cbe_vfs_init); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_vfs_start_node(xml, _tresor_vfs); + gen_sync_to_tresor_vfs_init_start_node(xml, _sync_to_tresor_vfs_init); break; - case State::STARTUP_DETERMINE_CLIENT_FS_SIZE: + case State::SETUP_DETERMINE_CLIENT_FS_SIZE: + case State::UNLOCK_DETERMINE_CLIENT_FS_SIZE: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_vfs_start_node(xml, _cbe_vfs); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_vfs_start_node(xml, _tresor_vfs); gen_client_fs_fs_query_start_node(xml, _client_fs_fs_query); break; - case State::SETUP_CREATE_CBE_IMAGE_FILE: + case State::SETUP_CREATE_TRESOR_IMAGE_FILE: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); gen_truncate_file_start_node( - xml, _truncate_file, "/cbe/cbe.img", - CBE_BLOCK_SIZE * - _cbe_nr_of_blocks( - CBE_NR_OF_SUPERBLOCKS, - CBE_VBD_TREE_NR_OF_LEVELS, - CBE_VBD_TREE_NR_OF_CHILDREN, - _cbe_tree_nr_of_leaves(_client_fs_size_input.value()), - CBE_FREE_TREE_NR_OF_LEVELS, - CBE_FREE_TREE_NR_OF_CHILDREN, - _cbe_tree_nr_of_leaves(_snapshot_buf_size_input.value()))); + xml, _truncate_file, "/tresor/tresor.img", + TRESOR_BLOCK_SIZE * + _tresor_nr_of_blocks( + TRESOR_NR_OF_SUPERBLOCKS, + TRESOR_VBD_TREE_NR_OF_LEVELS, + TRESOR_VBD_TREE_NR_OF_CHILDREN, + _tresor_tree_nr_of_leaves(_ui_client_fs_size()), + TRESOR_FREE_TREE_NR_OF_LEVELS, + TRESOR_FREE_TREE_NR_OF_CHILDREN, + _tresor_tree_nr_of_leaves(_ui_journaling_buf_size()))); break; - case State::SETUP_RUN_CBE_INIT: + case State::SETUP_RUN_TRESOR_INIT: { Tree_geometry const vbd_tree_geom { - CBE_VBD_TREE_NR_OF_LEVELS, - CBE_VBD_TREE_NR_OF_CHILDREN, - _cbe_tree_nr_of_leaves(_client_fs_size_input.value()) }; + TRESOR_VBD_TREE_NR_OF_LEVELS, + TRESOR_VBD_TREE_NR_OF_CHILDREN, + _tresor_tree_nr_of_leaves(_ui_client_fs_size()) }; Tree_geometry const free_tree_geom { - CBE_VBD_TREE_NR_OF_LEVELS, - CBE_VBD_TREE_NR_OF_CHILDREN, - _cbe_tree_nr_of_leaves(_snapshot_buf_size_input.value()) }; + TRESOR_VBD_TREE_NR_OF_LEVELS, + TRESOR_VBD_TREE_NR_OF_CHILDREN, + _tresor_tree_nr_of_leaves(_ui_journaling_buf_size()) }; gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_image_vfs_block_start_node(xml, _cbe_image_vfs_block); - gen_cbe_init_start_node(xml, _cbe_init, vbd_tree_geom, free_tree_geom); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_init_start_node(xml, _tresor_init, vbd_tree_geom, free_tree_geom); break; } - case State::SETUP_START_CBE_VFS: + case State::SETUP_START_TRESOR_VFS: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_vfs_start_node(xml, _cbe_vfs); - gen_sync_to_cbe_vfs_init_start_node(xml, _sync_to_cbe_vfs_init); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_vfs_start_node(xml, _tresor_vfs); + gen_sync_to_tresor_vfs_init_start_node(xml, _sync_to_tresor_vfs_init); break; - case State::SETUP_FORMAT_CBE: + case State::SETUP_FORMAT_TRESOR: gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_vfs_start_node(xml, _cbe_vfs); - gen_cbe_vfs_block_start_node(xml, _cbe_vfs_block); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_vfs_start_node(xml, _tresor_vfs); + gen_tresor_vfs_block_start_node(xml, _tresor_vfs_block); gen_mke2fs_start_node(xml, _mke2fs); break; @@ -2167,10 +2434,10 @@ void File_vault::Main::_generate_sandbox_config(Xml_generator &xml) const case State::CONTROLS_SECURITY_USER_PASSPHRASE: { gen_parent_provides_and_report_nodes(xml); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_vfs_start_node(xml, _cbe_vfs); - gen_cbe_vfs_block_start_node(xml, _cbe_vfs_block); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_vfs_start_node(xml, _tresor_vfs); + gen_tresor_vfs_block_start_node(xml, _tresor_vfs_block); gen_snapshots_fs_query_start_node(xml, _snapshots_fs_query); gen_image_fs_query_start_node(xml, _image_fs_query); @@ -2179,7 +2446,7 @@ void File_vault::Main::_generate_sandbox_config(Xml_generator &xml) const break; - case Resizing_state::ADAPT_CBE_IMAGE_SIZE: + case Resizing_state::ADAPT_TRESOR_IMAGE_SIZE: switch (_resizing_type) { case Resizing_type::EXPAND_CLIENT_FS: @@ -2188,11 +2455,11 @@ void File_vault::Main::_generate_sandbox_config(Xml_generator &xml) const _expand_client_fs_contingent.value() }; size_t const effective_bytes { - bytes - (bytes % CBE_BLOCK_SIZE) }; + bytes - (bytes % TRESOR_BLOCK_SIZE) }; gen_truncate_file_start_node( - xml, _truncate_file, "/cbe/cbe.img", - _cbe_image_size + effective_bytes); + xml, _truncate_file, "/tresor/tresor.img", + _tresor_image_size + effective_bytes); break; } @@ -2202,11 +2469,11 @@ void File_vault::Main::_generate_sandbox_config(Xml_generator &xml) const _expand_snapshot_buf_contingent.value() }; size_t const effective_bytes { - bytes - (bytes % CBE_BLOCK_SIZE) }; + bytes - (bytes % TRESOR_BLOCK_SIZE) }; gen_truncate_file_start_node( - xml, _truncate_file, "/cbe/cbe.img", - _cbe_image_size + effective_bytes); + xml, _truncate_file, "/tresor/tresor.img", + _tresor_image_size + effective_bytes); break; } @@ -2230,7 +2497,7 @@ void File_vault::Main::_generate_sandbox_config(Xml_generator &xml) const gen_resizing_fs_tool_start_node( xml, _resizing_fs_tool, "vbd", - _expand_client_fs_contingent.value() / CBE_BLOCK_SIZE); + _expand_client_fs_contingent.value() / TRESOR_BLOCK_SIZE); break; @@ -2238,7 +2505,7 @@ void File_vault::Main::_generate_sandbox_config(Xml_generator &xml) const gen_resizing_fs_tool_start_node( xml, _resizing_fs_tool, "ft", - _expand_snapshot_buf_contingent.value() / CBE_BLOCK_SIZE); + _expand_snapshot_buf_contingent.value() / TRESOR_BLOCK_SIZE); break; @@ -2317,28 +2584,28 @@ void File_vault::Main::_generate_sandbox_config(Xml_generator &xml) const } break; } - case State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE: + case State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR: gen_parent_provides_and_report_nodes(xml); gen_policy_for_child_service(xml, "File_system", _rump_vfs); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_vfs_start_node(xml, _cbe_vfs); - gen_cbe_vfs_block_start_node(xml, _cbe_vfs_block); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_vfs_start_node(xml, _tresor_vfs); + gen_tresor_vfs_block_start_node(xml, _tresor_vfs_block); gen_snapshots_fs_query_start_node(xml, _snapshots_fs_query); - gen_shut_down_fs_tool_start_node(xml, _shut_down_fs_tool); + gen_lock_fs_tool_start_node(xml, _lock_fs_tool); break; - case State::SHUTDOWN_WAIT_TILL_DEINIT_REQUEST_IS_DONE: + case State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE: gen_parent_provides_and_report_nodes(xml); gen_policy_for_child_service(xml, "File_system", _rump_vfs); - gen_menu_view_start_node(xml, _menu_view); - gen_cbe_trust_anchor_vfs_start_node(xml, _cbe_trust_anchor_vfs); - gen_cbe_vfs_start_node(xml, _cbe_vfs); - gen_cbe_vfs_block_start_node(xml, _cbe_vfs_block); + _gen_menu_view_start_node_if_required(xml); + gen_tresor_trust_anchor_vfs_start_node(xml, _tresor_trust_anchor_vfs); + gen_tresor_vfs_start_node(xml, _tresor_vfs); + gen_tresor_vfs_block_start_node(xml, _tresor_vfs_block); gen_snapshots_fs_query_start_node(xml, _snapshots_fs_query); - gen_shut_down_fs_query_start_node(xml, _shut_down_fs_query); + gen_lock_fs_query_start_node(xml, _lock_fs_query); break; } } @@ -2362,22 +2629,22 @@ size_t Main::_tree_nr_of_blocks(size_t nr_of_lvls, } -size_t Main::_cbe_size() const +size_t Main::_tresor_size() const { return - _cbe_nr_of_blocks( - CBE_NR_OF_SUPERBLOCKS, - CBE_VBD_TREE_NR_OF_LEVELS, - CBE_VBD_TREE_NR_OF_CHILDREN, - _cbe_tree_nr_of_leaves(_client_fs_size_input.value()), - CBE_FREE_TREE_NR_OF_LEVELS, - CBE_FREE_TREE_NR_OF_CHILDREN, - _cbe_tree_nr_of_leaves(_snapshot_buf_size_input.value())) - * CBE_BLOCK_SIZE; + _tresor_nr_of_blocks( + TRESOR_NR_OF_SUPERBLOCKS, + TRESOR_VBD_TREE_NR_OF_LEVELS, + TRESOR_VBD_TREE_NR_OF_CHILDREN, + _tresor_tree_nr_of_leaves(_ui_client_fs_size()), + TRESOR_FREE_TREE_NR_OF_LEVELS, + TRESOR_FREE_TREE_NR_OF_CHILDREN, + _tresor_tree_nr_of_leaves(_ui_journaling_buf_size())) + * TRESOR_BLOCK_SIZE; } -size_t Main::_cbe_nr_of_blocks(size_t nr_of_superblocks, +size_t Main::_tresor_nr_of_blocks(size_t nr_of_superblocks, size_t nr_of_vbd_lvls, size_t nr_of_vbd_children, size_t nr_of_vbd_leafs, @@ -2400,8 +2667,8 @@ size_t Main::_cbe_nr_of_blocks(size_t nr_of_superblocks, /* FIXME * * This would be the correct way to calculate the number of MT blocks - * but the CBE still uses an MT the same size as the FT for simplicity - * reasons. As soon as the CBE does it right we should fix also this path. + * but the Tresor still uses an MT the same size as the FT for simplicity + * reasons. As soon as the Tresor does it right we should fix also this path. * * size_t const nr_of_mt_leafs { * nr_of_ft_blks - nr_of_ft_leafs }; @@ -2476,9 +2743,7 @@ void File_vault::Main::handle_input_event(Input::Event const &event) } else if (key == Input::KEY_ENTER) { - if (_client_fs_size_input.value() >= MIN_CLIENT_FS_SIZE && - _snapshot_buf_size_input.value() >= _min_snapshot_buf_size() && - _setup_obtain_params_passphrase.suitable() && + if (_ui_setup_obtain_params_suitable() && _setup_obtain_params_select != Setup_obtain_params_select::START_BUTTON) { _setup_obtain_params_select = Setup_obtain_params_select::START_BUTTON; @@ -2541,27 +2806,27 @@ void File_vault::Main::handle_input_event(Input::Event const &event) } } else if (_setup_obtain_params_select == Setup_obtain_params_select::SNAPSHOT_BUFFER_SIZE_INPUT) { - if (_snapshot_buf_size_input.appendable_character(code)) { + if (_journaling_buf_size_input.appendable_character(code)) { - _snapshot_buf_size_input.append_character(code); + _journaling_buf_size_input.append_character(code); update_dialog = true; } else if (code.value == CODEPOINT_BACKSPACE) { - _snapshot_buf_size_input.remove_last_character(); + _journaling_buf_size_input.remove_last_character(); update_dialog = true; } } else if (_setup_obtain_params_select == Setup_obtain_params_select::SNAPSHOT_BUFFER_SIZE_INPUT) { - if (_snapshot_buf_size_input.appendable_character(code)) { + if (_journaling_buf_size_input.appendable_character(code)) { - _snapshot_buf_size_input.append_character(code); + _journaling_buf_size_input.append_character(code); update_dialog = true; } else if (code.value == CODEPOINT_BACKSPACE) { - _snapshot_buf_size_input.remove_last_character(); + _journaling_buf_size_input.remove_last_character(); update_dialog = true; } @@ -2587,12 +2852,9 @@ void File_vault::Main::handle_input_event(Input::Event const &event) case Setup_obtain_params_select::START_BUTTON: - if(_client_fs_size_input.value() >= MIN_CLIENT_FS_SIZE && - _snapshot_buf_size_input.value() >= _min_snapshot_buf_size() && - _setup_obtain_params_passphrase.suitable()) { - + if(_ui_setup_obtain_params_suitable()) { _setup_obtain_params_select = Setup_obtain_params_select::NONE; - _state = State::SETUP_CREATE_CBE_IMAGE_FILE; + _set_state(State::SETUP_CREATE_TRESOR_IMAGE_FILE); update_sandbox_config = true; update_dialog = true; } @@ -2606,7 +2868,7 @@ void File_vault::Main::handle_input_event(Input::Event const &event) }); break; - case State::STARTUP_OBTAIN_PARAMETERS: + case State::UNLOCK_OBTAIN_PARAMETERS: event.handle_press([&] (Input::Keycode key, Codepoint code) { @@ -2654,7 +2916,7 @@ void File_vault::Main::handle_input_event(Input::Event const &event) } else if (key == Input::KEY_ENTER) { - if (_setup_obtain_params_passphrase.suitable() && + if (_ui_setup_obtain_params_passphrase_suitable() && _setup_obtain_params_select != Setup_obtain_params_select::START_BUTTON) { _setup_obtain_params_select = Setup_obtain_params_select::START_BUTTON; @@ -2697,10 +2959,10 @@ void File_vault::Main::handle_input_event(Input::Event const &event) case Setup_obtain_params_select::START_BUTTON: - if (_setup_obtain_params_passphrase.suitable()) { + if (_ui_setup_obtain_params_passphrase_suitable()) { _setup_obtain_params_select = Setup_obtain_params_select::NONE; - _state = State::STARTUP_RUN_CBE_INIT_TRUST_ANCHOR; + _set_state(State::UNLOCK_RUN_TRESOR_INIT_TRUST_ANCHOR); update_sandbox_config = true; update_dialog = true; } @@ -2726,25 +2988,25 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_controls_root_hover) { case Controls_root_hover::SNAPSHOTS_EXPAND_BUTTON: - _state = State::CONTROLS_SNAPSHOTS; + _set_state(State::CONTROLS_SNAPSHOTS); update_dialog = true; break; case Controls_root_hover::DIMENSIONS_BUTTON: - _state = State::CONTROLS_DIMENSIONS; + _set_state(State::CONTROLS_DIMENSIONS); update_dialog = true; break; case Controls_root_hover::SECURITY_EXPAND_BUTTON: - _state = State::CONTROLS_SECURITY; + _set_state(State::CONTROLS_SECURITY); update_dialog = true; break; - case Controls_root_hover::SHUT_DOWN_BUTTON: + case Controls_root_hover::LOCK_BUTTON: - next_select = Controls_root_select::SHUT_DOWN_BUTTON; + next_select = Controls_root_select::LOCK_BUTTON; break; case Controls_root_hover::NONE: @@ -2764,10 +3026,10 @@ void File_vault::Main::handle_input_event(Input::Event const &event) if (key == Input::BTN_LEFT) { switch (_controls_root_select) { - case Controls_root_select::SHUT_DOWN_BUTTON: + case Controls_root_select::LOCK_BUTTON: _controls_root_select = Controls_root_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -2793,13 +3055,13 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_controls_snapshots_hover) { case Controls_snapshots_hover::LEAVE_BUTTON: - _state = State::CONTROLS_ROOT; + _set_state(State::CONTROLS_ROOT); update_dialog = true; break; - case Controls_snapshots_hover::SHUT_DOWN_BUTTON: + case Controls_snapshots_hover::LOCK_BUTTON: - next_select = Controls_snapshots_select::SHUT_DOWN_BUTTON; + next_select = Controls_snapshots_select::LOCK_BUTTON; break; case Controls_snapshots_hover::CREATE_BUTTON: @@ -2847,10 +3109,10 @@ void File_vault::Main::handle_input_event(Input::Event const &event) if (key == Input::BTN_LEFT) { switch (_controls_snapshots_select) { - case Controls_snapshots_select::SHUT_DOWN_BUTTON: + case Controls_snapshots_select::LOCK_BUTTON: _controls_snapshots_select = Controls_snapshots_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -2897,27 +3159,27 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_dimensions_hover) { case Dimensions_hover::LEAVE_BUTTON: - _state = State::CONTROLS_ROOT; + _set_state(State::CONTROLS_ROOT); update_dialog = true; break; case Dimensions_hover::EXPAND_CLIENT_FS_BUTTON: - _state = State::CONTROLS_EXPAND_CLIENT_FS; + _set_state(State::CONTROLS_EXPAND_CLIENT_FS); _expand_client_fs_select = Expand_client_fs_select::CONTINGENT_INPUT; update_dialog = true; break; case Dimensions_hover::EXPAND_SNAPSHOT_BUF_BUTTON: - _state = State::CONTROLS_EXPAND_SNAPSHOT_BUF; + _set_state(State::CONTROLS_EXPAND_SNAPSHOT_BUF); _expand_snapshot_buf_select = Expand_snapshot_buf_select::CONTINGENT_INPUT; update_dialog = true; break; - case Dimensions_hover::SHUT_DOWN_BUTTON: + case Dimensions_hover::LOCK_BUTTON: - next_select = Dimensions_select::SHUT_DOWN_BUTTON; + next_select = Dimensions_select::LOCK_BUTTON; break; case Dimensions_hover::NONE: @@ -2937,10 +3199,10 @@ void File_vault::Main::handle_input_event(Input::Event const &event) if (key == Input::BTN_LEFT) { switch (_dimensions_select) { - case Dimensions_select::SHUT_DOWN_BUTTON: + case Dimensions_select::LOCK_BUTTON: _dimensions_select = Dimensions_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -2968,13 +3230,13 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_expand_client_fs_hover) { case Expand_client_fs_hover::LEAVE_BUTTON: - _state = State::CONTROLS_DIMENSIONS; + _set_state(State::CONTROLS_DIMENSIONS); update_dialog = true; break; - case Expand_client_fs_hover::SHUT_DOWN_BUTTON: + case Expand_client_fs_hover::LOCK_BUTTON: - next_select = Expand_client_fs_select::SHUT_DOWN_BUTTON; + next_select = Expand_client_fs_select::LOCK_BUTTON; break; case Expand_client_fs_hover::START_BUTTON: @@ -3005,10 +3267,10 @@ void File_vault::Main::handle_input_event(Input::Event const &event) break; - case Expand_client_fs_select::SHUT_DOWN_BUTTON: + case Expand_client_fs_select::LOCK_BUTTON: _expand_client_fs_select = Expand_client_fs_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -3033,13 +3295,13 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_expand_client_fs_hover) { case Expand_client_fs_hover::LEAVE_BUTTON: - _state = State::CONTROLS_DIMENSIONS; + _set_state(State::CONTROLS_DIMENSIONS); update_dialog = true; break; - case Expand_client_fs_hover::SHUT_DOWN_BUTTON: + case Expand_client_fs_hover::LOCK_BUTTON: - next_select = Expand_client_fs_select::SHUT_DOWN_BUTTON; + next_select = Expand_client_fs_select::LOCK_BUTTON; break; case Expand_client_fs_hover::START_BUTTON: @@ -3069,7 +3331,7 @@ void File_vault::Main::handle_input_event(Input::Event const &event) _expand_client_fs_contingent.value() }; size_t const effective_bytes { - bytes - (bytes % CBE_BLOCK_SIZE) }; + bytes - (bytes % TRESOR_BLOCK_SIZE) }; if (effective_bytes > 0) { @@ -3103,16 +3365,16 @@ void File_vault::Main::handle_input_event(Input::Event const &event) _expand_client_fs_select = Expand_client_fs_select::NONE; _resizing_type = Resizing_type::EXPAND_CLIENT_FS; - _resizing_state = Resizing_state::ADAPT_CBE_IMAGE_SIZE; + _resizing_state = Resizing_state::ADAPT_TRESOR_IMAGE_SIZE; update_sandbox_config = true; update_dialog = true; break; - case Expand_client_fs_select::SHUT_DOWN_BUTTON: + case Expand_client_fs_select::LOCK_BUTTON: _expand_client_fs_select = Expand_client_fs_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -3139,13 +3401,13 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_expand_snapshot_buf_hover) { case Expand_snapshot_buf_hover::LEAVE_BUTTON: - _state = State::CONTROLS_DIMENSIONS; + _set_state(State::CONTROLS_DIMENSIONS); update_dialog = true; break; - case Expand_snapshot_buf_hover::SHUT_DOWN_BUTTON: + case Expand_snapshot_buf_hover::LOCK_BUTTON: - next_select = Expand_snapshot_buf_select::SHUT_DOWN_BUTTON; + next_select = Expand_snapshot_buf_select::LOCK_BUTTON; break; case Expand_snapshot_buf_hover::START_BUTTON: @@ -3175,7 +3437,7 @@ void File_vault::Main::handle_input_event(Input::Event const &event) _expand_snapshot_buf_contingent.value() }; size_t const effective_bytes { - bytes - (bytes % CBE_BLOCK_SIZE) }; + bytes - (bytes % TRESOR_BLOCK_SIZE) }; if (effective_bytes > 0) { @@ -3209,16 +3471,16 @@ void File_vault::Main::handle_input_event(Input::Event const &event) _expand_snapshot_buf_select = Expand_snapshot_buf_select::NONE; _resizing_type = Resizing_type::EXPAND_SNAPSHOT_BUF; - _resizing_state = Resizing_state::WAIT_TILL_DEVICE_IS_READY; + _resizing_state = Resizing_state::ADAPT_TRESOR_IMAGE_SIZE; update_sandbox_config = true; update_dialog = true; break; - case Expand_snapshot_buf_select::SHUT_DOWN_BUTTON: + case Expand_snapshot_buf_select::LOCK_BUTTON: _expand_snapshot_buf_select = Expand_snapshot_buf_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -3244,31 +3506,31 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_controls_security_hover) { case Controls_security_hover::SECURITY_EXPAND_BUTTON: - _state = State::CONTROLS_ROOT; + _set_state(State::CONTROLS_ROOT); update_dialog = true; break; case Controls_security_hover::BLOCK_ENCRYPTION_KEY_EXPAND_BUTTON: - _state = State::CONTROLS_SECURITY_BLOCK_ENCRYPTION_KEY; + _set_state(State::CONTROLS_SECURITY_BLOCK_ENCRYPTION_KEY); update_dialog = true; break; case Controls_security_hover::MASTER_KEY_EXPAND_BUTTON: - _state = State::CONTROLS_SECURITY_MASTER_KEY; + _set_state(State::CONTROLS_SECURITY_MASTER_KEY); update_dialog = true; break; case Controls_security_hover::USER_PASSPHRASE_EXPAND_BUTTON: - _state = State::CONTROLS_SECURITY_USER_PASSPHRASE; + _set_state(State::CONTROLS_SECURITY_USER_PASSPHRASE); update_dialog = true; break; - case Controls_security_hover::SHUT_DOWN_BUTTON: + case Controls_security_hover::LOCK_BUTTON: - next_select = Controls_security_select::SHUT_DOWN_BUTTON; + next_select = Controls_security_select::LOCK_BUTTON; break; case Controls_security_hover::NONE: @@ -3288,10 +3550,10 @@ void File_vault::Main::handle_input_event(Input::Event const &event) if (key == Input::BTN_LEFT) { switch (_controls_security_select) { - case Controls_security_select::SHUT_DOWN_BUTTON: + case Controls_security_select::LOCK_BUTTON: _controls_security_select = Controls_security_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -3317,7 +3579,7 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_controls_security_block_encryption_key_hover) { case Controls_security_block_encryption_key_hover::LEAVE_BUTTON: - _state = State::CONTROLS_SECURITY; + _set_state(State::CONTROLS_SECURITY); update_dialog = true; break; @@ -3326,9 +3588,9 @@ void File_vault::Main::handle_input_event(Input::Event const &event) next_select = Controls_security_block_encryption_key_select::REPLACE_BUTTON; break; - case Controls_security_block_encryption_key_hover::SHUT_DOWN_BUTTON: + case Controls_security_block_encryption_key_hover::LOCK_BUTTON: - next_select = Controls_security_block_encryption_key_select::SHUT_DOWN_BUTTON; + next_select = Controls_security_block_encryption_key_select::LOCK_BUTTON; break; case Controls_security_block_encryption_key_hover::NONE: @@ -3357,10 +3619,10 @@ void File_vault::Main::handle_input_event(Input::Event const &event) update_dialog = true; break; - case Controls_security_block_encryption_key_select::SHUT_DOWN_BUTTON: + case Controls_security_block_encryption_key_select::LOCK_BUTTON: _controls_security_block_encryption_key_select = Controls_security_block_encryption_key_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -3386,13 +3648,13 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_controls_security_master_key_hover) { case Controls_security_master_key_hover::LEAVE_BUTTON: - _state = State::CONTROLS_SECURITY; + _set_state(State::CONTROLS_SECURITY); update_dialog = true; break; - case Controls_security_master_key_hover::SHUT_DOWN_BUTTON: + case Controls_security_master_key_hover::LOCK_BUTTON: - next_select = Controls_security_master_key_select::SHUT_DOWN_BUTTON; + next_select = Controls_security_master_key_select::LOCK_BUTTON; break; case Controls_security_master_key_hover::NONE: @@ -3412,10 +3674,10 @@ void File_vault::Main::handle_input_event(Input::Event const &event) if (key == Input::BTN_LEFT) { switch (_controls_security_master_key_select) { - case Controls_security_master_key_select::SHUT_DOWN_BUTTON: + case Controls_security_master_key_select::LOCK_BUTTON: _controls_security_master_key_select = Controls_security_master_key_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -3441,13 +3703,13 @@ void File_vault::Main::handle_input_event(Input::Event const &event) switch (_controls_security_user_passphrase_hover) { case Controls_security_user_passphrase_hover::LEAVE_BUTTON: - _state = State::CONTROLS_SECURITY; + _set_state(State::CONTROLS_SECURITY); update_dialog = true; break; - case Controls_security_user_passphrase_hover::SHUT_DOWN_BUTTON: + case Controls_security_user_passphrase_hover::LOCK_BUTTON: - next_select = Controls_security_user_passphrase_select::SHUT_DOWN_BUTTON; + next_select = Controls_security_user_passphrase_select::LOCK_BUTTON; break; case Controls_security_user_passphrase_hover::NONE: @@ -3467,10 +3729,10 @@ void File_vault::Main::handle_input_event(Input::Event const &event) if (key == Input::BTN_LEFT) { switch (_controls_security_user_passphrase_select) { - case Controls_security_user_passphrase_select::SHUT_DOWN_BUTTON: + case Controls_security_user_passphrase_select::LOCK_BUTTON: _controls_security_user_passphrase_select = Controls_security_user_passphrase_select::NONE; - _state = State::SHUTDOWN_ISSUE_DEINIT_REQUEST_AT_CBE; + _set_state(State::LOCK_ISSUE_DEINIT_REQUEST_AT_TRESOR); update_sandbox_config = true; update_dialog = true; @@ -3551,7 +3813,7 @@ void File_vault::Main::_handle_hover(Xml_node const &node) } break; } - case State::STARTUP_OBTAIN_PARAMETERS: + case State::UNLOCK_OBTAIN_PARAMETERS: { Setup_obtain_params_hover const prev_hover { _setup_obtain_params_hover }; Setup_obtain_params_hover next_hover { Setup_obtain_params_hover::NONE }; @@ -3602,9 +3864,9 @@ void File_vault::Main::_handle_hover(Xml_node const &node) node_2.with_optional_sub_node("hbox", [&] (Xml_node const &node_3) { node_3.with_optional_sub_node("button", [&] (Xml_node const &node_4) { - if (_has_name(node_4, "Shut down")) { + if (_has_name(node_4, "Lock")) { - next_hover = Controls_root_hover::SHUT_DOWN_BUTTON; + next_hover = Controls_root_hover::LOCK_BUTTON; } }); @@ -3652,9 +3914,9 @@ void File_vault::Main::_handle_hover(Xml_node const &node) node_2.with_optional_sub_node("hbox", [&] (Xml_node const &node_3) { node_3.with_optional_sub_node("button", [&] (Xml_node const &node_4) { - if (_has_name(node_4, "Shut down")) { + if (_has_name(node_4, "Lock")) { - next_hover = Controls_snapshots_hover::SHUT_DOWN_BUTTON; + next_hover = Controls_snapshots_hover::LOCK_BUTTON; } }); }); @@ -3747,9 +4009,9 @@ void File_vault::Main::_handle_hover(Xml_node const &node) node_2.with_optional_sub_node("hbox", [&] (Xml_node const &node_3) { node_3.with_optional_sub_node("button", [&] (Xml_node const &node_4) { - if (_has_name(node_4, "Shut down")) { + if (_has_name(node_4, "Lock")) { - next_hover = Dimensions_hover::SHUT_DOWN_BUTTON; + next_hover = Dimensions_hover::LOCK_BUTTON; } }); }); @@ -3799,9 +4061,9 @@ void File_vault::Main::_handle_hover(Xml_node const &node) node_2.with_optional_sub_node("hbox", [&] (Xml_node const &node_3) { node_3.with_optional_sub_node("button", [&] (Xml_node const &node_4) { - if (_has_name(node_4, "Shut down")) { + if (_has_name(node_4, "Lock")) { - next_hover = Expand_client_fs_hover::SHUT_DOWN_BUTTON; + next_hover = Expand_client_fs_hover::LOCK_BUTTON; } }); @@ -3855,9 +4117,9 @@ void File_vault::Main::_handle_hover(Xml_node const &node) node_3.with_optional_sub_node("button", [&] (Xml_node const &node_4) { - if (_has_name(node_4, "Shut down")) { + if (_has_name(node_4, "Lock")) { - next_hover = Expand_snapshot_buf_hover::SHUT_DOWN_BUTTON; + next_hover = Expand_snapshot_buf_hover::LOCK_BUTTON; } }); @@ -3911,9 +4173,9 @@ void File_vault::Main::_handle_hover(Xml_node const &node) node_2.with_optional_sub_node("hbox", [&] (Xml_node const &node_3) { node_3.with_optional_sub_node("button", [&] (Xml_node const &node_4) { - if (_has_name(node_4, "Shut down")) { + if (_has_name(node_4, "Lock")) { - next_hover = Controls_security_hover::SHUT_DOWN_BUTTON; + next_hover = Controls_security_hover::LOCK_BUTTON; } }); @@ -3965,9 +4227,9 @@ void File_vault::Main::_handle_hover(Xml_node const &node) node_2.with_optional_sub_node("hbox", [&] (Xml_node const &node_3) { node_3.with_optional_sub_node("button", [&] (Xml_node const &node_4) { - if (_has_name(node_4, "Shut down")) { + if (_has_name(node_4, "Lock")) { - next_hover = Controls_security_block_encryption_key_hover::SHUT_DOWN_BUTTON; + next_hover = Controls_security_block_encryption_key_hover::LOCK_BUTTON; } }); @@ -4011,9 +4273,9 @@ void File_vault::Main::_handle_hover(Xml_node const &node) node_2.with_optional_sub_node("hbox", [&] (Xml_node const &node_3) { node_3.with_optional_sub_node("button", [&] (Xml_node const &node_4) { - if (_has_name(node_4, "Shut down")) { + if (_has_name(node_4, "Lock")) { - next_hover = Controls_security_master_key_hover::SHUT_DOWN_BUTTON; + next_hover = Controls_security_master_key_hover::LOCK_BUTTON; } }); @@ -4050,9 +4312,9 @@ void File_vault::Main::_handle_hover(Xml_node const &node) node_2.with_optional_sub_node("hbox", [&] (Xml_node const &node_3) { node_3.with_optional_sub_node("button", [&] (Xml_node const &node_4) { - if (_has_name(node_4, "Shut down")) { + if (_has_name(node_4, "Lock")) { - next_hover = Controls_security_user_passphrase_hover::SHUT_DOWN_BUTTON; + next_hover = Controls_security_user_passphrase_hover::LOCK_BUTTON; } }); diff --git a/repos/gems/src/app/file_vault/menu_view_dialog.cc b/repos/gems/src/app/file_vault/menu_view_dialog.cc index a154a05fae..8e6a8e61e1 100644 --- a/repos/gems/src/app/file_vault/menu_view_dialog.cc +++ b/repos/gems/src/app/file_vault/menu_view_dialog.cc @@ -360,17 +360,17 @@ void File_vault::gen_closed_menu(Xml_generator &xml, void File_vault::gen_global_controls(Xml_generator &xml, size_t min_width, - size_t cbe_image_size, + size_t tresor_image_size, size_t client_fs_size, size_t nr_of_clients, - bool shut_down_button_hovered, - bool shut_down_button_selected) + bool lock_button_hovered, + bool lock_button_selected) { gen_empty_line(xml, "Status 0", min_width); gen_centered_info_line(xml, "Status 1", String<256> { " Image: ", - Capacity_string { cbe_image_size }, + Capacity_string { tresor_image_size }, ", Client FS: ", Capacity_string { client_fs_size }, ", Clients: ", @@ -382,8 +382,6 @@ void File_vault::gen_global_controls(Xml_generator &xml, xml.node("hbox", [&] () { gen_action_button( - xml, "Shut down", "Shut down", - shut_down_button_hovered, - shut_down_button_selected); + xml, "Lock", "Lock", lock_button_hovered, lock_button_selected); }); } diff --git a/repos/gems/src/app/file_vault/menu_view_dialog.h b/repos/gems/src/app/file_vault/menu_view_dialog.h index 7c66dfc270..05badc08e4 100644 --- a/repos/gems/src/app/file_vault/menu_view_dialog.h +++ b/repos/gems/src/app/file_vault/menu_view_dialog.h @@ -171,11 +171,11 @@ namespace File_vault { void gen_global_controls(Xml_generator &xml, size_t min_width, - size_t cbe_image_size, + size_t tresor_image_size, size_t client_fs_size, size_t nr_of_clients, - bool shut_down_button_hovered, - bool shut_down_button_selected); + bool lock_button_hovered, + bool lock_button_selected); } #endif /* _MENU_VIEW_DIALOG_H_ */ diff --git a/repos/gems/src/app/file_vault/report_session_component.h b/repos/gems/src/app/file_vault/report_session_component.h index 2e1c6a63b2..c80bf69af9 100644 --- a/repos/gems/src/app/file_vault/report_session_component.h +++ b/repos/gems/src/app/file_vault/report_session_component.h @@ -1,5 +1,5 @@ /* - * \brief Report session provided by the CBE manager + * \brief Report session provided by the Tresor manager * \author Martin Stein * \author Norman Feske * \date 2021-02-25 diff --git a/repos/gems/src/app/file_vault/sandbox.h b/repos/gems/src/app/file_vault/sandbox.h index 0d6b89ef2c..b9982ef4e8 100644 --- a/repos/gems/src/app/file_vault/sandbox.h +++ b/repos/gems/src/app/file_vault/sandbox.h @@ -267,7 +267,7 @@ namespace File_vault { }); } - void gen_cbe_vfs_start_node(Xml_generator &xml, + void gen_tresor_vfs_start_node(Xml_generator &xml, Child_state const &child) { child.gen_start_node(xml, [&] () { @@ -279,9 +279,9 @@ namespace File_vault { xml.node("fs", [&] () { xml.attribute("buffer_size", "1M"); - xml.attribute("label", "cbe_fs"); + xml.attribute("label", "tresor_fs"); }); - xml.node("cbe_crypto_aes_cbc", [&] () { + xml.node("tresor_crypto_aes_cbc", [&] () { xml.attribute("name", "crypto"); }); xml.node("dir", [&] () { @@ -295,11 +295,11 @@ namespace File_vault { xml.node("dir", [&] () { xml.attribute("name", "dev"); - xml.node("cbe", [&] () { - xml.attribute("name", "cbe"); + xml.node("tresor", [&] () { + xml.attribute("name", "tresor"); xml.attribute("verbose", "no"); xml.attribute("debug", "no"); - xml.attribute("block", "/cbe.img"); + xml.attribute("block", "/tresor.img"); xml.attribute("crypto", "/crypto"); xml.attribute("trust_anchor", "/trust_anchor"); }); @@ -317,7 +317,7 @@ namespace File_vault { xml.attribute("writeable", "yes"); }); xml.node("policy", [&] () { - xml.attribute("label", "shut_down_fs_tool -> "); + xml.attribute("label", "lock_fs_tool -> "); xml.attribute("root", "/dev"); xml.attribute("writeable", "yes"); }); @@ -347,35 +347,35 @@ namespace File_vault { xml.attribute("writeable", "yes"); }); xml.node("policy", [&] () { - xml.attribute("label", "shut_down_fs_query -> "); + xml.attribute("label", "lock_fs_query -> "); xml.attribute("root", "/dev"); xml.attribute("writeable", "yes"); }); xml.node("policy", [&] () { xml.attribute("label", "vfs_block -> "); - xml.attribute("root", "/dev/cbe/current"); + xml.attribute("root", "/dev/tresor/current"); xml.attribute("writeable", "yes"); }); xml.node("policy", [&] () { xml.attribute("label", "client_fs_fs_query -> "); - xml.attribute("root", "/dev/cbe/current"); + xml.attribute("root", "/dev/tresor/current"); xml.attribute("writeable", "no"); }); xml.node("policy", [&] () { - xml.attribute("label", "sync_to_cbe_vfs_init -> "); + xml.attribute("label", "sync_to_tresor_vfs_init -> "); xml.attribute("root", "/dev"); xml.attribute("writeable", "yes"); }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_trust_anchor_vfs", "File_system", "trust_anchor"); - route_to_parent_service(xml, "File_system", "cbe_fs"); + route_to_child_service(xml, "tresor_trust_anchor_vfs", "File_system", "trust_anchor"); + route_to_parent_service(xml, "File_system", "tresor_fs"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); } - void gen_cbe_trust_anchor_vfs_start_node(Xml_generator &xml, + void gen_tresor_trust_anchor_vfs_start_node(Xml_generator &xml, Child_state const &child) { child.gen_start_node(xml, [&] () { @@ -396,8 +396,8 @@ namespace File_vault { xml.node("dir", [&] () { xml.attribute("name", "dev"); - xml.node("cbe_trust_anchor", [&] () { - xml.attribute("name", "cbe_trust_anchor"); + xml.node("tresor_trust_anchor", [&] () { + xml.attribute("name", "tresor_trust_anchor"); xml.attribute("storage_dir", "/storage_dir"); }); @@ -407,18 +407,18 @@ namespace File_vault { }); }); xml.node("policy", [&] () { - xml.attribute("label", "cbe_init_trust_anchor -> trust_anchor"); - xml.attribute("root", "/dev/cbe_trust_anchor"); + xml.attribute("label", "tresor_init_trust_anchor -> trust_anchor"); + xml.attribute("root", "/dev/tresor_trust_anchor"); xml.attribute("writeable", "yes"); }); xml.node("policy", [&] () { - xml.attribute("label", "cbe_init -> trust_anchor"); - xml.attribute("root", "/dev/cbe_trust_anchor"); + xml.attribute("label", "tresor_init -> trust_anchor"); + xml.attribute("root", "/dev/tresor_trust_anchor"); xml.attribute("writeable", "yes"); }); xml.node("policy", [&] () { - xml.attribute("label", "cbe_vfs -> trust_anchor"); - xml.attribute("root", "/dev/cbe_trust_anchor"); + xml.attribute("label", "tresor_vfs -> trust_anchor"); + xml.attribute("root", "/dev/tresor_trust_anchor"); xml.attribute("writeable", "yes"); }); }); @@ -440,7 +440,7 @@ namespace File_vault { xml.node("vfs", [&] () { xml.node("rump", [&] () { xml.attribute("fs", "ext2fs"); - xml.attribute("ram", "10M"); + xml.attribute("ram", "20M"); }); }); @@ -471,10 +471,10 @@ namespace File_vault { xml.node("vfs", [&] () { xml.node("dir", [&] () { - xml.attribute("name", "cbe"); + xml.attribute("name", "tresor"); xml.node("fs", [&] () { - xml.attribute("label", "cbe"); + xml.attribute("label", "tresor"); }); }); }); @@ -486,7 +486,7 @@ namespace File_vault { }); } - void gen_sync_to_cbe_vfs_init_start_node(Xml_generator &xml, + void gen_sync_to_tresor_vfs_init_start_node(Xml_generator &xml, Child_state const &child) { child.gen_start_node(xml, [&] () { @@ -505,7 +505,7 @@ namespace File_vault { xml.node("log", [&] () { }); }); xml.node("dir", [&] () { - xml.attribute("name", "cbe"); + xml.attribute("name", "tresor"); xml.node("fs", [&] () { xml.attribute("writeable", "yes"); @@ -514,13 +514,13 @@ namespace File_vault { }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); } - void gen_cbe_vfs_block_start_node(Xml_generator &xml, + void gen_tresor_vfs_block_start_node(Xml_generator &xml, Child_state const &child) { child.gen_start_node(xml, [&] () { @@ -552,7 +552,7 @@ namespace File_vault { }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); @@ -602,7 +602,7 @@ namespace File_vault { }); xml.node("route", [&] () { route_to_local_service(xml, "Report"); - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); @@ -632,15 +632,15 @@ namespace File_vault { }); } - void gen_cbe_init_trust_anchor_start_node(Xml_generator &xml, - Child_state const &child, - Input_passphrase const &passphrase) + void gen_tresor_init_trust_anchor_start_node(Xml_generator &xml, + Child_state const &child, + Passphrase_string const &passphrase) { child.gen_start_node(xml, [&] () { xml.node("config", [&] () { - xml.attribute("passphrase", passphrase.plaintext().string()); + xml.attribute("passphrase", passphrase); xml.attribute("trust_anchor_dir", "/trust_anchor"); xml.node("vfs", [&] () { xml.node("dir", [&] () { @@ -652,39 +652,13 @@ namespace File_vault { }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_trust_anchor_vfs", "File_system", "trust_anchor"); + route_to_child_service(xml, "tresor_trust_anchor_vfs", "File_system", "trust_anchor"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); } - void gen_cbe_image_vfs_block_start_node(Xml_generator &xml, - Child_state const &child) - { - child.gen_start_node(xml, [&] () { - - gen_provides_service(xml, "Block"); - xml.node("config", [&] () { - xml.node("vfs", [&] () { - xml.node("fs", [&] () { - xml.attribute("buffer_size", "1M"); - }); - }); - xml.node("policy", [&] () { - xml.attribute("label", "cbe_init -> "); - xml.attribute("block_size", "512"); - xml.attribute("file", "/cbe.img"); - xml.attribute("writeable", "yes"); - }); - }); - xml.node("route", [&] () { - route_to_parent_service(xml, "File_system"); - gen_parent_routes_for_pd_rom_cpu_log(xml); - }); - }); - } - - void gen_cbe_init_start_node(Xml_generator &xml, + void gen_tresor_init_start_node(Xml_generator &xml, Child_state const &child, Tree_geometry const &vbd_geom, Tree_geometry const &ft_geom) @@ -692,9 +666,24 @@ namespace File_vault { child.gen_start_node(xml, [&] () { xml.node("config", [&] () { - xml.attribute("trust_anchor_dir", "/trust_anchor"); + xml.node("trust-anchor", [&] () { + xml.attribute("path", "/trust_anchor"); + }); + xml.node("block-io", [&] () { + xml.attribute("type", "vfs"); + xml.attribute("path", "/tresor.img"); + }); + xml.node("crypto", [&] () { + xml.attribute("path", "/crypto"); + }); xml.node("vfs", [&] () { + xml.node("fs", [&] () { + xml.attribute("buffer_size", "1M"); + }); + xml.node("tresor_crypto_aes_cbc", [&] () { + xml.attribute("name", "crypto"); + }); xml.node("dir", [&] () { xml.attribute("name", "trust_anchor"); xml.node("fs", [&] () { @@ -702,9 +691,6 @@ namespace File_vault { }); }); }); - xml.node("key", [&] () { - xml.attribute("id", "12"); - }); xml.node("virtual-block-device", [&] () { xml.attribute("nr_of_levels", vbd_geom.nr_of_levels()); xml.attribute("nr_of_children", vbd_geom.nr_of_children()); @@ -717,8 +703,8 @@ namespace File_vault { }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_trust_anchor_vfs", "File_system", "trust_anchor"); - route_to_child_service(xml, "vfs_block", "Block"); + route_to_child_service(xml, "tresor_trust_anchor_vfs", "File_system", "trust_anchor"); + route_to_parent_service(xml, "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); @@ -750,13 +736,13 @@ namespace File_vault { }); }); xml.node("query", [&] () { - xml.attribute("path", "/cbe/snapshots"); + xml.attribute("path", "/tresor/snapshots"); xml.attribute("content", "yes"); }); }); xml.node("route", [&] () { route_to_local_service(xml, "Report"); - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); @@ -775,7 +761,7 @@ namespace File_vault { xml.node("vfs", [&] () { xml.node("dir", [&] () { - xml.attribute("name", "cbe"); + xml.attribute("name", "tresor"); xml.node("fs", [&] () { xml.attribute("writeable", "yes"); @@ -783,13 +769,13 @@ namespace File_vault { }); }); xml.node("new-file", [&] () { - xml.attribute("path", "/cbe/cbe/control/extend"); + xml.attribute("path", "/tresor/tresor/control/extend"); xml.append_content("tree=", tree, ",blocks=", nr_of_blocks); }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); @@ -807,19 +793,19 @@ namespace File_vault { }); }); xml.node("query", [&] () { - xml.attribute("path", "/cbe/control"); + xml.attribute("path", "/tresor/control"); xml.attribute("content", "yes"); }); }); xml.node("route", [&] () { route_to_local_service(xml, "Report"); - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); } - void gen_shut_down_fs_tool_start_node(Xml_generator &xml, + void gen_lock_fs_tool_start_node(Xml_generator &xml, Child_state const &child) { child.gen_start_node(xml, [&] () { @@ -830,7 +816,7 @@ namespace File_vault { xml.node("vfs", [&] () { xml.node("dir", [&] () { - xml.attribute("name", "cbe"); + xml.attribute("name", "tresor"); xml.node("fs", [&] () { xml.attribute("writeable", "yes"); @@ -838,13 +824,13 @@ namespace File_vault { }); }); xml.node("new-file", [&] () { - xml.attribute("path", "/cbe/cbe/control/deinitialize"); + xml.attribute("path", "/tresor/tresor/control/deinitialize"); xml.append_content("true"); }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); @@ -861,7 +847,7 @@ namespace File_vault { xml.node("vfs", [&] () { xml.node("dir", [&] () { - xml.attribute("name", "cbe"); + xml.attribute("name", "tresor"); xml.node("fs", [&] () { xml.attribute("writeable", "yes"); @@ -869,20 +855,20 @@ namespace File_vault { }); }); xml.node("new-file", [&] () { - xml.attribute("path", "/cbe/cbe/control/rekey"); + xml.attribute("path", "/tresor/tresor/control/rekey"); xml.append_content("true"); }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); } - void gen_shut_down_fs_query_start_node(Xml_generator &xml, - Child_state const &child) + void gen_lock_fs_query_start_node(Xml_generator &xml, + Child_state const &child) { child.gen_start_node(xml, [&] () { @@ -893,13 +879,13 @@ namespace File_vault { }); }); xml.node("query", [&] () { - xml.attribute("path", "/cbe/control"); + xml.attribute("path", "/tresor/control"); xml.attribute("content", "yes"); }); }); xml.node("route", [&] () { route_to_local_service(xml, "Report"); - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); @@ -917,13 +903,13 @@ namespace File_vault { }); }); xml.node("query", [&] () { - xml.attribute("path", "/cbe/control"); + xml.attribute("path", "/tresor/control"); xml.attribute("content", "yes"); }); }); xml.node("route", [&] () { route_to_local_service(xml, "Report"); - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); @@ -940,7 +926,7 @@ namespace File_vault { xml.node("vfs", [&] () { xml.node("dir", [&] () { - xml.attribute("name", "cbe"); + xml.attribute("name", "tresor"); xml.node("fs", [&] () { xml.attribute("writeable", "yes"); @@ -948,13 +934,13 @@ namespace File_vault { }); }); xml.node("new-file", [&] () { - xml.attribute("path", "/cbe/cbe/control/create_snapshot"); + xml.attribute("path", "/tresor/tresor/control/create_snapshot"); xml.append_content("true"); }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); @@ -972,7 +958,7 @@ namespace File_vault { xml.node("vfs", [&] () { xml.node("dir", [&] () { - xml.attribute("name", "cbe"); + xml.attribute("name", "tresor"); xml.node("fs", [&] () { xml.attribute("writeable", "yes"); @@ -980,13 +966,13 @@ namespace File_vault { }); }); xml.node("new-file", [&] () { - xml.attribute("path", "/cbe/cbe/control/discard_snapshot"); + xml.attribute("path", "/tresor/tresor/control/discard_snapshot"); xml.append_content(Generation_string(generation)); }); }); xml.node("route", [&] () { - route_to_child_service(xml, "cbe_vfs", "File_system"); + route_to_child_service(xml, "tresor_vfs", "File_system"); gen_parent_routes_for_pd_rom_cpu_log(xml); }); }); diff --git a/repos/gems/src/app/file_vault/sync_to_cbe_vfs_init/target.mk b/repos/gems/src/app/file_vault/sync_to_cbe_vfs_init/target.mk deleted file mode 100644 index 9dd672f548..0000000000 --- a/repos/gems/src/app/file_vault/sync_to_cbe_vfs_init/target.mk +++ /dev/null @@ -1,3 +0,0 @@ -TARGET = file_vault-sync_to_cbe_vfs_init -LIBS = base vfs -SRC_CC = main.cc diff --git a/repos/gems/src/app/file_vault/sync_to_cbe_vfs_init/main.cc b/repos/gems/src/app/file_vault/sync_to_tresor_vfs_init/main.cc similarity index 86% rename from repos/gems/src/app/file_vault/sync_to_cbe_vfs_init/main.cc rename to repos/gems/src/app/file_vault/sync_to_tresor_vfs_init/main.cc index 0056a7726c..7384930d3d 100644 --- a/repos/gems/src/app/file_vault/sync_to_cbe_vfs_init/main.cc +++ b/repos/gems/src/app/file_vault/sync_to_tresor_vfs_init/main.cc @@ -1,5 +1,5 @@ /* - * \brief Helps synchronizing the CBE manager to the CBE-driver initialization + * \brief Synchronize the File Vault to the Tresor VFS initialization * \author Martin Stein * \date 2021-03-19 */ @@ -37,7 +37,7 @@ struct Main : private Vfs::Env::User { { Append_file { _root_dir, - Directory::Path("/cbe/cbe/current/data") }; + Directory::Path("/tresor/tresor/current/data") }; } _env.parent().exit(0); } diff --git a/repos/gems/src/app/file_vault/sync_to_tresor_vfs_init/target.mk b/repos/gems/src/app/file_vault/sync_to_tresor_vfs_init/target.mk new file mode 100644 index 0000000000..0ca9d3b1e8 --- /dev/null +++ b/repos/gems/src/app/file_vault/sync_to_tresor_vfs_init/target.mk @@ -0,0 +1,3 @@ +TARGET = file_vault-sync_to_tresor_vfs_init +LIBS = base vfs +SRC_CC = main.cc diff --git a/repos/gems/src/app/file_vault/target.mk b/repos/gems/src/app/file_vault/target.mk index 26b0a3db23..01bdb98872 100644 --- a/repos/gems/src/app/file_vault/target.mk +++ b/repos/gems/src/app/file_vault/target.mk @@ -1,6 +1,10 @@ -TARGET := file_vault -SRC_CC += main.cc menu_view_dialog.cc capacity.cc +TARGET := file_vault + +SRC_CC += main.cc menu_view_dialog.cc capacity.cc + INC_DIR += $(PRG_DIR) -LIBS += base sandbox vfs +INC_DIR += $(REP_DIR)/src/lib/tresor/include + +LIBS += base sandbox vfs CC_OPT += -Os diff --git a/repos/gems/src/app/file_vault/truncate_file/main.cc b/repos/gems/src/app/file_vault/truncate_file/main.cc index 6c929446dd..1ea06a01e0 100644 --- a/repos/gems/src/app/file_vault/truncate_file/main.cc +++ b/repos/gems/src/app/file_vault/truncate_file/main.cc @@ -1,5 +1,5 @@ /* - * \brief Helps synchronizing the CBE manager to the CBE-driver initialization + * \brief Small utility for truncating a given file * \author Martin Stein * \date 2021-03-19 */ diff --git a/repos/gems/src/app/file_vault/types.h b/repos/gems/src/app/file_vault/types.h index 2586a050ed..491567784b 100644 --- a/repos/gems/src/app/file_vault/types.h +++ b/repos/gems/src/app/file_vault/types.h @@ -15,16 +15,17 @@ #define _TYPES_H_ /* Genode includes */ -#include +#include namespace Genode { } namespace File_vault { - using namespace Cbe; + using namespace Tresor; using namespace Genode; using Node_name = String<32>; + using Passphrase_string = String<64>; class Tree_geometry { diff --git a/repos/gems/src/app/cbe_check/README b/repos/gems/src/app/tresor_check/README similarity index 62% rename from repos/gems/src/app/cbe_check/README rename to repos/gems/src/app/tresor_check/README index c51da4f9ea..900e07886d 100644 --- a/repos/gems/src/app/cbe_check/README +++ b/repos/gems/src/app/tresor_check/README @@ -1,4 +1,4 @@ -The cbe_check component check the meta data of a CBE device. This includes +The tresor_check component check the meta data of a Tresor device. This includes the tree for the virtual block device, free tree and meta tree. On success, the component exits with exit value 0, otherwise with exit value -1. @@ -15,5 +15,5 @@ component apart from the environment sessions: Examples ~~~~~~~~ -An example of how to use the cbe_init component can be found in the test script -'cbe/run/cbe_check.run'. +An example of how to use the tresor_init component can be found in the test script +'tresor/run/tresor_check.run'. diff --git a/repos/gems/src/app/cbe_check/config.xsd b/repos/gems/src/app/tresor_check/config.xsd similarity index 100% rename from repos/gems/src/app/cbe_check/config.xsd rename to repos/gems/src/app/tresor_check/config.xsd diff --git a/repos/gems/src/app/cbe_check/main.cc b/repos/gems/src/app/tresor_check/main.cc similarity index 71% rename from repos/gems/src/app/cbe_check/main.cc rename to repos/gems/src/app/tresor_check/main.cc index 36d0675db4..81066179a1 100644 --- a/repos/gems/src/app/cbe_check/main.cc +++ b/repos/gems/src/app/tresor_check/main.cc @@ -1,5 +1,5 @@ /* - * \brief Integration of the Consistent Block Encrypter (CBE) + * \brief Integration of the Tresor block encryption * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 @@ -20,28 +20,36 @@ #include -/* CBE-init includes */ -#include +/* gems includes */ +#include using namespace Genode; +namespace Tresor { + + char const *module_name(unsigned long) + { + return "?"; + } +} + class Main { private: - enum { TX_BUF_SIZE = Block::Session::TX_QUEUE_SIZE * Cbe::BLOCK_SIZE }; + enum { TX_BUF_SIZE = Block::Session::TX_QUEUE_SIZE * Tresor::BLOCK_SIZE }; Env &_env; Heap _heap { _env.ram(), _env.rm() }; Allocator_avl _blk_alloc { &_heap }; Block::Connection<> _blk { _env, &_blk_alloc, TX_BUF_SIZE }; Signal_handler
_blk_handler { _env.ep(), *this, &Main::_execute }; - Cbe::Request _blk_req { }; - Cbe::Io_buffer _blk_buf { }; - Cbe_check::Library _cbe_check { }; + Tresor::Request _blk_req { }; + Tresor::Io_buffer _blk_buf { }; + Tresor_check::Library _tresor_check { }; Genode::size_t _blk_ratio { - Cbe::BLOCK_SIZE / _blk.info().block_size }; + Tresor::BLOCK_SIZE / _blk.info().block_size }; void _execute() { @@ -49,16 +57,16 @@ class Main progress = false; - _cbe_check.execute(_blk_buf); - if (_cbe_check.execute_progress()) { + _tresor_check.execute(_blk_buf); + if (_tresor_check.execute_progress()) { progress = true; } - Cbe::Request const req { - _cbe_check.peek_completed_client_request() }; + Tresor::Request const req { + _tresor_check.peek_completed_client_request() }; if (req.valid()) { - _cbe_check.drop_completed_client_request(req); + _tresor_check.drop_completed_client_request(req); if (req.success()) { _env.parent().exit(0); } else { @@ -71,9 +79,9 @@ class Main while (_blk.tx()->ready_to_submit()) { - Cbe::Io_buffer::Index data_index { 0 }; - Cbe::Request request { }; - _cbe_check.has_io_request(request, data_index); + Tresor::Io_buffer::Index data_index { 0 }; + Tresor::Request request { }; + _tresor_check.has_io_request(request, data_index); if (!request.valid()) { break; @@ -85,28 +93,28 @@ class Main request.tag(data_index.value); Block::Packet_descriptor::Opcode op; switch (request.operation()) { - case Cbe::Request::Operation::READ: + case Tresor::Request::Operation::READ: op = Block::Packet_descriptor::READ; break; - case Cbe::Request::Operation::WRITE: + case Tresor::Request::Operation::WRITE: op = Block::Packet_descriptor::WRITE; break; default: throw Invalid_io_request(); } Block::Packet_descriptor packet { - _blk.alloc_packet(Cbe::BLOCK_SIZE), op, + _blk.alloc_packet(Tresor::BLOCK_SIZE), op, request.block_number() * _blk_ratio, request.count() * _blk_ratio }; - if (request.operation() == Cbe::Request::Operation::WRITE) { - *reinterpret_cast( + if (request.operation() == Tresor::Request::Operation::WRITE) { + *reinterpret_cast( _blk.tx()->packet_content(packet)) = _blk_buf.item(data_index); } _blk.tx()->try_submit_packet(packet); _blk_req = request; - _cbe_check.io_request_in_progress(data_index); + _tresor_check.io_request_in_progress(data_index); progress = true; } catch (Block::Session::Tx::Source::Packet_alloc_failed) { @@ -142,17 +150,17 @@ class Main _blk_req.success(packet.succeeded()); - Cbe::Io_buffer::Index const data_index { _blk_req.tag() }; + Tresor::Io_buffer::Index const data_index { _blk_req.tag() }; bool const success { _blk_req.success() }; if (read && success) { _blk_buf.item(data_index) = - *reinterpret_cast( + *reinterpret_cast( _blk.tx()->packet_content(packet)); } - _cbe_check.io_request_completed(data_index, success); + _tresor_check.io_request_completed(data_index, success); _blk.tx()->release_packet(packet); - _blk_req = Cbe::Request(); + _blk_req = Tresor::Request(); progress = true; } } @@ -171,13 +179,13 @@ class Main return; } - if (!_cbe_check.client_request_acceptable()) { + if (!_tresor_check.client_request_acceptable()) { error("failed to submit request"); _env.parent().exit(-1); } - _cbe_check.submit_client_request( - Cbe::Request( - Cbe::Request::Operation::READ, + _tresor_check.submit_client_request( + Tresor::Request( + Tresor::Request::Operation::READ, false, 0, 0, 0, 0, 0)); _blk.tx_channel()->sigh_ack_avail(_blk_handler); @@ -207,9 +215,9 @@ void Component::construct(Genode::Env &env) timer.msleep(3000); Genode::log("start checking"); - Cbe::assert_valid_object_size(); + Tresor::assert_valid_object_size(); - cbe_check_cxx_init(); + tresor_check_cxx_init(); static Main main(env); } diff --git a/repos/gems/src/app/cbe_dump/target.mk b/repos/gems/src/app/tresor_check/target.mk similarity index 60% rename from repos/gems/src/app/cbe_dump/target.mk rename to repos/gems/src/app/tresor_check/target.mk index 3b1870c2cb..7a02b65167 100644 --- a/repos/gems/src/app/cbe_dump/target.mk +++ b/repos/gems/src/app/tresor_check/target.mk @@ -1,9 +1,9 @@ REQUIRES += x86_64 -TARGET := cbe_dump +TARGET := tresor_check SRC_CC += main.cc INC_DIR += $(PRG_DIR) -LIBS += base cbe_dump_cxx +LIBS += base tresor_check_cxx CONFIG_XSD = config.xsd diff --git a/repos/gems/src/app/cbe_init/README b/repos/gems/src/app/tresor_init/README similarity index 83% rename from repos/gems/src/app/cbe_init/README rename to repos/gems/src/app/tresor_init/README index 7fb8c27615..71c72149d3 100644 --- a/repos/gems/src/app/cbe_init/README +++ b/repos/gems/src/app/tresor_init/README @@ -1,4 +1,4 @@ -The cbe_init component creates a fresh CBE device (virtual block device, +The tresor_init component creates a fresh Tresor device (virtual block device, free tree and superblocks) on a back-end block-device according to the configured parameters. On success, the component exits with exit value 0, otherwise with exit value -1. @@ -37,13 +37,13 @@ This is a short description of the tags and attributes: :config.virtual-block-device.nr_of_leafs: Mandatory. The number of leafs of the tree that are used. This defines the - number of virtual blocks available to the CBE device. This number must be + number of virtual blocks available to the Tresor device. This number must be less or equal the number of leafs of the tree, which results from the number of tree levels and the tree degree. :config.free-tree: Mandatory. Contains parameters for the tree that is used for managing the - spare blocks of the CBE device. + spare blocks of the Tresor device. :config.free-tree.nr_of_levels: Mandatory. Number of tree levels including the leafs and the root. @@ -54,7 +54,7 @@ This is a short description of the tags and attributes: :config.free-tree.nr_of_leafs: Mandatory. The number of leafs of the tree that are used. This defines the - number of spare blocks available to the CBE device. This number must be less + number of spare blocks available to the Tresor device. This number must be less or equal the number of leafs of the tree, which results from the number of tree levels and the tree degree. @@ -71,5 +71,5 @@ component apart from the environment sessions: Examples ~~~~~~~~ -An example of how to use the cbe_init component can be found in the test script -'cbe/run/cbe_init_dev.run'. +An example of how to use the tresor_init component can be found in the test script +'tresor/run/tresor_init_dev.run'. diff --git a/repos/gems/src/app/cbe_init/config.xsd b/repos/gems/src/app/tresor_init/config.xsd similarity index 100% rename from repos/gems/src/app/cbe_init/config.xsd rename to repos/gems/src/app/tresor_init/config.xsd diff --git a/repos/gems/src/app/tresor_init/main.cc b/repos/gems/src/app/tresor_init/main.cc new file mode 100644 index 0000000000..6a45214c3a --- /dev/null +++ b/repos/gems/src/app/tresor_init/main.cc @@ -0,0 +1,236 @@ +/* + * \brief Integration of the Tresor block encryption + * \author Martin Stein + * \author Josef Soentgen + * \date 2020-11-10 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* Genode includes */ +#include +#include +#include +#include +#include +#include +#include +#include + +/* tresor includes */ +#include +#include +#include +#include +#include +#include +#include +#include + + +enum { VERBOSE = 0 }; + +using namespace Genode; +using namespace Tresor; + +static Block_allocator *_block_allocator_ptr; + + +Genode::uint64_t block_allocator_first_block() +{ + if (!_block_allocator_ptr) { + struct Exception_1 { }; + throw Exception_1(); + } + + return _block_allocator_ptr->first_block(); +} + + +Genode::uint64_t block_allocator_nr_of_blks() +{ + if (!_block_allocator_ptr) { + struct Exception_1 { }; + throw Exception_1(); + } + + return _block_allocator_ptr->nr_of_blks(); +} + + +class Main +: + private Vfs::Env::User, + private Tresor::Module_composition, + public Tresor::Module +{ + private: + + /* + * Noncopyable + */ + Main(Main const &) = delete; + Main &operator = (Main const &) = delete; + + 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 }; + Vfs::File_system &_vfs { _vfs_env.root_dir() }; + Signal_handler
_sigh { _env.ep(), *this, &Main::_execute }; + + 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") }; + Block_allocator _block_allocator { NR_OF_SUPERBLOCK_SLOTS }; + Vbd_initializer _vbd_initializer { }; + Ft_initializer _ft_initializer { }; + Sb_initializer _sb_initializer { }; + + /** + * Vfs::Env::User interface + */ + void wakeup_vfs_user() override { _sigh.local_submit(); } + + void _execute() + { + bool progress { true }; + while (progress) { + + progress = false; + execute_modules(progress); + } + + _vfs_env.io().commit(); + + if (_state == COMPLETE) + _env.parent().exit(0); + } + + /**************** + ** Module API ** + ****************/ + + enum State { INVALID, PENDING, IN_PROGRESS, COMPLETE }; + + State _state { INVALID }; + + bool _peek_generated_request(Genode::uint8_t *buf_ptr, + Genode::size_t buf_size) override + { + if (_state != PENDING) + return false; + + Sb_initializer_request::create( + buf_ptr, buf_size, COMMAND_POOL, 0, + (unsigned long)Sb_initializer_request::INIT, + (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()); + + return true; + } + + void _drop_generated_request(Module_request &mod_req) override + { + if (_state != PENDING) { + class Exception_1 { }; + throw Exception_1 { }; + } + + switch (mod_req.dst_module_id()) { + case SB_INITIALIZER: + _state = IN_PROGRESS; + break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } + } + + void generated_request_complete(Module_request &mod_req) override + { + if (_state != IN_PROGRESS) { + class Exception_1 { }; + throw Exception_1 { }; + } + + switch (mod_req.dst_module_id()) { + case SB_INITIALIZER: + _state = COMPLETE; + break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } + } + + public: + + Main(Env &env) : _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(BLOCK_ALLOCATOR, _block_allocator); + add_module(VBD_INITIALIZER, _vbd_initializer); + add_module(FT_INITIALIZER, _ft_initializer); + add_module(SB_INITIALIZER, _sb_initializer); + + _block_allocator_ptr = &_block_allocator; + + Xml_node const &config { _config_rom.xml() }; + try { + _cfg.construct(config); + _state = PENDING; + + _execute(); + } + catch (Tresor_init::Configuration::Invalid) { + error("bad configuration"); + _env.parent().exit(-1); + } + } +}; + + +void Component::construct(Genode::Env &env) +{ + env.exec_static_constructors(); + + static Main main(env); +} + + +/* + * XXX Libc::Component::construct is needed for linking libcrypto + * because it depends on the libc but does not need to be + * executed. + */ +namespace Libc { + struct Env; + + struct Component + { + void construct(Libc::Env &); + }; +} + + +void Libc::Component::construct(Libc::Env &) { } diff --git a/repos/gems/src/app/tresor_init/target.mk b/repos/gems/src/app/tresor_init/target.mk new file mode 100644 index 0000000000..4f8be3feda --- /dev/null +++ b/repos/gems/src/app/tresor_init/target.mk @@ -0,0 +1,10 @@ +TARGET := tresor_init + +SRC_CC += main.cc + +INC_DIR += $(PRG_DIR) + +LIBS += base +LIBS += tresor + +CONFIG_XSD := config.xsd diff --git a/repos/gems/src/app/cbe_init_trust_anchor/component.cc b/repos/gems/src/app/tresor_init_trust_anchor/component.cc similarity index 97% rename from repos/gems/src/app/cbe_init_trust_anchor/component.cc rename to repos/gems/src/app/tresor_init_trust_anchor/component.cc index a9ad5dec80..bb26c33951 100644 --- a/repos/gems/src/app/cbe_init_trust_anchor/component.cc +++ b/repos/gems/src/app/tresor_init_trust_anchor/component.cc @@ -1,5 +1,5 @@ /* - * \brief Integration of the Consistent Block Encrypter (CBE) + * \brief Integration of the Tresor block encryption * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 @@ -22,8 +22,8 @@ #include #include -/* CBE includes */ -#include +/* Tresor includes */ +#include using namespace Genode; diff --git a/repos/gems/src/app/tresor_init_trust_anchor/target.mk b/repos/gems/src/app/tresor_init_trust_anchor/target.mk new file mode 100644 index 0000000000..10059681c8 --- /dev/null +++ b/repos/gems/src/app/tresor_init_trust_anchor/target.mk @@ -0,0 +1,7 @@ +TARGET:= tresor_init_trust_anchor + +SRC_CC := component.cc +INC_DIR += $(PRG_DIR) +INC_DIR += $(REP_DIR)/src/lib/tresor/include + +LIBS := base vfs diff --git a/repos/gems/src/app/cbe_tester/crypto.cc b/repos/gems/src/app/tresor_tester/crypto.cc similarity index 89% rename from repos/gems/src/app/cbe_tester/crypto.cc rename to repos/gems/src/app/tresor_tester/crypto.cc index 764c31bbac..ae0c779ee6 100644 --- a/repos/gems/src/app/cbe_tester/crypto.cc +++ b/repos/gems/src/app/tresor_tester/crypto.cc @@ -15,7 +15,7 @@ #include using namespace Genode; -using namespace Cbe; +using namespace Tresor; using namespace Vfs; @@ -92,7 +92,7 @@ Crypto::Result Crypto::add_key(Key const &key) } -Crypto::Result Crypto::remove_key(Cbe::Key::Id key_id) +Crypto::Result Crypto::remove_key(Tresor::Key::Id key_id) { size_t written_bytes = 0; _remove_key_handle.seek(0); @@ -117,7 +117,7 @@ Crypto::Result Crypto::remove_key(Cbe::Key::Id key_id) } -void Crypto::submit_request(Cbe::Request const &request, +void Crypto::submit_request(Tresor::Request const &request, Operation op, Crypto_plain_buffer::Index plain_buf_idx, Crypto_cipher_buffer::Index cipher_buf_idx) @@ -155,23 +155,23 @@ void Crypto::submit_request(Cbe::Request const &request, } -Cbe::Request Crypto::peek_completed_encryption_request() const +Tresor::Request Crypto::peek_completed_encryption_request() const { if (_job.state != Job_state::COMPLETE || _job.op != Operation::ENCRYPT_BLOCK) { - return Cbe::Request { }; + return Tresor::Request { }; } return _job.request; } -Cbe::Request Crypto::peek_completed_decryption_request() const +Tresor::Request Crypto::peek_completed_decryption_request() const { if (_job.state != Job_state::COMPLETE || _job.op != Operation::DECRYPT_BLOCK) { - return Cbe::Request { }; + return Tresor::Request { }; } return _job.request; } @@ -196,13 +196,13 @@ void Crypto::_execute_decrypt_block(Job &job, switch (job.state) { case Job_state::SUBMITTED: { - job.handle->seek(job.request.block_number() * Cbe::BLOCK_SIZE); + job.handle->seek(job.request.block_number() * Tresor::BLOCK_SIZE); size_t written_bytes = 0; Const_byte_range_ptr const src( reinterpret_cast(&cipher_buf.item(job.cipher_buf_idx)), - sizeof(Cbe::Block_data)); + sizeof(Tresor::Block)); job.handle->fs().write( job.handle, src, written_bytes); @@ -212,10 +212,10 @@ void Crypto::_execute_decrypt_block(Job &job, } case Job_state::OP_WRITTEN_TO_VFS_HANDLE: { - job.handle->seek(job.request.block_number() * Cbe::BLOCK_SIZE); + job.handle->seek(job.request.block_number() * Tresor::BLOCK_SIZE); bool const success { job.handle->fs().queue_read( - job.handle, sizeof (Cbe::Block_data)) }; + job.handle, sizeof (Tresor::Block)) }; if (!success) { return; @@ -230,7 +230,7 @@ void Crypto::_execute_decrypt_block(Job &job, Byte_range_ptr const dst( reinterpret_cast(&plain_buf.item(job.plain_buf_idx)), - sizeof(Cbe::Block_data)); + sizeof(Tresor::Block)); Read_result const result = job.handle->fs().complete_read(job.handle, dst, read_bytes); @@ -260,14 +260,14 @@ void Crypto::_execute_encrypt_block(Job &job, switch (job.state) { case Job_state::SUBMITTED: { - job.handle->seek(job.request.block_number() * Cbe::BLOCK_SIZE); + job.handle->seek(job.request.block_number() * Tresor::BLOCK_SIZE); size_t written_bytes = 0; Const_byte_range_ptr const src( reinterpret_cast( &plain_buf.item(job.plain_buf_idx)), - sizeof(Cbe::Block_data)); + sizeof(Tresor::Block)); job.handle->fs().write(job.handle, src, written_bytes); @@ -277,10 +277,10 @@ void Crypto::_execute_encrypt_block(Job &job, } case Job_state::OP_WRITTEN_TO_VFS_HANDLE: { - job.handle->seek(job.request.block_number() * Cbe::BLOCK_SIZE); + job.handle->seek(job.request.block_number() * Tresor::BLOCK_SIZE); bool success { job.handle->fs().queue_read( - job.handle, sizeof (Cbe::Block_data)) }; + job.handle, sizeof (Tresor::Block)) }; if (!success) { return; @@ -295,7 +295,7 @@ void Crypto::_execute_encrypt_block(Job &job, Byte_range_ptr const dst( reinterpret_cast(&cipher_buf.item(job.cipher_buf_idx)), - sizeof (Cbe::Block_data)); + sizeof (Tresor::Block)); Read_result const result = job.handle->fs().complete_read(job.handle, dst, read_bytes); diff --git a/repos/gems/src/app/tresor_tester/main.cc b/repos/gems/src/app/tresor_tester/main.cc new file mode 100644 index 0000000000..ddcd0744a4 --- /dev/null +++ b/repos/gems/src/app/tresor_tester/main.cc @@ -0,0 +1,1495 @@ +/* + * \brief Tool for running tests and benchmarks on Tresor library + * \author Martin Stein + * \date 2020-08-26 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +/* base includes */ +#include +#include +#include +#include +#include +#include + +/* tresor includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* tresor tester includes */ +#include + +using namespace Genode; +using namespace Tresor; +using namespace Vfs; + +namespace Tresor_tester { + + class Main; +} + + +template +T read_attribute(Xml_node const &node, + char const *attr) +{ + T value { }; + + if (!node.has_attribute(attr)) { + + error("<", node.type(), "> node misses attribute '", attr, "'"); + class Attribute_missing { }; + throw Attribute_missing { }; + } + if (!node.attribute(attr).value(value)) { + + error("<", node.type(), "> node has malformed '", attr, "' attribute"); + class Malformed_attribute { }; + throw Malformed_attribute { }; + } + return value; +} + + +class Log_node +{ + private: + + String<128> const _string; + + public: + + Log_node(Xml_node const &node) + : + _string { node.attribute_value("string", String<128> { }) } + { } + + String<128> const &string() const { return _string; } + + void print(Genode::Output &out) const + { + Genode::print(out, "string=\"", _string, "\""); + } +}; + + +class Benchmark_node +{ + public: + + using Label = String<128>; + + enum Operation { START, STOP }; + + private: + + Operation const _op; + bool const _label_avail; + Label const _label; + + Operation _read_op_attr(Xml_node const &node) + { + class Attribute_missing { }; + if (!node.has_attribute("op")) { + throw Attribute_missing { }; + } + if (node.attribute("op").has_value("start")) { + return Operation::START; + } + if (node.attribute("op").has_value("stop")) { + return Operation::STOP; + } + class Malformed_attribute { }; + throw Malformed_attribute { }; + } + + static char const *_op_to_string(Operation op) + { + switch (op) { + case START: return "start"; + case STOP: return "stop"; + } + return "?"; + } + + public: + + bool has_attr_label() const + { + return _op == Operation::START; + } + + Benchmark_node(Xml_node const &node) + : + _op { _read_op_attr(node) }, + _label_avail { has_attr_label() && node.has_attribute("label") }, + _label { _label_avail ? + node.attribute_value("label", Label { }) : + Label { } } + { } + + Operation op() const { return _op; } + bool label_avail() const { return _label_avail; } + Label const &label() const { return _label; } + + void print(Genode::Output &out) const + { + Genode::print(out, "op=", _op_to_string(_op)); + if (_label_avail) { + Genode::print(out, " label=", _label); + } + } +}; + + +class Benchmark +{ + private: + + enum State { STARTED, STOPPED }; + + Genode::Env &_env; + Timer::Connection _timer { _env }; + State _state { STOPPED }; + Microseconds _start_time { 0 }; + uint64_t _nr_of_virt_blks_read { 0 }; + uint64_t _nr_of_virt_blks_written { 0 }; + Constructible _start_node { }; + uint64_t _id { 0 }; + + public: + + Benchmark(Genode::Env &env) : _env { env } { } + + void submit_request(Benchmark_node const &node) + { + switch (node.op()) { + case Benchmark_node::START: + + if (_state != STOPPED) { + class Bad_state_to_start { }; + throw Bad_state_to_start { }; + } + _id++; + _nr_of_virt_blks_read = 0; + _nr_of_virt_blks_written = 0; + _state = STARTED; + _start_node.construct(node); + _start_time = _timer.curr_time().trunc_to_plain_us(); + break; + + case Benchmark_node::STOP: + + if (_state != STARTED) { + class Bad_state_to_stop { }; + throw Bad_state_to_stop { }; + } + uint64_t const stop_time_us { + _timer.curr_time().trunc_to_plain_us().value }; + + log(""); + if (_start_node->label_avail()) { + log("Benchmark result \"", _start_node->label(), "\""); + } else { + log("Benchmark result (command ID ", _id, ")"); + } + + double const passed_time_sec { + (double)(stop_time_us - _start_time.value) / + (double)(1000 * 1000) }; + + log(" Ran ", passed_time_sec, " seconds."); + + if (_nr_of_virt_blks_read != 0) { + + uint64_t const bytes_read { + _nr_of_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 (_nr_of_virt_blks_written != 0) { + + uint64_t bytes_written { + _nr_of_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(""); + _state = STOPPED; + break; + } + } + + void raise_nr_of_virt_blks_read() { _nr_of_virt_blks_read++; } + void raise_nr_of_virt_blks_written() { _nr_of_virt_blks_written++; } +}; + + +class Trust_anchor_node +{ + private: + + using Operation = Trust_anchor_request::Type; + + Operation const _op; + String<64> const _passphrase; + + Operation _read_op_attr(Xml_node const &node) + { + class Attribute_missing { }; + if (!node.has_attribute("op")) { + throw Attribute_missing { }; + } + if (node.attribute("op").has_value("initialize")) { + return Operation::INITIALIZE; + } + class Malformed_attribute { }; + throw Malformed_attribute { }; + } + + public: + + Trust_anchor_node(Xml_node const &node) + : + _op { _read_op_attr(node) }, + _passphrase { has_attr_passphrase() ? + node.attribute_value("passphrase", String<64>()) : + String<64>() } + { } + + Operation op() const { return _op; } + String<64> const &passphrase() const { return _passphrase; } + + bool has_attr_passphrase() const + { + return _op == Operation::INITIALIZE; + } + + void print(Genode::Output &out) const + { + Genode::print(out, "op=", + Trust_anchor_request::type_to_string(_op)); + + if (has_attr_passphrase()) { + Genode::print(out, " passphrase=", _passphrase); + } + } +}; + + +class Request_node +{ + private: + + using Operation = Tresor::Request::Operation; + + Operation const _op; + Virtual_block_address const _vba; + Number_of_blocks const _count; + bool const _sync; + bool const _salt_avail; + uint64_t const _salt; + + Operation _read_op_attr(Xml_node const &node) + { + class Attribute_missing { }; + if (!node.has_attribute("op")) { + throw Attribute_missing { }; + } + if (node.attribute("op").has_value("read")) { + return Operation::READ; + } + if (node.attribute("op").has_value("write")) { + return Operation::WRITE; + } + 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("extend_ft")) { + return Operation::EXTEND_FT; + } + 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; + } + class Malformed_attribute { }; + throw Malformed_attribute { }; + } + + public: + + Request_node(Xml_node const &node) + : + _op { _read_op_attr(node) }, + _vba { has_attr_vba() ? + read_attribute(node, "vba") : 0 }, + _count { has_attr_count() ? + read_attribute(node, "count") : 0 }, + _sync { read_attribute(node, "sync") }, + _salt_avail { has_attr_salt() ? + node.has_attribute("salt") : false }, + _salt { has_attr_salt() && _salt_avail ? + read_attribute(node, "salt") : 0 } + { } + + Operation op() const { return _op; } + Virtual_block_address vba() const { return _vba; } + Number_of_blocks count() const { return _count; } + bool sync() const { return _sync; } + bool salt_avail() const { return _salt_avail; } + uint64_t salt() const { return _salt; } + + bool has_attr_vba() const + { + return _op == Operation::READ || + _op == Operation::WRITE || + _op == Operation::SYNC; + } + + bool has_attr_salt() const + { + return _op == Operation::READ || + _op == Operation::WRITE; + } + + bool has_attr_count() const + { + return _op == Operation::READ || + _op == Operation::WRITE || + _op == Operation::SYNC || + _op == Operation::EXTEND_FT || + _op == Operation::EXTEND_VBD; + } + + void print(Genode::Output &out) const + { + Genode::print(out, "op=", to_string(_op)); + if (has_attr_vba()) { + Genode::print(out, " vba=", _vba); + } + if (has_attr_count()) { + Genode::print(out, " count=", _count); + } + Genode::print(out, " sync=", _sync); + if (_salt_avail) { + Genode::print(out, " salt=", _salt); + } + } +}; + + +class Command : public Fifo::Element +{ + public: + + enum Type + { + INVALID, + REQUEST, + TRUST_ANCHOR, + BENCHMARK, + CONSTRUCT, + DESTRUCT, + INITIALIZE, + CHECK, + LIST_SNAPSHOTS, + LOG + }; + + enum State + { + PENDING, + IN_PROGRESS, + COMPLETED + }; + + private: + + Type _type { INVALID }; + uint32_t _id { 0 }; + State _state { PENDING }; + bool _success { false }; + bool _data_mismatch { false }; + Constructible _request_node { }; + Constructible _trust_anchor_node { }; + Constructible _benchmark_node { }; + Constructible _log_node { }; + Constructible _initialize { }; + + char const *_state_to_string() const + { + switch (_state) { + case PENDING: return "pending"; + case IN_PROGRESS: return "in_progress"; + case COMPLETED: return "completed"; + } + return "?"; + } + + char const *_type_to_string() const + { + 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 LIST_SNAPSHOTS: return "list_snapshots"; + case LOG: return "log"; + } + return "?"; + } + + public: + + Command() { } + + Command(Type type, + Xml_node const &node, + uint32_t id) + : + _type { 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; + } + } + + Command(Command &other) + : + _type { other._type }, + _id { other._id }, + _state { other._state }, + _success { other._success } + { + switch (_type) { + case INITIALIZE: _initialize.construct(*other._initialize); break; + case REQUEST: _request_node.construct(*other._request_node); break; + case TRUST_ANCHOR: _trust_anchor_node.construct(*other._trust_anchor_node); break; + case BENCHMARK: _benchmark_node.construct(*other._benchmark_node); break; + case LOG: _log_node.construct(*other._log_node); break; + default: break; + } + } + + bool has_attr_data_mismatch() const + { + return + _type == REQUEST && + _request_node->op() == Tresor::Request::Operation::READ && + _request_node->salt_avail(); + } + + bool synchronize() const + { + class Bad_type { }; + switch (_type) { + case INITIALIZE: return true; + case BENCHMARK: return true; + case CONSTRUCT: return true; + case DESTRUCT: return true; + case CHECK: return true; + case TRUST_ANCHOR: return true; + case LIST_SNAPSHOTS: return true; + case LOG: return true; + case REQUEST: return _request_node->sync(); + case INVALID: throw Bad_type { }; + } + throw Bad_type { }; + } + + static Type type_from_string(String<64> 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 == "list-snapshots") { return LIST_SNAPSHOTS; } + if (str == "log") { return LOG; } + class Bad_string { }; + throw Bad_string { }; + } + + void print(Genode::Output &out) const + { + Genode::print(out, "id=", _id, " type=", _type_to_string()); + class Bad_type { }; + switch (_type) { + case INITIALIZE: Genode::print(out, " cfg=(", *_initialize, ")"); break; + case REQUEST: Genode::print(out, " cfg=(", *_request_node, ")"); break; + case TRUST_ANCHOR: Genode::print(out, " cfg=(", *_trust_anchor_node, ")"); break; + case BENCHMARK: Genode::print(out, " cfg=(", *_benchmark_node, ")"); break; + case LOG: Genode::print(out, " cfg=(", *_log_node, ")"); break; + case INVALID: break; + case CHECK: break; + case CONSTRUCT: break; + case DESTRUCT: break; + case LIST_SNAPSHOTS: break; + } + Genode::print(out, " succ=", _success); + if (has_attr_data_mismatch()) { + Genode::print(out, " bad_data=", _data_mismatch); + } + Genode::print(out, " state=", _state_to_string()); + } + + Type type () const { return _type ; } + State state () const { return _state ; } + uint32_t 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; } +}; + + +class Command_pool : public Module { + + private: + + Allocator &_alloc; + Verbose_node const &_verbose_node; + Fifo _cmd_queue { }; + uint32_t _next_command_id { 0 }; + unsigned long _nr_of_uncompleted_cmds { 0 }; + unsigned long _nr_of_errors { 0 }; + Tresor::Block _blk_data { }; + + void _read_cmd_node(Xml_node const &node, + Command::Type cmd_type) + { + Command &cmd { + *new (_alloc) Command(cmd_type, node, _next_command_id++) }; + + _nr_of_uncompleted_cmds++; + _cmd_queue.enqueue(cmd); + + if (_verbose_node.cmd_pool_cmd_pending()) { + log("cmd pending: ", cmd); + } + } + + static void _generate_blk_data(Tresor::Block &blk_data, + Virtual_block_address vba, + uint64_t salt) + { + for (uint64_t idx { 0 }; idx + sizeof(vba) + sizeof(salt) <= BLOCK_SIZE; ) { + + memcpy(&blk_data.bytes[idx], &vba, sizeof(vba)); + idx += sizeof(vba); + memcpy(&blk_data.bytes[idx], &salt, sizeof(salt)); + idx += sizeof(salt); + vba += idx + salt; + salt += idx + vba; + } + } + + + /************ + ** Module ** + ************/ + + bool _peek_generated_request(Genode::uint8_t *buf_ptr, + Genode::size_t buf_size) override + { + { + Command const cmd { + peek_pending_command(Command::TRUST_ANCHOR) }; + + if (cmd.type() != Command::INVALID) { + + Trust_anchor_node const &node { cmd.trust_anchor_node() }; + switch (node.op()) { + case Trust_anchor_request::INITIALIZE: + + Trust_anchor_request::create( + buf_ptr, buf_size, COMMAND_POOL, cmd.id(), + Trust_anchor_request::INITIALIZE, + nullptr, nullptr, node.passphrase().string(), + nullptr); + + return true; + + default: break; + } + class Exception_1 { }; + throw Exception_1 { }; + } + } + + { + Command const cmd { + peek_pending_command(Command::INITIALIZE) }; + + if (cmd.type() != Command::INVALID) { + + Tresor_init::Configuration const &cfg { cmd.initialize() }; + + Sb_initializer_request::create( + buf_ptr, buf_size, COMMAND_POOL, cmd.id(), + Sb_initializer_request::INIT, + (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()); + + return true; + } + } + + { + Command const cmd { + peek_pending_command(Command::CHECK) }; + + if (cmd.type() != Command::INVALID) { + + Sb_check_request::create( + buf_ptr, buf_size, COMMAND_POOL, cmd.id(), + Sb_check_request::CHECK); + + return true; + } + } + return false; + } + + void _drop_generated_request(Module_request &mod_req) override + { + switch (mod_req.dst_module_id()) { + case TRUST_ANCHOR: + { + Trust_anchor_request const &ta_req { + *static_cast(&mod_req)}; + + if (ta_req.type() != Trust_anchor_request::INITIALIZE) { + class Exception_2 { }; + throw Exception_2 { }; + } + mark_command_in_progress(ta_req.src_request_id()); + break; + } + case SB_INITIALIZER: + { + Sb_initializer_request const &sb_req { + *static_cast(&mod_req)}; + + if (sb_req.type() != Sb_initializer_request::INIT) { + class Exception_4 { }; + throw Exception_4 { }; + } + mark_command_in_progress(sb_req.src_request_id()); + break; + } + case SB_CHECK: + { + Sb_check_request const &req { + *static_cast(&mod_req)}; + + if (req.type() != Sb_check_request::CHECK) { + class Exception_3 { }; + throw Exception_3 { }; + } + mark_command_in_progress(req.src_request_id()); + break; + } + default: + { + class Exception_1 { }; + throw Exception_1 { }; + } + } + } + + void generated_request_complete(Module_request &mod_req) override + { + switch (mod_req.dst_module_id()) { + case TRUST_ANCHOR: + { + Trust_anchor_request const &ta_req { + *static_cast(&mod_req)}; + + if (ta_req.type() != Trust_anchor_request::INITIALIZE) { + class Exception_2 { }; + throw Exception_2 { }; + } + mark_command_completed( + ta_req.src_request_id(), ta_req.success()); + break; + } + case SB_INITIALIZER: + { + Sb_initializer_request const &sb_req { + *static_cast(&mod_req)}; + + if (sb_req.type() != Sb_initializer_request::INIT) { + class Exception_2 { }; + throw Exception_2 { }; + } + mark_command_completed( + sb_req.src_request_id(), sb_req.success()); + break; + } + case SB_CHECK: + { + Sb_check_request const &sb_req { + *static_cast(&mod_req)}; + + if (sb_req.type() != Sb_check_request::CHECK) { + class Exception_2 { }; + throw Exception_2 { }; + } + mark_command_completed( + sb_req.src_request_id(), sb_req.success()); + break; + } + case REQUEST_POOL: + { + Request const &rp_req { + *static_cast(&mod_req)}; + + mark_command_completed( + rp_req.src_request_id(), rp_req.success()); + break; + } + default: + { + class Exception_1 { }; + throw Exception_1 { }; + } + } + } + + public: + + Command_pool(Allocator &alloc, + Xml_node const &config_xml, + Verbose_node const &verbose_node) + : + _alloc { alloc }, + _verbose_node { verbose_node } + { + config_xml.sub_node("commands").for_each_sub_node( + [&] (Xml_node const &node) + { + _read_cmd_node(node, Command::type_from_string(node.type())); + }); + } + + Command peek_pending_command(Command::Type type) const + { + Reconstructible resulting_cmd { }; + bool first_uncompleted_cmd { true }; + bool exit_loop { false }; + _cmd_queue.for_each([&] (Command &curr_cmd) + { + if (exit_loop) { + return; + } + switch (curr_cmd.state()) { + case Command::PENDING: + + /* + * Stop iterating at the first uncompleted command + * that needs to be synchronized. + */ + if (curr_cmd.synchronize()) { + if (curr_cmd.type() == type && first_uncompleted_cmd) { + resulting_cmd.construct(curr_cmd); + } + exit_loop = true; + return; + } + /* + * Select command and stop iterating if the command is of + * the desired type. + */ + if (curr_cmd.type() == type) { + resulting_cmd.construct(curr_cmd); + exit_loop = true; + } + first_uncompleted_cmd = false; + return; + + case Command::IN_PROGRESS: + + /* + * Stop iterating at the first uncompleted command + * that needs to be synchronized. + */ + if (curr_cmd.synchronize()) { + exit_loop = true; + return; + } + first_uncompleted_cmd = false; + return; + + case Command::COMPLETED: + + return; + } + }); + return *resulting_cmd; + } + + void mark_command_in_progress(Module_request_id cmd_id) + { + bool exit_loop { false }; + _cmd_queue.for_each([&] (Command &cmd) + { + if (exit_loop) { + return; + } + if (cmd.id() == cmd_id) { + if (cmd.state() != Command::PENDING) { + class Bad_state { }; + throw Bad_state { }; + } + cmd.state(Command::IN_PROGRESS); + exit_loop = true; + + if (_verbose_node.cmd_pool_cmd_in_progress()) { + log("cmd in progress: ", cmd); + } + } + }); + } + + void mark_command_completed(Module_request_id cmd_id, + bool success) + { + bool exit_loop { false }; + _cmd_queue.for_each([&] (Command &cmd) + { + if (exit_loop) { + return; + } + if (cmd.id() == cmd_id) { + + if (cmd.state() != Command::IN_PROGRESS) { + + class Bad_state { }; + throw Bad_state { }; + } + cmd.state(Command::COMPLETED); + _nr_of_uncompleted_cmds--; + cmd.success(success); + if (!cmd.success()) { + error("cmd failed"); + _nr_of_errors++; + } + exit_loop = true; + + if (_verbose_node.cmd_pool_cmd_completed()) { + log("cmd completed: ", cmd); + } + } + }); + } + + void generate_blk_data(uint64_t tresor_req_tag, + Virtual_block_address vba, + Tresor::Block &blk_data) const + { + bool exit_loop { false }; + _cmd_queue.for_each([&] (Command &cmd) + { + if (exit_loop) { + return; + } + if (cmd.id() != tresor_req_tag) { + return; + } + if (cmd.type() != Command::REQUEST) { + class Bad_command_type { }; + throw Bad_command_type { }; + } + Request_node const &req_node { cmd.request_node() }; + if (req_node.salt_avail()) { + + _generate_blk_data(blk_data, vba, req_node.salt()); + } + exit_loop = true; + }); + } + + void verify_blk_data(uint64_t tresor_req_tag, + Virtual_block_address vba, + Tresor::Block &blk_data) + { + bool exit_loop { false }; + _cmd_queue.for_each([&] (Command &cmd) + { + if (exit_loop) { + return; + } + if (cmd.id() != tresor_req_tag) { + return; + } + if (cmd.type() != Command::REQUEST) { + class Bad_command_type { }; + throw Bad_command_type { }; + } + Request_node const &req_node { cmd.request_node() }; + if (req_node.salt_avail()) { + Tresor::Block gen_blk_data { }; + _generate_blk_data(gen_blk_data, vba, req_node.salt()); + + if (memcmp(&blk_data, &gen_blk_data, BLOCK_SIZE)) { + + cmd.data_mismatch(true); + error("client data mismatch"); + _nr_of_errors++; + + if (_verbose_node.client_data_mismatch()) { + log("client data mismatch: vba=", vba, + " req_tag=(", tresor_req_tag, ")"); + log("client data should be: ", gen_blk_data); + log("client data is: ", blk_data); + class Client_data_mismatch { }; + throw Client_data_mismatch { }; + } + } + } + exit_loop = true; + }); + } + + void print_failed_cmds() const + { + _cmd_queue.for_each([&] (Command &cmd) + { + if (cmd.state() != Command::COMPLETED) { + return; + } + if (cmd.success() && + (!cmd.has_attr_data_mismatch() || !cmd.data_mismatch())) { + + return; + } + log("cmd failed: ", cmd); + }); + } + + unsigned long nr_of_uncompleted_cmds() { return _nr_of_uncompleted_cmds; } + unsigned long nr_of_errors() { return _nr_of_errors; } +}; + + +static Block_allocator *_block_allocator_ptr; + + +Genode::uint64_t block_allocator_first_block() +{ + if (!_block_allocator_ptr) { + struct Exception_1 { }; + throw Exception_1(); + } + + return _block_allocator_ptr->first_block(); +} + + +Genode::uint64_t block_allocator_nr_of_blks() +{ + if (!_block_allocator_ptr) { + struct Exception_1 { }; + throw Exception_1(); + } + + return _block_allocator_ptr->nr_of_blks(); +} + + +class Tresor_tester::Main +: + private Vfs::Env::User, + private Tresor::Module_composition, + public Tresor::Module +{ + private: + + Genode::Env &_env; + Attached_rom_dataspace _config_rom { _env, "config" }; + Verbose_node _verbose_node { _config_rom.xml() }; + Heap _heap { _env.ram(), _env.rm() }; + Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this }; + Signal_handler
_sigh { _env.ep(), *this, &Main::_execute }; + Command_pool _cmd_pool { _heap, _config_rom.xml(), _verbose_node }; + Constructible _free_tree { }; + Constructible _vbd { }; + Constructible _sb_control { }; + Constructible _request_pool { }; + Constructible _ft_resizing { }; + Benchmark _benchmark { _env }; + Meta_tree _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") }; + Block_allocator _block_allocator { 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 { }; + Client_data_request _client_data_request { }; + + /* + * Noncopyable + */ + Main(Main const &) = delete; + Main &operator = (Main const &) = delete; + + void _construct_tresor() + { + _free_tree.construct(); + add_module(FREE_TREE, *_free_tree); + + _vbd.construct(); + add_module(VIRTUAL_BLOCK_DEVICE, *_vbd); + + _sb_control.construct(); + add_module(SUPERBLOCK_CONTROL, *_sb_control); + + _request_pool.construct(); + add_module(REQUEST_POOL, *_request_pool); + + _ft_resizing.construct(); + add_module(FT_RESIZING, *_ft_resizing); + } + + void _destruct_tresor() + { + remove_module(FT_RESIZING); + _ft_resizing.destruct(); + + remove_module(REQUEST_POOL); + _request_pool.destruct(); + + remove_module(SUPERBLOCK_CONTROL); + _sb_control.destruct(); + + remove_module(VIRTUAL_BLOCK_DEVICE); + _vbd.destruct(); + + remove_module(FREE_TREE); + _free_tree.destruct(); + } + + /** + * Vfs::Env::User interface + */ + void wakeup_vfs_user() override { _sigh.local_submit(); } + + template + void _handle_completed_client_requests_of_module(MODULE &module, + bool &progress) + { + while (true) { + + Tresor::Request const tresor_req { + module.peek_completed_client_request() }; + + if (!tresor_req.valid()) { + break; + } + _cmd_pool.mark_command_completed(tresor_req.tag(), + tresor_req.success()); + + module.drop_completed_client_request(tresor_req); + progress = true; + } + } + + bool ready_to_submit_request() override + { + return _client_data_request._type == Client_data_request::INVALID; + } + + void submit_request(Module_request &req) override + { + if (_client_data_request._type != Client_data_request::INVALID) { + + class Exception_1 { }; + throw Exception_1 { }; + } + req.dst_request_id(0); + _client_data_request = *static_cast(&req); + switch (_client_data_request._type) { + case Client_data_request::OBTAIN_PLAINTEXT_BLK: + + _cmd_pool.generate_blk_data( + _client_data_request._client_req_tag, + _client_data_request._vba, + *(Tresor::Block *)_client_data_request._plaintext_blk_ptr); + + _benchmark.raise_nr_of_virt_blks_written(); + + if (_verbose_node.client_data_transferred()) + log("client data: vba=", _client_data_request._vba, + " req_tag=", _client_data_request._client_req_tag); + + _client_data_request._success = true; + break; + + case Client_data_request::SUPPLY_PLAINTEXT_BLK: + + _cmd_pool.verify_blk_data( + _client_data_request._client_req_tag, + _client_data_request._vba, + *(Tresor::Block *)_client_data_request._plaintext_blk_ptr); + + _benchmark.raise_nr_of_virt_blks_read(); + + if (_verbose_node.client_data_transferred()) + log("client data: vba=", _client_data_request._vba, + " req_tag=", _client_data_request._client_req_tag); + + _client_data_request._success = true; + break; + + case Client_data_request::INVALID: + + class Exception_2 { }; + throw Exception_2 { }; + } + } + + void execute(bool &) override { } + + bool _peek_completed_request(Genode::uint8_t *buf_ptr, + Genode::size_t buf_size) override + { + if (_client_data_request._type != Client_data_request::INVALID) { + if (sizeof(_client_data_request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + Genode::memcpy(buf_ptr, &_client_data_request, + sizeof(_client_data_request));; + return true; + } + return false; + } + + void _drop_completed_request(Module_request &) override + { + if (_client_data_request._type == Client_data_request::INVALID) { + class Exception_2 { }; + throw Exception_2 { }; + } + _client_data_request._type = Client_data_request::INVALID; + } + + void _cmd_pool_handle_pending_tresor_cmds(bool &progress) + { + while (true) { + + if (!_request_pool->ready_to_submit_request()) { + break; + } + Command const cmd { + _cmd_pool.peek_pending_command(Command::REQUEST) }; + + if (cmd.type() == Command::INVALID) { + break; + } + if (cmd.request_node().op() == Tresor::Request::Operation::CREATE_SNAPSHOT) { + warning("skip command because it is temporarily not supported"); + _cmd_pool.mark_command_in_progress(cmd.id()); + _cmd_pool.mark_command_completed(cmd.id(), true); + progress = true; + continue; + } + if (cmd.request_node().op() == Tresor::Request::Operation::DISCARD_SNAPSHOT) { + warning("skip command because it is temporarily not supported"); + _cmd_pool.mark_command_in_progress(cmd.id()); + _cmd_pool.mark_command_completed(cmd.id(), true); + progress = true; + continue; + } + Request_node req_node { cmd.request_node() }; + Tresor::Request tresor_req { + cmd.request_node().op(), + false, + req_node.has_attr_vba() ? req_node.vba() : 0, + 0, + req_node.has_attr_count() ? req_node.count() : 0, + 0, + cmd.id(), + 0, + COMMAND_POOL, cmd.id() }; + + _request_pool->submit_request(tresor_req); + if (VERBOSE_MODULE_COMMUNICATION) + Genode::log( + module_name(tresor_req.src_module_id()), " ", + tresor_req.src_request_id_str(), + " --", tresor_req, "--> ", + module_name(tresor_req.dst_module_id()), " ", + tresor_req.dst_request_id_str()); + + _cmd_pool.mark_command_in_progress(cmd.id()); + progress = true; + } + } + + void _cmd_pool_handle_pending_construct_cmds(bool &progress) + { + while (true) { + + Command const cmd { + _cmd_pool.peek_pending_command(Command::CONSTRUCT) }; + + if (cmd.type() == Command::INVALID) { + break; + } + _construct_tresor(); + _cmd_pool.mark_command_in_progress(cmd.id()); + _cmd_pool.mark_command_completed(cmd.id(), true); + progress = true; + } + } + + void _cmd_pool_handle_pending_destruct_cmds(bool &progress) + { + while (true) { + + Command const cmd { + _cmd_pool.peek_pending_command(Command::DESTRUCT) }; + + if (cmd.type() == Command::INVALID) { + break; + } + _destruct_tresor(); + _cmd_pool.mark_command_in_progress(cmd.id()); + _cmd_pool.mark_command_completed(cmd.id(), true); + progress = true; + } + } + + void _cmd_pool_handle_pending_list_snapshots_cmds(bool &progress) + { + while (true) { + + Command const cmd { + _cmd_pool.peek_pending_command(Command::LIST_SNAPSHOTS) }; + + if (cmd.type() == Command::INVALID) { + break; + } + Snapshot_generations generations; + _sb_control->snapshot_generations(generations); + unsigned snap_nr { 0 }; + log(""); + log("List snapshots (command ID ", cmd.id(), ")"); + for (Generation const &gen : generations.items) { + if (gen != INVALID_GENERATION) { + log(" Snapshot #", snap_nr, " is generation ", gen); + snap_nr++; + } + } + log(""); + _cmd_pool.mark_command_in_progress(cmd.id()); + _cmd_pool.mark_command_completed(cmd.id(), true); + progress = true; + } + } + + void _cmd_pool_handle_pending_log_cmds(bool &progress) + { + while (true) { + + Command const cmd { + _cmd_pool.peek_pending_command(Command::LOG) }; + + if (cmd.type() == Command::INVALID) { + break; + } + log("\n", cmd.log_node().string(), "\n"); + _cmd_pool.mark_command_in_progress(cmd.id()); + _cmd_pool.mark_command_completed(cmd.id(), true); + progress = true; + } + } + + void _cmd_pool_handle_pending_benchmark_cmds(bool &progress) + { + while (true) { + + Command const cmd { + _cmd_pool.peek_pending_command(Command::BENCHMARK) }; + + if (cmd.type() == Command::INVALID) { + break; + } + _benchmark.submit_request(cmd.benchmark_node()); + _cmd_pool.mark_command_in_progress(cmd.id()); + _cmd_pool.mark_command_completed(cmd.id(), true); + progress = true; + } + } + + void _execute_command_pool(bool &progress) + { + if (_request_pool.constructed()) { + _cmd_pool_handle_pending_tresor_cmds(progress); + _cmd_pool_handle_pending_list_snapshots_cmds(progress); + } + _cmd_pool_handle_pending_log_cmds(progress); + _cmd_pool_handle_pending_benchmark_cmds(progress); + _cmd_pool_handle_pending_construct_cmds(progress); + _cmd_pool_handle_pending_destruct_cmds(progress); + + if (_cmd_pool.nr_of_uncompleted_cmds() == 0) { + + if (_cmd_pool.nr_of_errors() > 0) { + + _cmd_pool.print_failed_cmds(); + _env.parent().exit(-1); + + } else { + + _env.parent().exit(0); + } + } + } + + void _execute() + { + bool progress { true }; + while (progress) { + + progress = false; + _execute_command_pool(progress); + execute_modules(progress); + } + _vfs_env.io().commit(); + } + + public: + + Main(Genode::Env &env) + : + _env { env } + { + add_module(META_TREE, _meta_tree); + add_module(CRYPTO, _crypto); + add_module(TRUST_ANCHOR, _trust_anchor); + add_module(CLIENT_DATA, *this); + add_module(COMMAND_POOL, _cmd_pool); + add_module(BLOCK_IO, _block_io); + add_module(BLOCK_ALLOCATOR, _block_allocator); + 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); + + _block_allocator_ptr = &_block_allocator; + + _execute(); + } +}; + +namespace Libc { + + struct Env; + + struct Component + { + void construct(Libc::Env &); + }; +} + + +void Libc::Component::construct(Libc::Env &) { } + + +void Component::construct(Genode::Env &env) +{ + env.exec_static_constructors(); + + static Tresor_tester::Main main(env); + + (void)block_allocator_first_block(); + (void)block_allocator_nr_of_blks(); +} + +extern "C" int memcmp(const void *p0, const void *p1, Genode::size_t size) +{ + return Genode::memcmp(p0, p1, size); +} diff --git a/repos/gems/src/app/cbe_tester/module_type.h b/repos/gems/src/app/tresor_tester/module_type.h similarity index 73% rename from repos/gems/src/app/cbe_tester/module_type.h rename to repos/gems/src/app/tresor_tester/module_type.h index acf77f2743..8c47eea20e 100644 --- a/repos/gems/src/app/cbe_tester/module_type.h +++ b/repos/gems/src/app/tresor_tester/module_type.h @@ -1,5 +1,5 @@ /* - * \brief Identifiers for the CBE modules used in the CBE tester + * \brief Identifiers for the Tresor modules used in the Tresor tester * \author Martin Stein * \date 2020-08-26 */ @@ -19,10 +19,9 @@ enum class Module_type : Genode::uint8_t { - CBE_INIT, - CBE_DUMP, - CBE_CHECK, - CBE, + TRESOR_INIT, + TRESOR_CHECK, + TRESOR, }; @@ -30,10 +29,9 @@ static Module_type module_type_from_uint32(Genode::uint32_t uint32) { class Bad_tag { }; switch (uint32) { - case 1: return Module_type::CBE_INIT; - case 2: return Module_type::CBE; - case 3: return Module_type::CBE_DUMP; - case 4: return Module_type::CBE_CHECK; + case 1: return Module_type::TRESOR_INIT; + case 2: return Module_type::TRESOR; + case 4: return Module_type::TRESOR_CHECK; default: throw Bad_tag(); } } @@ -43,10 +41,9 @@ static Genode::uint32_t module_type_to_uint32(Module_type type) { class Bad_type { }; switch (type) { - case Module_type::CBE_INIT : return 1; - case Module_type::CBE : return 2; - case Module_type::CBE_DUMP : return 3; - case Module_type::CBE_CHECK: return 4; + case Module_type::TRESOR_INIT : return 1; + case Module_type::TRESOR : return 2; + case Module_type::TRESOR_CHECK: return 4; } throw Bad_type(); } diff --git a/repos/gems/src/app/tresor_tester/target.mk b/repos/gems/src/app/tresor_tester/target.mk new file mode 100644 index 0000000000..4fdf22caf5 --- /dev/null +++ b/repos/gems/src/app/tresor_tester/target.mk @@ -0,0 +1,8 @@ +TARGET := tresor_tester + +SRC_CC += main.cc + +INC_DIR += $(PRG_DIR) + +LIBS += base +LIBS += tresor diff --git a/repos/gems/src/app/cbe_tester/verbose_node.h b/repos/gems/src/app/tresor_tester/verbose_node.h similarity index 80% rename from repos/gems/src/app/cbe_tester/verbose_node.h rename to repos/gems/src/app/tresor_tester/verbose_node.h index 9aa0f1131f..6d6044726f 100644 --- a/repos/gems/src/app/cbe_tester/verbose_node.h +++ b/repos/gems/src/app/tresor_tester/verbose_node.h @@ -1,5 +1,5 @@ /* - * \brief Verbosity configuration of the CBE tester + * \brief Verbosity configuration of the Tresor tester * \author Martin Stein * \date 2020-10-29 */ @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _CBE_TESTER__VERBOSE_NODE_H_ -#define _CBE_TESTER__VERBOSE_NODE_H_ +#ifndef _TRESOR_TESTER__VERBOSE_NODE_H_ +#define _TRESOR_TESTER__VERBOSE_NODE_H_ /* Genode includes */ #include @@ -28,8 +28,6 @@ class Verbose_node bool _blk_io_req_completed { false }; bool _ta_req_in_progress { false }; bool _ta_req_completed { false }; - bool _crypto_req_completed { false }; - bool _crypto_req_in_progress { false }; bool _client_data_mismatch { false }; bool _client_data_transferred { false }; @@ -46,8 +44,6 @@ class Verbose_node _blk_io_req_completed = verbose.attribute_value("blk_io_req_completed" , false); _ta_req_in_progress = verbose.attribute_value("ta_req_in_progress" , false); _ta_req_completed = verbose.attribute_value("ta_req_completed" , false); - _crypto_req_completed = verbose.attribute_value("crypto_req_completed" , false); - _crypto_req_in_progress = verbose.attribute_value("crypto_req_in_progress" , false); _client_data_mismatch = verbose.attribute_value("client_data_mismatch" , false); _client_data_transferred = verbose.attribute_value("client_data_transferred" , false); }); @@ -60,10 +56,8 @@ class Verbose_node bool blk_io_req_completed () const { return _blk_io_req_completed ; } bool ta_req_in_progress () const { return _ta_req_in_progress ; } bool ta_req_completed () const { return _ta_req_completed ; } - bool crypto_req_completed () const { return _crypto_req_completed ; } - bool crypto_req_in_progress () const { return _crypto_req_in_progress ; } bool client_data_mismatch () const { return _client_data_mismatch ; } bool client_data_transferred () const { return _client_data_transferred ; } }; -#endif /* _CBE_TESTER__VERBOSE_NODE_H_ */ +#endif /* _TRESOR_TESTER__VERBOSE_NODE_H_ */ diff --git a/repos/gems/src/app/vfs_replay/target.mk b/repos/gems/src/app/vfs_replay/target.mk index 63d8f78430..cb3b60c896 100644 --- a/repos/gems/src/app/vfs_replay/target.mk +++ b/repos/gems/src/app/vfs_replay/target.mk @@ -1,3 +1,3 @@ -TARGET = cbe_vfs_replay +TARGET = tresor_vfs_replay SRC_CC = component.cc LIBS = base vfs diff --git a/repos/gems/src/lib/tresor/block_allocator.cc b/repos/gems/src/lib/tresor/block_allocator.cc new file mode 100644 index 0000000000..4e76f40e32 --- /dev/null +++ b/repos/gems/src/lib/tresor/block_allocator.cc @@ -0,0 +1,197 @@ +/* + * \brief Managing block allocation for the initialization of a Tresor device + * \author Josef Soentgen + * \date 2023-02-28 + */ + +/* + * 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. + */ + +/* base includes */ +#include + +/* tresor includes */ +#include + +using namespace Tresor; + + +Block_allocator_request::Block_allocator_request(Module_id src_module_id, + Module_request_id src_request_id) +: + Module_request { src_module_id, src_request_id, BLOCK_ALLOCATOR } +{ } + + +void Block_allocator_request::print(Output &out) const +{ + Genode::print(out, type_to_string(_type)); +} + + +void Block_allocator_request::create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type) +{ + Block_allocator_request req { src_module_id, src_request_id }; + req._type = (Type)req_type; + + if (sizeof(req) > buf_size) { + class Bad_size_0 { }; + throw Bad_size_0 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); +} + + +char const *Block_allocator_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + case GET: return "get"; + } + return "?"; +} + + +void Block_allocator::_execute_get(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::PENDING: + + if (_nr_of_blks <= MAX_PBA - _first_block) { + + req._blk_nr = _first_block + _nr_of_blks; + ++_nr_of_blks; + + _mark_req_successful(channel, progress); + + } else + + _mark_req_failed(channel, progress, " get next block number"); + + return; + + default: + return; + } +} + + +void Block_allocator::_mark_req_failed(Channel &channel, + bool &progress, + char const *str) +{ + error("request failed: failed to ", str); + channel._request._success = false; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Block_allocator::_mark_req_successful(Channel &channel, + bool &progress) +{ + channel._request._success = true; + channel._state = Channel::COMPLETE; + progress = true; +} + + +bool Block_allocator::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::COMPLETE) { + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Block_allocator::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._state != Channel::COMPLETE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._state = Channel::INACTIVE; +} + + +Block_allocator::Block_allocator(uint64_t first_block) +: + _first_block { first_block }, + _nr_of_blks { 0 } +{ } + + +bool Block_allocator::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::INACTIVE) + return true; + } + return false; +} + + +void Block_allocator::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + if (_channels[id]._state == Channel::INACTIVE) { + req.dst_request_id(id); + _channels[id]._request = *static_cast(&req); + _channels[id]._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} + + +void Block_allocator::execute(bool &progress) +{ + for (Channel &channel : _channels) { + + if (channel._state == Channel::INACTIVE) + continue; + + Request &req { channel._request }; + switch (req._type) { + case Request::GET: + + if (channel._state == Channel::SUBMITTED) + channel._state = Channel::PENDING; + + _execute_get(channel, progress); + + break; + default: + + class Exception_1 { }; + throw Exception_1 { }; + } + } +} diff --git a/repos/gems/src/lib/tresor/block_io.cc b/repos/gems/src/lib/tresor/block_io.cc new file mode 100644 index 0000000000..39c6cef4dc --- /dev/null +++ b/repos/gems/src/lib/tresor/block_io.cc @@ -0,0 +1,687 @@ +/* + * \brief Module for accessing the back-end block device + * \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. + */ + +/* base includes */ +#include +#include + +/* tresor includes */ +#include +#include +#include + +using namespace Tresor; + + +/********************** + ** Block_io_request ** + **********************/ + +Block_io_request::Block_io_request(uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t client_req_offset, + uint64_t client_req_tag, + uint32_t key_id, + uint64_t pba, + uint64_t vba, + uint64_t blk_count, + void *blk_ptr, + void *hash_ptr) +: + Module_request { src_module_id, src_request_id, BLOCK_IO }, + _type { (Type)req_type }, + _client_req_offset { client_req_offset }, + _client_req_tag { client_req_tag }, + _key_id { key_id }, + _pba { pba }, + _vba { vba }, + _blk_count { blk_count }, + _blk_ptr { (addr_t)blk_ptr }, + _hash_ptr { (addr_t)hash_ptr } +{ } + + +void Block_io_request::print(Output &out) const +{ + if (_blk_count > 1) + Genode::print(out, type_to_string(_type), " pbas ", _pba, "..", _pba + _blk_count - 1); + else + Genode::print(out, type_to_string(_type), " pba ", _pba); +} + + +char const *Block_io_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + 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"; + } + return "?"; +} + + +/************** + ** Block_io ** + **************/ + +bool Block_io::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel const &channel { _channels[id] }; + Crypto_request::Type crypto_req_type { + channel._state == Channel::DECRYPT_CLIENT_DATA_PENDING ? + Crypto_request::DECRYPT_CLIENT_DATA : + channel._state == Channel::ENCRYPT_CLIENT_DATA_PENDING ? + Crypto_request::ENCRYPT_CLIENT_DATA : + Crypto_request::INVALID }; + + if (crypto_req_type != Crypto_request::INVALID) { + + Request const &req { channel._request }; + construct_in_buf( + buf_ptr, buf_size, BLOCK_IO, id, crypto_req_type, + req._client_req_offset, req._client_req_tag, + req._key_id, nullptr, req._pba, req._vba, nullptr, + (void *)channel._blk_buf); + + return true; + } + } + return false; +} + + +void Block_io::_drop_generated_request(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Bad_id { }; + throw Bad_id { }; + } + switch (_channels[id]._state) { + case Channel::DECRYPT_CLIENT_DATA_PENDING: + _channels[id]._state = Channel::DECRYPT_CLIENT_DATA_IN_PROGRESS; + break; + case Channel::ENCRYPT_CLIENT_DATA_PENDING: + _channels[id]._state = Channel::ENCRYPT_CLIENT_DATA_IN_PROGRESS; + break; + default: + class Exception_1 { }; + throw Exception_1 { }; + } +} + + +void Block_io::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + switch (mod_req.dst_module_id()) { + case CRYPTO: + { + Crypto_request const &gen_req { *static_cast(&mod_req) }; + switch (_channels[id]._state) { + case Channel::DECRYPT_CLIENT_DATA_IN_PROGRESS: + _channels[id]._state = Channel::DECRYPT_CLIENT_DATA_COMPLETE; + _channels[id]._generated_req_success = gen_req.success(); + break; + case Channel::ENCRYPT_CLIENT_DATA_IN_PROGRESS: + _channels[id]._state = Channel::ENCRYPT_CLIENT_DATA_COMPLETE; + _channels[id]._generated_req_success = gen_req.success(); + break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } + break; + } + default: + class Exception_3 { }; + throw Exception_3 { }; + } +} + + +void Block_io::_mark_req_failed(Channel &channel, + bool &progress, + char const *str) +{ + error("request failed: failed to ", str); + channel._request._success = false; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Block_io::_mark_req_successful(Channel &channel, + bool &progress) +{ + channel._request._success = true; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Block_io::_execute_read(Channel &channel, + bool &progress) +{ + using Result = Vfs::File_io_service::Read_result; + + Request &req { channel._request }; + switch (channel._state) { + case Channel::PENDING: + + enum : uint64_t { MAX_FILE_OFFSET = 0x7fffffffffffffff }; + if (req._pba > (size_t)MAX_FILE_OFFSET / (size_t)BLOCK_SIZE) { + + error("request failed: failed to seek file offset, pba: ", req._pba); + channel._state = Channel::COMPLETE; + req._success = false; + progress = true; + return; + } + _vfs_handle.seek(req._pba * BLOCK_SIZE + + channel._nr_of_processed_bytes); + + if (!_vfs_handle.fs().queue_read(&_vfs_handle, channel._nr_of_remaining_bytes)) { + return; + } + channel._state = Channel::IN_PROGRESS; + progress = true; + return; + + case Channel::IN_PROGRESS: + { + size_t nr_of_read_bytes { 0 }; + + Byte_range_ptr dst { + (char *)req._blk_ptr + channel._nr_of_processed_bytes, + channel._nr_of_remaining_bytes }; + + Result const result { + _vfs_handle.fs().complete_read( + &_vfs_handle, dst, nr_of_read_bytes) }; + + switch (result) { + case Result::READ_QUEUED: + case Result::READ_ERR_WOULD_BLOCK: + + return; + + case Result::READ_OK: + + if (nr_of_read_bytes == 0) { + + error("request failed: number of read bytes is 0"); + channel._state = Channel::COMPLETE; + req._success = false; + progress = true; + return; + } + channel._nr_of_processed_bytes += nr_of_read_bytes; + channel._nr_of_remaining_bytes -= nr_of_read_bytes; + + if (channel._nr_of_remaining_bytes == 0) { + + channel._state = Channel::COMPLETE; + req._success = true; + progress = true; + return; + + } else { + + channel._state = Channel::PENDING; + progress = true; + return; + } + + case Result::READ_ERR_IO: + case Result::READ_ERR_INVALID: + + error("request failed: failed to read from file"); + channel._state = Channel::COMPLETE; + req._success = false; + progress = true; + return; + + default: + + class Bad_complete_read_result { }; + throw Bad_complete_read_result { }; + } + } + default: return; + } +} + + +void Block_io::_execute_read_client_data(Channel &channel, + bool &progress) +{ + using Result = Vfs::File_io_service::Read_result; + + Request &req { channel._request }; + switch (channel._state) { + case Channel::PENDING: + + _vfs_handle.seek(req._pba * BLOCK_SIZE + + channel._nr_of_processed_bytes); + + if (!_vfs_handle.fs().queue_read(&_vfs_handle, channel._nr_of_remaining_bytes)) { + return; + } + channel._state = Channel::IN_PROGRESS; + progress = true; + return; + + case Channel::IN_PROGRESS: + { + size_t nr_of_read_bytes { 0 }; + + Byte_range_ptr dst { + (char *)channel._blk_buf + channel._nr_of_processed_bytes, + channel._nr_of_remaining_bytes }; + + Result const result { + _vfs_handle.fs().complete_read( + &_vfs_handle, dst, nr_of_read_bytes) }; + + switch (result) { + case Result::READ_QUEUED: + case Result::READ_ERR_WOULD_BLOCK: + + return; + + case Result::READ_OK: + + channel._nr_of_processed_bytes += nr_of_read_bytes; + channel._nr_of_remaining_bytes -= nr_of_read_bytes; + + if (channel._nr_of_remaining_bytes == 0) { + + channel._state = Channel::DECRYPT_CLIENT_DATA_PENDING; + progress = true; + return; + + } else { + + channel._state = Channel::PENDING; + progress = true; + return; + } + + case Result::READ_ERR_IO: + case Result::READ_ERR_INVALID: + + channel._state = Channel::COMPLETE; + req._success = false; + progress = true; + return; + + default: + + class Bad_complete_read_result { }; + throw Bad_complete_read_result { }; + } + } + case Channel::DECRYPT_CLIENT_DATA_COMPLETE: + + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, "decrypt client data"); + return; + } + _mark_req_successful(channel, progress); + return; + + default: return; + } +} + + +void Block_io::_execute_write_client_data(Channel &channel, + bool &progress) +{ + using Result = Vfs::File_io_service::Write_result; + + Request &req { channel._request }; + switch (channel._state) { + case Channel::PENDING: + + channel._state = Channel::ENCRYPT_CLIENT_DATA_PENDING; + progress = true; + return; + + case Channel::ENCRYPT_CLIENT_DATA_COMPLETE: + + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, "encrypt client data"); + return; + } + calc_sha256_4k_hash((void *)channel._blk_buf, (void *)req._hash_ptr); + _vfs_handle.seek(req._pba * BLOCK_SIZE + + channel._nr_of_processed_bytes); + + channel._state = Channel::IN_PROGRESS; + progress = true; + return; + + case Channel::IN_PROGRESS: + { + size_t nr_of_written_bytes { 0 }; + + Const_byte_range_ptr src { + (char const *)channel._blk_buf + channel._nr_of_processed_bytes, + channel._nr_of_remaining_bytes }; + + Result const result = + _vfs_handle.fs().write( + &_vfs_handle, src, nr_of_written_bytes); + + switch (result) { + case Result::WRITE_ERR_WOULD_BLOCK: + return; + + case Result::WRITE_OK: + + channel._nr_of_processed_bytes += nr_of_written_bytes; + channel._nr_of_remaining_bytes -= nr_of_written_bytes; + + if (channel._nr_of_remaining_bytes == 0) { + + channel._state = Channel::COMPLETE; + req._success = true; + progress = true; + return; + + } else { + + channel._state = Channel::PENDING; + progress = true; + return; + } + + case Result::WRITE_ERR_IO: + case Result::WRITE_ERR_INVALID: + + channel._state = Channel::COMPLETE; + req._success = false; + progress = true; + return; + + default: + + class Bad_write_result { }; + throw Bad_write_result { }; + } + + } + default: return; + } +} + + +void Block_io::_execute_write(Channel &channel, + bool &progress) +{ + using Result = Vfs::File_io_service::Write_result; + + Request &req { channel._request }; + switch (channel._state) { + case Channel::PENDING: + + _vfs_handle.seek(req._pba * BLOCK_SIZE + + channel._nr_of_processed_bytes); + + channel._state = Channel::IN_PROGRESS; + progress = true; + break; + + case Channel::IN_PROGRESS: + { + size_t nr_of_written_bytes { 0 }; + + Const_byte_range_ptr src { + (char const *)req._blk_ptr + channel._nr_of_processed_bytes, + channel._nr_of_remaining_bytes }; + + Result const result = + _vfs_handle.fs().write( + &_vfs_handle, src, nr_of_written_bytes); + + switch (result) { + case Result::WRITE_ERR_WOULD_BLOCK: + return; + + case Result::WRITE_OK: + + channel._nr_of_processed_bytes += nr_of_written_bytes; + channel._nr_of_remaining_bytes -= nr_of_written_bytes; + + if (channel._nr_of_remaining_bytes == 0) { + + channel._state = Channel::COMPLETE; + req._success = true; + progress = true; + return; + + } else { + + channel._state = Channel::PENDING; + progress = true; + return; + } + + case Result::WRITE_ERR_IO: + case Result::WRITE_ERR_INVALID: + + channel._state = Channel::COMPLETE; + req._success = false; + progress = true; + return; + + default: + + class Bad_write_result { }; + throw Bad_write_result { }; + } + + } + default: return; + } +} + +void Block_io::_execute_sync(Channel &channel, + bool &progress) +{ + using Result = Vfs::File_io_service::Sync_result; + + Request &req { channel._request }; + switch (channel._state) { + case Channel::PENDING: + + if (!_vfs_handle.fs().queue_sync(&_vfs_handle)) { + return; + } + channel._state = Channel::IN_PROGRESS; + progress = true; + break;; + + case Channel::IN_PROGRESS: + + switch (_vfs_handle.fs().complete_sync(&_vfs_handle)) { + case Result::SYNC_QUEUED: + + return; + + case Result::SYNC_ERR_INVALID: + + req._success = false; + channel._state = Channel::COMPLETE; + progress = true; + return; + + case Result::SYNC_OK: + + req._success = true; + channel._state = Channel::COMPLETE; + progress = true; + return; + + default: + + class Bad_sync_result { }; + throw Bad_sync_result { }; + } + + default: return; + } +} + +void Block_io::execute(bool &progress) +{ + for (Channel &channel : _channels) { + + if (channel._state == Channel::INACTIVE) + continue; + + Request &req { channel._request }; + if (channel._state == Channel::SUBMITTED) { + + uint64_t const nr_of_remaining_bytes { + req._blk_count * BLOCK_SIZE }; + + if (nr_of_remaining_bytes > ~(size_t)0) { + class Exception_2 { }; + throw Exception_2 { }; + } + channel._state = Channel::PENDING; + channel._nr_of_processed_bytes = 0; + channel._nr_of_remaining_bytes = (size_t)nr_of_remaining_bytes; + } + switch (req._type) { + case Request::READ: _execute_read(channel, progress); break; + case Request::WRITE: _execute_write(channel, progress); break; + case Request::SYNC: _execute_sync(channel, progress); break; + case Request::READ_CLIENT_DATA: _execute_read_client_data(channel, progress); break; + case Request::WRITE_CLIENT_DATA: _execute_write_client_data(channel, progress); break; + default: + class Exception_1 { }; + throw Exception_1 { }; + } + } +} + + +Block_io::Block_io(Vfs::Env &vfs_env, + Xml_node const &xml_node) +: + _path { xml_node.attribute_value("path", String<32> { "" } ) }, + _vfs_env { vfs_env } +{ } + + +bool Block_io::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::COMPLETE) { + Request &req { channel._request }; + if (sizeof(req) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); + + if (VERBOSE_BLOCK_IO) { + + switch (req._type) { + case Request::READ: + case Request::WRITE: + { + Hash hash; + calc_sha256_4k_hash((void *)req._blk_ptr, &hash); + log("block_io: ", req.type_name(), " pba ", req._pba, + " data ", *(Block *)req._blk_ptr, " hash ", hash); + + break; + } + case Request::READ_CLIENT_DATA: + case Request::WRITE_CLIENT_DATA: + { + Hash hash; + calc_sha256_4k_hash((void *)channel._blk_buf, &hash); + log("block_io: ", req.type_name(), " pba ", req._pba, + " data ", *(Block *)channel._blk_buf, + " hash ", hash); + + break; + } + default: + break; + } + } + return true; + } + } + return false; +} + + +void Block_io::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._state != Channel::COMPLETE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._state = Channel::INACTIVE; +} + + +bool Block_io::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::INACTIVE) + return true; + } + return false; +} + +void Block_io::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + if (_channels[id]._state == Channel::INACTIVE) { + req.dst_request_id(id); + _channels[id]._request = *static_cast(&req); + _channels[id]._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} diff --git a/repos/gems/src/lib/tresor/crypto.cc b/repos/gems/src/lib/tresor/crypto.cc new file mode 100644 index 0000000000..16c5b488df --- /dev/null +++ b/repos/gems/src/lib/tresor/crypto.cc @@ -0,0 +1,732 @@ +/* + * \brief Module for encrypting/decrypting single data blocks + * \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. + */ + +/* base includes */ +#include +#include + +/* tresor includes */ +#include +#include + +using namespace Tresor; + + +/******************** + ** Crypto_request ** + ********************/ + +Crypto_request::Crypto_request(uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t client_req_offset, + uint64_t client_req_tag, + uint32_t key_id, + void *key_plaintext_ptr, + uint64_t pba, + uint64_t vba, + void *plaintext_blk_ptr, + void *ciphertext_blk_ptr) +: + Module_request { src_module_id, src_request_id, CRYPTO }, + _type { (Type)req_type }, + _client_req_offset { client_req_offset }, + _client_req_tag { client_req_tag }, + _pba { pba }, + _vba { vba }, + _key_id { key_id }, + _key_plaintext_ptr { (addr_t)key_plaintext_ptr }, + _plaintext_blk_ptr { (addr_t)plaintext_blk_ptr }, + _ciphertext_blk_ptr { (addr_t)ciphertext_blk_ptr } +{ } + + +char const *Crypto_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + 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"; + } + return "?"; +} + + +/************ + ** Crypto ** + ************/ + +bool Crypto::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel const &chan { _channels[id] }; + Client_data_request::Type cd_req_type { + chan._state == Channel::OBTAIN_PLAINTEXT_BLK_PENDING ? + Client_data_request::OBTAIN_PLAINTEXT_BLK : + chan._state == Channel::SUPPLY_PLAINTEXT_BLK_PENDING ? + Client_data_request::SUPPLY_PLAINTEXT_BLK : + Client_data_request::INVALID }; + + if (cd_req_type != Client_data_request::INVALID) { + + Request const &req { chan._request }; + Client_data_request const cd_req { + CRYPTO, id, cd_req_type, req._client_req_offset, + req._client_req_tag, req._pba, req._vba, + (addr_t)&chan._blk_buf }; + + if (sizeof(cd_req) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &cd_req, sizeof(cd_req));; + return true; + } + } + return false; +} + + +void Crypto::_drop_generated_request(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Bad_id { }; + throw Bad_id { }; + } + switch (_channels[id]._state) { + case Channel::OBTAIN_PLAINTEXT_BLK_PENDING: + _channels[id]._state = Channel::OBTAIN_PLAINTEXT_BLK_IN_PROGRESS; + break; + case Channel::SUPPLY_PLAINTEXT_BLK_PENDING: + _channels[id]._state = Channel::SUPPLY_PLAINTEXT_BLK_IN_PROGRESS; + break; + default: + class Exception_1 { }; + throw Exception_1 { }; + } +} + + +Crypto::Key_directory &Crypto::_lookup_key_dir(uint32_t key_id) +{ + for (Key_directory &key_dir : _key_dirs) { + if (key_dir.key_id == key_id) { + return key_dir; + } + } + class Exception_1 { }; + throw Exception_1 { }; +} + + +void Crypto::_mark_req_failed(Channel &channel, + bool &progress, + char const *str) +{ + error("crypto: request (", channel._request, ") failed at step \"", str, "\""); + channel._request._success = false; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Crypto::_mark_req_successful(Channel &channel, + bool &progress) +{ + channel._request._success = true; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Crypto::_execute_add_key(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::SUBMITTED: + { + _add_key_handle.seek(0); + + char buf[sizeof(req._key_id) + KEY_SIZE] { }; + memcpy(buf, &req._key_id, sizeof(req._key_id)); + memcpy(buf + sizeof(req._key_id), (void *)req._key_plaintext_ptr, KEY_SIZE); + + Const_byte_range_ptr const src(buf, sizeof(buf)); + size_t nr_of_written_bytes { 0 }; + Write_result const write_result { + _add_key_handle.fs().write( + &_add_key_handle, src, nr_of_written_bytes) }; + + switch (write_result) { + case Write_result::WRITE_OK: + { + Key_directory *key_dir_ptr { nullptr }; + for (Key_directory &key_dir : _key_dirs) { + if (key_dir.key_id == 0) + key_dir_ptr = &key_dir; + } + if (key_dir_ptr == nullptr) { + + _mark_req_failed(channel, progress, "find unused key dir"); + return; + } + key_dir_ptr->key_id = req._key_id; + key_dir_ptr->encrypt_handle = + &vfs_open_rw( + _vfs_env, + { _path.string(), "/keys/", req._key_id, "/encrypt" }); + + key_dir_ptr->decrypt_handle = + &vfs_open_rw( + _vfs_env, + { _path.string(), "/keys/", req._key_id, "/decrypt" }); + + _mark_req_successful(channel, progress); + return; + } + case Write_result::WRITE_ERR_WOULD_BLOCK: + case Write_result::WRITE_ERR_INVALID: + case Write_result::WRITE_ERR_IO: + + _mark_req_failed(channel, progress, "write command"); + return; + } + return; + } + default: + + return; + } +} + + +void Crypto::_execute_remove_key(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::SUBMITTED: + { + _remove_key_handle.seek(0); + + Const_byte_range_ptr src { + (char const*)&req._key_id, sizeof(req._key_id) }; + + size_t nr_of_written_bytes { 0 }; + Write_result const result = + _remove_key_handle.fs().write( + &_remove_key_handle, src, nr_of_written_bytes); + + switch (result) { + case Write_result::WRITE_OK: + { + Key_directory &key_dir { _lookup_key_dir(req._key_id) }; + _vfs_env.root_dir().close(key_dir.encrypt_handle); + key_dir.encrypt_handle = nullptr; + _vfs_env.root_dir().close(key_dir.decrypt_handle); + key_dir.decrypt_handle = nullptr; + key_dir.key_id = 0; + + _mark_req_successful(channel, progress); + return; + } + case Write_result::WRITE_ERR_WOULD_BLOCK: + case Write_result::WRITE_ERR_INVALID: + case Write_result::WRITE_ERR_IO: + + _mark_req_failed(channel, progress, "write command"); + return; + } + } + default: + + return; + } +} + + +void Crypto::_execute_encrypt_client_data(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::SUBMITTED: + + channel._state = Channel::OBTAIN_PLAINTEXT_BLK_PENDING; + progress = true; + return; + + case Channel::OBTAIN_PLAINTEXT_BLK_COMPLETE: + { + if (!channel._generated_req_success) { + + _mark_req_failed(channel, progress, "obtain plaintext block"); + return; + } + channel._vfs_handle = _lookup_key_dir(req._key_id).encrypt_handle; + channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + size_t nr_of_written_bytes { 0 }; + + Const_byte_range_ptr dst { + (char *)&channel._blk_buf, BLOCK_SIZE }; + + channel._vfs_handle->fs().write( + channel._vfs_handle, dst, nr_of_written_bytes); + + channel._state = Channel::OP_WRITTEN_TO_VFS_HANDLE; + progress = true; + return; + } + case Channel::OP_WRITTEN_TO_VFS_HANDLE: + { + channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + bool success { + channel._vfs_handle->fs().queue_read( + channel._vfs_handle, BLOCK_SIZE) }; + + if (!success) + return; + + channel._state = Channel::QUEUE_READ_SUCCEEDED; + progress = true; + return; + } + case Channel::QUEUE_READ_SUCCEEDED: + { + size_t nr_of_read_bytes { 0 }; + + Byte_range_ptr dst { + (char *)req._ciphertext_blk_ptr, BLOCK_SIZE }; + + Read_result const result { + channel._vfs_handle->fs().complete_read( + channel._vfs_handle, dst, nr_of_read_bytes) }; + + switch (result) { + case Read_result::READ_OK: + + _mark_req_successful(channel, progress); + return; + + case Read_result::READ_QUEUED: + case Read_result::READ_ERR_WOULD_BLOCK: + + return; + + case Read_result::READ_ERR_IO: + case Read_result::READ_ERR_INVALID: + + _mark_req_failed(channel, progress, "read ciphertext data"); + return; + } + } + default: + + return; + } +} + + +void Crypto::_execute_encrypt(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::SUBMITTED: + { + channel._vfs_handle = _lookup_key_dir(req._key_id).encrypt_handle; + channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + size_t nr_of_written_bytes { 0 }; + + Const_byte_range_ptr src { + (char *)req._plaintext_blk_ptr, BLOCK_SIZE }; + + channel._vfs_handle->fs().write( + channel._vfs_handle, src, nr_of_written_bytes); + + channel._state = Channel::OP_WRITTEN_TO_VFS_HANDLE; + progress = true; + return; + } + case Channel::OP_WRITTEN_TO_VFS_HANDLE: + { + channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + bool success { + channel._vfs_handle->fs().queue_read( + channel._vfs_handle, BLOCK_SIZE) }; + + if (!success) + return; + + channel._state = Channel::QUEUE_READ_SUCCEEDED; + progress = true; + return; + } + case Channel::QUEUE_READ_SUCCEEDED: + { + size_t nr_of_read_bytes { 0 }; + + Byte_range_ptr dst { (char *)req._ciphertext_blk_ptr, BLOCK_SIZE }; + + Read_result const result { + channel._vfs_handle->fs().complete_read( + channel._vfs_handle, dst, nr_of_read_bytes) }; + + switch (result) { + case Read_result::READ_OK: + + _mark_req_successful(channel, progress); + return; + + case Read_result::READ_QUEUED: + case Read_result::READ_ERR_WOULD_BLOCK: + + return; + + case Read_result::READ_ERR_IO: + case Read_result::READ_ERR_INVALID: + + _mark_req_failed(channel, progress, "read ciphertext data"); + return; + } + } + default: + + return; + } +} + + +void Crypto::_execute_decrypt(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::SUBMITTED: + { + channel._vfs_handle = _lookup_key_dir(req._key_id).decrypt_handle; + channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + + size_t nr_of_written_bytes { 0 }; + + Const_byte_range_ptr src { + (char *)channel._request._ciphertext_blk_ptr, BLOCK_SIZE }; + + channel._vfs_handle->fs().write( + channel._vfs_handle, src, nr_of_written_bytes); + + channel._state = Channel::OP_WRITTEN_TO_VFS_HANDLE; + progress = true; + return; + } + case Channel::OP_WRITTEN_TO_VFS_HANDLE: + { + channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + + bool success { + channel._vfs_handle->fs().queue_read( + channel._vfs_handle, BLOCK_SIZE) }; + + if (!success) + return; + + channel._state = Channel::QUEUE_READ_SUCCEEDED; + progress = true; + return; + } + case Channel::QUEUE_READ_SUCCEEDED: + { + size_t nr_of_read_bytes { 0 }; + Byte_range_ptr dst { + (char *)req._plaintext_blk_ptr, BLOCK_SIZE }; + + Read_result const result { + channel._vfs_handle->fs().complete_read( + channel._vfs_handle, dst, nr_of_read_bytes) }; + + switch (result) { + case Read_result::READ_OK: + + _mark_req_successful(channel, progress); + return; + + case Read_result::READ_QUEUED: + case Read_result::READ_ERR_WOULD_BLOCK: + + return; + + case Read_result::READ_ERR_IO: + case Read_result::READ_ERR_INVALID: + + _mark_req_failed(channel, progress, "read plaintext data"); + return; + } + return; + } + default: + + return; + } +} + + +void Crypto::_execute_decrypt_client_data(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::SUBMITTED: + { + channel._vfs_handle = _lookup_key_dir(req._key_id).decrypt_handle; + if (channel._vfs_handle == nullptr) { + _mark_req_failed(channel, progress, "lookup key dir"); + return; + } + channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + + size_t nr_of_written_bytes { 0 }; + Const_byte_range_ptr src { + (char *)channel._request._ciphertext_blk_ptr, BLOCK_SIZE }; + + channel._vfs_handle->fs().write( + channel._vfs_handle, src, nr_of_written_bytes); + + channel._state = Channel::OP_WRITTEN_TO_VFS_HANDLE; + progress = true; + return; + } + case Channel::OP_WRITTEN_TO_VFS_HANDLE: + { + channel._vfs_handle->seek(req._pba * BLOCK_SIZE); + + bool success { + channel._vfs_handle->fs().queue_read( + channel._vfs_handle, BLOCK_SIZE) }; + + if (!success) + return; + + channel._state = Channel::QUEUE_READ_SUCCEEDED; + progress = true; + return; + } + case Channel::QUEUE_READ_SUCCEEDED: + { + size_t nr_of_read_bytes { 0 }; + Byte_range_ptr dst { + (char *)&channel._blk_buf, BLOCK_SIZE }; + + Read_result const result { + channel._vfs_handle->fs().complete_read( + channel._vfs_handle, dst, nr_of_read_bytes) }; + + switch (result) { + case Read_result::READ_OK: + + channel._state = Channel::SUPPLY_PLAINTEXT_BLK_PENDING; + progress = true; + return; + + case Read_result::READ_QUEUED: + case Read_result::READ_ERR_WOULD_BLOCK: + + return; + + case Read_result::READ_ERR_IO: + case Read_result::READ_ERR_INVALID: + + _mark_req_failed(channel, progress, "read plaintext data"); + return; + } + return; + } + case Channel::SUPPLY_PLAINTEXT_BLK_COMPLETE: + + if (!channel._generated_req_success) { + + _mark_req_failed(channel, progress, "supply plaintext block"); + return; + } + _mark_req_successful(channel, progress); + return; + + default: + + return; + } +} + + +void Crypto::execute(bool &progress) +{ + for (Channel &channel : _channels) { + + if (channel._state == Channel::INACTIVE) + continue; + + switch (channel._request._type) { + case Request::ADD_KEY: _execute_add_key(channel, progress); break; + case Request::REMOVE_KEY: _execute_remove_key(channel, progress); break; + case Request::DECRYPT: _execute_decrypt(channel, progress); break; + case Request::ENCRYPT: _execute_encrypt(channel, progress); break; + case Request::DECRYPT_CLIENT_DATA: _execute_decrypt_client_data(channel, progress); break; + case Request::ENCRYPT_CLIENT_DATA: _execute_encrypt_client_data(channel, progress); break; + default: + class Exception_1 { }; + throw Exception_1 { }; + } + } +} + + +Crypto::Crypto(Vfs::Env &vfs_env, + Xml_node const &xml_node) +: + _vfs_env { vfs_env }, + _path { xml_node.attribute_value("path", String<32>()) }, + _add_key_handle { vfs_open_wo(_vfs_env, { _path.string(), "/add_key" }) }, + _remove_key_handle { vfs_open_wo(_vfs_env, { _path.string(), "/remove_key" }) } +{ } + + +void Crypto::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + switch (mod_req.dst_module_id()) { + case CLIENT_DATA: + { + Client_data_request const &gen_req { *static_cast(&mod_req) }; + switch (_channels[id]._state) { + case Channel::OBTAIN_PLAINTEXT_BLK_IN_PROGRESS: + _channels[id]._state = Channel::OBTAIN_PLAINTEXT_BLK_COMPLETE; + _channels[id]._generated_req_success = gen_req.success(); + break; + case Channel::SUPPLY_PLAINTEXT_BLK_IN_PROGRESS: + _channels[id]._state = Channel::SUPPLY_PLAINTEXT_BLK_COMPLETE; + _channels[id]._generated_req_success = gen_req.success(); + break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } + break; + } + default: + class Exception_3 { }; + throw Exception_3 { }; + } +} + + +bool Crypto::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::COMPLETE) { + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + + Request &req { channel._request }; + if (VERBOSE_VBA_ACCESS) { + + switch (req._type) { + case Request::DECRYPT_CLIENT_DATA: + case Request::ENCRYPT_CLIENT_DATA: + { + log(" plain ", *(Block *)channel._blk_buf); + log(" cipher ", *(Block *)req._ciphertext_blk_ptr); + + break; + } + default: + break; + } + } + 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 ", *(Block *)channel._blk_buf, + " cipher ", *(Block *)req._ciphertext_blk_ptr); + + break; + } + default: + break; + } + } + return true; + } + } + return false; +} + + +void Crypto::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._state != Channel::COMPLETE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._state = Channel::INACTIVE; +} + + +bool Crypto::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::INACTIVE) + return true; + } + return false; +} + +void Crypto::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + if (_channels[id]._state == Channel::INACTIVE) { + req.dst_request_id(id); + _channels[id]._request = *static_cast(&req); + _channels[id]._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} diff --git a/repos/gems/src/lib/tresor/free_tree.cc b/repos/gems/src/lib/tresor/free_tree.cc new file mode 100644 index 0000000000..de99f2a0d4 --- /dev/null +++ b/repos/gems/src/lib/tresor/free_tree.cc @@ -0,0 +1,993 @@ +/* + * \brief Module for doing VBD COW allocations on the free tree + * \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 +#include +#include + +using namespace Tresor; + + +/*************** + ** Utilities ** + ***************/ + +static Virtual_block_address +vbd_node_lowest_vba(Tree_degree_log_2 vbd_degree_log_2, + Tree_level_index vbd_level, + Virtual_block_address vbd_leaf_vba) +{ + return vbd_leaf_vba & + (0xffff'ffff'ffff'ffff << + ((uint32_t)vbd_degree_log_2 * (uint32_t)vbd_level)); +} + + +static Number_of_blocks vbd_node_nr_of_vbas(Tree_degree_log_2 vbd_degree_log_2, + Tree_level_index vbd_level) +{ + return (Number_of_blocks)1 << (vbd_level * vbd_degree_log_2); +} + + +static Virtual_block_address +vbd_node_highest_vba(Tree_degree_log_2 vbd_degree_log_2, + Tree_level_index vbd_level, + Virtual_block_address vbd_leaf_vba) +{ + return + vbd_node_lowest_vba(vbd_degree_log_2, vbd_level, vbd_leaf_vba) + + (vbd_node_nr_of_vbas(vbd_degree_log_2, vbd_level) - 1); +} + + +/*********************** + ** Free_tree_request ** + ***********************/ + +char const *Free_tree_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + 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"; + } + return "?"; +} + + +Free_tree_request::Free_tree_request(uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + addr_t ft_root_pba_ptr, + addr_t ft_root_gen_ptr, + addr_t ft_root_hash_ptr, + uint64_t ft_max_level, + uint64_t ft_degree, + uint64_t ft_leaves, + addr_t mt_root_pba_ptr, + addr_t mt_root_gen_ptr, + addr_t mt_root_hash_ptr, + uint64_t mt_max_level, + uint64_t mt_degree, + uint64_t mt_leaves, + Snapshots const *snapshots_ptr, + Generation last_secured_generation, + uint64_t current_gen, + uint64_t free_gen, + uint64_t requested_blocks, + addr_t new_blocks_ptr, + addr_t old_blocks_ptr, + uint64_t max_level, + uint64_t vba, + uint64_t vbd_degree, + uint64_t vbd_highest_vba, + bool rekeying, + uint32_t previous_key_id, + uint32_t current_key_id, + uint64_t rekeying_vba) +: + Module_request { src_module_id, src_request_id, FREE_TREE }, + _type { (Type)req_type }, + _ft_root_pba_ptr { (addr_t)ft_root_pba_ptr }, + _ft_root_gen_ptr { (addr_t)ft_root_gen_ptr }, + _ft_root_hash_ptr { (addr_t)ft_root_hash_ptr }, + _ft_max_level { ft_max_level }, + _ft_degree { ft_degree }, + _ft_leaves { ft_leaves }, + _mt_root_pba_ptr { (addr_t)mt_root_pba_ptr }, + _mt_root_gen_ptr { (addr_t)mt_root_gen_ptr }, + _mt_root_hash_ptr { (addr_t)mt_root_hash_ptr }, + _mt_max_level { mt_max_level }, + _mt_degree { mt_degree }, + _mt_leaves { mt_leaves }, + _current_gen { current_gen }, + _free_gen { free_gen }, + _requested_blocks { requested_blocks }, + _new_blocks_ptr { (addr_t)new_blocks_ptr }, + _old_blocks_ptr { (addr_t)old_blocks_ptr }, + _max_level { max_level }, + _vba { vba }, + _vbd_degree { vbd_degree }, + _vbd_highest_vba { vbd_highest_vba }, + _rekeying { rekeying }, + _previous_key_id { previous_key_id }, + _current_key_id { current_key_id }, + _rekeying_vba { rekeying_vba }, + _snapshots_ptr { (addr_t)snapshots_ptr }, + _last_secured_generation { last_secured_generation } +{ } + + +/*************** + ** Free_tree ** + ***************/ + +void Free_tree::execute(bool &progress) +{ + for (Channel &channel : _channels) { + _execute( + channel, *(Snapshots *)channel._request._snapshots_ptr, + channel._request._last_secured_generation, progress); + } +} + + +Free_tree::Local_cache_request Free_tree::_new_cache_request(Physical_block_address pba, + Local_cache_request::Op op, + Tree_level_index lvl) +{ + return Local_cache_request { + Local_cache_request::PENDING, op, false, + pba, lvl }; +} + + +void Free_tree::_check_type_2_stack(Type_2_info_stack &stack, + Type_1_info_stack &stack_next, + Node_queue &leaves, + Number_of_blocks &found) +{ + if (!stack.empty()) { + while (!stack.empty()) { + Type_2_info const info { stack.peek_top() }; + if (!leaves.full()) { + leaves.enqueue(info); + } + found++; + stack.pop(); + } + } + if (!stack_next.empty()) { + Type_1_info n { stack_next.peek_top() }; + + /* + * Only when the node is in read state we actually have to acknowledge + * checking the leaf nodes. + */ + if (n.state == Type_1_info::READ) { + n.state = Type_1_info::COMPLETE; + stack_next.update_top(n); + } + } +} + + +void Free_tree::_populate_lower_n_stack(Type_1_info_stack &stack, + Type_1_node_block &entries, + Block const &block_data, + Generation current_gen) +{ + stack.reset(); + memcpy(&entries, &block_data, BLOCK_SIZE); + for (Tree_node_index idx = 0; idx < NR_OF_T1_NODES_PER_BLK; idx++) { + + if (entries.nodes[idx].pba != 0) { + + stack.push({ + Type_1_info::INVALID, entries.nodes[idx], idx, + _node_volatile(entries.nodes[idx], current_gen) }); + } + } +} + + +bool +Free_tree::_check_type_2_leaf_usable(Snapshots const &snapshots, + Generation last_secured_gen, + Type_2_node const &node, + bool rekeying, + Key_id previous_key_id, + Virtual_block_address rekeying_vba) +{ + if (node.pba == 0 || + node.pba == INVALID_PBA || + node.free_gen > last_secured_gen) + return false; + + if (!node.reserved) + return true; + + if (rekeying && + node.last_key_id == previous_key_id && + node.last_vba < rekeying_vba) + return true; + + for (Snapshot const &snap : snapshots.items) { + if (snap.valid && + node.free_gen > snap.gen && + node.alloc_gen < snap.gen + 1) + return false; + } + return true; +} + + +void Free_tree::_populate_level_0_stack(Type_2_info_stack &stack, + Type_2_node_block &entries, + Block const &block_data, + Snapshots const &active_snaps, + Generation secured_gen, + bool rekeying, + Key_id previous_key_id, + Virtual_block_address rekeying_vba) +{ + stack.reset(); + memcpy(&entries, &block_data, BLOCK_SIZE); + for (Tree_node_index idx = 0; idx < NR_OF_T1_NODES_PER_BLK; idx++) { + if (_check_type_2_leaf_usable(active_snaps, secured_gen, + entries.nodes[idx], rekeying, + previous_key_id, rekeying_vba)) { + + stack.push({ Type_2_info::INVALID, entries.nodes[idx], idx }); + } + } +} + + +void Free_tree::_execute_scan(Channel &chan, + Snapshots const &active_snaps, + Generation last_secured_gen, + bool &progress) +{ + Request &req { chan._request }; + bool end_of_tree = false; + bool enough_found = false; + + // handle level 0 + { + Number_of_blocks found_blocks = 0; + _check_type_2_stack( + chan._level_0_stack, chan._level_n_stacks[FIRST_LVL_N_STACKS_IDX], + chan._type_2_leafs, found_blocks); + + chan._found_blocks += found_blocks; + } + + // handle level 1 - n + for (Tree_level_index lvl = FIRST_LVL_N_STACKS_IDX; lvl <= MAX_LVL_N_STACKS_IDX; lvl++) { + + if (!chan._level_n_stacks[lvl].empty()) { + + Type_1_info t1_info = chan._level_n_stacks[lvl].peek_top(); + switch (t1_info.state) { + case Type_1_info::INVALID: + + if (chan._cache_request.state != Local_cache_request::INVALID) { + class Exception_1 { }; + throw Exception_1 { }; + } + chan._cache_request = _new_cache_request( + t1_info.node.pba, Local_cache_request::READ, lvl); + + progress = true; + break; + + case Type_1_info::AVAILABLE: + + chan._cache_request.state = Local_cache_request::INVALID; + if (lvl >= 2) { + _populate_lower_n_stack( + chan._level_n_stacks[lvl - 1], + chan._level_n_node, chan._cache_block_data, + req._current_gen); + } else { + _populate_level_0_stack( + chan._level_0_stack, + chan._level_0_node, chan._cache_block_data, + active_snaps, last_secured_gen, + req._rekeying, req._previous_key_id, + req._rekeying_vba); + } + t1_info.state = Type_1_info::READ; + chan._level_n_stacks[lvl].update_top(t1_info); + progress = true; + break; + + case Type_1_info::READ: + + t1_info.state = Type_1_info::COMPLETE; + chan._level_n_stacks[lvl].update_top(t1_info); + progress = true; + break; + + case Type_1_info::WRITE: + + class Exception_1 { }; + throw Exception_1 { }; + + case Type_1_info::COMPLETE: + + if (lvl == req._ft_max_level) + end_of_tree = true; + + if (chan._found_blocks >= chan._needed_blocks) + enough_found = true; + + chan._level_n_stacks[lvl].pop(); + progress = true; + break; + } + break; + } + } + + if (chan._state != Channel::SCAN) + return; + + if (enough_found) { + chan._state = Channel::SCAN_COMPLETE; + + for (Type_1_info_stack &stack : chan._level_n_stacks) + stack = { }; + + for (Type_1_node_block &blk : chan._level_n_nodes) + blk = { }; + + chan._level_n_stacks[req._ft_max_level].push( + Type_1_info { + Type_1_info::INVALID, chan._root_node(), 0, + _node_volatile(chan._root_node(), req._current_gen) }); + } + + if (end_of_tree && !enough_found) + chan._state = Channel::NOT_ENOUGH_FREE_BLOCKS; +} + + +void +Free_tree::_exchange_type_2_leaves(Generation free_gen, + Tree_level_index max_level, + Type_1_node_walk const &old_blocks, + Tree_walk_pbas &new_blocks, + Virtual_block_address vba, + Tree_degree_log_2 vbd_degree_log_2, + Request::Type req_type, + Type_2_info_stack &stack, + Type_2_node_block &entries, + Number_of_blocks &exchanged, + bool &handled, + Virtual_block_address vbd_highest_vba, + bool rekeying, + Key_id previous_key_id, + Key_id current_key_id, + Virtual_block_address rekeying_vba) +{ + Number_of_blocks local_exchanged { 0 }; + handled = false; + + for (Tree_level_index i = 0; i <= max_level; i++) { + + if (new_blocks.pbas[i] == 0) { + + if (!stack.empty()) { + + Type_2_info const info { stack.peek_top() }; + Type_2_node &t2_node { entries.nodes[info.index] }; + if (t2_node.pba != info.node.pba) { + class Exception_1 { }; + throw Exception_1 { }; + } + switch (req_type) { + case Request::ALLOC_FOR_NON_RKG: + + new_blocks.pbas[i] = t2_node.pba; + t2_node.pba = old_blocks.nodes[i].pba; + t2_node.alloc_gen = old_blocks.nodes[i].gen; + t2_node.free_gen = free_gen; + t2_node.last_vba = + vbd_node_lowest_vba(vbd_degree_log_2, i, vba); + + if (rekeying) { + + if (vba < rekeying_vba) + t2_node.last_key_id = current_key_id; + else + t2_node.last_key_id = previous_key_id; + + } else { + + t2_node.last_key_id = current_key_id; + } + t2_node.reserved = true; + break; + + case Request::ALLOC_FOR_RKG_CURR_GEN_BLKS: + + new_blocks.pbas[i] = t2_node.pba; + + t2_node.pba = old_blocks.nodes[i].pba; + t2_node.alloc_gen = old_blocks.nodes[i].gen; + t2_node.free_gen = free_gen; + t2_node.last_vba = + vbd_node_lowest_vba (vbd_degree_log_2, i, vba); + + t2_node.last_key_id = previous_key_id; + t2_node.reserved = false; + break; + + case Request::ALLOC_FOR_RKG_OLD_GEN_BLKS: + { + new_blocks.pbas[i] = t2_node.pba; + + t2_node.alloc_gen = old_blocks.nodes[i].gen; + t2_node.free_gen = free_gen; + + Virtual_block_address const node_highest_vba { + vbd_node_highest_vba(vbd_degree_log_2, i, vba) }; + + if (rekeying_vba < node_highest_vba && + rekeying_vba < vbd_highest_vba) + { + t2_node.last_key_id = previous_key_id; + t2_node.last_vba = rekeying_vba + 1; + + } else if (rekeying_vba == node_highest_vba || + rekeying_vba == vbd_highest_vba) { + + t2_node.last_key_id = current_key_id; + t2_node.last_vba = + vbd_node_lowest_vba (vbd_degree_log_2, i, vba); + + } else { + + class Exception_1 { }; + throw Exception_1 { }; + } + t2_node.reserved = true; + break; + } + default: + + class Exception_2 { }; + throw Exception_2 { }; + } + + local_exchanged = local_exchanged + 1; + stack.pop(); + handled = true; + + } else { + + break; + } + } + } + exchanged = local_exchanged; +} + + +Free_tree::Local_meta_tree_request +Free_tree::_new_meta_tree_request(Physical_block_address pba) +{ + return { + Local_meta_tree_request::PENDING, Local_meta_tree_request::READ, pba }; +} + + +void Free_tree::_update_upper_n_stack(Type_1_info const &t, + Generation gen, + Block const &block_data, + Type_1_node_block &entries) +{ + entries.nodes[t.index].pba = t.node.pba; + entries.nodes[t.index].gen = gen; + calc_sha256_4k_hash(&block_data, &entries.nodes[t.index].hash); +} + + +void Free_tree::_execute_update(Channel &chan, + Snapshots const &active_snaps, + Generation last_secured_gen, + bool &progress) +{ + Request &req { chan._request }; + bool exchange_finished { false }; + bool update_finished { false }; + Number_of_blocks exchanged; + + /* handle level 0 */ + { + bool handled; + + _exchange_type_2_leaves( + req._free_gen, (Tree_level_index)req._max_level, + *(Type_1_node_walk *)req._old_blocks_ptr, + *(Tree_walk_pbas *)req._new_blocks_ptr, + req._vba, (Tree_degree_log_2)chan._vbd_degree_log_2, req._type, chan._level_0_stack, + chan._level_0_node, exchanged, handled, req._vbd_highest_vba, + req._rekeying, req._previous_key_id, req._current_key_id, + req._rekeying_vba); + + if (handled) { + if (exchanged > 0) { + chan._exchanged_blocks += exchanged; + } else { + Type_1_info n { chan._level_n_stacks[FIRST_LVL_N_STACKS_IDX].peek_top() }; + n.state = Type_1_info::COMPLETE; + chan._level_n_stacks[FIRST_LVL_N_STACKS_IDX].update_top(n); + } + } + } + if (chan._exchanged_blocks == chan._needed_blocks) { + exchange_finished = true; + } + /* handle level 1..N */ + for (Tree_level_index l { FIRST_LVL_N_STACKS_IDX }; l <= MAX_LVL_N_STACKS_IDX; l++) { + + Type_1_info_stack &stack { chan._level_n_stacks[l] }; + + if (!stack.empty()) { + + Type_1_info n { stack.peek_top() }; + switch (n.state) { + case Type_1_info::INVALID: + + if (chan._cache_request.state != Local_cache_request::INVALID) { + class Exception_1 { }; + throw Exception_1 { }; + } + chan._cache_request = + _new_cache_request( + n.node.pba, Local_cache_request::READ, l); + + progress = true; + break; + + case Type_1_info::AVAILABLE: + + chan._cache_request.state = Local_cache_request::INVALID; + if (l >= 2) { + + _populate_lower_n_stack( + chan._level_n_stacks[l - 1], + chan._level_n_nodes[l - 1], chan._cache_block_data, + req._current_gen); + + if (!chan._level_n_stacks[l - 1].empty()) + n.state = Type_1_info::WRITE; + else + n.state = Type_1_info::COMPLETE; + + } else { + + _populate_level_0_stack( + chan._level_0_stack, chan._level_0_node, + chan._cache_block_data, active_snaps, last_secured_gen, + req._rekeying, req._previous_key_id, + req._rekeying_vba); + + if (!chan._level_0_stack.empty()) + n.state = Type_1_info::WRITE; + else + n.state = Type_1_info::COMPLETE; + } + stack.update_top(n); + progress = true; + break; + + case Type_1_info::READ: + + class Exception_2 { }; + throw Exception_2 { }; + + case Type_1_info::WRITE: + + if (!n.volatil) { + + Local_meta_tree_request &mtr { chan._meta_tree_request }; + if (mtr.state == Local_meta_tree_request::INVALID) { + + mtr = _new_meta_tree_request(n.node.pba); + progress = true; + break; + + } else if (mtr.state == Local_meta_tree_request::COMPLETE) { + + mtr.state = Local_meta_tree_request::INVALID; + n.volatil = true; + n.node.pba = mtr.pba; + stack.update_top(n); + + } else { + + class Exception_3 { }; + throw Exception_3 { }; + } + } + if (l >= 2) { + memcpy(&chan._cache_block_data, + &chan._level_n_nodes[l - 1], BLOCK_SIZE); + + if (l < req._ft_max_level) { + _update_upper_n_stack( + n, req._current_gen, chan._cache_block_data, + chan._level_n_nodes[l]); + } else { + calc_sha256_4k_hash(&chan._cache_block_data, + (void *)req._ft_root_hash_ptr); + + *(Generation *)req._ft_root_gen_ptr = req._current_gen; + *(Physical_block_address *)req._ft_root_pba_ptr = + n.node.pba; + } + } else { + memcpy(&chan._cache_block_data, + &chan._level_0_node, BLOCK_SIZE); + + _update_upper_n_stack( + n, req._current_gen, chan._cache_block_data, + chan._level_n_nodes[l]); + } + chan._cache_request = _new_cache_request( + n.node.pba, Local_cache_request::WRITE, l); + + progress = true; + break; + + case Type_1_info::COMPLETE: + + chan._cache_request.state = Local_cache_request::INVALID; + stack.pop(); + + if (exchange_finished) + while (!stack.empty()) + stack.pop(); + + if (l == req._ft_max_level) + update_finished = true; + + progress = true; + break; + } + break; + } + } + if (chan._state != Channel::UPDATE) + return; + + if (exchange_finished && update_finished) + chan._state = Channel::UPDATE_COMPLETE; +} + + +void Free_tree::_execute(Channel &chan, + Snapshots const &active_snaps, + Generation last_secured_gen, + bool &progress) +{ + if (chan._meta_tree_request.state == Local_meta_tree_request::PENDING || + chan._meta_tree_request.state == Local_meta_tree_request::IN_PROGRESS) + return; + + if (chan._cache_request.state == Local_cache_request::PENDING || + chan._cache_request.state == Local_cache_request::IN_PROGRESS) + return; + + switch (chan._state) { + case Channel::INVALID: + break; + case Channel::SCAN: + _execute_scan(chan, active_snaps, last_secured_gen, progress); + break; + case Channel::SCAN_COMPLETE: + chan._state = Channel::UPDATE; + progress = true; + break; + case Channel::UPDATE: + _execute_update(chan, active_snaps, last_secured_gen, progress); + break; + case Channel::UPDATE_COMPLETE: + chan._request._success = true; + chan._state = Channel::COMPLETE; + break; + case Channel::COMPLETE: + break; + case Channel::NOT_ENOUGH_FREE_BLOCKS: + chan._request._success = false; + chan._state = Channel::COMPLETE; + progress = true; + break; + case Channel::TREE_HASH_MISMATCH: + class Exception_1 { }; + throw Exception_1 { }; + } +} + + +bool Free_tree::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::INVALID) + return true; + } + return false; +} + + +void Free_tree::_reset_block_state(Channel &chan) +{ + Request &req { chan._request }; + chan._needed_blocks = req._requested_blocks; + chan._found_blocks = 0; + for (Type_1_info_stack &stack : chan._level_n_stacks) + stack = { }; + + for (Type_1_node_block &blk : chan._level_n_nodes) + blk = { }; + + chan._level_0_stack = { }; + chan._level_n_node = { }; + chan._level_0_node = { }; +} + + +bool Free_tree::_node_volatile(Type_1_node const &node, + uint64_t gen) +{ + return node.gen == 0 || node.gen == gen; +} + + +void Free_tree::submit_request(Module_request &mod_req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + Channel &chan { _channels[id] }; + if (chan._state == Channel::INVALID) { + + mod_req.dst_request_id(id); + + chan._request = *static_cast(&mod_req); + chan._exchanged_blocks = 0; + _reset_block_state(chan); + + Request &req { chan._request }; + Type_1_node root_node { }; + root_node.pba = *(uint64_t *)req._ft_root_pba_ptr; + root_node.gen = *(uint64_t *)req._ft_root_gen_ptr; + memcpy(&root_node.hash, (void *)req._ft_root_hash_ptr, + HASH_SIZE); + + chan._level_n_stacks[req._ft_max_level].push( + { Type_1_info::INVALID, root_node, 0, + _node_volatile(root_node, req._current_gen) }); + + chan._state = Channel::SCAN; + chan._vbd_degree_log_2 = log2(req._vbd_degree); + return; + } + } + class Exception_1 { }; + throw Exception_1 { }; +} + +bool Free_tree::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel &channel { _channels[id] }; + Local_cache_request const &local_crq { channel._cache_request }; + if (local_crq.state == Local_cache_request::PENDING) { + + Block_io_request::Type blk_io_req_type { + local_crq.op == Local_cache_request::READ ? + Block_io_request::READ : + Local_cache_request::WRITE ? + Block_io_request::WRITE : + Block_io_request::INVALID }; + + if (blk_io_req_type == Block_io_request::INVALID) { + class Exception_1 { }; + throw Exception_1 { }; + } + construct_in_buf( + buf_ptr, buf_size, FREE_TREE, id, blk_io_req_type, 0, 0, 0, + local_crq.pba, 0, 1, &channel._cache_block_data, nullptr); + + return true; + } + + Local_meta_tree_request const &local_mtr { channel._meta_tree_request }; + if (local_mtr.state == Local_meta_tree_request::PENDING) { + + Meta_tree_request::Type mt_req_type { + local_mtr.op == Local_meta_tree_request::READ ? + Meta_tree_request::UPDATE : + Meta_tree_request::INVALID }; + + if (mt_req_type == Meta_tree_request::INVALID) { + class Exception_1 { }; + throw Exception_1 { }; + } + Meta_tree_request::create( + buf_ptr, buf_size, FREE_TREE, id, mt_req_type, + (void*)channel._request._mt_root_pba_ptr, + (void*)channel._request._mt_root_gen_ptr, + (void*)channel._request._mt_root_hash_ptr, + channel._request._mt_max_level, + channel._request._mt_degree, + channel._request._mt_leaves, + channel._request._current_gen, + local_mtr.pba); + + return true; + } + } + return false; +} + +void Free_tree::_drop_generated_request(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + switch (mod_req.dst_module_id()) { + case BLOCK_IO: + { + Local_cache_request &local_req { _channels[id]._cache_request }; + if (local_req.state != Local_cache_request::PENDING) { + class Exception_2 { }; + throw Exception_2 { }; + } + local_req.state = Local_cache_request::IN_PROGRESS; + break; + } + case META_TREE: + { + Local_meta_tree_request &local_req { _channels[id]._meta_tree_request }; + if (local_req.state != Local_meta_tree_request::PENDING) { + class Exception_3 { }; + throw Exception_3 { }; + } + local_req.state = Local_meta_tree_request::IN_PROGRESS; + break; + } + default: + + class Exception_4 { }; + throw Exception_4 { }; + } +} + +void Free_tree::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + switch (mod_req.dst_module_id()) { + case BLOCK_IO: + { + Local_cache_request &local_req { _channels[id]._cache_request }; + if (local_req.state != Local_cache_request::IN_PROGRESS) { + class Exception_2 { }; + throw Exception_2 { }; + } + Block_io_request &blk_io_req { *static_cast(&mod_req) }; + Channel &channel { _channels[id] }; + if (!blk_io_req.success()) { + class Exception_3 { }; + throw Exception_3 { }; + } + Type_1_info n { channel._level_n_stacks[local_req.level].peek_top() }; + local_req.state = Local_cache_request::COMPLETE; + + switch (local_req.op) { + case Local_cache_request::SYNC: + + class Exception_4 { }; + throw Exception_4 { }; + + case Local_cache_request::READ: + + if (check_sha256_4k_hash(&channel._cache_block_data, &n.node.hash)) { + + n.state = Type_1_info::AVAILABLE; + channel._level_n_stacks[local_req.level].update_top(n); + + } else { + + channel._state = Channel::TREE_HASH_MISMATCH; + } + break; + + case Local_cache_request::WRITE: + + n.state = Type_1_info::COMPLETE; + channel._level_n_stacks[local_req.level].update_top(n); + break; + } + break; + } + case META_TREE: + { + Local_meta_tree_request &local_req { _channels[id]._meta_tree_request }; + if (local_req.state != Local_meta_tree_request::IN_PROGRESS) { + class Exception_5 { }; + throw Exception_5 { }; + } + Meta_tree_request &mt_req { *static_cast(&mod_req) }; + if (!mt_req.success()) { + class Exception_6 { }; + throw Exception_6 { }; + } + local_req.pba = mt_req.new_pba(); + local_req.state = Local_meta_tree_request::COMPLETE; + break; + } + default: + + class Exception_7 { }; + throw Exception_7 { }; + } +} + + +bool Free_tree::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::COMPLETE) { + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Free_tree::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._state != Channel::COMPLETE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._state = Channel::INVALID; +} diff --git a/repos/gems/src/lib/tresor/ft_check.cc b/repos/gems/src/lib/tresor/ft_check.cc new file mode 100644 index 0000000000..23faee22d2 --- /dev/null +++ b/repos/gems/src/lib/tresor/ft_check.cc @@ -0,0 +1,496 @@ +/* + * \brief Module for checking all hashes of a free tree or meta tree + * \author Martin Stein + * \date 2023-05-03 + */ + +/* + * 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. + */ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include +#include + +using namespace Tresor; + + +/********************** + ** Ft_check_request ** + **********************/ + +Ft_check_request::Ft_check_request(uint64_t src_module_id, + uint64_t src_request_id, + Type type, + Tree_level_index max_lvl, + Tree_node_index max_child_idx, + Number_of_leaves nr_of_leaves, + Type_1_node root) +: + Module_request { src_module_id, src_request_id, FT_CHECK }, + _type { type }, + _max_lvl { max_lvl }, + _max_child_idx { max_child_idx }, + _nr_of_leaves { nr_of_leaves }, + _root { root } +{ } + + +char const *Ft_check_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + case CHECK: return "check"; + } + return "?"; +} + + +/************** + ** Ft_check ** + **************/ + +void Ft_check::_execute_inner_t2_child(Channel &chan, + Tree_level_index lvl, + Tree_node_index child_idx, + bool &progress) +{ + Request &req { chan._request }; + Child_state &child_state { chan._t1_lvls[lvl].children_state[child_idx] }; + Type_1_node const &child { chan._t1_lvls[lvl].children.nodes[child_idx] }; + Type_2_level &child_lvl { chan._t2_lvl }; + + if (child_state == Channel::READ_BLOCK) { + + if (!child.valid()) { + + if (chan._nr_of_leaves == 0) { + + child_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " unused"); + + } else { + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " unexpectedly in use"); + + _mark_req_failed(chan, progress, "check for valid child"); + } + + } else if (!chan._gen_prim.valid()) { + + chan._gen_prim = { + .success = false, + .tag = Channel::BLOCK_IO, + .blk_nr = child.pba, + .dropped = false }; + + chan._lvl_to_read = lvl - 1; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " (", child, "): load to lvl ", lvl - 1); + + } else if (chan._gen_prim.tag != Channel::BLOCK_IO || + chan._gen_prim.blk_nr != child.pba) { + + class Exception_1 { }; + throw Exception_1 { }; + + } else if (!chan._gen_prim.success) { + + } else { + + for (Child_state &state : child_lvl.children_state) { + state = Channel::READ_BLOCK; + } + chan._gen_prim = { }; + child_state = Channel::CHECK_HASH; + progress = true; + } + + } else if (child_state == Channel::CHECK_HASH) { + + if (child.gen == INITIAL_GENERATION || + check_sha256_4k_hash(&child_lvl.children, &child.hash)) { + + child_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " has good hash"); + + } else { + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " has bad hash"); + + _mark_req_failed(chan, progress, "check inner hash"); + } + } +} + + +void Ft_check::_execute_inner_t1_child(Channel &chan, + Type_1_node const &child, + Type_1_level &child_lvl, + Child_state &child_state, + Tree_level_index lvl, + Tree_node_index child_idx, + bool &progress) +{ + Request &req { chan._request }; + if (child_state == Channel::READ_BLOCK) { + + if (!child.valid()) { + + if (chan._nr_of_leaves == 0) { + + child_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " unused"); + + } else { + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " unexpectedly in use"); + + _mark_req_failed(chan, progress, "check for valid child"); + } + + } else if (!chan._gen_prim.valid()) { + + chan._gen_prim = { + .success = false, + .tag = Channel::BLOCK_IO, + .blk_nr = child.pba, + .dropped = false }; + + chan._lvl_to_read = lvl - 1; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " (", child, "): load to lvl ", lvl - 1); + + } else if (chan._gen_prim.tag != Channel::BLOCK_IO || + chan._gen_prim.blk_nr != child.pba) { + + class Exception_1 { }; + throw Exception_1 { }; + + } else if (!chan._gen_prim.success) { + + } else { + + for (Child_state &state : child_lvl.children_state) { + state = Channel::READ_BLOCK; + } + chan._gen_prim = { }; + child_state = Channel::CHECK_HASH; + progress = true; + } + + } else if (child_state == Channel::CHECK_HASH) { + + if (child.gen == INITIAL_GENERATION || + check_sha256_4k_hash(&child_lvl.children, &child.hash)) { + + child_state = Channel::DONE; + if (&child_state == &chan._root_state) { + chan._request._success = true; + } + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " has good hash"); + + } else { + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " has bad hash"); + + _mark_req_failed(chan, progress, "check inner hash"); + } + } +} + + +void Ft_check::_execute_leaf_child(Channel &chan, + Tree_node_index child_idx, + bool &progress) +{ + Request &req { chan._request }; + Type_2_node const &child { chan._t2_lvl.children.nodes[child_idx] }; + Child_state &child_state { chan._t2_lvl.children_state[child_idx] }; + + if (child_state == Channel::READ_BLOCK) { + + if (chan._nr_of_leaves == 0) { + + if (child.valid()) { + + if (VERBOSE_CHECK) + log(Level_indent { 1, req._max_lvl }, + " lvl 1 child ", child_idx, " unexpectedly in use"); + + _mark_req_failed(chan, progress, "check for unused child"); + + } else { + + child_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { 1, req._max_lvl }, + " lvl 1 child ", child_idx, " unused"); + } + + } else { + + chan._nr_of_leaves--; + child_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { 1, req._max_lvl }, + " lvl 1 child ", child_idx, " done"); + + } + } +} + + +void Ft_check::_execute_check(Channel &chan, + bool &progress) +{ + Request &req { chan._request }; + for (Tree_node_index child_idx { 0 }; + child_idx <= req._max_child_idx; + child_idx++) { + + if (chan._t2_lvl.children_state[child_idx] != Channel::DONE) { + + _execute_leaf_child(chan, child_idx, progress); + return; + } + } + for (Tree_level_index lvl { FT_LOWEST_T1_LVL }; lvl <= req._max_lvl; lvl++) { + + for (Tree_node_index child_idx { 0 }; + child_idx <= req._max_child_idx; + child_idx++) { + + Type_1_level &t1_lvl { chan._t1_lvls[lvl] }; + if (t1_lvl.children_state[child_idx] != Channel::DONE) { + + if (lvl == FT_LOWEST_T1_LVL) + _execute_inner_t2_child( + chan, lvl, child_idx, progress); + else + _execute_inner_t1_child( + chan, + chan._t1_lvls[lvl].children.nodes[child_idx], + chan._t1_lvls[lvl - 1], + chan._t1_lvls[lvl].children_state[child_idx], + lvl, child_idx, progress); + + return; + } + } + } + if (chan._root_state != Channel::DONE) { + + _execute_inner_t1_child( + chan, req._root, chan._t1_lvls[req._max_lvl], chan._root_state, + req._max_lvl + 1, 0, progress); + + return; + } +} + + +void Ft_check::_mark_req_failed(Channel &chan, + bool &progress, + char const *str) +{ + error("ft check: request (", chan._request, ") failed at step \"", str, "\""); + chan._request._success = false; + chan._root_state = Channel::DONE; + progress = true; +} + + +bool Ft_check::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &chan : _channels) { + + if (chan._request._type != Request::INVALID && + chan._root_state == Channel::DONE) { + + if (sizeof(chan._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &chan._request, sizeof(chan._request)); + return true; + } + } + return false; +} + + +void Ft_check::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + if (chan._request._type == Request::INVALID && + chan._root_state != Channel::DONE) { + + class Exception_2 { }; + throw Exception_2 { }; + } + chan = Channel { }; +} + + +bool Ft_check::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel &chan { _channels[id] }; + + if (!chan._gen_prim.valid() || chan._gen_prim.dropped) + continue; + + switch (chan._gen_prim.tag) { + case Channel::BLOCK_IO: + + construct_in_buf( + buf_ptr, buf_size, FT_CHECK, id, + Block_io_request::READ, 0, 0, 0, + chan._gen_prim.blk_nr, 0, 1, + chan._lvl_to_read == 1 ? + (void *)&chan._t2_lvl.children : + (void *)&chan._t1_lvls[chan._lvl_to_read].children, + nullptr); + + return true; + + default: + + class Exception_1 { }; + throw Exception_1 { }; + } + } + return false; +} + + +void Ft_check::_drop_generated_request(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_0 { }; + throw Exception_0 { }; + } + Channel &chan { _channels[id] }; + chan._gen_prim.dropped = true; +} + + +void Ft_check::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (mod_req.dst_module_id()) { + case BLOCK_IO: + { + Block_io_request &gen_req { *static_cast(&mod_req) }; + chan._gen_prim.success = gen_req.success(); + break; + } + default: + class Exception_8 { }; + throw Exception_8 { }; + } +} + + +bool Ft_check::ready_to_submit_request() +{ + for (Channel &chan : _channels) { + if (chan._request._type == Request::INVALID) + return true; + } + return false; +} + + +void Ft_check::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + Channel &chan { _channels[id] }; + if (chan._request._type == Request::INVALID) { + req.dst_request_id(id); + chan._request = *static_cast(&req); + chan._nr_of_leaves = chan._request._nr_of_leaves; + chan._root_state = Channel::READ_BLOCK; + return; + } + } + class Exception_1 { }; + throw Exception_1 { }; +} + + +void Ft_check::execute(bool &progress) +{ + for (Channel &chan : _channels) { + + Request &req { chan._request }; + switch (req._type) { + case Request::CHECK: + + _execute_check(chan, progress); + break; + + default: + + break; + } + } +} diff --git a/repos/gems/src/lib/tresor/ft_initializer.cc b/repos/gems/src/lib/tresor/ft_initializer.cc new file mode 100644 index 0000000000..214f7320ad --- /dev/null +++ b/repos/gems/src/lib/tresor/ft_initializer.cc @@ -0,0 +1,749 @@ +/* + * \brief Module for initializing the free tree + * \author Josef Soentgen + * \date 2023-03-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. + */ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include +#include +#include + +using namespace Tresor; + +static constexpr bool DEBUG = false; + + +Ft_initializer_request::Ft_initializer_request(Module_id src_module_id, + Module_request_id src_request_id) +: + Module_request { src_module_id, src_request_id, FT_INITIALIZER } +{ } + + +void Ft_initializer_request::create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t max_level_idx, + uint64_t max_child_idx, + uint64_t nr_of_leaves) +{ + Ft_initializer_request req { src_module_id, src_request_id }; + + req._type = (Type)req_type; + req._max_level_idx = max_level_idx; + req._max_child_idx = max_child_idx; + req._nr_of_leaves = nr_of_leaves; + + if (sizeof(req) > buf_size) { + class Bad_size_0 { }; + throw Bad_size_0 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); +} + + +char const *Ft_initializer_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + case INIT: return "init"; + } + return "?"; +} + + +void Ft_initializer::_execute_leaf_child(Channel &channel, + bool &progress, + uint64_t &nr_of_leaves, + Type_2_node &child, + Ft_initializer_channel::Child_state &child_state, + uint64_t child_index) +{ + using CS = Ft_initializer_channel::Child_state; + + switch (child_state) { + case CS::INIT_BLOCK: + child_state = CS::INIT_NODE; + progress = true; + return; + + case CS::INIT_NODE: + if (nr_of_leaves == 0) { + + if (DEBUG) + log("[ft_init] node: ", 1, " ", child_index, + " assign pba 0, leaf unused"); + + Ft_initializer_channel::reset_node(child); + child_state = CS::DONE; + progress = true; + } else { + + switch (channel._state) { + case Channel::IN_PROGRESS: + channel._state = Channel::BLOCK_ALLOC_PENDING; + progress = true; + break; + + case Channel::BLOCK_ALLOC_PENDING: + break; + + case Channel::BLOCK_ALLOC_IN_PROGRESS: + break; + + case Channel::BLOCK_ALLOC_COMPLETE: + /* bail early in case the allocator failed */ + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, + "allocate block for FT initialization"); + break; + } + channel._state = Channel::IN_PROGRESS; + + Ft_initializer_channel::reset_node(child); + + child.pba = channel._blk_nr; + child_state = CS::DONE; + --nr_of_leaves; + progress = true; + + if (DEBUG) + log("[ft_init] node: ", 1, " ", child_index, + " assign pba: ", channel._blk_nr, " leaves left: ", + nr_of_leaves); + break; + + default: + break; + } + } + default: + break; + } +} + + +void Ft_initializer::_execute_inner_t2_child(Channel &channel, + bool &progress, + uint64_t nr_of_leaves, + uint64_t &level_to_write, + Type_1_node &child, + Ft_initializer_channel::Type_2_level &child_level, + Ft_initializer_channel::Child_state &child_state, + uint64_t level_index, + uint64_t child_index) + +{ + using CS = Ft_initializer_channel::Child_state; + + switch (child_state) { + case CS::INIT_BLOCK: + + if (nr_of_leaves == 0) { + + if (DEBUG) + log("[ft_init] node: ", level_index, " ", child_index, + " assign pba 0, inner node unused"); + + Ft_initializer_channel::reset_node(child); + child_state = CS::DONE; + progress = true; + return; + } else { + + if (DEBUG) + log("[ft_init] node: ", level_index, " ", child_index, + " reset level: ", level_index - 1); + + Ft_initializer_channel::reset_level(child_level, CS::INIT_BLOCK); + child_state = CS::INIT_NODE; + progress = true; + return; + } + break; + + case CS::INIT_NODE: + + switch (channel._state) { + case Channel::IN_PROGRESS: + channel._state = Channel::BLOCK_ALLOC_PENDING; + progress = true; + break; + + case Channel::BLOCK_ALLOC_PENDING: + break; + + case Channel::BLOCK_ALLOC_IN_PROGRESS: + break; + + case Channel::BLOCK_ALLOC_COMPLETE: + /* bail early in case the allocator failed */ + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, + "allocate block for FT initialization"); + break; + } + channel._state = Channel::IN_PROGRESS; + + Ft_initializer_channel::reset_node(child); + child.pba = channel._blk_nr; + calc_sha256_4k_hash(&child_level.children, &child.hash); + child_state = CS::WRITE_BLOCK; + progress = true; + + if (DEBUG) + log("[ft_init] node: ", level_index, " ", child_index, + " assign pba: ", channel._blk_nr); + break; + + default: + break; + } + break; + + case CS::WRITE_BLOCK: + + switch (channel._state) { + case Channel::IN_PROGRESS: + { + channel._state = Channel::BLOCK_IO_PENDING; + channel._child_pba = child.pba; + level_to_write = level_index - 1; + progress = true; + break; + } + + case Channel::BLOCK_IO_PENDING: + break; + + case Channel::BLOCK_IO_IN_PROGRESS: + break; + + case Channel::BLOCK_IO_COMPLETE: + /* bail early in case the allocator failed */ + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, + "write block for FT initialization"); + break; + } + channel._state = Channel::IN_PROGRESS; + + child_state = CS::DONE; + progress = true; + + if (DEBUG) + log("[ft_init] node: ", level_index, " ", child_index, + " write pba: ", channel._child_pba, " level: ", + level_index -1, " (child: ", child, ")"); + break; + default: + break; + } + + break; + + default: + break; + } +} + + +void Ft_initializer::_execute_inner_t1_child(Channel &channel, + bool &progress, + uint64_t nr_of_leaves, + uint64_t &level_to_write, + Type_1_node &child, + Ft_initializer_channel::Type_1_level &child_level, + Ft_initializer_channel::Child_state &child_state, + uint64_t level_index, + uint64_t child_index) + +{ + using CS = Ft_initializer_channel::Child_state; + + switch (child_state) { + case CS::INIT_BLOCK: + + if (nr_of_leaves == 0) { + + if (DEBUG) + log("[ft_init] node: ", level_index, " ", child_index, + " assign pba 0, inner node unused"); + + Ft_initializer_channel::reset_node(child); + child_state = CS::DONE; + progress = true; + return; + } else { + + if (DEBUG) + log("[ft_init] node: ", level_index, " ", child_index, + " reset level: ", level_index - 1); + + Ft_initializer_channel::reset_level(child_level, CS::INIT_BLOCK); + child_state = CS::INIT_NODE; + progress = true; + return; + } + break; + + case CS::INIT_NODE: + + switch (channel._state) { + case Channel::IN_PROGRESS: + channel._state = Channel::BLOCK_ALLOC_PENDING; + progress = true; + break; + + case Channel::BLOCK_ALLOC_PENDING: + break; + + case Channel::BLOCK_ALLOC_IN_PROGRESS: + break; + + case Channel::BLOCK_ALLOC_COMPLETE: + /* bail early in case the allocator failed */ + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, + "allocate block for FT initialization"); + break; + } + channel._state = Channel::IN_PROGRESS; + + Ft_initializer_channel::reset_node(child); + child.pba = channel._blk_nr; + calc_sha256_4k_hash(&child_level.children, &child.hash); + child_state = CS::WRITE_BLOCK; + progress = true; + + if (DEBUG) + log("[ft_init] node: ", level_index, " ", child_index, + " assign pba: ", channel._blk_nr); + break; + + default: + break; + } + break; + + case CS::WRITE_BLOCK: + + switch (channel._state) { + case Channel::IN_PROGRESS: + { + channel._state = Channel::BLOCK_IO_PENDING; + channel._child_pba = child.pba; + level_to_write = level_index - 1; + progress = true; + break; + } + + case Channel::BLOCK_IO_PENDING: + break; + + case Channel::BLOCK_IO_IN_PROGRESS: + break; + + case Channel::BLOCK_IO_COMPLETE: + /* bail early in case the allocator failed */ + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, + "write block for FT initialization"); + break; + } + channel._state = Channel::IN_PROGRESS; + + child_state = CS::DONE; + progress = true; + + if (DEBUG) + log("[ft_init] node: ", level_index, " ", child_index, + " write pba: ", channel._child_pba, " level: ", + level_index -1, " (child: ", child, ")"); + break; + default: + break; + } + + break; + + default: + break; + } +} + + +void Ft_initializer::_execute(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + + /* + * First handle all leaf child nodes that starts after + * triggering the inner T2 nodes below. + */ + for (uint64_t child_idx = 0; child_idx <= req._max_child_idx; child_idx++) { + + Ft_initializer_channel::Child_state &state = + channel._t2_level.children_state[child_idx]; + + if (state != Ft_initializer_channel::Child_state::DONE) { + + Type_2_node &child = + channel._t2_level.children.nodes[child_idx]; + + _execute_leaf_child(channel, progress, req._nr_of_leaves, + child, state, child_idx); + } + } + + /* + * Second handle all inner child nodes that starts after + * triggering the root node below. + */ + for (uint64_t level_idx = 1; level_idx <= req._max_level_idx; level_idx++) { + + for (uint64_t child_idx = 0; child_idx <= req._max_child_idx; child_idx++) { + + Ft_initializer_channel::Child_state &state = + channel._t1_levels[level_idx].children_state[child_idx]; + + if (state != Ft_initializer_channel::Child_state::DONE) { + + Type_1_node &child = + channel._t1_levels[level_idx].children.nodes[child_idx]; + + if (level_idx == 2) { + Ft_initializer_channel::Type_2_level &t2_level = + channel._t2_level; + + _execute_inner_t2_child(channel, progress, + req._nr_of_leaves, + channel._level_to_write, + child, t2_level, state, + level_idx, child_idx); + } else { + + Ft_initializer_channel::Type_1_level &t1_level = + channel._t1_levels[level_idx - 1]; + + _execute_inner_t1_child(channel, progress, + req._nr_of_leaves, + channel._level_to_write, + child, t1_level, state, + level_idx, child_idx); + } + return; + } + } + } + + /* + * Checking the root node will trigger the initialization process as + * well as will finish it. + */ + if (channel._root_node.state != Ft_initializer_channel::Child_state::DONE) { + + Ft_initializer_channel::Type_1_level &t1_level = + channel._t1_levels[req._max_level_idx]; + + _execute_inner_t1_child(channel, progress, + req._nr_of_leaves, + channel._level_to_write, + channel._root_node.node, t1_level, channel._root_node.state, + req._max_level_idx + 1, 0); + return; + } + + /* + * We will end up here when the root state is 'DONE'. + */ + if (req._nr_of_leaves == 0) + _mark_req_successful(channel, progress); + else + _mark_req_failed(channel, progress, "initialize FT"); +} + + +void Ft_initializer::_execute_init(Channel &channel, + bool &progress) +{ + switch (channel._state) { + case Channel::SUBMITTED: + + /* clean residual state */ + for (unsigned int i = 0; i < TREE_MAX_LEVEL; i++) { + Ft_initializer_channel::reset_level(channel._t1_levels[i], + Ft_initializer_channel::Child_state::DONE); + } + channel._level_to_write = 0; + + channel._state = Channel::PENDING; + channel._root_node.state = Ft_initializer_channel::Child_state::INIT_BLOCK; + progress = true; + + return; + + case Channel::PENDING: + + channel._state = Channel::IN_PROGRESS; + progress = true; + return; + + case Channel::IN_PROGRESS: + + _execute(channel, progress); + return; + + case Channel::BLOCK_ALLOC_COMPLETE: + + _execute(channel, progress); + return; + + case Channel::BLOCK_IO_COMPLETE: + + _execute(channel, progress); + return; + + default: + /* + * Omit other states related to ALLOC and IO as those + * are handled via Module API. + */ + return; + } +} + + +void Ft_initializer::_mark_req_failed(Channel &channel, + bool &progress, + char const *str) +{ + error("request failed: failed to ", str); + channel._request._success = false; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Ft_initializer::_mark_req_successful(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + + memcpy(req._root_node, &channel._root_node.node, sizeof (req._root_node)); + req._success = true; + + channel._state = Channel::COMPLETE; + progress = true; +} + + +bool Ft_initializer::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::COMPLETE) { + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Ft_initializer::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._state != Channel::COMPLETE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._state = Channel::INACTIVE; +} + + +bool Ft_initializer::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel const &channel { _channels[id] }; + + if (channel._state != Ft_initializer_channel::State::INACTIVE) + + switch (channel._state) { + case Ft_initializer_channel::State::BLOCK_ALLOC_PENDING: + { + Block_allocator_request::Type const block_allocator_req_type { + Block_allocator_request::GET }; + + Block_allocator_request::create( + buf_ptr, buf_size, FT_INITIALIZER, id, + block_allocator_req_type); + + return true; + } + case Ft_initializer_channel::State::BLOCK_IO_PENDING: + { + Block_io_request::Type const block_io_req_type { + Block_io_request::WRITE }; + + void *data = (channel._level_to_write == 1) + ? (void *)&channel._t2_level.children + : (void *)&channel._t1_levels[channel._level_to_write].children; + + construct_in_buf( + buf_ptr, buf_size, FT_INITIALIZER, id, block_io_req_type, 0, + 0, 0, channel._child_pba, 0, 1, data, nullptr); + + if (DEBUG) { + log("BLOCK_IO_PENDING write ", channel._child_pba); + if (channel._level_to_write == 1) + Ft_initializer_channel::dump(channel._t2_level.children); + else + Ft_initializer_channel::dump(channel._t1_levels[channel._level_to_write].children); + } + + return true; + } + default: + break; + } + } + return false; +} + + +void Ft_initializer::_drop_generated_request(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Bad_id { }; + throw Bad_id { }; + } + switch (_channels[id]._state) { + case Ft_initializer_channel::State::BLOCK_ALLOC_PENDING: + _channels[id]._state = Ft_initializer_channel::State::BLOCK_ALLOC_IN_PROGRESS; + break; + case Ft_initializer_channel::State::BLOCK_IO_PENDING: + _channels[id]._state = Ft_initializer_channel::State::BLOCK_IO_IN_PROGRESS; + break; + default: + class Exception_1 { }; + throw Exception_1 { }; + } +} + + +void Ft_initializer::generated_request_complete(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + switch (_channels[id]._state) { + case Channel::BLOCK_ALLOC_IN_PROGRESS: + { + if (req.dst_module_id() != BLOCK_ALLOCATOR) { + class Exception_3 { }; + throw Exception_3 { }; + } + Block_allocator_request const *block_allocator_req = static_cast(&req); + _channels[id]._state = Channel::BLOCK_ALLOC_COMPLETE; + _channels[id]._blk_nr = block_allocator_req->blk_nr(); + _channels[id]._generated_req_success = block_allocator_req->success(); + break; + } + case Channel::BLOCK_IO_IN_PROGRESS: + { + if (req.dst_module_id() != BLOCK_IO) { + class Exception_4 { }; + throw Exception_4 { }; + } + Block_io_request const *block_io_req = static_cast(&req); + _channels[id]._state = Channel::BLOCK_IO_COMPLETE; + _channels[id]._generated_req_success = block_io_req->success(); + break; + } + default: + class Exception_2 { }; + throw Exception_2 { }; + } +} + + +Ft_initializer::Ft_initializer() +{ } + + +bool Ft_initializer::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::INACTIVE) + return true; + } + return false; +} + + +void Ft_initializer::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + if (_channels[id]._state == Channel::INACTIVE) { + req.dst_request_id(id); + _channels[id]._request = *static_cast(&req); + _channels[id]._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} + + +void Ft_initializer::execute(bool &progress) +{ + for (Channel &channel : _channels) { + + if (channel._state == Channel::INACTIVE) + continue; + + Request &req { channel._request }; + switch (req._type) { + case Request::INIT: + + _execute_init(channel, progress); + + break; + default: + + class Exception_1 { }; + throw Exception_1 { }; + } + } +} diff --git a/repos/gems/src/lib/tresor/ft_resizing.cc b/repos/gems/src/lib/tresor/ft_resizing.cc new file mode 100644 index 0000000000..2c939cec14 --- /dev/null +++ b/repos/gems/src/lib/tresor/ft_resizing.cc @@ -0,0 +1,858 @@ +/* + * \brief Module for re-sizing the free tree + * \author Martin Stein + * \date 2023-05-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. + */ + +/* base includes */ +#include + +/* tresor tester includes */ +#include +#include +#include +#include + +using namespace Tresor; + + +/************************* + ** Ft_resizing_request ** + *************************/ + +Ft_resizing_request:: +Ft_resizing_request(uint64_t src_module_id, + uint64_t src_request_id, + Type type, + Generation curr_gen, + Type_1_node ft_root, + Tree_level_index ft_max_lvl, + Number_of_leaves ft_nr_of_leaves, + Tree_degree ft_degree, + addr_t mt_root_pba_ptr, + addr_t mt_root_gen_ptr, + addr_t mt_root_hash_ptr, + Tree_level_index mt_max_level, + Tree_degree mt_degree, + Number_of_leaves mt_leaves, + Physical_block_address pba, + Number_of_blocks nr_of_pbas) +: + Module_request { src_module_id, src_request_id, FT_RESIZING }, + _type { type }, + _curr_gen { curr_gen }, + _ft_root { ft_root }, + _ft_max_lvl { ft_max_lvl }, + _ft_nr_of_leaves { ft_nr_of_leaves }, + _ft_degree { ft_degree }, + _mt_root_pba_ptr { mt_root_pba_ptr }, + _mt_root_gen_ptr { mt_root_gen_ptr }, + _mt_root_hash_ptr { mt_root_hash_ptr }, + _mt_max_level { mt_max_level }, + _mt_degree { mt_degree }, + _mt_leaves { mt_leaves }, + _pba { pba }, + _nr_of_pbas { nr_of_pbas } +{ } + +char const *Ft_resizing_request::type_to_string(Type op) +{ + switch (op) { + case INVALID: return "invalid"; + case FT_EXTENSION_STEP: return "ft_ext_step"; + } + return "?"; +} + + +/************************* + ** Ft_resizing_request ** + *************************/ + +void Ft_resizing::_execute_ft_ext_step_read_inner_node_completed(Channel &channel, + unsigned const job_idx, + bool &progress) +{ + Request &req { channel._request }; + if (not channel._generated_prim.succ) { + class Primitive_not_successfull_ft_resizing { }; + throw Primitive_not_successfull_ft_resizing { }; + } + + if (channel._lvl_idx > 1) { + + if (channel._lvl_idx == req._ft_max_lvl) { + + if (not check_sha256_4k_hash(&channel._t1_blks.items[channel._lvl_idx], + &req._ft_root.hash)) { + class Program_error_ft_resizing_hash_mismatch { }; + throw Program_error_ft_resizing_hash_mismatch { }; + } + + } else { + + Tree_level_index const parent_lvl_idx = channel._lvl_idx + 1; + Tree_node_index const child_idx = t1_child_idx_for_vba(channel._vba, parent_lvl_idx, req._ft_degree); + Type_1_node const &child = channel._t1_blks.items[parent_lvl_idx].nodes[child_idx]; + + if (not check_sha256_4k_hash(&channel._t1_blks.items[channel._lvl_idx], + &child.hash)) { + class Program_error_ft_resizing_hash_mismatch_2 { }; + throw Program_error_ft_resizing_hash_mismatch_2 { }; + } + + } + + Tree_level_index const parent_lvl_idx = channel._lvl_idx; + Tree_level_index const child_lvl_idx = channel._lvl_idx - 1; + Tree_node_index const child_idx = t1_child_idx_for_vba(channel._vba, parent_lvl_idx, req._ft_degree); + Type_1_node const &child = channel._t1_blks.items[parent_lvl_idx].nodes[child_idx]; + + if (child.valid()) { + + channel._lvl_idx = child_lvl_idx; + channel._old_pbas.pbas [child_lvl_idx] = child.pba; + channel._old_generations.items[child_lvl_idx] = child.gen; + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_FT_RSZG_CACHE, + .blk_nr = child.pba, + .idx = job_idx + }; + + channel._state = Channel::State::READ_INNER_NODE_PENDING; + progress = true; + + if (VERBOSE_FT_EXTENSION) + log(" lvl ", parent_lvl_idx, " child ", child_idx, + " (", child, "): load to lvl ", channel._lvl_idx); + + } else { + + _add_new_branch_to_ft_using_pba_contingent(parent_lvl_idx, + child_idx, + req._ft_degree, + req._curr_gen, + req._pba, + req._nr_of_pbas, + channel._t1_blks, + channel._t2_blk, + channel._new_pbas, + channel._lvl_idx, + req._nr_of_leaves); + + channel._alloc_lvl_idx = parent_lvl_idx; + + if (channel._old_generations.items[channel._alloc_lvl_idx] == req._curr_gen) { + + channel._new_pbas.pbas[channel._alloc_lvl_idx] = + channel._old_pbas.pbas[channel._alloc_lvl_idx]; + + channel._state = Channel::State::ALLOC_PBA_COMPLETED; + progress = true; + + } else { + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_FT_RSZG_MT_ALLOC, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::ALLOC_PBA_PENDING; + progress = true; + + } + } + } else { + + { + Tree_level_index const parent_lvl_idx = channel._lvl_idx + 1; + Tree_node_index const child_idx = t1_child_idx_for_vba(channel._vba, parent_lvl_idx, req._ft_degree); + + if (not check_sha256_4k_hash(&channel._t2_blk, + &channel._t1_blks.items[parent_lvl_idx].nodes[child_idx].hash)) { + class Program_error_ft_resizing_hash_mismatch_3 { }; + throw Program_error_ft_resizing_hash_mismatch_3 { }; + } + } + + { + Tree_level_index const parent_lvl_idx = channel._lvl_idx; + Tree_node_index const child_idx = t2_child_idx_for_vba(channel._vba, req._ft_degree); + Type_2_node const &child = channel._t2_blk.nodes[child_idx]; + + if (child.valid()) { + class Program_error_ft_resizing_t2_valid { }; + throw Program_error_ft_resizing_t2_valid { }; + } + + _add_new_branch_to_ft_using_pba_contingent(parent_lvl_idx, + child_idx, + req._ft_degree, + req._curr_gen, + req._pba, + req._nr_of_pbas, + channel._t1_blks, + channel._t2_blk, + channel._new_pbas, + channel._lvl_idx, + req._nr_of_leaves); + + channel._alloc_lvl_idx = parent_lvl_idx; + + if (VERBOSE_FT_EXTENSION) + log(" alloc lvl ", channel._alloc_lvl_idx); + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_FT_RSZG_MT_ALLOC, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::ALLOC_PBA_PENDING; + progress = true; + } + } +} + + +void Ft_resizing::_set_args_for_write_back_of_inner_lvl(Tree_level_index const max_lvl_idx, + Tree_level_index const lvl_idx, + Physical_block_address const pba, + unsigned const prim_idx, + Channel::State &job_state, + bool &progress, + Channel::Generated_prim &prim) +{ + if (lvl_idx == 0) { + class Program_error_ft_resizing_lvl_idx_zero { }; + throw Program_error_ft_resizing_lvl_idx_zero { }; + } + + if (lvl_idx > max_lvl_idx) { + class Program_error_ft_resizing_lvl_idx_large { }; + throw Program_error_ft_resizing_lvl_idx_large { }; + } + + prim = { + .op = Channel::Generated_prim::Type::WRITE, + .succ = false, + .tg = Channel::Tag_type::TAG_FT_RSZG_CACHE, + .blk_nr = pba, + .idx = prim_idx + }; + + if (VERBOSE_FT_EXTENSION) + log(" lvl ", lvl_idx, " write to pba ", pba); + + if (lvl_idx < max_lvl_idx) { + job_state = Channel::State::WRITE_INNER_NODE_PENDING; + progress = true; + } else { + job_state = Channel::State::WRITE_ROOT_NODE_PENDING; + progress = true; + } +} + + +void Ft_resizing::_add_new_root_lvl_to_ft_using_pba_contingent(Type_1_node &ft_root, + Tree_level_index &ft_max_lvl_idx, + Number_of_leaves const ft_nr_of_leaves, + Generation const curr_gen, + Channel::Type_1_node_blocks &t1_blks, + Tree_walk_pbas &new_pbas, + Physical_block_address &first_pba, + Number_of_blocks &nr_of_pbas) +{ + if (ft_max_lvl_idx >= TREE_MAX_LEVEL) { + class Program_error_ft_resizing_max_level { }; + throw Program_error_ft_resizing_max_level { }; + } + + ft_max_lvl_idx += 1; + + t1_blks.items[ft_max_lvl_idx] = { }; + t1_blks.items[ft_max_lvl_idx].nodes[0] = ft_root; + + new_pbas.pbas[ft_max_lvl_idx] = alloc_pba_from_resizing_contingent(first_pba, nr_of_pbas); + + ft_root = { + .pba = new_pbas.pbas[ft_max_lvl_idx], + .gen = curr_gen, + .hash = { }, + }; + + if (VERBOSE_FT_EXTENSION) { + log(" set ft root: ", ft_root, " leaves ", ft_nr_of_leaves, + " max lvl ", ft_max_lvl_idx); + + log(" set lvl ", ft_max_lvl_idx, + " child 0: ", t1_blks.items[ft_max_lvl_idx].nodes[0]); + } + (void)ft_nr_of_leaves; +} + + +void Ft_resizing::_add_new_branch_to_ft_using_pba_contingent(Tree_level_index const mount_point_lvl_idx, + Tree_node_index const mount_point_child_idx, + Tree_degree const ft_degree, + Generation const curr_gen, + Physical_block_address &first_pba, + Number_of_blocks &nr_of_pbas, + Channel::Type_1_node_blocks &t1_blks, + Type_2_node_block &t2_blk, + Tree_walk_pbas &new_pbas, + Tree_level_index &stopped_at_lvl_idx, + Number_of_leaves &nr_of_leaves) +{ + nr_of_leaves = 0; + stopped_at_lvl_idx = mount_point_lvl_idx; + + if (mount_point_lvl_idx > 1) { + for (unsigned lvl_idx = 1; lvl_idx <= mount_point_lvl_idx - 1; lvl_idx++) { + if (lvl_idx > 1) + t1_blks.items[lvl_idx] = Type_1_node_block { }; + else + t2_blk = Type_2_node_block { }; + + if (VERBOSE_FT_EXTENSION) + log(" reset lvl ", lvl_idx); + } + } + + if (nr_of_pbas > 0) { + + for (unsigned lvl_idx = mount_point_lvl_idx; lvl_idx >= 1; lvl_idx --) { + stopped_at_lvl_idx = lvl_idx; + + if (lvl_idx > 1) { + + if (nr_of_pbas == 0) + break; + + Tree_node_index const child_idx = (lvl_idx == mount_point_lvl_idx) ? mount_point_child_idx : 0; + Tree_level_index const child_lvl_idx = lvl_idx - 1; + + new_pbas.pbas[child_lvl_idx] = alloc_pba_from_resizing_contingent(first_pba, nr_of_pbas); + + t1_blks.items[lvl_idx].nodes[child_idx] = { + .pba = new_pbas.pbas[child_lvl_idx], + .gen = curr_gen, + .hash = { } + }; + + if (VERBOSE_FT_EXTENSION) + log(" set lvl d ", lvl_idx, " child ", child_idx, + ": ", t1_blks.items[lvl_idx].nodes[child_idx]); + + } else { + Tree_node_index const first_child_idx = (lvl_idx == mount_point_lvl_idx) ? mount_point_child_idx : 0; + + for (Tree_node_index child_idx = first_child_idx; child_idx <= ft_degree - 1; child_idx++) { + + if (nr_of_pbas == 0) + break; + + Physical_block_address child_pba = alloc_pba_from_resizing_contingent(first_pba, nr_of_pbas); + + t2_blk.nodes[child_idx] = { + .pba = child_pba, + .last_vba = INVALID_VBA, + .alloc_gen = INITIAL_GENERATION, + .free_gen = INITIAL_GENERATION, + .last_key_id = INVALID_KEY_ID, + .reserved = false + }; + + if (VERBOSE_FT_EXTENSION) + log(" set lvl e ", lvl_idx, " child ", child_idx, + ": ", t2_blk.nodes[child_idx]); + + nr_of_leaves = nr_of_leaves + 1; + } + } + } + } +} + + +void Ft_resizing::_execute_ft_extension_step(Channel &chan, + unsigned const chan_idx, + bool &progress) +{ + Request &req { chan._request }; + switch (chan._state) { + case Channel::State::SUBMITTED: + + req._nr_of_leaves = 0; + chan._vba = req._ft_nr_of_leaves; + + chan._old_pbas = { }; + chan._old_generations = { }; + chan._new_pbas = { }; + + chan._lvl_idx = req._ft_max_lvl; + chan._old_pbas.pbas[chan._lvl_idx] = req._ft_root.pba; + chan._old_generations.items[chan._lvl_idx] = req._ft_root.gen; + + if (chan._vba <= tree_max_max_vba(req._ft_degree, req._ft_max_lvl)) { + + chan._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_FT_RSZG_CACHE, + .blk_nr = req._ft_root.pba, + .idx = chan_idx + }; + + if (VERBOSE_FT_EXTENSION) + log(" root (", req._ft_root, + " leaves ", req._ft_nr_of_leaves, + " max lvl ", req._ft_max_lvl, + "): load to lvl ", chan._lvl_idx); + + chan._state = Channel::State::READ_ROOT_NODE_PENDING; + progress = true; + + } else { + + _add_new_root_lvl_to_ft_using_pba_contingent(req._ft_root, + req._ft_max_lvl, + req._ft_nr_of_leaves, + req._curr_gen, + chan._t1_blks, + chan._new_pbas, + req._pba, + req._nr_of_pbas); + + _add_new_branch_to_ft_using_pba_contingent(req._ft_max_lvl, + 1, + req._ft_degree, + req._curr_gen, + req._pba, + req._nr_of_pbas, + chan._t1_blks, + chan._t2_blk, + chan._new_pbas, + chan._lvl_idx, + req._nr_of_leaves); + + if (VERBOSE_FT_EXTENSION) + log(" pbas allocated: curr gen ", req._curr_gen); + + _set_args_for_write_back_of_inner_lvl(req._ft_max_lvl, + chan._lvl_idx, + chan._new_pbas.pbas[chan._lvl_idx], + chan_idx, + chan._state, + progress, + chan._generated_prim); + + } + + break; + case Channel::State::READ_ROOT_NODE_COMPLETED: + _execute_ft_ext_step_read_inner_node_completed(chan, chan_idx, progress); + break; + case Channel::State::READ_INNER_NODE_COMPLETED: + _execute_ft_ext_step_read_inner_node_completed(chan, chan_idx, progress); + break; + case Channel::State::ALLOC_PBA_COMPLETED: + if (chan._alloc_lvl_idx < req._ft_max_lvl) { + + chan._alloc_lvl_idx = chan._alloc_lvl_idx + 1; + + if (chan._old_generations.items[chan._alloc_lvl_idx] == req._curr_gen) { + + chan._new_pbas.pbas[chan._alloc_lvl_idx] = chan._old_pbas.pbas[chan._alloc_lvl_idx]; + + chan._state = Channel::State::ALLOC_PBA_COMPLETED; + progress = true; + + } else { + + chan._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_FT_RSZG_MT_ALLOC, + .blk_nr = 0, + .idx = chan_idx + }; + + chan._state = Channel::State::ALLOC_PBA_PENDING; + progress = true; + + } + + } else { + + if (VERBOSE_FT_EXTENSION) + log(" pbas allocated: curr gen ", req._curr_gen); +/* +log("YYY ", +chan._alloc_lvl_idx, " ", +req._ft_max_lvl, " ", +req._ft_degree, " ", +req._pba, " ", +req._nr_of_pbas, " ", +(uint64_t)chan._new_pbas.pbas[0], " ", + (uint64_t)chan._new_pbas.pbas[1], " ", + (uint64_t)chan._new_pbas.pbas[2], " ", + (uint64_t)chan._new_pbas.pbas[3], " ", + (uint64_t)chan._new_pbas.pbas[4], " ", + (uint64_t)chan._new_pbas.pbas[5], " ", + (uint64_t)chan._new_pbas.pbas[6], " ", +chan._lvl_idx, " ", +req._nr_of_leaves); +*/ + + _set_args_for_write_back_of_inner_lvl(req._ft_max_lvl, + chan._lvl_idx, + chan._new_pbas.pbas[chan._lvl_idx], + chan_idx, + chan._state, + progress, + chan._generated_prim); + + } + break; + case Channel::State::WRITE_INNER_NODE_COMPLETED: + + if (not chan._generated_prim.succ) { + class Primitive_not_successfull_ft_resizing_write_inner { }; + throw Primitive_not_successfull_ft_resizing_write_inner { }; + } + + if (chan._lvl_idx > 1) { + + Tree_level_index const parent_lvl_idx = chan._lvl_idx + 1; + Tree_level_index const child_lvl_idx = chan._lvl_idx; + Tree_node_index const child_idx = t1_child_idx_for_vba(chan._vba, parent_lvl_idx, req._ft_degree); + + Type_1_node &child { + chan._t1_blks.items[parent_lvl_idx].nodes[child_idx] }; + + child = { + .pba = chan._new_pbas.pbas[child_lvl_idx], + .gen = req._curr_gen, + .hash = { }, + .padding = { } + }; + + calc_sha256_4k_hash(&chan._t1_blks.items[child_lvl_idx], + &child.hash); + + if (VERBOSE_FT_EXTENSION) + log(" set lvl a ", parent_lvl_idx, " child ", child_idx, + ": ", child); + + _set_args_for_write_back_of_inner_lvl(req._ft_max_lvl, + parent_lvl_idx, + chan._new_pbas.pbas[parent_lvl_idx], + chan_idx, + chan._state, + progress, + chan._generated_prim); + + chan._lvl_idx += 1; + + } else { + + Tree_level_index const parent_lvl_idx = chan._lvl_idx + 1; + Tree_level_index const child_lvl_idx = chan._lvl_idx; + Tree_node_index const child_idx = t1_child_idx_for_vba(chan._vba, parent_lvl_idx, req._ft_degree); + Type_1_node &child = chan._t1_blks.items[parent_lvl_idx].nodes[child_idx]; + child = { + .pba = chan._new_pbas.pbas[child_lvl_idx], + .gen = req._curr_gen, + .padding = {} + }; + + calc_sha256_4k_hash(&chan._t2_blk, &child.hash); + + if (VERBOSE_FT_EXTENSION) + log(" set lvl b ", parent_lvl_idx, " child ", child_idx, + ": ", child); + + _set_args_for_write_back_of_inner_lvl(req._ft_max_lvl, + parent_lvl_idx, + chan._new_pbas.pbas[parent_lvl_idx], + chan_idx, + chan._state, + progress, + chan._generated_prim); + + chan._lvl_idx += 1; // = 2 + + } + break; + case Channel::State::WRITE_ROOT_NODE_COMPLETED: { + + if (not chan._generated_prim.succ) { + class Primitive_not_successfull_ft_resizing_write_root { }; + throw Primitive_not_successfull_ft_resizing_write_root { }; + } + + Tree_level_index const child_lvl_idx = chan._lvl_idx; + Physical_block_address const child_pba = chan._new_pbas.pbas[child_lvl_idx]; + + req._ft_root = { + .pba = child_pba, + .gen = req._curr_gen, + .padding = {} + }; + + calc_sha256_4k_hash(&chan._t1_blks.items[child_lvl_idx], &req._ft_root.hash); + + req._ft_nr_of_leaves += req._nr_of_leaves; + + req._success = true; + + chan._state = Channel::State::COMPLETED; + progress = true; + + break; + } + default: + break; + } +} + + +void Ft_resizing::execute(bool &progress) +{ + for (unsigned idx = 0; idx < NR_OF_CHANNELS; idx++) { + + Channel &channel = _channels[idx]; + Request &request { channel._request }; + + switch (request._type) { + case Request::INVALID: + break; + case Request::FT_EXTENSION_STEP: + _execute_ft_extension_step(channel, idx, progress); + break; + } + } +} + + +bool Ft_resizing::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._request._type != Request::INVALID && + channel._state == Channel::COMPLETED) { + + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Ft_resizing::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + if (chan._request._type == Request::INVALID || + chan._state != Channel::COMPLETED) { + + class Exception_2 { }; + throw Exception_2 { }; + } + chan._request._type = Request::INVALID; +} + + +bool Ft_resizing::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel &chan { _channels[id] }; + Request &req { chan._request }; + if (req._type == Request::INVALID) + continue; + + switch (chan._state) { + case Channel::WRITE_ROOT_NODE_PENDING: + case Channel::WRITE_INNER_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, FT_RESIZING, id, + Block_io_request::WRITE, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, + chan._lvl_idx > 1 ? + (void *)&chan._t1_blks.items[chan._lvl_idx] : + (void *)&chan._t2_blk, + nullptr); + + return true; + + case Channel::READ_ROOT_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, FT_RESIZING, id, + Block_io_request::READ, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, + (void *)&chan._t1_blks.items[chan._lvl_idx], + nullptr); + + return true; + + case Channel::READ_INNER_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, FT_RESIZING, id, + Block_io_request::READ, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, + chan._lvl_idx > 1 ? + (void *)&chan._t1_blks.items[chan._lvl_idx] : + (void *)&chan._t2_blk, + nullptr); + + return true; + + case Channel::State::ALLOC_PBA_PENDING: + + Meta_tree_request::create( + buf_ptr, buf_size, FT_RESIZING, id, Meta_tree_request::UPDATE, + (void *)req._mt_root_pba_ptr, + (void *)req._mt_root_gen_ptr, + (void *)req._mt_root_hash_ptr, + req._mt_max_level, + req._mt_degree, + req._mt_leaves, + req._curr_gen, + chan._old_pbas.pbas[chan._alloc_lvl_idx]); + + return true; + + case Channel::EXTEND_MT_BY_ONE_LEAF_PENDING: + + class Exception_10 { }; + throw Exception_10 { }; + + default: break; + } + } + return false; +} + + +void Ft_resizing::_drop_generated_request(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (chan._state) { + case Channel::READ_ROOT_NODE_PENDING: chan._state = Channel::READ_ROOT_NODE_IN_PROGRESS; break; + case Channel::READ_INNER_NODE_PENDING: chan._state = Channel::READ_INNER_NODE_IN_PROGRESS; break; + case Channel::WRITE_ROOT_NODE_PENDING: chan._state = Channel::WRITE_ROOT_NODE_IN_PROGRESS; break; + case Channel::WRITE_INNER_NODE_PENDING: chan._state = Channel::WRITE_INNER_NODE_IN_PROGRESS; break; + case Channel::ALLOC_PBA_PENDING: chan._state = Channel::ALLOC_PBA_IN_PROGRESS; break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } +} + + +void Ft_resizing::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (mod_req.dst_module_id()) { + case BLOCK_IO: + { + Block_io_request &blk_io_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = blk_io_req.success(); + switch (chan._state) { + case Channel::READ_ROOT_NODE_IN_PROGRESS: chan._state = Channel::READ_ROOT_NODE_COMPLETED; break; + case Channel::READ_INNER_NODE_IN_PROGRESS: chan._state = Channel::READ_INNER_NODE_COMPLETED; break; + case Channel::WRITE_ROOT_NODE_IN_PROGRESS: chan._state = Channel::WRITE_ROOT_NODE_COMPLETED; break; + case Channel::WRITE_INNER_NODE_IN_PROGRESS: chan._state = Channel::WRITE_INNER_NODE_COMPLETED; break; + default: + class Exception_4 { }; + throw Exception_4 { }; + } + break; + } + case META_TREE: + { + Meta_tree_request &mt_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = mt_req.success(); + switch (chan._state) { + case Channel::ALLOC_PBA_IN_PROGRESS: + chan._new_pbas.pbas[chan._alloc_lvl_idx] = mt_req.new_pba(); + chan._state = Channel::ALLOC_PBA_COMPLETED; + break; + default: + class Exception_7 { }; + throw Exception_7 { }; + } + break; + } + default: + class Exception_5 { }; + throw Exception_5 { }; + } +} + + +bool Ft_resizing::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._request._type == Request::INVALID) + return true; + } + return false; +} + + +void Ft_resizing::submit_request(Module_request &mod_req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + Channel &chan { _channels[id] }; + if (chan._request._type == Request::INVALID) { + mod_req.dst_request_id(id); + chan._request = *static_cast(&mod_req); + chan._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} diff --git a/repos/gems/src/lib/tresor/include/tresor/block_allocator.h b/repos/gems/src/lib/tresor/include/tresor/block_allocator.h new file mode 100644 index 0000000000..90954fcc33 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/block_allocator.h @@ -0,0 +1,141 @@ +/* + * \brief Managing block allocation for the initialization of a Tresor device + * \author Josef Soentgen + * \date 2023-02-28 + */ + +/* + * 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__BLOCK_ALLOCATOR_H_ +#define _TRESOR__BLOCK_ALLOCATOR_H_ + +/* tresor includes */ +#include +#include + +namespace Tresor { + + class Block_allocator; + class Block_allocator_request; + class Block_allocator_channel; +} + + +class Tresor::Block_allocator_request : public Module_request +{ + public: + + enum Type { INVALID = 0, GET = 1, }; + + private: + + friend class Block_allocator; + friend class Block_allocator_channel; + + Type _type { INVALID }; + uint64_t _blk_nr { 0 }; + bool _success { false }; + + public: + + Block_allocator_request() { } + + Block_allocator_request(Module_id src_module_id, + Module_request_id src_request_id); + + static void create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type); + + uint64_t blk_nr() const { return _blk_nr; } + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override; +}; + + +class Tresor::Block_allocator_channel +{ + private: + + friend class Block_allocator; + + enum State { INACTIVE, SUBMITTED, PENDING, COMPLETE }; + + State _state { INACTIVE }; + Block_allocator_request _request { }; +}; + + +class Tresor::Block_allocator : public Module +{ + private: + + using Request = Block_allocator_request; + using Channel = Block_allocator_channel; + + uint64_t const _first_block; + uint64_t _nr_of_blks; + + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + void _execute_get(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + public: + + Block_allocator(uint64_t first_block); + + uint64_t first_block() const { return _first_block; } + + uint64_t nr_of_blks() const { return _nr_of_blks; } + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + void execute(bool &) override; + +}; + +#endif /* _TRESOR__BLOCK_ALLOCATOR_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/block_io.h b/repos/gems/src/lib/tresor/include/tresor/block_io.h new file mode 100644 index 0000000000..72c2d92456 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/block_io.h @@ -0,0 +1,178 @@ +/* + * \brief Module for accessing the back-end block device + * \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__BLOCK_IO_H_ +#define _TRESOR__BLOCK_IO_H_ + +/* tresor includes */ +#include +#include +#include + +namespace Tresor { + + class Block_io; + class Block_io_request; + class Block_io_channel; +} + +class Tresor::Block_io_request : public Module_request +{ + public: + + enum Type { + INVALID = 0, READ = 1, WRITE = 2, SYNC = 3, READ_CLIENT_DATA = 4, + WRITE_CLIENT_DATA = 5 }; + + private: + + friend class Block_io; + friend class Block_io_channel; + + Type _type { INVALID }; + uint64_t _client_req_offset { 0 }; + uint64_t _client_req_tag { 0 }; + uint32_t _key_id { 0 }; + uint64_t _pba { 0 }; + uint64_t _vba { 0 }; + uint64_t _blk_count { 0 }; + addr_t _blk_ptr { 0 }; + addr_t _hash_ptr { 0 }; + bool _success { false }; + + public: + + Block_io_request() { } + + Block_io_request(uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t client_req_offset, + uint64_t client_req_tag, + uint32_t key_id, + uint64_t pba, + uint64_t vba, + uint64_t blk_count, + void *blk_ptr, + void *hash_ptr); + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + char const *type_name() const { return type_to_string(_type); } + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override; +}; + +class Tresor::Block_io_channel +{ + private: + + friend class Block_io; + + enum State { + INACTIVE, SUBMITTED, PENDING, IN_PROGRESS, COMPLETE, + ENCRYPT_CLIENT_DATA_PENDING, + ENCRYPT_CLIENT_DATA_IN_PROGRESS, + ENCRYPT_CLIENT_DATA_COMPLETE, + DECRYPT_CLIENT_DATA_PENDING, + DECRYPT_CLIENT_DATA_IN_PROGRESS, + DECRYPT_CLIENT_DATA_COMPLETE + }; + + State _state { INACTIVE }; + Block_io_request _request { }; + Vfs::file_offset _nr_of_processed_bytes { 0 }; + size_t _nr_of_remaining_bytes { 0 }; + char _blk_buf[BLOCK_SIZE] { 0 }; + bool _generated_req_success { false }; +}; + +class Tresor::Block_io : public Module +{ + private: + + using Request = Block_io_request; + using Channel = Block_io_channel; + using Read_result = Vfs::File_io_service::Read_result; + using Write_result = Vfs::File_io_service::Write_result; + using file_size = Vfs::file_size; + using file_offset = Vfs::file_offset; + + enum { NR_OF_CHANNELS = 1 }; + + String<32> const _path; + Vfs::Env &_vfs_env; + Vfs::Vfs_handle &_vfs_handle { vfs_open_rw(_vfs_env, _path) }; + Channel _channels[NR_OF_CHANNELS] { }; + + void _execute_read(Channel &channel, + bool &progress); + + void _execute_write(Channel &channel, + bool &progress); + + void _execute_read_client_data(Channel &channel, + bool &progress); + + void _execute_write_client_data(Channel &channel, + bool &progress); + + void _execute_sync(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + void execute(bool &) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + public: + + Block_io(Vfs::Env &vfs_env, + Xml_node const &xml_node); +}; + +#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 new file mode 100644 index 0000000000..5255d40100 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/client_data.h @@ -0,0 +1,104 @@ +/* + * \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 +#include + +namespace Tresor { + + class Client_data_request; +} + +namespace Vfs_tresor { + + class Wrapper; +} + +namespace Tresor_tester { + + class Main; +} + +class Tresor::Client_data_request : public Module_request +{ + public: + + enum Type { INVALID, OBTAIN_PLAINTEXT_BLK, SUPPLY_PLAINTEXT_BLK }; + + private: + + friend class ::Vfs_tresor::Wrapper; + friend class ::Tresor_tester::Main; + + Type _type { INVALID }; + uint64_t _client_req_offset { 0 }; + uint64_t _client_req_tag { 0 }; + uint64_t _pba { 0 }; + uint64_t _vba { 0 }; + addr_t _plaintext_blk_ptr { 0 }; + bool _success { false }; + + public: + + Client_data_request() { } + + Type type() const { return _type; } + + + /***************************************************** + ** can be removed once the tresor translation is done ** + *****************************************************/ + + Client_data_request(Module_id src_module_id, + Module_request_id src_request_id, + Type type, + uint64_t client_req_offset, + uint64_t client_req_tag, + uint64_t pba, + uint64_t vba, + addr_t plaintext_blk_ptr) + : + Module_request { src_module_id, src_request_id, CLIENT_DATA }, + _type { type }, + _client_req_offset { client_req_offset }, + _client_req_tag { client_req_tag }, + _pba { pba }, + _vba { vba }, + _plaintext_blk_ptr { plaintext_blk_ptr } + { } + + bool success() const { return _success; } + + static char const *type_to_string(Type type) + { + switch (type) { + case INVALID: return "invalid"; + case OBTAIN_PLAINTEXT_BLK: return "obtain_plaintext_blk"; + case SUPPLY_PLAINTEXT_BLK: return "supply_plaintext_blk"; + } + return "?"; + } + + + /******************** + ** Module_request ** + ********************/ + + 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/construct_in_buf.h b/repos/gems/src/lib/tresor/include/tresor/construct_in_buf.h new file mode 100644 index 0000000000..53102f54dc --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/construct_in_buf.h @@ -0,0 +1,38 @@ +/* + * \brief Size protected wrapper for the manual placement of objects + * \author Martin Stein + * \date 2023-03-23 + */ + +/* + * 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__CONSTRUCT_IN_BUF_H_ +#define _TRESOR__CONSTRUCT_IN_BUF_H_ + +/* base includes */ +#include + +namespace Tresor { + + using namespace Genode; + + template + static inline void construct_in_buf(void *buf_ptr, + size_t buf_size, + ARGS &&... args) + { + if (sizeof(T) > buf_size) { + class Buffer_too_small { }; + throw Buffer_too_small { }; + } + construct_at(buf_ptr, args...); + } +} + +#endif /* _TRESOR__CONSTRUCT_IN_BUF_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/crypto.h b/repos/gems/src/lib/tresor/include/tresor/crypto.h new file mode 100644 index 0000000000..be98c9f289 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/crypto.h @@ -0,0 +1,205 @@ +/* + * \brief Module for encrypting/decrypting single data blocks + * \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__CRYPTO_H_ +#define _TRESOR__CRYPTO_H_ + +/* tresor includes */ +#include +#include +#include + +namespace Tresor { + + class Crypto; + class Crypto_request; + class Crypto_channel; +} + +class Tresor::Crypto_request : public Module_request +{ + public: + + enum Type { + INVALID = 0, ADD_KEY = 1, REMOVE_KEY = 2, DECRYPT = 3, ENCRYPT = 4, + DECRYPT_CLIENT_DATA = 5, ENCRYPT_CLIENT_DATA = 6 }; + + private: + + friend class Crypto; + friend class Crypto_channel; + + Type _type { INVALID }; + uint64_t _client_req_offset { 0 }; + uint64_t _client_req_tag { 0 }; + uint64_t _pba { 0 }; + uint64_t _vba { 0 }; + uint32_t _key_id { 0 }; + addr_t _key_plaintext_ptr { 0 }; + addr_t _plaintext_blk_ptr { 0 }; + addr_t _ciphertext_blk_ptr { 0 }; + bool _success { false }; + + public: + + Crypto_request() { } + + Type type() const { return _type; } + + Crypto_request(uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t client_req_offset, + uint64_t client_req_tag, + uint32_t key_id, + void *key_plaintext_ptr, + uint64_t pba, + uint64_t vba, + void *plaintext_blk_ptr, + void *ciphertext_blk_ptr); + + bool success() const { return _success; } + + static const char *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override + { + 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; + } + } +}; + +class Tresor::Crypto_channel +{ + private: + + friend class Crypto; + + enum State { + INACTIVE, SUBMITTED, COMPLETE, OBTAIN_PLAINTEXT_BLK_PENDING, + OBTAIN_PLAINTEXT_BLK_IN_PROGRESS, OBTAIN_PLAINTEXT_BLK_COMPLETE, + SUPPLY_PLAINTEXT_BLK_PENDING, SUPPLY_PLAINTEXT_BLK_IN_PROGRESS, + SUPPLY_PLAINTEXT_BLK_COMPLETE, OP_WRITTEN_TO_VFS_HANDLE, + QUEUE_READ_SUCCEEDED }; + + State _state { INACTIVE }; + Crypto_request _request { }; + bool _generated_req_success { false }; + Vfs::Vfs_handle *_vfs_handle { nullptr }; + char _blk_buf[BLOCK_SIZE] { 0 }; + + public: + + Crypto_request const &request() const { return _request; } +}; + +class Tresor::Crypto : public Module +{ + private: + + using Request = Crypto_request; + using Channel = Crypto_channel; + using Write_result = Vfs::File_io_service::Write_result; + using Read_result = Vfs::File_io_service::Read_result; + + enum { NR_OF_CHANNELS = 4 }; + + struct Key_directory + { + Vfs::Vfs_handle *encrypt_handle { nullptr }; + Vfs::Vfs_handle *decrypt_handle { nullptr }; + uint32_t key_id { 0 }; + }; + + Vfs::Env &_vfs_env; + String<32> const _path; + Vfs::Vfs_handle &_add_key_handle; + Vfs::Vfs_handle &_remove_key_handle; + Channel _channels[NR_OF_CHANNELS] { }; + Key_directory _key_dirs[2] { }; + + Key_directory &_lookup_key_dir(uint32_t key_id); + + void _execute_add_key(Channel &channel, + bool &progress); + + void _execute_remove_key(Channel &channel, + bool &progress); + + void _execute_decrypt(Channel &channel, + bool &progress); + + void _execute_encrypt(Channel &channel, + bool &progress); + + void _execute_encrypt_client_data(Channel &channel, + bool &progress); + + void _execute_decrypt_client_data(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + void execute(bool &) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + public: + + Crypto(Vfs::Env &vfs_env, + Xml_node const &xml_node); +}; + +#endif /* _TRESOR__CRYPTO_H_ */ diff --git a/repos/gems/include/cbe/crypto/interface.h b/repos/gems/src/lib/tresor/include/tresor/crypto/interface.h similarity index 62% rename from repos/gems/include/cbe/crypto/interface.h rename to repos/gems/src/lib/tresor/include/tresor/crypto/interface.h index e0fe70037a..9aea23664d 100644 --- a/repos/gems/include/cbe/crypto/interface.h +++ b/repos/gems/src/lib/tresor/include/tresor/crypto/interface.h @@ -1,5 +1,5 @@ /* - * \brief Integration of the Consistent Block Encrypter (CBE) + * \brief Integration of the Tresor block encryption * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 @@ -12,35 +12,32 @@ * under the terms of the GNU Affero General Public License version 3. */ -#ifndef _INCLUDE__CBE__CRYPTO__INTERFACE_H_ -#define _INCLUDE__CBE__CRYPTO__INTERFACE_H_ +#ifndef _TRESOR__CRYPTO__INTERFACE_H_ +#define _TRESOR__CRYPTO__INTERFACE_H_ -/* Genode includes */ +/* base includes */ #include #include +/* tresor includes */ +#include -namespace Cbe_crypto { - using uint32_t = Genode::uint32_t; - using uint64_t = Genode::uint64_t; - using size_t = Genode::size_t; - using Byte_range_ptr = Genode::Byte_range_ptr; - using Const_byte_range_ptr = Genode::Const_byte_range_ptr; +namespace Tresor_crypto { + + using namespace Genode; + using namespace Tresor; struct Interface; Interface &get_interface(); - - enum { BLOCK_SIZE = 4096u }; - -} /* namespace Cbe_crypto */ +} -struct Cbe_crypto::Interface +struct Tresor_crypto::Interface { - struct Buffer_too_small : Genode::Exception { }; - struct Key_value_size_mismatch : Genode::Exception { }; + struct Buffer_too_small : Exception { }; + struct Key_value_size_mismatch : Exception { }; struct Complete_request { @@ -51,6 +48,7 @@ struct Cbe_crypto::Interface struct Slots { enum { NUM_SLOTS = 2, }; + uint32_t _store[NUM_SLOTS] { }; bool store(uint32_t const id) @@ -98,22 +96,22 @@ struct Cbe_crypto::Interface virtual bool execute() = 0; virtual bool add_key(uint32_t const id, - char const *value, + char const *value, size_t value_len) = 0; virtual bool remove_key(uint32_t const id) = 0; - virtual bool submit_encryption_request(uint64_t const block_number, - uint32_t const key_id, + virtual bool submit_encryption_request(uint64_t const block_number, + uint32_t const key_id, Const_byte_range_ptr const &src) = 0; virtual Complete_request encryption_request_complete(Byte_range_ptr const &dst) = 0; - virtual bool submit_decryption_request(uint64_t const block_number, - uint32_t const key_id, + virtual bool submit_decryption_request(uint64_t const block_number, + uint32_t const key_id, Const_byte_range_ptr const &src) = 0; virtual Complete_request decryption_request_complete(Byte_range_ptr const &dst) = 0; }; -#endif /* _INCLUDE__CBE__CRYPTO__INTERFACE_H_ */ +#endif /* _TRESOR__CRYPTO__INTERFACE_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 new file mode 100644 index 0000000000..d2132f3681 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/free_tree.h @@ -0,0 +1,488 @@ +/* + * \brief Module for doing VBD COW allocations on the free tree + * \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__FREE_TREE_H_ +#define _TRESOR__FREE_TREE_H_ + +/* tresor includes */ +#include +#include +#include + +namespace Tresor { + + class Free_tree; + class Free_tree_request; + class Free_tree_channel; +} + +class Tresor::Free_tree_request : public Module_request +{ + public: + + enum Type { + INVALID = 0, ALLOC_FOR_NON_RKG = 1, ALLOC_FOR_RKG_CURR_GEN_BLKS = 2, + ALLOC_FOR_RKG_OLD_GEN_BLKS = 3 }; + + private: + + friend class Free_tree; + friend class Free_tree_channel; + + Type _type { INVALID }; + addr_t _ft_root_pba_ptr { 0 }; + addr_t _ft_root_gen_ptr { 0 }; + addr_t _ft_root_hash_ptr { 0 }; + uint64_t _ft_max_level { 0 }; + uint64_t _ft_degree { 0 }; + uint64_t _ft_leaves { 0 }; + addr_t _mt_root_pba_ptr { 0 }; + addr_t _mt_root_gen_ptr { 0 }; + addr_t _mt_root_hash_ptr { 0 }; + uint64_t _mt_max_level { 0 }; + uint64_t _mt_degree { 0 }; + uint64_t _mt_leaves { 0 }; + uint64_t _current_gen { 0 }; + uint64_t _free_gen { 0 }; + uint64_t _requested_blocks { 0 }; + addr_t _new_blocks_ptr { 0 }; + addr_t _old_blocks_ptr { 0 }; + uint64_t _max_level { 0 }; + uint64_t _vba { INVALID_VBA }; + uint64_t _vbd_degree { 0 }; + uint64_t _vbd_highest_vba { 0 }; + bool _rekeying { 0 }; + uint32_t _previous_key_id { 0 }; + uint32_t _current_key_id { 0 }; + uint64_t _rekeying_vba { 0 }; + bool _success { false }; + addr_t _snapshots_ptr { 0 }; + Generation _last_secured_generation { INVALID_GENERATION }; + + public: + + Free_tree_request() { } + + Free_tree_request(uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + addr_t ft_root_pba_ptr, + addr_t ft_root_gen_ptr, + addr_t ft_root_hash_ptr, + uint64_t ft_max_level, + uint64_t ft_degree, + uint64_t ft_leaves, + addr_t mt_root_pba_ptr, + addr_t mt_root_gen_ptr, + addr_t mt_root_hash_ptr, + uint64_t mt_max_level, + uint64_t mt_degree, + uint64_t mt_leaves, + Snapshots const *snapshots, + Generation last_secured_generation, + uint64_t current_gen, + uint64_t free_gen, + uint64_t requested_blocks, + addr_t new_blocks_ptr, + addr_t old_blocks_ptr, + uint64_t max_level, + uint64_t vba, + uint64_t vbd_degree, + uint64_t vbd_highest_vba, + bool rekeying, + uint32_t previous_key_id, + uint32_t current_key_id, + uint64_t rekeying_vba); + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } +}; + + +class Tresor::Free_tree_channel +{ + private: + + friend class Free_tree; + + using Request = Free_tree_request; + + enum State { + INVALID, + SCAN, + SCAN_COMPLETE, + UPDATE, + UPDATE_COMPLETE, + COMPLETE, + NOT_ENOUGH_FREE_BLOCKS, + TREE_HASH_MISMATCH + }; + + struct Type_1_info + { + enum State { + INVALID, AVAILABLE, READ, WRITE, COMPLETE }; + + State state { INVALID }; + Type_1_node node { }; + Tree_node_index index { INVALID_NODE_INDEX }; + bool volatil { false }; + }; + + struct Type_2_info + { + enum State { + INVALID, AVAILABLE, READ, WRITE, COMPLETE }; + + State state { INVALID }; + Type_2_node node { }; + Tree_node_index index { INVALID_NODE_INDEX }; + }; + + struct Local_cache_request + { + enum State { INVALID, PENDING, IN_PROGRESS, COMPLETE }; + enum Op { READ, WRITE, SYNC }; + + State state { INVALID }; + Op op { READ }; + bool success { false }; + uint64_t pba { 0 }; + uint64_t level { 0 }; + }; + + struct Local_meta_tree_request + { + enum State { INVALID, PENDING, IN_PROGRESS, COMPLETE }; + enum Op { READ, WRITE, SYNC }; + + State state { INVALID }; + Op op { READ }; + uint64_t pba { 0 }; + }; + + class Type_1_info_stack { + + private: + + enum { MIN = 1, MAX = TREE_MAX_DEGREE, }; + + Type_1_info _container[MAX + 1] { }; + uint64_t _top { MIN - 1 }; + + public: + + bool empty() const { return _top < MIN; } + + bool full() const { return _top >= MAX; } + + Type_1_info peek_top() const + { + if (empty()) { + class Exception_1 { }; + throw Exception_1 { }; + } + return _container[_top]; + } + + void reset() { _top = MIN - 1; } + + void pop() + { + if (empty()) { + class Exception_1 { }; + throw Exception_1 { }; + } + _top--; + } + + void push(Type_1_info val) + { + if (full()) { + class Exception_1 { }; + throw Exception_1 { }; + } + _top++; + _container[_top] = val; + } + + void update_top(Type_1_info val) + { + if (empty()) { + class Exception_1 { }; + throw Exception_1 { }; + } + _container[_top] = val; + } + }; + + class Type_2_info_stack { + + private: + + enum { MIN = 1, MAX = TREE_MAX_DEGREE, }; + + Type_2_info _container[MAX + 1] { }; + uint64_t _top { MIN - 1 }; + + public: + + bool empty() const { return _top < MIN; } + + bool full() const { return _top >= MAX; } + + Type_2_info peek_top() const + { + if (empty()) { + class Exception_1 { }; + throw Exception_1 { }; + } + return _container[_top]; + } + + void reset() { _top = MIN - 1; } + + void pop() + { + if (empty()) { + class Exception_1 { }; + throw Exception_1 { }; + } + _top--; + } + + void push(Type_2_info val) + { + if (full()) { + class Exception_1 { }; + throw Exception_1 { }; + } + _top++; + _container[_top] = val; + } + + void update_top(Type_2_info val) + { + if (empty()) { + class Exception_1 { }; + throw Exception_1 { }; + } + _container[_top] = val; + } + }; + + class Node_queue + { + private: + + enum { + FIRST_CONTAINER_IDX = 1, + MAX_CONTAINER_IDX = TREE_MAX_DEGREE, + MAX_USED_VALUE = TREE_MAX_DEGREE - 1, + FIRST_USED_VALUE = 0, + }; + + uint64_t _head { FIRST_CONTAINER_IDX }; + uint64_t _tail { FIRST_CONTAINER_IDX }; + Type_2_info _container[MAX_CONTAINER_IDX + 1] { }; + uint64_t _used { FIRST_USED_VALUE }; + + public: + + void enqueue(Type_2_info const &node) + { + _container[_tail] = node; + if (_tail < MAX_CONTAINER_IDX) + _tail++; + else + _tail = FIRST_CONTAINER_IDX; + + _used++; + } + + void dequeue_head() + { + if (_head < MAX_CONTAINER_IDX) + _head++; + else + _head = FIRST_CONTAINER_IDX; + + _used--; + } + + Type_2_info const &head() const { return _container[_head]; } + + bool empty() const { return _used == FIRST_USED_VALUE; }; + + bool full() const { return _used == MAX_USED_VALUE; }; + }; + + State _state { INVALID }; + Request _request { }; + uint64_t _needed_blocks { 0 }; + uint64_t _found_blocks { 0 }; + uint64_t _exchanged_blocks { 0 }; + Local_meta_tree_request _meta_tree_request { }; + Local_cache_request _cache_request { }; + Block _cache_block_data { }; + Type_1_info_stack _level_n_stacks[TREE_MAX_NR_OF_LEVELS] { }; + Type_2_info_stack _level_0_stack { }; + Type_1_node_block _level_n_nodes[TREE_MAX_NR_OF_LEVELS] { }; + Type_1_node_block _level_n_node { }; + Type_2_node_block _level_0_node { }; + Node_queue _type_2_leafs { }; + uint64_t _vbd_degree_log_2 { 0 }; + bool _wb_data_prim_success { false }; + + Type_1_node _root_node() const + { + Type_1_node node { }; + node.pba = *(Physical_block_address *)_request._ft_root_pba_ptr; + node.gen = *(Generation *)_request._ft_root_gen_ptr; + memcpy(&node.hash, (void *)_request._ft_root_hash_ptr, HASH_SIZE); + return node; + } +}; + +class Tresor::Free_tree : public Module +{ + private: + + using Request = Free_tree_request; + using Channel = Free_tree_channel; + using Local_cache_request = Channel::Local_cache_request; + using Local_meta_tree_request = Channel::Local_meta_tree_request; + using Type_1_info = Channel::Type_1_info; + using Type_2_info = Channel::Type_2_info; + using Type_1_info_stack = Channel::Type_1_info_stack; + using Type_2_info_stack = Channel::Type_2_info_stack; + using Node_queue = Channel::Node_queue; + + enum { FIRST_LVL_N_STACKS_IDX = 1 }; + enum { MAX_LVL_N_STACKS_IDX = TREE_MAX_LEVEL }; + enum { FIRST_LVL_N_NODES_IDX = 1 }; + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + void _reset_block_state(Channel &chan); + + static Local_meta_tree_request + _new_meta_tree_request(Physical_block_address pba); + + void _update_upper_n_stack(Type_1_info const &t, + Generation gen, + Block const &block_data, + Type_1_node_block &entries); + + void + _exchange_type_2_leaves(Generation free_gen, + Tree_level_index max_level, + Type_1_node_walk const &old_blocks, + Tree_walk_pbas &new_blocks, + Virtual_block_address vba, + Tree_degree_log_2 vbd_degree_log_2, + Request::Type req_type, + Type_2_info_stack &stack, + Type_2_node_block &entries, + Number_of_blocks &exchanged, + bool &handled, + Virtual_block_address vbd_highest_vba, + bool rekeying, + Key_id previous_key_id, + Key_id current_key_id, + Virtual_block_address rekeying_vba); + + void _populate_lower_n_stack(Type_1_info_stack &stack, + Type_1_node_block &entries, + Block const &block_data, + Generation current_gen); + + bool + _check_type_2_leaf_usable(Snapshots const &snapshots, + Generation last_secured_gen, + Type_2_node const &node, + bool rekeying, + Key_id previous_key_id, + Virtual_block_address rekeying_vba); + + void _populate_level_0_stack(Type_2_info_stack &stack, + Type_2_node_block &entries, + Block const &block_data, + Snapshots const &active_snaps, + Generation secured_gen, + bool rekeying, + Key_id previous_key_id, + Virtual_block_address rekeying_vba); + + void _execute_update(Channel &chan, + Snapshots const &active_snaps, + Generation last_secured_gen, + bool &progress); + + bool _node_volatile(Type_1_node const &node, + uint64_t gen); + + void _execute_scan(Channel &chan, + Snapshots const &active_snaps, + Generation last_secured_gen, + bool &progress); + + void _execute(Channel &chan, + Snapshots const &active_snaps, + Generation last_secured_gen, + bool &progress); + + void _check_type_2_stack(Type_2_info_stack &stack, + Type_1_info_stack &stack_next, + Node_queue &leaves, + Number_of_blocks &found); + + Local_cache_request _new_cache_request(Physical_block_address pba, + Local_cache_request::Op op, + Tree_level_index lvl); + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + void execute(bool &) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; +}; + +#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 new file mode 100644 index 0000000000..95f8760cfc --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/ft_check.h @@ -0,0 +1,211 @@ +/* + * \brief Module for checking all hashes of a free tree or meta tree + * \author Martin Stein + * \date 2023-05-03 + */ + +/* + * 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__FT_CHECK_H_ +#define _TRESOR__FT_CHECK_H_ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include + +namespace Tresor { + + class Ft_check; + class Ft_check_request; + class Ft_check_channel; +} + + +class Tresor::Ft_check_request : public Module_request +{ + public: + + enum Type { INVALID = 0, CHECK = 1, }; + + private: + + friend class Ft_check; + friend class Ft_check_channel; + + Type _type { INVALID }; + Tree_level_index _max_lvl { 0 }; + Tree_node_index _max_child_idx { 0 }; + Number_of_leaves _nr_of_leaves { 0 }; + Type_1_node _root { }; + bool _success { false }; + + public: + + Ft_check_request() { } + + Ft_check_request(uint64_t src_module_id, + uint64_t src_request_id, + Type type, + Tree_level_index max_lvl, + Tree_node_index max_child_idx, + Number_of_leaves nr_of_leaves, + Type_1_node root); + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override + { + Genode::print(out, type_to_string(_type), " root ", _root); + } +}; + + +class Tresor::Ft_check_channel +{ + private: + + friend class Ft_check; + + using Request = Ft_check_request; + + enum Child_state { + READ_BLOCK = 0, CHECK_HASH = 1, DONE = 2 }; + + struct Type_1_level + { + Child_state children_state[NR_OF_T1_NODES_PER_BLK] { }; + Type_1_node_block children { }; + + Type_1_level() + { + for (Child_state &state : children_state) + state = DONE; + } + }; + + struct Type_2_level + { + Child_state children_state[NR_OF_T1_NODES_PER_BLK] { }; + Type_2_node_block children { }; + + Type_2_level() + { + for (Child_state &state : children_state) + state = DONE; + } + }; + + enum Primitive_tag { INVALID, BLOCK_IO }; + + struct Generated_primitive + { + bool success { false }; + Primitive_tag tag { INVALID }; + Physical_block_address blk_nr { 0 }; + bool dropped { false }; + + bool valid() const { return tag != INVALID; } + }; + + Generated_primitive _gen_prim { }; + Tree_level_index _lvl_to_read { 0 }; + Child_state _root_state { DONE }; + Type_2_level _t2_lvl { }; + Type_1_level _t1_lvls[TREE_MAX_LEVEL] { }; + Number_of_leaves _nr_of_leaves { 0 }; + Request _request { }; +}; + + +class Tresor::Ft_check : public Module +{ + private: + + using Request = Ft_check_request; + using Channel = Ft_check_channel; + using Child_state = Ft_check_channel::Child_state; + using Type_1_level = Ft_check_channel::Type_1_level; + using Type_2_level = Ft_check_channel::Type_2_level; + + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + void _execute_inner_t2_child(Channel &chan, + Tree_level_index lvl, + Tree_node_index child_idx, + bool &progress); + + void _execute_check(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + void _execute_inner_t1_child(Channel &chan, + Type_1_node const &child, + Type_1_level &child_lvl, + Child_state &child_state, + Tree_level_index lvl, + Tree_node_index child_idx, + bool &progress); + + + void _execute_leaf_child(Channel &chan, + Tree_node_index child_idx, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + + public: + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + void execute(bool &) override; + +}; + +#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 new file mode 100644 index 0000000000..8405a4307d --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/ft_initializer.h @@ -0,0 +1,260 @@ +/* + * \brief Module for initializing the FT + * \author Josef Soentgen + * \date 2023-03-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__FT_INITIALIZER_H_ +#define _TRESOR__FT_INITIALIZER_H_ + +/* base includes */ +#include + +/* tresor includes */ +#include + +namespace Tresor { + + class Ft_initializer; + class Ft_initializer_request; + class Ft_initializer_channel; +} + + +class Tresor::Ft_initializer_request : public Module_request +{ + public: + + enum Type { INVALID = 0, INIT = 1, }; + + private: + + friend class Ft_initializer; + friend class Ft_initializer_channel; + + Type _type { INVALID }; + uint8_t _root_node[sizeof(Type_1_node)] { 0 }; + uint64_t _max_level_idx { 0 }; + uint64_t _max_child_idx { 0 }; + uint64_t _nr_of_leaves { 0 }; + bool _success { false }; + + + public: + + Ft_initializer_request() { } + + Ft_initializer_request(Module_id src_module_id, + Module_request_id src_request_id); + + static void create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t max_level_idx, + uint64_t max_child_idx, + uint64_t nr_of_leaves); + + void *root_node() { return _root_node; } + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } +}; + + +class Tresor::Ft_initializer_channel +{ + private: + + friend class Ft_initializer; + + enum State { + INACTIVE, SUBMITTED, PENDING, IN_PROGRESS, COMPLETE, + BLOCK_ALLOC_PENDING, + BLOCK_ALLOC_IN_PROGRESS, + BLOCK_ALLOC_COMPLETE, + BLOCK_IO_PENDING, + BLOCK_IO_IN_PROGRESS, + BLOCK_IO_COMPLETE, + }; + + enum Child_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLOCK, }; + + struct Type_1_level + { + Type_1_node_block children { }; + Child_state children_state[NR_OF_T1_NODES_PER_BLK] { DONE }; + }; + + struct Type_2_level + { + Type_2_node_block children { }; + Child_state children_state[NR_OF_T2_NODES_PER_BLK] { DONE }; + }; + + struct Root_node + { + Type_1_node node { }; + Child_state state { DONE }; + }; + + State _state { INACTIVE }; + Ft_initializer_request _request { }; + Root_node _root_node { }; + Type_1_level _t1_levels[TREE_MAX_LEVEL] { }; + Type_2_level _t2_level { }; + uint64_t _level_to_write { 0 }; + uint64_t _blk_nr { 0 }; + uint64_t _child_pba { 0 }; + bool _generated_req_success { false }; + + static void reset_node(Tresor::Type_1_node &node) + { + memset(&node, 0, sizeof(Type_1_node)); + } + + static void reset_node(Tresor::Type_2_node &node) + { + memset(&node, 0, sizeof(Type_2_node)); + } + + static void reset_level(Type_1_level &level, + Child_state state) + { + for (unsigned int i = 0; i < NR_OF_T1_NODES_PER_BLK; i++) { + reset_node(level.children.nodes[i]); + level.children_state[i] = state; + } + } + + static void reset_level(Type_2_level &level, + Child_state state) + { + for (unsigned int i = 0; i < NR_OF_T2_NODES_PER_BLK; i++) { + reset_node(level.children.nodes[i]); + level.children_state[i] = state; + } + } + + static void dump(Type_1_node_block const &node_block) + { + for (auto v : node_block.nodes) { + if (v.pba != 0) + log(v); + } + } + + static void dump(Type_2_node_block const &node_block) + { + for (auto v : node_block.nodes) { + if (v.pba != 0) + log(v); + } + } +}; + + +class Tresor::Ft_initializer : public Module +{ + private: + + using Request = Ft_initializer_request; + using Channel = Ft_initializer_channel; + + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + void _execute_leaf_child(Channel &channel, + bool &progress, + uint64_t &nr_of_leaves, + Tresor::Type_2_node &child, + Ft_initializer_channel::Child_state &child_state, + uint64_t child_index); + + void _execute_inner_t2_child(Channel &channel, + bool &progress, + uint64_t nr_of_leaves, + uint64_t &level_to_write, + Tresor::Type_1_node &child, + Ft_initializer_channel::Type_2_level &child_level, + Ft_initializer_channel::Child_state &child_state, + uint64_t level_index, + uint64_t child_index); + + void _execute_inner_t1_child(Channel &channel, + bool &progress, + uint64_t nr_of_leaves, + uint64_t &level_to_write, + Tresor::Type_1_node &child, + Ft_initializer_channel::Type_1_level &child_level, + Ft_initializer_channel::Child_state &child_state, + uint64_t level_index, + uint64_t child_index); + + void _execute(Channel &channel, + bool &progress); + + void _execute_init(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + + public: + + Ft_initializer(); + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + void execute(bool &) override; + +}; + +#endif /* _TRESOR__FT_INITIALIZER_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/ft_resizing.h b/repos/gems/src/lib/tresor/include/tresor/ft_resizing.h new file mode 100644 index 0000000000..276f714742 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/ft_resizing.h @@ -0,0 +1,256 @@ +/* + * \brief Module for file tree resizing + * \author Martin Stein + * \date 2023-03-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__FT_RESIZING_H_ +#define _TRESOR__FT_RESIZING_H_ + +/* tresor includes */ +#include +#include +#include + +namespace Tresor { + + class Ft_resizing; + class Ft_resizing_request; + class Ft_resizing_channel; +} + + +class Tresor::Ft_resizing_request : public Module_request +{ + public: + + enum Type { INVALID = 0, FT_EXTENSION_STEP = 1 }; + + private: + + friend class Ft_resizing; + friend class Ft_resizing_channel; + + Type _type { INVALID }; + Generation _curr_gen { INVALID_GENERATION }; + Type_1_node _ft_root { }; + Tree_level_index _ft_max_lvl { 0 }; + Number_of_leaves _ft_nr_of_leaves { 0 }; + Tree_degree _ft_degree { TREE_MIN_DEGREE }; + addr_t _mt_root_pba_ptr { 0 }; + addr_t _mt_root_gen_ptr { 0 }; + addr_t _mt_root_hash_ptr { 0 }; + Tree_level_index _mt_max_level { 0 }; + Tree_degree _mt_degree { 0 }; + Number_of_leaves _mt_leaves { 0 }; + Physical_block_address _pba { 0 }; + Number_of_blocks _nr_of_pbas { 0 }; + Number_of_leaves _nr_of_leaves { 0 }; + bool _success { false }; + + public: + + Ft_resizing_request() { } + + Ft_resizing_request(uint64_t src_module_id, + uint64_t src_request_id, + Type type, + Generation curr_gen, + Type_1_node ft_root, + Tree_level_index ft_max_lvl, + Number_of_leaves ft_nr_of_leaves, + Tree_degree ft_degree, + addr_t mt_root_pba_ptr, + addr_t mt_root_gen_ptr, + addr_t mt_root_hash_ptr, + Tree_level_index mt_max_level, + Tree_degree mt_degree, + Number_of_leaves mt_leaves, + Physical_block_address pba, + Number_of_blocks nr_of_pbas); + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + Type_1_node ft_root() const { return _ft_root; } + Tree_level_index ft_max_lvl() const { return _ft_max_lvl; } + Number_of_leaves ft_nr_of_leaves() const { return _ft_nr_of_leaves; } + Number_of_leaves nr_of_leaves() const { return _nr_of_leaves; } + Physical_block_address pba() const { return _pba; } + Number_of_blocks nr_of_pbas() const { return _nr_of_pbas; } + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override + { + Genode::print(out, type_to_string(_type), " root ", _ft_root, " leaves ", _ft_nr_of_leaves, " max_lvl ", _ft_max_lvl); + } +}; + +class Tresor::Ft_resizing_channel +{ + private: + + friend class Ft_resizing; + + enum State { + SUBMITTED, + + READ_ROOT_NODE_PENDING, + READ_ROOT_NODE_IN_PROGRESS, + READ_ROOT_NODE_COMPLETED, + + READ_INNER_NODE_PENDING, + READ_INNER_NODE_IN_PROGRESS, + READ_INNER_NODE_COMPLETED, + + ALLOC_PBA_PENDING, + ALLOC_PBA_IN_PROGRESS, + ALLOC_PBA_COMPLETED, + + EXTEND_MT_BY_ONE_LEAF_PENDING, + EXTEND_MT_BY_ONE_LEAF_IN_PROGRESS, + EXTEND_MT_BY_ONE_LEAF_COMPLETED, + + WRITE_INNER_NODE_PENDING, + WRITE_INNER_NODE_IN_PROGRESS, + WRITE_INNER_NODE_COMPLETED, + + WRITE_ROOT_NODE_PENDING, + WRITE_ROOT_NODE_IN_PROGRESS, + WRITE_ROOT_NODE_COMPLETED, + + COMPLETED + }; + + enum Tag_type + { + TAG_INVALID, + TAG_FT_RSZG_CACHE, + TAG_FT_RSZG_MT_ALLOC, + }; + + struct Generated_prim + { + enum Type { READ, WRITE }; + + Type op { READ }; + bool succ { false }; + Tag_type tg { TAG_INVALID }; + uint64_t blk_nr { 0 }; + uint64_t idx { 0 }; + }; + + struct Type_1_node_blocks + { + Type_1_node_block items[TREE_MAX_LEVEL] { }; + }; + + struct Generations + { + Generation items[TREE_MAX_LEVEL + 1] { }; + }; + + Ft_resizing_request _request { }; + State _state { SUBMITTED }; + Generated_prim _generated_prim { }; + Type_1_node_blocks _t1_blks { }; + Type_2_node_block _t2_blk { }; + Tree_level_index _lvl_idx { 0 }; + Tree_level_index _alloc_lvl_idx { 0 }; + Virtual_block_address _vba { }; + Tree_walk_pbas _old_pbas { }; + Generations _old_generations { }; + Tree_walk_pbas _new_pbas { }; +}; + +class Tresor::Ft_resizing : public Module +{ + private: + + using Request = Ft_resizing_request; + using Channel = Ft_resizing_channel; + + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + void _set_args_for_write_back_of_inner_lvl(Tree_level_index const, + Tree_level_index const, + Physical_block_address const, + unsigned const prim_idx, + Channel::State &, + bool &progress, + Channel::Generated_prim &); + + void _add_new_root_lvl_to_ft_using_pba_contingent(Type_1_node &, + Tree_level_index &, + Number_of_leaves const, + Generation const, + Channel::Type_1_node_blocks &, + Tree_walk_pbas &, + Physical_block_address &, + Number_of_blocks &); + + void _add_new_branch_to_ft_using_pba_contingent(Tree_level_index const, + Tree_node_index const, + Tree_degree const, + Generation const, + Physical_block_address &, + Number_of_blocks &, + Channel::Type_1_node_blocks &, + Type_2_node_block &, + Tree_walk_pbas &, + Tree_level_index &, + Number_of_leaves &); + + void _execute_ft_extension_step(Channel &, unsigned const idx, bool &); + + void _execute_ft_ext_step_read_inner_node_completed(Channel &, + unsigned const job_idx, + bool &progress); + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + + public: + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + void execute(bool &) override; +}; + +#endif /* _TRESOR__FT_RESIZING_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/init/configuration.h b/repos/gems/src/lib/tresor/include/tresor/init/configuration.h new file mode 100644 index 0000000000..5ab94ff416 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/init/configuration.h @@ -0,0 +1,105 @@ +/* + * \brief Integration of the Tresor block encryption + * \author Martin Stein + * \author Josef Soentgen + * \date 2020-11-10 + */ + +/* + * Copyright (C) 2020 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU Affero General Public License version 3. + */ + +#ifndef _TRESOR__INIT__CONFIGURATION_H_ +#define _TRESOR__INIT__CONFIGURATION_H_ + +/* base includes */ +#include + +namespace Tresor_init { + + using namespace Genode; + + class Configuration; +} + +class Tresor_init::Configuration +{ + private: + + uint64_t _vbd_nr_of_lvls { 0 }; + uint64_t _vbd_nr_of_children { 0 }; + uint64_t _vbd_nr_of_leafs { 0 }; + uint64_t _ft_nr_of_lvls { 0 }; + uint64_t _ft_nr_of_children { 0 }; + uint64_t _ft_nr_of_leafs { 0 }; + + public: + + struct Invalid : Exception { }; + + Configuration (Xml_node const &node) + { + node.with_optional_sub_node("virtual-block-device", + [&] (Xml_node const &vbd) + { + _vbd_nr_of_lvls = + vbd.attribute_value("nr_of_levels", (uint64_t)0); + _vbd_nr_of_children = + vbd.attribute_value("nr_of_children", (uint64_t)0); + _vbd_nr_of_leafs = + vbd.attribute_value("nr_of_leafs", (uint64_t)0); + }); + node.with_optional_sub_node("free-tree", + [&] (Xml_node const &ft) + { + _ft_nr_of_lvls = + ft.attribute_value("nr_of_levels", (uint64_t)0); + _ft_nr_of_children = + ft.attribute_value("nr_of_children", (uint64_t)0); + _ft_nr_of_leafs = + ft.attribute_value("nr_of_leafs", (uint64_t)0); + }); + if (_vbd_nr_of_lvls == 0 || + _vbd_nr_of_children == 0 || + _vbd_nr_of_leafs == 0 || + _ft_nr_of_lvls == 0 || + _ft_nr_of_children == 0 || + _ft_nr_of_leafs == 0) + { + throw Invalid(); + } + } + + Configuration (Configuration const &other) + { + _vbd_nr_of_lvls = other._vbd_nr_of_lvls ; + _vbd_nr_of_children = other._vbd_nr_of_children; + _vbd_nr_of_leafs = other._vbd_nr_of_leafs ; + _ft_nr_of_lvls = other._ft_nr_of_lvls ; + _ft_nr_of_children = other._ft_nr_of_children ; + _ft_nr_of_leafs = other._ft_nr_of_leafs ; + } + + uint64_t vbd_nr_of_lvls () const { return _vbd_nr_of_lvls ; } + uint64_t vbd_nr_of_children () const { return _vbd_nr_of_children; } + uint64_t vbd_nr_of_leafs () const { return _vbd_nr_of_leafs ; } + uint64_t ft_nr_of_lvls () const { return _ft_nr_of_lvls ; } + uint64_t ft_nr_of_children () const { return _ft_nr_of_children ; } + uint64_t ft_nr_of_leafs () const { return _ft_nr_of_leafs ; } + + void print(Output &out) const + { + Genode::print(out, + "vbd=(lvls=", _vbd_nr_of_lvls, + " children=", _vbd_nr_of_children, + " leafs=", _vbd_nr_of_leafs, ")", + " ft=(lvls=", _ft_nr_of_lvls, + " children=", _ft_nr_of_children, + " leafs=", _ft_nr_of_leafs, ")"); + } +}; + +#endif /* _TRESOR__INIT__CONFIGURATION_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/math.h b/repos/gems/src/lib/tresor/include/tresor/math.h new file mode 100644 index 0000000000..0c8c758f69 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/math.h @@ -0,0 +1,37 @@ +/* + * \brief Tresor-local math functions + * \author Martin Stein + * \date 2020-11-10 + */ + +/* + * 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__MATH_H_ +#define _TRESOR__MATH_H_ + +namespace Tresor { + + template + constexpr T to_the_power_of(T base, T exponent) + { + if (exponent < 0) { + class Negative_exponent { }; + throw Negative_exponent { }; + } + if (exponent == 0) + return 1; + + T result { base }; + for (T round { 1 }; round < exponent; round++) + result *= base; + + return result; + } +} + +#endif /* _TRESOR__MATH_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 new file mode 100644 index 0000000000..d667263681 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/meta_tree.h @@ -0,0 +1,252 @@ +/* + * \brief Module for doing free tree COW allocations on the meta tree + * \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__META_TREE_H_ +#define _TRESOR__META_TREE_H_ + +/* tresor includes */ +#include +#include +#include + +namespace Tresor { + + class Meta_tree; + class Meta_tree_request; + class Meta_tree_channel; +} + +class Tresor::Meta_tree_request : public Module_request +{ + public: + + enum Type { INVALID = 0, UPDATE = 1 }; + + private: + + friend class Meta_tree; + friend class Meta_tree_channel; + + Type _type { INVALID }; + addr_t _mt_root_pba_ptr { 0 }; + addr_t _mt_root_gen_ptr { 0 }; + addr_t _mt_root_hash_ptr { 0 }; + uint64_t _mt_max_lvl { 0 }; + uint64_t _mt_edges { 0 }; + uint64_t _mt_leaves { 0 }; + uint64_t _current_gen { 0 }; + uint64_t _old_pba { INVALID_PBA }; + uint64_t _new_pba { INVALID_PBA }; + bool _success { false }; + + public: + + Meta_tree_request() { } + + Meta_tree_request(Module_id src_module_id, + Module_request_id src_request_id); + + static void create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + void *mt_root_pba_ptr, + void *mt_root_gen_ptr, + void *mt_root_hash_ptr, + uint64_t mt_max_lvl, + uint64_t mt_edges, + uint64_t mt_leaves, + uint64_t curr_gen, + uint64_t old_pba); + + uint64_t new_pba() { return _new_pba; } + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } +}; + + +class Tresor::Meta_tree_channel +{ + private: + + friend class Meta_tree; + + enum State { + INVALID, + UPDATE, + COMPLETE, + TREE_HASH_MISMATCH + }; + + struct Type_1_info + { + enum State { + INVALID, READ, READ_COMPLETE, WRITE, WRITE_COMPLETE, COMPLETE }; + + State state { INVALID }; + Type_1_node node { }; + Type_1_node_block entries { }; + uint8_t index { INVALID_NODE_INDEX }; + bool dirty { false }; + bool volatil { false }; + }; + + struct Type_2_info + { + enum State { + INVALID, READ, READ_COMPLETE, WRITE, WRITE_COMPLETE, COMPLETE }; + + State state { INVALID }; + Type_1_node node { }; + Type_2_node_block entries { }; + uint8_t index { INVALID_NODE_INDEX }; + bool volatil { false }; + }; + + struct Local_cache_request + { + enum State { INVALID, PENDING, IN_PROGRESS }; + enum Op { READ, WRITE, SYNC }; + + State state { INVALID }; + Op op { READ }; + bool success { false }; + uint64_t pba { 0 }; + uint64_t level { 0 }; + uint8_t block_data[BLOCK_SIZE] { 0 }; + + Local_cache_request(State state, + Op op, + bool success, + uint64_t pba, + uint64_t level, + uint8_t *blk_ptr) + : + state { state }, + op { op }, + success { success }, + pba { pba }, + level { level } + { + if (blk_ptr != nullptr) { + memcpy(&block_data, blk_ptr, BLOCK_SIZE); + } + } + + Local_cache_request() { } + }; + + State _state { INVALID }; + Meta_tree_request _request { }; + Local_cache_request _cache_request { }; + Type_2_info _level_1_node { }; + Type_1_info _level_n_nodes[TREE_MAX_NR_OF_LEVELS] { }; /* index starts at 2 */ + bool _finished { false }; + bool _root_dirty { false }; +}; + +class Tresor::Meta_tree : public Module +{ + private: + + using Request = Meta_tree_request; + using Channel = Meta_tree_channel; + using Local_cache_request = Channel::Local_cache_request; + using Type_1_info = Channel::Type_1_info; + using Type_2_info = Channel::Type_2_info; + + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + void _handle_level_n_nodes(Channel &channel, + bool &handled); + + void _handle_level_1_node(Channel &channel, + bool &handled); + + void _exchange_request_pba(Channel &channel, + Type_2_node &t2_entry); + + void _exchange_nv_inner_nodes(Channel &channel, + Type_2_node &t2_entry, + bool &exchanged); + + void _exchange_nv_level_1_node(Channel &channel, + Type_2_node &t2_entry, + bool &exchanged); + + bool _node_volatile(Type_1_node const &node, + uint64_t gen); + + void _handle_level_0_nodes(Channel &channel, + bool &handled); + + void _update_parent(Type_1_node &node, + uint8_t const *blk_ptr, + uint64_t gen, + uint64_t pba); + + void _handle_level_0_nodes(bool &handled); + + void _execute_update(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + void execute(bool &) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + public: + + Meta_tree(); +}; + +#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 new file mode 100644 index 0000000000..697e949ca3 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/module.h @@ -0,0 +1,291 @@ +/* + * \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 +#include + +/* tresor includes */ +#include +#include + +namespace Tresor { + + using namespace Genode; + + using Module_id = uint64_t; + using Module_request_id = uint64_t; + + enum { + INVALID_MODULE_ID = ~0UL, + INVALID_MODULE_REQUEST_ID = ~0UL, + }; + + 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, + BLOCK_ALLOCATOR = 10, + VBD_INITIALIZER = 11, + FT_INITIALIZER = 12, + SB_INITIALIZER = 13, + REQUEST_POOL = 14, + SB_CHECK = 15, + VBD_CHECK = 16, + FT_CHECK = 17, + FT_RESIZING = 18, + MAX_MODULE_ID = 18, + }; + + char const *module_name(Module_id module_id); + + class Module_request; + class Module; + class Module_composition; +} + + +class Tresor::Module_request : public Interface +{ + private: + + Module_id _src_module_id { INVALID_MODULE_ID }; + Module_request_id _src_request_id { INVALID_MODULE_REQUEST_ID }; + Module_id _dst_module_id { INVALID_MODULE_ID }; + Module_request_id _dst_request_id { INVALID_MODULE_REQUEST_ID }; + + public: + + Module_request() { } + + Module_request(Module_id src_module_id, + Module_request_id src_request_id, + Module_id dst_module_id); + + void dst_request_id(Module_request_id id) { _dst_request_id = id; } + + String<32> src_request_id_str() const; + + String<32> dst_request_id_str() const; + + virtual void print(Output &) const = 0; + + virtual ~Module_request() { } + + + /*************** + ** Accessors ** + ***************/ + + Module_id src_module_id() const { return _src_module_id; } + Module_request_id src_request_id() const { return _src_request_id; } + Module_id dst_module_id() const { return _dst_module_id; } + Module_request_id dst_request_id() const { return _dst_request_id; } +}; + + +class Tresor::Module : public Interface +{ + private: + + virtual bool _peek_completed_request(uint8_t *, + size_t ) + { + return false; + } + + virtual void _drop_completed_request(Module_request &) + { + class Exception_1 { }; + throw Exception_1 { }; + } + + virtual bool _peek_generated_request(uint8_t *, + size_t ) + { + return false; + } + + virtual void _drop_generated_request(Module_request &) + { + class Exception_1 { }; + throw Exception_1 { }; + } + + public: + + enum Handle_request_result { REQUEST_HANDLED, REQUEST_NOT_HANDLED }; + + typedef Handle_request_result ( + *Handle_request_function)(Module_request &req); + + virtual bool ready_to_submit_request() { return false; }; + + virtual void submit_request(Module_request &) + { + class Exception_1 { }; + throw Exception_1 { }; + } + + virtual void execute(bool &) { } + + template + void for_each_generated_request(FUNC && handle_request) + { + uint8_t buf[4000]; + while (_peek_generated_request(buf, sizeof(buf))) { + + Module_request &req = *(Module_request *)buf; + switch (handle_request(req)) { + case Module::REQUEST_HANDLED: + + _drop_generated_request(req); + break; + + case Module::REQUEST_NOT_HANDLED: + + return; + } + } + } + + virtual void generated_request_complete(Module_request &) + { + class Exception_1 { }; + throw Exception_1 { }; + } + + template + void for_each_completed_request(FUNC && handle_request) + { + uint8_t buf[4000]; + while (_peek_completed_request(buf, sizeof(buf))) { + + Module_request &req = *(Module_request *)buf; + handle_request(req); + _drop_completed_request(req); + } + } + + virtual ~Module() { } +}; + + +class Tresor::Module_composition +{ + private: + + Module *_module_ptrs[MAX_MODULE_ID + 1] { }; + + public: + + void add_module(Module_id module_id, + Module &module) + { + if (module_id > MAX_MODULE_ID) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_module_ptrs[module_id] != nullptr) { + class Exception_2 { }; + throw Exception_2 { }; + } + _module_ptrs[module_id] = &module; + } + + void remove_module(Module_id module_id) + { + if (module_id > MAX_MODULE_ID) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_module_ptrs[module_id] == nullptr) { + class Exception_2 { }; + throw Exception_2 { }; + } + _module_ptrs[module_id] = nullptr; + } + + void execute_modules(bool &progress) + { + for (Module_id id { 0 }; id <= MAX_MODULE_ID; id++) { + + if (_module_ptrs[id] == nullptr) + continue; + + Module *module_ptr { _module_ptrs[id] }; + module_ptr->execute(progress); + module_ptr->for_each_generated_request([&] (Module_request &req) { + if (req.dst_module_id() > MAX_MODULE_ID) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_module_ptrs[req.dst_module_id()] == nullptr) { + class Exception_2 { }; + throw Exception_2 { }; + } + Module &dst_module { *_module_ptrs[req.dst_module_id()] }; + if (!dst_module.ready_to_submit_request()) { + + if (VERBOSE_MODULE_COMMUNICATION) + log( + module_name(id), " ", req.src_request_id_str(), + " --", req, "-| ", + module_name(req.dst_module_id())); + + return Module::REQUEST_NOT_HANDLED; + } + dst_module.submit_request(req); + + if (VERBOSE_MODULE_COMMUNICATION) + log( + module_name(id), " ", req.src_request_id_str(), + " --", req, "--> ", + module_name(req.dst_module_id()), " ", + req.dst_request_id_str()); + + progress = true; + return Module::REQUEST_HANDLED; + }); + module_ptr->for_each_completed_request([&] (Module_request &req) { + if (req.src_module_id() > MAX_MODULE_ID) { + class Exception_3 { }; + throw Exception_3 { }; + } + if (VERBOSE_MODULE_COMMUNICATION) + log( + module_name(req.src_module_id()), " ", + req.src_request_id_str(), " <--", req, + "-- ", module_name(id), " ", + req.dst_request_id_str()); + + Module &src_module { *_module_ptrs[req.src_module_id()] }; + src_module.generated_request_complete(req); + progress = true; + }); + } + } +}; + +#endif /* _TRESOR__MODULE_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 new file mode 100644 index 0000000000..72b830d8f4 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/request_pool.h @@ -0,0 +1,478 @@ +/* + * \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 +#include + +namespace Tresor { + + class Request_pool; + class Request_pool_request; + class Request_pool_channel; + + + class Request : public Module_request + { + public: + + enum Operation : uint32_t { + INVALID = 0, + READ = 1, + WRITE = 2, + SYNC = 3, + CREATE_SNAPSHOT = 4, + DISCARD_SNAPSHOT = 5, + REKEY = 6, + EXTEND_VBD = 7, + EXTEND_FT = 8, + RESUME_REKEYING = 10, + DEINITIALIZE = 11, + INITIALIZE = 12, + }; + + private: + + Operation _operation; + bool _success; + uint64_t _block_number; + uint64_t _offset; + Number_of_blocks _count; + uint32_t _key_id; + uint32_t _tag; + uint32_t _snap_id; + + public: + + Request(Operation operation, + bool success, + uint64_t block_number, + uint64_t offset, + Number_of_blocks count, + uint32_t key_id, + uint32_t tag, + uint32_t snap_id, + Module_id src_module_id, + Module_request_id src_request_id) + : + Module_request { src_module_id, src_request_id, REQUEST_POOL }, + _operation { operation }, + _success { success }, + _block_number { block_number }, + _offset { offset }, + _count { count }, + _key_id { key_id }, + _tag { tag }, + _snap_id { snap_id } + { } + + Request() + : + Module_request { }, + _operation { Operation::INVALID }, + _success { false }, + _block_number { 0 }, + _offset { 0 }, + _count { 0 }, + _key_id { 0 }, + _tag { 0 }, + _snap_id { 0 } + { } + + bool valid() const + { + return _operation != Operation::INVALID; + } + + + /*************** + ** Accessors ** + ***************/ + + bool read() const { return _operation == Operation::READ; } + bool write() const { return _operation == Operation::WRITE; } + bool sync() const { return _operation == Operation::SYNC; } + bool create_snapshot() const { return _operation == Operation::CREATE_SNAPSHOT; } + bool discard_snapshot() const { return _operation == Operation::DISCARD_SNAPSHOT; } + bool rekey() const { return _operation == Operation::REKEY; } + bool extend_vbd() const { return _operation == Operation::EXTEND_VBD; } + bool extend_ft() const { return _operation == Operation::EXTEND_FT; } + bool resume_rekeying() const { return _operation == Operation::RESUME_REKEYING; } + bool deinitialize() const { return _operation == Operation::DEINITIALIZE; } + bool initialize() const { return _operation == Operation::INITIALIZE; } + + Operation operation() const { return _operation; } + bool success() const { return _success; } + uint64_t block_number() const { return _block_number; } + uint64_t offset() const { return _offset; } + Number_of_blocks count() const { return _count; } + uint32_t key_id() const { return _key_id; } + uint32_t tag() const { return _tag; } + uint32_t snap_id() const { return _snap_id; } + + void offset(uint64_t arg) { _offset = arg; } + void success(bool arg) { _success = arg; } + void tag(uint32_t arg) { _tag = arg; } + void snap_id(uint32_t arg) { _snap_id = arg; } + + static char const *op_to_string(Operation op); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override + { + Genode::print(out, op_to_string(_operation)); + switch (_operation) { + case READ: + case WRITE: + case SYNC: + if (_count > 1) + Genode::print(out, " vbas ", _block_number, "..", _block_number + _count - 1); + else + Genode::print(out, " vba ", _block_number); + break; + default: + break; + } + } + + } __attribute__((packed)); + +} + +class Tresor::Request_pool_channel +{ + private: + + friend class Request_pool; + + enum State { + INVALID, + SUBMITTED, + SUBMITTED_RESUME_REKEYING, + REKEY_INIT_PENDING, + REKEY_INIT_IN_PROGRESS, + REKEY_INIT_COMPLETE, + PREPONE_REQUESTS_PENDING, + PREPONE_REQUESTS_COMPLETE, + VBD_EXTENSION_STEP_PENDING, + FT_EXTENSION_STEP_PENDING, + TREE_EXTENSION_STEP_IN_PROGRESS, + TREE_EXTENSION_STEP_COMPLETE, + CREATE_SNAP_AT_SB_CTRL_PENDING, + CREATE_SNAP_AT_SB_CTRL_IN_PROGRESS, + CREATE_SNAP_AT_SB_CTRL_COMPLETE, + SYNC_AT_SB_CTRL_PENDING, + SYNC_AT_SB_CTRL_IN_PROGRESS, + SYNC_AT_SB_CTRL_COMPLETE, + READ_VBA_AT_SB_CTRL_PENDING, + READ_VBA_AT_SB_CTRL_IN_PROGRESS, + READ_VBA_AT_SB_CTRL_COMPLETE, + WRITE_VBA_AT_SB_CTRL_PENDING, + WRITE_VBA_AT_SB_CTRL_IN_PROGRESS, + WRITE_VBA_AT_SB_CTRL_COMPLETE, + DISCARD_SNAP_AT_SB_CTRL_PENDING, + DISCARD_SNAP_AT_SB_CTRL_IN_PROGRESS, + DISCARD_SNAP_AT_SB_CTRL_COMPLETE, + REKEY_VBA_PENDING, + REKEY_VBA_IN_PROGRESS, + REKEY_VBA_COMPLETE, + INITIALIZE_SB_CTRL_PENDING, + INITIALIZE_SB_CTRL_IN_PROGRESS, + INITIALIZE_SB_CTRL_COMPLETE, + DEINITIALIZE_SB_CTRL_PENDING, + DEINITIALIZE_SB_CTRL_IN_PROGRESS, + DEINITIALIZE_SB_CTRL_COMPLETE, + COMPLETE + }; + + enum Tag_type { + TAG_POOL_SB_CTRL_TREE_EXT_STEP, + TAG_POOL_SB_CTRL_READ_VBA, + TAG_POOL_SB_CTRL_WRITE_VBA, + TAG_POOL_SB_CTRL_SYNC, + TAG_POOL_SB_CTRL_INITIALIZE, + TAG_POOL_SB_CTRL_DEINITIALIZE, + TAG_POOL_SB_CTRL_INIT_REKEY, + TAG_POOL_SB_CTRL_REKEY_VBA, + }; + + using Pool_index = uint32_t; + + struct Generated_prim { + enum Type { READ, WRITE }; + + Type op; + bool succ; + Tag_type tg; + Pool_index pl_idx; + uint64_t blk_nr; + uint64_t idx; + }; + + Tresor::Request _request { }; + State _state { INVALID }; + Generated_prim _prim { }; + uint64_t _nr_of_blks { 0 }; + Generation _gen { }; + Superblock::State _sb_state { Superblock::INVALID }; + uint32_t _nr_of_requests_preponed { 0 }; + bool _request_finished { false }; + + void invalidate() + { + _request = { }; + _state = { INVALID }; + _prim = { }; + _nr_of_blks = 0; + _gen = { }; + _sb_state = { Superblock::INVALID }; + } +}; + +class Tresor::Request_pool : public Module +{ + private: + + enum { MAX_NR_OF_REQUESTS_PREPONED_AT_A_TIME = 8 }; + + using Channel = Request_pool_channel; + using Request = Tresor::Request; + using Slots_index = uint32_t; + using Pool_index = Channel::Pool_index; + using Generated_prim = Channel::Generated_prim; + + enum { NR_OF_CHANNELS = 16 }; + + struct Index_queue + { + using Index = Slots_index; + + Slots_index _head { 0 }; + Slots_index _tail { 0 }; + unsigned _nr_of_used_slots { 0 }; + Slots_index _slots[NR_OF_CHANNELS] { 0 }; + + bool empty() const { return _nr_of_used_slots == 0; } + + bool full() const { + return _nr_of_used_slots >= NR_OF_CHANNELS; } + + Slots_index head() const + { + if (empty()) { + class Index_queue_empty_head { }; + throw Index_queue_empty_head { }; + } + return _slots[_head]; + } + + void enqueue(Slots_index const idx) + { + if (full()) { + class Index_queue_enqueue_full { }; + throw Index_queue_enqueue_full { }; + } + + _slots[_tail] = idx; + + _tail = (_tail + 1) % NR_OF_CHANNELS; + + _nr_of_used_slots += 1; + } + + void move_one_item_towards_tail(Index idx) + { + Slots_index slot_idx { _head }; + Slots_index next_slot_idx; + Index next_idx; + + if (empty()) { + class Exception_1 { }; + throw Exception_1 { }; + } + while (true) { + + if (slot_idx < NR_OF_CHANNELS - 1) + next_slot_idx = slot_idx + 1; + else + next_slot_idx = 0; + + if (next_slot_idx == _tail) { + class Exception_2 { }; + throw Exception_2 { }; + } + if (_slots[slot_idx] == idx) { + next_idx = _slots[next_slot_idx]; + _slots[next_slot_idx] = _slots[slot_idx]; + _slots[slot_idx] = next_idx; + return; + } else + slot_idx = next_slot_idx; + } + } + + bool item_is_tail(Slots_index idx) const + { + Slots_index slot_idx; + + if (empty()) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_tail > 0) + slot_idx = _tail - 1; + else + slot_idx = NR_OF_CHANNELS - 1; + + return _slots[slot_idx] == idx; + } + + Index next_item(Index idx) const + { + Slots_index slot_idx { _head }; + Slots_index next_slot_idx; + if (empty()) { + class Exception_1 { }; + throw Exception_1 { }; + } + while (true) { + + if (slot_idx < NR_OF_CHANNELS - 1) + next_slot_idx = slot_idx + 1; + else + next_slot_idx = 0; + + if (next_slot_idx == _tail) { + class Exception_2 { }; + throw Exception_2 { }; + } + if (_slots[slot_idx] == idx) + return _slots[next_slot_idx]; + else + slot_idx = next_slot_idx; + } + } + + void dequeue(Slots_index const idx) + { + if (empty() or head() != idx) { + class Index_queue_dequeue_error { }; + throw Index_queue_dequeue_error { }; + } + + _head = (_head + 1) % NR_OF_CHANNELS; + + _nr_of_used_slots -= 1; + } + }; + + static char const *_state_to_step_label(Channel::State state); + + void _mark_req_successful(Channel &chan, + Slots_index idx, + bool &progress); + + bool _handle_failed_generated_req(Channel &chan, + bool &progress); + + void _mark_req_failed(Channel &chan, + bool &progress, + char const *str); + + Channel _channels[NR_OF_CHANNELS] { }; + Index_queue _indices { }; + + void _execute_read (Channel &, Index_queue &, Slots_index const, bool &); + + void _execute_write(Channel &, Index_queue &, Slots_index const, bool &); + + void _execute_sync (Channel &, Index_queue &, Slots_index const, bool &); + + void _execute_rekey(Channel &chan, + Index_queue &indices, + Slots_index idx, + bool &progress); + + void _execute_extend_tree(Channel &chan, + Slots_index idx, + Channel::State tree_ext_step_pending, + bool &progress); + + void _execute_initialize(Channel &, Index_queue &, Slots_index const, + bool &); + void _execute_deinitialize(Channel &, Index_queue &, Slots_index const, + bool &); + + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + void execute(bool &) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + public: + + Request_pool(); + + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override { return !_indices.full(); } + + void submit_request(Module_request &req) override; +}; + + +inline char const *to_string(Tresor::Request::Operation op) +{ + switch (op) { + case Tresor::Request::INVALID: return "invalid"; + case Tresor::Request::READ: return "read"; + case Tresor::Request::WRITE: return "write"; + case Tresor::Request::SYNC: return "sync"; + case Tresor::Request::CREATE_SNAPSHOT: return "create_snapshot"; + case Tresor::Request::DISCARD_SNAPSHOT: return "discard_snapshot"; + case Tresor::Request::REKEY: return "rekey"; + case Tresor::Request::EXTEND_VBD: return "extend_vbd"; + case Tresor::Request::EXTEND_FT: return "extend_ft"; + case Tresor::Request::RESUME_REKEYING: return "resume_rekeying"; + case Tresor::Request::DEINITIALIZE: return "deinitialize"; + case Tresor::Request::INITIALIZE: return "initialize"; + } + class Exception_1 { }; + throw Exception_1 { }; +} + +#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 new file mode 100644 index 0000000000..12c9898297 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/sb_check.h @@ -0,0 +1,166 @@ +/* + * \brief Module for checking all hashes of a superblock and its hash trees + * \author Martin Stein + * \date 2023-05-03 + */ + +/* + * 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__SB_CHECK_H_ +#define _TRESOR__SB_CHECK_H_ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include + +namespace Tresor { + + class Sb_check; + class Sb_check_request; + class Sb_check_channel; +} + + +class Tresor::Sb_check_request : public Module_request +{ + public: + + enum Type { INVALID = 0, CHECK = 1, }; + + private: + + friend class Sb_check; + friend class Sb_check_channel; + + Type _type { INVALID }; + bool _success { false }; + + + public: + + Sb_check_request() { } + + Sb_check_request(Module_id src_module_id, + Module_request_id src_request_id); + + static void create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type); + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } +}; + + +class Tresor::Sb_check_channel +{ + private: + + friend class Sb_check; + + using Request = Sb_check_request; + + enum State { INSPECT_SBS, CHECK_SB }; + + enum Sb_slot_state { + INACTIVE, INIT, DONE, + READ_STARTED, READ_DROPPED, READ_DONE, + VBD_CHECK_STARTED, VBD_CHECK_DROPPED, VBD_CHECK_DONE, + FT_CHECK_STARTED, FT_CHECK_DROPPED, FT_CHECK_DONE, + MT_CHECK_STARTED, MT_CHECK_DROPPED, MT_CHECK_DONE }; + + State _state { INSPECT_SBS }; + Request _request { }; + Generation _highest_gen { 0 }; + Superblock_index _last_sb_slot_idx { 0 }; + Sb_slot_state _sb_slot_state { INACTIVE }; + Superblock_index _sb_slot_idx { 0 }; + Superblock _sb_slot { }; + Snapshot_index _snap_idx { 0 }; + Type_1_node _vbd { }; + Type_1_node _ft { }; + Type_1_node _mt { }; + Physical_block_address _gen_prim_blk_nr { 0 }; + bool _gen_prim_success { false }; +}; + + +class Tresor::Sb_check : public Module +{ + private: + + using Request = Sb_check_request; + using Channel = Sb_check_channel; + + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + static char const *_state_to_step_label(Channel::Sb_slot_state state); + + bool _handle_failed_generated_req(Channel &chan, + bool &progress); + + void _execute_check(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + + public: + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + void execute(bool &) override; + +}; + +#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 new file mode 100644 index 0000000000..6337678203 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/sb_initializer.h @@ -0,0 +1,219 @@ +/* + * \brief Module for initializing the superblocks of a new Tresor + * \author Josef Soentgen + * \date 2023-03-14 + */ + +/* + * 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__SB_INITIALIZER_H_ +#define _TRESOR__SB_INITIALIZER_H_ + +/* base includes */ +#include + +/* tresor includes */ +#include + +namespace Tresor { + + class Sb_initializer; + class Sb_initializer_request; + class Sb_initializer_channel; +} + + +class Tresor::Sb_initializer_request : public Module_request +{ + public: + + enum Type { INVALID = 0, INIT = 1, }; + + private: + + friend class Sb_initializer; + friend class Sb_initializer_channel; + + Type _type { INVALID }; + Tree_level_index _vbd_max_level_idx { 0 }; + Tree_degree _vbd_max_child_idx { 0 }; + Number_of_leaves _vbd_nr_of_leaves { 0 }; + Tree_level_index _ft_max_level_idx { 0 }; + Tree_degree _ft_max_child_idx { 0 }; + Number_of_leaves _ft_nr_of_leaves { 0 }; + Tree_level_index _mt_max_level_idx { 0 }; + Tree_degree _mt_max_child_idx { 0 }; + Number_of_leaves _mt_nr_of_leaves { 0 }; + bool _success { false }; + + + public: + + Sb_initializer_request() { } + + Sb_initializer_request(Module_id src_module_id, + Module_request_id src_request_id); + + static void create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + Tree_level_index vbd_max_level_idx, + Tree_degree vbd_max_child_idx, + Number_of_leaves vbd_nr_of_leaves, + Tree_level_index ft_max_level_idx, + Tree_degree ft_max_child_idx, + Number_of_leaves ft_nr_of_leaves, + Tree_level_index mt_max_level_idx, + Tree_degree mt_max_child_idx, + Number_of_leaves mt_nr_of_leaves); + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } +}; + + +class Tresor::Sb_initializer_channel +{ + private: + + friend class Sb_initializer; + + enum State { + INACTIVE, SUBMITTED, PENDING, IN_PROGRESS, SLOT_COMPLETE, COMPLETE, + FT_REQUEST_COMPLETE, + FT_REQUEST_IN_PROGRESS, + FT_REQUEST_PENDING, + MT_REQUEST_COMPLETE, + MT_REQUEST_IN_PROGRESS, + MT_REQUEST_PENDING, + SYNC_REQUEST_COMPLETE, + SYNC_REQUEST_IN_PROGRESS, + SYNC_REQUEST_PENDING, + TA_REQUEST_CREATE_KEY_COMPLETE, + TA_REQUEST_CREATE_KEY_IN_PROGRESS, + TA_REQUEST_CREATE_KEY_PENDING, + TA_REQUEST_ENCRYPT_KEY_COMPLETE, + TA_REQUEST_ENCRYPT_KEY_IN_PROGRESS, + TA_REQUEST_ENCRYPT_KEY_PENDING, + TA_REQUEST_SECURE_SB_COMPLETE, + TA_REQUEST_SECURE_SB_IN_PROGRESS, + TA_REQUEST_SECURE_SB_PENDING, + VBD_REQUEST_COMPLETE, + VBD_REQUEST_IN_PROGRESS, + VBD_REQUEST_PENDING, + WRITE_REQUEST_COMPLETE, + WRITE_REQUEST_IN_PROGRESS, + WRITE_REQUEST_PENDING, + }; + + State _state { INACTIVE }; + Sb_initializer_request _request { }; + Superblock_index _sb_slot_index { 0 }; + Superblock _sb { }; + Block _sb_slot { }; + Block _blk_io_data { }; + Key _key_plain { }; + Key _key_cipher { }; + Hash _sb_hash { }; + Type_1_node _vbd_node { }; + Type_1_node _ft_node { }; + Type_1_node _mt_node { }; + bool _generated_req_success { false }; + + void clean_data() + { + _sb = Superblock { }; + memset(&_sb_slot, 0, sizeof(_sb_slot)); + + memset(&_blk_io_data, 0, sizeof(_blk_io_data)); + memset(&_key_plain, 0, sizeof(_key_plain)); + memset(&_key_cipher, 0, sizeof(_key_cipher)); + memset(&_sb_hash, 0, sizeof(_sb_hash)); + + memset(&_vbd_node, 0, sizeof(_vbd_node)); + memset(&_ft_node, 0, sizeof(_ft_node)); + memset(&_mt_node, 0, sizeof(_mt_node)); + } +}; + + +class Tresor::Sb_initializer : public Module +{ + private: + + using Request = Sb_initializer_request; + using Channel = Sb_initializer_channel; + + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + void _populate_sb_slot(Channel &channel, + Physical_block_address first, + Number_of_blocks num); + + void _execute(Channel &channel, + bool &progress); + + void _execute_init(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + + public: + + Sb_initializer(); + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + void execute(bool &) override; + +}; + +#endif /* _TRESOR__SB_INITIALIZER_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/sha256_4k_hash.h b/repos/gems/src/lib/tresor/include/tresor/sha256_4k_hash.h new file mode 100644 index 0000000000..815943f0e4 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/sha256_4k_hash.h @@ -0,0 +1,27 @@ +/* + * \brief Calculate SHA256 hash over data blocks of a size of 4096 bytes + * \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__SHAE256_4K_HASH_H_ +#define _TRESOR__SHAE256_4K_HASH_H_ + +namespace Tresor { + + void calc_sha256_4k_hash(void const *data_ptr, + void *hash_ptr); + + + bool check_sha256_4k_hash(void const *data_ptr, + void const *exp_hash_ptr); +} + +#endif /* _TRESOR__SHAE256_4K_HASH_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/superblock_control.h b/repos/gems/src/lib/tresor/include/tresor/superblock_control.h new file mode 100644 index 0000000000..431466178f --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/superblock_control.h @@ -0,0 +1,393 @@ +/* + * \brief Module for management of the superblocks + * \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__SUPERBLOCK_CONTROL_H_ +#define _TRESOR__SUPERBLOCK_CONTROL_H_ + +/* tresor includes */ +#include +#include + +namespace Tresor { + + class Superblock_control; + class Superblock_control_request; + class Superblock_control_channel; +} + +class Tresor::Superblock_control_request : public Module_request +{ + public: + + enum Type { + INVALID = 0, READ_VBA = 1, WRITE_VBA = 2, SYNC = 3, INITIALIZE = 4, + DEINITIALIZE = 5, + VBD_EXTENSION_STEP = 6, + FT_EXTENSION_STEP = 7, + CREATE_SNAPSHOT = 8, + DISCARD_SNAPSHOT = 9, + INITIALIZE_REKEYING = 10, + REKEY_VBA = 11 + }; + + private: + + friend class Superblock_control; + friend class Superblock_control_channel; + + Type _type { INVALID }; + uint64_t _client_req_offset { 0 }; + uint64_t _client_req_tag { 0 }; + Virtual_block_address _vba { 0 }; + Superblock::State _sb_state { INVALID }; + Number_of_blocks _nr_of_blks { 0 }; + bool _success { false }; + bool _request_finished { false }; + + public: + + Superblock_control_request() { } + + Type type() const { return _type; } + + Superblock_control_request(Module_id src_module_id, + Module_request_id src_request_id); + + static void create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t client_req_offset, + uint64_t client_req_tag, + Number_of_blocks nr_of_blks, + uint64_t vba); + + Superblock::State sb_state() { return _sb_state; } + + bool success() const { return _success; } + + bool request_finished() const { return _request_finished; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override + { + 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; + } + } +}; + +class Tresor::Superblock_control_channel +{ + private: + + friend class Superblock_control; + + enum State { + SUBMITTED, + READ_VBA_AT_VBD_PENDING, + READ_VBA_AT_VBD_IN_PROGRESS, + READ_VBA_AT_VBD_COMPLETED, + WRITE_VBA_AT_VBD_PENDING, + WRITE_VBA_AT_VBD_IN_PROGRESS, + WRITE_VBA_AT_VBD_COMPLETED, + READ_SB_PENDING, + READ_SB_IN_PROGRESS, + READ_SB_COMPLETED, + READ_CURRENT_SB_PENDING, + READ_CURRENT_SB_IN_PROGRESS, + READ_CURRENT_SB_COMPLETED, + REKEY_VBA_IN_VBD_PENDING, + REKEY_VBA_IN_VBD_IN_PROGRESS, + REKEY_VBA_IN_VBD_COMPLETED, + VBD_EXT_STEP_IN_VBD_PENDING, + VBD_EXT_STEP_IN_VBD_IN_PROGRESS, + FT_EXT_STEP_IN_FT_PENDING, + FT_EXT_STEP_IN_FT_IN_PROGRESS, + TREE_EXT_STEP_IN_TREE_COMPLETED, + CREATE_KEY_PENDING, + CREATE_KEY_IN_PROGRESS, + CREATE_KEY_COMPLETED, + ENCRYPT_CURRENT_KEY_PENDING, + ENCRYPT_CURRENT_KEY_IN_PROGRESS, + ENCRYPT_CURRENT_KEY_COMPLETED, + ENCRYPT_PREVIOUS_KEY_PENDING, + ENCRYPT_PREVIOUS_KEY_IN_PROGRESS, + ENCRYPT_PREVIOUS_KEY_COMPLETED, + DECRYPT_CURRENT_KEY_PENDING, + DECRYPT_CURRENT_KEY_IN_PROGRESS, + DECRYPT_CURRENT_KEY_COMPLETED, + DECRYPT_PREVIOUS_KEY_PENDING, + DECRYPT_PREVIOUS_KEY_IN_PROGRESS, + DECRYPT_PREVIOUS_KEY_COMPLETED, + SYNC_CACHE_PENDING, + SYNC_CACHE_IN_PROGRESS, + SYNC_CACHE_COMPLETED, + ADD_KEY_AT_CRYPTO_MODULE_PENDING, + ADD_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, + ADD_KEY_AT_CRYPTO_MODULE_COMPLETED, + ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING, + ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, + ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED, + ADD_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING, + ADD_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, + ADD_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED, + REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING, + REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, + REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED, + REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING, + REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS, + REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED, + WRITE_SB_PENDING, + WRITE_SB_IN_PROGRESS, + WRITE_SB_COMPLETED, + SYNC_BLK_IO_PENDING, + SYNC_BLK_IO_IN_PROGRESS, + SYNC_BLK_IO_COMPLETED, + SECURE_SB_PENDING, + SECURE_SB_IN_PROGRESS, + SECURE_SB_COMPLETED, + MAX_SB_HASH_PENDING, + MAX_SB_HASH_IN_PROGRESS, + MAX_SB_HASH_COMPLETED, + COMPLETED + }; + + enum Tag_type { + TAG_SB_CTRL_VBD_VBD_EXT_STEP, + TAG_SB_CTRL_FT_FT_EXT_STEP, + TAG_SB_CTRL_VBD_RKG_REKEY_VBA, + TAG_SB_CTRL_VBD_RKG_READ_VBA, + TAG_SB_CTRL_VBD_RKG_WRITE_VBA, + TAG_SB_CTRL_TA_ENCRYPT_KEY, + TAG_SB_CTRL_CACHE, + TAG_SB_CTRL_BLK_IO_READ_SB, + TAG_SB_CTRL_BLK_IO_WRITE_SB, + TAG_SB_CTRL_BLK_IO_SYNC, + TAG_SB_CTRL_TA_SECURE_SB, + TAG_SB_CTRL_TA_LAST_SB_HASH, + TAG_SB_CTRL_TA_DECRYPT_KEY, + TAG_SB_CTRL_TA_CREATE_KEY, + TAG_SB_CTRL_CRYPTO_ADD_KEY, + TAG_SB_CTRL_CRYPTO_REMOVE_KEY, + }; + + struct Generated_prim + { + enum Type { READ, WRITE, SYNC }; + + Type op { READ }; + bool succ { false }; + Tag_type tg { }; + uint64_t blk_nr { 0 }; + uint64_t idx { 0 }; + }; + + State _state { SUBMITTED }; + Superblock_control_request _request { }; + Generated_prim _generated_prim { }; + Key _key_plaintext { }; + Block _sb_ciphertext_blk { }; + Superblock_index _sb_idx { 0 }; + bool _sb_found { false }; + Superblock_index _read_sb_idx { 0 }; + Generation _generation { 0 }; + Snapshots _snapshots { }; + Hash _hash { }; + Key _curr_key_plaintext { }; + Key _prev_key_plaintext { }; + Physical_block_address _pba { 0 }; + Number_of_blocks _nr_of_leaves { 0 }; + Type_1_node _ft_root { }; + Tree_level_index _ft_max_lvl { 0 }; + Number_of_leaves _ft_nr_of_leaves { 0 }; + + Superblock &_sb_ciphertext() { return *(Superblock *)&_sb_ciphertext_blk; } + + public: + + Superblock_control_request const &request() const { return _request; } +}; + +class Tresor::Superblock_control : public Module +{ + private: + + using Request = Superblock_control_request; + using Channel = Superblock_control_channel; + using Generated_prim = Channel::Generated_prim; + using Tag = Channel::Tag_type; + + enum { NR_OF_CHANNELS = 1 }; + + Superblock _sb { }; + Superblock_index _sb_idx { 0 }; + Generation _curr_gen { 0 }; + Channel _channels[NR_OF_CHANNELS] { }; + + void _mark_req_failed(Channel &chan, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &chan, + bool &progress); + + static char const *_state_to_step_label(Channel::State state); + + bool _handle_failed_generated_req(Channel &chan, + bool &progress); + + void _secure_sb_init(Channel &chan, + uint64_t chan_idx, + bool &progress); + + void _secure_sb_encr_curr_key_compl(Channel &chan, + uint64_t chan_idx, + bool &progress); + + void _secure_sb_encr_prev_key_compl(Channel &chan, + uint64_t chan_idx, + bool &progress); + + void _secure_sb_sync_cache_compl(Channel &chan, + uint64_t chan_idx, + bool &progress); + + void _secure_sb_write_sb_compl(Channel &chan, + uint64_t chan_idx, + bool &progress); + + void _secure_sb_sync_blk_io_compl(Channel &chan, + uint64_t chan_idx, + bool &progress); + + void _init_sb_without_key_values(Superblock const &, Superblock &); + + void _execute_sync(Channel &, uint64_t const job_idx, Superblock &, + Superblock_index &, Generation &, bool &progress); + + void _execute_tree_ext_step(Channel &chan, + uint64_t chan_idx, + Superblock::State tree_ext_sb_state, + bool tree_ext_verbose, + Tag tree_ext_tag, + Channel::State tree_ext_pending_state, + String<4> tree_name, + bool &progress); + + void _execute_rekey_vba(Channel &chan, + uint64_t chan_idx, + bool &progress); + + void _execute_initialize_rekeying(Channel &chan, + uint64_t chan_idx, + bool &progress); + + void _execute_read_vba(Channel &, uint64_t const job_idx, + Superblock const &, bool &progress); + + void _execute_write_vba(Channel &, uint64_t const job_idx, + Superblock &, Generation const &, bool &progress); + + void _discard_disposable_snapshots(Snapshots &, Generation const, + Generation const); + + void _execute_initialize(Channel &, uint64_t const job_idx, + Superblock &, Superblock_index &, + Generation &, bool &progress); + + void _execute_deinitialize(Channel &, uint64_t const job_idx, + Superblock &, Superblock_index &, + Generation &, bool &progress); + + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + void execute(bool &) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + public: + + Virtual_block_address max_vba() const; + + Virtual_block_address resizing_nr_of_pbas() const; + + Virtual_block_address rekeying_vba() const; + + void snapshot_generations(Snapshot_generations &generations) const + { + if (_sb.valid()) { + + for (Snapshot_index idx { 0 }; + idx < MAX_NR_OF_SNAPSHOTS; + idx++) { + + Snapshot const &snap { _sb.snapshots.items[idx] }; + if (snap.valid && snap.keep) + generations.items[idx] = snap.gen; + else + generations.items[idx] = INVALID_GENERATION; + } + } else { + + generations = Snapshot_generations { }; + } + } + + Superblock_info sb_info() const + { + if (_sb.valid()) + + return Superblock_info { + true, _sb.state == Superblock::REKEYING, + _sb.state == Superblock::EXTENDING_FT, + _sb.state == Superblock::EXTENDING_VBD }; + + else + + return Superblock_info { }; + } +}; + +#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 new file mode 100644 index 0000000000..7c81dcf88d --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/trust_anchor.h @@ -0,0 +1,175 @@ +/* + * \brief Module for accessing the systems trust anchor + * \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__TRUST_ANCHOR_H_ +#define _TRESOR__TRUST_ANCHOR_H_ + +/* tresor includes */ +#include +#include +#include + +namespace Tresor { + + class Trust_anchor; + class Trust_anchor_request; + class Trust_anchor_channel; +} + +class Tresor::Trust_anchor_request : public Module_request +{ + public: + + enum Type { + INVALID = 0, CREATE_KEY = 1, ENCRYPT_KEY = 2, DECRYPT_KEY = 3, + SECURE_SUPERBLOCK = 4, GET_LAST_SB_HASH = 5, INITIALIZE = 6 }; + + private: + + friend class Trust_anchor; + friend class Trust_anchor_channel; + + Type _type { INVALID }; + uint8_t _key_plaintext[KEY_SIZE] { 0 }; + uint8_t _key_ciphertext[KEY_SIZE] { 0 }; + Hash _hash { }; + addr_t _passphrase_ptr { 0 }; + bool _success { false }; + + public: + + Trust_anchor_request() { } + + Trust_anchor_request(Module_id src_module_id, + Module_request_id src_request_id); + + static void create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + void *key_plaintext_ptr, + void *key_ciphertext_ptr, + char const *passphrase_ptr, + void *hash_ptr); + + void *hash_ptr() { return (void *)&_hash; } + void *key_plaintext_ptr() { return (void *)&_key_plaintext; } + void *key_ciphertext_ptr() { return (void *)&_key_ciphertext; } + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } +}; + +class Tresor::Trust_anchor_channel +{ + private: + + friend class Trust_anchor; + + enum State { + INACTIVE, SUBMITTED, WRITE_PENDING, WRITE_IN_PROGRESS, + READ_PENDING, READ_IN_PROGRESS, COMPLETE }; + + State _state { INACTIVE }; + Trust_anchor_request _request { }; + Vfs::file_offset _file_offset { 0 }; + size_t _file_size { 0 }; +}; + +class Tresor::Trust_anchor : public Module +{ + private: + + using Request = Trust_anchor_request; + using Channel = Trust_anchor_channel; + using Read_result = Vfs::File_io_service::Read_result; + using Write_result = Vfs::File_io_service::Write_result; + + enum { NR_OF_CHANNELS = 1 }; + + Vfs::Env &_vfs_env; + char _read_buf[64]; + String<128> const _path; + String<128> const _decrypt_path { _path, "/decrypt" }; + Vfs::Vfs_handle &_decrypt_file { vfs_open_rw(_vfs_env, { _decrypt_path }) }; + String<128> const _encrypt_path { _path, "/encrypt" }; + Vfs::Vfs_handle &_encrypt_file { vfs_open_rw(_vfs_env, { _encrypt_path }) }; + String<128> const _generate_key_path { _path, "/generate_key" }; + Vfs::Vfs_handle &_generate_key_file { vfs_open_rw(_vfs_env, { _generate_key_path }) }; + String<128> const _initialize_path { _path, "/initialize" }; + Vfs::Vfs_handle &_initialize_file { vfs_open_rw(_vfs_env, { _initialize_path }) }; + String<128> const _hashsum_path { _path, "/hashsum" }; + Vfs::Vfs_handle &_hashsum_file { vfs_open_rw(_vfs_env, { _hashsum_path }) }; + Channel _channels[NR_OF_CHANNELS] { }; + + void + _execute_write_read_operation(Vfs::Vfs_handle &file, + String<128> const &file_path, + Channel &channel, + char const *write_buf, + char *read_buf, + size_t read_size, + bool &progress); + + void _execute_write_operation(Vfs::Vfs_handle &file, + String<128> const &file_path, + Channel &channel, + char const *write_buf, + bool &progress, + bool result_via_read); + + void _execute_read_operation(Vfs::Vfs_handle &file, + String<128> const &file_path, + Channel &channel, + char *read_buf, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + public: + + Trust_anchor(Vfs::Env &vfs_env, + Xml_node const &xml_node); + + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + void execute(bool &) override; +}; + +#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 new file mode 100644 index 0000000000..90dc9bef3c --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/types.h @@ -0,0 +1,528 @@ +/* + * \brief Basic types, functions, enums used throughout the Tresor ecosystem + * \author Martin Stein + * \author Josef Soentgen + * \date 2020-11-10 + */ + +/* + * 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__TYPES_H_ +#define _TRESOR__TYPES_H_ + +/* base includes */ +#include +#include + +/* tresor includes */ +#include +#include + +namespace Tresor { + + using namespace Genode; + + using Physical_block_address = uint64_t; + using Virtual_block_address = uint64_t; + using Generation = uint64_t; + using Generation_string = String<21>; + using Number_of_leaves = uint64_t; + using Number_of_blocks = uint64_t; + using Tree_level_index = uint32_t; + using Tree_node_index = uint64_t; + using Tree_degree = uint32_t; + using Tree_degree_log_2 = uint32_t; + using Key_id = uint32_t; + using Snapshot_id = uint32_t; + using Snapshot_index = uint32_t; + using Superblock_index = uint8_t; + + enum { BLOCK_SIZE = 4096 }; + enum { INVALID_KEY_ID = 0 }; + enum { INVALID_GENERATION = 0 }; + enum { INITIAL_GENERATION = 0 }; + enum { MAX_PBA = 0xffff'ffff'ffff'ffff }; + enum { INVALID_PBA = MAX_PBA }; + enum { INVALID_NODE_INDEX = 0xff }; + enum { MAX_GENERATION = 0xffff'ffff'ffff'ffff }; + enum { MAX_SNAP_ID = 0xffff'ffff }; + enum { HASH_SIZE = 32 }; + enum { T1_NODE_STORAGE_SIZE = 64 }; + enum { T2_NODE_STORAGE_SIZE = 64 }; + enum { NR_OF_T2_NODES_PER_BLK = (size_t)BLOCK_SIZE / (size_t)T2_NODE_STORAGE_SIZE }; + enum { NR_OF_T1_NODES_PER_BLK = (size_t)BLOCK_SIZE / (size_t)T1_NODE_STORAGE_SIZE }; + enum { TREE_MAX_DEGREE_LOG_2 = 6 }; + enum { TREE_MAX_DEGREE = 1 << TREE_MAX_DEGREE_LOG_2 }; + enum { TREE_MAX_LEVEL = 6 }; + enum { TREE_MAX_NR_OF_LEVELS = TREE_MAX_LEVEL + 1 }; + enum { T2_NODE_LVL = 1 }; + enum { VBD_LOWEST_T1_LVL = 1 }; + enum { FT_LOWEST_T1_LVL = 2 }; + enum { MT_LOWEST_T1_LVL = 2 }; + enum { KEY_SIZE = 32 }; + enum { MAX_NR_OF_SNAPSHOTS = 48 }; + enum { MAX_SNAP_IDX = MAX_NR_OF_SNAPSHOTS - 1 }; + enum { INVALID_SNAP_IDX = MAX_NR_OF_SNAPSHOTS }; + enum { SNAPSHOT_STORAGE_SIZE = 72 }; + enum { NR_OF_SUPERBLOCK_SLOTS = 8 }; + enum { MAX_SUPERBLOCK_INDEX = NR_OF_SUPERBLOCK_SLOTS - 1 }; + enum { FREE_TREE_MIN_MAX_LEVEL = 2 }; + enum { TREE_MAX_NR_OF_LEAVES = to_the_power_of(TREE_MAX_DEGREE, (TREE_MAX_LEVEL - 1)) }; + enum { INVALID_VBA = to_the_power_of(TREE_MAX_DEGREE, TREE_MAX_LEVEL - 1) }; + enum { TREE_MIN_DEGREE = 1 }; + + struct Byte_range; + struct Key_value; + struct Key; + struct Hash; + struct Block; + struct Superblock; + struct Superblock_info; + struct Snapshot; + struct Snapshot_generations; + struct Snapshots; + struct Type_1_node; + struct Type_1_node_block; + struct Type_1_node_walk; + struct Type_2_node; + struct Type_2_node_block; + struct Tree_walk_pbas; + struct Level_indent; + + constexpr Virtual_block_address tree_max_max_vba(Tree_degree degree, + Tree_level_index max_lvl) + { + return to_the_power_of(degree, max_lvl) - 1; + } + + inline Physical_block_address + alloc_pba_from_resizing_contingent(Physical_block_address &first_pba, + Number_of_blocks &nr_of_pbas) + { + if (nr_of_pbas == 0) { + class Exception_1 { }; + throw Exception_1 { }; + } + Physical_block_address const allocated_pba { first_pba }; + first_pba = first_pba + 1; + nr_of_pbas = nr_of_pbas - 1; + return allocated_pba; + } + + inline Tree_node_index + t1_child_idx_for_vba_typed(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 }; + uint64_t const vba_rshift { degr_log_2 * ((uint64_t)lvl - 1) }; + return (Tree_node_index)(degr_mask & (vba >> vba_rshift)); + } + + template + inline Tree_node_index t1_child_idx_for_vba(T1 vba, + T2 lvl, + T3 degr) + { + return t1_child_idx_for_vba_typed((Virtual_block_address)vba, + (Tree_level_index)lvl, + (Tree_degree)degr); + } + + inline Tree_node_index t2_child_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); + } +} + + +struct Tresor::Byte_range +{ + uint8_t const *ptr; + size_t size; + + void print(Output &out) const + { + using Genode::print; + + enum { MAX_BYTES_PER_LINE = 64 }; + enum { MAX_BYTES_PER_WORD = 4 }; + + if (size > 0xffff) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (size > MAX_BYTES_PER_LINE) { + + for (size_t idx { 0 }; idx < size; idx++) { + + if (idx % MAX_BYTES_PER_LINE == 0) + print(out, "\n ", + Hex((uint16_t)idx, Hex::PREFIX, Hex::PAD), ": "); + + else if (idx % MAX_BYTES_PER_WORD == 0) + print(out, " "); + + print(out, Hex(ptr[idx], Hex::OMIT_PREFIX, Hex::PAD)); + } + + } else { + + for (size_t idx { 0 }; idx < size; idx++) { + + if (idx % MAX_BYTES_PER_WORD == 0 && idx != 0) + print(out, " "); + + print(out, Hex(ptr[idx], Hex::OMIT_PREFIX, Hex::PAD)); + } + } + } +}; + + +struct Tresor::Superblock_info +{ + bool valid { false }; + bool rekeying { false }; + bool extending_vbd { false }; + bool extending_ft { false }; +}; + + +struct Tresor::Key_value +{ + uint8_t bytes[KEY_SIZE]; + + void print(Output &out) const + { + Genode::print(out, Byte_range { bytes, KEY_SIZE }); + } +} +__attribute__((packed)); + + +struct Tresor::Key +{ + Key_value value; + Key_id id; +} +__attribute__((packed)); + + +struct Tresor::Hash +{ + uint8_t bytes[HASH_SIZE] { }; + + void print(Output &out) const + { + Genode::print(out, Byte_range { bytes, 4 }, "…"); + } + + bool operator == (Hash const &other) const + { + return !memcmp(bytes, other.bytes, sizeof(bytes)); + } + + bool operator != (Hash const &other) const + { + return !(*this == other); + } +} +__attribute__((packed)); + + +struct Tresor::Type_1_node +{ + Physical_block_address pba { 0 }; + Generation gen { 0 }; + Hash hash { }; + uint8_t padding[16] { 0 }; + + bool valid() const + { + Type_1_node node { }; + return + pba != node.pba || gen != node.gen || hash != node.hash; + } + + void print(Output &out) const + { + Genode::print(out, "pba ", pba, " gen ", gen, " hash ", hash); + } +} +__attribute__((packed)); + +static_assert(sizeof(Tresor::Type_1_node) == Tresor::T1_NODE_STORAGE_SIZE); + + +struct Tresor::Type_1_node_block +{ + Type_1_node nodes[NR_OF_T1_NODES_PER_BLK] { }; +} +__attribute__((packed)); + +static_assert(sizeof(Tresor::Type_1_node_block) == Tresor::BLOCK_SIZE); + + +struct Tresor::Type_2_node +{ + uint64_t pba { 0 }; + uint64_t last_vba { 0 }; + uint64_t alloc_gen { 0 }; + uint64_t free_gen { 0 }; + uint32_t last_key_id { 0 }; + uint8_t reserved { 0 }; + uint8_t padding[27] { 0 }; + + bool valid() const + { + Type_2_node node { }; + return memcmp(this, &node, sizeof(node)) != 0; + } + + void print(Output &out) const + { + Genode::print( + out, "pba ", pba, " last_vba ", last_vba, " alloc_gen ", + alloc_gen, " free_gen ", free_gen, " last_key ", last_key_id); + } + +} +__attribute__((packed)); + +static_assert(sizeof(Tresor::Type_2_node) == Tresor::T2_NODE_STORAGE_SIZE); + + +struct Tresor::Type_2_node_block +{ + Type_2_node nodes[NR_OF_T2_NODES_PER_BLK] { }; +} +__attribute__((packed)); + +static_assert(sizeof(Tresor::Type_2_node_block) == Tresor::BLOCK_SIZE); + + +struct Tresor::Block +{ + uint8_t bytes[BLOCK_SIZE] { }; + + void print(Output &out) const + { + Genode::print(out, Byte_range { bytes, 16 }, "…"); + } +} +__attribute__((packed)); + + +struct Tresor::Snapshot +{ + Hash hash { }; + Physical_block_address pba { INVALID_PBA }; + Generation gen { MAX_GENERATION }; + Number_of_leaves nr_of_leaves { TREE_MAX_NR_OF_LEAVES }; + Tree_level_index max_level { TREE_MAX_LEVEL }; + bool valid { false }; + Snapshot_id id { MAX_SNAP_ID }; + bool keep { false }; + uint8_t padding[6] { 0 }; + + void print(Output &out) const + { + if (valid) + Genode::print( + out, "pba ", (Physical_block_address)pba, " gen ", + (Generation)gen, " hash ", hash, " leaves ", nr_of_leaves, + " max_lvl ", max_level); + else + Genode::print(out, ""); + } + + bool contains_vba(Virtual_block_address vba) const + { + return vba <= nr_of_leaves - 1; + } +} +__attribute__((packed)); + +static_assert(sizeof(Tresor::Snapshot) == Tresor::SNAPSHOT_STORAGE_SIZE); + + +struct Tresor::Snapshots +{ + Snapshot items[MAX_NR_OF_SNAPSHOTS]; + + void discard_disposable_snapshots(Generation curr_gen, + Generation last_secured_gen) + { + for (Snapshot &snap : items) { + + if (snap.valid && + !snap.keep && + snap.gen != curr_gen && + snap.gen != last_secured_gen) + + snap.valid = false; + } + } + + Snapshot_index newest_snapshot_idx() const + { + Snapshot_index result { INVALID_SNAP_IDX }; + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx ++) { + + Snapshot const &snap { items[idx] }; + if (!snap.valid) + continue; + + if (result != INVALID_SNAP_IDX && + snap.gen <= items[result].gen) + continue; + + result = idx; + } + if (result != INVALID_SNAP_IDX) + return result; + + class Exception_1 { }; + throw Exception_1 { }; + } + + Snapshot_index + idx_of_invalid_or_lowest_gen_evictable_snap(Generation curr_gen, + Generation last_secured_gen) const + { + Snapshot_index result { INVALID_SNAP_IDX }; + for (Snapshot_index idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx ++) { + + Snapshot const &snap { items[idx] }; + if (!snap.valid) + return idx; + + if (snap.keep || + snap.gen == curr_gen || + snap.gen == last_secured_gen) + continue; + + if (result != INVALID_SNAP_IDX && + snap.gen >= items[result].gen) + continue; + + result = idx; + } + if (result != INVALID_SNAP_IDX) + return result; + + class Exception_1 { }; + throw Exception_1 { }; + } +} +__attribute__((packed)); + + +struct Tresor::Superblock +{ + enum State : uint8_t + { + INVALID = 0, + NORMAL = 1, + REKEYING = 2, + EXTENDING_VBD = 3, + EXTENDING_FT = 4, + }; + + 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 { }; // offset 3553 + Snapshot_index curr_snap { }; // 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 { 0 }; // 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 { 0 }; // 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 + uint8_t padding[383] { 0 }; // offset 3713 + + bool valid() const { return state != INVALID; } + + char const *state_to_str(State state) const + { + switch (state) { + case INVALID: return "INVALID"; + case NORMAL: return "NORMAL"; + case REKEYING: return "REKEYING"; + case EXTENDING_VBD: return "EXTENDING_VBD"; + case EXTENDING_FT: return "EXTENDING_FT"; } + } + + void print(Output &out) const + { + Genode::print( + out, "state ", state_to_str(state), " last_secured_gen ", + last_secured_generation, " curr_snap ", curr_snap, " degr ", + degree, " first_pba ", first_pba, " pbas ", nr_of_pbas, + " snapshots"); + + for (Snapshot const &snap : snapshots.items) + if (snap.valid) + Genode::print(out, " ", snap); + } +} +__attribute__((packed)); + +static_assert(sizeof(Tresor::Superblock) == Tresor::BLOCK_SIZE); + + +struct Tresor::Type_1_node_walk +{ + Type_1_node nodes[TREE_MAX_NR_OF_LEVELS] { }; +}; + + +struct Tresor::Tree_walk_pbas +{ + Physical_block_address pbas[TREE_MAX_NR_OF_LEVELS] { 0 }; +}; + + +struct Tresor::Snapshot_generations +{ + Generation items[MAX_NR_OF_SNAPSHOTS] { 0 }; +}; + + +struct Tresor::Level_indent +{ + Tree_level_index lvl; + Tree_level_index max_lvl; + + void print(Output &out) const + { + for (Tree_level_index i { 0 }; i < max_lvl + 1 - lvl; i++) + Genode::print(out, " "); + } +}; + +#endif /* _TRESOR__TYPES_H_ */ diff --git a/repos/gems/src/lib/tresor/include/tresor/vbd_check.h b/repos/gems/src/lib/tresor/include/tresor/vbd_check.h new file mode 100644 index 0000000000..bd2a2dd4ad --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/vbd_check.h @@ -0,0 +1,196 @@ +/* + * \brief Module for checking all hashes of a VBD snapshot + * \author Martin Stein + * \date 2023-05-03 + */ + +/* + * 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__VBD_CHECK_H_ +#define _TRESOR__VBD_CHECK_H_ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include + +namespace Tresor { + + class Vbd_check; + class Vbd_check_request; + class Vbd_check_channel; +} + + +class Tresor::Vbd_check_request : public Module_request +{ + public: + + enum Type { INVALID = 0, CHECK = 1, }; + + private: + + friend class Vbd_check; + friend class Vbd_check_channel; + + Type _type { INVALID }; + Tree_level_index _max_lvl { 0 }; + Tree_node_index _max_child_idx { 0 }; + Number_of_leaves _nr_of_leaves { 0 }; + Type_1_node _root { }; + bool _success { false }; + + public: + + Vbd_check_request() { } + + Vbd_check_request(uint64_t src_module_id, + uint64_t src_request_id, + Type type, + Tree_level_index max_lvl, + Tree_node_index max_child_idx, + Number_of_leaves nr_of_leaves, + Type_1_node root); + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override + { + Genode::print(out, type_to_string(_type), " root ", _root); + } +}; + + +class Tresor::Vbd_check_channel +{ + private: + + friend class Vbd_check; + + using Request = Vbd_check_request; + + enum Child_state { + READ_BLOCK = 0, CHECK_HASH = 1, DONE = 2 }; + + struct Type_1_level + { + Child_state children_state[NR_OF_T1_NODES_PER_BLK] { }; + Type_1_node_block children { }; + + Type_1_level() + { + for (Child_state &state : children_state) + state = DONE; + } + }; + + enum Primitive_tag { INVALID, BLOCK_IO }; + + struct Generated_primitive + { + bool success { false }; + Primitive_tag tag { INVALID }; + Physical_block_address blk_nr { 0 }; + bool dropped { false }; + + bool valid() const { return tag != INVALID; } + }; + + Generated_primitive _gen_prim { }; + Tree_level_index _lvl_to_read { 0 }; + Child_state _root_state { DONE }; + Block _leaf_lvl { }; + Type_1_level _t1_lvls[TREE_MAX_LEVEL] { }; + Request _request { }; +}; + + +class Tresor::Vbd_check : public Module +{ + private: + + using Request = Vbd_check_request; + using Channel = Vbd_check_channel; + using Child_state = Vbd_check_channel::Child_state; + using Type_1_level = Vbd_check_channel::Type_1_level; + + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + void _execute_check(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + void _execute_inner_t1_child(Channel &chan, + Type_1_node const &child, + Type_1_level &child_lvl, + Child_state &child_state, + Tree_level_index lvl, + Tree_node_index child_idx, + bool &progress); + + + void _execute_leaf_child(Channel &chan, + Type_1_node const &child, + Block const &child_lvl, + Child_state &child_state, + Tree_level_index lvl, + Tree_node_index child_idx, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + + public: + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + void execute(bool &) override; + +}; + +#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 new file mode 100644 index 0000000000..f67608bacb --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/vbd_initializer.h @@ -0,0 +1,221 @@ +/* + * \brief Module for initializing the VBD + * \author Josef Soentgen + * \date 2023-03-03 + */ + +/* + * 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__VBD_INITIALIZER_H_ +#define _TRESOR__VBD_INITIALIZER_H_ + +/* base includes */ +#include + +/* tresor includes */ +#include + +namespace Tresor { + + class Vbd_initializer; + class Vbd_initializer_request; + class Vbd_initializer_channel; +} + + +class Tresor::Vbd_initializer_request : public Module_request +{ + public: + + enum Type { INVALID = 0, INIT = 1, }; + + private: + + friend class Vbd_initializer; + friend class Vbd_initializer_channel; + + Type _type { INVALID }; + uint8_t _root_node[sizeof(Type_1_node)] { 0 }; + uint64_t _max_level_idx { 0 }; + uint64_t _max_child_idx { 0 }; + uint64_t _nr_of_leaves { 0 }; + bool _success { false }; + + + public: + + Vbd_initializer_request() { } + + Vbd_initializer_request(Module_id src_module_id, + Module_request_id src_request_id); + + static void create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t max_level_idx, + uint64_t max_child_idx, + uint64_t nr_of_leaves); + + void *root_node() { return _root_node; } + + Type type() const { return _type; } + + bool success() const { return _success; } + + static char const *type_to_string(Type type); + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } +}; + + +class Tresor::Vbd_initializer_channel +{ + private: + + friend class Vbd_initializer; + + enum State { + INACTIVE, SUBMITTED, PENDING, IN_PROGRESS, COMPLETE, + BLOCK_ALLOC_PENDING, + BLOCK_ALLOC_IN_PROGRESS, + BLOCK_ALLOC_COMPLETE, + BLOCK_IO_PENDING, + BLOCK_IO_IN_PROGRESS, + BLOCK_IO_COMPLETE, + }; + + enum Child_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLOCK, }; + + struct Type_1_level + { + Type_1_node_block children { }; + Child_state children_state[NR_OF_T1_NODES_PER_BLK] { DONE }; + }; + + struct Root_node + { + Type_1_node node { }; + Child_state state { DONE }; + }; + + State _state { INACTIVE }; + Vbd_initializer_request _request { }; + Root_node _root_node { }; + Type_1_level _t1_levels[TREE_MAX_LEVEL] { }; + uint64_t _level_to_write { 0 }; + uint64_t _blk_nr { 0 }; + uint64_t _child_pba { 0 }; + bool _generated_req_success { false }; + + static void reset_node(Type_1_node &node) + { + memset(&node, 0, sizeof(Type_1_node)); + } + + static void reset_level(Type_1_level &level, + Child_state state) + { + for (unsigned int i = 0; i < NR_OF_T1_NODES_PER_BLK; i++) { + reset_node(level.children.nodes[i]); + level.children_state[i] = state; + } + } + + static void dump(Type_1_node_block const &node_block) + { + for (auto v : node_block.nodes) { + log(v); + } + } +}; + + +class Tresor::Vbd_initializer : public Module +{ + private: + + using Request = Vbd_initializer_request; + using Channel = Vbd_initializer_channel; + + enum { NR_OF_CHANNELS = 1 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + void _execute_leaf_child(Channel &channel, + bool &progress, + uint64_t &nr_of_leaves, + Type_1_node &child, + Vbd_initializer_channel::Child_state &child_state, + uint64_t level_index, + uint64_t child_index); + + void _execute_inner_t1_child(Channel &channel, + bool &progress, + uint64_t nr_of_leaves, + uint64_t &level_to_write, + Type_1_node &child, + Vbd_initializer_channel::Type_1_level &child_level, + Vbd_initializer_channel::Child_state &child_state, + uint64_t level_index, + uint64_t child_index); + + void _execute(Channel &channel, + bool &progress); + + void _execute_init(Channel &channel, + bool &progress); + + void _mark_req_failed(Channel &channel, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &channel, + bool &progress); + + + /************ + ** Module ** + ************/ + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; + + + public: + + Vbd_initializer(); + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &req) override; + + void execute(bool &) override; + +}; + +#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 new file mode 100644 index 0000000000..558ca82778 --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/verbosity.h @@ -0,0 +1,29 @@ +/* + * \brief Verbosity configuration + * \author Martin Stein + * \date 2023-05-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__VERBOSITY_H_ +#define _TRESOR__VERBOSITY_H_ + +namespace Tresor { + + enum { VERBOSE_MODULE_COMMUNICATION = 0 }; + enum { VERBOSE_VBD_EXTENSION = 0 }; + enum { VERBOSE_FT_EXTENSION = 0 }; + enum { VERBOSE_REKEYING = 0 }; + enum { VERBOSE_VBA_ACCESS = 0 }; + enum { VERBOSE_CRYPTO = 0 }; + enum { VERBOSE_BLOCK_IO = 0 }; + enum { VERBOSE_CHECK = 0 }; +} + +#endif /* _TRESOR__VERBOSITY_H_ */ diff --git a/repos/gems/include/cbe/vfs/io_job.h b/repos/gems/src/lib/tresor/include/tresor/vfs/io_job.h similarity index 84% rename from repos/gems/include/cbe/vfs/io_job.h rename to repos/gems/src/lib/tresor/include/tresor/vfs/io_job.h index aded1f7e30..a04a53354d 100644 --- a/repos/gems/include/cbe/vfs/io_job.h +++ b/repos/gems/src/lib/tresor/include/tresor/vfs/io_job.h @@ -1,38 +1,34 @@ /* - * \brief Integration of the Consistent Block Encrypter (CBE) + * \brief Integration of the Tresor block encryption * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 */ /* - * Copyright (C) 2020 Genode Labs GmbH + * 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 _CBE__VFS__IO_JOB_H_ -#define _CBE__VFS__IO_JOB_H_ +#ifndef _TRESOR__VFS__IO_JOB_H_ +#define _TRESOR__VFS__IO_JOB_H_ -/* Genode includes */ +/* base includes */ #include #include namespace Util { - using file_size = Vfs::file_size; - using file_offset = Vfs::file_offset; - using Byte_range_ptr = Vfs::Byte_range_ptr; - using Const_byte_range_ptr = Vfs::Const_byte_range_ptr; - using size_t = Genode::size_t; + using namespace Genode; struct Io_job { struct Buffer { - char *base; - size_t size; + char *base; + size_t size; }; enum class Operation { INVALID, READ, WRITE, SYNC }; @@ -49,8 +45,8 @@ namespace Util { } } - struct Unsupported_Operation : Genode::Exception { }; - struct Invalid_state : Genode::Exception { }; + struct Unsupported_Operation : Exception { }; + struct Invalid_state : Exception { }; enum State { PENDING, IN_PROGRESS, COMPLETE, }; @@ -79,19 +75,16 @@ namespace Util { enum class Partial_result { ALLOW, DENY }; - Vfs::Vfs_handle &_handle; - - Operation const _op; - State _state; - char *_data; - file_offset const _base_offset; - file_offset _current_offset; - size_t _current_count; - - bool const _allow_partial; - - bool _success; - bool _complete; + Vfs::Vfs_handle &_handle; + Operation const _op; + State _state; + char *_data; + Vfs::file_offset const _base_offset; + size_t _current_offset; + size_t _current_count; + bool const _allow_partial; + bool _success; + bool _complete; bool _read() { @@ -261,7 +254,7 @@ namespace Util { Io_job(Vfs::Vfs_handle &handle, Operation op, Buffer &buffer, - file_offset base_offset, + Vfs::file_offset base_offset, Partial_result partial_result = Partial_result::DENY) : _handle { handle }, @@ -280,7 +273,7 @@ namespace Util { bool succeeded() const { return _success; } Operation op() const { return _op; } - void print(Genode::Output &out) const + void print(Output &out) const { Genode::print(out, "(", to_string(_op), ")", " state: ", _state_to_string(_state), @@ -302,9 +295,8 @@ namespace Util { } } - Genode::size_t current_offset() const { return _current_offset; } + size_t current_offset() const { return _current_offset; } }; +} -} /* namespace Util */ - -#endif /* _CBE__VFS__IO_JOB_H_ */ +#endif /* _TRESOR__VFS__IO_JOB_H_ */ diff --git a/repos/gems/src/app/cbe_tester/vfs_utilities.h b/repos/gems/src/lib/tresor/include/tresor/vfs_utilities.h similarity index 80% rename from repos/gems/src/app/cbe_tester/vfs_utilities.h rename to repos/gems/src/lib/tresor/include/tresor/vfs_utilities.h index 25053498d7..bce620c001 100644 --- a/repos/gems/src/app/cbe_tester/vfs_utilities.h +++ b/repos/gems/src/lib/tresor/include/tresor/vfs_utilities.h @@ -5,16 +5,16 @@ */ /* - * Copyright (C) 2020 Genode Labs GmbH + * 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 _CBE_TESTER__VFS_UTILITIES_H_ -#define _CBE_TESTER__VFS_UTILITIES_H_ +#ifndef _TRESOR__VFS_UTILITIES_H_ +#define _TRESOR__VFS_UTILITIES_H_ -/* Genode includes */ +/* base includes */ #include #include @@ -31,4 +31,5 @@ Vfs::Vfs_handle &vfs_open_wo(Vfs::Env &vfs_env, Vfs::Vfs_handle &vfs_open_rw(Vfs::Env &vfs_env, Genode::String<128> path); -#endif /* _CBE_TESTER__VFS_UTILITIES_H_ */ + +#endif /* _TRESOR__VFS_UTILITIES_H_ */ 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 new file mode 100644 index 0000000000..6290b8b91a --- /dev/null +++ b/repos/gems/src/lib/tresor/include/tresor/virtual_block_device.h @@ -0,0 +1,400 @@ +/* + * \brief Module for accessing and managing trees of the virtual block device + * \author Martin Stein + * \date 2023-03-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__VIRTUAL_BLOCK_DEVICE_H_ +#define _TRESOR__VIRTUAL_BLOCK_DEVICE_H_ + +/* tresor includes */ +#include +#include +#include + +namespace Tresor { + + class Virtual_block_device; + class Virtual_block_device_request; + class Virtual_block_device_channel; +} + +class Tresor::Virtual_block_device_request : public Module_request +{ + public: + + enum Type { + INVALID = 0, REKEY_VBA = 3, READ_VBA = 1, WRITE_VBA = 2, VBD_EXTENSION_STEP = 4 }; + + private: + + friend class Virtual_block_device; + friend class Virtual_block_device_channel; + + Type _type { INVALID }; + Virtual_block_address _vba { 0 }; + Snapshots _snapshots { }; + Tree_degree _snapshots_degree { 0 }; + Generation _curr_gen { INVALID_GENERATION }; + Key_id _new_key_id { 0 }; + Key_id _old_key_id { 0 }; + addr_t _ft_root_pba_ptr { 0 }; + addr_t _ft_root_gen_ptr { 0 }; + addr_t _ft_root_hash_ptr { 0 }; + uint64_t _ft_max_level { 0 }; + uint64_t _ft_degree { 0 }; + uint64_t _ft_leaves { 0 }; + addr_t _mt_root_pba_ptr { 0 }; + addr_t _mt_root_gen_ptr { 0 }; + addr_t _mt_root_hash_ptr { 0 }; + uint64_t _mt_max_level { 0 }; + uint64_t _mt_degree { 0 }; + uint64_t _mt_leaves { 0 }; + uint64_t _vbd_degree { 0 }; + uint64_t _vbd_highest_vba { 0 }; + bool _rekeying { 0 }; + uint64_t _client_req_offset { 0 }; + uint64_t _client_req_tag { 0 }; + Generation _last_secured_generation { INVALID_GENERATION }; + Physical_block_address _pba { 0 }; + Number_of_blocks _nr_of_pbas { 0 }; + Number_of_leaves _nr_of_leaves { 0 }; + bool _success { false }; + + public: + + Virtual_block_device_request() { } + + Virtual_block_device_request(Module_id src_module_id, + Module_request_id src_request_id); + + static void create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t client_req_offset, + uint64_t client_req_tag, + Generation last_secured_generation, + addr_t ft_root_pba_ptr, + addr_t ft_root_gen_ptr, + addr_t ft_root_hash_ptr, + uint64_t ft_max_level, + uint64_t ft_degree, + uint64_t ft_leaves, + addr_t mt_root_pba_ptr, + addr_t mt_root_gen_ptr, + addr_t mt_root_hash_ptr, + uint64_t mt_max_level, + uint64_t mt_degree, + uint64_t mt_leaves, + uint64_t vbd_degree, + uint64_t vbd_highest_vba, + bool rekeying, + Virtual_block_address vba, + Snapshot const *snapshot_ptr, + Snapshots const *snapshots_ptr, + Tree_degree snapshots_degree, + Key_id old_key_id, + Key_id new_key_id, + Generation current_gen, + Key_id key_id, + Physical_block_address first_pba, + Number_of_blocks nr_of_pbas); + + bool success() const { return _success; } + + Physical_block_address pba() const { return _pba; } + + Number_of_blocks nr_of_pbas() const { return _nr_of_pbas; } + + Number_of_leaves nr_of_leaves() const { return _nr_of_leaves; } + + Snapshot *snapshot_ptr() { return &_snapshots.items[0]; } + + Snapshots *snapshots_ptr() { return &_snapshots; } + + static char const *type_to_string(Type type); + + char const *type_name() const { return type_to_string(_type); } + + + /******************** + ** Module_request ** + ********************/ + + void print(Output &out) const override { Genode::print(out, type_to_string(_type)); } +}; + +class Tresor::Virtual_block_device_channel +{ + private: + + friend class Virtual_block_device; + + enum State { + SUBMITTED, + READ_ROOT_NODE_PENDING, + READ_ROOT_NODE_IN_PROGRESS, + READ_ROOT_NODE_COMPLETED, + READ_INNER_NODE_PENDING, + READ_INNER_NODE_IN_PROGRESS, + READ_INNER_NODE_COMPLETED, + READ_LEAF_NODE_PENDING, + READ_LEAF_NODE_IN_PROGRESS, + READ_LEAF_NODE_COMPLETED, + READ_CLIENT_DATA_FROM_LEAF_NODE_PENDING, + READ_CLIENT_DATA_FROM_LEAF_NODE_IN_PROGRESS, + READ_CLIENT_DATA_FROM_LEAF_NODE_COMPLETED, + WRITE_CLIENT_DATA_TO_LEAF_NODE_PENDING, + WRITE_CLIENT_DATA_TO_LEAF_NODE_IN_PROGRESS, + WRITE_CLIENT_DATA_TO_LEAF_NODE_COMPLETED, + DECRYPT_LEAF_NODE_PENDING, + DECRYPT_LEAF_NODE_IN_PROGRESS, + DECRYPT_LEAF_NODE_COMPLETED, + ALLOC_PBAS_AT_LEAF_LVL_PENDING, + ALLOC_PBAS_AT_LEAF_LVL_IN_PROGRESS, + ALLOC_PBAS_AT_LEAF_LVL_COMPLETED, + ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING, + ALLOC_PBAS_AT_LOWEST_INNER_LVL_IN_PROGRESS, + ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED, + ALLOC_PBAS_AT_HIGHER_INNER_LVL_PENDING, + ALLOC_PBAS_AT_HIGHER_INNER_LVL_IN_PROGRESS, + ALLOC_PBAS_AT_HIGHER_INNER_LVL_COMPLETED, + ENCRYPT_LEAF_NODE_PENDING, + ENCRYPT_LEAF_NODE_IN_PROGRESS, + ENCRYPT_LEAF_NODE_COMPLETED, + WRITE_LEAF_NODE_PENDING, + WRITE_LEAF_NODE_IN_PROGRESS, + WRITE_LEAF_NODE_COMPLETED, + WRITE_INNER_NODE_PENDING, + WRITE_INNER_NODE_IN_PROGRESS, + WRITE_INNER_NODE_COMPLETED, + WRITE_ROOT_NODE_PENDING, + WRITE_ROOT_NODE_IN_PROGRESS, + WRITE_ROOT_NODE_COMPLETED, + COMPLETED + }; + + struct Type_1_node_blocks + { + Type_1_node_block items[TREE_MAX_LEVEL] { }; + }; + + struct Type_1_node_blocks_pbas + { + Physical_block_address items[TREE_MAX_LEVEL] { 0 }; + }; + + enum Tag_type + { + TAG_INVALID, + TAG_VBD_CACHE, + TAG_VBD_BLK_IO_WRITE_CLIENT_DATA, + TAG_VBD_BLK_IO_READ_CLIENT_DATA, + TAG_VBD_BLK_IO, + TAG_VBD_FT_ALLOC_FOR_NON_RKG, + TAG_VBD_FT_ALLOC_FOR_RKG_CURR_GEN_BLKS, + TAG_VBD_FT_ALLOC_FOR_RKG_OLD_GEN_BLKS, + TAG_VBD_CRYPTO_ENCRYPT, + TAG_VBD_CRYPTO_DECRYPT, + }; + + struct Generated_prim + { + enum Type { READ, WRITE }; + + Type op { READ }; + bool succ { false }; + Tag_type tg { TAG_INVALID }; + uint64_t blk_nr { 0 }; + uint64_t idx { 0 }; + }; + + Snapshot &snapshots(Snapshot_index idx) + { + if (idx < MAX_NR_OF_SNAPSHOTS) + return _request._snapshots.items[idx]; + + class Snapshot_idx_too_large { }; + throw Snapshot_idx_too_large { }; + } + + Snapshot &snap(); + + Virtual_block_device_request _request { }; + State _state { SUBMITTED }; + Generated_prim _generated_prim { }; + Snapshot_index _snapshot_idx { 0 }; + Type_1_node_blocks _t1_blks { }; + Type_1_node_blocks_pbas _t1_blks_old_pbas { }; + Tree_level_index _t1_blk_idx { 0 }; + Virtual_block_address _vba { 0 }; + Type_1_node_walk _t1_node_walk { }; + Tree_walk_pbas _new_pbas { }; + Hash _hash { }; + Number_of_blocks _nr_of_blks { 0 }; + Generation _last_secured_gen { 0 }; + Generation _free_gen { 0 }; + Block _data_blk { }; + Physical_block_address _data_blk_old_pba { 0 }; + bool _first_snapshot { false }; +}; + +class Tresor::Virtual_block_device : public Module +{ + private: + + using Channel = Virtual_block_device_channel; + using Request = Virtual_block_device_request; + using Generated_prim = Channel::Generated_prim; + using Type_1_node_blocks = Channel::Type_1_node_blocks; + + enum { NR_OF_CHANNELS = 1 }; + enum { FIRST_T1_NODE_BLKS_IDX = 1 }; + enum { MAX_T1_NODE_BLKS_IDX = 6 }; + + Channel _channels[NR_OF_CHANNELS] { }; + + static char const *_state_to_step_label(Channel::State state); + + bool _handle_failed_generated_req(Channel &chan, + bool &progress); + + bool _find_next_snap_to_rekey_vba_at(Channel const &chan, + Snapshot_index &next_snap_idx); + + void _execute_read_vba (Channel &, uint64_t, bool &); + void _execute_write_vba (Channel &, uint64_t, bool &); + void _execute_rekey_vba (Channel &, uint64_t, bool &); + void _execute_vbd_extension_step (Channel &, uint64_t, bool &); + + void _mark_req_failed(Channel &chan, + bool &progress, + char const *str); + + void _mark_req_successful(Channel &chan, + bool &progress); + + void _check_that_primitive_was_successful(Channel::Generated_prim const &); + + void _execute_read_vba_read_inner_node_completed(Channel &channel, + uint64_t const job_idx, + bool &progress); + + Virtual_block_address _tree_max_max_vba(Tree_degree snap_degree, + Snapshot const &snap); + + void _update_nodes_of_branch_of_written_vba(Snapshot &snapshot, + uint64_t const snapshot_degree, + uint64_t const vba, + Tree_walk_pbas const &new_pbas, + Hash const & leaf_hash, + uint64_t curr_gen, + Channel::Type_1_node_blocks &t1_blks); + + void + _alloc_pba_from_resizing_contingent(Physical_block_address &first_pba, + Number_of_blocks &nr_of_pbas, + Physical_block_address &allocated_pba); + + void _set_args_in_order_to_write_client_data_to_leaf_node(Tree_walk_pbas const &, + uint64_t const job_idx, + Channel::State &, + Channel::Generated_prim &, + bool &progress); + + void _set_new_pbas_identical_to_current_pbas(Channel &chan); + + void + _add_new_branch_to_snap_using_pba_contingent(Channel &chan, + Tree_level_index mount_at_lvl, + Tree_node_index mount_at_child_idx); + + void + _set_args_for_alloc_of_new_pbas_for_resizing(Channel &chan, + uint64_t chan_idx, + Tree_level_index min_lvl, + bool &progress); + + void _add_new_root_lvl_to_snap_using_pba_contingent(Channel &chan); + + void _check_hash_of_read_type_1_node(Snapshot const &snapshot, + uint64_t const snapshots_degree, + uint64_t const t1_blk_idx, + Channel::Type_1_node_blocks const &t1_blks, + uint64_t const vba); + + void _initialize_new_pbas_and_determine_nr_of_pbas_to_allocate(uint64_t const curr_gen, + Snapshot const &snapshot, + uint64_t const snapshots_degree, + uint64_t const vba, + Channel::Type_1_node_blocks const &t1_blks, + Tree_walk_pbas &new_pbas, + uint64_t &nr_of_blks); + + void _set_args_for_alloc_of_new_pbas_for_branch_of_written_vba(uint64_t curr_gen, + Snapshot const &snapshot, + uint64_t const snapshots_degree, + uint64_t const vba, + Channel::Type_1_node_blocks const &t1_blks, + uint64_t const prim_idx, + uint64_t &free_gen, + Type_1_node_walk &t1_walk, + Channel::State &state, + Channel::Generated_prim &prim, + bool &progress); + + void _set_args_for_alloc_of_new_pbas_for_rekeying(Channel &chan, + uint64_t chan_idx, + Tree_level_index min_lvl); + + void _set_args_in_order_to_read_type_1_node(Snapshot const &snapshot, + uint64_t const snapshots_degree, + uint64_t const t1_blk_idx, + Channel::Type_1_node_blocks const &t1_blks, + uint64_t const vba, + uint64_t const job_idx, + Channel::State &state, + Channel::Generated_prim &prim, + bool &progress); + + void _set_args_for_write_back_of_t1_lvl(Tree_level_index const max_lvl_idx, + uint64_t const t1_lvl_idx, + uint64_t const pba, + uint64_t const prim_idx, + Channel::State &state, + bool &progress, + Channel::Generated_prim &prim); + + /************ + ** Module ** + ************/ + + bool ready_to_submit_request() override; + + void submit_request(Module_request &mod_req) override; + + bool _peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_completed_request(Module_request &req) override; + + void execute(bool &) override; + + bool _peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) override; + + void _drop_generated_request(Module_request &mod_req) override; + + void generated_request_complete(Module_request &req) override; +}; + +#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 new file mode 100644 index 0000000000..deb18d2df7 --- /dev/null +++ b/repos/gems/src/lib/tresor/meta_tree.cc @@ -0,0 +1,683 @@ +/* + * \brief Module for doing free tree COW allocations on the meta tree + * \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 +#include + +using namespace Tresor; + + +/*************** + ** Utilities ** + ***************/ + +static bool check_level_0_usable(Generation gen, + Type_2_node &node) +{ + return node.alloc_gen != gen; +} + + +/*********************** + ** Meta_tree_request ** + ***********************/ + +void Meta_tree_request::create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + void *mt_root_pba_ptr, + void *mt_root_gen_ptr, + void *mt_root_hash_ptr, + uint64_t mt_max_lvl, + uint64_t mt_edges, + uint64_t mt_leaves, + uint64_t curr_gen, + uint64_t old_pba) +{ + Meta_tree_request req { src_module_id, src_request_id }; + req._type = (Type)req_type; + req._mt_root_pba_ptr = (addr_t)mt_root_pba_ptr; + req._mt_root_gen_ptr = (addr_t)mt_root_gen_ptr; + req._mt_root_hash_ptr = (addr_t)mt_root_hash_ptr; + req._mt_max_lvl = mt_max_lvl; + req._mt_edges = mt_edges; + req._mt_leaves = mt_leaves; + req._current_gen = curr_gen; + req._old_pba = old_pba; + if (sizeof(req) > buf_size) { + class Exception_2 { }; + throw Exception_2 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); +} + + +Meta_tree_request::Meta_tree_request(Module_id src_module_id, + Module_request_id src_request_id) +: + Module_request { src_module_id, src_request_id, META_TREE } +{ } + + +char const *Meta_tree_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + case UPDATE: return "update"; + } + return "?"; +} + + +/*************** + ** Meta_tree ** + ***************/ + +bool Meta_tree::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel &channel { _channels[id] }; + Local_cache_request const &local_req { channel._cache_request }; + if (local_req.state == Local_cache_request::PENDING) { + + Block_io_request::Type blk_io_req_type { + local_req.op == Local_cache_request::READ ? + Block_io_request::READ : + Local_cache_request::WRITE ? + Block_io_request::WRITE : + Block_io_request::INVALID }; + + if (blk_io_req_type == Block_io_request::INVALID) { + class Exception_1 { }; + throw Exception_1 { }; + } + construct_in_buf( + buf_ptr, buf_size, META_TREE, id, blk_io_req_type, + 0, 0, 0, local_req.pba, 0, 1, + channel._cache_request.block_data, nullptr); + + return true; + } + } + return false; +} + + +void Meta_tree::_drop_generated_request(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Local_cache_request &local_req { _channels[id]._cache_request }; + if (local_req.state != Local_cache_request::PENDING) { + class Exception_2 { }; + throw Exception_2 { }; + } + local_req.state = Local_cache_request::IN_PROGRESS; +} + + +void Meta_tree::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Local_cache_request &local_req { _channels[id]._cache_request }; + if (local_req.state != Local_cache_request::IN_PROGRESS) { + class Exception_2 { }; + throw Exception_2 { }; + } + if (mod_req.dst_module_id() != BLOCK_IO) { + class Exception_3 { }; + throw Exception_3 { }; + } + Block_io_request &blk_io_req { *static_cast(&mod_req) }; + Channel &channel { _channels[id] }; + if (!blk_io_req.success()) { + + channel._request._success = false; + channel._request._new_pba = INVALID_PBA; + channel._state = Channel::COMPLETE; + return; + + } + Type_1_info &t1_info { channel._level_n_nodes[local_req.level] }; + Type_2_info &t2_info { channel._level_1_node }; + + switch (local_req.op) { + case Local_cache_request::SYNC: + + class Exception_3 { }; + throw Exception_3 { }; + + case Local_cache_request::READ: + + if (local_req.level > T2_NODE_LVL) { + + if (!check_sha256_4k_hash(channel._cache_request.block_data, &t1_info.node.hash)) { + + channel._state = Channel::TREE_HASH_MISMATCH; + + } else { + + memcpy(&t1_info.entries, channel._cache_request.block_data, BLOCK_SIZE); + t1_info.index = 0; + t1_info.state = Type_1_info::READ_COMPLETE; + } + } else if (local_req.level == T2_NODE_LVL) { + + if (!check_sha256_4k_hash(channel._cache_request.block_data, &t2_info.node.hash)) { + + channel._state = Channel::TREE_HASH_MISMATCH; + + } else { + + memcpy(&t2_info.entries, channel._cache_request.block_data, BLOCK_SIZE); + t2_info.index = 0; + t2_info.state = Type_2_info::READ_COMPLETE; + } + } else { + class Exception_4 { }; + throw Exception_4 { }; + } + break; + + case Local_cache_request::WRITE: + + if (local_req.level > T2_NODE_LVL) { + + t1_info.state = Type_1_info::WRITE_COMPLETE; + + } else if (local_req.level == T2_NODE_LVL) { + + t2_info.state = Type_2_info::WRITE_COMPLETE; + + } else { + + class Exception_5 { }; + throw Exception_5 { }; + } + break; + } + local_req = Local_cache_request { + Local_cache_request::INVALID, Local_cache_request::READ, + false, 0, 0, nullptr }; +} + + +void Meta_tree::_mark_req_failed(Channel &channel, + bool &progress, + char const *str) +{ + error("request failed: failed to ", str); + channel._request._success = false; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Meta_tree::_mark_req_successful(Channel &channel, + bool &progress) +{ + channel._request._success = true; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Meta_tree::_update_parent(Type_1_node &node, + uint8_t const *blk_ptr, + uint64_t gen, + uint64_t pba) +{ + calc_sha256_4k_hash(blk_ptr, &node.hash); + node.gen = gen; + node.pba = pba; +} + + +void Meta_tree::_exchange_nv_inner_nodes(Channel &channel, + Type_2_node &t2_entry, + bool &exchanged) +{ + Request &req { channel._request }; + uint64_t pba; + exchanged = false; + + // loop non-volatile inner nodes + for (uint64_t lvl { MT_LOWEST_T1_LVL }; lvl <= TREE_MAX_LEVEL; lvl++) { + + Type_1_info &t1_info { channel._level_n_nodes[lvl] }; + if (t1_info.node.valid() && !t1_info.volatil) { + + pba = t1_info.node.pba; + t1_info.node.pba = t2_entry.pba; + t1_info.node.gen = req._current_gen; + t1_info.volatil = true; + t2_entry.pba = pba; + t2_entry.alloc_gen = req._current_gen; + t2_entry.free_gen = req._current_gen; + t2_entry.reserved = false; + + exchanged = true; + break; + } + } +} + + +void Meta_tree::_exchange_nv_level_1_node(Channel &channel, + Type_2_node &t2_entry, + bool &exchanged) +{ + Request &req { channel._request }; + uint64_t pba { channel._level_1_node.node.pba }; + exchanged = false; + + if (!channel._level_1_node.volatil) { + + channel._level_1_node.node.pba = t2_entry.pba; + channel._level_1_node.volatil = true; + + t2_entry.pba = pba; + t2_entry.alloc_gen = req._current_gen; + t2_entry.free_gen = req._current_gen; + t2_entry.reserved = false; + + exchanged = true; + } +} + + +void Meta_tree::_exchange_request_pba(Channel &channel, + Type_2_node &t2_entry) +{ + Request &req { channel._request }; + req._success = true; + req._new_pba = t2_entry.pba; + channel._finished = true; + + t2_entry.pba = req._old_pba; + t2_entry.alloc_gen = req._current_gen; + t2_entry.free_gen = req._current_gen; + t2_entry.reserved = false; +} + + +void Meta_tree::_handle_level_0_nodes(Channel &channel, + bool &handled) +{ + Request &req { channel._request }; + Type_2_node tmp_t2_entry; + handled = false; + + for(unsigned i = 0; i <= req._mt_edges - 1; i++) { + + tmp_t2_entry = channel._level_1_node.entries.nodes[i]; + + if (tmp_t2_entry.valid() && + check_level_0_usable(req._current_gen, tmp_t2_entry)) + { + bool exchanged_level_1; + bool exchanged_level_n { false }; + bool exchanged_request_pba { false }; + + // first try to exchange the level 1 node ... + _exchange_nv_level_1_node( + channel, tmp_t2_entry, exchanged_level_1); + + // ... next the inner level n nodes ... + if (!exchanged_level_1) + _exchange_nv_inner_nodes( + channel, tmp_t2_entry, exchanged_level_n); + + // ... and than satisfy the original mt request + if (!exchanged_level_1 && !exchanged_level_n) { + _exchange_request_pba(channel, tmp_t2_entry); + exchanged_request_pba = true; + } + channel._level_1_node.entries.nodes[i] = tmp_t2_entry; + handled = true; + + if (exchanged_request_pba) + return; + } + } +} + + +void Meta_tree::_handle_level_1_node(Channel &channel, + bool &handled) +{ + Type_1_info &t1_info { channel._level_n_nodes[MT_LOWEST_T1_LVL] }; + Type_2_info &t2_info { channel._level_1_node }; + Request &req { channel._request }; + + switch (t2_info.state) { + case Type_2_info::INVALID: + + handled = false; + break; + + case Type_2_info::READ: + + channel._cache_request = Local_cache_request { + Local_cache_request::PENDING, Local_cache_request::READ, false, + t2_info.node.pba, 1, nullptr }; + + handled = true; + break; + + case Type_2_info::READ_COMPLETE: + + _handle_level_0_nodes(channel, handled); + if (handled) { + t2_info.state = Type_2_info::WRITE; + } else { + t2_info.state = Type_2_info::COMPLETE; + handled = true; + } + break; + + case Type_2_info::WRITE: + { + uint8_t block_data[BLOCK_SIZE]; + memcpy(block_data, &t2_info.entries, BLOCK_SIZE); + + _update_parent( + t1_info.entries.nodes[t1_info.index], block_data, req._current_gen, + t2_info.node.pba); + + channel._cache_request = Local_cache_request { + Local_cache_request::PENDING, Local_cache_request::WRITE, false, + t2_info.node.pba, 1, block_data }; + + t1_info.dirty = true; + handled = true; + break; + } + case Type_2_info::WRITE_COMPLETE: + + t1_info.index++; + t2_info.state = Type_2_info::INVALID; + handled = true; + break; + + case Type_2_info::COMPLETE: + + t1_info.index++; + t2_info.state = Type_2_info::INVALID; + handled = true; + break; + } +} + + +void Meta_tree::_execute_update(Channel &channel, + bool &progress) +{ + bool handled_level_1_node; + bool handled_level_n_nodes; + _handle_level_1_node(channel, handled_level_1_node); + if (handled_level_1_node) { + progress = true; + return; + } + _handle_level_n_nodes(channel, handled_level_n_nodes); + progress = progress || handled_level_n_nodes; +} + + +void Meta_tree::execute(bool &progress) +{ + for (Channel &channel : _channels) { + + if (channel._cache_request.state != Local_cache_request::INVALID) + continue; + + switch(channel._state) { + case Channel::INVALID: + break; + case Channel::UPDATE: + _execute_update(channel, progress); + break; + case Channel::COMPLETE: + break; + case Channel::TREE_HASH_MISMATCH: + class Exception_1 { }; + throw Exception_1 { }; + } + } +} + + +Meta_tree::Meta_tree() { } + + +bool Meta_tree::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::COMPLETE) { + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Meta_tree::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._state != Channel::COMPLETE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._state = Channel::INVALID; +} + + +bool Meta_tree::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::INVALID) + return true; + } + return false; +} + + +bool Meta_tree::_node_volatile(Type_1_node const &node, + uint64_t gen) +{ + return node.gen == 0 || node.gen != gen; +} + + +void Meta_tree::submit_request(Module_request &mod_req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + Channel &chan { _channels[id] }; + if (chan._state == Channel::INVALID) { + + mod_req.dst_request_id(id); + + chan._request = *static_cast(&mod_req); + chan._finished = false; + chan._state = Channel::UPDATE; + for (Type_1_info &t1_info : chan._level_n_nodes) { + t1_info = Type_1_info { }; + } + chan._level_1_node = Type_2_info { }; + + Request &req { chan._request }; + Type_1_node root_node { }; + root_node.pba = *(uint64_t *)req._mt_root_pba_ptr; + root_node.gen = *(uint64_t *)req._mt_root_gen_ptr; + memcpy(&root_node.hash, (uint8_t *)req._mt_root_hash_ptr, + HASH_SIZE); + + chan._level_n_nodes[req._mt_max_lvl].node = root_node; + chan._level_n_nodes[req._mt_max_lvl].state = Type_1_info::READ; + chan._level_n_nodes[req._mt_max_lvl].volatil = + _node_volatile(root_node, req._current_gen); + + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} + + +void Meta_tree::_handle_level_n_nodes(Channel &channel, + bool &handled) +{ + Request &req { channel._request }; + handled = false; + + for (uint64_t lvl { MT_LOWEST_T1_LVL }; lvl <= TREE_MAX_LEVEL; lvl++) { + + Type_1_info &t1_info { channel._level_n_nodes[lvl] }; + + switch (t1_info.state) { + case Type_1_info::INVALID: + + break; + + case Type_1_info::READ: + + channel._cache_request = Local_cache_request { + Local_cache_request::PENDING, Local_cache_request::READ, false, + t1_info.node.pba, lvl, nullptr }; + + handled = true; + return; + + case Type_1_info::READ_COMPLETE: + + if (t1_info.index < req._mt_edges && + t1_info.entries.nodes[t1_info.index].valid() && + !channel._finished) { + + if (lvl != MT_LOWEST_T1_LVL) { + channel._level_n_nodes[lvl - 1] = { + Type_1_info::READ, t1_info.entries.nodes[t1_info.index], + { }, 0, false, + _node_volatile(t1_info.node, req._current_gen) }; + + } else { + channel._level_1_node = { + Type_2_info::READ, t1_info.entries.nodes[t1_info.index], + { }, 0, + _node_volatile(t1_info.node, req._current_gen) }; + } + + } else { + + if (t1_info.dirty) + t1_info.state = Type_1_info::WRITE; + else + t1_info.state = Type_1_info::COMPLETE; + } + handled = true; + return; + + case Type_1_info::WRITE: + { + uint8_t block_data[BLOCK_SIZE]; + memcpy(&block_data, &t1_info.entries, BLOCK_SIZE); + + if (lvl == req._mt_max_lvl) { + + Type_1_node root_node { }; + root_node.pba = *(uint64_t *)req._mt_root_pba_ptr; + root_node.gen = *(uint64_t *)req._mt_root_gen_ptr; + memcpy(&root_node.hash, (uint8_t *)req._mt_root_hash_ptr, + HASH_SIZE); + + _update_parent( + root_node, block_data, req._current_gen, + t1_info.node.pba); + + *(uint64_t *)req._mt_root_pba_ptr = root_node.pba; + *(uint64_t *)req._mt_root_gen_ptr = root_node.gen; + memcpy((uint8_t *)req._mt_root_hash_ptr, &root_node.hash, + HASH_SIZE); + + channel._root_dirty = true; + + } else { + + Type_1_info &parent { channel._level_n_nodes[lvl + 1] }; + _update_parent( + parent.entries.nodes[parent.index], block_data, + req._current_gen, t1_info.node.pba); + + parent.dirty = true; + } + channel._cache_request = Local_cache_request { + Local_cache_request::PENDING, Local_cache_request::WRITE, + false, t1_info.node.pba, lvl, block_data }; + + handled = true; + return; + } + case Type_1_info::WRITE_COMPLETE: + + if (lvl == req._mt_max_lvl) + channel._state = Channel::COMPLETE; + else + channel._level_n_nodes[lvl + 1].index++; + + channel._cache_request = Local_cache_request { + Local_cache_request::INVALID, Local_cache_request::READ, + false, 0, 0, nullptr }; + + t1_info.state = Type_1_info::INVALID; + handled = true; + return; + + case Type_1_info::COMPLETE: + + if (lvl == req._mt_max_lvl) + channel._state = Channel::COMPLETE; + else + channel._level_n_nodes[lvl + 1].index++; + + t1_info.state = Type_1_info::INVALID; + handled = true; + return; + } + } +} diff --git a/repos/gems/src/lib/tresor/module.cc b/repos/gems/src/lib/tresor/module.cc new file mode 100644 index 0000000000..d4285b6bbf --- /dev/null +++ b/repos/gems/src/lib/tresor/module.cc @@ -0,0 +1,80 @@ +/* + * \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_request(Module_id src_module_id, + Module_request_id src_request_id, + Module_id dst_module_id) +: + _src_module_id { src_module_id }, + _src_request_id { src_request_id }, + _dst_module_id { dst_module_id } +{ } + + +String<32> Module_request::src_request_id_str() const +{ + return + _src_request_id == INVALID_MODULE_REQUEST_ID ? + String<32> { "?" } : String<32> { _src_request_id }; +} + + +String<32> Module_request::dst_request_id_str() const +{ + return + _dst_request_id == INVALID_MODULE_REQUEST_ID ? + String<32> { "?" } : String<32> { _dst_request_id }; +} + + +/********************** + ** Global functions ** + **********************/ + +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 BLOCK_ALLOCATOR: return "block_allocator"; + 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 FT_RESIZING: return "ft_resizing"; + case REQUEST_POOL: return "request_pool"; + default: break; + } + return "?"; +} diff --git a/repos/gems/src/lib/tresor/request_pool.cc b/repos/gems/src/lib/tresor/request_pool.cc new file mode 100644 index 0000000000..0558415a8c --- /dev/null +++ b/repos/gems/src/lib/tresor/request_pool.cc @@ -0,0 +1,803 @@ +/* + * \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 +#include + +using namespace Tresor; + + +char const *Request::op_to_string(Operation op) { return to_string(op); } + + +void Request_pool::_execute_read(Channel &channel, Index_queue &indices, + Slots_index const idx, bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + channel._nr_of_blks = 0; + + channel._prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_READ_VBA, + .pl_idx = idx, + .blk_nr = channel._request.block_number() + channel._nr_of_blks, + .idx = 0 + }; + + channel._state = Channel::State::READ_VBA_AT_SB_CTRL_PENDING; + progress = true; + + break; + case Channel::State::READ_VBA_AT_SB_CTRL_COMPLETE: + if (channel._prim.succ) { + + channel._nr_of_blks += 1; + + if (channel._nr_of_blks < channel._request.count()) { + + channel._prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_READ_VBA, + .pl_idx = idx, + .blk_nr = channel._request.block_number() + channel._nr_of_blks, + .idx = 0 + }; + + channel._state = Channel::State::READ_VBA_AT_SB_CTRL_PENDING; + progress = true; + } else { + channel._request.success(true); + channel._state = Channel::State::COMPLETE; + indices.dequeue(idx); + progress = true; + } + } else { + channel._request.success(false); + channel._state = Channel::State::COMPLETE; + indices.dequeue(idx); + progress = true; + } + break; + default: + break; + } +} + + +void Request_pool::_execute_write(Channel &channel, Index_queue &indices, + Slots_index const idx, bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + + channel._nr_of_blks = 0; + + channel._prim = { + .op = Channel::Generated_prim::Type::WRITE, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_WRITE_VBA, + .pl_idx = idx, + .blk_nr = channel._request.block_number() + channel._nr_of_blks, + .idx = 0 + }; + channel._state = Channel::State::WRITE_VBA_AT_SB_CTRL_PENDING; + progress = true; + break; + + case Channel::State::WRITE_VBA_AT_SB_CTRL_COMPLETE: + + if (channel._prim.succ) { + channel._nr_of_blks += 1; + + if (channel._nr_of_blks < channel._request.count()) { + + channel._prim = { + .op = Channel::Generated_prim::Type::WRITE, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_WRITE_VBA, + .pl_idx = idx, + .blk_nr = channel._request.block_number() + channel._nr_of_blks, + .idx = 0 + }; + + channel._state = Channel::State::WRITE_VBA_AT_SB_CTRL_PENDING; + progress = true; + + } else { + + channel._request.success(true); + channel._state = Channel::State::COMPLETE; + indices.dequeue(idx); + progress = true; + + } + } else { + + channel._request.success(false); + channel._state = Channel::State::COMPLETE; + indices.dequeue(idx); + progress = true; + + } + + break; + default: + break; + } +} + + +void Request_pool::_execute_sync(Channel &channel, Index_queue &indices, + Slots_index const idx, bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + + channel._prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_SYNC, + .pl_idx = idx, + .blk_nr = 0, + .idx = 0 + }; + + channel._state = Channel::State::SYNC_AT_SB_CTRL_PENDING; + progress = true; + + break; + case Channel::State::SYNC_AT_SB_CTRL_COMPLETE: + + if (channel._prim.succ) { + channel._request.success(true); + channel._request.offset(channel._gen); + } else + channel._request.success(false); + + channel._state = Channel::State::COMPLETE; + indices.dequeue(idx); + progress = true; + + break; + default: + break; + } +} + + +char const *Request_pool::_state_to_step_label(Channel::State state) +{ + switch (state) { + case Channel::State::TREE_EXTENSION_STEP_COMPLETE: return "tree ext step"; + default: break; + } + return "?"; +} + + +void Request_pool::_mark_req_failed(Channel &chan, + bool &progress, + char const *str) +{ + error("request_pool: request (", chan._request, + ") failed at step \"", str, "\""); + + chan._request.success(false); + chan._state = Channel::COMPLETE; + progress = true; +} + + +bool Request_pool::_handle_failed_generated_req(Channel &chan, + bool &progress) +{ + if (chan._prim.succ) + return false; + + _mark_req_failed(chan, progress, _state_to_step_label(chan._state)); + return true; +} + + +void Request_pool::_mark_req_successful(Channel &chan, + Slots_index idx, + bool &progress) +{ + chan._request.success(true); + chan._state = Channel::COMPLETE; + _indices.dequeue(idx); + progress = true; +} + + +void Request_pool::_execute_extend_tree(Channel &chan, + Slots_index idx, + Channel::State tree_ext_step_pending, + bool &progress) +{ + switch (chan._state) { + case Channel::SUBMITTED: + + chan._prim = { + .op = Generated_prim::Type::READ, + .succ = false, + .tg = Channel::TAG_POOL_SB_CTRL_TREE_EXT_STEP, + .pl_idx = idx, + .blk_nr = 0, + .idx = 0 + }; + chan._state = tree_ext_step_pending; + progress = true; + break; + + case Channel::TREE_EXTENSION_STEP_COMPLETE: + + if (_handle_failed_generated_req(chan, progress)) + break; + + if (chan._request_finished) { + + _mark_req_successful(chan, idx, progress); + + } else { + + chan._nr_of_requests_preponed = 0; + chan._state = Channel::PREPONE_REQUESTS_PENDING; + progress = true; + } + break; + + case Channel::PREPONE_REQUESTS_PENDING: + { + bool requests_preponed { false }; + bool at_req_that_cannot_be_preponed { false }; + + while (chan._nr_of_requests_preponed < MAX_NR_OF_REQUESTS_PREPONED_AT_A_TIME && + !at_req_that_cannot_be_preponed && + !_indices.item_is_tail(idx)) + { + Pool_index const next_idx { _indices.next_item(idx) }; + switch (_channels[next_idx]._request.operation()) { + case Request::READ: + case Request::WRITE: + case Request::SYNC: + case Request::DISCARD_SNAPSHOT: + + _indices.move_one_item_towards_tail(idx); + chan._nr_of_requests_preponed++; + requests_preponed = true; + progress = true; + break; + + default: + + at_req_that_cannot_be_preponed = true; + break; + } + } + if (!requests_preponed) { + + chan._state = Channel::PREPONE_REQUESTS_COMPLETE; + progress = true; + } + break; + } + case Channel::PREPONE_REQUESTS_COMPLETE: + + chan._prim = { + .op = Generated_prim::Type::READ, + .succ = false, + .tg = Channel::TAG_POOL_SB_CTRL_TREE_EXT_STEP, + .pl_idx = idx, + .blk_nr = 0, + .idx = 0 + }; + chan._state = tree_ext_step_pending; + progress = true; + break; + + default: + + break; + } +} + + +void Request_pool::_execute_rekey(Channel &chan, + Index_queue &indices, + Slots_index idx, + bool &progress) +{ + Request &req { chan._request }; + + switch (chan._state) { + case Channel::State::SUBMITTED: + + chan._prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_INIT_REKEY, + .pl_idx = idx, + .blk_nr = 0, + .idx = 0 + }; + chan._state = Channel::State::REKEY_INIT_PENDING; + progress = true; + break; + + case Channel::State::SUBMITTED_RESUME_REKEYING: + + chan._prim = { }; + chan._nr_of_requests_preponed = 0; + chan._state = Channel::State::PREPONE_REQUESTS_PENDING; + progress = true; + break; + + case Channel::State::REKEY_INIT_COMPLETE: + + if (!chan._prim.succ) { + class Exception_1 { }; + throw Exception_1 { }; + } + chan._nr_of_requests_preponed = 0; + chan._state = Channel::State::PREPONE_REQUESTS_PENDING; + progress = true; + break; + + case Channel::State::REKEY_VBA_COMPLETE: + + if (!chan._prim.succ) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (chan._request_finished) { + + req.success(true); + chan._state = Channel::State::COMPLETE; + _indices.dequeue(idx); + progress = true; + break; + + } else { + + chan._nr_of_requests_preponed = 0; + chan._state = Channel::State::PREPONE_REQUESTS_PENDING; + progress = true; + break; + } + + case Channel::State::PREPONE_REQUESTS_PENDING: + { + bool requests_preponed { false }; + while (true) { + + bool exit_loop { false }; + + if (chan._nr_of_requests_preponed >= MAX_NR_OF_REQUESTS_PREPONED_AT_A_TIME || + indices.item_is_tail(idx)) + break; + + Pool_index const next_idx { indices.next_item(idx) }; + switch (_channels[next_idx]._request.operation()) { + case Request::READ: + case Request::WRITE: + case Request::SYNC: + case Request::DISCARD_SNAPSHOT: + + indices.move_one_item_towards_tail(idx); + chan._nr_of_requests_preponed++; + requests_preponed = true; + progress = true; + break; + + default: + + exit_loop = true; + break; + } + if (exit_loop) + break; + } + if (!requests_preponed) { + chan._state = Channel::State::PREPONE_REQUESTS_COMPLETE; + progress = true; + } + break; + } + case Channel::State::PREPONE_REQUESTS_COMPLETE: + + chan._prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_REKEY_VBA, + .pl_idx = idx, + .blk_nr = 0, + .idx = 0 + }; + chan._state = Channel::State::REKEY_VBA_PENDING; + progress = true; + break; + + default: + + break; + } +} + + +void Request_pool::_execute_initialize(Channel &channel, Index_queue &indices, + Slots_index const idx, bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + + channel._prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_INITIALIZE, + .pl_idx = idx, + .blk_nr = 0, + .idx = 0 + }; + + channel._state = Channel::State::INITIALIZE_SB_CTRL_PENDING; + progress = true; + + break; + + case Channel::State::INITIALIZE_SB_CTRL_COMPLETE: + + if (not channel._prim.succ) { + class Initialize_primitive_not_successfull { }; + throw Initialize_primitive_not_successfull { }; + } + + switch (channel._sb_state) { + case Superblock::INVALID: + class Initialize_sb_ctrl_invalid { }; + throw Initialize_sb_ctrl_invalid { }; + + break; + case Superblock::NORMAL: + + indices.dequeue(idx); + channel.invalidate(); + progress = true; + + break; + + case Superblock::REKEYING: + + class Exception_rekeying { }; + throw Exception_rekeying { }; + channel._request = Tresor::Request(Request::Operation::REKEY, + false, 0, 0, 0, 0, 0, 0, + INVALID_MODULE_ID, + INVALID_MODULE_REQUEST_ID); + indices.enqueue(idx); + progress = true; + + break; + case Superblock::EXTENDING_VBD: + + class Exception_ext_vbd { }; + throw Exception_ext_vbd { }; + channel._state = Channel::State::SUBMITTED; + + channel._request = Tresor::Request(Request::Operation::EXTEND_VBD, + false, 0, 0, 0, 0, 0, 0, + INVALID_MODULE_ID, + INVALID_MODULE_REQUEST_ID); + + indices.enqueue(idx); + + progress = true; + + break; + case Superblock::EXTENDING_FT: + + class Exception_ext_ft { }; + throw Exception_ext_ft { }; + channel._state = Channel::State::SUBMITTED; + + channel._request = Tresor::Request(Request::Operation::EXTEND_FT, + false, 0, 0, 0, 0, 0, 0, + INVALID_MODULE_ID, + INVALID_MODULE_REQUEST_ID); + + indices.enqueue(idx); + + progress = true; + + break; + } + + break; + default: + break; + } +} + + +void Request_pool::_execute_deinitialize(Channel &channel, Index_queue &indices, + Slots_index const idx, bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + + channel._prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_POOL_SB_CTRL_DEINITIALIZE, + .pl_idx = idx, + .blk_nr = 0, + .idx = 0 + }; + + channel._state = Channel::State::DEINITIALIZE_SB_CTRL_PENDING; + progress = true; + + break; + + case Channel::State::DEINITIALIZE_SB_CTRL_COMPLETE: + + if (not channel._prim.succ) { + class Deinitialize_primitive_not_successfull { }; + throw Deinitialize_primitive_not_successfull { }; + } + + channel._request.success(true); + channel._state = Channel::State::COMPLETE; + indices.dequeue(idx); + progress = true; + + break; + default: + break; + } +} + + +void Request_pool::execute(bool &progress) +{ + if (_indices.empty()) + return; + + class Not_implemented { }; + + auto const idx = _indices.head(); + + if (idx >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &channel = _channels[idx]; + Request &request = { channel._request }; + + switch (request.operation()) { + case Tresor::Request::Operation::READ: _execute_read(channel, _indices, idx, progress); break; + case Tresor::Request::Operation::WRITE: _execute_write(channel, _indices, idx, progress); break; + case Tresor::Request::Operation::SYNC: _execute_sync(channel, _indices, idx, progress); break; + case Tresor::Request::Operation::REKEY: _execute_rekey(channel, _indices, idx, progress); break; + case Tresor::Request::Operation::EXTEND_VBD: _execute_extend_tree(channel, idx, Channel::VBD_EXTENSION_STEP_PENDING, progress); break; + case Tresor::Request::Operation::EXTEND_FT: _execute_extend_tree(channel, idx, Channel::FT_EXTENSION_STEP_PENDING, progress); break; + case Tresor::Request::Operation::INITIALIZE: _execute_initialize(channel, _indices, idx, progress); break; + case Tresor::Request::Operation::DEINITIALIZE: _execute_deinitialize(channel, _indices, idx, progress); break; + case Tresor::Request::Operation::CREATE_SNAPSHOT: throw Not_implemented { }; + case Tresor::Request::Operation::DISCARD_SNAPSHOT: throw Not_implemented { }; + default: break; + } +} + + +void Request_pool::submit_request(Module_request &mod_req) +{ + for (Module_request_id idx { 0 }; idx < NR_OF_CHANNELS; idx++) { + if (_channels[idx]._state == Channel::INVALID) { + Request &req { *static_cast(&mod_req) }; + switch (req.operation()) { + case Request::INITIALIZE: + + class Exception_1 { }; + throw Exception_1 { }; + + case Request::SYNC: + case Request::READ: + case Request::WRITE: + case Request::DEINITIALIZE: + case Request::REKEY: + case Request::EXTEND_VBD: + case Request::EXTEND_FT: + + mod_req.dst_request_id(idx); + _channels[idx]._state = Channel::SUBMITTED; + _channels[idx]._request = req; + _indices.enqueue((Slots_index)idx); + return; + + default: + + class Exception_2 { }; + throw Exception_2 { }; + } + } + } + class Exception_3 { }; + throw Exception_3 { }; +} + + +bool Request_pool::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + if (_indices.empty()) + return false; + + Slots_index const idx { _indices.head() }; + Channel const &chan { _channels[idx] }; + Superblock_control_request::Type scr_type; + + switch (chan._state) { + case Channel::READ_VBA_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::READ_VBA; break; + case Channel::WRITE_VBA_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::WRITE_VBA; break; + case Channel::SYNC_AT_SB_CTRL_PENDING: scr_type = Superblock_control_request::SYNC; break; + case Channel::INITIALIZE_SB_CTRL_PENDING: scr_type = Superblock_control_request::INITIALIZE; break; + case Channel::DEINITIALIZE_SB_CTRL_PENDING: scr_type = Superblock_control_request::DEINITIALIZE; break; + case Channel::REKEY_INIT_PENDING: scr_type = Superblock_control_request::INITIALIZE_REKEYING; break; + case Channel::REKEY_VBA_PENDING: scr_type = Superblock_control_request::REKEY_VBA; break; + case Channel::VBD_EXTENSION_STEP_PENDING: scr_type = Superblock_control_request::VBD_EXTENSION_STEP; break; + case Channel::FT_EXTENSION_STEP_PENDING: scr_type = Superblock_control_request::FT_EXTENSION_STEP; break; + default: return false; + } + Superblock_control_request::create( + buf_ptr, buf_size, REQUEST_POOL, idx, scr_type, + chan._request.offset(), chan._request.tag(), + chan._request.count(), chan._prim.blk_nr); + + return true; +} + + +void Request_pool::_drop_generated_request(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (chan._state) { + case Channel::READ_VBA_AT_SB_CTRL_PENDING: chan._state = Channel::READ_VBA_AT_SB_CTRL_IN_PROGRESS; break; + case Channel::WRITE_VBA_AT_SB_CTRL_PENDING: chan._state = Channel::WRITE_VBA_AT_SB_CTRL_IN_PROGRESS; break; + case Channel::SYNC_AT_SB_CTRL_PENDING: chan._state = Channel::SYNC_AT_SB_CTRL_IN_PROGRESS; break; + case Channel::REKEY_INIT_PENDING: chan._state = Channel::REKEY_INIT_IN_PROGRESS; break; + case Channel::REKEY_VBA_PENDING: chan._state = Channel::REKEY_VBA_IN_PROGRESS; break; + case Channel::VBD_EXTENSION_STEP_PENDING: chan._state = Channel::TREE_EXTENSION_STEP_IN_PROGRESS; break; + case Channel::FT_EXTENSION_STEP_PENDING: chan._state = Channel::TREE_EXTENSION_STEP_IN_PROGRESS; break; + case Channel::CREATE_SNAP_AT_SB_CTRL_PENDING: chan._state = Channel::CREATE_SNAP_AT_SB_CTRL_IN_PROGRESS; break; + case Channel::DISCARD_SNAP_AT_SB_CTRL_PENDING: chan._state = Channel::DISCARD_SNAP_AT_SB_CTRL_IN_PROGRESS; break; + case Channel::INITIALIZE_SB_CTRL_PENDING: chan._state = Channel::INITIALIZE_SB_CTRL_IN_PROGRESS; break; + case Channel::DEINITIALIZE_SB_CTRL_PENDING: chan._state = Channel::DEINITIALIZE_SB_CTRL_IN_PROGRESS; break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } +} + + +void Request_pool::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (mod_req.dst_module_id()) { + case SUPERBLOCK_CONTROL: + { + Superblock_control_request &gen_req { *static_cast(&mod_req) }; + chan._prim.succ = gen_req.success(); + switch (chan._state) { + case Channel::READ_VBA_AT_SB_CTRL_IN_PROGRESS: chan._state = Channel::READ_VBA_AT_SB_CTRL_COMPLETE; break; + case Channel::WRITE_VBA_AT_SB_CTRL_IN_PROGRESS: chan._state = Channel::WRITE_VBA_AT_SB_CTRL_COMPLETE; break; + case Channel::SYNC_AT_SB_CTRL_IN_PROGRESS: chan._state = Channel::SYNC_AT_SB_CTRL_COMPLETE; break; + case Channel::TREE_EXTENSION_STEP_IN_PROGRESS: + chan._state = Channel::TREE_EXTENSION_STEP_COMPLETE; + chan._request_finished = gen_req.request_finished(); + break; + case Channel::CREATE_SNAP_AT_SB_CTRL_IN_PROGRESS: + chan._state = Channel::CREATE_SNAP_AT_SB_CTRL_COMPLETE; + class Exception_6 { }; + throw Exception_6 { }; + break; + case Channel::DISCARD_SNAP_AT_SB_CTRL_IN_PROGRESS: + chan._state = Channel::DISCARD_SNAP_AT_SB_CTRL_COMPLETE; + class Exception_4 { }; + throw Exception_4 { }; + break; + case Channel::INITIALIZE_SB_CTRL_IN_PROGRESS: + chan._sb_state = gen_req.sb_state(); + chan._state = Channel::INITIALIZE_SB_CTRL_COMPLETE; + break; + case Channel::DEINITIALIZE_SB_CTRL_IN_PROGRESS: chan._state = Channel::DEINITIALIZE_SB_CTRL_COMPLETE; break; + case Channel::REKEY_INIT_IN_PROGRESS: chan._state = Channel::REKEY_INIT_COMPLETE; break; + case Channel::REKEY_VBA_IN_PROGRESS: + chan._request_finished = gen_req.request_finished(); + chan._state = Channel::REKEY_VBA_COMPLETE; + break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } + break; + } + default: + class Exception_5 { }; + throw Exception_5 { }; + } +} + + +Request_pool::Request_pool() +{ + Slots_index const idx { 0 }; + _channels[idx]._state = Channel::SUBMITTED; + _channels[idx]._request = Request { + Request::INITIALIZE, false, 0, 0, 0, 0, 0, 0, + INVALID_MODULE_ID, INVALID_MODULE_REQUEST_ID }; + + _indices.enqueue(idx); +} + + +bool Request_pool::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._request.operation() != Request::INVALID && + channel._state == Channel::COMPLETE) { + + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Request_pool::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + if (chan._request.operation() == Request::INVALID || + chan._state != Channel::COMPLETE) { + + class Exception_2 { }; + throw Exception_2 { }; + } + chan = Channel { }; +} diff --git a/repos/gems/src/lib/tresor/sb_check.cc b/repos/gems/src/lib/tresor/sb_check.cc new file mode 100644 index 0000000000..16b2547028 --- /dev/null +++ b/repos/gems/src/lib/tresor/sb_check.cc @@ -0,0 +1,505 @@ +/* + * \brief Module for checking all hashes of a superblock and its hash trees + * \author Martin Stein + * \date 2023-05-03 + */ + +/* + * 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. + */ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include +#include +#include + +using namespace Tresor; + + +/********************** + ** Sb_check_request ** + **********************/ + +Sb_check_request::Sb_check_request(Module_id src_module_id, + Module_request_id src_request_id) +: + Module_request { src_module_id, src_request_id, SB_CHECK } +{ } + + +void Sb_check_request::create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type) +{ + Sb_check_request req { src_module_id, src_request_id }; + req._type = (Type)req_type; + + if (sizeof(req) > buf_size) { + class Bad_size_0 { }; + throw Bad_size_0 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); +} + + +char const *Sb_check_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + case CHECK: return "check"; + } + return "?"; +} + + +/************** + ** Sb_check ** + **************/ + +char const *Sb_check::_state_to_step_label(Channel::Sb_slot_state state) +{ + switch (state) { + case Channel::READ_DONE: return "read"; + case Channel::VBD_CHECK_DONE: return "vbd check"; + case Channel::FT_CHECK_DONE: return "ft check"; + case Channel::MT_CHECK_DONE: return "mt check"; + default: break; + } + return "?"; +} + + +bool Sb_check::_handle_failed_generated_req(Channel &chan, + bool &progress) +{ + if (chan._gen_prim_success) + return false; + + _mark_req_failed( + chan, progress, _state_to_step_label(chan._sb_slot_state)); + + return true; +} + +void Sb_check::_execute_check(Channel &chan, + bool &progress) +{ + switch (chan._state) { + case Channel::INSPECT_SBS: + + switch (chan._sb_slot_state) { + case Channel::INIT: + + chan._sb_slot_state = Channel::READ_STARTED; + chan._gen_prim_blk_nr = chan._sb_slot_idx; + progress = true; + break; + + case Channel::READ_DONE: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Snapshot &snap { + chan._sb_slot.snapshots.items[chan._sb_slot.curr_snap] }; + + if (chan._sb_slot.valid() && + snap.gen > chan._highest_gen) { + + chan._highest_gen = snap.gen; + chan._last_sb_slot_idx = chan._sb_slot_idx; + } + if (chan._sb_slot_idx < MAX_SUPERBLOCK_INDEX) { + + chan._sb_slot_idx++; + chan._sb_slot_state = Channel::INIT; + progress = true; + + } else { + + chan._state = Channel::CHECK_SB; + chan._sb_slot_idx = chan._last_sb_slot_idx; + chan._sb_slot_state = Channel::INIT; + progress = true; + + if (VERBOSE_CHECK) + log("check superblock ", chan._sb_slot_idx); + } + break; + } + default: + + break; + } + break; + + case Channel::CHECK_SB: + + switch (chan._sb_slot_state) { + case Channel::INIT: + + chan._sb_slot_state = Channel::READ_STARTED; + chan._gen_prim_blk_nr = chan._sb_slot_idx; + progress = true; + + if (VERBOSE_CHECK) + log(" read superblock"); + + break; + + case Channel::READ_DONE: + + if (_handle_failed_generated_req(chan, progress)) + break; + + if (chan._sb_slot.valid()) { + + Snapshot &snap { + chan._sb_slot.snapshots.items[chan._snap_idx] }; + + if (snap.valid) { + + chan._sb_slot_state = Channel::VBD_CHECK_STARTED; + chan._gen_prim_blk_nr = snap.pba; + progress = true; + + if (VERBOSE_CHECK) + log(" check snap ", chan._snap_idx, " (", snap, ")"); + + } else { + + chan._sb_slot_state = Channel::VBD_CHECK_DONE; + progress = true; + + if (VERBOSE_CHECK) + log(" skip snap ", chan._snap_idx, + " as it is unused"); + } + } else { + + chan._sb_slot_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(" skip superblock as it is unused"); + } + break; + + case Channel::VBD_CHECK_DONE: + + if (_handle_failed_generated_req(chan, progress)) + break; + + if (chan._snap_idx < MAX_SNAP_IDX) { + + chan._snap_idx++; + chan._sb_slot_state = Channel::READ_DONE; + progress = true; + + } else { + + chan._snap_idx = 0; + chan._gen_prim_blk_nr = chan._sb_slot.free_number; + chan._sb_slot_state = Channel::FT_CHECK_STARTED; + progress = true; + + if (VERBOSE_CHECK) + log(" check free tree"); + } + break; + + case Channel::FT_CHECK_DONE: + + if (_handle_failed_generated_req(chan, progress)) + break; + + chan._sb_slot_state = Channel::MT_CHECK_STARTED; + progress = true; + + if (VERBOSE_CHECK) + log(" check meta tree"); + + break; + + case Channel::MT_CHECK_DONE: + + if (_handle_failed_generated_req(chan, progress)) + break; + + _mark_req_successful(chan, progress); + break; + + case Channel::DONE: + + break; + + default: + + break; + } + break; + + default: + + break; + } +} + + +void Sb_check::_mark_req_failed(Channel &chan, + bool &progress, + char const *str) +{ + error("sb check: request (", chan._request, ") failed at step \"", str, "\""); + chan._request._success = false; + chan._sb_slot_state = Channel::DONE; + progress = true; +} + + +void Sb_check::_mark_req_successful(Channel &chan, + bool &progress) +{ + Request &req { chan._request }; + req._success = true; + chan._sb_slot_state = Channel::DONE; + progress = true; +} + + +bool Sb_check::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._sb_slot_state == Channel::DONE) { + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Sb_check::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._sb_slot_state != Channel::DONE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._sb_slot_state = Channel::INACTIVE; +} + + +bool Sb_check::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel &chan { _channels[id] }; + + if (chan._sb_slot_state == Channel::INACTIVE) + continue; + + switch (chan._sb_slot_state) { + case Channel::READ_STARTED: + + construct_in_buf( + buf_ptr, buf_size, SB_CHECK, id, + Block_io_request::READ, 0, 0, 0, + chan._gen_prim_blk_nr, 0, 1, &chan._sb_slot, + nullptr); + + return true; + + case Channel::VBD_CHECK_STARTED: + { + Snapshot const &snap { + chan._sb_slot.snapshots.items[chan._snap_idx] }; + + construct_in_buf( + buf_ptr, buf_size, SB_CHECK, id, + Vbd_check_request::CHECK, snap.max_level, + chan._sb_slot.degree - 1, + snap.nr_of_leaves, + Type_1_node { snap.pba, snap.gen, snap.hash }); + + return true; + } + case Channel::FT_CHECK_STARTED: + + construct_in_buf( + buf_ptr, buf_size, SB_CHECK, id, + Ft_check_request::CHECK, + (Tree_level_index)chan._sb_slot.free_max_level, + (Tree_degree)chan._sb_slot.free_degree - 1, + (Number_of_leaves)chan._sb_slot.free_leaves, + Type_1_node { + chan._sb_slot.free_number, + chan._sb_slot.free_gen, + chan._sb_slot.free_hash }); + + return true; + + case Channel::MT_CHECK_STARTED: + + construct_in_buf( + buf_ptr, buf_size, SB_CHECK, id, + Ft_check_request::CHECK, + (Tree_level_index)chan._sb_slot.meta_max_level, + (Tree_degree)chan._sb_slot.meta_degree - 1, + (Number_of_leaves)chan._sb_slot.meta_leaves, + Type_1_node { + chan._sb_slot.meta_number, + chan._sb_slot.meta_gen, + chan._sb_slot.meta_hash }); + + return true; + + default: + break; + } + } + return false; +} + + +void Sb_check::_drop_generated_request(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_0 { }; + throw Exception_0 { }; + } + Channel &chan { _channels[id] }; + switch (chan._sb_slot_state) { + case Channel::READ_STARTED: chan._sb_slot_state = Channel::READ_DROPPED; break; + case Channel::VBD_CHECK_STARTED: chan._sb_slot_state = Channel::VBD_CHECK_DROPPED; break; + case Channel::FT_CHECK_STARTED: chan._sb_slot_state = Channel::FT_CHECK_DROPPED; break; + case Channel::MT_CHECK_STARTED: chan._sb_slot_state = Channel::MT_CHECK_DROPPED; break; + default: + class Exception_4 { }; + throw Exception_4 { }; + } +} + + +void Sb_check::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (mod_req.dst_module_id()) { + case BLOCK_IO: + { + Block_io_request &gen_req { *static_cast(&mod_req) }; + chan._gen_prim_success = gen_req.success(); + switch (chan._sb_slot_state) { + case Channel::READ_DROPPED: chan._sb_slot_state = Channel::READ_DONE; break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } + break; + } + case VBD_CHECK: + { + Vbd_check_request &gen_req { *static_cast(&mod_req) }; + chan._gen_prim_success = gen_req.success(); + switch (chan._sb_slot_state) { + case Channel::VBD_CHECK_DROPPED: chan._sb_slot_state = Channel::VBD_CHECK_DONE; break; + default: + class Exception_3 { }; + throw Exception_3 { }; + } + break; + } + case FT_CHECK: + { + Ft_check_request &gen_req { *static_cast(&mod_req) }; + chan._gen_prim_success = gen_req.success(); + switch (chan._sb_slot_state) { + case Channel::FT_CHECK_DROPPED: chan._sb_slot_state = Channel::FT_CHECK_DONE; break; + case Channel::MT_CHECK_DROPPED: chan._sb_slot_state = Channel::MT_CHECK_DONE; break; + default: + class Exception_3 { }; + throw Exception_3 { }; + } + break; + } + default: + class Exception_8 { }; + throw Exception_8 { }; + } +} + + +bool Sb_check::ready_to_submit_request() +{ + for (Channel &chan : _channels) { + if (chan._sb_slot_state == Channel::INACTIVE) + return true; + } + return false; +} + + +void Sb_check::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + Channel &chan { _channels[id] }; + if (chan._sb_slot_state == Channel::INACTIVE) { + req.dst_request_id(id); + chan = Channel { }; + chan._request = *static_cast(&req); + chan._sb_slot_state = Channel::INIT; + return; + } + } + class Exception_1 { }; + throw Exception_1 { }; +} + + +void Sb_check::execute(bool &progress) +{ + for (Channel &chan : _channels) { + + if (chan._sb_slot_state == Channel::INACTIVE) + continue; + + Request &req { chan._request }; + switch (req._type) { + case Request::CHECK: + + _execute_check(chan, progress); + break; + + default: + + class Exception_1 { }; + throw Exception_1 { }; + } + } +} diff --git a/repos/gems/src/lib/tresor/sb_initializer.cc b/repos/gems/src/lib/tresor/sb_initializer.cc new file mode 100644 index 0000000000..24d00f5a7d --- /dev/null +++ b/repos/gems/src/lib/tresor/sb_initializer.cc @@ -0,0 +1,725 @@ +/* + * \brief Module for initializing the superblocks of a new Tresor + * \author Josef Soentgen + * \date 2023-03-14 + */ + +/* + * 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. + */ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include +#include +#include +#include +#include +#include + +using namespace Tresor; + + +Sb_initializer_request::Sb_initializer_request(Module_id src_module_id, + Module_request_id src_request_id) +: + Module_request { src_module_id, src_request_id, SB_INITIALIZER } +{ } + + +void Sb_initializer_request::create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + Tree_level_index vbd_max_level_idx, + Tree_degree vbd_max_child_idx, + Number_of_leaves vbd_nr_of_leaves, + Tree_level_index ft_max_level_idx, + Tree_degree ft_max_child_idx, + Number_of_leaves ft_nr_of_leaves, + Tree_level_index mt_max_level_idx, + Tree_degree mt_max_child_idx, + Number_of_leaves mt_nr_of_leaves) +{ + Sb_initializer_request req { src_module_id, src_request_id }; + + req._type = (Type)req_type; + req._vbd_max_level_idx = vbd_max_level_idx; + req._vbd_max_child_idx = vbd_max_child_idx; + req._vbd_nr_of_leaves = vbd_nr_of_leaves; + req._ft_max_level_idx = ft_max_level_idx; + req._ft_max_child_idx = ft_max_child_idx; + req._ft_nr_of_leaves = ft_nr_of_leaves; + req._mt_max_level_idx = mt_max_level_idx; + req._mt_max_child_idx = mt_max_child_idx; + req._mt_nr_of_leaves = mt_nr_of_leaves; + + if (sizeof(req) > buf_size) { + class Bad_size_0 { }; + throw Bad_size_0 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); +} + + +char const *Sb_initializer_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + case INIT: return "init"; + } + return "?"; +} + + +void Sb_initializer::_populate_sb_slot(Channel &channel, + Physical_block_address first, + Number_of_blocks num) +{ + Superblock &sb = channel._sb; + + Request const &req = channel._request; + Type_1_node const &vbd_node = channel._vbd_node; + Type_1_node const &ft_node = channel._ft_node; + Type_1_node const &mt_node = channel._mt_node; + + sb.state = Superblock::NORMAL; + sb.snapshots.items[0] = Snapshot { + .hash = vbd_node.hash, + .pba = vbd_node.pba, + .gen = 0, + .nr_of_leaves = req._vbd_nr_of_leaves, + .max_level = req._vbd_max_level_idx, + .valid = true, + .id = 0, + .keep = false + }; + + sb.rekeying_vba = 0; + sb.resizing_nr_of_pbas = 0; + sb.resizing_nr_of_leaves = 0; + memset(&sb.previous_key, 0, sizeof(sb.previous_key)); + sb.current_key = channel._key_cipher; + sb.curr_snap = 0; + sb.degree = req._vbd_max_child_idx; + sb.first_pba = first; + sb.nr_of_pbas = num; + sb.last_secured_generation = 0; + sb.free_gen = 0; + sb.free_number = ft_node.pba; + sb.free_hash = ft_node.hash; + sb.free_max_level = req._ft_max_level_idx; + sb.free_degree = req._ft_max_child_idx; + sb.free_leaves = req._ft_nr_of_leaves; + sb.meta_gen = 0; + sb.meta_number = mt_node.pba; + sb.meta_hash = mt_node.hash; + sb.meta_max_level = req._mt_max_level_idx; + sb.meta_degree = req._mt_max_child_idx; + sb.meta_leaves = req._mt_nr_of_leaves; +} + + +extern uint64_t block_allocator_first_block(); +extern uint64_t block_allocator_nr_of_blks(); + + +void Sb_initializer::_execute(Channel &channel, + bool &progress) +{ + + using CS = Channel::State; + + switch (channel._state) { + case CS::IN_PROGRESS: + + if (channel._sb_slot_index == 0) { + channel._state = CS::VBD_REQUEST_PENDING; + } else { + memset(&channel._sb_slot, 0, sizeof(channel._sb_slot)); + memcpy(&channel._sb_slot, &channel._sb, sizeof(channel._sb)); + channel._state = CS::WRITE_REQUEST_PENDING; + } + progress = true; + break; + + case CS::VBD_REQUEST_COMPLETE: + + channel._state = CS::FT_REQUEST_PENDING; + progress = true; + break; + + case CS::FT_REQUEST_COMPLETE: + + channel._state = CS::MT_REQUEST_PENDING; + progress = true; + break; + + case CS::MT_REQUEST_COMPLETE: + + channel._state = CS::TA_REQUEST_CREATE_KEY_PENDING; + progress = true; + break; + + case CS::TA_REQUEST_CREATE_KEY_COMPLETE: + + channel._state = CS::TA_REQUEST_ENCRYPT_KEY_PENDING; + progress = true; + break; + + case CS::TA_REQUEST_ENCRYPT_KEY_COMPLETE: + + _populate_sb_slot(channel, + Physical_block_address { block_allocator_first_block() } - NR_OF_SUPERBLOCK_SLOTS, + Number_of_blocks { (uint32_t)block_allocator_nr_of_blks() + NR_OF_SUPERBLOCK_SLOTS }); + memcpy(&channel._sb_slot, &channel._sb, sizeof(channel._sb)); + calc_sha256_4k_hash(&channel._sb_slot, (void*)&channel._sb_hash); + + channel._state = CS::WRITE_REQUEST_PENDING; + progress = true; + break; + + case CS::WRITE_REQUEST_COMPLETE: + + channel._state = CS::SYNC_REQUEST_PENDING; + progress = true; + break; + + case CS::SYNC_REQUEST_COMPLETE: + + if (channel._sb_slot_index == 0) { + channel._state = CS::TA_REQUEST_SECURE_SB_PENDING; + } else { + channel._state = CS::SLOT_COMPLETE; + } + progress = true; + break; + + case CS::TA_REQUEST_SECURE_SB_COMPLETE: + + channel._state = CS::SLOT_COMPLETE; + progress = true; + break; + default: + break; + } + + /* finished */ + if (channel._sb_slot_index == NR_OF_SUPERBLOCK_SLOTS) + _mark_req_successful(channel, progress); +} + + +void Sb_initializer::_execute_init(Channel &channel, + bool &progress) +{ + using CS = Channel::State; + + switch (channel._state) { + case CS::SUBMITTED: + + /* + * Reset the index on every new job as it is + * indicator for a finished job. + */ + channel._sb_slot_index = 0; + + channel._state = Channel::PENDING; + progress = true; + return; + + case CS::PENDING: + + /* + * Remove residual data here as we will end up + * here for every SB slot. + */ + channel.clean_data(); + + channel._state = Channel::IN_PROGRESS; + progress = true; + return; + + case CS::IN_PROGRESS: + + _execute(channel, progress); + return; + + case CS::SLOT_COMPLETE: + + if (channel._sb_slot_index < NR_OF_SUPERBLOCK_SLOTS) { + ++channel._sb_slot_index; + channel._state = Channel::PENDING; + progress = true; + } + return; + + case CS::FT_REQUEST_COMPLETE: + + _execute(channel, progress); + return; + + case CS::MT_REQUEST_COMPLETE: + + _execute(channel, progress); + return; + + case CS::VBD_REQUEST_COMPLETE: + + _execute(channel, progress); + return; + + case CS::SYNC_REQUEST_COMPLETE: + + _execute(channel, progress); + return; + + case CS::TA_REQUEST_CREATE_KEY_COMPLETE: + + _execute(channel, progress); + return; + + case CS::TA_REQUEST_ENCRYPT_KEY_COMPLETE: + + _execute(channel, progress); + return; + + case CS::TA_REQUEST_SECURE_SB_COMPLETE: + + _execute(channel, progress); + return; + + case CS::WRITE_REQUEST_COMPLETE: + + _execute(channel, progress); + return; + + default: + /* + * Omit other states related to FT/MT/VBD as + * those are handled via Module API. + */ + return; + } +} + + +void Sb_initializer::_mark_req_failed(Channel &channel, + bool &progress, + char const *str) +{ + error("request failed: failed to ", str); + channel._request._success = false; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Sb_initializer::_mark_req_successful(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + + req._success = true; + + channel._state = Channel::COMPLETE; + progress = true; +} + + +bool Sb_initializer::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::COMPLETE) { + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Sb_initializer::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._state != Channel::COMPLETE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._state = Channel::INACTIVE; +} + + +bool Sb_initializer::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + using CS = Channel::State; + + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel const &channel { _channels[id] }; + + if (channel._state == CS::INACTIVE) + continue; + + switch (channel._state) { + case CS::VBD_REQUEST_PENDING: + { + Vbd_initializer_request::Type const vbd_initializer_req_type { + Vbd_initializer_request::INIT }; + + Vbd_initializer_request::create( + buf_ptr, buf_size, SB_INITIALIZER, id, + vbd_initializer_req_type, + channel._request._vbd_max_level_idx, + channel._request._vbd_max_child_idx - 1, + channel._request._vbd_nr_of_leaves); + + return true; + } + case CS::FT_REQUEST_PENDING: + { + Ft_initializer_request::Type const ft_initializer_req_type { + Ft_initializer_request::INIT }; + + Ft_initializer_request::create( + buf_ptr, buf_size, SB_INITIALIZER, id, + ft_initializer_req_type, + channel._request._ft_max_level_idx, + channel._request._ft_max_child_idx - 1, + channel._request._ft_nr_of_leaves); + + return true; + } + case CS::MT_REQUEST_PENDING: + { + Ft_initializer_request::Type const ft_initializer_req_type { + Ft_initializer_request::INIT }; + + Ft_initializer_request::create( + buf_ptr, buf_size, SB_INITIALIZER, id, + ft_initializer_req_type, + channel._request._ft_max_level_idx, + channel._request._ft_max_child_idx - 1, + channel._request._ft_nr_of_leaves); + + return true; + } + case CS::WRITE_REQUEST_PENDING: + { + Block_io_request::Type const block_io_req_type { + Block_io_request::WRITE }; + + construct_in_buf( + buf_ptr, buf_size, SB_INITIALIZER, id, block_io_req_type, 0, 0, + 0, channel._sb_slot_index, 0, 1, (void*)&channel._sb_slot, + nullptr); + + return true; + } + case CS::SYNC_REQUEST_PENDING: + { + Block_io_request::Type const block_io_req_type { + Block_io_request::SYNC }; + + construct_in_buf( + buf_ptr, buf_size, SB_INITIALIZER, id, + block_io_req_type, 0, 0, 0, + channel._sb_slot_index, 0, + 0, nullptr, nullptr); + + return true; + } + case CS::TA_REQUEST_CREATE_KEY_PENDING: + { + Trust_anchor_request::Type const trust_anchor_req_type { + Trust_anchor_request::CREATE_KEY }; + + Trust_anchor_request::create( + buf_ptr, buf_size, SB_INITIALIZER, id, + trust_anchor_req_type, + nullptr, nullptr, nullptr, nullptr); + + return true; + } + case CS::TA_REQUEST_ENCRYPT_KEY_PENDING: + { + Trust_anchor_request::Type const trust_anchor_req_type { + Trust_anchor_request::ENCRYPT_KEY }; + + Trust_anchor_request::create( + buf_ptr, buf_size, SB_INITIALIZER, id, + trust_anchor_req_type, + (void*)&channel._key_plain.value, + nullptr, nullptr, nullptr); + + return true; + } + case CS::TA_REQUEST_SECURE_SB_PENDING: + { + Trust_anchor_request::Type const trust_anchor_req_type { + Trust_anchor_request::SECURE_SUPERBLOCK }; + + Trust_anchor_request::create( + buf_ptr, buf_size, SB_INITIALIZER, id, + trust_anchor_req_type, + nullptr, nullptr, nullptr, + (void*)&channel._sb_hash); + + return true; + } + default: + break; + } + } + return false; +} + + +void Sb_initializer::_drop_generated_request(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Bad_id { }; + throw Bad_id { }; + } + switch (_channels[id]._state) { + case Channel::VBD_REQUEST_PENDING: + _channels[id]._state = Channel::VBD_REQUEST_IN_PROGRESS; + break; + case Channel::FT_REQUEST_PENDING: + _channels[id]._state = Channel::FT_REQUEST_IN_PROGRESS; + break; + case Channel::MT_REQUEST_PENDING: + _channels[id]._state = Channel::MT_REQUEST_IN_PROGRESS; + break; + case Channel::WRITE_REQUEST_PENDING: + _channels[id]._state = Channel::WRITE_REQUEST_IN_PROGRESS; + break; + case Channel::SYNC_REQUEST_PENDING: + _channels[id]._state = Channel::SYNC_REQUEST_IN_PROGRESS; + break; + case Channel::TA_REQUEST_CREATE_KEY_PENDING: + _channels[id]._state = Channel::TA_REQUEST_CREATE_KEY_IN_PROGRESS; + break; + case Channel::TA_REQUEST_ENCRYPT_KEY_PENDING: + _channels[id]._state = Channel::TA_REQUEST_ENCRYPT_KEY_IN_PROGRESS; + break; + case Channel::TA_REQUEST_SECURE_SB_PENDING: + _channels[id]._state = Channel::TA_REQUEST_SECURE_SB_IN_PROGRESS; + break; + default: + class Exception_1 { }; + throw Exception_1 { }; + } +} + + +void Sb_initializer::generated_request_complete(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &channel = _channels[id]; + + switch (channel._state) { + case Channel::VBD_REQUEST_IN_PROGRESS: + { + if (req.dst_module_id() != VBD_INITIALIZER) { + class Exception_3 { }; + throw Exception_3 { }; + } + Vbd_initializer_request const *vbd_initializer_req = static_cast(&req); + channel._state = Channel::VBD_REQUEST_COMPLETE; + channel._generated_req_success = vbd_initializer_req->success(); + memcpy(&channel._vbd_node, + const_cast(vbd_initializer_req)->root_node(), + sizeof(Type_1_node)); + + break; + } + case Channel::FT_REQUEST_IN_PROGRESS: + { + if (req.dst_module_id() != FT_INITIALIZER) { + class Exception_4 { }; + throw Exception_4 { }; + } + Ft_initializer_request const *ft_initializer_req = static_cast(&req); + channel._state = Channel::FT_REQUEST_COMPLETE; + channel._generated_req_success = ft_initializer_req->success(); + memcpy(&channel._ft_node, + const_cast(ft_initializer_req)->root_node(), + sizeof(Type_1_node)); + + break; + } + case Channel::MT_REQUEST_IN_PROGRESS: + { + if (req.dst_module_id() != FT_INITIALIZER) { + class Exception_5 { }; + throw Exception_5 { }; + } + channel._state = Channel::MT_REQUEST_COMPLETE; + Ft_initializer_request const *ft_initializer_req = static_cast(&req); + + memcpy(&channel._mt_node, + const_cast(ft_initializer_req)->root_node(), + sizeof(Type_1_node)); + + channel._generated_req_success = + ft_initializer_req->success(); + break; + } + case Channel::TA_REQUEST_CREATE_KEY_IN_PROGRESS: + { + if (req.dst_module_id() != TRUST_ANCHOR) { + class Exception_6 { }; + throw Exception_6 { }; + } + Trust_anchor_request const *trust_anchor_req = static_cast(&req); + channel._state = Channel::TA_REQUEST_CREATE_KEY_COMPLETE; + channel._generated_req_success = trust_anchor_req->success(); + memcpy(&channel._key_plain.value, + const_cast(trust_anchor_req)->key_plaintext_ptr(), + sizeof(channel._key_plain.value)); + + break; + } + case Channel::TA_REQUEST_ENCRYPT_KEY_IN_PROGRESS: + { + if (req.dst_module_id() != TRUST_ANCHOR) { + class Exception_7 { }; + throw Exception_7 { }; + } + channel._state = Channel::TA_REQUEST_ENCRYPT_KEY_COMPLETE; + Trust_anchor_request const *trust_anchor_req = + static_cast(&req); + + /* store and set ID to copy later on */ + memcpy(&channel._key_cipher.value, + const_cast(trust_anchor_req)->key_ciphertext_ptr(), + sizeof(channel._key_cipher.value)); + channel._key_cipher.id = 1; + + channel._generated_req_success = + trust_anchor_req->success(); + break; + } + case Channel::TA_REQUEST_SECURE_SB_IN_PROGRESS: + { + if (req.dst_module_id() != TRUST_ANCHOR) { + class Exception_8 { }; + throw Exception_8 { }; + } + channel._state = Channel::TA_REQUEST_SECURE_SB_COMPLETE; + Trust_anchor_request const *trust_anchor_req = + static_cast(&req); + + channel._generated_req_success = + trust_anchor_req->success(); + break; + } + case Channel::WRITE_REQUEST_IN_PROGRESS: + { + if (req.dst_module_id() != BLOCK_IO) { + class Exception_9 { }; + throw Exception_9 { }; + } + channel._state = Channel::WRITE_REQUEST_COMPLETE; + Block_io_request const *block_io_req = + static_cast(&req); + + channel._generated_req_success = + block_io_req->success(); + break; + } + case Channel::SYNC_REQUEST_IN_PROGRESS: + { + if (req.dst_module_id() != BLOCK_IO) { + class Exception_10 { }; + throw Exception_10 { }; + } + channel._state = Channel::SYNC_REQUEST_COMPLETE; + Block_io_request const *block_io_req = + static_cast(&req); + + channel._generated_req_success = + block_io_req->success(); + break; + } + default: + class Exception_2 { }; + throw Exception_2 { }; + } +} + + +Sb_initializer::Sb_initializer() +{ } + + +bool Sb_initializer::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::INACTIVE) + return true; + } + return false; +} + + +void Sb_initializer::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + if (_channels[id]._state == Channel::INACTIVE) { + req.dst_request_id(id); + _channels[id]._request = *static_cast(&req); + _channels[id]._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} + + +void Sb_initializer::execute(bool &progress) +{ + for (Channel &channel : _channels) { + + if (channel._state == Channel::INACTIVE) + continue; + + Request &req { channel._request }; + switch (req._type) { + case Request::INIT: + + _execute_init(channel, progress); + + break; + default: + + class Exception_1 { }; + throw Exception_1 { }; + } + } +} diff --git a/repos/gems/src/lib/tresor/sha256_4k_hash.cc b/repos/gems/src/lib/tresor/sha256_4k_hash.cc new file mode 100644 index 0000000000..cdaf384b7f --- /dev/null +++ b/repos/gems/src/lib/tresor/sha256_4k_hash.cc @@ -0,0 +1,52 @@ +/* + * \brief Calculate SHA256 hash over data blocks of a size of 4096 bytes + * \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. + */ + +/* base includes */ +#include + +/* libcrypto */ +#include + +/* tresor includes */ +#include + +using namespace Genode; +using namespace Tresor; + + +bool Tresor::check_sha256_4k_hash(void const *data_ptr, + void const *exp_hash_ptr) +{ + uint8_t got_hash[32]; + calc_sha256_4k_hash(data_ptr, &got_hash); + return !memcmp(&got_hash, exp_hash_ptr, sizeof(got_hash)); +} + + +void Tresor::calc_sha256_4k_hash(void const * const data_ptr, + void * const hash_ptr) +{ + SHA256_CTX context { }; + if (!SHA256_Init(&context)) { + class Calc_sha256_4k_hash_init_error { }; + throw Calc_sha256_4k_hash_init_error { }; + } + if (!SHA256_Update(&context, data_ptr, 4096)) { + class Calc_sha256_4k_hash_update_error { }; + throw Calc_sha256_4k_hash_update_error { }; + } + if (!SHA256_Final(static_cast(hash_ptr), &context)) { + class Calc_sha256_4k_hash_final_error { }; + throw Calc_sha256_4k_hash_final_error { }; + } +} diff --git a/repos/gems/src/lib/tresor/superblock_control.cc b/repos/gems/src/lib/tresor/superblock_control.cc new file mode 100644 index 0000000000..d82111b60a --- /dev/null +++ b/repos/gems/src/lib/tresor/superblock_control.cc @@ -0,0 +1,2051 @@ +/* + * \brief Module for management of the superblocks + * \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. + */ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include +#include +#include +#include +#include +#include + +using namespace Tresor; + + +/******************************** + ** Superblock_control_request ** + ********************************/ + +void Superblock_control_request::create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t client_req_offset, + uint64_t client_req_tag, + Number_of_blocks nr_of_blks, + uint64_t vba) +{ + Superblock_control_request req { src_module_id, src_request_id }; + + req._type = (Type)req_type; + req._client_req_offset = client_req_offset; + req._client_req_tag = client_req_tag; + req._nr_of_blks = nr_of_blks; + req._vba = vba; + + if (sizeof(req) > buf_size) { + class Bad_size_0 { }; + throw Bad_size_0 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); +} + + +Superblock_control_request:: +Superblock_control_request(Module_id src_module_id, + Module_request_id src_request_id) +: + Module_request { src_module_id, src_request_id, SUPERBLOCK_CONTROL } +{ } + + +char const *Superblock_control_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + 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"; + } + return "?"; +} + + +/************************ + ** Superblock_control ** + ************************/ + +void Superblock_control::_mark_req_failed(Channel &chan, + bool &progress, + char const *str) +{ + error("sb control: request (", chan._request, ") failed at step \"", str, "\""); + chan._request._success = false; + chan._state = Channel::COMPLETED; + progress = true; +} + + +void Superblock_control::_mark_req_successful(Channel &chan, + bool &progress) +{ + chan._request._success = true; + chan._state = Channel::COMPLETED; + progress = true; +} + + +Virtual_block_address Superblock_control::max_vba() const +{ + if (_sb.valid()) + return _sb.snapshots.items[_sb.curr_snap].nr_of_leaves - 1; + else + return 0; +} + + +Virtual_block_address Superblock_control::rekeying_vba() const +{ + return _sb.rekeying_vba; +} + + +Virtual_block_address Superblock_control::resizing_nr_of_pbas() const +{ + return _sb.resizing_nr_of_pbas; +} + + +void Superblock_control::_execute_read_vba(Channel &channel, + uint64_t const job_idx, + Superblock const &sb, + bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + switch (sb.state) { + case Superblock::REKEYING: { + Virtual_block_address const vba = channel._request._vba; + + if (vba < sb.rekeying_vba) + channel._curr_key_plaintext.id = sb.current_key.id; + else + channel._curr_key_plaintext.id = sb.previous_key.id; + + break; + } + case Superblock::NORMAL: + { + Virtual_block_address const vba = channel._request._vba; + if (vba > max_vba()) { + channel._request._success = false; + channel._state = Channel::State::COMPLETED; + progress = true; + return; + } + channel._curr_key_plaintext.id = sb.current_key.id; + break; + } + case Superblock::EXTENDING_FT: + case Superblock::EXTENDING_VBD: + channel._curr_key_plaintext.id = sb.current_key.id; + break; + case Superblock::INVALID: + class Superblock_not_valid { }; + throw Superblock_not_valid { }; + + break; + } + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_VBD_RKG_READ_VBA, + .blk_nr = channel._request._vba, + .idx = job_idx + }; + + channel._state = Channel::State::READ_VBA_AT_VBD_PENDING; + progress = true; + + if (VERBOSE_VBA_ACCESS) + log("read vba ", channel._request._vba, + ": snap ", (Snapshot_index)_sb.curr_snap, + " key ", (Key_id)channel._curr_key_plaintext.id); + + break; + case Channel::State::READ_VBA_AT_VBD_COMPLETED: + channel._request._success = channel._generated_prim.succ; + channel._state = Channel::State::COMPLETED; + progress = true; + + break; + default: + break; + } +} + + +void Superblock_control::_execute_write_vba(Channel &channel, + uint64_t const job_idx, + Superblock &sb, + Generation const &curr_gen, + bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + switch (sb.state) { + case Superblock::REKEYING: { + Virtual_block_address const vba = channel._request._vba; + + if (vba < sb.rekeying_vba) + channel._curr_key_plaintext.id = sb.current_key.id; + else + channel._curr_key_plaintext.id = sb.previous_key.id; + + break; + } + case Superblock::NORMAL: + { + Virtual_block_address const vba = channel._request._vba; + if (vba > max_vba()) { + channel._request._success = false; + channel._state = Channel::State::COMPLETED; + progress = true; + return; + } + channel._curr_key_plaintext.id = sb.current_key.id; + break; + } + case Superblock::EXTENDING_FT: + case Superblock::EXTENDING_VBD: + channel._curr_key_plaintext.id = sb.current_key.id; + + break; + case Superblock::INVALID: + class Superblock_not_valid_write { }; + throw Superblock_not_valid_write { }; + + break; + } + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::WRITE, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_VBD_RKG_WRITE_VBA, + .blk_nr = channel._request._vba, + .idx = job_idx + }; + + channel._state = Channel::State::WRITE_VBA_AT_VBD_PENDING; + progress = true; + + if (VERBOSE_VBA_ACCESS) + log("write vba ", channel._request._vba, + ": snap ", (Snapshot_index)_sb.curr_snap, + " key ", (Key_id)channel._curr_key_plaintext.id); + + break; + case Channel::State::WRITE_VBA_AT_VBD_COMPLETED: + if (sb.snapshots.items[sb.curr_snap].gen < curr_gen) { + + sb.curr_snap = + sb.snapshots.idx_of_invalid_or_lowest_gen_evictable_snap( + curr_gen, sb.last_secured_generation); + + sb.snapshots.items[sb.curr_snap] = channel._snapshots.items[0]; + sb.snapshots.items[sb.curr_snap].keep = false; + } else if (sb.snapshots.items[sb.curr_snap].gen == curr_gen) { + sb.snapshots.items[sb.curr_snap] = channel._snapshots.items[0]; + } else { + class Superblock_write_vba_at_vbd { }; + throw Superblock_write_vba_at_vbd { }; + } + + channel._request._success = channel._generated_prim.succ; + channel._state = Channel::State::COMPLETED; + progress = true; + + break; + default: + break; + } +} + + +void Superblock_control::_discard_disposable_snapshots(Snapshots &snapshots, + Generation const curr_gen, + Generation const last_secured_gen) +{ + for (auto &snapshot : snapshots.items) + { + if (snapshot.valid && !snapshot.keep && + snapshot.gen != curr_gen && snapshot.gen != last_secured_gen) + snapshot.valid = false; + } +} + + +void Superblock_control::_init_sb_without_key_values(Superblock const &sb_in, + Superblock &sb_out) +{ + sb_out.state = sb_in.state; + sb_out.rekeying_vba = sb_in.rekeying_vba; + sb_out.resizing_nr_of_pbas = sb_in.resizing_nr_of_pbas; + sb_out.resizing_nr_of_leaves = sb_in.resizing_nr_of_leaves; + sb_out.first_pba = sb_in.first_pba; + sb_out.nr_of_pbas = sb_in.nr_of_pbas; + memset(&sb_out.previous_key.value, 0, sizeof(sb_out.previous_key.value)); + sb_out.previous_key.id = sb_in.previous_key.id; + memset(&sb_out.current_key.value, 0, sizeof(sb_out.current_key.value)); + sb_out.current_key.id = sb_in.current_key.id; + sb_out.snapshots = sb_in.snapshots; + sb_out.last_secured_generation = sb_in.last_secured_generation; + sb_out.curr_snap = sb_in.curr_snap; + sb_out.degree = sb_in.degree; + sb_out.free_gen = sb_in.free_gen; + sb_out.free_number = sb_in.free_number; + sb_out.free_hash = sb_in.free_hash; + sb_out.free_max_level = sb_in.free_max_level; + sb_out.free_degree = sb_in.free_degree; + sb_out.free_leaves = sb_in.free_leaves; + sb_out.meta_gen = sb_in.meta_gen; + sb_out.meta_number = sb_in.meta_number; + sb_out.meta_hash = sb_in.meta_hash; + sb_out.meta_max_level = sb_in.meta_max_level; + sb_out.meta_degree = sb_in.meta_degree; + sb_out.meta_leaves = sb_in.meta_leaves; +} + + +char const *Superblock_control::_state_to_step_label(Channel::State state) +{ + switch (state) { + case Channel::TREE_EXT_STEP_IN_TREE_COMPLETED: return "tree ext step in tree"; + case Channel::SECURE_SB_COMPLETED: return "secure sb"; + default: break; + } + return "?"; +} + + +bool Superblock_control::_handle_failed_generated_req(Channel &chan, + bool &progress) +{ + if (chan._generated_prim.succ) + return false; + + _mark_req_failed(chan, progress, _state_to_step_label(chan._state)); + return true; +} + + +void Superblock_control::_execute_tree_ext_step(Channel &chan, + uint64_t chan_idx, + Superblock::State tree_ext_sb_state, + bool tree_ext_verbose, + Tag tree_ext_tag, + Channel::State tree_ext_pending_state, + String<4> tree_name, + bool &progress) +{ + Request &req { chan._request }; + switch (chan._state) { + case Channel::SUBMITTED: + { + 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(chan, progress, "check number of unused blocks"); + break; + } + if (_sb.state == Superblock::NORMAL) { + + req._request_finished = false; + _sb.state = tree_ext_sb_state; + _sb.resizing_nr_of_pbas = req._nr_of_blks; + _sb.resizing_nr_of_leaves = 0; + chan._pba = last_used_pba + 1; + + if (tree_ext_verbose) + log(tree_name, " ext init: pbas ", chan._pba, "..", + chan._pba + (Number_of_blocks)_sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)_sb.resizing_nr_of_leaves); + + _secure_sb_init(chan, chan_idx, progress); + break; + + } else if (_sb.state == tree_ext_sb_state) { + + chan._pba = last_used_pba + 1; + req._nr_of_blks = _sb.resizing_nr_of_pbas; + + if (tree_ext_verbose) + log(tree_name, " ext step: pbas ", chan._pba, "..", + chan._pba + (Number_of_blocks)_sb.resizing_nr_of_pbas - 1, + " leaves ", (Number_of_blocks)_sb.resizing_nr_of_leaves); + + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = tree_ext_tag, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = tree_ext_pending_state; + progress = true; + break; + + } else { + + _mark_req_failed(chan, progress, "check superblock state"); + break; + } + break; + } + case Channel::TREE_EXT_STEP_IN_TREE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + if (req._nr_of_blks >= _sb.resizing_nr_of_pbas) { + _mark_req_failed(chan, 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 (chan._pba != new_first_unused_pba) { + _mark_req_failed(chan, 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 += chan._nr_of_leaves; + + if (tree_name == "vbd") { + + _sb.snapshots = chan._snapshots; + _sb.curr_snap = chan._snapshots.newest_snapshot_idx(); + + } else if (tree_name == "ft") { + + _sb.free_gen = chan._ft_root.gen; + _sb.free_number = chan._ft_root.pba; + _sb.free_hash = chan._ft_root.hash; + _sb.free_max_level = chan._ft_max_lvl; + _sb.free_leaves = chan._ft_nr_of_leaves; + + } else { + + class Exception_1 { }; + throw Exception_1 { }; + } + if (req._nr_of_blks == 0) { + + _sb.state = Superblock::NORMAL; + req._request_finished = true; + } + _secure_sb_init(chan, chan_idx, progress); + break; + } + case Channel::ENCRYPT_CURRENT_KEY_COMPLETED: _secure_sb_encr_curr_key_compl(chan, chan_idx, progress); break; + case Channel::ENCRYPT_PREVIOUS_KEY_COMPLETED: _secure_sb_encr_prev_key_compl(chan, chan_idx, progress); break; + case Channel::SYNC_CACHE_COMPLETED: _secure_sb_sync_cache_compl(chan, chan_idx, progress); break; + case Channel::WRITE_SB_COMPLETED: _secure_sb_write_sb_compl(chan, chan_idx, progress); break; + case Channel::SYNC_BLK_IO_COMPLETED: _secure_sb_sync_blk_io_compl(chan, chan_idx, progress); break; + case Channel::SECURE_SB_COMPLETED: + + if (_handle_failed_generated_req(chan, progress)) + break; + + _sb.last_secured_generation = chan._generation; + _mark_req_successful(chan, progress); + break; + + default: + break; + } +} + + + +void Superblock_control::_execute_rekey_vba(Channel &chan, + uint64_t chan_idx, + bool &progress) +{ + Request &req { chan._request }; + + switch (chan._state) { + case Channel::SUBMITTED: + + if (_sb.state != Superblock::REKEYING) { + _mark_req_failed(chan, progress, "check superblock state"); + break; + } + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_SB_CTRL_VBD_RKG_REKEY_VBA, + .blk_nr = _sb.rekeying_vba, + .idx = chan_idx + }; + chan._state = Channel::REKEY_VBA_IN_VBD_PENDING; + progress = true; + + if (VERBOSE_REKEYING) { + log("rekey vba ", (Virtual_block_address)_sb.rekeying_vba, ":"); + log(" update vbd: keys ", (Key_id)_sb.previous_key.id, + ",", (Key_id)_sb.current_key.id, + " generations ", (Generation)_sb.last_secured_generation, + ",", _curr_gen); + } + break; + + case Channel::REKEY_VBA_IN_VBD_COMPLETED: + { + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "rekey vba at vbd"); + break; + } + _sb.snapshots = chan._snapshots; + Number_of_leaves max_nr_of_leaves { 0 }; + + for (Snapshot const &snap : _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._request_finished = false; + _secure_sb_init(chan, chan_idx, progress); + + if (VERBOSE_REKEYING) + log(" secure sb: gen ", _curr_gen); + + } else { + + chan._prev_key_plaintext.id = _sb.previous_key.id; + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_SB_CTRL_CRYPTO_REMOVE_KEY, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING; + progress = true; + + if (VERBOSE_REKEYING) + log(" remove key ", (Key_id)chan._key_plaintext.id); + } + break; + } + case Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED: + + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "remove key at crypto"); + break; + } + _sb.previous_key = { }; + _sb.state = Superblock::NORMAL; + req._request_finished = true; + _secure_sb_init(chan, chan_idx, progress); + + if (VERBOSE_REKEYING) + log(" secure sb: gen ", _curr_gen); + + break; + + case Channel::ENCRYPT_CURRENT_KEY_COMPLETED: _secure_sb_encr_curr_key_compl(chan, chan_idx, progress); break; + case Channel::ENCRYPT_PREVIOUS_KEY_COMPLETED: _secure_sb_encr_prev_key_compl(chan, chan_idx, progress); break; + case Channel::SYNC_CACHE_COMPLETED: _secure_sb_sync_cache_compl(chan, chan_idx, progress); break; + case Channel::WRITE_SB_COMPLETED: _secure_sb_write_sb_compl(chan, chan_idx, progress); break; + case Channel::SYNC_BLK_IO_COMPLETED: _secure_sb_sync_blk_io_compl(chan, chan_idx, progress); break; + case Channel::SECURE_SB_COMPLETED: + + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "secure superblock"); + break; + } + _sb.last_secured_generation = chan._generation; + _mark_req_successful(chan, progress); + break; + + default: + + break; + } +} + + +void Superblock_control::_secure_sb_init(Channel &chan, + uint64_t chan_idx, + bool &progress) +{ + _sb.snapshots.items[_sb.curr_snap].gen = _curr_gen; + _init_sb_without_key_values(_sb, chan._sb_ciphertext()); + chan._key_plaintext = _sb.current_key; + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_SB_CTRL_TA_ENCRYPT_KEY, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = Channel::ENCRYPT_CURRENT_KEY_PENDING; + progress = true; +} + + +void Superblock_control::_secure_sb_encr_curr_key_compl(Channel &chan, + uint64_t chan_idx, + bool &progress) +{ + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "encrypt current key"); + return; + } + switch (_sb.state) { + case Superblock::REKEYING: + + chan._key_plaintext = _sb.previous_key; + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_SB_CTRL_TA_ENCRYPT_KEY, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = Channel::ENCRYPT_PREVIOUS_KEY_PENDING; + progress = true; + break; + + default: + + chan._generated_prim = { + .op = Generated_prim::SYNC, + .succ = false, + .tg = Channel::TAG_SB_CTRL_CACHE, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = Channel::SYNC_CACHE_PENDING; + progress = true; + break; + } +} + + +void Superblock_control::_secure_sb_encr_prev_key_compl(Channel &chan, + uint64_t chan_idx, + bool &progress) +{ + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "encrypt previous key"); + return; + } + chan._generated_prim = { + .op = Generated_prim::SYNC, + .succ = false, + .tg = Channel::TAG_SB_CTRL_CACHE, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = Channel::SYNC_CACHE_PENDING; + progress = true; +} + + +void Superblock_control::_secure_sb_sync_cache_compl(Channel &chan, + uint64_t chan_idx, + bool &progress) +{ + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "sync cache"); + return; + } + chan._generated_prim = { + .op = Generated_prim::WRITE, + .succ = false, + .tg = Channel::TAG_SB_CTRL_BLK_IO_WRITE_SB, + .blk_nr = _sb_idx, + .idx = chan_idx + }; + chan._state = Channel::WRITE_SB_PENDING; + progress = true; +} + + +void Superblock_control::_secure_sb_sync_blk_io_compl(Channel &chan, + uint64_t chan_idx, + bool &progress) +{ + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "sync block io"); + return; + } + calc_sha256_4k_hash(&chan._sb_ciphertext_blk, &chan._hash); + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_SB_CTRL_TA_SECURE_SB, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = Channel::SECURE_SB_PENDING; + if (_sb_idx < MAX_SUPERBLOCK_INDEX) + _sb_idx++; + else + _sb_idx = 0; + + chan._generation = _curr_gen; + _curr_gen++; + progress = true; +} + + +void Superblock_control::_secure_sb_write_sb_compl(Channel &chan, + uint64_t chan_idx, + bool &progress) +{ + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "write superblock"); + return; + } + chan._generated_prim = { + .op = Generated_prim::SYNC, + .succ = false, + .tg = Channel::TAG_SB_CTRL_BLK_IO_SYNC, + .blk_nr = _sb_idx, + .idx = chan_idx + }; + chan._state = Channel::SYNC_BLK_IO_PENDING; + progress = true; +} + + +void +Superblock_control::_execute_initialize_rekeying(Channel &chan, + uint64_t const chan_idx, + bool &progress) +{ + switch (chan._state) { + case Channel::SUBMITTED: + + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_SB_CTRL_TA_CREATE_KEY, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = Channel::CREATE_KEY_PENDING; + progress = true; + break; + + case Channel::CREATE_KEY_COMPLETED: + + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "create key"); + break; + } + if (_sb.state != Superblock::NORMAL) { + _mark_req_failed(chan, progress, "check superblock state"); + break; + } + _sb.state = Superblock::REKEYING; + _sb.rekeying_vba = 0; + _sb.previous_key = _sb.current_key; + _sb.current_key = { + .value = chan._key_plaintext.value, + .id = _sb.previous_key.id + 1 + }; + chan._key_plaintext = _sb.current_key; + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_SB_CTRL_CRYPTO_ADD_KEY, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = Channel::ADD_KEY_AT_CRYPTO_MODULE_PENDING; + progress = true; + + if (VERBOSE_REKEYING) { + log("start rekeying:"); + log(" update sb: keys ", (Key_id)_sb.previous_key.id, + ",", (Key_id)chan._key_plaintext.id); + } + break; + + case Channel::ADD_KEY_AT_CRYPTO_MODULE_COMPLETED: + + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "add key at crypto"); + break; + } + _secure_sb_init(chan, chan_idx, progress); + + if (VERBOSE_REKEYING) + log(" secure sb: gen ", _curr_gen); + + break; + + case Channel::ENCRYPT_CURRENT_KEY_COMPLETED: _secure_sb_encr_curr_key_compl(chan, chan_idx, progress); break; + case Channel::ENCRYPT_PREVIOUS_KEY_COMPLETED: _secure_sb_encr_prev_key_compl(chan, chan_idx, progress); break; + case Channel::SYNC_CACHE_COMPLETED: _secure_sb_sync_cache_compl(chan, chan_idx, progress); break; + case Channel::WRITE_SB_COMPLETED: _secure_sb_write_sb_compl(chan, chan_idx, progress); break; + case Channel::SYNC_BLK_IO_COMPLETED: _secure_sb_sync_blk_io_compl(chan, chan_idx, progress); break; + case Channel::SECURE_SB_COMPLETED: + + if (!chan._generated_prim.succ) { + _mark_req_failed(chan, progress, "secure superblock"); + break; + } + _sb.last_secured_generation = chan._generation; + _mark_req_successful(chan, progress); + break; + + default: + + break; + } +} + + +void Superblock_control::_execute_sync(Channel &channel, + uint64_t const job_idx, + Superblock &sb, + Superblock_index &sb_idx, + Generation &curr_gen, + bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + + _discard_disposable_snapshots( + sb.snapshots, sb.last_secured_generation, curr_gen); + + sb.last_secured_generation = curr_gen; + sb.snapshots.items[sb.curr_snap].gen = curr_gen; + _init_sb_without_key_values(sb, channel._sb_ciphertext()); + + channel._key_plaintext = sb.current_key; + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_TA_ENCRYPT_KEY, + .blk_nr = 0, + .idx = job_idx + }; + channel._state = Channel::State::ENCRYPT_CURRENT_KEY_PENDING; + progress = true; + break; + + case Channel::State::ENCRYPT_CURRENT_KEY_COMPLETED: + + if (!channel._generated_prim.succ) { + class Encrypt_current_key_error { }; + throw Encrypt_current_key_error { }; + } + switch (sb.state) { + case Superblock::REKEYING: + + channel._key_plaintext = sb.previous_key; + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_TA_ENCRYPT_KEY, + .blk_nr = 0, + .idx = job_idx + }; + channel._state = Channel::State::ENCRYPT_PREVIOUS_KEY_PENDING; + progress = true; + break; + + default: + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::SYNC, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_CACHE, + .blk_nr = 0, + .idx = job_idx + }; + channel._state = Channel::State::SYNC_CACHE_PENDING; + progress = true; + break; + } + break; + + case Channel::State::ENCRYPT_PREVIOUS_KEY_COMPLETED: + + if (!channel._generated_prim.succ) { + class Encrypt_previous_key_error { }; + throw Encrypt_previous_key_error { }; + } + channel._generated_prim = { + .op = Channel::Generated_prim::Type::SYNC, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_CACHE, + .blk_nr = 0, + .idx = job_idx + }; + channel._state = Channel::State::SYNC_CACHE_PENDING; + progress = true; + break; + + case Channel::State::SYNC_CACHE_COMPLETED: + + if (!channel._generated_prim.succ) { + class Sync_cache_error { }; + throw Sync_cache_error { }; + } + channel._generated_prim = { + .op = Channel::Generated_prim::Type::WRITE, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_WRITE_SB, + .blk_nr = sb_idx, + .idx = job_idx + }; + channel._state = Channel::State::WRITE_SB_PENDING; + progress = true; + break; + + case Channel::State::WRITE_SB_COMPLETED: + + if (!channel._generated_prim.succ) { + class Write_sb_completed_error { }; + throw Write_sb_completed_error { }; + } + channel._generated_prim = { + .op = Channel::Generated_prim::Type::SYNC, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_SYNC, + .blk_nr = sb_idx, + .idx = job_idx + }; + channel._state = Channel::State::SYNC_BLK_IO_PENDING; + progress = true; + break; + + case Channel::State::SYNC_BLK_IO_COMPLETED: + + if (!channel._generated_prim.succ) { + class Sync_blk_io_completed_error { }; + throw Sync_blk_io_completed_error { }; + } + calc_sha256_4k_hash(&channel._sb_ciphertext_blk, &channel._hash); + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_TA_SECURE_SB, + .blk_nr = 0, + .idx = job_idx + }; + channel._state = Channel::State::SECURE_SB_PENDING; + + if (sb_idx < MAX_SUPERBLOCK_INDEX) + sb_idx = sb_idx + 1; + else + sb_idx = 0; + + channel._generation = curr_gen; + curr_gen = curr_gen + 1; + progress = true; + break; + + case Channel::State::SECURE_SB_COMPLETED: + + if (!channel._generated_prim.succ) { + class Secure_sb_completed_error { }; + throw Secure_sb_completed_error { }; + } + sb.last_secured_generation = channel._generation; + channel._request._success = true; + channel._state = Channel::State::COMPLETED; + progress = true; + break; + + default: + + break; + } +} + + +void Superblock_control::_execute_initialize(Channel &channel, + uint64_t const job_idx, + Superblock &sb, + Superblock_index &sb_idx, + Generation &curr_gen, + bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + + channel._sb_found = false; + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_TA_LAST_SB_HASH, + .blk_nr = 0, + .idx = job_idx + }; + channel._state = Channel::State::MAX_SB_HASH_PENDING; + progress = true; + break; + + case Channel::State::MAX_SB_HASH_COMPLETED: + + channel._read_sb_idx = 0; + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_READ_SB, + .blk_nr = channel._read_sb_idx, + .idx = job_idx + }; + channel._state = Channel::State::READ_SB_PENDING; + progress = true; + break; + + case Channel::State::READ_SB_COMPLETED: + + if (!channel._generated_prim.succ) { + class Execute_initialize_error { }; + throw Execute_initialize_error { }; + } + if (channel._sb_ciphertext().state != Superblock::INVALID) { + + Superblock const &cipher { channel._sb_ciphertext() }; + Snapshot_index const snap_index { cipher.snapshots.newest_snapshot_idx() }; + Generation const sb_generation { cipher.snapshots.items[snap_index].gen }; + + if (check_sha256_4k_hash(&channel._sb_ciphertext_blk, channel._hash.bytes)) { + channel._generation = sb_generation; + channel._sb_idx = channel._read_sb_idx; + channel._sb_found = true; + } + } + if (channel._read_sb_idx < MAX_SUPERBLOCK_INDEX) { + + channel._read_sb_idx = channel._read_sb_idx + 1; + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_READ_SB, + .blk_nr = channel._read_sb_idx, + .idx = job_idx + }; + channel._state = Channel::State::READ_SB_PENDING; + progress = true; + + } else { + + if (!channel._sb_found) { + class Execute_initialize_sb_found_error { }; + throw Execute_initialize_sb_found_error { }; + } + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_READ_SB, + .blk_nr = channel._sb_idx, + .idx = job_idx + }; + + channel._state = Channel::State::READ_CURRENT_SB_PENDING; + progress = true; + } + break; + + case Channel::State::READ_CURRENT_SB_COMPLETED: + + if (!channel._generated_prim.succ) { + class Execute_initialize_read_current_sb_error { }; + throw Execute_initialize_read_current_sb_error { }; + } + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_TA_DECRYPT_KEY, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::DECRYPT_CURRENT_KEY_PENDING; + progress = true; + + break; + case Channel::State::DECRYPT_CURRENT_KEY_COMPLETED: + if (!channel._generated_prim.succ) { + class Execute_initialize_decrypt_current_key_error { }; + throw Execute_initialize_decrypt_current_key_error { }; + } + + channel._curr_key_plaintext.id = channel._sb_ciphertext().current_key.id; + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_CRYPTO_ADD_KEY, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING; + progress = true; + + break; + case Channel::State::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED: + if (!channel._generated_prim.succ) { + class Execute_add_current_key_at_crypto_error { }; + throw Execute_add_current_key_at_crypto_error { }; + } + + switch (channel._sb_ciphertext().state) { + case Superblock::INVALID: + class Execute_add_current_key_at_crypto_invalid_error { }; + throw Execute_add_current_key_at_crypto_invalid_error { }; + + break; + case Superblock::REKEYING: + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_TA_DECRYPT_KEY, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::DECRYPT_PREVIOUS_KEY_PENDING; + progress = true; + + break; + case Superblock::NORMAL: + case Superblock::EXTENDING_VBD: + case Superblock::EXTENDING_FT: + + _init_sb_without_key_values(channel._sb_ciphertext(), sb); + + sb.current_key.value = channel._curr_key_plaintext.value; + sb_idx = channel._sb_idx; + curr_gen = channel._generation + 1; + + sb_idx = channel._sb_idx; + curr_gen = channel._generation + 1; + + if (sb.free_max_level < FREE_TREE_MIN_MAX_LEVEL) { + class Execute_add_current_key_at_crypto_max_level_error { }; + throw Execute_add_current_key_at_crypto_max_level_error { }; + } + + channel._request._sb_state = _sb.state; + channel._request._success = true; + + channel._state = Channel::State::COMPLETED; + progress = true; + + break; + } + + break; + case Channel::State::DECRYPT_PREVIOUS_KEY_COMPLETED: + if (!channel._generated_prim.succ) { + class Decrypt_previous_key_error { }; + throw Decrypt_previous_key_error { }; + } + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_CRYPTO_ADD_KEY, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING; + progress = true; + + break; + case Channel::State::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED: + if (!channel._generated_prim.succ) { + class Add_previous_key_at_crypto_module_error { }; + throw Add_previous_key_at_crypto_module_error { }; + } + + _init_sb_without_key_values(channel._sb_ciphertext(), sb); + + sb.current_key.value = channel._curr_key_plaintext.value; + sb.previous_key.value = channel._prev_key_plaintext.value; + + sb_idx = channel._sb_idx; + curr_gen = channel._generation + 1; + + channel._request._sb_state = _sb.state; + channel._request._success = true; + + channel._state = Channel::State::COMPLETED; + progress = true; + + break; + default: + break; + } +} + + +void Superblock_control::_execute_deinitialize(Channel &channel, + uint64_t const job_idx, + Superblock &sb, + Superblock_index &sb_idx, + Generation &curr_gen, + bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + + _discard_disposable_snapshots(sb.snapshots, sb.last_secured_generation, + curr_gen); + + sb.last_secured_generation = curr_gen; + sb.snapshots.items[sb.curr_snap].gen = curr_gen; + + _init_sb_without_key_values(sb, channel._sb_ciphertext()); + channel._key_plaintext = sb.current_key; + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_TA_ENCRYPT_KEY, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::ENCRYPT_CURRENT_KEY_PENDING; + progress = true; + + break; + case Channel::State::ENCRYPT_CURRENT_KEY_COMPLETED: + if (!channel._generated_prim.succ) { + class Deinitialize_encrypt_current_key_error { }; + throw Deinitialize_encrypt_current_key_error { }; + } + + switch (sb.state) { + case Superblock::REKEYING: + channel._key_plaintext = sb.previous_key; + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_TA_ENCRYPT_KEY, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::ENCRYPT_PREVIOUS_KEY_PENDING; + progress = true; + + break; + + default: + channel._generated_prim = { + .op = Channel::Generated_prim::Type::SYNC, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_CACHE, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::SYNC_CACHE_PENDING; + progress = true; + + break; + } + + break; + case Channel::State::ENCRYPT_PREVIOUS_KEY_COMPLETED: + + if (!channel._generated_prim.succ) { + class Deinitialize_encrypt_previous_key_error { }; + throw Deinitialize_encrypt_previous_key_error { }; + } + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::SYNC, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_CACHE, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::SYNC_CACHE_PENDING; + progress = true; + + break; + case Channel::State::SYNC_CACHE_COMPLETED: + + if (!channel._generated_prim.succ) { + class Deinitialize_sync_cache_error { }; + throw Deinitialize_sync_cache_error { }; + } + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::WRITE, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_WRITE_SB, + .blk_nr = sb_idx, + .idx = job_idx + }; + + channel._state = Channel::State::WRITE_SB_PENDING; + progress = true; + + break; + case Channel::State::WRITE_SB_COMPLETED: + + if (!channel._generated_prim.succ) { + class Deinitialize_write_sb_error { }; + throw Deinitialize_write_sb_error { }; + } + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::SYNC, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_BLK_IO_SYNC, + .blk_nr = sb_idx, + .idx = job_idx + }; + + channel._state = Channel::State::SYNC_BLK_IO_PENDING; + progress = true; + + break; + case Channel::State::SYNC_BLK_IO_COMPLETED: + + if (!channel._generated_prim.succ) { + class Deinitialize_sync_blk_io_error { }; + throw Deinitialize_sync_blk_io_error { }; + } + calc_sha256_4k_hash(&channel._sb_ciphertext_blk, &channel._hash); + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_TA_SECURE_SB, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::SECURE_SB_PENDING; + + if (sb_idx < MAX_SUPERBLOCK_INDEX) + sb_idx = sb_idx + 1; + else + sb_idx = 0; + + channel._generation = curr_gen; + curr_gen = curr_gen + 1; + + progress = true; + + break; + case Channel::State::SECURE_SB_COMPLETED: + + if (!channel._generated_prim.succ) { + class Deinitialize_secure_sb_error { }; + throw Deinitialize_secure_sb_error { }; + } + + sb.last_secured_generation = channel._generation; + + channel._request._success = true; + + channel._curr_key_plaintext.id = sb.current_key.id; + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_CRYPTO_REMOVE_KEY, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING; + progress = true; + + break; + case Channel::State::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED: + + if (!channel._generated_prim.succ) { + class Deinitialize_remove_current_key_error { }; + throw Deinitialize_remove_current_key_error { }; + } + + switch (sb.state) { + default: + class Deinitialize_remove_current_key_invalid_error { }; + throw Deinitialize_remove_current_key_invalid_error { }; + break; + case Superblock::REKEYING: + + channel._prev_key_plaintext.id = sb.previous_key.id; + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_SB_CTRL_CRYPTO_REMOVE_KEY, + .blk_nr = 0, + .idx = job_idx + }; + + channel._state = Channel::State::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING; + progress = true; + + break; + case Superblock::NORMAL: + case Superblock::EXTENDING_VBD: + case Superblock::EXTENDING_FT: + + channel._request._success = true; + + channel._state = Channel::State::COMPLETED; + progress = true; + + break; + } + + break; + case Channel::State::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED: + + if (!channel._generated_prim.succ) { + class Deinitialize_remove_previous_key_error { }; + throw Deinitialize_remove_previous_key_error { }; + } + + sb.state = Superblock::INVALID; + + channel._request._success = true; + + channel._state = Channel::State::COMPLETED; + progress = true; + + break; + default: + break; + } +} + + +bool Superblock_control::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (unsigned id = 0; id < NR_OF_CHANNELS; id++) { + + Channel &chan { _channels[id] }; + Request &req { chan._request }; + if (req._type == Request::INVALID) + continue; + + switch (chan._state) { + case Channel::CREATE_KEY_PENDING: + + Trust_anchor_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Trust_anchor_request::CREATE_KEY, nullptr, + nullptr, nullptr, nullptr); + + return 1; + + case Channel::ENCRYPT_CURRENT_KEY_PENDING: + case Channel::ENCRYPT_PREVIOUS_KEY_PENDING: + + Trust_anchor_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Trust_anchor_request::ENCRYPT_KEY, + &chan._key_plaintext.value, nullptr, nullptr, nullptr); + + return 1; + + case Channel::DECRYPT_CURRENT_KEY_PENDING: + + Trust_anchor_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Trust_anchor_request::DECRYPT_KEY, + nullptr, &chan._sb_ciphertext().current_key.value, + nullptr, nullptr); + + return 1; + + case Channel::DECRYPT_PREVIOUS_KEY_PENDING: + + Trust_anchor_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Trust_anchor_request::DECRYPT_KEY, + nullptr, &chan._sb_ciphertext().previous_key.value, + nullptr, nullptr); + + return 1; + + case Channel::SECURE_SB_PENDING: + + Trust_anchor_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Trust_anchor_request::SECURE_SUPERBLOCK, + nullptr, nullptr, nullptr, &chan._hash); + + return 1; + + case Channel::MAX_SB_HASH_PENDING: + + Trust_anchor_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Trust_anchor_request::GET_LAST_SB_HASH, + nullptr, nullptr, nullptr, nullptr); + + return 1; + + case Channel::ADD_KEY_AT_CRYPTO_MODULE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Crypto_request::ADD_KEY, 0, 0, (Key_id)chan._key_plaintext.id, + &chan._key_plaintext.value, 0, 0, nullptr, nullptr); + + return 1; + + case Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Crypto_request::ADD_KEY, 0, 0, (Key_id)chan._curr_key_plaintext.id, + &chan._curr_key_plaintext.value, 0, 0, nullptr, nullptr); + + return 1; + + case Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Crypto_request::ADD_KEY, 0, 0, + (Key_id)chan._prev_key_plaintext.id, &chan._prev_key_plaintext.value, + 0, 0, nullptr, nullptr); + + return 1; + + case Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Crypto_request::REMOVE_KEY, 0, 0, + (Key_id)chan._prev_key_plaintext.id, nullptr, + 0, 0, nullptr, nullptr); + + return 1; + + case Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Crypto_request::REMOVE_KEY, 0, 0, + (Key_id)chan._curr_key_plaintext.id, nullptr, + 0, 0, nullptr, nullptr); + + return 1; + + case Channel::READ_VBA_AT_VBD_PENDING: + + Virtual_block_device_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Virtual_block_device_request::READ_VBA, + req._client_req_offset, req._client_req_tag, + _sb.last_secured_generation, + (addr_t)&_sb.free_number, + (addr_t)&_sb.free_gen, + (addr_t)&_sb.free_hash, + _sb.free_max_level, + _sb.free_degree, + _sb.free_leaves, + (addr_t)&_sb.meta_number, + (addr_t)&_sb.meta_gen, + (addr_t)&_sb.meta_hash, + _sb.meta_max_level, + _sb.meta_degree, + _sb.meta_leaves, + _sb.degree, + max_vba(), + _sb.state == Superblock::REKEYING ? 1 : 0, + req._vba, + &_sb.snapshots.items[_sb.curr_snap], + nullptr, + _sb.degree, 0, 0, + _curr_gen, + chan._curr_key_plaintext.id, 0, 0); + + return 1; + + case Channel::WRITE_VBA_AT_VBD_PENDING: + + Virtual_block_device_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Virtual_block_device_request::WRITE_VBA, + req._client_req_offset, req._client_req_tag, + _sb.last_secured_generation, + (addr_t)&_sb.free_number, + (addr_t)&_sb.free_gen, + (addr_t)&_sb.free_hash, + _sb.free_max_level, + _sb.free_degree, + _sb.free_leaves, + (addr_t)&_sb.meta_number, + (addr_t)&_sb.meta_gen, + (addr_t)&_sb.meta_hash, + _sb.meta_max_level, + _sb.meta_degree, + _sb.meta_leaves, + _sb.degree, + max_vba(), + _sb.state == Superblock::REKEYING ? 1 : 0, + req._vba, + &_sb.snapshots.items[_sb.curr_snap], + nullptr, + _sb.degree, 0, 0, + _curr_gen, + chan._curr_key_plaintext.id, 0, 0); + + return 1; + + case Channel::READ_SB_PENDING: + case Channel::READ_CURRENT_SB_PENDING: + + construct_in_buf( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Block_io_request::READ, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, &chan._sb_ciphertext_blk, + nullptr); + + return true; + + case Channel::SYNC_BLK_IO_PENDING: + case Channel::SYNC_CACHE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Block_io_request::SYNC, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, nullptr, nullptr); + + return true; + + case Channel::WRITE_SB_PENDING: + + construct_in_buf( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Block_io_request::WRITE, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, &chan._sb_ciphertext_blk, + nullptr); + + return true; + + case Channel::REKEY_VBA_IN_VBD_PENDING: + + Virtual_block_device_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Virtual_block_device_request::REKEY_VBA, + req._client_req_offset, req._client_req_tag, + _sb.last_secured_generation, + (addr_t)&_sb.free_number, + (addr_t)&_sb.free_gen, + (addr_t)&_sb.free_hash, + _sb.free_max_level, + _sb.free_degree, + _sb.free_leaves, + (addr_t)&_sb.meta_number, + (addr_t)&_sb.meta_gen, + (addr_t)&_sb.meta_hash, + _sb.meta_max_level, + _sb.meta_degree, + _sb.meta_leaves, + _sb.degree, + max_vba(), + _sb.state == Superblock::REKEYING ? 1 : 0, + _sb.rekeying_vba, + nullptr, + &_sb.snapshots, + _sb.degree, + _sb.previous_key.id, + _sb.current_key.id, + _curr_gen, + chan._curr_key_plaintext.id, 0, 0); + + return 1; + + case Channel::VBD_EXT_STEP_IN_VBD_PENDING: + + Virtual_block_device_request::create( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Virtual_block_device_request::VBD_EXTENSION_STEP, + req._client_req_offset, req._client_req_tag, + _sb.last_secured_generation, + (addr_t)&_sb.free_number, + (addr_t)&_sb.free_gen, + (addr_t)&_sb.free_hash, + _sb.free_max_level, + _sb.free_degree, + _sb.free_leaves, + (addr_t)&_sb.meta_number, + (addr_t)&_sb.meta_gen, + (addr_t)&_sb.meta_hash, + _sb.meta_max_level, + _sb.meta_degree, + _sb.meta_leaves, + _sb.degree, + max_vba(), + _sb.state == Superblock::REKEYING ? 1 : 0, + 0, + nullptr, + &_sb.snapshots, + _sb.degree, + 0, + 0, + _curr_gen, + 0, + _sb.first_pba + _sb.nr_of_pbas, + _sb.resizing_nr_of_pbas); + + return 1; + + case Channel::FT_EXT_STEP_IN_FT_PENDING: + + construct_in_buf( + buf_ptr, buf_size, SUPERBLOCK_CONTROL, id, + Ft_resizing_request::FT_EXTENSION_STEP, _curr_gen, + Type_1_node { _sb.free_number, _sb.free_gen, _sb.free_hash }, + (Tree_level_index)_sb.free_max_level, + (Number_of_leaves)_sb.free_leaves, + (Tree_degree)_sb.free_degree, + (addr_t)&_sb.meta_number, + (addr_t)&_sb.meta_gen, + (addr_t)&_sb.meta_hash, + (Tree_level_index)_sb.meta_max_level, + (Tree_degree)_sb.meta_degree, + (Number_of_leaves)_sb.meta_leaves, + _sb.first_pba + _sb.nr_of_pbas, + (Number_of_blocks)_sb.resizing_nr_of_pbas); + + return 1; + + default: break; + } + } + return false; +} + + +void Superblock_control::_drop_generated_request(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_3 { }; + throw Exception_3 { }; + } + Channel &chan { _channels[id] }; + Request &req { chan._request }; + if (req._type == Request::INVALID) { + class Exception_2 { }; + throw Exception_2 { }; + } + switch (chan._state) { + case Channel::CREATE_KEY_PENDING: chan._state = Channel::CREATE_KEY_IN_PROGRESS; break; + case Channel::ENCRYPT_CURRENT_KEY_PENDING: chan._state = Channel::ENCRYPT_CURRENT_KEY_IN_PROGRESS; break; + case Channel::ENCRYPT_PREVIOUS_KEY_PENDING: chan._state = Channel::ENCRYPT_PREVIOUS_KEY_IN_PROGRESS; break; + case Channel::DECRYPT_CURRENT_KEY_PENDING: chan._state = Channel::DECRYPT_CURRENT_KEY_IN_PROGRESS; break; + case Channel::DECRYPT_PREVIOUS_KEY_PENDING: chan._state = Channel::DECRYPT_PREVIOUS_KEY_IN_PROGRESS; break; + case Channel::SECURE_SB_PENDING: chan._state = Channel::SECURE_SB_IN_PROGRESS; break; + case Channel::MAX_SB_HASH_PENDING: chan._state = Channel::MAX_SB_HASH_IN_PROGRESS; break; + case Channel::ADD_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::ADD_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; + case Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; + case Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; + case Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; + case Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_PENDING: chan._state = Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS; break; + case Channel::READ_VBA_AT_VBD_PENDING: chan._state = Channel::READ_VBA_AT_VBD_IN_PROGRESS; break; + case Channel::WRITE_VBA_AT_VBD_PENDING: chan._state = Channel::WRITE_VBA_AT_VBD_IN_PROGRESS; break; + case Channel::READ_SB_PENDING: chan._state = Channel::READ_SB_IN_PROGRESS; break; + case Channel::READ_CURRENT_SB_PENDING: chan._state = Channel::READ_CURRENT_SB_IN_PROGRESS; break; + case Channel::SYNC_BLK_IO_PENDING: chan._state = Channel::SYNC_BLK_IO_IN_PROGRESS; break; + case Channel::SYNC_CACHE_PENDING: chan._state = Channel::SYNC_CACHE_IN_PROGRESS; break; + case Channel::WRITE_SB_PENDING: chan._state = Channel::WRITE_SB_IN_PROGRESS; break; + case Channel::REKEY_VBA_IN_VBD_PENDING: chan._state = Channel::REKEY_VBA_IN_VBD_IN_PROGRESS; break; + case Channel::VBD_EXT_STEP_IN_VBD_PENDING: chan._state = Channel::VBD_EXT_STEP_IN_VBD_IN_PROGRESS; break; + case Channel::FT_EXT_STEP_IN_FT_PENDING: chan._state = Channel::FT_EXT_STEP_IN_FT_IN_PROGRESS; break; + default: + class Exception_1 { }; + throw Exception_1 { }; + } +} + + +void Superblock_control::execute(bool &progress) +{ + for (unsigned idx = 0; idx < NR_OF_CHANNELS; idx++) { + + Channel &channel = _channels[idx]; + Request &request { channel._request }; + + switch (request._type) { + case Request::READ_VBA: + _execute_read_vba(channel, idx, _sb, progress); + + break; + case Request::WRITE_VBA: + _execute_write_vba(channel, idx, _sb, _curr_gen, progress); + + break; + case Request::SYNC: + _execute_sync(channel, idx, _sb, _sb_idx, _curr_gen, progress); + + break; + case Request::INITIALIZE_REKEYING: _execute_initialize_rekeying(channel, idx, progress); break; + case Request::REKEY_VBA: _execute_rekey_vba(channel, idx, progress); break; + case Request::VBD_EXTENSION_STEP: _execute_tree_ext_step(channel, idx, Superblock::EXTENDING_VBD, VERBOSE_VBD_EXTENSION, Channel::TAG_SB_CTRL_VBD_VBD_EXT_STEP, Channel::VBD_EXT_STEP_IN_VBD_PENDING, "vbd", progress); break; + case Request::FT_EXTENSION_STEP: _execute_tree_ext_step(channel, idx, Superblock::EXTENDING_FT, VERBOSE_FT_EXTENSION, Channel::TAG_SB_CTRL_FT_FT_EXT_STEP, Channel::FT_EXT_STEP_IN_FT_PENDING, "ft", progress); break; + case Request::CREATE_SNAPSHOT: + class Superblock_control_create_snapshot { }; + throw Superblock_control_create_snapshot { }; + + break; + case Request::DISCARD_SNAPSHOT: + class Superblock_control_discard_snapshot { }; + throw Superblock_control_discard_snapshot { }; + + break; + case Request::INITIALIZE: + _execute_initialize(channel, idx, _sb, _sb_idx, _curr_gen, + progress); + + break; + case Request::DEINITIALIZE: + _execute_deinitialize (channel, idx, _sb, _sb_idx, + _curr_gen, progress); + + break; + case Request::INVALID: + break; + } + } +} + + +void Superblock_control::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (mod_req.dst_module_id()) { + case TRUST_ANCHOR: + { + Trust_anchor_request &gen_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = gen_req.success(); + switch (chan._state) { + case Channel::CREATE_KEY_IN_PROGRESS: + chan._state = Channel::CREATE_KEY_COMPLETED; + memcpy(&chan._key_plaintext.value, gen_req.key_plaintext_ptr(), KEY_SIZE); + break; + case Channel::ENCRYPT_CURRENT_KEY_IN_PROGRESS: + chan._state = Channel::ENCRYPT_CURRENT_KEY_COMPLETED; + memcpy(&chan._sb_ciphertext().current_key.value, gen_req.key_ciphertext_ptr(), KEY_SIZE); + break; + case Channel::ENCRYPT_PREVIOUS_KEY_IN_PROGRESS: + chan._state = Channel::ENCRYPT_PREVIOUS_KEY_COMPLETED; + memcpy(&chan._sb_ciphertext().previous_key.value, gen_req.key_ciphertext_ptr(), KEY_SIZE); + break; + case Channel::DECRYPT_CURRENT_KEY_IN_PROGRESS: + chan._state = Channel::DECRYPT_CURRENT_KEY_COMPLETED; + memcpy(&chan._curr_key_plaintext.value, gen_req.key_plaintext_ptr(), KEY_SIZE); + break; + case Channel::DECRYPT_PREVIOUS_KEY_IN_PROGRESS: + chan._state = Channel::DECRYPT_PREVIOUS_KEY_COMPLETED; + memcpy(&chan._prev_key_plaintext.value, gen_req.key_plaintext_ptr(), KEY_SIZE); + break; + case Channel::SECURE_SB_IN_PROGRESS: chan._state = Channel::SECURE_SB_COMPLETED; break; + case Channel::MAX_SB_HASH_IN_PROGRESS: + chan._state = Channel::MAX_SB_HASH_COMPLETED; + memcpy(&chan._hash, gen_req.hash_ptr(), HASH_SIZE); + break; + default: + class Exception_4 { }; + throw Exception_4 { }; + } + break; + } + case CRYPTO: + { + Crypto_request &gen_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = gen_req.success(); + switch (chan._state) { + case Channel::ADD_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::ADD_KEY_AT_CRYPTO_MODULE_COMPLETED; break; + case Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::ADD_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED; break; + case Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::ADD_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED; break; + case Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::REMOVE_PREVIOUS_KEY_AT_CRYPTO_MODULE_COMPLETED; break; + case Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_IN_PROGRESS: chan._state = Channel::REMOVE_CURRENT_KEY_AT_CRYPTO_MODULE_COMPLETED; break; + default: + class Exception_5 { }; + throw Exception_5 { }; + } + break; + } + case VIRTUAL_BLOCK_DEVICE: + { + Virtual_block_device_request &gen_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = gen_req.success(); + switch (chan._state) { + case Channel::READ_VBA_AT_VBD_IN_PROGRESS: chan._state = Channel::READ_VBA_AT_VBD_COMPLETED; break; + case Channel::WRITE_VBA_AT_VBD_IN_PROGRESS: + chan._state = Channel::WRITE_VBA_AT_VBD_COMPLETED; + chan._snapshots.items[0] = *(gen_req.snapshot_ptr()); + break; + case Channel::REKEY_VBA_IN_VBD_IN_PROGRESS: + chan._state = Channel::REKEY_VBA_IN_VBD_COMPLETED; + chan._snapshots = *(gen_req.snapshots_ptr()); + break; + case Channel::VBD_EXT_STEP_IN_VBD_IN_PROGRESS: + chan._state = Channel::TREE_EXT_STEP_IN_TREE_COMPLETED; + chan._snapshots = *(gen_req.snapshots_ptr()); + chan._pba = gen_req.pba(); + chan._request._nr_of_blks = gen_req.nr_of_pbas(); + chan._nr_of_leaves = gen_req.nr_of_leaves(); + break; + default: + class Exception_6 { }; + throw Exception_6 { }; + } + break; + } + case FT_RESIZING: + { + Ft_resizing_request &gen_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = gen_req.success(); + switch (chan._state) { + case Channel::FT_EXT_STEP_IN_FT_IN_PROGRESS: + chan._state = Channel::TREE_EXT_STEP_IN_TREE_COMPLETED; + chan._ft_root = gen_req.ft_root(); + chan._ft_max_lvl = gen_req.ft_max_lvl(); + chan._ft_nr_of_leaves = gen_req.ft_nr_of_leaves(); + chan._pba = gen_req.pba(); + chan._request._nr_of_blks = gen_req.nr_of_pbas(); + chan._nr_of_leaves = gen_req.nr_of_leaves(); + break; + default: + class Exception_16 { }; + throw Exception_16 { }; + } + break; + } + case BLOCK_IO: + { + Block_io_request &gen_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = gen_req.success(); + switch (chan._state) { + case Channel::READ_SB_IN_PROGRESS: chan._state = Channel::READ_SB_COMPLETED; break; + case Channel::READ_CURRENT_SB_IN_PROGRESS: chan._state = Channel::READ_CURRENT_SB_COMPLETED; break; + case Channel::SYNC_BLK_IO_IN_PROGRESS: chan._state = Channel::SYNC_BLK_IO_COMPLETED; break; + case Channel::SYNC_CACHE_IN_PROGRESS: chan._state = Channel::SYNC_CACHE_COMPLETED; break; + case Channel::WRITE_SB_IN_PROGRESS: chan._state = Channel::WRITE_SB_COMPLETED; break; + default: + class Exception_7 { }; + throw Exception_7 { }; + } + break; + } + default: + class Exception_8 { }; + throw Exception_8 { }; + } +} + + +bool Superblock_control::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._request._type != Request::INVALID && + channel._state == Channel::COMPLETED) { + + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Superblock_control::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._request._type == Request::INVALID) { + class Exception_2 { }; + throw Exception_2 { }; + } + if (_channels[id]._state != Channel::COMPLETED) { + class Exception_3 { }; + throw Exception_3 { }; + } + _channels[id]._request._type = Request::INVALID; +} + + +bool Superblock_control::ready_to_submit_request() +{ + for (Channel const &channel : _channels) { + if (channel._request._type == Request::INVALID) + return true; + } + return false; +} + + +void Superblock_control::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + if (_channels[id]._request._type == Request::INVALID) { + req.dst_request_id(id); + _channels[id]._request = *static_cast(&req); + _channels[id]._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} diff --git a/repos/gems/src/lib/tresor/trust_anchor.cc b/repos/gems/src/lib/tresor/trust_anchor.cc new file mode 100644 index 0000000000..c21729223b --- /dev/null +++ b/repos/gems/src/lib/tresor/trust_anchor.cc @@ -0,0 +1,556 @@ +/* + * \brief Module for accessing the systems trust anchor + * \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. + */ + +/* base includes */ +#include + +/* tresor includes */ +#include + +using namespace Tresor; + + +/************************** + ** Trust_anchor_request ** + **************************/ + +void Trust_anchor_request::create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + void *key_plaintext_ptr, + void *key_ciphertext_ptr, + char const *passphrase_ptr, + void *hash_ptr) +{ + Trust_anchor_request req { src_module_id, src_request_id }; + req._type = (Type)req_type; + req._passphrase_ptr = (addr_t)passphrase_ptr; + if (key_plaintext_ptr != nullptr) + memcpy( + &req._key_plaintext, key_plaintext_ptr, + sizeof(req._key_plaintext)); + + if (key_ciphertext_ptr != nullptr) + memcpy( + &req._key_ciphertext, key_ciphertext_ptr, + sizeof(req._key_ciphertext)); + + if (hash_ptr != nullptr) + memcpy(&req._hash, hash_ptr, sizeof(req._hash)); + + if (sizeof(req) > buf_size) { + class Exception_2 { }; + throw Exception_2 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); +} + + +Trust_anchor_request::Trust_anchor_request(Module_id src_module_id, + Module_request_id src_request_id) +: + Module_request { src_module_id, src_request_id, TRUST_ANCHOR } +{ } + + +char const *Trust_anchor_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + case CREATE_KEY: return "create_key"; + case ENCRYPT_KEY: return "encrypt_key"; + case DECRYPT_KEY: return "decrypt_key"; + case SECURE_SUPERBLOCK: return "secure_superblock"; + case GET_LAST_SB_HASH: return "get_last_sb_hash"; + case INITIALIZE: return "initialize"; + } + return "?"; +} + + +/****************** + ** Trust_anchor ** + ******************/ + +void Trust_anchor::_execute_write_read_operation(Vfs::Vfs_handle &file, + String<128> const &file_path, + Channel &channel, + char const *write_buf, + char *read_buf, + size_t read_size, + bool &progress) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::WRITE_PENDING: + + file.seek(channel._file_offset); + channel._state = Channel::WRITE_IN_PROGRESS; + progress = true; + return; + + case Channel::WRITE_IN_PROGRESS: + { + size_t nr_of_written_bytes { 0 }; + + Const_byte_range_ptr src { + write_buf + channel._file_offset, channel._file_size }; + + Write_result const result = + file.fs().write(&file, src, nr_of_written_bytes); + + switch (result) { + + case Write_result::WRITE_ERR_WOULD_BLOCK: + return; + + case Write_result::WRITE_OK: + + channel._file_offset += nr_of_written_bytes; + channel._file_size -= nr_of_written_bytes; + + if (channel._file_size > 0) { + + channel._state = Channel::WRITE_PENDING; + progress = true; + return; + } + channel._state = Channel::READ_PENDING; + channel._file_offset = 0; + channel._file_size = read_size; + progress = true; + return; + + default: + + req._success = false; + error("failed to write file ", file_path); + channel._state = Channel::COMPLETE; + progress = true; + return; + } + } + case Channel::READ_PENDING: + + file.seek(channel._file_offset); + + if (!file.fs().queue_read(&file, channel._file_size)) { + return; + } + channel._state = Channel::READ_IN_PROGRESS; + progress = true; + return; + + case Channel::READ_IN_PROGRESS: + { + size_t nr_of_read_bytes { 0 }; + + Byte_range_ptr dst { + read_buf + channel._file_offset, channel._file_size }; + + Read_result const result { + file.fs().complete_read( &file, dst, nr_of_read_bytes) }; + + switch (result) { + case Read_result::READ_QUEUED: + case Read_result::READ_ERR_WOULD_BLOCK: + + return; + + case Read_result::READ_OK: + + channel._file_offset += nr_of_read_bytes; + channel._file_size -= nr_of_read_bytes; + req._success = true; + + if (channel._file_size > 0) { + + channel._state = Channel::READ_PENDING; + progress = true; + return; + } + channel._state = Channel::COMPLETE; + progress = true; + return; + + default: + + req._success = false; + error("failed to read file ", file_path); + channel._state = Channel::COMPLETE; + return; + } + } + default: + + return; + } +} + + +void Trust_anchor::_execute_write_operation(Vfs::Vfs_handle &file, + String<128> const &file_path, + Channel &channel, + char const *write_buf, + bool &progress, + bool result_via_read) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::WRITE_PENDING: + + file.seek(channel._file_offset); + channel._state = Channel::WRITE_IN_PROGRESS; + progress = true; + return; + + case Channel::WRITE_IN_PROGRESS: + { + size_t nr_of_written_bytes { 0 }; + + Const_byte_range_ptr src { + write_buf + channel._file_offset, channel._file_size }; + + Write_result const result = + file.fs().write(&file, src, nr_of_written_bytes); + + switch (result) { + + case Write_result::WRITE_ERR_WOULD_BLOCK: + return; + + case Write_result::WRITE_OK: + + channel._file_offset += nr_of_written_bytes; + channel._file_size -= nr_of_written_bytes; + + if (channel._file_size > 0) { + + channel._state = Channel::WRITE_PENDING; + progress = true; + return; + } + channel._state = Channel::READ_PENDING; + channel._file_offset = 0; + + if (result_via_read) + channel._file_size = sizeof(_read_buf); + else + channel._file_size = 0; + + progress = true; + return; + + default: + + req._success = false; + error("failed to write file ", file_path); + channel._state = Channel::COMPLETE; + progress = true; + return; + } + } + case Channel::READ_PENDING: + + file.seek(channel._file_offset); + + if (!file.fs().queue_read(&file, channel._file_size)) { + return; + } + channel._state = Channel::READ_IN_PROGRESS; + progress = true; + return; + + case Channel::READ_IN_PROGRESS: + { + size_t nr_of_read_bytes { 0 }; + Byte_range_ptr dst { + _read_buf + channel._file_offset, channel._file_size }; + + Read_result const result { + file.fs().complete_read(&file, dst, nr_of_read_bytes) }; + + switch (result) { + case Read_result::READ_QUEUED: + case Read_result::READ_ERR_WOULD_BLOCK: + + return; + + case Read_result::READ_OK: + + channel._file_offset += nr_of_read_bytes; + channel._file_size -= nr_of_read_bytes; + + if (channel._file_size > 0) { + + channel._state = Channel::READ_PENDING; + progress = true; + return; + } + if (result_via_read) { + req._success = !strcmp(_read_buf, "ok", 3); + } else + req._success = true; + + channel._state = Channel::COMPLETE; + progress = true; + return; + + default: + + req._success = false; + error("failed to read file ", file_path); + channel._state = Channel::COMPLETE; + return; + } + } + default: + + return; + } +} + + +void Trust_anchor::_execute_read_operation(Vfs::Vfs_handle &file, + String<128> const &file_path, + Channel &channel, + char *read_buf, + bool &progress) +{ + Request &req { channel._request }; + switch (channel._state) { + case Channel::READ_PENDING: + + file.seek(channel._file_offset); + + if (!file.fs().queue_read(&file, channel._file_size)) { + return; + } + channel._state = Channel::READ_IN_PROGRESS; + progress = true; + return; + + case Channel::READ_IN_PROGRESS: + { + size_t nr_of_read_bytes { 0 }; + Byte_range_ptr dst { + read_buf + channel._file_offset, channel._file_size }; + + Read_result const result { + file.fs().complete_read(&file, dst, nr_of_read_bytes) }; + + switch (result) { + case Read_result::READ_QUEUED: + case Read_result::READ_ERR_WOULD_BLOCK: + + return; + + case Read_result::READ_OK: + + channel._file_offset += nr_of_read_bytes; + channel._file_size -= nr_of_read_bytes; + req._success = true; + + if (channel._file_size > 0) { + + channel._state = Channel::READ_PENDING; + progress = true; + return; + } + channel._state = Channel::COMPLETE; + progress = true; + return; + + default: + + req._success = false; + error("failed to read file ", file_path); + channel._state = Channel::COMPLETE; + return; + } + } + default: + + return; + } +} + + +void Trust_anchor::execute(bool &progress) +{ + for (Channel &channel : _channels) { + + if (channel._state == Channel::INACTIVE) + continue; + + Request &req { channel._request }; + switch (req._type) { + case Request::INITIALIZE: + + if (channel._state == Channel::SUBMITTED) { + channel._state = Channel::WRITE_PENDING; + channel._file_offset = 0; + channel._file_size = + strlen((char const *)req._passphrase_ptr); + } + _execute_write_operation( + _initialize_file, _initialize_path, channel, + (char const *)req._passphrase_ptr, progress, true); + + break; + + case Request::SECURE_SUPERBLOCK: + + if (channel._state == Channel::SUBMITTED) { + channel._state = Channel::WRITE_PENDING; + channel._file_offset = 0; + channel._file_size = sizeof(req._hash); + } + _execute_write_operation( + _hashsum_file, _hashsum_path, channel, + (char const *)&req._hash, progress, false); + + break; + + case Request::GET_LAST_SB_HASH: + + if (channel._state == Channel::SUBMITTED) { + channel._state = Channel::READ_PENDING; + channel._file_offset = 0; + channel._file_size = sizeof(req._hash); + } + _execute_read_operation( + _hashsum_file, _hashsum_path, channel, + (char *)&req._hash, progress); + + break; + + case Request::CREATE_KEY: + + if (channel._state == Channel::SUBMITTED) { + channel._state = Channel::READ_PENDING; + channel._file_offset = 0; + channel._file_size = sizeof(req._key_plaintext); + } + _execute_read_operation( + _generate_key_file, _generate_key_path, channel, + (char *)req._key_plaintext, progress); + + break; + + case Request::ENCRYPT_KEY: + + if (channel._state == Channel::SUBMITTED) { + channel._state = Channel::WRITE_PENDING; + channel._file_offset = 0; + channel._file_size = sizeof(req._key_plaintext); + } + _execute_write_read_operation( + _encrypt_file, _encrypt_path, channel, + (char const *)req._key_plaintext, + (char *)req._key_ciphertext, + sizeof(req._key_ciphertext), + progress); + + break; + + case Request::DECRYPT_KEY: + + if (channel._state == Channel::SUBMITTED) { + channel._state = Channel::WRITE_PENDING; + channel._file_offset = 0; + channel._file_size = sizeof(req._key_ciphertext); + } + _execute_write_read_operation( + _decrypt_file, _decrypt_path, channel, + (char const *)req._key_ciphertext, + (char *)req._key_plaintext, + sizeof(req._key_plaintext), + progress); + + break; + + default: + + class Exception_1 { }; + throw Exception_1 { }; + } + } +} + + +Trust_anchor::Trust_anchor(Vfs::Env &vfs_env, + Xml_node const &xml_node) +: + _vfs_env { vfs_env }, + _path { xml_node.attribute_value("path", String<128>()) } +{ } + + +bool Trust_anchor::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::COMPLETE) { + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Trust_anchor::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._state != Channel::COMPLETE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._state = Channel::INACTIVE; +} + + +bool Trust_anchor::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::INACTIVE) + return true; + } + return false; +} + +void Trust_anchor::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + if (_channels[id]._state == Channel::INACTIVE) { + req.dst_request_id(id); + _channels[id]._request = *static_cast(&req); + _channels[id]._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} diff --git a/repos/gems/src/lib/tresor/vbd_check.cc b/repos/gems/src/lib/tresor/vbd_check.cc new file mode 100644 index 0000000000..fd171ba6bc --- /dev/null +++ b/repos/gems/src/lib/tresor/vbd_check.cc @@ -0,0 +1,458 @@ +/* + * \brief Module for checking all hashes of a VBD snapshot + * \author Martin Stein + * \date 2023-05-03 + */ + +/* + * 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. + */ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include +#include + +using namespace Tresor; + + +/*********************** + ** Vbd_check_request ** + ***********************/ + +Vbd_check_request::Vbd_check_request(uint64_t src_module_id, + uint64_t src_request_id, + Type type, + Tree_level_index max_lvl, + Tree_node_index max_child_idx, + Number_of_leaves nr_of_leaves, + Type_1_node root) +: + Module_request { src_module_id, src_request_id, VBD_CHECK }, + _type { type }, + _max_lvl { max_lvl }, + _max_child_idx { max_child_idx }, + _nr_of_leaves { nr_of_leaves }, + _root { root } +{ } + + +char const *Vbd_check_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + case CHECK: return "check"; + } + return "?"; +} + + +/*************** + ** Vbd_check ** + ***************/ + +void Vbd_check::_execute_inner_t1_child(Channel &chan, + Type_1_node const &child, + Type_1_level &child_lvl, + Child_state &child_state, + Tree_level_index lvl, + Tree_node_index child_idx, + bool &progress) +{ + Request &req { chan._request }; + if (child_state == Channel::READ_BLOCK) { + + if (!child.valid()) { + + if (req._nr_of_leaves == 0) { + + child_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, + ": expectedly invalid"); + + } else { + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " (", child,"): unexpectedly invalid"); + + _mark_req_failed(chan, progress, "check for valid child"); + } + + } else if (!chan._gen_prim.valid()) { + + chan._gen_prim = { + .success = false, + .tag = Channel::BLOCK_IO, + .blk_nr = child.pba, + .dropped = false }; + + chan._lvl_to_read = lvl - 1; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " (", child, "): load to lvl ", lvl - 1); + + } else if (chan._gen_prim.tag != Channel::BLOCK_IO || + chan._gen_prim.blk_nr != child.pba) { + + class Exception_1 { }; + throw Exception_1 { }; + + } else if (!chan._gen_prim.success) { + + } else { + + for (Child_state &state : child_lvl.children_state) { + state = Channel::READ_BLOCK; + } + chan._gen_prim = { }; + child_state = Channel::CHECK_HASH; + progress = true; + } + + } else if (child_state == Channel::CHECK_HASH) { + + if (child.gen == INITIAL_GENERATION || + check_sha256_4k_hash(&child_lvl.children, &child.hash)) { + + child_state = Channel::DONE; + if (&child_state == &chan._root_state) { + chan._request._success = true; + } + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, ": good hash"); + + } else { + + if (VERBOSE_CHECK) { + + Hash hash; + calc_sha256_4k_hash(&child_lvl.children, &hash); + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " (", child, "): bad hash ", hash); + } + + _mark_req_failed(chan, progress, "check inner hash"); + } + } +} + + +void Vbd_check::_execute_leaf_child(Channel &chan, + Type_1_node const &child, + Block const &child_lvl, + Child_state &child_state, + Tree_level_index lvl, + Tree_node_index child_idx, + bool &progress) +{ + Request &req { chan._request }; + if (child_state == Channel::READ_BLOCK) { + + if (req._nr_of_leaves == 0) { + + if (child.valid()) { + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " (", child, "): unexpectedly valid"); + + _mark_req_failed(chan, progress, "check for unused child"); + + } else { + + child_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, ": expectedly invalid"); + } + + } else if (child.gen == INITIAL_GENERATION) { + + req._nr_of_leaves--; + child_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, ": uninitialized"); + + } else if (!chan._gen_prim.valid()) { + + chan._gen_prim = { + .success = false, + .tag = Channel::BLOCK_IO, + .blk_nr = child.pba, + .dropped = false }; + + chan._lvl_to_read = lvl - 1; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " (", child, "): load to lvl ", lvl - 1); + + } else if (chan._gen_prim.tag != Channel::BLOCK_IO || + chan._gen_prim.blk_nr != child.pba) { + + class Exception_1 { }; + throw Exception_1 { }; + + } else if (!chan._gen_prim.success) { + + } else { + + chan._gen_prim = { }; + child_state = Channel::CHECK_HASH; + progress = true; + } + + } else if (child_state == Channel::CHECK_HASH) { + + if (check_sha256_4k_hash(&child_lvl, &child.hash)) { + + req._nr_of_leaves--; + child_state = Channel::DONE; + progress = true; + + if (VERBOSE_CHECK) + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, ": good hash"); + + } else { + + if (VERBOSE_CHECK) { + + Hash hash; + calc_sha256_4k_hash(&child_lvl, &hash); + log(Level_indent { lvl, req._max_lvl }, + " lvl ", lvl, " child ", child_idx, " (", child, "): bad hash ", hash); + } + + _mark_req_failed(chan, progress, "check leaf hash"); + } + } +} + + +void Vbd_check::_execute_check(Channel &chan, + bool &progress) +{ + Request &req { chan._request }; + for (Tree_level_index lvl { VBD_LOWEST_T1_LVL }; lvl <= req._max_lvl; lvl++) { + for (Tree_node_index child_idx { 0 }; + child_idx <= req._max_child_idx; + child_idx++) { + + Type_1_level &t1_lvl { chan._t1_lvls[lvl] }; + if (t1_lvl.children_state[child_idx] != Channel::DONE) { + + if (lvl == VBD_LOWEST_T1_LVL) + _execute_leaf_child( + chan, + chan._t1_lvls[lvl].children.nodes[child_idx], + chan._leaf_lvl, + chan._t1_lvls[lvl].children_state[child_idx], + lvl, child_idx, progress); + else + _execute_inner_t1_child( + chan, + chan._t1_lvls[lvl].children.nodes[child_idx], + chan._t1_lvls[lvl - 1], + chan._t1_lvls[lvl].children_state[child_idx], + lvl, child_idx, progress); + + return; + } + } + } + if (chan._root_state != Channel::DONE) { + + _execute_inner_t1_child( + chan, req._root, chan._t1_lvls[req._max_lvl], chan._root_state, + req._max_lvl + 1, 0, progress); + + return; + } +} + + +void Vbd_check::_mark_req_failed(Channel &chan, + bool &progress, + char const *str) +{ + error("vbd check: request (", chan._request, ") failed at step \"", str, "\""); + chan._request._success = false; + chan._root_state = Channel::DONE; + progress = true; +} + + +bool Vbd_check::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &chan : _channels) { + + if (chan._request._type != Request::INVALID && + chan._root_state == Channel::DONE) { + + if (sizeof(chan._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &chan._request, sizeof(chan._request)); + return true; + } + } + return false; +} + + +void Vbd_check::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + if (chan._request._type == Request::INVALID && + chan._root_state != Channel::DONE) { + + class Exception_2 { }; + throw Exception_2 { }; + } + chan = Channel { }; +} + + +bool Vbd_check::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel &chan { _channels[id] }; + + if (!chan._gen_prim.valid() || chan._gen_prim.dropped) + continue; + + switch (chan._gen_prim.tag) { + case Channel::BLOCK_IO: + + construct_in_buf( + buf_ptr, buf_size, VBD_CHECK, id, + Block_io_request::READ, 0, 0, 0, + chan._gen_prim.blk_nr, 0, 1, + chan._lvl_to_read == 0 ? + (void *)&chan._leaf_lvl : + (void *)&chan._t1_lvls[chan._lvl_to_read].children, + nullptr); + + return true; + + default: + + class Exception_1 { }; + throw Exception_1 { }; + } + } + return false; +} + + +void Vbd_check::_drop_generated_request(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_0 { }; + throw Exception_0 { }; + } + Channel &chan { _channels[id] }; + chan._gen_prim.dropped = true; +} + + +void Vbd_check::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (mod_req.dst_module_id()) { + case BLOCK_IO: + { + Block_io_request &gen_req { *static_cast(&mod_req) }; + chan._gen_prim.success = gen_req.success(); + break; + } + default: + class Exception_8 { }; + throw Exception_8 { }; + } +} + + +bool Vbd_check::ready_to_submit_request() +{ + for (Channel &chan : _channels) { + if (chan._request._type == Request::INVALID) + return true; + } + return false; +} + + +void Vbd_check::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + Channel &chan { _channels[id] }; + if (chan._request._type == Request::INVALID) { + req.dst_request_id(id); + chan._request = *static_cast(&req); + chan._root_state = Channel::READ_BLOCK; + return; + } + } + class Exception_1 { }; + throw Exception_1 { }; +} + + +void Vbd_check::execute(bool &progress) +{ + for (Channel &chan : _channels) { + + Request &req { chan._request }; + switch (req._type) { + case Request::CHECK: + + _execute_check(chan, progress); + break; + + default: + + break; + } + } +} diff --git a/repos/gems/src/lib/tresor/vbd_initializer.cc b/repos/gems/src/lib/tresor/vbd_initializer.cc new file mode 100644 index 0000000000..0be043a83b --- /dev/null +++ b/repos/gems/src/lib/tresor/vbd_initializer.cc @@ -0,0 +1,602 @@ +/* + * \brief Module for initializing the VBD + * \author Josef Soentgen + * \date 2023-03-03 + */ + +/* + * 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. + */ + +/* base includes */ +#include + +/* tresor includes */ +#include +#include +#include +#include + +using namespace Tresor; + +static constexpr bool DEBUG = false; + + +Vbd_initializer_request::Vbd_initializer_request(Module_id src_module_id, + Module_request_id src_request_id) +: + Module_request { src_module_id, src_request_id, VBD_INITIALIZER } +{ } + + +void Vbd_initializer_request::create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t max_level_idx, + uint64_t max_child_idx, + uint64_t nr_of_leaves) +{ + Vbd_initializer_request req { src_module_id, src_request_id }; + req._type = (Type)req_type; + + req._max_level_idx = max_level_idx; + req._max_child_idx = max_child_idx; + req._nr_of_leaves = nr_of_leaves; + + if (sizeof(req) > buf_size) { + class Bad_size_0 { }; + throw Bad_size_0 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); +} + + +char const *Vbd_initializer_request::type_to_string(Type type) +{ + switch (type) { + case INVALID: return "invalid"; + case INIT: return "init"; + } + return "?"; +} + + +void Vbd_initializer::_execute_leaf_child(Channel &channel, + bool &progress, + uint64_t &nr_of_leaves, + Type_1_node &child, + Vbd_initializer_channel::Child_state &child_state, + uint64_t level_index, + uint64_t child_index) +{ + using CS = Vbd_initializer_channel::Child_state; + + switch (child_state) { + case CS::INIT_BLOCK: + child_state = CS::INIT_NODE; + progress = true; + return; + + case CS::INIT_NODE: + if (nr_of_leaves == 0) { + + if (DEBUG) + log("[vbd_init] node: ", level_index, " ", child_index, + " assign pba 0, leaf unused"); + + Vbd_initializer_channel::reset_node(child); + child_state = CS::DONE; + progress = true; + } else { + + switch (channel._state) { + case Channel::IN_PROGRESS: + channel._state = Channel::BLOCK_ALLOC_PENDING; + progress = true; + break; + + case Channel::BLOCK_ALLOC_PENDING: + break; + + case Channel::BLOCK_ALLOC_IN_PROGRESS: + break; + + case Channel::BLOCK_ALLOC_COMPLETE: + /* bail early in case the allocator failed */ + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, + "allocate block for VBD initialization"); + break; + } + channel._state = Channel::IN_PROGRESS; + + Vbd_initializer_channel::reset_node(child); + + child.pba = channel._blk_nr; + child_state = CS::DONE; + --nr_of_leaves; + progress = true; + + if (DEBUG) + log("[vbd_init] node: ", level_index, " ", child_index, + " assign pba: ", channel._blk_nr, " leaves left: ", + nr_of_leaves); + break; + + default: + break; + } + } + default: + break; + } +} + + +void Vbd_initializer::_execute_inner_t1_child(Channel &channel, + bool &progress, + uint64_t nr_of_leaves, + uint64_t &level_to_write, + Type_1_node &child, + Vbd_initializer_channel::Type_1_level &child_level, + Vbd_initializer_channel::Child_state &child_state, + uint64_t level_index, + uint64_t child_index) + +{ + using CS = Vbd_initializer_channel::Child_state; + + switch (child_state) { + case CS::INIT_BLOCK: + + if (nr_of_leaves == 0) { + + if (DEBUG) + log("[vbd_init] node: ", level_index, " ", child_index, + " assign pba 0, inner node unused"); + + Vbd_initializer_channel::reset_node(child); + child_state = CS::DONE; + progress = true; + return; + } else { + + if (DEBUG) + log("[vbd_init] node: ", level_index, " ", child_index, + " reset level: ", level_index - 1); + + Vbd_initializer_channel::reset_level(child_level, CS::INIT_BLOCK); + child_state = CS::INIT_NODE; + progress = true; + return; + } + break; + + case CS::INIT_NODE: + + switch (channel._state) { + case Channel::IN_PROGRESS: + channel._state = Channel::BLOCK_ALLOC_PENDING; + progress = true; + break; + + case Channel::BLOCK_ALLOC_PENDING: + break; + + case Channel::BLOCK_ALLOC_IN_PROGRESS: + break; + + case Channel::BLOCK_ALLOC_COMPLETE: + /* bail early in case the allocator failed */ + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, + "allocate block for VBD initialization"); + break; + } + channel._state = Channel::IN_PROGRESS; + + Vbd_initializer_channel::reset_node(child); + child.pba = channel._blk_nr; + calc_sha256_4k_hash(&child_level.children, &child.hash); + child_state = CS::WRITE_BLOCK; + progress = true; + + if (DEBUG) + log("[vbd_init] node: ", level_index, " ", child_index, + " assign pba: ", channel._blk_nr); + break; + + default: + break; + } + break; + + case CS::WRITE_BLOCK: + + switch (channel._state) { + case Channel::IN_PROGRESS: + { + channel._state = Channel::BLOCK_IO_PENDING; + channel._child_pba = child.pba; + level_to_write = level_index - 1; + progress = true; + break; + } + + case Channel::BLOCK_IO_PENDING: + break; + + case Channel::BLOCK_IO_IN_PROGRESS: + break; + + case Channel::BLOCK_IO_COMPLETE: + /* bail early in case the allocator failed */ + if (!channel._generated_req_success) { + _mark_req_failed(channel, progress, + "write block for VBD initialization"); + break; + } + channel._state = Channel::IN_PROGRESS; + + child_state = CS::DONE; + progress = true; + + if (DEBUG) + log("[vbd_init] node: ", level_index, " ", child_index, + " write pba: ", channel._child_pba, " level: ", + level_index -1, " (child: ", child, ")"); + break; + default: + break; + } + + break; + + default: + break; + } +} + + +void Vbd_initializer::_execute(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + + /* + * First handle all child nodes (leaves and inner nodes) that starts after + * triggering the root node below. + */ + for (uint64_t level_idx = 0; level_idx <= req._max_level_idx; level_idx++) { + + for (uint64_t child_idx = 0; child_idx <= req._max_child_idx; child_idx++) { + + Vbd_initializer_channel::Child_state &state = + channel._t1_levels[level_idx].children_state[child_idx]; + + if (state != Vbd_initializer_channel::Child_state::DONE) { + + Type_1_node &child = + channel._t1_levels[level_idx].children.nodes[child_idx]; + + if (level_idx == 1) { + _execute_leaf_child(channel, progress, req._nr_of_leaves, + child, state, level_idx, child_idx); + } else { + + Vbd_initializer_channel::Type_1_level &t1_level = + channel._t1_levels[level_idx - 1]; + + _execute_inner_t1_child(channel, progress, + req._nr_of_leaves, + channel._level_to_write, + child, t1_level, state, + level_idx, child_idx); + } + return; + } + } + } + + /* + * Checking the root node will trigger the initialization process as + * well as will finish it. + */ + if (channel._root_node.state != Vbd_initializer_channel::Child_state::DONE) { + + Vbd_initializer_channel::Type_1_level &t1_level = + channel._t1_levels[req._max_level_idx]; + + _execute_inner_t1_child(channel, progress, + req._nr_of_leaves, + channel._level_to_write, + channel._root_node.node, t1_level, channel._root_node.state, + req._max_level_idx + 1, 0); + return; + } + + /* + * We will end up here when the root state is 'DONE'. + */ + if (req._nr_of_leaves == 0) + _mark_req_successful(channel, progress); + else + _mark_req_failed(channel, progress, "initialize VBD"); +} + + +void Vbd_initializer::_execute_init(Channel &channel, + bool &progress) +{ + switch (channel._state) { + case Channel::SUBMITTED: + + /* clean residual state */ + for (unsigned int i = 0; i < TREE_MAX_LEVEL; i++) { + Vbd_initializer_channel::reset_level(channel._t1_levels[i], + Vbd_initializer_channel::Child_state::DONE); + } + channel._level_to_write = 0; + + channel._state = Channel::PENDING; + channel._root_node.state = Vbd_initializer_channel::Child_state::INIT_BLOCK; + progress = true; + + return; + + case Channel::PENDING: + + channel._state = Channel::IN_PROGRESS; + progress = true; + return; + + case Channel::IN_PROGRESS: + + _execute(channel, progress); + return; + + case Channel::BLOCK_ALLOC_COMPLETE: + + _execute(channel, progress); + return; + + case Channel::BLOCK_IO_COMPLETE: + + _execute(channel, progress); + return; + + default: + /* + * Omit other states related to ALLOC and IO as those + * are handled via Module API. + */ + return; + } +} + + +void Vbd_initializer::_mark_req_failed(Channel &channel, + bool &progress, + char const *str) +{ + error("request failed: failed to ", str); + channel._request._success = false; + channel._state = Channel::COMPLETE; + progress = true; +} + + +void Vbd_initializer::_mark_req_successful(Channel &channel, + bool &progress) +{ + Request &req { channel._request }; + + memcpy(req._root_node, &channel._root_node.node, sizeof (req._root_node)); + req._success = true; + + channel._state = Channel::COMPLETE; + progress = true; +} + + +bool Vbd_initializer::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::COMPLETE) { + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Vbd_initializer::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + if (_channels[id]._state != Channel::COMPLETE) { + class Exception_2 { }; + throw Exception_2 { }; + } + _channels[id]._state = Channel::INACTIVE; +} + + +bool Vbd_initializer::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel &channel { _channels[id] }; + + if (channel._state != Vbd_initializer_channel::State::INACTIVE) + + switch (channel._state) { + case Vbd_initializer_channel::State::BLOCK_ALLOC_PENDING: + { + Block_allocator_request::Type const block_allocator_req_type { + Block_allocator_request::GET }; + + Block_allocator_request::create( + buf_ptr, buf_size, VBD_INITIALIZER, id, + block_allocator_req_type); + + return true; + } + case Vbd_initializer_channel::State::BLOCK_IO_PENDING: + { + Block_io_request::Type const block_io_req_type { + Block_io_request::WRITE }; + + construct_in_buf( + buf_ptr, buf_size, VBD_INITIALIZER, id, + block_io_req_type, 0, 0, 0, + channel._child_pba, 0, + 1, &channel._t1_levels[channel._level_to_write].children, + nullptr); + + if (DEBUG) { + log("BLOCK_IO_PENDING write ", channel._child_pba); + Vbd_initializer_channel::dump(channel._t1_levels[channel._level_to_write].children); + } + + return true; + } + default: + break; + } + } + return false; +} + + +void Vbd_initializer::_drop_generated_request(Module_request &req) +{ + Module_request_id const id { req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Bad_id { }; + throw Bad_id { }; + } + switch (_channels[id]._state) { + case Vbd_initializer_channel::State::BLOCK_ALLOC_PENDING: + _channels[id]._state = Vbd_initializer_channel::State::BLOCK_ALLOC_IN_PROGRESS; + break; + case Vbd_initializer_channel::State::BLOCK_IO_PENDING: + _channels[id]._state = Vbd_initializer_channel::State::BLOCK_IO_IN_PROGRESS; + break; + default: + class Exception_1 { }; + throw Exception_1 { }; + } +} + + +void Vbd_initializer::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + switch (mod_req.dst_module_id()) { + case BLOCK_ALLOCATOR: + { + Block_allocator_request const &gen_req { *static_cast(&mod_req) }; + switch (_channels[id]._state) { + case Channel::BLOCK_ALLOC_IN_PROGRESS: + _channels[id]._state = Channel::BLOCK_ALLOC_COMPLETE; + _channels[id]._blk_nr = gen_req.blk_nr(); + _channels[id]._generated_req_success = gen_req.success(); + break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } + break; + } + case BLOCK_IO: + { + Block_io_request const &gen_req { *static_cast(&mod_req) }; + switch (_channels[id]._state) { + case Channel::BLOCK_IO_IN_PROGRESS: + _channels[id]._state = Channel::BLOCK_IO_COMPLETE; + _channels[id]._generated_req_success = gen_req.success(); + break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } + break; + } + default: + class Exception_2 { }; + throw Exception_2 { }; + } +} + + +Vbd_initializer::Vbd_initializer() +{ } + + +bool Vbd_initializer::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._state == Channel::INACTIVE) + return true; + } + return false; +} + + +void Vbd_initializer::submit_request(Module_request &req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + if (_channels[id]._state == Channel::INACTIVE) { + req.dst_request_id(id); + _channels[id]._request = *static_cast(&req); + _channels[id]._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} + + +void Vbd_initializer::execute(bool &progress) +{ + for (Channel &channel : _channels) { + + if (channel._state == Channel::INACTIVE) + continue; + + Request &req { channel._request }; + switch (req._type) { + case Request::INIT: + + _execute_init(channel, progress); + + break; + default: + + class Exception_1 { }; + throw Exception_1 { }; + } + } +} diff --git a/repos/gems/src/app/cbe_tester/vfs_utilities.cc b/repos/gems/src/lib/tresor/vfs_utilities.cc similarity index 83% rename from repos/gems/src/app/cbe_tester/vfs_utilities.cc rename to repos/gems/src/lib/tresor/vfs_utilities.cc index d75c78e3ec..c22c73cf84 100644 --- a/repos/gems/src/app/cbe_tester/vfs_utilities.cc +++ b/repos/gems/src/lib/tresor/vfs_utilities.cc @@ -11,8 +11,8 @@ * under the terms of the GNU Affero General Public License version 3. */ -/* CBE tester includes */ -#include +/* tresor includes */ +#include using namespace Genode; using namespace Vfs; @@ -23,7 +23,7 @@ using namespace Vfs; **********************/ Vfs::Vfs_handle &vfs_open(Vfs::Env &vfs_env, - Genode::String<128> path, + String<128> path, Vfs::Directory_service::Open_mode mode) { Vfs_handle *handle { nullptr }; @@ -48,8 +48,8 @@ Vfs_handle &vfs_open_wo(Vfs::Env &vfs_env, } -Vfs::Vfs_handle &vfs_open_rw(Vfs::Env &vfs_env, - Genode::String<128> path) +Vfs::Vfs_handle &vfs_open_rw(Vfs::Env &vfs_env, + String<128> path) { return vfs_open(vfs_env, path, Directory_service::OPEN_MODE_RDWR); } diff --git a/repos/gems/src/lib/tresor/virtual_block_device.cc b/repos/gems/src/lib/tresor/virtual_block_device.cc new file mode 100644 index 0000000000..dacdb657bf --- /dev/null +++ b/repos/gems/src/lib/tresor/virtual_block_device.cc @@ -0,0 +1,2064 @@ +/* + * \brief Module for accessing and managing trees of the virtual block device + * \author Martin Stein + * \date 2023-03-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. + */ + +/* base includes */ +#include +#include + +/* tresor includes */ +#include +#include +#include +#include +#include + +using namespace Tresor; + + +/********************************** + ** Virtual_block_device_request ** + **********************************/ + +char const *Virtual_block_device_request::type_to_string(Type op) +{ + switch (op) { + case INVALID: return "invalid"; + case READ_VBA: return "read_vba"; + case WRITE_VBA: return "write_vba"; + case REKEY_VBA: return "rekey_vba"; + case VBD_EXTENSION_STEP: return "vbd_extension_step"; + } + return "?"; +} + +void Virtual_block_device_request::create(void *buf_ptr, + size_t buf_size, + uint64_t src_module_id, + uint64_t src_request_id, + size_t req_type, + uint64_t client_req_offset, + uint64_t client_req_tag, + Generation last_secured_generation, + addr_t ft_root_pba_ptr, + addr_t ft_root_gen_ptr, + addr_t ft_root_hash_ptr, + uint64_t ft_max_level, + uint64_t ft_degree, + uint64_t ft_leaves, + addr_t mt_root_pba_ptr, + addr_t mt_root_gen_ptr, + addr_t mt_root_hash_ptr, + uint64_t mt_max_level, + uint64_t mt_degree, + uint64_t mt_leaves, + uint64_t vbd_degree, + uint64_t vbd_highest_vba, + bool rekeying, + Virtual_block_address vba, + Snapshot const *snapshot_ptr, + Snapshots const *snapshots_ptr, + Tree_degree snapshots_degree, + Key_id old_key_id, + Key_id new_key_id, + Generation current_gen, + Key_id key_id, + Physical_block_address first_pba, + Number_of_blocks nr_of_pbas) +{ + Virtual_block_device_request req { src_module_id, src_request_id }; + + req._type = (Type)req_type; + req._last_secured_generation = last_secured_generation; + req._ft_root_pba_ptr = (addr_t)ft_root_pba_ptr; + req._ft_root_gen_ptr = (addr_t)ft_root_gen_ptr; + req._ft_root_hash_ptr = (addr_t)ft_root_hash_ptr; + req._ft_max_level = ft_max_level; + req._ft_degree = ft_degree; + req._ft_leaves = ft_leaves; + req._mt_root_pba_ptr = (addr_t)mt_root_pba_ptr; + req._mt_root_gen_ptr = (addr_t)mt_root_gen_ptr; + req._mt_root_hash_ptr = (addr_t)mt_root_hash_ptr; + req._mt_max_level = mt_max_level; + req._mt_degree = mt_degree; + req._mt_leaves = mt_leaves; + req._vbd_degree = vbd_degree; + req._vbd_highest_vba = vbd_highest_vba; + req._rekeying = rekeying; + req._vba = vba; + + switch (req_type) { + case READ_VBA: + case WRITE_VBA: + req._snapshots.items[0] = *snapshot_ptr; + req._new_key_id = key_id; + break; + case REKEY_VBA: + req._snapshots = *snapshots_ptr; + req._old_key_id = old_key_id; + req._new_key_id = new_key_id; + break; + case VBD_EXTENSION_STEP: + req._snapshots = *snapshots_ptr; + req._pba = first_pba; + req._nr_of_pbas = nr_of_pbas; + break; + default: + class Exception_3 { }; + throw Exception_3 { }; + } + req._snapshots_degree = snapshots_degree; + req._client_req_offset = client_req_offset; + req._client_req_tag = client_req_tag; + req._curr_gen = current_gen; + + if (sizeof(req) > buf_size) { + class Exception_2 { }; + throw Exception_2 { }; + } + memcpy(buf_ptr, &req, sizeof(req)); +} + + +Virtual_block_device_request::Virtual_block_device_request(Module_id src_module_id, + Module_request_id src_request_id) +: + Module_request { src_module_id, src_request_id, VIRTUAL_BLOCK_DEVICE } +{ } + + +/********************************** + ** Virtual_block_device_channel ** + **********************************/ + +Snapshot &Virtual_block_device_channel::snap() +{ + return _request._snapshots.items[_snapshot_idx]; +} + + +/************************** + ** Virtual_block_device ** + **************************/ + +void Virtual_block_device::_set_args_for_write_back_of_t1_lvl(Tree_level_index const max_lvl, + uint64_t const t1_lvl, + uint64_t const pba, + uint64_t const prim_idx, + Channel::State &state, + bool &progress, + Channel::Generated_prim &prim) +{ + prim = { + .op = Channel::Generated_prim::Type::WRITE, + .succ = false, + .tg = Channel::Tag_type::TAG_VBD_CACHE, + .blk_nr = pba, + .idx = prim_idx + }; + + if (t1_lvl < max_lvl) { + state = Channel::State::WRITE_INNER_NODE_PENDING; + progress = true; + } else { + state = Channel::State::WRITE_ROOT_NODE_PENDING; + progress = true; + } +} + + +bool Virtual_block_device::ready_to_submit_request() +{ + for (Channel &channel : _channels) { + if (channel._request._type == Request::INVALID) + return true; + } + return false; +} + + +void Virtual_block_device::submit_request(Module_request &mod_req) +{ + for (Module_request_id id { 0 }; id < NR_OF_CHANNELS; id++) { + Channel &chan { _channels[id] }; + if (chan._request._type == Request::INVALID) { + mod_req.dst_request_id(id); + chan._request = *static_cast(&mod_req); + chan._state = Channel::SUBMITTED; + return; + } + } + class Invalid_call { }; + throw Invalid_call { }; +} + + +void Virtual_block_device::_execute_read_vba_read_inner_node_completed (Channel &channel, + uint64_t const job_idx, + bool &progress) +{ + _check_that_primitive_was_successful(channel._generated_prim); + + auto &snapshot = channel.snapshots(channel._snapshot_idx); + + _check_hash_of_read_type_1_node(snapshot, + channel._request._snapshots_degree, + channel._t1_blk_idx, channel._t1_blks, + channel._vba); + + if (channel._t1_blk_idx > 1) { + + auto const parent_lvl = channel._t1_blk_idx; + auto const child_lvl = channel._t1_blk_idx - 1; + + auto const child_idx = t1_child_idx_for_vba(channel._request._vba, parent_lvl, channel._request._snapshots_degree); + auto const &child = channel._t1_blks.items[parent_lvl].nodes[child_idx]; + + channel._t1_blk_idx = child_lvl; + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_VBD_CACHE, + .blk_nr = child.pba, + .idx = job_idx + }; + if (VERBOSE_VBA_ACCESS) { + log( + " lvl ", channel._t1_blk_idx, + ": read t1 nodes blk: pba ", channel._generated_prim.blk_nr); + } + + channel._state = Channel::State::READ_INNER_NODE_PENDING; + progress = true; + + } else { + + Tree_level_index const parent_lvl { channel._t1_blk_idx }; + Tree_node_index const child_idx { + t1_child_idx_for_vba( + channel._request._vba, parent_lvl, + channel._request._snapshots_degree) }; + + Type_1_node const &child { + channel._t1_blks.items[parent_lvl].nodes[child_idx] }; + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_VBD_BLK_IO_READ_CLIENT_DATA, + .blk_nr = child.pba, + .idx = job_idx + }; + if (VERBOSE_VBA_ACCESS) { + log( + " lvl ", 0, + ": read data blk: pba ", channel._generated_prim.blk_nr, + " key ", channel._request._new_key_id); + } + + channel._state = Channel::State::READ_CLIENT_DATA_FROM_LEAF_NODE_PENDING; + progress = true; + } +} + + +void Virtual_block_device::_execute_read_vba(Channel &channel, + uint64_t const idx, + bool &progress) +{ + switch (channel._state) { + case Channel::State::SUBMITTED: + { + Request &request = channel._request; + + channel._snapshot_idx = 0; + channel._vba = request._vba; + + Snapshot &snapshot = channel.snapshots(channel._snapshot_idx); + channel._t1_blk_idx = snapshot.max_level; + + channel._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_VBD_CACHE, + .blk_nr = snapshot.pba, + .idx = idx + }; + if (VERBOSE_VBA_ACCESS) + log(" lvl ", channel._t1_blk_idx, ": read t1 nodes blk: pba ", + channel._generated_prim.blk_nr); + + channel._state = Channel::State::READ_ROOT_NODE_PENDING; + progress = true; + break; + } + case Channel::State::READ_ROOT_NODE_COMPLETED: + + _execute_read_vba_read_inner_node_completed (channel, idx, progress); + break; + + case Channel::State::READ_INNER_NODE_COMPLETED: + + _execute_read_vba_read_inner_node_completed (channel, idx, progress); + break; + + case Channel::State::READ_CLIENT_DATA_FROM_LEAF_NODE_COMPLETED: + + _check_that_primitive_was_successful(channel._generated_prim); + channel._request._success = channel._generated_prim.succ; + channel._state = Channel::State::COMPLETED; + progress = true; + break; + default: + break; + } +} + + +void Virtual_block_device::_update_nodes_of_branch_of_written_vba(Snapshot &snapshot, + uint64_t const snapshot_degree, + uint64_t const vba, + Tree_walk_pbas const &new_pbas, + Hash const & leaf_hash, + uint64_t curr_gen, + Channel::Type_1_node_blocks &t1_blks) +{ + for (Tree_level_index lvl = 0; lvl <= snapshot.max_level; lvl++) { + + if (lvl == 0) { + + auto const child_idx = t1_child_idx_for_vba(vba, lvl + 1, snapshot_degree); + auto &node = t1_blks.items[lvl + 1].nodes[child_idx]; + + node.pba = new_pbas.pbas[lvl]; + node.gen = curr_gen; + node.hash = leaf_hash; + + } else if (lvl < snapshot.max_level) { + + auto const child_idx = t1_child_idx_for_vba(vba, lvl + 1, snapshot_degree); + auto &node = t1_blks.items[lvl + 1].nodes[child_idx]; + + node.pba = new_pbas.pbas[lvl]; + node.gen = curr_gen; + calc_sha256_4k_hash(&t1_blks.items[lvl], &node.hash); + + } else { + + snapshot.pba = new_pbas.pbas[lvl]; + snapshot.gen = curr_gen; + calc_sha256_4k_hash(&t1_blks.items[lvl], &snapshot.hash); + } + } +} + + +void Virtual_block_device:: +_set_args_in_order_to_write_client_data_to_leaf_node(Tree_walk_pbas const &new_pbas, + uint64_t const job_idx, + Channel::State &state, + Channel::Generated_prim &prim, + bool &progress) +{ + prim = { + .op = Channel::Generated_prim::Type::WRITE, + .succ = false, + .tg = Channel::Tag_type::TAG_VBD_BLK_IO_WRITE_CLIENT_DATA, + .blk_nr = new_pbas.pbas[0], + .idx = job_idx + }; + + state = Channel::State::WRITE_CLIENT_DATA_TO_LEAF_NODE_PENDING; + progress = true; +} + + +void Virtual_block_device:: +_check_that_primitive_was_successful(Channel::Generated_prim const &prim) +{ + if (prim.succ) + return; + + class Primitive_not_successfull { }; + throw Primitive_not_successfull { }; +} + + +void Virtual_block_device::_check_hash_of_read_type_1_node(Snapshot const &snapshot, + uint64_t const snapshots_degree, + uint64_t const t1_blk_idx, + Channel::Type_1_node_blocks const &t1_blks, + uint64_t const vba) +{ + if (t1_blk_idx == snapshot.max_level) { + if (!check_sha256_4k_hash(&t1_blks.items[t1_blk_idx], &snapshot.hash)) { + class Program_error_hash_of_read_type_1 { }; + throw Program_error_hash_of_read_type_1 { }; + } + } else { + uint64_t const child_idx = t1_child_idx_for_vba(vba, t1_blk_idx + 1, snapshots_degree); + Type_1_node const &child = t1_blks.items[t1_blk_idx + 1].nodes[child_idx]; + if (!check_sha256_4k_hash(&t1_blks.items[t1_blk_idx], &child.hash)) { + class Program_error_hash_of_read_type_1_B { }; + throw Program_error_hash_of_read_type_1_B { }; + } + } +} + + +void Virtual_block_device::_set_args_in_order_to_read_type_1_node(Snapshot const &snapshot, + uint64_t const snapshots_degree, + uint64_t const t1_blk_idx, + Channel::Type_1_node_blocks const &t1_blks, + uint64_t const vba, + uint64_t const job_idx, + Channel::State &state, + Channel::Generated_prim &prim, + bool &progress) +{ + if (t1_blk_idx == snapshot.max_level) { + prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_VBD_CACHE, + .blk_nr = snapshot.pba, + .idx = job_idx + }; + } else { + auto const child_idx = t1_child_idx_for_vba(vba, t1_blk_idx + 1, snapshots_degree); + auto const &child = t1_blks.items[t1_blk_idx + 1].nodes[child_idx]; + + prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_VBD_CACHE, + .blk_nr = child.pba, + .idx = job_idx + }; + } + + state = Channel::State::READ_INNER_NODE_PENDING; + progress = true; +} + + +void Virtual_block_device:: +_initialize_new_pbas_and_determine_nr_of_pbas_to_allocate(uint64_t const curr_gen, + Snapshot const &snapshot, + uint64_t const snapshots_degree, + uint64_t const vba, + Channel::Type_1_node_blocks const &t1_blks, + Tree_walk_pbas &new_pbas, + uint64_t &nr_of_blks) +{ + nr_of_blks = 0; + for (Tree_level_index lvl = 0; lvl <= TREE_MAX_LEVEL; lvl++) { + + if (lvl > snapshot.max_level) { + + new_pbas.pbas[lvl] = 0; + + } else if (lvl == snapshot.max_level) { + + if (snapshot.gen < curr_gen) { + + nr_of_blks++; + new_pbas.pbas[lvl] = 0; + + } else if (snapshot.gen == curr_gen) { + + new_pbas.pbas[lvl] = snapshot.pba; + + } else { + + class Exception_1 { }; + throw Exception_1 { }; + } + } else { + + Tree_node_index const child_idx { + t1_child_idx_for_vba(vba, lvl + 1, snapshots_degree) }; + + Type_1_node const &child { + t1_blks.items[lvl + 1].nodes[child_idx] }; + + if (child.gen < curr_gen) { + + if (lvl == 0 && child.gen == INVALID_GENERATION) { + + new_pbas.pbas[lvl] = child.pba; + + } else { + + nr_of_blks++; + new_pbas.pbas[lvl] = 0; + } + } else if (child.gen == curr_gen) { + + new_pbas.pbas[lvl] = child.pba; + + } else { + + class Exception_2 { }; + throw Exception_2 { }; + } + } + } +} + + +void Virtual_block_device:: +_set_args_for_alloc_of_new_pbas_for_branch_of_written_vba(uint64_t curr_gen, + Snapshot const &snapshot, + uint64_t const snapshots_degree, + uint64_t const vba, + Channel::Type_1_node_blocks const &t1_blks, + uint64_t const prim_idx, + uint64_t &free_gen, + Type_1_node_walk &t1_walk, + Channel::State &state, + Channel::Generated_prim &prim, + bool &progress) +{ + for (Tree_level_index lvl = 0; lvl <= TREE_MAX_LEVEL; lvl++) { + if (lvl > snapshot.max_level) { + t1_walk.nodes[lvl] = Type_1_node { }; /* invalid */ + } else if (lvl == snapshot.max_level) { + auto &node = t1_walk.nodes[lvl]; + + node.pba = snapshot.pba; + node.gen = snapshot.gen; + node.hash = snapshot.hash; + } else { + auto const child_idx = t1_child_idx_for_vba(vba, lvl + 1, snapshots_degree); + t1_walk.nodes[lvl] = t1_blks.items[lvl + 1].nodes[child_idx]; + } + } + + free_gen = curr_gen; + + prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_VBD_FT_ALLOC_FOR_NON_RKG, + .blk_nr = 0, + .idx = prim_idx + }; + + state = Channel::State::ALLOC_PBAS_AT_LEAF_LVL_PENDING; + progress = true; +} + + +void Virtual_block_device::_execute_write_vba(Channel &chan, + uint64_t const job_idx, + bool &progress) +{ + Request &req { chan._request }; + switch (chan._state) { + case Channel::State::SUBMITTED: { + Request &request { chan._request }; + + chan._snapshot_idx = 0; + chan._vba = request._vba; + chan._t1_blk_idx = chan.snapshots(chan._snapshot_idx).max_level; + + _set_args_in_order_to_read_type_1_node(chan.snapshots(chan._snapshot_idx), + chan._request._snapshots_degree, + chan._t1_blk_idx, + chan._t1_blks, + chan._vba, + job_idx, + chan._state, + chan._generated_prim, + progress); + + if (VERBOSE_VBA_ACCESS) { + log(" lvl ", chan._t1_blk_idx, ": read t1 nodes blk: pba ", + chan._generated_prim.blk_nr); + } + + break; + } + case Channel::State::READ_INNER_NODE_COMPLETED: + + _check_that_primitive_was_successful(chan._generated_prim); + _check_hash_of_read_type_1_node(chan.snapshots(chan._snapshot_idx), + chan._request._snapshots_degree, + chan._t1_blk_idx, chan._t1_blks, + chan._vba); + + if (chan._t1_blk_idx > 1) { + chan._t1_blk_idx = chan._t1_blk_idx - 1; + + _set_args_in_order_to_read_type_1_node(chan.snapshots(chan._snapshot_idx), + chan._request._snapshots_degree, + chan._t1_blk_idx, + chan._t1_blks, + chan._vba, + job_idx, + chan._state, + chan._generated_prim, + progress); + + if (VERBOSE_VBA_ACCESS) { + log(" lvl ", chan._t1_blk_idx, ": read t1 nodes blk: pba ", + chan._generated_prim.blk_nr); + } + + } else { + _initialize_new_pbas_and_determine_nr_of_pbas_to_allocate(req._curr_gen, + chan.snapshots(chan._snapshot_idx), + chan._request._snapshots_degree, + chan._vba, + chan._t1_blks, + chan._new_pbas, + chan._nr_of_blks); + + if (chan._nr_of_blks > 0) { + _set_args_for_alloc_of_new_pbas_for_branch_of_written_vba(req._curr_gen, + chan.snapshots(chan._snapshot_idx), + chan._request._snapshots_degree, + chan._vba, + chan._t1_blks, + job_idx, + chan._free_gen, + chan._t1_node_walk, + chan._state, + chan._generated_prim, + progress); + + } else { + + _set_args_in_order_to_write_client_data_to_leaf_node(chan._new_pbas, + job_idx, + chan._state, + chan._generated_prim, + progress); + + if (VERBOSE_VBA_ACCESS) + log(" lvl ", 0, ": write data blk: pba ", + chan._generated_prim.blk_nr, + " key ", req._new_key_id); + } + } + + break; + case Channel::State::ALLOC_PBAS_AT_LEAF_LVL_COMPLETED: + + _check_that_primitive_was_successful(chan._generated_prim); + + if (VERBOSE_VBA_ACCESS) { + log(" lvl ", 0, ": alloc ", chan._nr_of_blks, " pba", + chan._nr_of_blks > 1 ? "s" : ""); + + for (Tree_level_index lvl = TREE_MAX_LEVEL; ; lvl--) { + if (lvl <= chan.snapshots(chan._snapshot_idx).max_level) { + Type_1_node &node = chan._t1_node_walk.nodes[lvl]; + log(" lvl ", lvl, " gen ", (Generation)node.gen, + " pba ", (Physical_block_address)node.pba, " -> ", + (Physical_block_address)chan._new_pbas.pbas[lvl]); + } + if (lvl == 0) + break; + } + } + _set_args_in_order_to_write_client_data_to_leaf_node(chan._new_pbas, + job_idx, + chan._state, + chan._generated_prim, + progress); + if (VERBOSE_VBA_ACCESS) + log(" lvl ", 0, ": write data blk: pba ", + chan._generated_prim.blk_nr, + " key ", req._new_key_id); + + break; + + case Channel::State::WRITE_CLIENT_DATA_TO_LEAF_NODE_COMPLETED: + + _check_that_primitive_was_successful(chan._generated_prim); + _update_nodes_of_branch_of_written_vba( + chan.snapshots(chan._snapshot_idx), + chan._request._snapshots_degree, chan._vba, + chan._new_pbas, chan._hash, req._curr_gen, chan._t1_blks); + + _set_args_for_write_back_of_t1_lvl( + chan.snapshots(chan._snapshot_idx).max_level, chan._t1_blk_idx, + chan._new_pbas.pbas[chan._t1_blk_idx], job_idx, chan._state, + progress, chan._generated_prim); + + if (VERBOSE_VBA_ACCESS) + log(" lvl ", chan._t1_blk_idx, ": write t1 nodes blk: pba ", + chan._generated_prim.blk_nr); + + break; + + case Channel::State::WRITE_INNER_NODE_COMPLETED: + + _check_that_primitive_was_successful(chan._generated_prim); + chan._t1_blk_idx = chan._t1_blk_idx + 1; + + _set_args_for_write_back_of_t1_lvl( + chan.snapshots(chan._snapshot_idx).max_level, + chan._t1_blk_idx, chan._new_pbas.pbas[chan._t1_blk_idx], + job_idx, chan._state, progress, chan._generated_prim); + + if (VERBOSE_VBA_ACCESS) + log(" lvl ", chan._t1_blk_idx, ": write t1 nodes blk: pba ", + chan._generated_prim.blk_nr); + + break; + case Channel::State::WRITE_ROOT_NODE_COMPLETED: + + _check_that_primitive_was_successful(chan._generated_prim); + chan._state = Channel::State::COMPLETED; + chan._request._success = true; + progress = true; + break; + + default: + break; + } +} + + +void Virtual_block_device::_mark_req_failed(Channel &chan, + bool &progress, + char const *str) +{ + error(chan._request.type_name(), " request failed at step \"", str, "\""); + chan._request._success = false; + chan._state = Channel::COMPLETED; + progress = true; +} + + +void Virtual_block_device::_mark_req_successful(Channel &chan, + bool &progress) +{ + chan._request._success = true; + chan._state = Channel::COMPLETED; + progress = true; +} + + +char const *Virtual_block_device::_state_to_step_label(Channel::State state) +{ + switch (state) { + case Channel::READ_ROOT_NODE_COMPLETED: return "read root node"; + case Channel::READ_INNER_NODE_COMPLETED: return "read inner node"; + case Channel::READ_LEAF_NODE_COMPLETED: return "read leaf node"; + case Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_COMPLETED: return "read client data from leaf node"; + case Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_COMPLETED: return "write client data to leaf node"; + case Channel::DECRYPT_LEAF_NODE_COMPLETED: return "decrypt leaf node"; + case Channel::ALLOC_PBAS_AT_LEAF_LVL_COMPLETED: return "alloc pbas at leaf lvl"; + case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED: return "alloc pbas at lowest inner lvl"; + case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_COMPLETED: return "alloc pbas at higher inner lvl"; + case Channel::ENCRYPT_LEAF_NODE_COMPLETED: return "encrypt leaf node"; + case Channel::WRITE_LEAF_NODE_COMPLETED: return "write leaf node"; + case Channel::WRITE_INNER_NODE_COMPLETED: return "write inner node"; + case Channel::WRITE_ROOT_NODE_COMPLETED: return "write root node"; + default: break; + } + return "?"; +} + + +bool Virtual_block_device::_handle_failed_generated_req(Channel &chan, + bool &progress) +{ + if (chan._generated_prim.succ) + return false; + + _mark_req_failed(chan, progress, _state_to_step_label(chan._state)); + return true; +} + + +bool +Virtual_block_device::_find_next_snap_to_rekey_vba_at(Channel const &chan, + Snapshot_index &next_snap_idx) +{ + bool next_snap_idx_valid { false }; + Request const &req { chan._request }; + Snapshot const &old_snap { req._snapshots.items[chan._snapshot_idx] }; + + for (Snapshot_index snap_idx { 0 }; + snap_idx < MAX_NR_OF_SNAPSHOTS; + snap_idx++) { + + Snapshot const &snap { req._snapshots.items[snap_idx] }; + if (snap.valid && snap.contains_vba(req._vba)) { + + if (next_snap_idx_valid) { + + Snapshot const &next_snap { req._snapshots.items[next_snap_idx] }; + if (snap.gen > next_snap.gen && + snap.gen < old_snap.gen) + next_snap_idx = snap_idx; + + } else { + + if (snap.gen < old_snap.gen) { + + next_snap_idx = snap_idx; + next_snap_idx_valid = true; + } + } + } + } + return next_snap_idx_valid; +} + + +void Virtual_block_device:: +_set_args_for_alloc_of_new_pbas_for_rekeying(Channel &chan, + uint64_t chan_idx, + Tree_level_index min_lvl) +{ + bool const for_curr_gen_blks { chan._first_snapshot }; + Generation const curr_gen { chan._request._curr_gen }; + Snapshot const &snap { chan._request._snapshots.items[chan._snapshot_idx] }; + Tree_degree const snap_degree { chan._request._snapshots_degree }; + Virtual_block_address const vba { chan._request._vba }; + Type_1_node_blocks const &t1_blks { chan._t1_blks }; + Type_1_node_walk &t1_walk { chan._t1_node_walk }; + Tree_walk_pbas &new_pbas { chan._new_pbas }; + + if (min_lvl > snap.max_level) { + class Exception_1 { }; + throw Exception_1 { }; + } + chan._nr_of_blks = 0; + + if (for_curr_gen_blks) + chan._free_gen = curr_gen; + else + chan._free_gen = snap.gen + 1; + + for (Tree_level_index lvl = 0; lvl <= TREE_MAX_LEVEL; lvl++) { + + if (lvl > snap.max_level) { + + t1_walk.nodes[lvl] = { }; + new_pbas.pbas[lvl] = 0; + + } else if (lvl == snap.max_level) { + + chan._nr_of_blks++; + new_pbas.pbas[lvl] = 0; + t1_walk.nodes[lvl] = { snap.pba, snap.gen, snap.hash }; + + } else if (lvl >= min_lvl) { + + chan._nr_of_blks++; + new_pbas.pbas[lvl] = 0; + Tree_node_index const child_idx { + t1_child_idx_for_vba(vba, lvl + 1, snap_degree) }; + + t1_walk.nodes[lvl] = t1_blks.items[lvl + 1].nodes[child_idx]; + + } else { + + Tree_node_index const child_idx { + t1_child_idx_for_vba(vba, lvl + 1, snap_degree) }; + + Type_1_node const &child { t1_blks.items[lvl + 1].nodes[child_idx] }; + t1_walk.nodes[lvl] = { new_pbas.pbas[lvl], child.gen, child.hash}; + } + } + if (for_curr_gen_blks) { + + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_VBD_FT_ALLOC_FOR_RKG_CURR_GEN_BLKS, + .blk_nr = 0, + .idx = chan_idx + }; + + } else { + + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_VBD_FT_ALLOC_FOR_RKG_OLD_GEN_BLKS, + .blk_nr = 0, + .idx = chan_idx + }; + } +} + + +void Virtual_block_device::_execute_rekey_vba(Channel &chan, + uint64_t chan_idx, + bool &progress) +{ + Request &req { chan._request }; + switch (chan._state) { + case Channel::State::SUBMITTED: + { + req._snapshots.discard_disposable_snapshots( + req._curr_gen, req._last_secured_generation); + + Snapshot_index first_snap_idx { 0 }; + bool first_snap_idx_found { false }; + for (Snapshot_index snap_idx { 0 }; + snap_idx < MAX_NR_OF_SNAPSHOTS; + snap_idx++) { + + Snapshot const &snap { req._snapshots.items[snap_idx] }; + Snapshot const &first_snap { req._snapshots.items[first_snap_idx] }; + if (snap.valid && + (!first_snap_idx_found || snap.gen > first_snap.gen)) { + + first_snap_idx = snap_idx; + first_snap_idx_found = true; + } + } + if (!first_snap_idx_found) { + + class Exception_1 { }; + throw Exception_1 { }; + } + chan._snapshot_idx = first_snap_idx; + chan._first_snapshot = true; + + Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; + chan._t1_blk_idx = snap.max_level; + chan._t1_blks_old_pbas.items[chan._t1_blk_idx] = snap.pba; + + if (VERBOSE_REKEYING) { + log(" snapshot ", chan._snapshot_idx, ":"); + log(" lvl ", (Tree_level_index)snap.max_level + 1, + ": old snap: ", snap); + } + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_VBD_CACHE, + .blk_nr = snap.pba, + .idx = chan_idx + }; + chan._state = Channel::READ_ROOT_NODE_PENDING; + progress = true; + + break; + } + case Channel::READ_ROOT_NODE_COMPLETED: + case Channel::READ_INNER_NODE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; + if (chan._t1_blk_idx == snap.max_level) { + + if (!check_sha256_4k_hash(&chan._t1_blks.items[chan._t1_blk_idx], &snap.hash)) { + + _mark_req_failed(chan, progress, "check root node hash"); + break; + } + + } else { + + Tree_level_index const parent_lvl { chan._t1_blk_idx + 1 }; + Tree_node_index const child_idx { + t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; + + if (!check_sha256_4k_hash(&chan._t1_blks.items[chan._t1_blk_idx], + &chan._t1_blks.items[parent_lvl].nodes[child_idx].hash)) { + + _mark_req_failed(chan, progress, "check inner node hash"); + break; + } + } + if (chan._t1_blk_idx > 1) { + + Tree_level_index const parent_lvl { chan._t1_blk_idx }; + Tree_level_index const child_lvl { parent_lvl - 1 }; + Tree_node_index const child_idx { + t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; + + Type_1_node const &child { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; + + if (VERBOSE_REKEYING) + log(" lvl ", parent_lvl, ": old t1 node ", child_idx, + ": ", child); + + if (!chan._first_snapshot && + chan._t1_blks_old_pbas.items[child_lvl] == child.pba) { + + /* + * The rest of this branch has already been rekeyed while + * rekeying the vba at another snapshot and can therefore be + * skipped. + */ + chan._t1_blk_idx = child_lvl; + _set_args_for_alloc_of_new_pbas_for_rekeying(chan, chan_idx, parent_lvl); + chan._state = Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_PENDING; + progress = true; + + } else { + + chan._t1_blk_idx = child_lvl; + chan._t1_blks_old_pbas.items[child_lvl] = child.pba; + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_VBD_CACHE, + .blk_nr = child.pba, + .idx = chan_idx + }; + chan._state = Channel::READ_INNER_NODE_PENDING; + progress = true; + } + + } else { + + Tree_level_index const parent_lvl { chan._t1_blk_idx }; + Tree_node_index const child_idx { + t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; + + Type_1_node const &child { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; + + if (VERBOSE_REKEYING) + log(" lvl ", parent_lvl, ": old t1 node ", child_idx, + ": ", child); + + if (!chan._first_snapshot + && chan._data_blk_old_pba == child.pba) { + + /* + * The leaf node of this branch has already been rekeyed while + * rekeying the vba at another snapshot and can therefore be + * skipped. + */ + _set_args_for_alloc_of_new_pbas_for_rekeying( + chan, chan_idx, parent_lvl); + + chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING; + progress = true; + + } else if (child.gen == INITIAL_GENERATION) { + + /* + * The leaf node of this branch is still unused and can + * therefore be skipped because the driver will yield all + * zeroes for it regardless of the used key. + */ + _set_args_for_alloc_of_new_pbas_for_rekeying(chan, chan_idx, 0); + chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING; + progress = true; + + } else { + + chan._data_blk_old_pba = child.pba; + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_VBD_BLK_IO, + .blk_nr = child.pba, + .idx = chan_idx + }; + chan._state = Channel::READ_LEAF_NODE_PENDING; + progress = true; + } + } + break; + } + case Channel::READ_LEAF_NODE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Tree_level_index const parent_lvl { FIRST_T1_NODE_BLKS_IDX }; + Tree_node_index const child_idx { + t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; + + Type_1_node &node { + chan._t1_blks.items[parent_lvl].nodes[child_idx] }; + + if (!check_sha256_4k_hash(&chan._data_blk, &node.hash)) { + + _mark_req_failed(chan, progress, "check leaf node hash"); + break; + } + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_VBD_CRYPTO_DECRYPT, + .blk_nr = chan._data_blk_old_pba, + .idx = chan_idx + }; + chan._state = Channel::DECRYPT_LEAF_NODE_PENDING; + progress = true; + + if (VERBOSE_REKEYING) + log(" lvl 0: old data: cipher ", chan._data_blk); + + break; + } + case Channel::DECRYPT_LEAF_NODE_COMPLETED: + + if (_handle_failed_generated_req(chan, progress)) + break; + + if (VERBOSE_REKEYING) + log(" plain ", chan._data_blk); + + _set_args_for_alloc_of_new_pbas_for_rekeying(chan, chan_idx, 0); + chan._state = Channel::ALLOC_PBAS_AT_LEAF_LVL_PENDING; + progress = true; + break; + + case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED: + + if (_handle_failed_generated_req(chan, progress)) + break; + + chan._state = Channel::WRITE_LEAF_NODE_COMPLETED; + progress = true; + break; + + case Channel::ALLOC_PBAS_AT_LEAF_LVL_COMPLETED: + + if (_handle_failed_generated_req(chan, progress)) + break; + + chan._generated_prim = { + .op = Generated_prim::WRITE, + .succ = false, + .tg = Channel::TAG_VBD_CRYPTO_ENCRYPT, + .blk_nr = chan._new_pbas.pbas[0], + .idx = chan_idx + }; + chan._state = Channel::ENCRYPT_LEAF_NODE_PENDING; + progress = true; + + if (VERBOSE_REKEYING) + log(" lvl 0: new data: plain ", chan._data_blk); + + break; + + case Channel::ENCRYPT_LEAF_NODE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Tree_level_index const child_lvl { 0 }; + Physical_block_address const child_pba { + chan._new_pbas.pbas[child_lvl] }; + + chan._generated_prim = { + .op = Generated_prim::WRITE, + .succ = false, + .tg = Channel::TAG_VBD_BLK_IO, + .blk_nr = child_pba, + .idx = chan_idx + }; + chan._state = Channel::WRITE_LEAF_NODE_PENDING; + progress = true; + + if (VERBOSE_REKEYING) + log(" cipher ", chan._data_blk); + + break; + } + case Channel::WRITE_LEAF_NODE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Tree_level_index const parent_lvl { 1 }; + Tree_level_index const child_lvl { 0 }; + Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; + Physical_block_address const parent_pba { chan._new_pbas.pbas[parent_lvl] }; + Tree_node_index const child_idx { + t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) }; + + Type_1_node &node { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; + node.pba = child_pba; + calc_sha256_4k_hash(&chan._data_blk, &node.hash); + + if (VERBOSE_REKEYING) + log(" lvl ", parent_lvl, + ": new t1 node ", child_idx, ": ", node); + + chan._generated_prim = { + .op = Generated_prim::WRITE, + .succ = false, + .tg = Channel::TAG_VBD_CACHE, + .blk_nr = parent_pba, + .idx = chan_idx + }; + chan._state = Channel::WRITE_INNER_NODE_PENDING; + progress = true; + break; + } + case Channel::WRITE_INNER_NODE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; + Tree_level_index const parent_lvl { chan._t1_blk_idx + 1 }; + Tree_level_index const child_lvl { chan._t1_blk_idx }; + Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; + Physical_block_address const parent_pba { chan._new_pbas.pbas[parent_lvl] }; + Tree_node_index const child_idx { + t1_child_idx_for_vba(req._vba, parent_lvl, req._snapshots_degree) };; + + Type_1_node &node { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; + node.pba = child_pba; + calc_sha256_4k_hash(&chan._t1_blks.items[child_lvl], &node.hash); + + if (VERBOSE_REKEYING) + log(" lvl ", parent_lvl, + ": new t1 node ", child_idx, ": ", node); + + chan._t1_blk_idx++; + chan._generated_prim = { + .op = Generated_prim::WRITE, + .succ = false, + .tg = Channel::TAG_VBD_CACHE, + .blk_nr = parent_pba, + .idx = chan_idx + }; + if (chan._t1_blk_idx < snap.max_level) + chan._state = Channel::WRITE_INNER_NODE_PENDING; + else + chan._state = Channel::WRITE_ROOT_NODE_PENDING; + + progress = true; + break; + } + case Channel::WRITE_ROOT_NODE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Snapshot &snap { req._snapshots.items[chan._snapshot_idx] }; + Tree_level_index const child_lvl { chan._t1_blk_idx }; + Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; + + snap.pba = child_pba; + calc_sha256_4k_hash(&chan._t1_blks.items[child_lvl], &snap.hash); + + if (VERBOSE_REKEYING) + log(" lvl ", (Tree_level_index)snap.max_level + 1, + ": new snap: ", snap); + + Snapshot_index next_snap_idx { 0 }; + if (_find_next_snap_to_rekey_vba_at(chan, next_snap_idx)) { + + chan._snapshot_idx = next_snap_idx; + Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; + + chan._first_snapshot = false; + chan._t1_blk_idx = snap.max_level; + if (chan._t1_blks_old_pbas.items[chan._t1_blk_idx] == snap.pba) { + + progress = true; + + } else { + + chan._t1_blks_old_pbas.items[chan._t1_blk_idx] = snap.pba; + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_VBD_CACHE, + .blk_nr = snap.pba, + .idx = chan_idx + }; + chan._state = Channel::READ_ROOT_NODE_PENDING; + progress = true; + + if (VERBOSE_REKEYING) + log(" snapshot ", chan._snapshot_idx, ":"); + } + + } else { + + _mark_req_successful(chan, progress); + } + break; + } + case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_COMPLETED: + + if (_handle_failed_generated_req(chan, progress)) + break; + + chan._state = Channel::WRITE_INNER_NODE_COMPLETED; + progress = true; + + default: + + break; + } +} + + +void Virtual_block_device:: +_add_new_root_lvl_to_snap_using_pba_contingent(Channel &chan) +{ + Request &req { chan._request }; + Snapshot_index const old_idx { chan._snapshot_idx }; + Snapshot_index &idx { chan._snapshot_idx }; + Snapshot *snap { req._snapshots.items }; + Physical_block_address new_pba; + + if (snap[idx].max_level == TREE_MAX_LEVEL) { + class Exception_1 { }; + throw Exception_1 { }; + } + Tree_level_index const new_lvl { snap[old_idx].max_level + 1 }; + chan._t1_blks.items[new_lvl] = { }; + chan._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.idx_of_invalid_or_lowest_gen_evictable_snap( + req._curr_gen, req._last_secured_generation); + + if (VERBOSE_VBD_EXTENSION) + log(" new snap ", idx); + } + + _alloc_pba_from_resizing_contingent( + req._pba, req._nr_of_pbas, new_pba); + + snap[idx] = { + Hash { }, new_pba, req._curr_gen, snap[old_idx].nr_of_leaves, + new_lvl, true, 0, false }; + + if (VERBOSE_VBD_EXTENSION) { + log(" update snap ", idx, " ", snap[idx]); + log(" update lvl ", new_lvl, + " child 0 ", chan._t1_blks.items[new_lvl].nodes[0]); + } +} + + +void Virtual_block_device:: +_alloc_pba_from_resizing_contingent(Physical_block_address &first_pba, + Number_of_blocks &nr_of_pbas, + Physical_block_address &allocated_pba) +{ + if (nr_of_pbas == 0) { + class Exception_1 { }; + throw Exception_1 { }; + } + allocated_pba = first_pba; + first_pba++; + nr_of_pbas--; +} + + +void Virtual_block_device:: +_add_new_branch_to_snap_using_pba_contingent(Channel &chan, + Tree_level_index mount_at_lvl, + Tree_node_index mount_at_child_idx) +{ + Request &req { chan._request }; + req._nr_of_leaves = 0; + chan._t1_blk_idx = mount_at_lvl; + + /* reset all levels below mount point */ + if (mount_at_lvl > 1) { + for (Tree_level_index lvl { 1 }; lvl < mount_at_lvl; lvl++) + chan._t1_blks.items[lvl] = { }; + } + if (!req._nr_of_pbas) + return; + + /* set child PBAs of new branch */ + for (Tree_level_index lvl { mount_at_lvl }; lvl > 0; lvl--) { + + chan._t1_blk_idx = lvl; + Tree_node_index child_idx { + lvl == mount_at_lvl ? mount_at_child_idx : 0 }; + + auto add_child_at_curr_lvl_and_child_idx = [&] () { + + if (!req._nr_of_pbas) + return false; + + Physical_block_address child_pba; + _alloc_pba_from_resizing_contingent( + req._pba, req._nr_of_pbas, child_pba); + + Type_1_node &child { chan._t1_blks.items[lvl].nodes[child_idx] }; + child = { child_pba, INITIAL_GENERATION, Hash { } }; + + if (VERBOSE_VBD_EXTENSION) + log(" update lvl ", lvl, " child ", child_idx, " ", child); + + return true; + }; + if (lvl > 1) { + + if (!add_child_at_curr_lvl_and_child_idx()) + return; + + } else { + + for (; child_idx < req._snapshots_degree; child_idx++) { + + if (!add_child_at_curr_lvl_and_child_idx()) + return; + + req._nr_of_leaves++; + } + } + } +} + + +void +Virtual_block_device::_set_new_pbas_identical_to_current_pbas(Channel &chan) +{ + Request &req { chan._request }; + Snapshot &snap { chan._request._snapshots.items[chan._snapshot_idx] }; + + for (Tree_level_index lvl { 0 }; lvl <= TREE_MAX_LEVEL; lvl++) { + + if (lvl > snap.max_level) { + + chan._new_pbas.pbas[lvl] = 0; + + } else if (lvl == snap.max_level) { + + chan._new_pbas.pbas[lvl] = snap.pba; + + } else { + + Tree_node_index const child_idx { + t1_child_idx_for_vba(chan._vba, lvl + 1, req._snapshots_degree) }; + + Type_1_node const &child { + chan._t1_blks.items[lvl + 1].nodes[child_idx] }; + + chan._new_pbas.pbas[lvl] = child.pba; + } + } +} + + +void Virtual_block_device:: +_set_args_for_alloc_of_new_pbas_for_resizing(Channel &chan, + uint64_t chan_idx, + Tree_level_index min_lvl, + bool &progress) +{ + Request const &req { chan._request }; + Snapshot const &snap { req._snapshots.items[chan._snapshot_idx] }; + + if (min_lvl > snap.max_level) { + + _mark_req_failed(chan, progress, "check parent lvl for alloc"); + return; + } + chan._nr_of_blks = 0; + chan._free_gen = req._curr_gen; + for (Tree_level_index lvl = 0; lvl <= TREE_MAX_LEVEL; lvl++) { + + if (lvl > snap.max_level) { + + chan._new_pbas.pbas[lvl] = 0; + chan._t1_node_walk.nodes[lvl] = { }; + + } else if (lvl == snap.max_level) { + + chan._nr_of_blks++; + chan._new_pbas.pbas[lvl] = 0; + chan._t1_node_walk.nodes[lvl] = { + snap.pba, snap.gen, snap.hash }; + + } else { + + Tree_node_index const child_idx { + t1_child_idx_for_vba( + chan._vba, lvl + 1, req._snapshots_degree) }; + + Type_1_node const &child { + chan._t1_blks.items[lvl + 1].nodes[child_idx] }; + + if (lvl >= min_lvl) { + + chan._nr_of_blks++; + chan._new_pbas.pbas[lvl] = 0; + chan._t1_node_walk.nodes[lvl] = child; + + } else { + + /* + * FIXME + * + * This is done only because the Free Tree module would + * otherwise get stuck. It is normal that the lowest + * levels have PBA 0 when creating the new branch + * stopped at an inner node because of a depleted PBA + * contingent. As soon as the strange behavior in the + * Free Tree module has been fixed, the whole 'if' + * statement can be removed. + */ + if (child.pba == 0) { + + chan._new_pbas.pbas[lvl] = INVALID_PBA; + chan._t1_node_walk.nodes[lvl] = { + INVALID_PBA, child.gen, child.hash }; + + } else { + + chan._new_pbas.pbas[lvl] = child.pba; + chan._t1_node_walk.nodes[lvl] = child; + } + } + } + } + chan._generated_prim = { + .op = Channel::Generated_prim::Type::READ, + .succ = false, + .tg = Channel::Tag_type::TAG_VBD_FT_ALLOC_FOR_NON_RKG, + .blk_nr = 0, + .idx = chan_idx + }; + chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING; + progress = true; +} + + + +void Virtual_block_device::_execute_vbd_extension_step(Channel &chan, + uint64_t chan_idx, + bool &progress) +{ + Request &req { chan._request }; + + switch (chan._state) { + case Channel::State::SUBMITTED: + { + req._snapshots.discard_disposable_snapshots( + req._curr_gen, req._last_secured_generation); + + req._nr_of_leaves = 0; + chan._snapshot_idx = req._snapshots.newest_snapshot_idx(); + + chan._vba = chan.snap().nr_of_leaves; + chan._t1_blk_idx = chan.snap().max_level; + chan._t1_blks_old_pbas.items[chan._t1_blk_idx] = chan.snap().pba; + + if (chan._vba <= tree_max_max_vba(req._snapshots_degree, chan.snap().max_level)) { + + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_VBD_CACHE, + .blk_nr = chan.snap().pba, + .idx = chan_idx + }; + + if (VERBOSE_VBD_EXTENSION) + log(" read lvl ", chan._t1_blk_idx, + " parent snap ", chan._snapshot_idx, + " ", chan.snap()); + + chan._state = Channel::READ_ROOT_NODE_PENDING; + progress = true; + + } else { + + _add_new_root_lvl_to_snap_using_pba_contingent(chan); + _add_new_branch_to_snap_using_pba_contingent(chan, req._snapshots.items[chan._snapshot_idx].max_level, 1); + _set_new_pbas_identical_to_current_pbas(chan); + _set_args_for_write_back_of_t1_lvl( + chan.snap().max_level, chan._t1_blk_idx, + chan._new_pbas.pbas[chan._t1_blk_idx], chan_idx, + chan._state, progress, chan._generated_prim); + + if (VERBOSE_VBD_EXTENSION) + log(" write 1 lvl ", chan._t1_blk_idx, " pba ", + (Physical_block_address)chan._new_pbas.pbas[chan._t1_blk_idx]); + } + break; + } + case Channel::READ_ROOT_NODE_COMPLETED: + case Channel::READ_INNER_NODE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + if (chan._t1_blk_idx == chan.snap().max_level) { + + if (!check_sha256_4k_hash(&chan._t1_blks.items[chan._t1_blk_idx], &chan.snap().hash)) { + + _mark_req_failed(chan, progress, "check root node hash"); + break; + } + + } else { + + Tree_level_index const parent_lvl { chan._t1_blk_idx + 1 }; + Tree_node_index const child_idx { + t1_child_idx_for_vba(chan._vba, parent_lvl, req._snapshots_degree) }; + + if (!check_sha256_4k_hash(&chan._t1_blks.items[chan._t1_blk_idx], + &chan._t1_blks.items[parent_lvl].nodes[child_idx].hash)) { + + _mark_req_failed(chan, progress, "check inner node hash"); + break; + } + } + if (chan._t1_blk_idx > 1) { + + Tree_level_index const parent_lvl { chan._t1_blk_idx }; + Tree_level_index const child_lvl { parent_lvl - 1 }; + Tree_node_index const child_idx { + t1_child_idx_for_vba(chan._vba, parent_lvl, req._snapshots_degree) }; + + Type_1_node const &child { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; + + if (child.valid()) { + + chan._t1_blk_idx = child_lvl; + chan._t1_blks_old_pbas.items[child_lvl] = child.pba; + chan._generated_prim = { + .op = Generated_prim::READ, + .succ = false, + .tg = Channel::TAG_VBD_CACHE, + .blk_nr = child.pba, + .idx = chan_idx + }; + chan._state = Channel::READ_INNER_NODE_PENDING; + progress = true; + + if (VERBOSE_VBD_EXTENSION) + log(" read lvl ", child_lvl, " parent lvl ", parent_lvl, + " child ", child_idx, " ", child); + + } else { + _add_new_branch_to_snap_using_pba_contingent(chan, parent_lvl, child_idx); + _set_args_for_alloc_of_new_pbas_for_resizing(chan, chan_idx, parent_lvl, progress); + break; + } + + } else { + + Tree_level_index const parent_lvl { chan._t1_blk_idx }; + Tree_node_index const child_idx { + t1_child_idx_for_vba(chan._vba, parent_lvl, req._snapshots_degree) }; + + _add_new_branch_to_snap_using_pba_contingent(chan, parent_lvl, child_idx); + _set_args_for_alloc_of_new_pbas_for_resizing(chan, chan_idx, parent_lvl, progress); + break; + } + break; + } + case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Physical_block_address const new_pba { + chan._new_pbas.pbas[chan._t1_blk_idx] }; + + if (VERBOSE_VBD_EXTENSION) { + log(" allocated ", chan._nr_of_blks, " pbas"); + for (Tree_level_index lvl { 0 }; lvl < chan.snap().max_level; lvl++) { + log(" lvl ", lvl, " ", + chan._t1_node_walk.nodes[lvl], " -> pba ", + (Physical_block_address)chan._new_pbas.pbas[lvl]); + } + log(" write 1 lvl ", chan._t1_blk_idx, " pba ", new_pba); + } + chan._generated_prim = { + .op = Generated_prim::WRITE, + .succ = false, + .tg = Channel::TAG_VBD_CACHE, + .blk_nr = new_pba, + .idx = chan_idx + }; + if (chan._t1_blk_idx < chan.snap().max_level) + chan._state = Channel::WRITE_INNER_NODE_PENDING; + else + chan._state = Channel::WRITE_ROOT_NODE_PENDING; + + progress = true; + break; + } + case Channel::WRITE_INNER_NODE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Tree_level_index const parent_lvl { chan._t1_blk_idx + 1 }; + Tree_level_index const child_lvl { chan._t1_blk_idx }; + Tree_node_index const child_idx { t1_child_idx_for_vba(chan._vba, parent_lvl, req._snapshots_degree) }; + Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; + Physical_block_address const parent_pba { chan._new_pbas.pbas[parent_lvl] }; + Type_1_node &child { chan._t1_blks.items[parent_lvl].nodes[child_idx] }; + + calc_sha256_4k_hash(&chan._t1_blks.items[child_lvl], &child.hash); + child.pba = child_pba; + + if (VERBOSE_VBD_EXTENSION) { + log(" update lvl ", parent_lvl, " child ", child_idx, " ", child); + log(" write 2 lvl ", parent_lvl, " pba ", parent_pba); + } + chan._t1_blk_idx++; + chan._generated_prim = { + .op = Generated_prim::WRITE, + .succ = false, + .tg = Channel::TAG_VBD_CACHE, + .blk_nr = parent_pba, + .idx = chan_idx + }; + if (chan._t1_blk_idx < chan.snap().max_level) + chan._state = Channel::WRITE_INNER_NODE_PENDING; + else + chan._state = Channel::WRITE_ROOT_NODE_PENDING; + + progress = true; + break; + } + case Channel::WRITE_ROOT_NODE_COMPLETED: + { + if (_handle_failed_generated_req(chan, progress)) + break; + + Tree_level_index const child_lvl { chan._t1_blk_idx }; + Physical_block_address const child_pba { chan._new_pbas.pbas[child_lvl] }; + Snapshot const &old_snap { req._snapshots.items[chan._snapshot_idx] }; + + if (old_snap.gen < req._curr_gen) { + + chan._snapshot_idx = + req._snapshots.idx_of_invalid_or_lowest_gen_evictable_snap( + req._curr_gen, req._last_secured_generation); + + if (VERBOSE_VBD_EXTENSION) + log(" new snap ", chan._snapshot_idx); + } + + Snapshot &new_snap { req._snapshots.items[chan._snapshot_idx] }; + new_snap = { + Hash { }, child_pba, req._curr_gen, + old_snap.nr_of_leaves + req._nr_of_leaves, old_snap.max_level, + true, 0, false }; + + calc_sha256_4k_hash(&chan._t1_blks.items[child_lvl], &new_snap.hash); + + if (VERBOSE_VBD_EXTENSION) + log(" update snap ", chan._snapshot_idx, " ", new_snap); + + _mark_req_successful(chan, progress); + break; + } + default: + + break; + } +} + + +void Virtual_block_device::execute(bool &progress) +{ + for (unsigned idx = 0; idx < NR_OF_CHANNELS; idx++) { + + Channel &channel = _channels[idx]; + Request &request { channel._request }; + + switch (request._type) { + case Request::INVALID: + break; + case Request::READ_VBA: + _execute_read_vba(channel, idx, progress); + break; + case Request::WRITE_VBA: + _execute_write_vba(channel, idx, progress); + break; + case Request::REKEY_VBA: + _execute_rekey_vba(channel, idx, progress); + break; + case Request::VBD_EXTENSION_STEP: + _execute_vbd_extension_step(channel, idx, progress); + break; + } + } +} + + +bool Virtual_block_device::_peek_generated_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (uint32_t id { 0 }; id < NR_OF_CHANNELS; id++) { + + Channel &chan { _channels[id] }; + Request &req { chan._request }; + if (req._type == Request::INVALID) + continue; + + switch (chan._state) { + case Channel::WRITE_ROOT_NODE_PENDING: + case Channel::WRITE_INNER_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, + Block_io_request::WRITE, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, + &chan._t1_blks.items[chan._t1_blk_idx], nullptr); + + return true; + + case Channel::WRITE_LEAF_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, + Block_io_request::WRITE, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, + &chan._data_blk, nullptr); + + return true; + + case Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, + Block_io_request::WRITE_CLIENT_DATA, req._client_req_offset, + req._client_req_tag, req._new_key_id, + chan._generated_prim.blk_nr, chan._vba, 1, nullptr, + &chan._hash); + + return true; + + case Channel::READ_ROOT_NODE_PENDING: + case Channel::READ_INNER_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, + Block_io_request::READ, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, + &chan._t1_blks.items[chan._t1_blk_idx], nullptr); + + return true; + + case Channel::READ_LEAF_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, + Block_io_request::READ, 0, 0, 0, + chan._generated_prim.blk_nr, 0, 1, &chan._data_blk, nullptr); + + return true; + + case Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, + Block_io_request::READ_CLIENT_DATA, req._client_req_offset, + req._client_req_tag, req._new_key_id, + chan._generated_prim.blk_nr, chan._vba, 1, nullptr, nullptr); + + return true; + + case Channel::DECRYPT_LEAF_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, + Crypto_request::DECRYPT, + 0, 0, req._old_key_id, nullptr, + chan._generated_prim.blk_nr, 0, &chan._data_blk, + &chan._data_blk); + + return true; + + case Channel::ENCRYPT_LEAF_NODE_PENDING: + + construct_in_buf( + buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, + Crypto_request::ENCRYPT, + 0, 0, req._new_key_id, nullptr, + chan._generated_prim.blk_nr, 0, &chan._data_blk, + &chan._data_blk); + + return true; + + case Channel::ALLOC_PBAS_AT_LEAF_LVL_PENDING: + case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_PENDING: + case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING: + { + Free_tree_request::Type ftrt { Free_tree_request::INVALID }; + switch (chan._generated_prim.tg) { + case Channel::TAG_VBD_FT_ALLOC_FOR_NON_RKG: ftrt = Free_tree_request::ALLOC_FOR_NON_RKG; break; + case Channel::TAG_VBD_FT_ALLOC_FOR_RKG_CURR_GEN_BLKS: ftrt = Free_tree_request::ALLOC_FOR_RKG_CURR_GEN_BLKS; break; + case Channel::TAG_VBD_FT_ALLOC_FOR_RKG_OLD_GEN_BLKS: ftrt = Free_tree_request::ALLOC_FOR_RKG_OLD_GEN_BLKS; break; + default: break; + } + if (ftrt == Free_tree_request::INVALID) { + class Exception_1 { }; + throw Exception_1 { }; + } + construct_in_buf( + buf_ptr, buf_size, VIRTUAL_BLOCK_DEVICE, id, + ftrt, req._ft_root_pba_ptr, + req._ft_root_gen_ptr, req._ft_root_hash_ptr, + req._ft_max_level, req._ft_degree, req._ft_leaves, + req._mt_root_pba_ptr, req._mt_root_gen_ptr, + req._mt_root_hash_ptr, req._mt_max_level, req._mt_degree, + req._mt_leaves, &req._snapshots, req._last_secured_generation, + req._curr_gen, chan._free_gen, chan._nr_of_blks, + (addr_t)&chan._new_pbas, (addr_t)&chan._t1_node_walk, + (uint64_t)req._snapshots.items[chan._snapshot_idx].max_level, + chan._vba, req._vbd_degree, req._vbd_highest_vba, + req._rekeying, req._old_key_id, req._new_key_id, chan._vba); + + return true; + } + default: break; + } + } + return false; +} + + +void Virtual_block_device::_drop_generated_request(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (chan._state) { + case Channel::READ_ROOT_NODE_PENDING: chan._state = Channel::READ_ROOT_NODE_IN_PROGRESS; break; + case Channel::READ_INNER_NODE_PENDING: chan._state = Channel::READ_INNER_NODE_IN_PROGRESS; break; + case Channel::WRITE_ROOT_NODE_PENDING: chan._state = Channel::WRITE_ROOT_NODE_IN_PROGRESS; break; + case Channel::WRITE_INNER_NODE_PENDING: chan._state = Channel::WRITE_INNER_NODE_IN_PROGRESS; break; + case Channel::READ_LEAF_NODE_PENDING: chan._state = Channel::READ_LEAF_NODE_IN_PROGRESS; break; + case Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_PENDING: chan._state = Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_IN_PROGRESS; break; + case Channel::WRITE_LEAF_NODE_PENDING: chan._state = Channel::WRITE_LEAF_NODE_IN_PROGRESS; break; + case Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_PENDING: chan._state = Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_IN_PROGRESS; break; + case Channel::DECRYPT_LEAF_NODE_PENDING: chan._state = Channel::DECRYPT_LEAF_NODE_IN_PROGRESS; break; + case Channel::ENCRYPT_LEAF_NODE_PENDING: chan._state = Channel::ENCRYPT_LEAF_NODE_IN_PROGRESS; break; + case Channel::ALLOC_PBAS_AT_LEAF_LVL_PENDING: chan._state = Channel::ALLOC_PBAS_AT_LEAF_LVL_IN_PROGRESS; break; + case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_PENDING: chan._state = Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_IN_PROGRESS; break; + case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_PENDING: chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_IN_PROGRESS; break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } +} + + +void Virtual_block_device::generated_request_complete(Module_request &mod_req) +{ + Module_request_id const id { mod_req.src_request_id() }; + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + switch (mod_req.dst_module_id()) { + case CRYPTO: + { + Crypto_request &crypto_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = crypto_req.success(); + switch (chan._state) { + case Channel::DECRYPT_LEAF_NODE_IN_PROGRESS: chan._state = Channel::DECRYPT_LEAF_NODE_COMPLETED; break; + case Channel::ENCRYPT_LEAF_NODE_IN_PROGRESS: chan._state = Channel::ENCRYPT_LEAF_NODE_COMPLETED; break; + default: + class Exception_3 { }; + throw Exception_3 { }; + } + break; + } + case BLOCK_IO: + { + Block_io_request &blk_io_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = blk_io_req.success(); + switch (chan._state) { + case Channel::READ_ROOT_NODE_IN_PROGRESS: chan._state = Channel::READ_ROOT_NODE_COMPLETED; break; + case Channel::READ_INNER_NODE_IN_PROGRESS: chan._state = Channel::READ_INNER_NODE_COMPLETED; break; + case Channel::WRITE_ROOT_NODE_IN_PROGRESS: chan._state = Channel::WRITE_ROOT_NODE_COMPLETED; break; + case Channel::WRITE_INNER_NODE_IN_PROGRESS: chan._state = Channel::WRITE_INNER_NODE_COMPLETED; break; + case Channel::READ_LEAF_NODE_IN_PROGRESS: chan._state = Channel::READ_LEAF_NODE_COMPLETED; break; + case Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_IN_PROGRESS: chan._state = Channel::READ_CLIENT_DATA_FROM_LEAF_NODE_COMPLETED; break; + case Channel::WRITE_LEAF_NODE_IN_PROGRESS: chan._state = Channel::WRITE_LEAF_NODE_COMPLETED; break; + case Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_IN_PROGRESS: chan._state = Channel::WRITE_CLIENT_DATA_TO_LEAF_NODE_COMPLETED; break; + default: + class Exception_4 { }; + throw Exception_4 { }; + } + break; + } + case FREE_TREE: + { + Free_tree_request &ft_req { *static_cast(&mod_req) }; + chan._generated_prim.succ = ft_req.success(); + switch (chan._state) { + case Channel::ALLOC_PBAS_AT_LEAF_LVL_IN_PROGRESS: chan._state = Channel::ALLOC_PBAS_AT_LEAF_LVL_COMPLETED; break; + case Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_IN_PROGRESS: chan._state = Channel::ALLOC_PBAS_AT_HIGHER_INNER_LVL_COMPLETED; break; + case Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_IN_PROGRESS: chan._state = Channel::ALLOC_PBAS_AT_LOWEST_INNER_LVL_COMPLETED; break; + default: + class Exception_2 { }; + throw Exception_2 { }; + } + break; + } + default: + class Exception_5 { }; + throw Exception_5 { }; + } +} + + +bool Virtual_block_device::_peek_completed_request(uint8_t *buf_ptr, + size_t buf_size) +{ + for (Channel &channel : _channels) { + if (channel._request._type != Request::INVALID && + channel._state == Channel::COMPLETED) { + + if (sizeof(channel._request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + memcpy(buf_ptr, &channel._request, sizeof(channel._request)); + return true; + } + } + return false; +} + + +void Virtual_block_device::_drop_completed_request(Module_request &req) +{ + Module_request_id id { 0 }; + id = req.dst_request_id(); + if (id >= NR_OF_CHANNELS) { + class Exception_1 { }; + throw Exception_1 { }; + } + Channel &chan { _channels[id] }; + if (chan._request._type == Request::INVALID || + chan._state != Channel::COMPLETED) { + + class Exception_2 { }; + throw Exception_2 { }; + } + chan._request._type = Request::INVALID; +} diff --git a/repos/gems/src/lib/vfs/cbe/io_job.h b/repos/gems/src/lib/vfs/cbe/io_job.h deleted file mode 100644 index c010120688..0000000000 --- a/repos/gems/src/lib/vfs/cbe/io_job.h +++ /dev/null @@ -1,293 +0,0 @@ -/* - * \brief Integration of the Consistent Block Encrypter (CBE) - * \author Martin Stein - * \author Josef Soentgen - * \date 2020-11-10 - */ - -/* - * Copyright (C) 2020 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#ifndef _CBE_VFS__IO_JOB_ -#define _CBE_VFS__IO_JOB_ - -namespace Vfs_cbe { - - using file_size = Vfs::file_size; - using file_offset = Vfs::file_offset; - using Byte_range_ptr = Vfs::Byte_range_ptr; - using Const_byte_range_ptr = Vfs::Const_byte_range_ptr; - using size_t = Genode::size_t; - - struct Io_job - { - struct Unsupported_Operation : Genode::Exception { }; - struct Invalid_state : Genode::Exception { }; - - enum State { PENDING, IN_PROGRESS, COMPLETE, }; - - static State _initial_state(Cbe::Request::Operation const op) - { - using Op = Cbe::Request::Operation; - - switch (op) { - case Op::READ: return State::PENDING; - case Op::WRITE: return State::PENDING; - case Op::SYNC: return State::PENDING; - default: throw Unsupported_Operation(); - } - } - - static char const *_state_to_string(State s) - { - switch (s) { - case State::PENDING: return "PENDING"; - case State::IN_PROGRESS: return "IN_PROGRESS"; - case State::COMPLETE: return "COMPLETE"; - } - - throw Invalid_state(); - } - - Vfs::Vfs_handle &_handle; - - Cbe::Request::Operation const _op; - Cbe::Io_buffer::Index const _index; - State _state; - file_offset const _base_offset; - file_offset _current_offset; - file_size _current_count; - - bool _success; - bool _complete; - - bool _read(Cbe::Library &cbe, Cbe::Io_buffer &io_data) - { - bool progress = false; - - switch (_state) { - case State::PENDING: - - _handle.seek(_base_offset + _current_offset); - if (!_handle.fs().queue_read(&_handle, _current_count)) { - return progress; - } - - cbe.io_request_in_progress(_index); - - _state = State::IN_PROGRESS; - progress = true; - [[fallthrough]]; - case State::IN_PROGRESS: - { - using Result = Vfs::File_io_service::Read_result; - - bool completed = false; - size_t out = 0; - - char * const data = reinterpret_cast(&io_data.item(_index)); - - Byte_range_ptr const dst(data + _current_offset, _current_count); - - Result const result = _handle.fs().complete_read(&_handle, dst, out); - - if (result == Result::READ_QUEUED - || result == Result::READ_ERR_WOULD_BLOCK) { - return progress; - } else - - if (result == Result::READ_OK) { - _current_offset += out; - _current_count -= out; - _success = true; - } else - - if ( result == Result::READ_ERR_IO - || result == Result::READ_ERR_INVALID) { - _success = false; - completed = true; - } - - if (_current_count == 0 || completed) { - _state = State::COMPLETE; - } else { - _state = State::PENDING; - /* partial read, keep trying */ - return true; - } - progress = true; - } - [[fallthrough]]; - case State::COMPLETE: - - cbe.io_request_completed(_index, _success); - _complete = true; - progress = true; - default: break; - } - - return progress; - } - - bool _write(Cbe::Library &cbe, Cbe::Io_buffer &io_data) - { - bool progress = false; - - switch (_state) { - case State::PENDING: - - _handle.seek(_base_offset + _current_offset); - - cbe.io_request_in_progress(_index); - _state = State::IN_PROGRESS; - progress = true; - [[fallthrough]]; - case State::IN_PROGRESS: - { - using Result = Vfs::File_io_service::Write_result; - - bool completed = false; - size_t out = 0; - - char const * const data = - reinterpret_cast(&io_data.item(_index)); - - Const_byte_range_ptr const src(data + _current_offset, _current_count); - - Result const result = _handle.fs().write(&_handle, src, out); - - switch (result) { - case Result::WRITE_ERR_WOULD_BLOCK: - return progress; - - case Result::WRITE_OK: - _current_offset += out; - _current_count -= out; - _success = true; - break; - - case Result::WRITE_ERR_IO: - case Result::WRITE_ERR_INVALID: - _success = false; - completed = true; - break; - } - - if (_current_count == 0 || completed) { - _state = State::COMPLETE; - } else { - _state = State::PENDING; - /* partial write, keep trying */ - return true; - } - progress = true; - } - [[fallthrough]]; - case State::COMPLETE: - - cbe.io_request_completed(_index, _success); - _complete = true; - progress = true; - default: break; - } - - return progress; - } - - bool _sync(Cbe::Library &cbe, Cbe::Io_buffer &io_data) - { - bool progress = false; - - switch (_state) { - case State::PENDING: - - if (!_handle.fs().queue_sync(&_handle)) { - return progress; - } - cbe.io_request_in_progress(_index); - _state = State::IN_PROGRESS; - progress = true; - [[fallthrough]]; - case State::IN_PROGRESS: - { - using Result = Vfs::File_io_service::Sync_result; - Result const result = _handle.fs().complete_sync(&_handle); - - if (result == Result::SYNC_QUEUED) { - return progress; - } else - - if (result == Result::SYNC_ERR_INVALID) { - _success = false; - } else - - if (result == Result::SYNC_OK) { - _success = true; - } - - _state = State::COMPLETE; - progress = true; - } - [[fallthrough]]; - case State::COMPLETE: - - cbe.io_request_completed(_index, _success); - _complete = true; - progress = true; - default: break; - } - - return progress; - } - - Io_job(Vfs::Vfs_handle &handle, - Cbe::Request::Operation op, - Cbe::Io_buffer::Index index, - file_offset base_offset, - file_size length) - : - _handle { handle }, - _op { op }, - _index { index }, - _state { _initial_state(op) }, - _base_offset { base_offset }, - _current_offset { 0 }, - _current_count { length }, - _success { false }, - _complete { false } - { } - - bool completed() const { return _complete; } - bool succeeded() const { return _success; } - - void print(Genode::Output &out) const - { - Genode::print(out, "(", to_string(_op), ")", - " state: ", _state_to_string(_state), - " base_offset: ", _base_offset, - " current_offset: ", _current_offset, - " current_count: ", _current_count, - " success: ", _success, - " complete: ", _complete); - } - - bool execute(Cbe::Library &cbe, Cbe::Io_buffer &io_data) - { - using Op = Cbe::Request::Operation; - - switch (_op) { - case Op::READ: return _read(cbe, io_data); - case Op::WRITE: return _write(cbe, io_data); - case Op::SYNC: return _sync(cbe, io_data); - default: return false; - } - } - }; - -} /* namespace Vfs_cbe */ - -#endif /* _CBE_VFS__IO_JOB_ */ diff --git a/repos/gems/src/lib/vfs/cbe_crypto/aes_cbc/dummy.ads b/repos/gems/src/lib/vfs/cbe_crypto/aes_cbc/dummy.ads deleted file mode 100644 index bf6121ad6e..0000000000 --- a/repos/gems/src/lib/vfs/cbe_crypto/aes_cbc/dummy.ads +++ /dev/null @@ -1,17 +0,0 @@ --- --- \brief Integration of the Consistent Block Encrypter (CBE) --- \author Martin Stein --- \author Josef Soentgen --- \date 2020-11-10 --- - --- --- Copyright (C) 2020 Genode Labs GmbH --- --- This file is part of the Genode OS framework, which is distributed --- under the terms of the GNU Affero General Public License version 3. --- - -package Dummy -is -end Dummy; diff --git a/repos/gems/src/lib/vfs/cbe/vfs.cc b/repos/gems/src/lib/vfs/tresor/vfs.cc similarity index 58% rename from repos/gems/src/lib/vfs/cbe/vfs.cc rename to repos/gems/src/lib/vfs/tresor/vfs.cc index a0dca924bd..cebaad33ea 100644 --- a/repos/gems/src/lib/vfs/cbe/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor/vfs.cc @@ -1,5 +1,5 @@ /* - * \brief Integration of the Consistent Block Encrypter (CBE) + * \brief Integration of the Tresor block encryption * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 @@ -19,22 +19,30 @@ #include #include -/* CBE includes */ -#include -#include - -/* local includes */ -#include +/* tresor includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include -namespace Vfs_cbe { +namespace Vfs_tresor { using namespace Vfs; using namespace Genode; + using namespace Tresor; class Data_file_system; class Extend_file_system; + class Extend_progress_file_system; class Rekey_file_system; + class Rekey_progress_file_system; class Deinitialize_file_system; class Create_snapshot_file_system; class Discard_snapshot_file_system; @@ -51,7 +59,6 @@ namespace Vfs_cbe { struct Local_factory; class File_system; - class Backend_file; class Wrapper; template @@ -82,69 +89,145 @@ namespace Vfs_cbe { } -extern "C" void adainit(); - - -extern "C" void print_u8(unsigned char const u) { Genode::log(u); } - - -class Vfs_cbe::Wrapper +class Vfs_tresor::Wrapper +: + private Tresor::Module_composition, + public Tresor::Module { private: - Vfs::Env &_env; + Vfs::Env &_vfs_env; - Vfs_handle *_backend_handle { nullptr }; - Constructible _backend_job { }; + Constructible _request_pool { }; + Constructible _free_tree { }; + Constructible _ft_resizing { }; + Constructible _vbd { }; + Constructible _sb_control { }; + Tresor::Meta_tree _meta_tree { }; + Constructible _trust_anchor { }; + Constructible _crypto { }; + Constructible _block_io { }; - Vfs_handle *_add_key_handle { nullptr }; - Vfs_handle *_remove_key_handle { nullptr }; - - struct Crypto_file - { - Vfs_handle *encrypt_handle; - Vfs_handle *decrypt_handle; - uint32_t key_id; - }; - - enum { NUM_CRYPTO_FILES = 2, }; - - Crypto_file _crypto_file[NUM_CRYPTO_FILES] { - { .encrypt_handle = nullptr, .decrypt_handle = nullptr, .key_id = 0 }, - { .encrypt_handle = nullptr, .decrypt_handle = nullptr, .key_id = 0 } }; - - Crypto_file *_get_unused_crypto_file() - { - for (Crypto_file &file : _crypto_file) { - if (file.key_id == 0) { - return &file; - } - } - struct No_unused_crypt_file_left { }; - throw No_unused_crypt_file_left(); - } - - Crypto_file *_lookup_crypto_file(uint32_t key_id) - { - for (Crypto_file &file : _crypto_file) { - if (file.key_id == key_id) { - return &file; - } - } - struct Crypt_file_not_found { }; - throw Crypt_file_not_found(); - } - - Cbe::Io_buffer _io_data { }; - Cbe::Crypto_cipher_buffer _cipher_data { }; - Cbe::Crypto_plain_buffer _plain_data { }; - - Constructible _trust_anchor { }; - - Constructible _cbe; + Client_data_request _client_data_request { }; public: + /******************************** + ** Module API for Client_data ** + ********************************/ + + bool ready_to_submit_request() override + { + return _client_data_request._type == Client_data_request::INVALID; + } + + void submit_request(Module_request &req) override + { + if (_client_data_request._type != Client_data_request::INVALID) { + + class Exception_1 { }; + throw Exception_1 { }; + } + req.dst_request_id(0); + _client_data_request = *dynamic_cast(&req); + switch (_client_data_request._type) { + case Client_data_request::OBTAIN_PLAINTEXT_BLK: + { + void const *src = + _lookup_write_buffer(_client_data_request._client_req_tag, + _client_data_request._vba); + if (src == nullptr) { + _client_data_request._success = false; + break; + } + + (void)memcpy((void*)_client_data_request._plaintext_blk_ptr, + src, sizeof(Tresor::Block)); + + _client_data_request._success = true; + break; + } + case Client_data_request::SUPPLY_PLAINTEXT_BLK: + { + void *dst = + _lookup_read_buffer(_client_data_request._client_req_tag, + _client_data_request._vba); + if (dst == nullptr) { + _client_data_request._success = false; + break; + } + + (void)memcpy(dst, (void const*)_client_data_request._plaintext_blk_ptr, + sizeof(Tresor::Block)); + + _client_data_request._success = true; + break; + } + case Client_data_request::INVALID: + + class Exception_2 { }; + throw Exception_2 { }; + } + } + + void execute(bool &progress) override + { + if (_helper_read_request.pending()) { + if (_request_pool->ready_to_submit_request()) { + _helper_read_request.tresor_request.snap_id( + _frontend_request.tresor_request.snap_id()); + _request_pool->submit_request(_helper_read_request.tresor_request); + _helper_read_request.state = Helper_request::State::IN_PROGRESS; + } + } + + if (_helper_write_request.pending()) { + if (_request_pool->ready_to_submit_request()) { + _helper_write_request.tresor_request.snap_id( + _frontend_request.tresor_request.snap_id()); + _request_pool->submit_request(_helper_write_request.tresor_request); + _helper_write_request.state = Helper_request::State::IN_PROGRESS; + } + } + + if (_frontend_request.pending()) { + + using ST = Frontend_request::State; + + Tresor::Request &request = _frontend_request.tresor_request; + + if (_request_pool->ready_to_submit_request()) { + _request_pool->submit_request(request); + _frontend_request.state = ST::IN_PROGRESS; + progress = true; + } + } + } + + bool _peek_completed_request(Genode::uint8_t *buf_ptr, + Genode::size_t buf_size) override + { + if (_client_data_request._type != Client_data_request::INVALID) { + if (sizeof(_client_data_request) > buf_size) { + class Exception_1 { }; + throw Exception_1 { }; + } + Genode::memcpy(buf_ptr, &_client_data_request, + sizeof(_client_data_request));; + return true; + } + return false; + } + + void _drop_completed_request(Module_request &) override + { + if (_client_data_request._type == Client_data_request::INVALID) { + class Exception_2 { }; + throw Exception_2 { }; + } + _client_data_request._type = Client_data_request::INVALID; + } + struct Rekeying { enum State { UNKNOWN, IDLE, IN_PROGRESS, }; @@ -153,6 +236,15 @@ class Vfs_cbe::Wrapper Result last_result; uint32_t key_id; + Virtual_block_address max_vba; + Virtual_block_address rekeying_vba; + uint64_t percent_done; + + bool idle() const { return state == IDLE; } + bool in_progress() const { return state == IN_PROGRESS; } + + bool success() const { return last_result == SUCCESS; } + static char const *state_to_cstring(State const s) { switch (s) { @@ -193,6 +285,14 @@ class Vfs_cbe::Wrapper State state; Result last_result; + Virtual_block_address resizing_nr_of_pbas; + uint64_t percent_done; + + bool idle() const { return state == IDLE; } + bool in_progress() const { return state == IN_PROGRESS; } + + bool success() const { return last_result == SUCCESS; } + static char const *state_to_cstring(State const s) { switch (s) { @@ -216,110 +316,295 @@ class Vfs_cbe::Wrapper 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: Rekeying _rekey_obj { - .state = Rekeying::State::UNKNOWN, - .last_result = Rekeying::Result::NONE, - .key_id = 0, }; + .state = Rekeying::State::UNKNOWN, + .last_result = Rekeying::Result::NONE, + .key_id = 0, + .max_vba = 0, + .rekeying_vba = 0, + .percent_done = 0, }; Deinitialize _deinit_obj { .state = Deinitialize::State::IDLE, - .last_result = Deinitialize::Result::NONE + .last_result = Deinitialize::Result::NONE, + .key_id = 0 }; Extending _extend_obj { - .type = Extending::Type::INVALID, - .state = Extending::State::UNKNOWN, - .last_result = Extending::Result::NONE, + .type = Extending::Type::INVALID, + .state = Extending::State::UNKNOWN, + .last_result = Extending::Result::NONE, + .resizing_nr_of_pbas = 0, + .percent_done = 0, }; - Pointer _snapshots_fs { }; - Pointer _extend_fs { }; - Pointer _rekey_fs { }; - Pointer _deinit_fs { }; + 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 }; - using Backend_device_path = Genode::String<32>; - Backend_device_path _block_device { "/dev/block" }; - - using Crypto_device_path = Genode::String<32>; - Crypto_device_path _crypto_device { "/dev/cbe_crypto" }; - - using Trust_anchor_device_path = Genode::String<64>; - Trust_anchor_device_path _trust_anchor_device { "/dev/cbe_trust_anchor" }; - void _read_config(Xml_node config) { _verbose = config.attribute_value("verbose", _verbose); _debug = config.attribute_value("debug", _debug); - _block_device = config.attribute_value("block", _block_device); - - _crypto_device = config.attribute_value("crypto", _crypto_device); - - _trust_anchor_device = - config.attribute_value("trust_anchor", _trust_anchor_device); } struct Could_not_open_block_backend : Genode::Exception { }; struct No_valid_superblock_found : Genode::Exception { }; - void _initialize_cbe() + void _initialize_tresor() { - using Result = Vfs::Directory_service::Open_result; + _ft_resizing.construct(); + add_module(FT_RESIZING, *_ft_resizing); - Result res = _env.root_dir().open(_block_device.string(), - Vfs::Directory_service::OPEN_MODE_RDWR, - (Vfs::Vfs_handle **)&_backend_handle, - _env.alloc()); - if (res != Result::OPEN_OK) { - error("cbe_fs: Could not open back end block device: '", _block_device, "'"); - throw Could_not_open_block_backend(); - } + _free_tree.construct(); + add_module(FREE_TREE, *_free_tree); - { - Genode::String<128> crypto_add_key_file { - _crypto_device.string(), "/add_key" }; + _vbd.construct(); + add_module(VIRTUAL_BLOCK_DEVICE, *_vbd); - res = _env.root_dir().open(crypto_add_key_file.string(), - Vfs::Directory_service::OPEN_MODE_WRONLY, - (Vfs::Vfs_handle **)&_add_key_handle, - _env.alloc()); - if (res != Result::OPEN_OK) { - error("cbe_fs: Could not open '", crypto_add_key_file, "' file"); - throw Could_not_open_block_backend(); - } - } + _sb_control.construct(); + add_module(SUPERBLOCK_CONTROL, *_sb_control); - { - Genode::String<128> crypto_remove_key_file { - _crypto_device.string(), "/remove_key" }; - - res = _env.root_dir().open(crypto_remove_key_file.string(), - Vfs::Directory_service::OPEN_MODE_WRONLY, - (Vfs::Vfs_handle **)&_remove_key_handle, - _env.alloc()); - if (res != Result::OPEN_OK) { - error("cbe_fs: Could not open '", crypto_remove_key_file, "' file"); - throw Could_not_open_block_backend(); - } - } - - _trust_anchor.construct(_env.root_dir(), _env.alloc(), - _trust_anchor_device.string()); - - _cbe.construct(); + _request_pool.construct(); + add_module(REQUEST_POOL, *_request_pool); } + /***************************** + ** COMMAND_POOL Module API ** + *****************************/ + + bool _peek_generated_request(Genode::uint8_t * /* buf_ptr */, + Genode::size_t /* buf_size */) override + { + return false; + } + + void _drop_generated_request(Module_request &/* mod_req */) override { } public: + void generated_request_complete(Module_request &mod_req) override + { + using ST = Frontend_request::State; + + switch (mod_req.dst_module_id()) { + case REQUEST_POOL: + { + Request const &tresor_request { + *static_cast(&mod_req)}; + + if (tresor_request.operation() == Tresor::Request::Operation::REKEY) { + bool const req_sucess = tresor_request.success(); + if (_verbose) { + log("Complete request: backend request (", tresor_request, ")"); + } + _rekey_obj.state = Rekeying::State::IDLE; + _rekey_obj.last_result = req_sucess ? Rekeying::Result::SUCCESS + : Rekeying::Result::FAILED; + + _rekey_fs_trigger_watch_response(); + _rekey_progress_fs_trigger_watch_response(); + break; + } + + if (tresor_request.operation() == Tresor::Request::Operation::DEINITIALIZE) { + bool const req_sucess = tresor_request.success(); + if (_verbose) { + log("Complete request: backend request (", tresor_request, ")"); + } + _deinit_obj.state = Deinitialize::State::IDLE; + _deinit_obj.last_result = req_sucess ? Deinitialize::Result::SUCCESS + : Deinitialize::Result::FAILED; + + _deinit_fs_trigger_watch_response(); + break; + } + + if (tresor_request.operation() == Tresor::Request::Operation::EXTEND_VBD) { + bool const req_sucess = tresor_request.success(); + if (_verbose) { + log("Complete request: backend request (", tresor_request, ")"); + } + _extend_obj.state = Extending::State::IDLE; + _extend_obj.last_result = + req_sucess ? Extending::Result::SUCCESS + : Extending::Result::FAILED; + + _extend_fs_trigger_watch_response(); + _extend_progress_fs_trigger_watch_response(); + break; + } + + if (tresor_request.operation() == Tresor::Request::Operation::EXTEND_FT) { + bool const req_sucess = tresor_request.success(); + if (_verbose) { + log("Complete request: backend request (", tresor_request, ")"); + } + _extend_obj.state = Extending::State::IDLE; + _extend_obj.last_result = + req_sucess ? Extending::Result::SUCCESS + : Extending::Result::FAILED; + + _extend_fs_trigger_watch_response(); + break; + } + + if (tresor_request.operation() == Tresor::Request::Operation::CREATE_SNAPSHOT) { + if (_verbose) { + log("Complete request: (", tresor_request, ")"); + } + _create_snapshot_request.tresor_request = Tresor::Request(); + _snapshots_fs_update_snapshot_registry(); + break; + } + + if (tresor_request.operation() == Tresor::Request::Operation::DISCARD_SNAPSHOT) { + if (_verbose) { + log("Complete request: (", tresor_request, ")"); + } + _discard_snapshot_request.tresor_request = Tresor::Request(); + _snapshots_fs_update_snapshot_registry(); + break; + } + + if (!tresor_request.success()) { + _helper_read_request.state = Helper_request::State::NONE; + _helper_write_request.state = Helper_request::State::NONE; + + bool const eof = tresor_request.block_number() > _sb_control->max_vba(); + _frontend_request.state = eof ? ST::ERROR_EOF : ST::ERROR; + _frontend_request.tresor_request.success(false); + if (_verbose) { + Genode::log("Request failed: ", + " (frontend request: ", _frontend_request.tresor_request, + " count: ", _frontend_request.count, ")"); + } + break; + } + + if (_helper_read_request.in_progress()) { + _helper_read_request.state = Helper_request::State::COMPLETE; + _helper_read_request.tresor_request.success( + tresor_request.success()); + } else if (_helper_write_request.in_progress()) { + _helper_write_request.state = Helper_request::State::COMPLETE; + _helper_write_request.tresor_request.success( + tresor_request.success()); + } else { + _frontend_request.state = ST::COMPLETE; + _frontend_request.tresor_request.success(tresor_request.success()); + if (_verbose) { + Genode::log("Complete request: ", + " (frontend request: ", _frontend_request.tresor_request, + " count: ", _frontend_request.count, ")"); + } + } + + if (_helper_read_request.complete()) { + if (_frontend_request.tresor_request.read()) { + char * dst = reinterpret_cast + (_frontend_request.tresor_request.offset()); + char const * src = reinterpret_cast + (&_helper_read_request.block_data) + _frontend_request.helper_offset; + + Genode::memcpy(dst, src, _frontend_request.count); + + _helper_read_request.state = Helper_request::State::NONE; + _frontend_request.state = ST::COMPLETE; + _frontend_request.tresor_request.success( + _helper_read_request.tresor_request.success()); + + if (_verbose) { + Genode::log("Complete unaligned READ request: ", + " (frontend request: ", _frontend_request.tresor_request, + " (helper request: ", _helper_read_request.tresor_request, + " offset: ", _frontend_request.helper_offset, + " count: ", _frontend_request.count, ")"); + } + } + + if (_frontend_request.tresor_request.write()) { + /* copy whole block first */ + { + char * dst = reinterpret_cast + (&_helper_write_request.block_data); + char const * src = reinterpret_cast + (&_helper_read_request.block_data); + Genode::memcpy(dst, src, sizeof (Tresor::Block)); + } + + /* and than actual request data */ + { + char * dst = reinterpret_cast + (&_helper_write_request.block_data) + _frontend_request.helper_offset; + char const * src = reinterpret_cast + (_frontend_request.tresor_request.offset()); + Genode::memcpy(dst, src, _frontend_request.count); + } + + /* re-use request */ + _helper_write_request.tresor_request = Tresor::Request( + Tresor::Request::Operation::WRITE, + false, + _helper_read_request.tresor_request.block_number(), + (uint64_t) &_helper_write_request.block_data, + _helper_read_request.tresor_request.count(), + _helper_read_request.tresor_request.key_id(), + _helper_read_request.tresor_request.tag(), + _helper_read_request.tresor_request.snap_id(), + COMMAND_POOL, 0); + + _helper_write_request.state = Helper_request::State::PENDING; + _helper_read_request.state = Helper_request::State::NONE; + } + } + + if (_helper_write_request.complete()) { + if (_verbose) { + Genode::log("Complete unaligned WRITE request: ", + " (frontend request: ", _frontend_request.tresor_request, + " (helper request: ", _helper_read_request.tresor_request, + " offset: ", _frontend_request.helper_offset, + " count: ", _frontend_request.count, ")"); + } + + _helper_write_request.state = Helper_request::State::NONE; + _frontend_request.state = ST::COMPLETE; + } + break; + } + default: + class Exception_2 { }; + throw Exception_2 { }; + } + } + void manage_snapshots_file_system(Snapshots_file_system &snapshots_fs) { if (_snapshots_fs.valid()) { @@ -376,6 +661,34 @@ class Vfs_cbe::Wrapper } } + 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 { }; + } + } + void manage_rekey_file_system(Rekey_file_system &rekey_fs) { if (_rekey_fs.valid()) { @@ -404,6 +717,34 @@ class Vfs_cbe::Wrapper } } + 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 { }; + } + } + void manage_deinit_file_system(Deinitialize_file_system &deinit_fs) { if (_deinit_fs.valid()) { @@ -432,20 +773,73 @@ class Vfs_cbe::Wrapper } } - Wrapper(Vfs::Env &env, Xml_node config) : _env(env) + template + void with_node(char const *name, char const *path, FN const &fn) { - _read_config(config); - _initialize_cbe(); + 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); } - Cbe::Library &cbe() + Wrapper(Vfs::Env &vfs_env, Xml_node config) : _vfs_env { vfs_env } { - if (!_cbe.constructed()) { - struct Cbe_Not_Initialized { }; - throw Cbe_Not_Initialized(); + _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); + }); + + 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, *this); + add_module(BLOCK_IO, *_block_io); + + _initialize_tresor(); + } + + Tresor::Request_pool &tresor() + { + if (!_request_pool.constructed()) { + struct Tresor_Not_Initialized { }; + throw Tresor_Not_Initialized(); } - return *_cbe; + return *_request_pool; + } + + Genode::uint64_t max_vba() + { + return _sb_control->max_vba(); } struct Invalid_Request : Genode::Exception { }; @@ -457,8 +851,8 @@ class Vfs_cbe::Wrapper State state { NONE }; - Cbe::Block_data block_data { }; - Cbe::Request cbe_request { }; + Tresor::Block block_data { }; + Tresor::Request tresor_request { }; bool pending() const { return state == PENDING; } bool in_progress() const { return state == IN_PROGRESS; } @@ -475,13 +869,12 @@ class Vfs_cbe::Wrapper PENDING, IN_PROGRESS, COMPLETE, ERROR, ERROR_EOF }; - State state { NONE }; - file_size count { 0 }; - Cbe::Request cbe_request { }; - uint32_t snap_id { 0 }; - - uint64_t offset { 0 }; - uint64_t helper_offset { 0 }; + State state { NONE }; + size_t count { 0 }; + Tresor::Request tresor_request { }; + void *data { nullptr }; + uint64_t offset { 0 }; + uint64_t helper_offset { 0 }; bool pending() const { return state == PENDING; } bool in_progress() const { return state == IN_PROGRESS; } @@ -501,6 +894,32 @@ class Vfs_cbe::Wrapper } }; + uint64_t _next_client_request_tag() + { + static uint64_t _client_request_tag { 0 }; + return _client_request_tag++; + } + + void const *_lookup_write_buffer(Genode::uint64_t /* tag */, Genode::uint64_t /* vba */) + { + if (_helper_write_request.in_progress()) + return (void const*)&_helper_write_request.block_data; + if (_frontend_request.in_progress()) + return (void const*)_frontend_request.data; + + return nullptr; + } + + void *_lookup_read_buffer(Genode::uint64_t /* tag */, Genode::uint64_t /* vba */) + { + if (_helper_read_request.in_progress()) + return (void *)&_helper_read_request.block_data; + if (_frontend_request.in_progress()) + return (void *)_frontend_request.data; + + return nullptr; + } + Frontend_request _frontend_request { }; Frontend_request const & frontend_request() const @@ -508,38 +927,41 @@ class Vfs_cbe::Wrapper return _frontend_request; } - void ack_frontend_request(Vfs_handle &handle) + void ack_frontend_request(Vfs_handle &/* handle */) { // assert current state was *_COMPLETE _frontend_request.state = Frontend_request::State::NONE; - _frontend_request.cbe_request = Cbe::Request { }; + _frontend_request.tresor_request = Tresor::Request { }; } bool submit_frontend_request(Vfs_handle &handle, Byte_range_ptr const &data, - Cbe::Request::Operation op, + Tresor::Request::Operation op, uint32_t snap_id) { if (_frontend_request.state != Frontend_request::State::NONE) { return false; } + uint64_t const tag = _next_client_request_tag(); + /* short-cut for SYNC requests */ - if (op == Cbe::Request::Operation::SYNC) { - _frontend_request.cbe_request = Cbe::Request( + if (op == Tresor::Request::Operation::SYNC) { + _frontend_request.tresor_request = Tresor::Request( op, false, 0, 0, 1, 0, - 0); + (Genode::uint32_t)tag, + 0, + COMMAND_POOL, 0); _frontend_request.count = 0; - _frontend_request.snap_id = 0; _frontend_request.state = Frontend_request::State::PENDING; if (_verbose) { Genode::log("Req: (front req: ", - _frontend_request.cbe_request, ")"); + _frontend_request.tresor_request, ")"); } return true; } @@ -548,36 +970,46 @@ class Vfs_cbe::Wrapper bool unaligned_request = false; /* unaligned request if any condition is true */ - unaligned_request |= (offset % Cbe::BLOCK_SIZE) != 0; - unaligned_request |= (data.num_bytes < Cbe::BLOCK_SIZE); + unaligned_request |= (offset % Tresor::BLOCK_SIZE) != 0; + unaligned_request |= (data.num_bytes < Tresor::BLOCK_SIZE); size_t count = data.num_bytes; - if ((count % Cbe::BLOCK_SIZE) != 0 && + if ((count % Tresor::BLOCK_SIZE) != 0 && !unaligned_request) { - count = count - (count % Cbe::BLOCK_SIZE); + count = count - (count % Tresor::BLOCK_SIZE); } if (unaligned_request) { - _helper_read_request.cbe_request = Cbe::Request( - Cbe::Request::Operation::READ, + _helper_read_request.tresor_request = Tresor::Request( + Tresor::Request::Operation::READ, false, - offset / Cbe::BLOCK_SIZE, + offset / Tresor::BLOCK_SIZE, (uint64_t)&_helper_read_request.block_data, 1, 0, - 0); + (Genode::uint32_t)tag, + 0, + COMMAND_POOL, 0); _helper_read_request.state = Helper_request::State::PENDING; - _frontend_request.helper_offset = (offset % Cbe::BLOCK_SIZE); - if (count >= (Cbe::BLOCK_SIZE - _frontend_request.helper_offset)) { - _frontend_request.count = Cbe::BLOCK_SIZE - _frontend_request.helper_offset; + _frontend_request.helper_offset = (offset % Tresor::BLOCK_SIZE); + if (count >= (Tresor::BLOCK_SIZE - _frontend_request.helper_offset)) { + + uint64_t const count_u64 { + Tresor::BLOCK_SIZE - _frontend_request.helper_offset }; + + if (count_u64 > ~(size_t)0) { + class Exception_3 { }; + throw Exception_3 { }; + } + _frontend_request.count = (size_t)count_u64; } else { _frontend_request.count = count; } - /* skip handling by the CBE, helper requests will do that for us */ + /* skip handling by Tresor library, helper requests will do that for us */ _frontend_request.state = Frontend_request::State::IN_PROGRESS; } else { @@ -585,987 +1017,65 @@ class Vfs_cbe::Wrapper _frontend_request.state = Frontend_request::State::PENDING; } + _frontend_request.data = data.start; _frontend_request.offset = offset; - _frontend_request.cbe_request = Cbe::Request( + _frontend_request.tresor_request = Tresor::Request( op, false, - offset / Cbe::BLOCK_SIZE, + offset / Tresor::BLOCK_SIZE, (uint64_t)data.start, - (uint32_t)(count / Cbe::BLOCK_SIZE), + (uint32_t)(count / Tresor::BLOCK_SIZE), 0, - 0); + (Genode::uint32_t)tag, + snap_id, + COMMAND_POOL, 0); if (_verbose) { if (unaligned_request) { Genode::log("Unaligned req: ", "off: ", offset, " bytes: ", count, - " (front req: ", _frontend_request.cbe_request, - " (helper req: ", _helper_read_request.cbe_request, + " (front req: ", _frontend_request.tresor_request, + " (helper req: ", _helper_read_request.tresor_request, " off: ", _frontend_request.helper_offset, " count: ", _frontend_request.count, ")"); } else { Genode::log("Req: ", "off: ", offset, " bytes: ", count, - " (front req: ", _frontend_request.cbe_request, ")"); + " (front req: ", _frontend_request.tresor_request, ")"); } } - _frontend_request.snap_id = snap_id; return true; } - bool _handle_cbe_backend(Cbe::Library &cbe, Cbe::Io_buffer &io_data) - { - Cbe::Io_buffer::Index data_index { 0 }; - Cbe::Request cbe_request = cbe.has_io_request(data_index); - - if (cbe_request.valid() && !_backend_job.constructed()) { - - file_offset const base_offset = cbe_request.block_number() - * Cbe::BLOCK_SIZE; - file_size const count = cbe_request.count() - * Cbe::BLOCK_SIZE; - - _backend_job.construct(*_backend_handle, cbe_request.operation(), - data_index, base_offset, count); - } - - if (!_backend_job.constructed()) { - return false; - } - - bool progress = _backend_job->execute(cbe, io_data); - - if (_backend_job->completed()) { - _backend_job.destruct(); - } - - return progress; - } - 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(); - bool _handle_cbe_frontend(Cbe::Library &cbe, Frontend_request &frontend_request) - { - if (_helper_read_request.pending()) { - if (_cbe->client_request_acceptable()) { - _cbe->submit_client_request(_helper_read_request.cbe_request, - frontend_request.snap_id); - _helper_read_request.state = Helper_request::State::IN_PROGRESS; - } - } - - if (_helper_write_request.pending()) { - if (_cbe->client_request_acceptable()) { - _cbe->submit_client_request(_helper_write_request.cbe_request, - frontend_request.snap_id); - _helper_write_request.state = Helper_request::State::IN_PROGRESS; - } - } - - if (frontend_request.pending()) { - - using ST = Frontend_request::State; - - Cbe::Request const &request = frontend_request.cbe_request; - Cbe::Virtual_block_address const vba = request.block_number(); - uint32_t const snap_id = frontend_request.snap_id; - - if (vba > cbe.max_vba()) { - warning("reject request with out-of-range virtual block start address ", vba); - _frontend_request.state = ST::ERROR_EOF; - return false; - } - - if (vba + request.count() < vba) { - warning("reject wraping request", vba); - _frontend_request.state = ST::ERROR_EOF; - return false; - } - - if (vba + request.count() > (cbe.max_vba() + 1)) { - warning("reject invalid request ", vba, " ", request.count()); - _frontend_request.state = ST::ERROR_EOF; - return false; - } - - if (cbe.client_request_acceptable()) { - cbe.submit_client_request(request, snap_id); - frontend_request.state = ST::IN_PROGRESS; - } - } - - cbe.execute(_io_data, _plain_data, _cipher_data); - bool progress = cbe.execute_progress(); - - using ST = Frontend_request::State; - - while (true) { - Cbe::Request const cbe_request = cbe.peek_completed_client_request(); - if (!cbe_request.valid()) { break; } - - cbe.drop_completed_client_request(cbe_request); - progress = true; - - if (cbe_request.operation() == Cbe::Request::Operation::REKEY) { - bool const req_sucess = cbe_request.success(); - if (_verbose) { - log("Complete request: backend request (", cbe_request, ")"); - } - _rekey_obj.state = Rekeying::State::IDLE; - _rekey_obj.last_result = req_sucess ? Rekeying::Result::SUCCESS - : Rekeying::Result::FAILED; - - _rekey_fs_trigger_watch_response(); - continue; - } - - if (cbe_request.operation() == Cbe::Request::Operation::DEINITIALIZE) { - bool const req_sucess = cbe_request.success(); - if (_verbose) { - log("Complete request: backend request (", cbe_request, ")"); - } - _deinit_obj.state = Deinitialize::State::IDLE; - _deinit_obj.last_result = req_sucess ? Deinitialize::Result::SUCCESS - : Deinitialize::Result::FAILED; - - _deinit_fs_trigger_watch_response(); - continue; - } - - if (cbe_request.operation() == Cbe::Request::Operation::EXTEND_VBD) { - bool const req_sucess = cbe_request.success(); - if (_verbose) { - log("Complete request: backend request (", cbe_request, ")"); - } - _extend_obj.state = Extending::State::IDLE; - _extend_obj.last_result = - req_sucess ? Extending::Result::SUCCESS - : Extending::Result::FAILED; - - _extend_fs_trigger_watch_response(); - continue; - } - - if (cbe_request.operation() == Cbe::Request::Operation::EXTEND_FT) { - bool const req_sucess = cbe_request.success(); - if (_verbose) { - log("Complete request: backend request (", cbe_request, ")"); - } - _extend_obj.state = Extending::State::IDLE; - _extend_obj.last_result = - req_sucess ? Extending::Result::SUCCESS - : Extending::Result::FAILED; - - _extend_fs_trigger_watch_response(); - continue; - } - - if (cbe_request.operation() == Cbe::Request::Operation::CREATE_SNAPSHOT) { - if (_verbose) { - log("Complete request: (", cbe_request, ")"); - } - _create_snapshot_request.cbe_request = Cbe::Request(); - _snapshots_fs_update_snapshot_registry(); - continue; - } - - if (cbe_request.operation() == Cbe::Request::Operation::DISCARD_SNAPSHOT) { - if (_verbose) { - log("Complete request: (", cbe_request, ")"); - } - _discard_snapshot_request.cbe_request = Cbe::Request(); - _snapshots_fs_update_snapshot_registry(); - continue; - } - - if (!cbe_request.success()) { - _helper_read_request.state = Helper_request::State::NONE; - _helper_write_request.state = Helper_request::State::NONE; - - frontend_request.state = ST::COMPLETE; - frontend_request.cbe_request.success(cbe_request.success()); - break; - } - - if (_helper_read_request.in_progress()) { - _helper_read_request.state = Helper_request::State::COMPLETE; - _helper_read_request.cbe_request.success( - cbe_request.success()); - } else if (_helper_write_request.in_progress()) { - _helper_write_request.state = Helper_request::State::COMPLETE; - _helper_write_request.cbe_request.success( - cbe_request.success()); - } else { - frontend_request.state = ST::COMPLETE; - frontend_request.cbe_request.success(cbe_request.success()); - if (_verbose) { - Genode::log("Complete request: ", - " (frontend request: ", _frontend_request.cbe_request, - " count: ", _frontend_request.count, ")"); - } - } - } - - if (_helper_read_request.complete()) { - if (frontend_request.cbe_request.read()) { - char * dst = reinterpret_cast - (frontend_request.cbe_request.offset()); - char const * src = reinterpret_cast - (&_helper_read_request.block_data) + frontend_request.helper_offset; - - Genode::memcpy(dst, src, _frontend_request.count); - - _helper_read_request.state = Helper_request::State::NONE; - frontend_request.state = ST::COMPLETE; - frontend_request.cbe_request.success( - _helper_read_request.cbe_request.success()); - - if (_verbose) { - Genode::log("Complete unaligned READ request: ", - " (frontend request: ", _frontend_request.cbe_request, - " (helper request: ", _helper_read_request.cbe_request, - " offset: ", _frontend_request.helper_offset, - " count: ", _frontend_request.count, ")"); - } - } - - if (frontend_request.cbe_request.write()) { - /* copy whole block first */ - { - char * dst = reinterpret_cast - (&_helper_write_request.block_data); - char const * src = reinterpret_cast - (&_helper_read_request.block_data); - Genode::memcpy(dst, src, sizeof (Cbe::Block_data)); - } - - /* and than actual request data */ - { - char * dst = reinterpret_cast - (&_helper_write_request.block_data) + frontend_request.helper_offset; - char const * src = reinterpret_cast - (frontend_request.cbe_request.offset()); - Genode::memcpy(dst, src, _frontend_request.count); - } - - /* re-use request */ - _helper_write_request.cbe_request = Cbe::Request( - Cbe::Request::Operation::WRITE, - false, - _helper_read_request.cbe_request.block_number(), - (uint64_t) &_helper_write_request.block_data, - _helper_read_request.cbe_request.count(), - _helper_read_request.cbe_request.key_id(), - _helper_read_request.cbe_request.tag()); - - _helper_write_request.state = Helper_request::State::PENDING; - _helper_read_request.state = Helper_request::State::NONE; - } - progress = true; - } - - if (_helper_write_request.complete()) { - if (_verbose) { - Genode::log("Complete unaligned WRITE request: ", - " (frontend request: ", _frontend_request.cbe_request, - " (helper request: ", _helper_read_request.cbe_request, - " offset: ", _frontend_request.helper_offset, - " count: ", _frontend_request.count, ")"); - } - - _helper_write_request.state = Helper_request::State::NONE; - frontend_request.state = ST::COMPLETE; - progress = true; - } - - /* read */ - { - struct Read_data_pointer_is_null : Genode::Exception { }; - struct Front_end_read_request_should_be_in_progress : - Genode::Exception { }; - - Cbe::Request cbe_req { }; - uint64_t vba { 0 }; - Cbe::Crypto_plain_buffer::Index plain_buf_idx { 0 }; - - _cbe->client_transfer_read_data_required( - cbe_req, vba, plain_buf_idx); - - if (cbe_req.valid()) { - - Cbe::Block_data *data { nullptr }; - - if (_helper_read_request.in_progress()) { - data = reinterpret_cast( - &_helper_read_request.block_data); - } else { - - if (_frontend_request.in_progress()) { - // XXX check after helper request because it will be IN_PROGRESS - // in case helper request is used - - uint64_t buf_base { cbe_req.offset() }; - uint64_t blk_off { vba - cbe_req.block_number() }; - data = reinterpret_cast( - buf_base + (blk_off * Cbe::BLOCK_SIZE)); - - } else { - throw Front_end_read_request_should_be_in_progress(); - } - } - if (data == nullptr) { - throw Read_data_pointer_is_null(); - } - Genode::memcpy( - data, - &_plain_data.item(plain_buf_idx), - sizeof (Cbe::Block_data)); - - _cbe->client_transfer_read_data_in_progress( - plain_buf_idx); - - _cbe->client_transfer_read_data_completed( - plain_buf_idx, true); - - progress = true; - } - } - - /* write */ - { - struct Write_data_pointer_is_null : Genode::Exception { }; - struct Front_end_write_request_should_be_in_progress : - Genode::Exception { }; - - Cbe::Request cbe_req { }; - uint64_t vba { 0 }; - Cbe::Crypto_plain_buffer::Index plain_buf_idx { 0 }; - - _cbe->client_transfer_write_data_required( - cbe_req, vba, plain_buf_idx); - - if (cbe_req.valid()) { - - Cbe::Block_data *data { nullptr }; - - if (_helper_write_request.in_progress()) { - data = reinterpret_cast( - &_helper_write_request.block_data); - } else { - - if (_frontend_request.in_progress()) { - // XXX check after helper request because it will be IN_PROGRESS - // in case helper request is used - - uint64_t buf_base { cbe_req.offset() }; - uint64_t blk_off { vba - cbe_req.block_number() }; - data = reinterpret_cast( - buf_base + (blk_off * Cbe::BLOCK_SIZE)); - } else { - throw Front_end_write_request_should_be_in_progress(); - } - } - if (data == nullptr) { - throw Write_data_pointer_is_null(); - } - Genode::memcpy( - &_plain_data.item(plain_buf_idx), - data, - sizeof (Cbe::Block_data)); - - _cbe->client_transfer_write_data_in_progress( - plain_buf_idx); - - _cbe->client_transfer_write_data_completed( - plain_buf_idx, true); - - progress = true; - } - } - - return progress; - } - - bool _handle_ta(Cbe::Library &cbe) - { - bool progress = false; - - Util::Trust_anchor_vfs &ta = *_trust_anchor; - - progress |= ta.execute(); - - using Op = Cbe::Trust_anchor_request::Operation; - - while (true) { - - Cbe::Trust_anchor_request const request = - _cbe->peek_generated_ta_request(); - - if (!request.valid()) { break; } - if (!ta.request_acceptable()) { break; } - - switch (request.operation()) { - case Op::CREATE_KEY: - ta.submit_create_key_request(request); - break; - case Op::SECURE_SUPERBLOCK: - { - Cbe::Hash const sb_hash = _cbe->peek_generated_ta_sb_hash(request); - ta.submit_secure_superblock_request(request, sb_hash); - break; - } - case Op::ENCRYPT_KEY: - { - Cbe::Key_plaintext_value const pk = - _cbe->peek_generated_ta_key_value_plaintext(request); - - ta.submit_encrypt_key_request(request, pk); - break; - } - case Op::DECRYPT_KEY: - { - Cbe::Key_ciphertext_value const ck = - _cbe->peek_generated_ta_key_value_ciphertext(request); - - ta.submit_decrypt_key_request(request, ck); - break; - } - case Op::LAST_SB_HASH: - ta.submit_superblock_hash_request(request); - break; - case Op::INITIALIZE: - class Bad_operation { }; - throw Bad_operation { }; - case Op::INVALID: - /* never reached */ - break; - } - _cbe->drop_generated_ta_request(request); - progress |= true; - } - - while (true) { - - Cbe::Trust_anchor_request const request = - ta.peek_completed_request(); - - if (!request.valid()) { break; } - - switch (request.operation()) { - case Op::CREATE_KEY: - { - Cbe::Key_plaintext_value const pk = - ta.peek_completed_key_value_plaintext(request); - - _cbe->mark_generated_ta_create_key_request_complete(request, pk); - break; - } - case Op::SECURE_SUPERBLOCK: - { - _cbe->mark_generated_ta_secure_sb_request_complete(request); - break; - } - case Op::ENCRYPT_KEY: - { - Cbe::Key_ciphertext_value const ck = - ta.peek_completed_key_value_ciphertext(request); - - _cbe->mark_generated_ta_encrypt_key_request_complete(request, ck); - break; - } - case Op::DECRYPT_KEY: - { - Cbe::Key_plaintext_value const pk = - ta.peek_completed_key_value_plaintext(request); - - _cbe->mark_generated_ta_decrypt_key_request_complete(request, pk); - break; - } - case Op::LAST_SB_HASH: - { - Cbe::Hash const hash = - ta.peek_completed_superblock_hash(request); - - _cbe->mark_generated_ta_last_sb_hash_request_complete(request, hash); - break; - } - case Op::INITIALIZE: - class Bad_operation { }; - throw Bad_operation { }; - case Op::INVALID: - /* never reached */ - break; - } - ta.drop_completed_request(request); - progress |= true; - } - - return progress; - } - - bool _handle_crypto_add_key() - { - bool progress = false; - - do { - Cbe::Key key { }; - Cbe::Request request = _cbe->crypto_add_key_required(key); - if (!request.valid()) { - break; - } - - char buffer[sizeof (key.value) + sizeof (key.id.value)] { }; - - memcpy(buffer, &key.id.value, sizeof (key.id.value)); - memcpy(buffer + sizeof (key.id.value), key.value, sizeof (key.value)); - - size_t written = 0; - _add_key_handle->seek(0); - - using Write_result = Vfs::File_io_service::Write_result; - - Const_byte_range_ptr const src(buffer, sizeof(buffer)); - - Write_result const result = - _add_key_handle->fs().write(_add_key_handle, src, written); - - if (result == Write_result::WRITE_ERR_WOULD_BLOCK) - break; /* try again later */ - - /* - * Instead of acknowledge the CBE's request before we write - * the key above do it afterwards. That allows us to perform the - * request multiple times in case the above exception is thrown. - */ - _cbe->crypto_add_key_requested(request); - - uint32_t const key_id_value = key.id.value; - - Crypto_file *cf = nullptr; - try { - cf = _get_unused_crypto_file(); - } catch (...) { - error("cannot manage key id: ", key_id_value); - request.success(false); - _cbe->crypto_add_key_completed(request); - continue; - } - - using Encrypt_file = Genode::String<128>; - Encrypt_file encrypt_file { - _crypto_device.string(), "/keys/", key_id_value, "/encrypt" }; - - using Result = Vfs::Directory_service::Open_result; - Result res = _env.root_dir().open(encrypt_file.string(), - Vfs::Directory_service::OPEN_MODE_RDWR, - (Vfs::Vfs_handle **)&cf->encrypt_handle, - _env.alloc()); - - request.success(res == Result::OPEN_OK); - if (!request.success()) { - error("could not open encrypt '", encrypt_file, "' file for key id: ", key_id_value); - - request.success(false); - _cbe->crypto_add_key_completed(request); - continue; - } - - using Decrypt_file = Genode::String<128>; - Decrypt_file decrypt_file { - _crypto_device.string(), "/keys/", key_id_value, "/decrypt" }; - - res = _env.root_dir().open(decrypt_file.string(), - Vfs::Directory_service::OPEN_MODE_RDWR, - (Vfs::Vfs_handle **)&cf->decrypt_handle, - _env.alloc()); - - request.success(res == Result::OPEN_OK); - if (!request.success()) { - _env.root_dir().close(cf->encrypt_handle); - - error("could not open decrypt '", decrypt_file, "' file for key id: ", key_id_value); - - request.success(false); - _cbe->crypto_add_key_completed(request); - continue; - } - - /* set key id to make file valid */ - cf->key_id = key_id_value; - - request.success(true); - _cbe->crypto_add_key_completed(request); - progress |= true; - } while (false); - - return progress; - } - - bool _handle_crypto_remove_key() - { - bool progress = false; - - do { - Cbe::Key::Id key_id { }; - Cbe::Request request = _cbe->crypto_remove_key_required(key_id); - if (!request.valid()) { - break; - } - - size_t written = 0; - _remove_key_handle->seek(0); - - Const_byte_range_ptr const src((char *)&key_id.value, - sizeof(key_id.value)); - - using Write_result = Vfs::File_io_service::Write_result; - - Write_result const result = - _remove_key_handle->fs().write(_remove_key_handle, src, written); - - if (result == Write_result::WRITE_ERR_WOULD_BLOCK) - break; /* try again later */ - - Crypto_file *cf = nullptr; - try { - cf = _lookup_crypto_file(key_id.value); - - _env.root_dir().close(cf->encrypt_handle); - cf->encrypt_handle = nullptr; - _env.root_dir().close(cf->decrypt_handle); - cf->decrypt_handle = nullptr; - cf->key_id = 0; - } catch (...) { - uint32_t const key_id_value = key_id.value; - Genode::warning("could not look up handles for key id: ", - key_id_value); - } - - /* - * Instead of acknowledge the CBE's request before we write - * the key do it afterwards. That allows us to perform the - * request multiple times in case the above exception is thrown. - */ - _cbe->crypto_remove_key_requested(request); - request.success(true); - _cbe->crypto_remove_key_completed(request); - progress |= true; - } while (false); - - return progress; - } - - struct Crypto_job - { - struct Invalid_operation : Genode::Exception { }; - - enum State { IDLE, SUBMITTED, PENDING, IN_PROGRESS, COMPLETE }; - enum Operation { INVALID, DECRYPT, ENCRYPT }; - - Crypto_file *file; - Vfs_handle *_handle; - - State state; - Operation op; - uint32_t data_index; - file_offset offset; - - Cbe::Crypto_cipher_buffer::Index cipher_index; - Cbe::Crypto_plain_buffer::Index plain_index; - - static bool _read_queued(Vfs::File_io_service::Read_result r) - { - using Result = Vfs::File_io_service::Read_result; - switch (r) { - case Result::READ_QUEUED: [[fallthrough]]; - case Result::READ_ERR_WOULD_BLOCK: return true; - default: break; - } - return false; - } - - struct Result - { - bool progress; - bool complete; - bool success; - }; - - bool request_acceptable() const - { - return state == State::IDLE; - } - - template - void submit_request(Crypto_file *cf, uint32_t data_index, file_offset offset) - { - file = cf; - state = Crypto_job::State::SUBMITTED; - op = OP; - data_index = data_index; - offset = offset; - - /* store both in regardless of operation */ - cipher_index.value = data_index; - plain_index.value = data_index; - - switch (op) { - case Crypto_job::Operation::ENCRYPT: - _handle = cf->encrypt_handle; break; - case Crypto_job::Operation::DECRYPT: - _handle = cf->decrypt_handle; break; - case Crypto_job::Operation::INVALID: - throw Invalid_operation(); - break; - } - } - - Result execute(Cbe::Library &cbe, - Cbe::Crypto_cipher_buffer &cipher, - Cbe::Crypto_plain_buffer &plain) - { - Result result { false, false, false }; - - switch (state) { - case Crypto_job::State::IDLE: - break; - case Crypto_job::State::SUBMITTED: - { - char const *data = nullptr; - - if (op == Crypto_job::Operation::ENCRYPT) { - data = reinterpret_cast(&plain.item(plain_index)); - } - else if (op == Crypto_job::Operation::DECRYPT) { - data = reinterpret_cast(&cipher.item(cipher_index)); - } - - size_t out = 0; - _handle->seek(offset); - - Const_byte_range_ptr const src(data, sizeof(Cbe::Block_data)); - - _handle->fs().write(_handle, src, out); - - if (op == Crypto_job::Operation::ENCRYPT) { - cbe.crypto_cipher_data_requested(plain_index); - } - else if (op == Crypto_job::Operation::DECRYPT) { - cbe.crypto_plain_data_requested(cipher_index); - } - - state = Crypto_job::State::PENDING; - result.progress |= true; - } - [[fallthrough]]; - - case Crypto_job::State::PENDING: - - _handle->seek(offset); - if (!_handle->fs().queue_read(_handle, sizeof (Cbe::Block_data))) { - break; - } - - state = Crypto_job::State::IN_PROGRESS; - result.progress |= true; - [[fallthrough]]; - - case Crypto_job::State::IN_PROGRESS: - { - using Result = Vfs::File_io_service::Read_result; - - size_t out = 0; - char *data = nullptr; - - if (op == Crypto_job::Operation::ENCRYPT) { - data = reinterpret_cast(&cipher.item(cipher_index)); - } else - - if (op == Crypto_job::Operation::DECRYPT) { - data = reinterpret_cast(&plain.item(plain_index)); - } - - Byte_range_ptr const dst(data, sizeof (Cbe::Block_data)); - - Result const res = _handle->fs().complete_read(_handle, dst, out); - - if (_read_queued(res)) { - break; - } - - result.success = res == Result::READ_OK; - - state = Crypto_job::State::COMPLETE; - result.progress |= true; - [[fallthrough]]; - } - case Crypto_job::State::COMPLETE: - - if (op == Crypto_job::Operation::ENCRYPT) { - if (!result.success) { - error("encryption request failed"); // XXX be more informative - } - - cbe.supply_crypto_cipher_data(cipher_index, result.success); - } else - - if (op == Crypto_job::Operation::DECRYPT) { - if (!result.success) { - error("decryption request failed"); // XXX be more informative - } - - cbe.supply_crypto_plain_data(plain_index, result.success); - } - - state = Crypto_job::State::IDLE; - result.complete |= true; - result.progress |= true; - break; - } - - return result; - } - }; - - Crypto_job _crypto_job { nullptr, nullptr, Crypto_job::State::IDLE, - Crypto_job::Operation::INVALID, - 0 , 0, - Cbe::Crypto_cipher_buffer::Index { 0 }, - Cbe::Crypto_plain_buffer::Index { 0 } }; // XXX make that more than 1 job - - bool _handle_crypto_request(Cbe::Library &cbe, - Cbe::Crypto_cipher_buffer &cipher, - Cbe::Crypto_plain_buffer &plain) - { - bool progress = false; - - /* encrypt */ - while (true) { - - Cbe::Crypto_plain_buffer::Index data_index { 0 }; - Cbe::Request request = cbe.crypto_cipher_data_required(data_index); - if (!request.valid() || !_crypto_job.request_acceptable()) { - break; - } - - Crypto_file *cf = nullptr; - try { - cf = _lookup_crypto_file(request.key_id()); - } catch (...) { - cbe.crypto_cipher_data_requested(data_index); - - Cbe::Crypto_cipher_buffer::Index const index { data_index.value }; - cbe.supply_crypto_cipher_data(index, false); - continue; - } - - using Op = Crypto_job::Operation; - file_offset const offset = request.block_number() * Cbe::BLOCK_SIZE; - _crypto_job.submit_request(cf, data_index.value, offset); - progress |= true; - } - - /* decrypt */ - while (true) { - - Cbe::Crypto_cipher_buffer::Index data_index { 0 }; - Cbe::Request request = cbe.crypto_plain_data_required(data_index); - if (!request.valid() || !_crypto_job.request_acceptable()) { - break; - } - - Crypto_file *cf = nullptr; - try { - cf = _lookup_crypto_file(request.key_id()); - } catch (...) { - cbe.crypto_plain_data_requested(data_index); - Cbe::Crypto_plain_buffer::Index const index { data_index.value }; - cbe.supply_crypto_plain_data(index, false); - continue; - } - - using Op = Crypto_job::Operation; - file_offset const offset = request.block_number() * Cbe::BLOCK_SIZE; - _crypto_job.submit_request(cf, data_index.value, offset); - progress |= true; - } - - Crypto_job::Result const result = _crypto_job.execute(cbe, cipher, plain); - progress |= result.progress; - - return progress; - } - - bool _handle_crypto() - { - bool progress = false; - - bool const add_key_progress = _handle_crypto_add_key(); - progress |= add_key_progress; - - bool const remove_key_progress = _handle_crypto_remove_key(); - progress |= remove_key_progress; - - bool const request_progress = _handle_crypto_request(*_cbe, _cipher_data, _plain_data); - progress |= request_progress; - - return progress; - } - - void _dump_state() - { - if (_debug) { - static uint64_t cnt = 0; - log("FE: ", Frontend_request::state_to_string(_frontend_request.state), - " (", _frontend_request.cbe_request, ") ", - "BE: ", *_backend_job, " ", ++cnt); - } - } - void handle_frontend_request() { - while (true) { + bool progress { true }; + while (progress) { - bool progress = false; - - bool const frontend_progress = - _handle_cbe_frontend(*_cbe, _frontend_request); - progress |= frontend_progress; - - bool const backend_progress = _handle_cbe_backend(*_cbe, _io_data); - progress |= backend_progress; - - bool const crypto_progress = _handle_crypto(); - progress |= crypto_progress; - - bool const ta_progress = _handle_ta(*_cbe); - progress |= ta_progress; - - if (!progress) { - _dump_state(); - } - - if (_debug) { - log("frontend_progress: ", frontend_progress, - " backend_progress: ", backend_progress, - " crypto_progress: ", crypto_progress); - } - - if (!progress) { break; } + progress = false; + execute_modules(progress); } + _vfs_env.io().commit(); - Cbe::Info const info = _cbe->info(); + Tresor::Superblock_info const sb_info { + _sb_control->sb_info() }; using ES = Extending::State; - if (_extend_obj.state == ES::UNKNOWN && info.valid) { - if (info.extending_ft) { + 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; @@ -1573,7 +1083,7 @@ class Vfs_cbe::Wrapper } else - if (info.extending_vbd) { + if (sb_info.extending_vbd) { _extend_obj.state = ES::IN_PROGRESS; _extend_obj.type = Extending::Type::VBD; @@ -1585,41 +1095,77 @@ class Vfs_cbe::Wrapper _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 && info.valid) { + if (_rekey_obj.state == RS::UNKNOWN && sb_info.valid) { _rekey_obj.state = - info.rekeying ? RS::IN_PROGRESS : RS::IDLE; + 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(); + } } - bool client_request_acceptable() const + bool client_request_acceptable() { - return _cbe->client_request_acceptable(); + return _request_pool->ready_to_submit_request(); } bool start_rekeying() { - if (!_cbe->client_request_acceptable()) { + if (!_request_pool->ready_to_submit_request()) { return false; } - Cbe::Request req( - Cbe::Request::Operation::REKEY, + Tresor::Request req( + Tresor::Request::Operation::REKEY, false, 0, 0, 0, _rekey_obj.key_id, - 0); + 0, 0, + COMMAND_POOL, 0); if (_verbose) { Genode::log("Req: (background req: ", req, ")"); } - _cbe->submit_client_request(req, 0); - _rekey_obj.state = Rekeying::State::IN_PROGRESS; - _rekey_obj.last_result = Rekeying::Rekeying::FAILED; + _request_pool->submit_request(req); + _rekey_obj.state = Rekeying::State::IN_PROGRESS; + _rekey_obj.last_result = Rekeying::Rekeying::FAILED; + _rekey_obj.max_vba = _sb_control->max_vba(); + _rekey_obj.rekeying_vba = _sb_control->rekeying_vba(); _rekey_fs_trigger_watch_response(); + _rekey_progress_fs_trigger_watch_response(); // XXX kick-off rekeying handle_frontend_request(); @@ -1633,22 +1179,23 @@ class Vfs_cbe::Wrapper bool start_deinitialize() { - if (!_cbe->client_request_acceptable()) { + if (!_request_pool->ready_to_submit_request()) { return false; } - Cbe::Request req( - Cbe::Request::Operation::DEINITIALIZE, + Tresor::Request req( + Tresor::Request::Operation::DEINITIALIZE, false, 0, 0, 0, 0, - 0); + 0, 0, + COMMAND_POOL, 0); if (_verbose) { Genode::log("Req: (background req: ", req, ")"); } - _cbe->submit_client_request(req, 0); + _request_pool->submit_request(req); _deinit_obj.state = Deinitialize::State::IN_PROGRESS; _deinit_obj.last_result = Deinitialize::Deinitialize::FAILED; _deinit_fs_trigger_watch_response(); @@ -1665,38 +1212,41 @@ class Vfs_cbe::Wrapper bool start_extending(Extending::Type type, - Cbe::Number_of_blocks blocks) + Tresor::Number_of_blocks blocks) { - if (!_cbe->client_request_acceptable()) { + if (!_request_pool->ready_to_submit_request()) { return false; } - Cbe::Request::Operation op = - Cbe::Request::Operation::INVALID; + Tresor::Request::Operation op = + Tresor::Request::Operation::INVALID; switch (type) { case Extending::Type::VBD: - op = Cbe::Request::Operation::EXTEND_VBD; + op = Tresor::Request::Operation::EXTEND_VBD; break; case Extending::Type::FT: - op = Cbe::Request::Operation::EXTEND_FT; + op = Tresor::Request::Operation::EXTEND_FT; break; case Extending::Type::INVALID: return false; } - Cbe::Request req(op, false, - 0, 0, blocks, 0, 0); + Tresor::Request req(op, false, + 0, 0, blocks, 0, 0, 0, + COMMAND_POOL, 0); if (_verbose) { Genode::log("Req: (background req: ", req, ")"); } - _cbe->submit_client_request(req, 0); - _extend_obj.type = type; - _extend_obj.state = Extending::State::IN_PROGRESS; - _extend_obj.last_result = Extending::Result::NONE; + _request_pool->submit_request(req); + _extend_obj.type = type; + _extend_obj.state = Extending::State::IN_PROGRESS; + _extend_obj.last_result = Extending::Result::NONE; + _extend_obj.resizing_nr_of_pbas = 0; _extend_fs_trigger_watch_response(); + _extend_progress_fs_trigger_watch_response(); // XXX kick-off extending handle_frontend_request(); @@ -1708,12 +1258,12 @@ class Vfs_cbe::Wrapper return _extend_obj; } - void active_snapshot_ids(Cbe::Active_snapshot_ids &ids) + void snapshot_generations(Tresor::Snapshot_generations &generations) { - if (!_cbe.constructed()) { - _initialize_cbe(); + if (!_request_pool.constructed()) { + _initialize_tresor(); } - _cbe->active_snapshot_ids(ids); + _sb_control->snapshot_generations(generations); handle_frontend_request(); } @@ -1722,29 +1272,30 @@ class Vfs_cbe::Wrapper bool create_snapshot() { - if (!_cbe.constructed()) { - _initialize_cbe(); + if (!_request_pool.constructed()) { + _initialize_tresor(); } - if (!_cbe->client_request_acceptable()) { + if (!_request_pool->ready_to_submit_request()) { return false; } - if (_create_snapshot_request.cbe_request.valid()) { + if (_create_snapshot_request.tresor_request.valid()) { return false; } - Cbe::Request::Operation const op = - Cbe::Request::Operation::CREATE_SNAPSHOT; + Tresor::Request::Operation const op = + Tresor::Request::Operation::CREATE_SNAPSHOT; - _create_snapshot_request.cbe_request = - Cbe::Request(op, false, 0, 0, 1, 0, 0); + _create_snapshot_request.tresor_request = + Tresor::Request(op, false, 0, 0, 1, 0, 0, 0, + COMMAND_POOL, 0); if (_verbose) { - Genode::log("Req: (req: ", _create_snapshot_request.cbe_request, ")"); + Genode::log("Req: (req: ", _create_snapshot_request.tresor_request, ")"); } - _cbe->submit_client_request(_create_snapshot_request.cbe_request, 0); + _request_pool->submit_request(_create_snapshot_request.tresor_request); _create_snapshot_request.state = Frontend_request::State::IN_PROGRESS; @@ -1756,31 +1307,32 @@ class Vfs_cbe::Wrapper Frontend_request _discard_snapshot_request { }; - bool discard_snapshot(Cbe::Generation id) + bool discard_snapshot(Tresor::Generation id) { - if (!_cbe.constructed()) { - _initialize_cbe(); + if (!_request_pool.constructed()) { + _initialize_tresor(); } - if (!_cbe->client_request_acceptable()) { + if (!_request_pool->ready_to_submit_request()) { return false; } - if (_discard_snapshot_request.cbe_request.valid()) { + if (_discard_snapshot_request.tresor_request.valid()) { return false; } - Cbe::Request::Operation const op = - Cbe::Request::Operation::DISCARD_SNAPSHOT; + Tresor::Request::Operation const op = + Tresor::Request::Operation::DISCARD_SNAPSHOT; - _discard_snapshot_request.cbe_request = - Cbe::Request(op, false, 0, 0, 1, 0, 0); + _discard_snapshot_request.tresor_request = + Tresor::Request(op, false, 0, 0, 1, 0, 0, (uint32_t)id, + COMMAND_POOL, 0); if (_verbose) { - Genode::log("Req: (req: ", _discard_snapshot_request.cbe_request, ")"); + Genode::log("Req: (req: ", _discard_snapshot_request.tresor_request, ")"); } - _cbe->submit_client_request(_discard_snapshot_request.cbe_request, id); + _request_pool->submit_request(_discard_snapshot_request.tresor_request); _discard_snapshot_request.state = Frontend_request::State::IN_PROGRESS; @@ -1796,7 +1348,7 @@ class Vfs_cbe::Wrapper }; -class Vfs_cbe::Data_file_system : public Single_file_system +class Vfs_tresor::Data_file_system : public Single_file_system { private: @@ -1832,7 +1384,7 @@ class Vfs_cbe::Data_file_system : public Single_file_system if (!_w.client_request_acceptable()) { return READ_QUEUED; } - using Op = Cbe::Request::Operation; + using Op = Tresor::Request::Operation; bool const accepted = _w.submit_frontend_request(*this, dst, Op::READ, _snap_id); @@ -1881,7 +1433,7 @@ class Vfs_cbe::Data_file_system : public Single_file_system if (!_w.client_request_acceptable()) return Write_result::WRITE_ERR_WOULD_BLOCK; - using Op = Cbe::Request::Operation; + using Op = Tresor::Request::Operation; bool const accepted = _w.submit_frontend_request(*this, @@ -1933,7 +1485,7 @@ class Vfs_cbe::Data_file_system : public Single_file_system if (!_w.client_request_acceptable()) { return SYNC_QUEUED; } - using Op = Cbe::Request::Operation; + using Op = Tresor::Request::Operation; bool const accepted = _w.submit_frontend_request(*this, Byte_range_ptr(nullptr, 0), @@ -1983,7 +1535,7 @@ class Vfs_cbe::Data_file_system : public Single_file_system Stat_result stat(char const *path, Stat &out) override { try { - (void)_w.cbe(); + (void)_w.tresor(); } catch (...) { return STAT_ERR_NO_ENTRY; } @@ -1991,7 +1543,7 @@ class Vfs_cbe::Data_file_system : public Single_file_system Stat_result result = Single_file_system::stat(path, out); /* max_vba range is from 0 ... N - 1 */ - out.size = (_w.cbe().max_vba() + 1) * Cbe::BLOCK_SIZE; + out.size = (_w.max_vba() + 1) * Tresor::BLOCK_SIZE; return result; } @@ -2000,7 +1552,7 @@ class Vfs_cbe::Data_file_system : public Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle *handle, file_size) override + Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override { return FTRUNCATE_OK; } @@ -2018,7 +1570,7 @@ class Vfs_cbe::Data_file_system : public Single_file_system return OPEN_ERR_UNACCESSIBLE; try { - (void)_w.cbe(); + (void)_w.tresor(); } catch (...) { return OPEN_ERR_UNACCESSIBLE; } @@ -2034,7 +1586,7 @@ class Vfs_cbe::Data_file_system : public Single_file_system }; -class Vfs_cbe::Extend_file_system : public Vfs::Single_file_system +class Vfs_tresor::Extend_file_system : public Vfs::Single_file_system { private: @@ -2047,31 +1599,13 @@ class Vfs_cbe::Extend_file_system : public Vfs::Single_file_system using Content_string = String<32>; - static Content_string content_string(Wrapper const &wrapper) + static file_size copy_content(Content_string const &content, + char *dst, size_t const count) { - Wrapper::Extending const & extending_progress { - wrapper.extending_progress() }; - - bool const in_progress { - extending_progress.state == - Wrapper::Extending::State::IN_PROGRESS }; - - bool const last_result { - !in_progress && - extending_progress.last_result != - Wrapper::Extending::Result::NONE }; - - bool const success { - extending_progress.last_result == - Wrapper::Extending::Result::SUCCESS }; - - Content_string const result { - Wrapper::Extending::state_to_cstring(extending_progress.state), - " last-result:", - last_result ? success ? "success" : "failed" : "none", - "\n" }; - - return result; + 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 @@ -2089,17 +1623,34 @@ class Vfs_cbe::Extend_file_system : public Vfs::Single_file_system Read_result read(Byte_range_ptr const &dst, size_t &out_count) override { + /* EOF */ if (seek() != 0) { out_count = 0; return READ_OK; } - Content_string const result { content_string(_w) }; - copy_cstring(dst.start, result.string(), dst.num_bytes); - size_t const length_without_nul = result.length() - 1; - out_count = dst.num_bytes > length_without_nul - 1 ? - length_without_nul : dst.num_bytes; - return READ_OK; + /* + * For now trigger extending execution via this hook + * like we do in the Data_file_system. + */ + _w.handle_frontend_request(); + + 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); + out_count = dst.num_bytes; + return READ_OK; + } + + return READ_ERR_IO; } Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override @@ -2146,11 +1697,6 @@ class Vfs_cbe::Extend_file_system : public Vfs::Single_file_system _w.manage_extend_file_system(*this); } - ~Extend_file_system() - { - _w.dissolve_extend_file_system(*this); - } - static char const *type_name() { return "extend"; } char const *type() override { return type_name(); } @@ -2208,7 +1754,7 @@ class Vfs_cbe::Extend_file_system : public Vfs::Single_file_system 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::size(); return result; } @@ -2217,14 +1763,14 @@ class Vfs_cbe::Extend_file_system : public Vfs::Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle *handle, file_size) override + Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_cbe::Rekey_file_system : public Vfs::Single_file_system +class Vfs_tresor::Extend_progress_file_system : public Vfs::Single_file_system { private: @@ -2237,31 +1783,13 @@ class Vfs_cbe::Rekey_file_system : public Vfs::Single_file_system using Content_string = String<32>; - static Content_string content_string(Wrapper const &wrapper) + static file_size copy_content(Content_string const &content, + char *dst, size_t const count) { - Wrapper::Rekeying const & rekeying_progress { - wrapper.rekeying_progress() }; - - bool const in_progress { - rekeying_progress.state == - Wrapper::Rekeying::State::IN_PROGRESS }; - - bool const last_result { - !in_progress && - rekeying_progress.last_result != - Wrapper::Rekeying::Result::NONE }; - - bool const success { - rekeying_progress.last_result == - Wrapper::Rekeying::Result::SUCCESS }; - - Content_string const result { - Wrapper::Rekeying::state_to_cstring(rekeying_progress.state), - " last-result:", - last_result ? success ? "success" : "failed" : "none", - "\n" }; - - return result; + 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 @@ -2277,19 +1805,206 @@ class Vfs_cbe::Rekey_file_system : public Vfs::Single_file_system _w(w) { } - Read_result read(Byte_range_ptr const &dst, size_t &out_count) override + Read_result read(Byte_range_ptr const &dst, + size_t &out_count) override { + /* EOF */ if (seek() != 0) { out_count = 0; return READ_OK; } - Content_string const result { content_string(_w) }; - copy_cstring(dst.start, result.string(), dst.num_bytes); - size_t const length_without_nul = result.length() - 1; - out_count = dst.num_bytes > length_without_nul - 1 ? - length_without_nul : dst.num_bytes; - return READ_OK; + /* + * For now trigger extending execution via this hook + * like we do in the Data_file_system. + */ + _w.handle_frontend_request(); + + 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 + { + 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 * /* handle */, file_size) override + { + return FTRUNCATE_OK; + } +}; + + +class Vfs_tresor::Rekey_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; + + /* 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.handle_frontend_request(); + + 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); + out_count = dst.num_bytes; + return READ_OK; + } + + return READ_ERR_IO; } Write_result write(Const_byte_range_ptr const &src, size_t &out_count) override @@ -2329,11 +2044,6 @@ class Vfs_cbe::Rekey_file_system : public Vfs::Single_file_system _w.manage_rekey_file_system(*this); } - ~Rekey_file_system() - { - _w.dissolve_rekey_file_system(*this); - } - static char const *type_name() { return "rekey"; } char const *type() override { return type_name(); } @@ -2391,7 +2101,7 @@ class Vfs_cbe::Rekey_file_system : public Vfs::Single_file_system 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::size(); return result; } @@ -2400,14 +2110,178 @@ class Vfs_cbe::Rekey_file_system : public Vfs::Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle *handle, file_size) override + Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_cbe::Deinitialize_file_system : public Vfs::Single_file_system +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.handle_frontend_request(); + + 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"; } + + 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 * /* handle */, file_size) override + { + return FTRUNCATE_OK; + } +}; + + +class Vfs_tresor::Deinitialize_file_system : public Vfs::Single_file_system { private: @@ -2512,11 +2386,6 @@ class Vfs_cbe::Deinitialize_file_system : public Vfs::Single_file_system _w.manage_deinit_file_system(*this); } - ~Deinitialize_file_system() - { - _w.dissolve_deinit_file_system(*this); - } - static char const *type_name() { return "deinitialize"; } char const *type() override { return type_name(); } @@ -2583,14 +2452,14 @@ class Vfs_cbe::Deinitialize_file_system : public Vfs::Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle *handle, file_size) override + Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_cbe::Create_snapshot_file_system : public Vfs::Single_file_system +class Vfs_tresor::Create_snapshot_file_system : public Vfs::Single_file_system { private: @@ -2682,14 +2551,14 @@ class Vfs_cbe::Create_snapshot_file_system : public Vfs::Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle *handle, file_size) override + Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override { return FTRUNCATE_OK; } }; -class Vfs_cbe::Discard_snapshot_file_system : public Vfs::Single_file_system +class Vfs_tresor::Discard_snapshot_file_system : public Vfs::Single_file_system { private: @@ -2724,7 +2593,7 @@ class Vfs_cbe::Discard_snapshot_file_system : public Vfs::Single_file_system return WRITE_ERR_IO; } - if (!_w.discard_snapshot(Cbe::Generation { id })) { + if (!_w.discard_snapshot(Tresor::Generation { id })) { out_count = 0; return WRITE_OK; } @@ -2780,21 +2649,21 @@ class Vfs_cbe::Discard_snapshot_file_system : public Vfs::Single_file_system ** File I/O service interface ** ********************************/ - Ftruncate_result ftruncate(Vfs::Vfs_handle *handle, file_size) override + Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override { return FTRUNCATE_OK; } }; -struct Vfs_cbe::Snapshot_local_factory : File_system_factory +struct Vfs_tresor::Snapshot_local_factory : File_system_factory { Data_file_system _block_fs; - Snapshot_local_factory(Vfs::Env &env, - Wrapper &cbe, + Snapshot_local_factory(Vfs::Env & /* env */, + Wrapper &tresor, uint32_t snap_id) - : _block_fs(cbe, snap_id) { } + : _block_fs(tresor, snap_id) { } Vfs::File_system *create(Vfs::Env&, Xml_node node) override { @@ -2806,8 +2675,8 @@ struct Vfs_cbe::Snapshot_local_factory : File_system_factory }; -class Vfs_cbe::Snapshot_file_system : private Snapshot_local_factory, - public Vfs::Dir_file_system +class Vfs_tresor::Snapshot_file_system : private Snapshot_local_factory, + public Vfs::Dir_file_system { private: @@ -2836,11 +2705,11 @@ class Vfs_cbe::Snapshot_file_system : private Snapshot_local_factory, public: Snapshot_file_system(Vfs::Env &vfs_env, - Wrapper &cbe, + Wrapper &tresor, Genode::uint32_t snap_id, bool readonly = false) : - Snapshot_local_factory(vfs_env, cbe, snap_id), + Snapshot_local_factory(vfs_env, tresor, snap_id), Vfs::Dir_file_system(vfs_env, Xml_node(_config(snap_id, readonly).string()), *this), @@ -2858,7 +2727,7 @@ class Vfs_cbe::Snapshot_file_system : private Snapshot_local_factory, }; -class Vfs_cbe::Snapshots_file_system : public Vfs::File_system +class Vfs_tresor::Snapshots_file_system : public Vfs::File_system { private: @@ -2898,9 +2767,9 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system uint32_t number_of_snapshots() const { return _number_of_snapshots; } - Snapshot_file_system const &by_index(uint32_t idx) const + Snapshot_file_system const &by_index(uint64_t idx) const { - uint32_t i = 0; + uint64_t i = 0; Snapshot_file_system const *fsp { nullptr }; auto lookup = [&] (Snapshot_file_system const &fs) { if (i == idx) { @@ -3138,7 +3007,7 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system Snapshots_file_system(Vfs::Env &vfs_env, - Genode::Xml_node node, + Genode::Xml_node /* node */, Wrapper &wrapper) : _vfs_env { vfs_env }, @@ -3148,11 +3017,6 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system _wrapper.manage_snapshots_file_system(*this); } - ~Snapshots_file_system() - { - _wrapper.dissolve_snapshots_file_system(*this); - } - static char const *type_name() { return "snapshots"; } char const *type() override { return type_name(); } @@ -3162,12 +3026,12 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system ** Directory service interface ** *********************************/ - Dataspace_capability dataspace(char const *path) + Dataspace_capability dataspace(char const * /* path */) override { return Genode::Dataspace_capability(); } - void release(char const *path, Dataspace_capability) + void release(char const * /* path */, Dataspace_capability) override { } @@ -3266,12 +3130,12 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system return STAT_ERR_NO_ENTRY; } - Unlink_result unlink(char const *path) + Unlink_result unlink(char const * /* path */) override { return UNLINK_ERR_NO_PERM; } - Rename_result rename(char const *from, char const *to) override + Rename_result rename(char const * /* from */, char const * /* to */) override { return RENAME_ERR_NO_PERM; } @@ -3346,8 +3210,8 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system ** File I/O service interface ** ********************************/ - Write_result write(Vfs::Vfs_handle *vfs_handle, - Const_byte_range_ptr const &, size_t &out_count) override + Write_result write(Vfs::Vfs_handle * /* vfs_handle */, + Const_byte_range_ptr const &, size_t & /* out_count */) override { return WRITE_ERR_IO; } @@ -3394,38 +3258,57 @@ class Vfs_cbe::Snapshots_file_system : public Vfs::File_system return false; } - Ftruncate_result ftruncate(Vfs::Vfs_handle *vfs_handle, - file_size len) override + Ftruncate_result ftruncate(Vfs::Vfs_handle * /* handle */, file_size) override { return FTRUNCATE_OK; } }; -struct Vfs_cbe::Control_local_factory : File_system_factory +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 &cbe) + Control_local_factory(Vfs::Env & /* env */, + Xml_node /* config */, + Wrapper & wrapper) : - _rekeying_fs(cbe), - _deinitialize_fs(cbe), - _create_snapshot_fs(cbe), - _discard_snapshot_fs(cbe), - _extend_fs(cbe) + _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; } @@ -3442,26 +3325,32 @@ struct Vfs_cbe::Control_local_factory : File_system_factory return &_extend_fs; } + if (node.has_type(Extend_progress_file_system::type_name())) { + return &_extend_progress_fs; + } + return nullptr; } }; -class Vfs_cbe::Control_file_system : private Control_local_factory, - public Vfs::Dir_file_system +class Vfs_tresor::Control_file_system : private Control_local_factory, + public Vfs::Dir_file_system { private: - typedef String<128> Config; + typedef String<256> Config; - static Config _config(Xml_node node) + static Config _config(Xml_node /* node */) { 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", [&] () { }); @@ -3474,9 +3363,9 @@ class Vfs_cbe::Control_file_system : private Control_local_factory, Control_file_system(Vfs::Env &vfs_env, Genode::Xml_node node, - Wrapper &cbe) + Wrapper &tresor) : - Control_local_factory(vfs_env, node, cbe), + Control_local_factory(vfs_env, node, tresor), Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), *this) { } @@ -3487,20 +3376,27 @@ class Vfs_cbe::Control_file_system : private Control_local_factory, }; -struct Vfs_cbe::Local_factory : File_system_factory +struct Vfs_tresor::Local_factory : File_system_factory { - Snapshot_file_system _current_snapshot_fs; - Snapshots_file_system _snapshots_fs; - Control_file_system _control_fs; + 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 &cbe) + Wrapper &wrapper) : - _current_snapshot_fs(env, cbe, 0, false), - _snapshots_fs(env, config, cbe), - _control_fs(env, config, cbe) + _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>; @@ -3519,8 +3415,8 @@ struct Vfs_cbe::Local_factory : File_system_factory }; -class Vfs_cbe::File_system : private Local_factory, - public Vfs::Dir_file_system +class Vfs_tresor::File_system : private Local_factory, + public Vfs::Dir_file_system { private: @@ -3537,7 +3433,7 @@ class Vfs_cbe::File_system : private Local_factory, xml.attribute("name", node.attribute_value("name", - Name("cbe"))); + Name("tresor"))); xml.node("control", [&] () { }); @@ -3585,45 +3481,27 @@ extern "C" Vfs::File_system_factory *vfs_file_system_factory(void) { try { /* XXX wrapper is not managed and will leak */ - Vfs_cbe::Wrapper *wrapper = - new (vfs_env.alloc()) Vfs_cbe::Wrapper { vfs_env, node }; + Vfs_tresor::Wrapper *wrapper = + new (vfs_env.alloc()) Vfs_tresor::Wrapper { vfs_env, node }; return new (vfs_env.alloc()) - Vfs_cbe::File_system(vfs_env, node, *wrapper); + Vfs_tresor::File_system(vfs_env, node, *wrapper); } catch (...) { - Genode::error("could not create 'cbe_fs' "); + Genode::error("could not create 'tresor_fs' "); } return nullptr; } }; - /* the CBE library requires a stack larger than the default */ - Genode::Thread::myself()->stack_size(64*1024); - - Cbe::assert_valid_object_size(); - - cbe_cxx_init(); - static Factory factory; return &factory; } -/* - * The SPARK compiler might generate a call to memcmp when it wants to - * compare objects. For the time being we implement here and hopefully - * any other memcmp symbol has at least the same semantics. - */ -extern "C" int memcmp(const void *s1, const void *s2, Genode::size_t n) -{ - return Genode::memcmp(s1, s2, n); -} - - /********************** - ** Vfs_cbe::Wrapper ** + ** Vfs_tresor::Wrapper ** **********************/ -void Vfs_cbe::Wrapper::_snapshots_fs_update_snapshot_registry() +void Vfs_tresor::Wrapper::_snapshots_fs_update_snapshot_registry() { if (_snapshots_fs.valid()) { _snapshots_fs.obj().update_snapshot_registry(); @@ -3631,7 +3509,7 @@ void Vfs_cbe::Wrapper::_snapshots_fs_update_snapshot_registry() } -void Vfs_cbe::Wrapper::_extend_fs_trigger_watch_response() +void Vfs_tresor::Wrapper::_extend_fs_trigger_watch_response() { if (_extend_fs.valid()) { _extend_fs.obj().trigger_watch_response(); @@ -3639,7 +3517,15 @@ void Vfs_cbe::Wrapper::_extend_fs_trigger_watch_response() } -void Vfs_cbe::Wrapper::_rekey_fs_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(); @@ -3647,7 +3533,15 @@ void Vfs_cbe::Wrapper::_rekey_fs_trigger_watch_response() } -void Vfs_cbe::Wrapper::_deinit_fs_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(); @@ -3656,19 +3550,19 @@ void Vfs_cbe::Wrapper::_deinit_fs_trigger_watch_response() /******************************************************* - ** Vfs_cbe::Snapshots_file_system::Snapshot_registry ** + ** Vfs_tresor::Snapshots_file_system::Snapshot_registry ** *******************************************************/ -void Vfs_cbe::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_env) +void Vfs_tresor::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_env) { - Cbe::Active_snapshot_ids list { }; - _wrapper.active_snapshot_ids(list); + Tresor::Snapshot_generations generations { }; + _wrapper.snapshot_generations(generations); bool trigger_watch_response { false }; /* alloc new */ - for (size_t i = 0; i < sizeof (list.values) / sizeof (list.values[0]); i++) { + for (size_t i = 0; i < MAX_NR_OF_SNAPSHOTS; i++) { - uint32_t const id = list.values[i]; + uint32_t const id = (uint32_t)generations.items[i]; if (!id) { continue; } @@ -3693,8 +3587,8 @@ void Vfs_cbe::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_env auto find_stale = [&] (Snapshot_file_system const &fs) { bool is_stale = true; - for (size_t i = 0; i < sizeof (list.values) / sizeof (list.values[0]); i++) { - uint32_t const id = list.values[i]; + for (size_t i = 0; i < MAX_NR_OF_SNAPSHOTS; i++) { + uint32_t const id = (uint32_t)generations.items[i]; if (!id) { continue; } if (fs.snapshot_id() == id) { @@ -3713,4 +3607,4 @@ void Vfs_cbe::Snapshots_file_system::Snapshot_registry::update(Vfs::Env &vfs_env if (trigger_watch_response) { _snapshots_fs.trigger_watch_response(); } -} +} diff --git a/repos/gems/src/lib/vfs/cbe_crypto/aes_cbc/aes_cbc.cc b/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/aes_cbc.cc similarity index 81% rename from repos/gems/src/lib/vfs/cbe_crypto/aes_cbc/aes_cbc.cc rename to repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/aes_cbc.cc index 4c3cc704fe..04edcfe60b 100644 --- a/repos/gems/src/lib/vfs/cbe_crypto/aes_cbc/aes_cbc.cc +++ b/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/aes_cbc.cc @@ -1,5 +1,5 @@ /* - * \brief Integration of the Consistent Block Encrypter (CBE) + * \brief Integration of the Tresor block encryption * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 @@ -17,14 +17,14 @@ #include -#include -#include +#include +#include namespace { using namespace Genode; -struct Crypto : Cbe_crypto::Interface +struct Crypto : Tresor_crypto::Interface { struct Buffer_size_mismatch : Genode::Exception { }; struct Key_value_size_mismatch : Genode::Exception { }; @@ -41,8 +41,9 @@ struct Crypto : Cbe_crypto::Interface unsigned tail { 0 }; struct { - Cbe::Request request { }; - Cbe::Block_data data { }; + uint64_t blk_nr { 0 }; + uint32_t key_id { 0 }; + Tresor::Block data { }; } queue [4]; unsigned max() const { @@ -162,7 +163,7 @@ struct Crypto : Cbe_crypto::Interface uint32_t const key_id, Const_byte_range_ptr const &src) override { - if (!src.start || src.num_bytes != sizeof (Cbe::Block_data)) { + if (!src.start || src.num_bytes != sizeof (Tresor::Block)) { error("buffer has wrong size"); throw Buffer_size_mismatch(); } @@ -172,10 +173,10 @@ struct Crypto : Cbe_crypto::Interface return apply_key (key_id, [&] (auto &meta) { return jobs.queue_encrypt([&] (auto &job) { - job.request = Cbe::Request(Cbe::Request::Operation::WRITE, - false, block_number, 0, 1, key_id, 0); + job.blk_nr = block_number; + job.key_id = key_id; - uint64_t block_id = job.request.block_number(); + uint64_t block_id = job.blk_nr; Aes_cbc_4k::Block_number block_number { block_id }; Aes_cbc_4k::Plaintext const &plaintext = *reinterpret_cast(src.start); @@ -191,10 +192,10 @@ struct Crypto : Cbe_crypto::Interface Complete_request encryption_request_complete(Byte_range_ptr const &dst) override { - static_assert(sizeof(Cbe::Block_data) == sizeof(Aes_cbc_4k::Ciphertext), "size mismatch"); - static_assert(sizeof(Cbe::Block_data) == sizeof(Aes_cbc_4k::Plaintext), "size mismatch"); + static_assert(sizeof(Tresor::Block) == sizeof(Aes_cbc_4k::Ciphertext), "size mismatch"); + static_assert(sizeof(Tresor::Block) == sizeof(Aes_cbc_4k::Plaintext), "size mismatch"); - if (dst.num_bytes != sizeof (Cbe::Block_data)) { + if (dst.num_bytes != sizeof (Tresor::Block)) { error("buffer has wrong size"); throw Buffer_size_mismatch(); } @@ -204,7 +205,7 @@ struct Crypto : Cbe_crypto::Interface bool const valid = jobs.apply_encrypt([&](auto const &job) { Genode::memcpy(dst.start, &job.data, sizeof(job.data)); - block_id = job.request.block_number(); + block_id = job.blk_nr; return true; }); @@ -217,7 +218,7 @@ struct Crypto : Cbe_crypto::Interface uint32_t const key_id, Const_byte_range_ptr const &src) override { - if (src.num_bytes != sizeof (Cbe::Block_data)) { + if (src.num_bytes != sizeof (Tresor::Block)) { error("buffer has wrong size"); throw Buffer_size_mismatch(); } @@ -228,8 +229,8 @@ struct Crypto : Cbe_crypto::Interface /* use apply_key to make sure key_id is actually known */ return apply_key (key_id, [&] (auto &) { return jobs.queue_decrypt([&] (auto &job) { - job.request = Cbe::Request(Cbe::Request::Operation::READ, - false, block_number, 0, 1, key_id, 0); + job.blk_nr = block_number; + job.key_id = key_id; Genode::memcpy(&job.data, src.start, sizeof(job.data)); }); }); @@ -237,10 +238,10 @@ struct Crypto : Cbe_crypto::Interface Complete_request decryption_request_complete(Byte_range_ptr const &dst) override { - static_assert(sizeof(Cbe::Block_data) == sizeof(Aes_cbc_4k::Ciphertext), "size mismatch"); - static_assert(sizeof(Cbe::Block_data) == sizeof(Aes_cbc_4k::Plaintext), "size mismatch"); + static_assert(sizeof(Tresor::Block) == sizeof(Aes_cbc_4k::Ciphertext), "size mismatch"); + static_assert(sizeof(Tresor::Block) == sizeof(Aes_cbc_4k::Plaintext), "size mismatch"); - if (dst.num_bytes != sizeof (Cbe::Block_data)) { + if (dst.num_bytes != sizeof (Tresor::Block)) { error("buffer has wrong size"); throw Buffer_size_mismatch(); } @@ -248,8 +249,8 @@ struct Crypto : Cbe_crypto::Interface uint64_t block_id = 0; bool const valid = jobs.apply_decrypt([&](auto const &job) { - bool ok = apply_key (job.request.key_id(), [&] (auto &meta) { - block_id = job.request.block_number(); + bool ok = apply_key (job.key_id, [&] (auto &meta) { + block_id = job.blk_nr; Aes_cbc_4k::Block_number block_number { block_id }; Aes_cbc_4k::Ciphertext const &ciphertext = *reinterpret_cast(&job.data); @@ -274,7 +275,7 @@ struct Crypto : Cbe_crypto::Interface } /* anonymous namespace */ -Cbe_crypto::Interface &Cbe_crypto::get_interface() +Tresor_crypto::Interface &Tresor_crypto::get_interface() { static Crypto inst; return inst; diff --git a/repos/gems/src/lib/vfs/cbe/dummy.ads b/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/dummy.ads similarity index 82% rename from repos/gems/src/lib/vfs/cbe/dummy.ads rename to repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/dummy.ads index bf6121ad6e..49400e28c4 100644 --- a/repos/gems/src/lib/vfs/cbe/dummy.ads +++ b/repos/gems/src/lib/vfs/tresor_crypto/aes_cbc/dummy.ads @@ -1,5 +1,5 @@ -- --- \brief Integration of the Consistent Block Encrypter (CBE) +-- \brief Integration of the Tresor block encryption -- \author Martin Stein -- \author Josef Soentgen -- \date 2020-11-10 diff --git a/repos/gems/src/lib/vfs/cbe_crypto/memcopy/memcopy.cc b/repos/gems/src/lib/vfs/tresor_crypto/memcopy/memcopy.cc similarity index 90% rename from repos/gems/src/lib/vfs/cbe_crypto/memcopy/memcopy.cc rename to repos/gems/src/lib/vfs/tresor_crypto/memcopy/memcopy.cc index 6ede129b0d..18d62cbed3 100644 --- a/repos/gems/src/lib/vfs/cbe_crypto/memcopy/memcopy.cc +++ b/repos/gems/src/lib/vfs/tresor_crypto/memcopy/memcopy.cc @@ -1,5 +1,5 @@ /* - * \brief Integration of the Consistent Block Encrypter (CBE) + * \brief Integration of the Tresor block encryption * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 @@ -16,16 +16,16 @@ #include #include -/* cbe_crypto includes */ -#include +/* tresor_crypto includes */ +#include namespace { using namespace Genode; -struct Crypto : Cbe_crypto::Interface +struct Crypto : Tresor_crypto::Interface { - char _internal_buffer[Cbe_crypto::BLOCK_SIZE] { }; + char _internal_buffer[Tresor_crypto::BLOCK_SIZE] { }; struct Request { @@ -131,7 +131,7 @@ struct Crypto : Cbe_crypto::Interface } /* anonymous namespace */ -Cbe_crypto::Interface &Cbe_crypto::get_interface() +Tresor_crypto::Interface &Tresor_crypto::get_interface() { static Crypto inst; return inst; diff --git a/repos/gems/src/lib/vfs/cbe_crypto/vfs.cc b/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc similarity index 90% rename from repos/gems/src/lib/vfs/cbe_crypto/vfs.cc rename to repos/gems/src/lib/vfs/tresor_crypto/vfs.cc index 2c9ed69984..5aee3d367b 100644 --- a/repos/gems/src/lib/vfs/cbe_crypto/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor_crypto/vfs.cc @@ -1,5 +1,5 @@ /* - * \brief Integration of the Consistent Block Encrypter (CBE) + * \brief Integration of the Tresor block encryption * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 @@ -18,11 +18,11 @@ #include #include -/* CBE includes */ -#include +/* Tresor includes */ +#include -namespace Vfs_cbe_crypto { +namespace Vfs_tresor_crypto { using namespace Vfs; using namespace Genode; @@ -44,16 +44,16 @@ namespace Vfs_cbe_crypto { } -class Vfs_cbe_crypto::Encrypt_file_system : public Vfs::Single_file_system +class Vfs_tresor_crypto::Encrypt_file_system : public Vfs::Single_file_system { private: - Cbe_crypto::Interface &_crypto; + Tresor_crypto::Interface &_crypto; uint32_t _key_id; struct Encrypt_handle : Single_vfs_handle { - Cbe_crypto::Interface &_crypto; + Tresor_crypto::Interface &_crypto; uint32_t _key_id; enum State { NONE, PENDING }; @@ -62,7 +62,7 @@ class Vfs_cbe_crypto::Encrypt_file_system : public Vfs::Single_file_system Encrypt_handle(Directory_service &ds, File_io_service &fs, Genode::Allocator &alloc, - Cbe_crypto::Interface &crypto, + Tresor_crypto::Interface &crypto, uint32_t key_id) : Single_vfs_handle { ds, fs, alloc, 0 }, @@ -80,7 +80,7 @@ class Vfs_cbe_crypto::Encrypt_file_system : public Vfs::Single_file_system _crypto.execute(); try { - Cbe_crypto::Interface::Complete_request const cr = + Tresor_crypto::Interface::Complete_request const cr = _crypto.encryption_request_complete(dst); if (!cr.valid) { return READ_ERR_INVALID; @@ -90,7 +90,7 @@ class Vfs_cbe_crypto::Encrypt_file_system : public Vfs::Single_file_system out_count = dst.num_bytes; return READ_OK; - } catch (Cbe_crypto::Interface::Buffer_too_small) { + } catch (Tresor_crypto::Interface::Buffer_too_small) { return READ_ERR_INVALID; } @@ -105,7 +105,7 @@ class Vfs_cbe_crypto::Encrypt_file_system : public Vfs::Single_file_system } try { - uint64_t const block_number = seek() / Cbe_crypto::BLOCK_SIZE; + uint64_t const block_number = seek() / Tresor_crypto::BLOCK_SIZE; bool const ok = _crypto.submit_encryption_request(block_number, _key_id, src); if (!ok) { @@ -113,7 +113,7 @@ class Vfs_cbe_crypto::Encrypt_file_system : public Vfs::Single_file_system return WRITE_OK; } _state = State::PENDING; - } catch (Cbe_crypto::Interface::Buffer_too_small) { + } catch (Tresor_crypto::Interface::Buffer_too_small) { return WRITE_ERR_INVALID; } @@ -128,7 +128,7 @@ class Vfs_cbe_crypto::Encrypt_file_system : public Vfs::Single_file_system public: - Encrypt_file_system(Cbe_crypto::Interface &crypto, uint32_t key_id) + 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("") }, @@ -178,16 +178,16 @@ class Vfs_cbe_crypto::Encrypt_file_system : public Vfs::Single_file_system }; -class Vfs_cbe_crypto::Decrypt_file_system : public Vfs::Single_file_system +class Vfs_tresor_crypto::Decrypt_file_system : public Vfs::Single_file_system { private: - Cbe_crypto::Interface &_crypto; + Tresor_crypto::Interface &_crypto; uint32_t _key_id; struct Decrypt_handle : Single_vfs_handle { - Cbe_crypto::Interface &_crypto; + Tresor_crypto::Interface &_crypto; uint32_t _key_id; enum State { NONE, PENDING }; @@ -196,7 +196,7 @@ class Vfs_cbe_crypto::Decrypt_file_system : public Vfs::Single_file_system Decrypt_handle(Directory_service &ds, File_io_service &fs, Genode::Allocator &alloc, - Cbe_crypto::Interface &crypto, + Tresor_crypto::Interface &crypto, uint32_t key_id) : Single_vfs_handle { ds, fs, alloc, 0 }, @@ -214,7 +214,7 @@ class Vfs_cbe_crypto::Decrypt_file_system : public Vfs::Single_file_system _crypto.execute(); try { - Cbe_crypto::Interface::Complete_request const cr = + Tresor_crypto::Interface::Complete_request const cr = _crypto.decryption_request_complete(dst); if (cr.valid) { } @@ -222,7 +222,7 @@ class Vfs_cbe_crypto::Decrypt_file_system : public Vfs::Single_file_system out_count = dst.num_bytes; return READ_OK; - } catch (Cbe_crypto::Interface::Buffer_too_small) { + } catch (Tresor_crypto::Interface::Buffer_too_small) { return READ_ERR_INVALID; } @@ -236,7 +236,7 @@ class Vfs_cbe_crypto::Decrypt_file_system : public Vfs::Single_file_system } try { - uint64_t const block_number = seek() / Cbe_crypto::BLOCK_SIZE; + uint64_t const block_number = seek() / Tresor_crypto::BLOCK_SIZE; bool const ok = _crypto.submit_decryption_request(block_number, _key_id, src); if (!ok) { @@ -244,7 +244,7 @@ class Vfs_cbe_crypto::Decrypt_file_system : public Vfs::Single_file_system return WRITE_OK; } _state = State::PENDING; - } catch (Cbe_crypto::Interface::Buffer_too_small) { + } catch (Tresor_crypto::Interface::Buffer_too_small) { return WRITE_ERR_INVALID; } @@ -259,7 +259,7 @@ class Vfs_cbe_crypto::Decrypt_file_system : public Vfs::Single_file_system public: - Decrypt_file_system(Cbe_crypto::Interface &crypto, uint32_t key_id) + 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("") }, @@ -309,12 +309,12 @@ class Vfs_cbe_crypto::Decrypt_file_system : public Vfs::Single_file_system }; -struct Vfs_cbe_crypto::Key_local_factory : File_system_factory +struct Vfs_tresor_crypto::Key_local_factory : File_system_factory { Encrypt_file_system _encrypt_fs; Decrypt_file_system _decrypt_fs; - Key_local_factory(Cbe_crypto::Interface &crypto, + Key_local_factory(Tresor_crypto::Interface &crypto, uint32_t key_id) : _encrypt_fs { crypto, key_id }, @@ -334,7 +334,7 @@ struct Vfs_cbe_crypto::Key_local_factory : File_system_factory }; -class Vfs_cbe_crypto::Key_file_system : private Key_local_factory, +class Vfs_tresor_crypto::Key_file_system : private Key_local_factory, public Vfs::Dir_file_system { private: @@ -361,7 +361,7 @@ class Vfs_cbe_crypto::Key_file_system : private Key_local_factory, public: Key_file_system(Vfs::Env &vfs_env, - Cbe_crypto::Interface &crypto, + Tresor_crypto::Interface &crypto, uint32_t key_id) : Key_local_factory { crypto, key_id }, @@ -382,7 +382,7 @@ class Vfs_cbe_crypto::Key_file_system : private Key_local_factory, }; -class Vfs_cbe_crypto::Keys_file_system : public Vfs::File_system +class Vfs_tresor_crypto::Keys_file_system : public Vfs::File_system { private: @@ -394,7 +394,7 @@ class Vfs_cbe_crypto::Keys_file_system : public Vfs::File_system struct Key_registry { Genode::Allocator &_alloc; - Cbe_crypto::Interface &_crypto; + Tresor_crypto::Interface &_crypto; struct Invalid_index : Genode::Exception { }; struct Invalid_path : Genode::Exception { }; @@ -403,7 +403,7 @@ class Vfs_cbe_crypto::Keys_file_system : public Vfs::File_system Genode::Registry> _key_fs { }; - Key_registry(Genode::Allocator &alloc, Cbe_crypto::Interface &crypto) + Key_registry(Genode::Allocator &alloc, Tresor_crypto::Interface &crypto) : _alloc { alloc }, _crypto { crypto } @@ -650,7 +650,7 @@ class Vfs_cbe_crypto::Keys_file_system : public Vfs::File_system Keys_file_system(Vfs::Env &vfs_env, - Cbe_crypto::Interface &crypto) + Tresor_crypto::Interface &crypto) : _vfs_env { vfs_env }, _key_reg { vfs_env.alloc(), crypto } @@ -906,7 +906,7 @@ class Vfs_cbe_crypto::Keys_file_system : public Vfs::File_system -class Vfs_cbe_crypto::Management_file_system : public Vfs::Single_file_system +class Vfs_tresor_crypto::Management_file_system : public Vfs::Single_file_system { public: @@ -927,18 +927,18 @@ class Vfs_cbe_crypto::Management_file_system : public Vfs::Single_file_system Management_file_system &operator=(Management_file_system const&) = delete; Type _type; - Cbe_crypto::Interface &_crypto; + Tresor_crypto::Interface &_crypto; struct Manage_handle : Single_vfs_handle { Type _type; - Cbe_crypto::Interface &_crypto; + Tresor_crypto::Interface &_crypto; Manage_handle(Directory_service &ds, File_io_service &fs, Genode::Allocator &alloc, Type type, - Cbe_crypto::Interface &crypto) + Tresor_crypto::Interface &crypto) : Single_vfs_handle { ds, fs, alloc, 0 }, _type { type }, @@ -970,7 +970,7 @@ class Vfs_cbe_crypto::Management_file_system : public Vfs::Single_file_system if (_type == Type::ADD_KEY) { - if (src.num_bytes != sizeof (uint32_t) + 32 /* XXX Cbe::Key::value*/) { + if (src.num_bytes != sizeof (uint32_t) + 32 /* XXX Tresor::Key::value*/) { return WRITE_ERR_INVALID; } @@ -1008,7 +1008,7 @@ class Vfs_cbe_crypto::Management_file_system : public Vfs::Single_file_system public: - Management_file_system(Cbe_crypto::Interface &crypto, Type type, char const *type_name) + 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("") }, @@ -1059,36 +1059,36 @@ class Vfs_cbe_crypto::Management_file_system : public Vfs::Single_file_system }; -struct Vfs_cbe_crypto::Add_key_file_system : public Vfs_cbe_crypto::Management_file_system +struct Vfs_tresor_crypto::Add_key_file_system : public Vfs_tresor_crypto::Management_file_system { static char const *type_name() { return "add_key"; } - Add_key_file_system(Cbe_crypto::Interface &crypto) + Add_key_file_system(Tresor_crypto::Interface &crypto) : Management_file_system(crypto, Management_file_system::ADD_KEY, type_name()) { } char const *type() override { return type_name(); } }; -struct Vfs_cbe_crypto::Remove_key_file_system : public Vfs_cbe_crypto::Management_file_system +struct Vfs_tresor_crypto::Remove_key_file_system : public Vfs_tresor_crypto::Management_file_system { static char const *type_name() { return "remove_key"; } - Remove_key_file_system(Cbe_crypto::Interface &crypto) + Remove_key_file_system(Tresor_crypto::Interface &crypto) : Management_file_system(crypto, Management_file_system::REMOVE_KEY, type_name()) { } char const *type() override { return type_name(); } }; -struct Vfs_cbe_crypto::Local_factory : File_system_factory +struct Vfs_tresor_crypto::Local_factory : File_system_factory { Keys_file_system _keys_fs; Add_key_file_system _add_key_fs; Remove_key_file_system _remove_key_fs; Local_factory(Vfs::Env &env, - Cbe_crypto::Interface &crypto) + Tresor_crypto::Interface &crypto) : _keys_fs { env, crypto }, _add_key_fs { crypto }, @@ -1114,7 +1114,7 @@ struct Vfs_cbe_crypto::Local_factory : File_system_factory }; -class Vfs_cbe_crypto::File_system : private Local_factory, +class Vfs_tresor_crypto::File_system : private Local_factory, public Vfs::Dir_file_system { private: @@ -1142,7 +1142,7 @@ class Vfs_cbe_crypto::File_system : private Local_factory, File_system(Vfs::Env &vfs_env, Genode::Xml_node node) : - Local_factory { vfs_env, Cbe_crypto::get_interface() }, + Local_factory { vfs_env, Tresor_crypto::get_interface() }, Vfs::Dir_file_system { vfs_env, Xml_node(_config(node).string()), *this } { } @@ -1164,9 +1164,9 @@ extern "C" Vfs::File_system_factory *vfs_file_system_factory(void) { try { return new (vfs_env.alloc()) - Vfs_cbe_crypto::File_system(vfs_env, node); + Vfs_tresor_crypto::File_system(vfs_env, node); } catch (...) { - Genode::error("could not create 'cbe_crypto_aes_cbc'"); + Genode::error("could not create 'tresor_crypto_aes_cbc'"); } return nullptr; } diff --git a/repos/gems/src/lib/vfs/cbe_trust_anchor/aes_256.cc b/repos/gems/src/lib/vfs/tresor_trust_anchor/aes_256.cc similarity index 100% rename from repos/gems/src/lib/vfs/cbe_trust_anchor/aes_256.cc rename to repos/gems/src/lib/vfs/tresor_trust_anchor/aes_256.cc diff --git a/repos/gems/src/lib/vfs/cbe_trust_anchor/aes_256.h b/repos/gems/src/lib/vfs/tresor_trust_anchor/aes_256.h similarity index 100% rename from repos/gems/src/lib/vfs/cbe_trust_anchor/aes_256.h rename to repos/gems/src/lib/vfs/tresor_trust_anchor/aes_256.h diff --git a/repos/gems/src/lib/vfs/cbe_trust_anchor/integer.cc b/repos/gems/src/lib/vfs/tresor_trust_anchor/integer.cc similarity index 100% rename from repos/gems/src/lib/vfs/cbe_trust_anchor/integer.cc rename to repos/gems/src/lib/vfs/tresor_trust_anchor/integer.cc diff --git a/repos/gems/src/lib/vfs/cbe_trust_anchor/integer.h b/repos/gems/src/lib/vfs/tresor_trust_anchor/integer.h similarity index 100% rename from repos/gems/src/lib/vfs/cbe_trust_anchor/integer.h rename to repos/gems/src/lib/vfs/tresor_trust_anchor/integer.h diff --git a/repos/gems/src/lib/vfs/cbe_trust_anchor/vfs.cc b/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc similarity index 96% rename from repos/gems/src/lib/vfs/cbe_trust_anchor/vfs.cc rename to repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc index cdda056f18..028bff5692 100644 --- a/repos/gems/src/lib/vfs/cbe_trust_anchor/vfs.cc +++ b/repos/gems/src/lib/vfs/tresor_trust_anchor/vfs.cc @@ -1,5 +1,5 @@ /* - * \brief Integration of the Consistent Block Encrypter (CBE) + * \brief Integration of the Tresor block encryption * \author Martin Stein * \author Josef Soentgen * \date 2020-11-10 @@ -21,8 +21,8 @@ /* OpenSSL includes */ #include -/* CBE includes */ -#include +/* resor includes */ +#include /* local includes */ #include @@ -30,9 +30,10 @@ enum { PRIVATE_KEY_SIZE = 32 }; enum { PASSPHRASE_HASH_SIZE = 32 }; enum { VERBOSE = 0 }; +enum { DEBUG_MODE_STATIC_KEYS_OF_VALUE_0 = 0 }; -namespace Vfs_cbe_trust_anchor { +namespace Vfs_tresor_trust_anchor { using namespace Vfs; using namespace Genode; @@ -225,10 +226,16 @@ class Trust_anchor class Bad_jitterentropy_io_buffer_size { }; throw Bad_jitterentropy_io_buffer_size { }; } - Genode::memcpy(key.value, - _jitterentropy_io_job_buffer.base, - _jitterentropy_io_job_buffer.size); - + if (DEBUG_MODE_STATIC_KEYS_OF_VALUE_0) { + Genode::warning("DEBUG MODE active! " + "Using static keys of value 0!"); + Genode::memset(key.value, 0, + _jitterentropy_io_job_buffer.size); + } else { + Genode::memcpy(key.value, + _jitterentropy_io_job_buffer.base, + _jitterentropy_io_job_buffer.size); + } _job_state = Job_state::COMPLETE; _job_success = true; progress = true; @@ -335,11 +342,18 @@ class Trust_anchor class Bad_private_key_io_buffer_size { }; throw Bad_private_key_io_buffer_size { }; } - Genode::memcpy( - _private_key.value, - _private_key_io_job_buffer.base, - _private_key_io_job_buffer.size); - + if (DEBUG_MODE_STATIC_KEYS_OF_VALUE_0) { + Genode::warning("DEBUG MODE active! " + "Using static keys of value 0!"); + Genode::memset( + _private_key.value, 0, + _private_key_io_job_buffer.size); + } else { + Genode::memcpy( + _private_key.value, + _private_key_io_job_buffer.base, + _private_key_io_job_buffer.size); + } _key_io_job_buffer.size = Aes_256_key_wrap::CIPHERTEXT_SIZE; Aes_256_key_wrap::wrap_key( (unsigned char *)_key_io_job_buffer.base, @@ -1241,7 +1255,7 @@ class Trust_anchor }; -class Vfs_cbe_trust_anchor::Hashsum_file_system : public Vfs::Single_file_system +class Vfs_tresor_trust_anchor::Hashsum_file_system : public Vfs::Single_file_system { private: @@ -1399,7 +1413,7 @@ class Vfs_cbe_trust_anchor::Hashsum_file_system : public Vfs::Single_file_system }; -class Vfs_cbe_trust_anchor::Generate_key_file_system : public Vfs::Single_file_system +class Vfs_tresor_trust_anchor::Generate_key_file_system : public Vfs::Single_file_system { private: @@ -1505,7 +1519,7 @@ class Vfs_cbe_trust_anchor::Generate_key_file_system : public Vfs::Single_file_s }; -class Vfs_cbe_trust_anchor::Encrypt_file_system : public Vfs::Single_file_system +class Vfs_tresor_trust_anchor::Encrypt_file_system : public Vfs::Single_file_system { private: @@ -1631,7 +1645,7 @@ class Vfs_cbe_trust_anchor::Encrypt_file_system : public Vfs::Single_file_system }; -class Vfs_cbe_trust_anchor::Decrypt_file_system : public Vfs::Single_file_system +class Vfs_tresor_trust_anchor::Decrypt_file_system : public Vfs::Single_file_system { private: @@ -1757,7 +1771,7 @@ class Vfs_cbe_trust_anchor::Decrypt_file_system : public Vfs::Single_file_system }; -class Vfs_cbe_trust_anchor::Initialize_file_system : public Vfs::Single_file_system +class Vfs_tresor_trust_anchor::Initialize_file_system : public Vfs::Single_file_system { private: @@ -1804,7 +1818,7 @@ class Vfs_cbe_trust_anchor::Initialize_file_system : public Vfs::Single_file_sys char const *str { "ok" }; if (buf.num_bytes < 3) { - Genode::error("read buffer too small ", buf.num_bytes); + Genode::error("read buffer too small"); return READ_ERR_IO; } memcpy(buf.start, str, 3); @@ -1814,7 +1828,7 @@ class Vfs_cbe_trust_anchor::Initialize_file_system : public Vfs::Single_file_sys char const *str { "failed" }; if (buf.num_bytes < 7) { - Genode::error("read buffer too small ", buf.num_bytes); + Genode::error("read buffer too small"); return READ_ERR_IO; } memcpy(buf.start, str, 7); @@ -1899,7 +1913,7 @@ class Vfs_cbe_trust_anchor::Initialize_file_system : public Vfs::Single_file_sys }; -struct Vfs_cbe_trust_anchor::Local_factory : File_system_factory +struct Vfs_tresor_trust_anchor::Local_factory : File_system_factory { Trust_anchor _trust_anchor; @@ -1957,7 +1971,7 @@ struct Vfs_cbe_trust_anchor::Local_factory : File_system_factory }; -class Vfs_cbe_trust_anchor::File_system : private Local_factory, +class Vfs_tresor_trust_anchor::File_system : private Local_factory, public Vfs::Dir_file_system { private: @@ -2006,10 +2020,10 @@ extern "C" Vfs::File_system_factory *vfs_file_system_factory(void) { try { return new (vfs_env.alloc()) - Vfs_cbe_trust_anchor::File_system(vfs_env, node); + Vfs_tresor_trust_anchor::File_system(vfs_env, node); } catch (...) { - Genode::error("could not create 'cbe_trust_anchor'"); + Genode::error("could not create 'tresor_trust_anchor'"); } return nullptr; }