mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-18 21:27:56 +00:00
tresor: streamline design further
* differentiates request types that where merged formerly per module; e.g. instead of type Superblock_control::Request, there are now types * Superblock_control::Read_vbas * Superblock_control::Write_vbas * Superblock_control::Rekey * Superblock_control::Initialize * ... each holding only the state and functionality that is required for exactly that request * removes all classes of the Tresor module framework and adapts all Tresor- and File-Vault- related libs, apps, and tests accordingly * the former "channel" state is merged into the new request types, meaning, a request manages no longer only the "call" to a functionality but also the execution of that functionality; every request has a lifetime equal to the "call" and an execute method to be driven forward * state that is used by a request but has a longer lifetime (e.g. VFS file handles in Tresor::Crypto) is managed by the top level of the user and handed over via the execute arguments; however, the synchronization of multiple requests on this state is done by the module (e.g. Tresor::Crypto) * requests are now driven explicitly as first argument of the (overloaded) execute method of their module; the module can, however, stall a request by returning false without doing anything (used for synchronization on resources) * introduces Request_helper, Generated_request and Generatable_request in the Tresor namespace in order to avoid the redundancy of sub-request generation and execution * moves access to Client-Data pointers up to Tresor::Virtual_block_device in order to simplify Tresor::Block_io and Tresor::Crypto * removes Tresor::Client_data and introduces pure interface Client_data_interface in order to remove Tresor::Client_data and move management of Client Data to the top level of a Tresor user * introduces pure interface Crypto_files_interface in order to move management of Crypto files to the top level of a Tresor user * moves management of Block-IO and Trust-Anchor files to the top level of a Tresor user * adapts all execute methods, so, that they return the progress state instead of modifying a reference argument * removes Tresor::Request_and Tresor:Request and instead implements scheduling at the top level of the Tresor user * the Tresor Tester uses a list as schedule that holds Command objects; this list ensures, that commands are started in the order of configuration the Command type is a merge of the state of all possible commands that can be configured at the Tresor Tester; the actual Tresor requests (if any) are then allocated on-demand only * the Tresor VFS plugin does not use a dynamic data structure for scheduling; the plugin has 5 members that each reflect a distinct type of operation: * initialize operation * deinitialize operation * data operation * extend operation * rekey operation consequently, of each type, there can be only one operation in-flight at a time; at the user front-end each operation (except "initialize") can be controlled through a dedicated VFS file; for each of these files, the VFS expects only one handle to be open at a time and only one file operation (read, write, sync) active at a time; once an operation gets started it is finished without preemtion (except of the interleaving at rekey and extend); when multiple operations are waiting to be started the plugin follows a static priority scheme: init op > deinit op > data op > extend op > rekey op there are some operation-specific details * the initialize operation is started only by the plugin itself on startup and will be driven as side effect by subsequent user calls to file operations * the data file is the only contiguous file in the front end and the file operations work as on usual data files * the other 3 files are transactional files and the user is expected to follow this scheme when operating on them 1) stat (to determine file size) 2) seek to offset 0 3) read entire file once (this will be queued until there is no operation of this type pending anymore and return the last result: "none" | "failed" | "succeeded"; used primarily for synchronization) 4) write operation parameters (this returns immediately and marks the operation as "requested") 5) read entire file once (the same as above but this time in order to determine the operation result) * the rekey op and deinitialize op are requested by writing "true" * the extend op is requested by writing "tree=[TREE], blocks=[BLOCKS]" where TREE is either "vbd" or "ft" and BLOCKS is the number of physical 4K blocks by which the physical range of the tresor container expands (the physical range always starts at block address 0 and is always expanded upwards) * replaces the former <trust-anchor op="initialize"> command at the Tresor Tester with <initialize-trust-achor> as there are no other trust anchor operations that can be requested through the Tester config anyway * removes the "sync" attribute from all commands at the Tresor Tester except from <request op="rekey">, <request "extend_ft">, <request op="extend_vbd">; as the Tester controls scheduling now, requests are generally synchronous; at the rekeying and extension commands, the "sync" attribute determines wether subsequent commands are interleaved with the execution of these commands (if possible) * removes "debug" config attribute from Tresor VFS plugin and reworks "verbose" attribute to generate more sensible output * removes NONCOPYABLE macro and instead uses Genode::Noncopyable and in-place Constructors deletion * introduces types Attr and Execute_attr where a constructor or execute method have many arguments in order to raise readability * renames the "hashsum" file that is provided by the Tresor Trust-Anchor VFS plugin to "hash" in order to become conformant with the wording in the Tresor lib * makes the VFS Tresor test an automated test by merging in the functionality of vfs_tresor_init.run and removing the interactive front end; removes vfs_tresor_init.run as it is not needed anymore; adds consideration for autopilot file structure in the Test and adds it to autopilot.list * removes all snapshot controls and the progress files for rekeying and extending from the Tresor VFS plugin; both functionalities were tested only rudimentary by the VFS Tresor test and are not supported with the only real user, the File Vault * use /* .. */ instead of // .. * use (..) instead of { .. } in init lists Ref #5148
This commit is contained in:
parent
14f4aa6e05
commit
b4c4681733
@ -1,7 +1,6 @@
|
||||
TRESOR_DIR := $(REP_DIR)/src/lib/tresor
|
||||
|
||||
SRC_CC += crypto.cc
|
||||
SRC_CC += request_pool.cc
|
||||
SRC_CC += hash.cc
|
||||
SRC_CC += trust_anchor.cc
|
||||
SRC_CC += block_io.cc
|
||||
@ -9,7 +8,6 @@ SRC_CC += meta_tree.cc
|
||||
SRC_CC += virtual_block_device.cc
|
||||
SRC_CC += superblock_control.cc
|
||||
SRC_CC += free_tree.cc
|
||||
SRC_CC += module.cc
|
||||
SRC_CC += vbd_initializer.cc
|
||||
SRC_CC += ft_initializer.cc
|
||||
SRC_CC += sb_initializer.cc
|
||||
|
@ -1,6 +1,6 @@
|
||||
LIB_DIR := $(REP_DIR)/src/lib/vfs/tresor
|
||||
|
||||
SRC_CC := vfs.cc splitter.cc
|
||||
SRC_CC := vfs.cc
|
||||
|
||||
INC_DIR += $(LIB_DIR)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,24 +1,26 @@
|
||||
assert_spec linux
|
||||
|
||||
set dd [installed_command dd]
|
||||
|
||||
create_boot_directory
|
||||
|
||||
proc tresor_image_file { } {
|
||||
return "vfs_tresor_block.img"
|
||||
}
|
||||
proc tresor_image_name { } { return "vfs_tresor_block.img" }
|
||||
|
||||
set use_interactively [expr ![get_cmd_switch --autopilot]]
|
||||
proc tresor_image_size_mb { } { return 4 }
|
||||
|
||||
import_from_depot [depot_user]/pkg/[drivers_interactive_pkg] \
|
||||
[depot_user]/pkg/terminal \
|
||||
[depot_user]/src/ncurses \
|
||||
proc local_tresor_image { } { return bin/[tresor_image_name] }
|
||||
|
||||
proc autopilot_tresor_image { } { return /tmp/[tresor_image_name].[exec id -un] }
|
||||
|
||||
import_from_depot [depot_user]/src/ncurses \
|
||||
[depot_user]/src/bash \
|
||||
[depot_user]/src/coreutils \
|
||||
[depot_user]/src/nitpicker
|
||||
|
||||
[depot_user]/src/coreutils
|
||||
|
||||
build {
|
||||
core lib/ld timer init
|
||||
server/lx_fs
|
||||
core
|
||||
timer
|
||||
init
|
||||
lib/ld
|
||||
lib/vfs_tresor
|
||||
lib/vfs_tresor_crypto_aes_cbc
|
||||
lib/vfs_tresor_crypto_memcopy
|
||||
@ -26,17 +28,24 @@ build {
|
||||
lib/vfs_import
|
||||
lib/vfs_jitterentropy
|
||||
lib/vfs_pipe
|
||||
lib/vfs lib/libc lib/posix lib/libcrypto
|
||||
lib/vfs
|
||||
lib/libc
|
||||
lib/libm
|
||||
lib/posix
|
||||
lib/libcrypto
|
||||
test/vfs_stress
|
||||
test/libc
|
||||
server/log_terminal
|
||||
server/report_rom
|
||||
server/fs_rom
|
||||
server/lx_fs
|
||||
server/vfs
|
||||
app/tresor_init_trust_anchor
|
||||
app/tresor_init
|
||||
app/sequence
|
||||
}
|
||||
|
||||
set config {
|
||||
append config {
|
||||
<config verbose="yes">
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
@ -54,64 +63,20 @@ set config {
|
||||
</default-route>
|
||||
|
||||
<default caps="100"/>
|
||||
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
|
||||
<start name="drivers" caps="1000" managing_system="yes">
|
||||
<resource name="RAM" quantum="32M"/>
|
||||
<binary name="init"/>
|
||||
<route>
|
||||
<service name="ROM" label="config"> <parent label="drivers.config"/> </service>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
<service name="Capture"> <child name="nitpicker"/> </service>
|
||||
<service name="Event"> <child name="nitpicker"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="nitpicker">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides>
|
||||
<service name="Gui"/>
|
||||
<service name="Capture"/>
|
||||
<service name="Event"/>
|
||||
</provides>
|
||||
<config focus="rom" request_framebuffer="no" request_input="no">
|
||||
<capture/> <event/>
|
||||
<domain name="default" layer="2" content="client" label="no" hover="always"/>
|
||||
<default-policy domain="default"/>
|
||||
</config>
|
||||
<route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>}
|
||||
|
||||
append_if $use_interactively config {
|
||||
|
||||
<start name="terminal_service" caps="110">
|
||||
<binary name="terminal"/>
|
||||
<resource name="RAM" quantum="12M"/>
|
||||
<provides><service name="Terminal"/></provides>
|
||||
<route>
|
||||
<service name="ROM" label="config"> <parent label="terminal.config"/> </service>
|
||||
<service name="Gui"> <child name="nitpicker"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>}
|
||||
|
||||
append_if [expr !$use_interactively] config {
|
||||
<start name="terminal_service" caps="110">
|
||||
<binary name="log_terminal"/>
|
||||
<start name="log_terminal" caps="110">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides><service name="Terminal"/></provides>
|
||||
<route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>}
|
||||
</start>
|
||||
|
||||
append config {
|
||||
<start name="lx_fs" ld="no">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<provides> <service name="File_system"/> </provides>
|
||||
@ -127,15 +92,9 @@ append config {
|
||||
<config>
|
||||
<vfs>
|
||||
<ram/>
|
||||
<import>
|
||||
<rom name="encrypted_private_key"/>
|
||||
<rom name="superblock_hash"/>
|
||||
</import>
|
||||
|
||||
<dir name="dev">
|
||||
<jitterentropy/>
|
||||
<tresor_trust_anchor name="tresor_trust_anchor"
|
||||
storage_dir="/"/>
|
||||
<tresor_trust_anchor name="tresor_trust_anchor" storage_dir="/"/>
|
||||
</dir>
|
||||
</vfs>
|
||||
|
||||
@ -146,8 +105,7 @@ append config {
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="initialize_tresor" caps="3000">
|
||||
<binary name="sequence"/>
|
||||
<start name="sequence" caps="3000">
|
||||
<resource name="RAM" quantum="300M"/>
|
||||
<config>
|
||||
|
||||
@ -156,12 +114,37 @@ append config {
|
||||
<config passphrase="foobar" trust_anchor_dir="/trust_anchor">
|
||||
<vfs>
|
||||
<dir name="trust_anchor">
|
||||
<fs label="ta"/>
|
||||
<fs label="tresor_trust_anchor"/>
|
||||
</dir>
|
||||
</vfs>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="tresor_init">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config>
|
||||
|
||||
<block-io type="vfs" path="/} [tresor_image_name] {"/>
|
||||
<crypto path="/crypto"/>
|
||||
<trust-anchor path="/trust_anchor"/>
|
||||
|
||||
<vfs>
|
||||
<fs label="tresor_block_io" buffer_size="1M"/>
|
||||
<tresor_crypto_aes_cbc name="crypto"/>
|
||||
<dir name="trust_anchor">
|
||||
<fs label="tresor_trust_anchor"/>
|
||||
</dir>
|
||||
</vfs>
|
||||
|
||||
<virtual-block-device nr_of_levels="3" nr_of_children="64" nr_of_leafs="512" />
|
||||
<free-tree nr_of_levels="3" nr_of_children="64" nr_of_leafs="2048" />
|
||||
|
||||
</config>
|
||||
<route>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="init" caps="1600">
|
||||
<resource name="RAM" quantum="256M"/>
|
||||
<config verbose="yes">
|
||||
@ -188,12 +171,12 @@ append config {
|
||||
<provides><service name="File_system"/></provides>
|
||||
<config>
|
||||
<vfs>
|
||||
<fs buffer_size="1M" label="fs_backend"/>
|
||||
<fs buffer_size="1M" label="tresor_block_io"/>
|
||||
<tresor_crypto_aes_cbc name="tresor_crypto"/>
|
||||
<dir name="ta"> <fs buffer_size="1M" label="ta"/> </dir>
|
||||
<dir name="ta"> <fs buffer_size="1M" label="tresor_trust_anchor"/> </dir>
|
||||
<dir name="dev">
|
||||
<tresor name="tresor" debug="no" verbose="yes"
|
||||
block="/} [tresor_image_file] {"
|
||||
block="/} [tresor_image_name] {"
|
||||
crypto="/tresor_crypto"
|
||||
trust_anchor="/ta"/>
|
||||
</dir>
|
||||
@ -202,8 +185,6 @@ append config {
|
||||
<default-policy root="/dev" writeable="yes"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="File_system" label="fs_backend"> <parent label="fs"/> </service>
|
||||
<service name="File_system" label="ta"> <parent label="ta"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
@ -230,7 +211,7 @@ append config {
|
||||
<default-policy root="/" writeable="yes"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="Terminal"> <parent label="terminal_service"/> </service>
|
||||
<service name="Terminal"> <parent label="log_terminal"/> </service>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
@ -266,21 +247,23 @@ append config {
|
||||
<env key="PATH" value="/bin"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="File_system" label="shell"> <child name="vfs"/> </service>
|
||||
<service name="File_system" label="tresor"> <child name="vfs_tresor"/> </service>
|
||||
<service name="File_system" label="shell"> <child name="vfs"/> </service>
|
||||
<service name="File_system" label="tresor"> <child name="vfs_tresor"/> </service>
|
||||
<service name="ROM" label_suffix=".lib.so"> <parent/> </service>
|
||||
<service name="ROM" label_last="/bin/bash"> <child name="vfs_rom"/> </service>
|
||||
<service name="ROM" label_prefix="/bin"> <child name="vfs_rom"/> </service>
|
||||
<service name="ROM" label_prefix="/bin"> <child name="vfs_rom"/> </service>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
</config>
|
||||
</start>
|
||||
|
||||
</config>
|
||||
<route>
|
||||
<service name="Terminal"> <child name="terminal_service"/> </service>
|
||||
<service name="File_system" label_last="fs"> <child name="lx_fs"/> </service>
|
||||
<service name="File_system" label_last="ta"> <child name="vfs_tresor_trust_anchor"/> </service>
|
||||
<service name="Terminal"> <child name="log_terminal"/> </service>
|
||||
<service name="File_system" label_suffix="tresor_block_io"> <child name="lx_fs"/> </service>
|
||||
<service name="File_system" label_suffix="tresor_trust_anchor"> <child name="vfs_tresor_trust_anchor"/> </service>
|
||||
<service name="Timer"> <child name="timer"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
@ -294,19 +277,28 @@ set shell_script "run/vfs_tresor.sh"
|
||||
set repo "[repository_contains $shell_script]"
|
||||
exec cp $repo/$shell_script bin/
|
||||
|
||||
exec rm -rf [local_tresor_image]
|
||||
if { [get_cmd_switch --autopilot] } {
|
||||
|
||||
exec rm -rf [autopilot_tresor_image]
|
||||
catch { exec $dd if=/dev/urandom of=[autopilot_tresor_image] bs=1M count=[tresor_image_size_mb] }
|
||||
exec ln -sf -T [autopilot_tresor_image] [local_tresor_image]
|
||||
|
||||
} else {
|
||||
|
||||
catch { exec $dd if=/dev/urandom of=[local_tresor_image] bs=1M count=[tresor_image_size_mb] }
|
||||
}
|
||||
|
||||
set boot_modules [build_artifacts]
|
||||
|
||||
append boot_modules { vfs_tresor.sh encrypted_private_key superblock_hash }
|
||||
lappend boot_modules [tresor_image_file]
|
||||
|
||||
set fd [open [run_dir]/genode/focus w]
|
||||
puts $fd "<focus label=\"terminal_service -> \" domain=\"default\"/>"
|
||||
close $fd
|
||||
append boot_modules { vfs_tresor.sh }
|
||||
lappend boot_modules [tresor_image_name]
|
||||
|
||||
build_boot_image $boot_modules
|
||||
|
||||
if {$use_interactively} {
|
||||
run_genode_until forever
|
||||
} else {
|
||||
run_genode_until {.*--- Automated Tresor testing finished.*} 1800
|
||||
run_genode_until {.*"/bin/bash".* exited with exit value 0.*\n} 120
|
||||
|
||||
if { [get_cmd_switch --autopilot] } {
|
||||
|
||||
exec rm -rf [local_tresor_image]
|
||||
exec rm -rf [autopilot_tresor_image]
|
||||
}
|
||||
|
@ -55,33 +55,25 @@ test_read_compare_1() {
|
||||
fi
|
||||
}
|
||||
|
||||
test_create_snapshot() {
|
||||
test_deinitialize() {
|
||||
local tresor_dir="$1"
|
||||
|
||||
echo "Create snapshot"
|
||||
echo true > $tresor_dir/control/create_snapshot
|
||||
echo "Deinitialize"
|
||||
local state="$(< $tresor_dir/control/deinitialize)"
|
||||
echo true > $tresor_dir/control/deinitialize
|
||||
}
|
||||
|
||||
test_list_snapshots() {
|
||||
wait_for_deinitialize() {
|
||||
local tresor_dir="$1"
|
||||
|
||||
echo "List content of '$tresor_dir'"
|
||||
ls -l $tresor_dir/snapshots
|
||||
}
|
||||
|
||||
test_discard_snapshot() {
|
||||
local tresor_dir="$1"
|
||||
local snap_id=$2
|
||||
|
||||
echo "Discard snapshot with id: $snap_id"
|
||||
echo $snap_id > $tresor_dir/control/discard_snapshot
|
||||
echo "Wait for deinitialize"
|
||||
local state="$(< $tresor_dir/control/deinitialize)"
|
||||
}
|
||||
|
||||
test_rekey_start() {
|
||||
local tresor_dir="$1"
|
||||
|
||||
echo "Start rekeying"
|
||||
echo on > $tresor_dir/control/rekey
|
||||
local state="$(< $tresor_dir/control/rekey)"
|
||||
echo true > $tresor_dir/control/rekey
|
||||
echo "Reykeying started"
|
||||
}
|
||||
|
||||
@ -137,16 +129,14 @@ wait_for_rekeying() {
|
||||
echo "Wait for rekeying to finish..."
|
||||
while : ; do
|
||||
local done=0
|
||||
local file_content="$(< $tresor_dir/control/rekey_progress)"
|
||||
local file_content="$(< $tresor_dir/control/rekey)"
|
||||
# XXX remove later
|
||||
echo "file_content: ${file_content}"
|
||||
case "$file_content" in
|
||||
*at*)
|
||||
if [ "$verbose" = "yes" ]; then
|
||||
echo "Rekeying: $file_content"
|
||||
fi
|
||||
*failed*)
|
||||
done=1;
|
||||
;;
|
||||
*idle*)
|
||||
*succeeded*)
|
||||
done=1;
|
||||
;;
|
||||
esac
|
||||
@ -163,16 +153,14 @@ wait_for_vbd_extension() {
|
||||
echo "Wait for VBD extension to finish..."
|
||||
while : ; do
|
||||
local done=0
|
||||
local file_content="$(< $tresor_dir/control/extend_progress)"
|
||||
local file_content="$(< $tresor_dir/control/extend)"
|
||||
# XXX remove later
|
||||
echo "file_content: ${file_content}"
|
||||
case "$file_content" in
|
||||
*at*)
|
||||
if [ "$verbose" = "yes" ]; then
|
||||
echo "Extending VBD: $file_content"
|
||||
fi
|
||||
*failed*)
|
||||
done=1;
|
||||
;;
|
||||
*idle*)
|
||||
*succeeded*)
|
||||
done=1;
|
||||
;;
|
||||
esac
|
||||
@ -189,16 +177,14 @@ wait_for_ft_extension() {
|
||||
echo "Wait for FT extension to finish..."
|
||||
while : ; do
|
||||
local done=0
|
||||
local file_content="$(< $tresor_dir/control/extend_progress)"
|
||||
local file_content="$(< $tresor_dir/control/extend)"
|
||||
# XXX remove later
|
||||
echo "file_content: ${file_content}"
|
||||
case "$file_content" in
|
||||
*at*)
|
||||
if [ "$verbose" = "yes" ]; then
|
||||
echo "Extending FT: $file_content"
|
||||
fi
|
||||
*failed*)
|
||||
done=1;
|
||||
;;
|
||||
*idle*)
|
||||
*succeeded*)
|
||||
done=1;
|
||||
;;
|
||||
esac
|
||||
@ -212,95 +198,37 @@ wait_for_ft_extension() {
|
||||
main() {
|
||||
local tresor_dir="/dev/tresor"
|
||||
local data_file="$tresor_dir/current/data"
|
||||
|
||||
echo "list files..."
|
||||
ls -l $tresor_dir
|
||||
|
||||
for i in $(seq 3); do
|
||||
|
||||
echo "--> Run $i:"
|
||||
|
||||
test_read_seq_unaligned_512 "$data_file" "1048576"
|
||||
|
||||
local pattern_file="/tmp/pattern"
|
||||
produce_pattern "$i" "4096" > $pattern_file
|
||||
|
||||
test_write_1 "$data_file" "419"
|
||||
test_write_1 "$data_file" "63"
|
||||
test_write_1 "$data_file" "333"
|
||||
|
||||
test_vbd_extension "$tresor_dir" "1000"
|
||||
test_read_compare_1 "$data_file" "63"
|
||||
test_write_1 "$data_file" "175"
|
||||
test_read_compare_1 "$data_file" "419"
|
||||
test_write_1 "$data_file" "91"
|
||||
test_read_compare_1 "$data_file" "175"
|
||||
test_read_compare_1 "$data_file" "91"
|
||||
test_read_compare_1 "$data_file" "333"
|
||||
wait_for_vbd_extension "$tresor_dir"
|
||||
|
||||
test_write_1 "$data_file" "32"
|
||||
test_write_1 "$data_file" "77"
|
||||
test_write_1 "$data_file" "199"
|
||||
|
||||
#test_ft_extension "$tresor_dir" "1000"
|
||||
test_read_compare_1 "$data_file" "32"
|
||||
test_write_1 "$data_file" "211"
|
||||
test_read_compare_1 "$data_file" "77"
|
||||
test_write_1 "$data_file" "278"
|
||||
test_read_compare_1 "$data_file" "199"
|
||||
test_read_compare_1 "$data_file" "278"
|
||||
test_read_compare_1 "$data_file" "211"
|
||||
#wait_for_ft_extension "$tresor_dir"
|
||||
|
||||
test_write_1 "$data_file" "0"
|
||||
test_write_1 "$data_file" "8"
|
||||
test_write_1 "$data_file" "16"
|
||||
test_write_1 "$data_file" "490"
|
||||
test_write_1 "$data_file" "468"
|
||||
|
||||
test_read_compare_1 "$data_file" "0"
|
||||
test_read_compare_1 "$data_file" "8"
|
||||
test_read_compare_1 "$data_file" "16"
|
||||
test_read_compare_1 "$data_file" "490"
|
||||
|
||||
#test_rekey "$tresor_dir"
|
||||
|
||||
test_rekey_start "$tresor_dir"
|
||||
test_write_1 "$data_file" "0"
|
||||
test_rekey_state "$tresor_dir"
|
||||
test_read_compare_1 "$data_file" "490"
|
||||
test_rekey_state "$tresor_dir"
|
||||
test_write_1 "$data_file" "16"
|
||||
test_rekey_state "$tresor_dir"
|
||||
test_read_compare_1 "$data_file" "468"
|
||||
test_rekey_state "$tresor_dir"
|
||||
test_read_compare_1 "$data_file" "8"
|
||||
test_rekey_state "$tresor_dir"
|
||||
test_read_compare_1 "$data_file" "16"
|
||||
test_rekey_state "$tresor_dir"
|
||||
test_read_compare_1 "$data_file" "0"
|
||||
test_write_1 "$data_file" "300"
|
||||
test_write_1 "$data_file" "240"
|
||||
test_write_1 "$data_file" "201"
|
||||
test_write_1 "$data_file" "328"
|
||||
wait_for_rekeying "$tresor_dir" "yes"
|
||||
|
||||
echo "--> Run $i done"
|
||||
|
||||
done
|
||||
|
||||
echo "--> Read/Compare test"
|
||||
test_read_compare_1 "$data_file" "0"
|
||||
test_read_compare_1 "$data_file" "490"
|
||||
test_read_compare_1 "$data_file" "468"
|
||||
test_read_compare_1 "$data_file" "8"
|
||||
test_read_compare_1 "$data_file" "16"
|
||||
echo "--> Read/Compare test done"
|
||||
|
||||
echo "--- Automated Tresor testing finished, shell is yours ---"
|
||||
echo "produce pattern..."
|
||||
local pattern_file="/tmp/pattern"
|
||||
produce_pattern "1" "4096" > $pattern_file
|
||||
echo "write..."
|
||||
test_write_1 "$data_file" "20"
|
||||
echo "read..."
|
||||
test_read_compare_1 "$data_file" "20"
|
||||
test_write_1 "$data_file" "20"
|
||||
echo "extend VBD..."
|
||||
test_vbd_extension "$tresor_dir" "100"
|
||||
test_write_1 "$data_file" "2"
|
||||
test_read_compare_1 "$data_file" "2"
|
||||
wait_for_vbd_extension "$tresor_dir"
|
||||
echo "extend FT..."
|
||||
test_ft_extension "$tresor_dir" "100"
|
||||
test_write_1 "$data_file" "2"
|
||||
test_read_compare_1 "$data_file" "2"
|
||||
wait_for_ft_extension "$tresor_dir"
|
||||
echo "rekey..."
|
||||
test_rekey_start "$tresor_dir"
|
||||
test_write_1 "$data_file" "2"
|
||||
test_read_compare_1 "$data_file" "2"
|
||||
wait_for_rekeying "$tresor_dir" "no"
|
||||
test_deinitialize "$tresor_dir"
|
||||
wait_for_deinitialize "$tresor_dir"
|
||||
echo "done!"
|
||||
}
|
||||
|
||||
main "$@"
|
||||
|
||||
# just drop into shell
|
||||
# exit 0
|
||||
exit 0
|
||||
|
@ -1,153 +0,0 @@
|
||||
assert_spec linux
|
||||
|
||||
proc tresor_image_file { } {
|
||||
return "vfs_tresor_block.img"
|
||||
}
|
||||
|
||||
set image_size 32
|
||||
|
||||
proc tresor_image_size_mb { } {
|
||||
global image_size
|
||||
return $image_size
|
||||
}
|
||||
|
||||
build {
|
||||
core lib/ld init timer
|
||||
server/lx_block
|
||||
server/lx_fs
|
||||
server/vfs lib/vfs
|
||||
app/sequence
|
||||
|
||||
app/tresor_init_trust_anchor
|
||||
app/tresor_init
|
||||
lib/vfs_tresor_crypto_aes_cbc
|
||||
lib/vfs_tresor_trust_anchor
|
||||
lib/vfs_jitterentropy
|
||||
lib/libc
|
||||
lib/libcrypto
|
||||
}
|
||||
|
||||
create_boot_directory
|
||||
|
||||
append config {
|
||||
<config verbose="yes">
|
||||
<parent-provides>
|
||||
<service name="ROM"/>
|
||||
<service name="IRQ"/>
|
||||
<service name="IO_MEM"/>
|
||||
<service name="IO_PORT"/>
|
||||
<service name="PD"/>
|
||||
<service name="RM"/>
|
||||
<service name="CPU"/>
|
||||
<service name="LOG"/>
|
||||
</parent-provides>
|
||||
|
||||
<default-route>
|
||||
<any-service> <parent/> <any-child/> </any-service>
|
||||
</default-route>
|
||||
|
||||
<default caps="100"/>
|
||||
<start name="timer">
|
||||
<resource name="RAM" quantum="1M"/>
|
||||
<provides><service name="Timer"/></provides>
|
||||
</start>
|
||||
|
||||
<start name="lx_fs" ld="no">
|
||||
<resource name="RAM" quantum="2M"/>
|
||||
<provides> <service name="File_system"/> </provides>
|
||||
<config>
|
||||
<default-policy root="/" writeable="yes"/>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="vfs_trust_anchor" caps="120">
|
||||
<binary name="vfs"/>
|
||||
<resource name="RAM" quantum="16M"/>
|
||||
<provides><service name="File_system"/></provides>
|
||||
<config>
|
||||
<vfs>
|
||||
<dir name="ta_storage">
|
||||
<fs/>
|
||||
</dir>
|
||||
|
||||
<dir name="dev">
|
||||
<jitterentropy/>
|
||||
<tresor_trust_anchor name="tresor_trust_anchor"
|
||||
storage_dir="/ta_storage"/>
|
||||
</dir>
|
||||
</vfs>
|
||||
|
||||
<default-policy root="/dev/tresor_trust_anchor" writeable="yes"/>
|
||||
</config>
|
||||
<route>
|
||||
<service name="File_system"> <child name="lx_fs"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
|
||||
<start name="initialize_tresor" caps="200">
|
||||
<binary name="sequence"/>
|
||||
<resource name="RAM" quantum="128M"/>
|
||||
<config>
|
||||
|
||||
<start name="tresor_init_trust_anchor">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config passphrase="foobar" trust_anchor_dir="/trust_anchor">
|
||||
<vfs>
|
||||
<dir name="trust_anchor">
|
||||
<fs label="ta"/>
|
||||
</dir>
|
||||
</vfs>
|
||||
</config>
|
||||
</start>
|
||||
|
||||
<start name="tresor_init">
|
||||
<resource name="RAM" quantum="4M"/>
|
||||
<config>
|
||||
|
||||
<block-io type="vfs" path="/} [tresor_image_file] {"/>
|
||||
<crypto path="/crypto"/>
|
||||
<trust-anchor path="/trust_anchor"/>
|
||||
|
||||
<vfs>
|
||||
<fs buffer_size="1M"/>
|
||||
<tresor_crypto_aes_cbc name="crypto"/>
|
||||
<dir name="trust_anchor">
|
||||
<fs label="ta"/>
|
||||
</dir>
|
||||
</vfs>
|
||||
|
||||
<virtual-block-device
|
||||
nr_of_levels="3"
|
||||
nr_of_children="64"
|
||||
nr_of_leafs="512" />
|
||||
|
||||
<free-tree
|
||||
nr_of_levels="3"
|
||||
nr_of_children="64"
|
||||
nr_of_leafs="2048" />
|
||||
</config>
|
||||
</start>
|
||||
|
||||
</config>
|
||||
<route>
|
||||
<service name="File_system" label_last="ta">
|
||||
<child name="vfs_trust_anchor"/>
|
||||
</service>
|
||||
<service name="File_system"> <child name="lx_fs"/> </service>
|
||||
<any-service> <parent/> </any-service>
|
||||
</route>
|
||||
</start>
|
||||
</config>}
|
||||
|
||||
install_config $config
|
||||
|
||||
exec rm -rf bin/[tresor_image_file]
|
||||
exec truncate -s [tresor_image_size_mb]M bin/[tresor_image_file]
|
||||
|
||||
build_boot_image [list {*}[build_artifacts] [tresor_image_file]]
|
||||
|
||||
run_genode_until {.*child "initialize_tresor" exited with exit value 0.*\n} 240
|
||||
|
||||
exec cp [run_dir]/genode/encrypted_private_key bin
|
||||
exec cp [run_dir]/genode/superblock_hash bin
|
@ -641,8 +641,28 @@ class File_vault::Main
|
||||
size_t nr_of_ft_children,
|
||||
size_t nr_of_ft_leafs);
|
||||
|
||||
static bool tresor_control_file_yields_state_idle(Xml_node const &fs_query_listing,
|
||||
char const *file_name);
|
||||
template <size_t N>
|
||||
static bool listing_file_starts_with(Xml_node const &fs_query_listing,
|
||||
char const *file_name,
|
||||
String<N> const &str)
|
||||
{
|
||||
bool result { false };
|
||||
bool done { false };
|
||||
fs_query_listing.with_optional_sub_node("dir", [&] (Xml_node const &node_0) {
|
||||
node_0.for_each_sub_node("file", [&] (Xml_node const &node_1) {
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
if (node_1.attribute_value("name", String<16>()) == file_name) {
|
||||
node_1.with_raw_content([&] (char const *base, size_t size) {
|
||||
result = String<N> { Cstring {base, size} } == str;
|
||||
done = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/***************************************************
|
||||
@ -699,28 +719,6 @@ void Main::_handle_ui_config()
|
||||
}
|
||||
|
||||
|
||||
bool Main::tresor_control_file_yields_state_idle(Xml_node const &fs_query_listing,
|
||||
char const *file_name)
|
||||
{
|
||||
bool result { false };
|
||||
bool done { false };
|
||||
fs_query_listing.with_optional_sub_node("dir", [&] (Xml_node const &node_0) {
|
||||
node_0.for_each_sub_node("file", [&] (Xml_node const &node_1) {
|
||||
if (done) {
|
||||
return;
|
||||
}
|
||||
if (node_1.attribute_value("name", String<16>()) == file_name) {
|
||||
node_1.with_raw_content([&] (char const *base, size_t size) {
|
||||
result = String<5> { Cstring {base, size} } == "idle";
|
||||
done = true;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void Main::_update_sandbox_config()
|
||||
{
|
||||
Buffered_xml const config { _heap, "config", [&] (Xml_generator &xml) {
|
||||
@ -940,16 +938,20 @@ void Main::_handle_resizing_fs_query_listing(Xml_node const &node)
|
||||
switch (_resizing_state) {
|
||||
case Resizing_state::WAIT_TILL_DEVICE_IS_READY:
|
||||
|
||||
if (tresor_control_file_yields_state_idle(node, "extend_progress")) {
|
||||
if (listing_file_starts_with(node, "extend", String<10>("succeeded")) ||
|
||||
listing_file_starts_with(node, "extend", String<5>("none"))) {
|
||||
|
||||
_resizing_state = Resizing_state::ISSUE_REQUEST_AT_DEVICE;
|
||||
Signal_transmitter(_state_handler).submit();
|
||||
}
|
||||
|
||||
} else
|
||||
error("failed to extend: tresor not ready");
|
||||
|
||||
break;
|
||||
|
||||
case Resizing_state::IN_PROGRESS_AT_DEVICE:
|
||||
|
||||
if (tresor_control_file_yields_state_idle(node, "extend_progress")) {
|
||||
if (listing_file_starts_with(node, "extend", String<10>("succeeded"))) {
|
||||
|
||||
switch (_resizing_type) {
|
||||
case Resizing_type::EXPAND_CLIENT_FS:
|
||||
@ -972,7 +974,10 @@ void Main::_handle_resizing_fs_query_listing(Xml_node const &node)
|
||||
}
|
||||
_resizing_state = Resizing_state::DETERMINE_CLIENT_FS_SIZE;
|
||||
Signal_transmitter(_state_handler).submit();
|
||||
}
|
||||
|
||||
} else
|
||||
error("failed to extend: operation failed at tresor");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -992,13 +997,16 @@ void Main::_handle_lock_fs_query_listing(Xml_node const &node)
|
||||
switch (_state) {
|
||||
case State::LOCK_WAIT_TILL_DEINIT_REQUEST_IS_DONE:
|
||||
|
||||
if (tresor_control_file_yields_state_idle(node, "deinitialize")) {
|
||||
if (listing_file_starts_with(node, "deinitialize", String<10>("succeeded"))) {
|
||||
|
||||
_set_state(State::UNLOCK_OBTAIN_PARAMETERS);
|
||||
_setup_obtain_params_passphrase = Input_passphrase { };
|
||||
_setup_obtain_params_select = Setup_obtain_params_select::PASSPHRASE_INPUT;
|
||||
Signal_transmitter(_state_handler).submit();
|
||||
}
|
||||
|
||||
} else
|
||||
error("failed to deinitialize: operation failed at tresor");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1024,20 +1032,27 @@ void Main::_handle_rekeying_fs_query_listing(Xml_node const &node)
|
||||
switch (_rekeying_state) {
|
||||
case Rekeying_state::WAIT_TILL_DEVICE_IS_READY:
|
||||
|
||||
if (tresor_control_file_yields_state_idle(node, "rekey_progress")) {
|
||||
if (listing_file_starts_with(node, "rekey", String<10>("succeeded")) ||
|
||||
listing_file_starts_with(node, "rekey", String<5>("none"))) {
|
||||
|
||||
_rekeying_state = Rekeying_state::ISSUE_REQUEST_AT_DEVICE;
|
||||
Signal_transmitter(_state_handler).submit();
|
||||
}
|
||||
|
||||
} else
|
||||
error("failed to rekey: tresor not ready");
|
||||
|
||||
break;
|
||||
|
||||
case Rekeying_state::IN_PROGRESS_AT_DEVICE:
|
||||
|
||||
if (tresor_control_file_yields_state_idle(node, "rekey_progress")) {
|
||||
if (listing_file_starts_with(node, "rekey", String<10>("succeeded"))) {
|
||||
|
||||
_rekeying_state = Rekeying_state::INACTIVE;
|
||||
Signal_transmitter(_state_handler).submit();
|
||||
}
|
||||
|
||||
} else
|
||||
error("failed to rekey: operation failed at tresor");
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -1465,10 +1480,8 @@ void File_vault::Main::handle_sandbox_state()
|
||||
update_dialog = true;
|
||||
update_sandbox = true;
|
||||
|
||||
} else {
|
||||
|
||||
} else
|
||||
_unlock_retry_delay.schedule(Microseconds { 3000000 });
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
|
@ -299,7 +299,6 @@ namespace File_vault {
|
||||
xml.node("tresor", [&] () {
|
||||
xml.attribute("name", "tresor");
|
||||
xml.attribute("verbose", "no");
|
||||
xml.attribute("debug", "no");
|
||||
xml.attribute("block", File_path { "/", tresor_img_file_name });
|
||||
xml.attribute("crypto", "/crypto");
|
||||
xml.attribute("trust_anchor", "/trust_anchor");
|
||||
@ -531,7 +530,7 @@ namespace File_vault {
|
||||
}
|
||||
|
||||
void gen_tresor_vfs_block_start_node(Xml_generator &xml,
|
||||
Child_state const &child)
|
||||
Child_state const &child)
|
||||
{
|
||||
child.gen_start_node(xml, [&] () {
|
||||
|
||||
|
@ -31,76 +31,44 @@ using namespace Tresor;
|
||||
|
||||
namespace Tresor_check { class Main; }
|
||||
|
||||
class Tresor_check::Main : private Vfs::Env::User, private Tresor::Module_composition, public Tresor::Module, public Module_channel
|
||||
class Tresor_check::Main : private Vfs::Env::User
|
||||
{
|
||||
private:
|
||||
|
||||
enum State { INIT, REQ_GENERATED, CHECK_SBS_SUCCEEDED };
|
||||
enum State { INIT, CHECK_SB, CHECK_SB_SUCCEEDED };
|
||||
|
||||
Env &_env;
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
Attached_rom_dataspace _config_rom { _env, "config" };
|
||||
Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this };
|
||||
Signal_handler<Main> _sigh { _env.ep(), *this, &Main::_handle_signal };
|
||||
Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") };
|
||||
Crypto _crypto { _vfs_env, _config_rom.xml().sub_node("crypto") };
|
||||
Block_io _block_io { _vfs_env, _config_rom.xml().sub_node("block-io") };
|
||||
Tresor::Path const _block_io_path { _config_rom.xml().sub_node("block-io").attribute_value("path", Tresor::Path()) };
|
||||
Vfs::Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, Vfs::Directory_service::OPEN_MODE_RDWR) };
|
||||
Block_io _block_io { _block_io_file };
|
||||
Vbd_check _vbd_check { };
|
||||
Ft_check _ft_check { };
|
||||
Sb_check _sb_check { };
|
||||
bool _generated_req_success { };
|
||||
State _state { INIT };
|
||||
|
||||
NONCOPYABLE(Main);
|
||||
|
||||
void _generated_req_completed(State_uint state_uint) override
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("command pool: request failed because generated request failed)");
|
||||
_env.parent().exit(-1);
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
void wakeup_vfs_user() override { _sigh.local_submit(); }
|
||||
Sb_check::Check _check_superblocks { };
|
||||
|
||||
void _wakeup_back_end_services() { _vfs_env.io().commit(); }
|
||||
|
||||
void _handle_signal()
|
||||
{
|
||||
execute_modules();
|
||||
while(_sb_check.execute(_check_superblocks, _vbd_check, _ft_check, _block_io));
|
||||
if (_check_superblocks.complete())
|
||||
_env.parent().exit(_check_superblocks.success() ? 0 : -1);
|
||||
_wakeup_back_end_services();
|
||||
}
|
||||
|
||||
/********************
|
||||
** Vfs::Env::User **
|
||||
********************/
|
||||
|
||||
void wakeup_vfs_user() override { _sigh.local_submit(); }
|
||||
|
||||
public:
|
||||
|
||||
Main(Env &env) : Module_channel { COMMAND_POOL, 0 }, _env { env }
|
||||
{
|
||||
add_module(COMMAND_POOL, *this);
|
||||
add_module(CRYPTO, _crypto);
|
||||
add_module(TRUST_ANCHOR, _trust_anchor);
|
||||
add_module(BLOCK_IO, _block_io);
|
||||
add_module(VBD_CHECK, _vbd_check);
|
||||
add_module(FT_CHECK, _ft_check);
|
||||
add_module(SB_CHECK, _sb_check);
|
||||
add_channel(*this);
|
||||
_handle_signal();
|
||||
}
|
||||
|
||||
void execute(bool &progress) override
|
||||
{
|
||||
switch(_state) {
|
||||
case INIT:
|
||||
|
||||
generate_req<Sb_check_request>(CHECK_SBS_SUCCEEDED, progress, _generated_req_success);
|
||||
_state = REQ_GENERATED;
|
||||
break;
|
||||
|
||||
case CHECK_SBS_SUCCEEDED: _env.parent().exit(0); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
Main(Env &env) : _env(env) { _handle_signal(); }
|
||||
};
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Tresor_check::Main main { env }; }
|
||||
|
@ -34,86 +34,116 @@ using namespace Tresor;
|
||||
|
||||
namespace Tresor_init { class Main; }
|
||||
|
||||
class Tresor_init::Main : private Vfs::Env::User, private Tresor::Module_composition, public Tresor::Module, public Module_channel
|
||||
class Tresor_init::Main : private Vfs::Env::User, private Crypto_key_files_interface
|
||||
{
|
||||
private:
|
||||
|
||||
enum State { INIT, REQ_GENERATED, INIT_SBS_SUCCEEDED };
|
||||
struct Crypto_key
|
||||
{
|
||||
Key_id const key_id;
|
||||
Vfs::Vfs_handle &encrypt_file;
|
||||
Vfs::Vfs_handle &decrypt_file;
|
||||
};
|
||||
|
||||
Env &_env;
|
||||
Heap _heap { _env.ram(), _env.rm() };
|
||||
Attached_rom_dataspace _config_rom { _env, "config" };
|
||||
Vfs::Simple_env _vfs_env { _env, _heap, _config_rom.xml().sub_node("vfs"), *this };
|
||||
Signal_handler<Main> _sigh { _env.ep(), *this, &Main::_handle_signal };
|
||||
Constructible<Configuration> _cfg { };
|
||||
Trust_anchor _trust_anchor { _vfs_env, _config_rom.xml().sub_node("trust-anchor") };
|
||||
Crypto _crypto { _vfs_env, _config_rom.xml().sub_node("crypto") };
|
||||
Block_io _block_io { _vfs_env, _config_rom.xml().sub_node("block-io") };
|
||||
Configuration _cfg { _config_rom.xml() };
|
||||
Tresor::Path const _crypto_path { _config_rom.xml().sub_node("crypto").attribute_value("path", Tresor::Path()) };
|
||||
Tresor::Path const _block_io_path { _config_rom.xml().sub_node("block-io").attribute_value("path", Tresor::Path()) };
|
||||
Tresor::Path const _trust_anchor_path { _config_rom.xml().sub_node("trust-anchor").attribute_value("path", Tresor::Path()) };
|
||||
Vfs::Vfs_handle &_block_io_file { open_file(_vfs_env, _block_io_path, Vfs::Directory_service::OPEN_MODE_RDWR) };
|
||||
Vfs::Vfs_handle &_crypto_add_key_file { open_file(_vfs_env, { _crypto_path, "/add_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) };
|
||||
Vfs::Vfs_handle &_crypto_remove_key_file { open_file(_vfs_env, { _crypto_path, "/remove_key" }, Vfs::Directory_service::OPEN_MODE_WRONLY) };
|
||||
Vfs::Vfs_handle &_ta_decrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
|
||||
Vfs::Vfs_handle &_ta_encrypt_file { open_file(_vfs_env, { _trust_anchor_path, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
|
||||
Vfs::Vfs_handle &_ta_generate_key_file { open_file(_vfs_env, { _trust_anchor_path, "/generate_key" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
|
||||
Vfs::Vfs_handle &_ta_initialize_file { open_file(_vfs_env, { _trust_anchor_path, "/initialize" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
|
||||
Vfs::Vfs_handle &_ta_hash_file { open_file(_vfs_env, { _trust_anchor_path, "/hash" }, Vfs::Directory_service::OPEN_MODE_RDWR) };
|
||||
Trust_anchor _trust_anchor { { _ta_decrypt_file, _ta_encrypt_file, _ta_generate_key_file, _ta_initialize_file, _ta_hash_file } };
|
||||
Crypto _crypto { {*this, _crypto_add_key_file, _crypto_remove_key_file} };
|
||||
Block_io _block_io { _block_io_file };
|
||||
Constructible<Crypto_key> _crypto_keys[2] { };
|
||||
Pba_allocator _pba_alloc { NR_OF_SUPERBLOCK_SLOTS };
|
||||
Vbd_initializer _vbd_initializer { };
|
||||
Ft_initializer _ft_initializer { };
|
||||
Sb_initializer _sb_initializer { };
|
||||
bool _generated_req_success { };
|
||||
State _state { INIT };
|
||||
Sb_initializer::Initialize _init_superblocks {{
|
||||
Tree_configuration {
|
||||
(Tree_level_index)(_cfg.vbd_nr_of_lvls() - 1),
|
||||
(Tree_degree)_cfg.vbd_nr_of_children(),
|
||||
_cfg.vbd_nr_of_leafs()
|
||||
},
|
||||
Tree_configuration {
|
||||
(Tree_level_index)_cfg.ft_nr_of_lvls() - 1,
|
||||
(Tree_degree)_cfg.ft_nr_of_children(),
|
||||
_cfg.ft_nr_of_leafs()
|
||||
},
|
||||
Tree_configuration {
|
||||
(Tree_level_index)_cfg.ft_nr_of_lvls() - 1,
|
||||
(Tree_degree)_cfg.ft_nr_of_children(),
|
||||
_cfg.ft_nr_of_leafs()
|
||||
},
|
||||
_pba_alloc
|
||||
}};
|
||||
|
||||
NONCOPYABLE(Main);
|
||||
|
||||
void _generated_req_completed(State_uint state_uint) override
|
||||
Constructible<Crypto_key> &_crypto_key(Key_id key_id)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("command pool: request failed because generated request failed)");
|
||||
_env.parent().exit(-1);
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
for (Constructible<Crypto_key> &key : _crypto_keys)
|
||||
if (key.constructed() && key->key_id == key_id)
|
||||
return key;
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
void wakeup_vfs_user() override { _sigh.local_submit(); }
|
||||
|
||||
void _wakeup_back_end_services() { _vfs_env.io().commit(); }
|
||||
|
||||
void _handle_signal()
|
||||
{
|
||||
execute_modules();
|
||||
while(_sb_initializer.execute(_init_superblocks, _block_io, _trust_anchor, _vbd_initializer, _ft_initializer));
|
||||
if (_init_superblocks.complete())
|
||||
_env.parent().exit(_init_superblocks.success() ? 0 : -1);
|
||||
_wakeup_back_end_services();
|
||||
}
|
||||
|
||||
/********************************
|
||||
** Crypto_key_files_interface **
|
||||
********************************/
|
||||
|
||||
void add_crypto_key(Key_id key_id) override
|
||||
{
|
||||
for (Constructible<Crypto_key> &key : _crypto_keys)
|
||||
if (!key.constructed()) {
|
||||
key.construct(key_id,
|
||||
open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/encrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR),
|
||||
open_file(_vfs_env, { _crypto_path, "/keys/", key_id, "/decrypt" }, Vfs::Directory_service::OPEN_MODE_RDWR)
|
||||
);
|
||||
return;
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
void remove_crypto_key(Key_id key_id) override
|
||||
{
|
||||
Constructible<Crypto_key> &crypto_key = _crypto_key(key_id);
|
||||
_vfs_env.root_dir().close(&crypto_key->encrypt_file);
|
||||
_vfs_env.root_dir().close(&crypto_key->decrypt_file);
|
||||
crypto_key.destruct();
|
||||
}
|
||||
|
||||
Vfs::Vfs_handle &encrypt_file(Key_id key_id) override { return _crypto_key(key_id)->encrypt_file; }
|
||||
Vfs::Vfs_handle &decrypt_file(Key_id key_id) override { return _crypto_key(key_id)->decrypt_file; }
|
||||
|
||||
/********************
|
||||
** Vfs::Env::User **
|
||||
********************/
|
||||
|
||||
void wakeup_vfs_user() override { _sigh.local_submit(); }
|
||||
|
||||
public:
|
||||
|
||||
Main(Env &env) : Module_channel { COMMAND_POOL, 0 }, _env { env }
|
||||
{
|
||||
add_module(COMMAND_POOL, *this);
|
||||
add_module(CRYPTO, _crypto);
|
||||
add_module(TRUST_ANCHOR, _trust_anchor);
|
||||
add_module(BLOCK_IO, _block_io);
|
||||
add_module(VBD_INITIALIZER, _vbd_initializer);
|
||||
add_module(FT_INITIALIZER, _ft_initializer);
|
||||
add_module(SB_INITIALIZER, _sb_initializer);
|
||||
add_channel(*this);
|
||||
_cfg.construct(_config_rom.xml());
|
||||
_handle_signal();
|
||||
}
|
||||
|
||||
void execute(bool &progress) override
|
||||
{
|
||||
switch(_state) {
|
||||
case INIT:
|
||||
|
||||
generate_req<Sb_initializer_request>(
|
||||
INIT_SBS_SUCCEEDED, progress, (Tree_level_index)_cfg->vbd_nr_of_lvls() - 1,
|
||||
(Tree_degree)_cfg->vbd_nr_of_children(), _cfg->vbd_nr_of_leafs(),
|
||||
(Tree_level_index)_cfg->ft_nr_of_lvls() - 1,
|
||||
(Tree_degree)_cfg->ft_nr_of_children(), _cfg->ft_nr_of_leafs(),
|
||||
(Tree_level_index)_cfg->ft_nr_of_lvls() - 1,
|
||||
(Tree_degree)_cfg->ft_nr_of_children(), _cfg->ft_nr_of_leafs(), _pba_alloc,
|
||||
_generated_req_success);
|
||||
_state = REQ_GENERATED;
|
||||
break;
|
||||
|
||||
case INIT_SBS_SUCCEEDED: _env.parent().exit(0); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
Main(Env &env) : _env(env) { _handle_signal(); }
|
||||
};
|
||||
|
||||
void Component::construct(Genode::Env &env) { static Tresor_init::Main main { env }; }
|
||||
|
@ -89,9 +89,8 @@ class Main : Vfs::Env::User
|
||||
char const *name,
|
||||
Vfs::File_system &vfs,
|
||||
Genode::Allocator &alloc)
|
||||
:
|
||||
_vfs { vfs },
|
||||
_vfs_handle { nullptr }
|
||||
:
|
||||
_vfs(vfs), _vfs_handle(nullptr)
|
||||
{
|
||||
using Result = Vfs::Directory_service::Open_result;
|
||||
|
||||
@ -207,9 +206,7 @@ class Main : Vfs::Env::User
|
||||
|
||||
public:
|
||||
|
||||
Main(Env &env)
|
||||
:
|
||||
_env { env }
|
||||
Main(Env &env) : _env(env)
|
||||
{
|
||||
Xml_node const &config { _config_rom.xml() };
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -12,199 +12,79 @@
|
||||
*/
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/crypto.h>
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/hash.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Block_io_request::Block_io_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type,
|
||||
Request_offset client_req_offset, Request_tag client_req_tag, Key_id key_id,
|
||||
Physical_block_address pba, Virtual_block_address vba, Block &blk, Hash &hash,
|
||||
bool &success)
|
||||
:
|
||||
Module_request { src_module_id, src_chan_id, BLOCK_IO }, _type { type },
|
||||
_client_req_offset { client_req_offset }, _client_req_tag { client_req_tag },
|
||||
_key_id { key_id }, _pba { pba }, _vba { vba }, _blk { blk }, _hash { hash }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
char const *Block_io_request::type_to_string(Type type)
|
||||
bool Block_io::Sync::execute(Vfs::Vfs_handle &file)
|
||||
{
|
||||
switch (type) {
|
||||
case READ: return "read";
|
||||
case WRITE: return "write";
|
||||
case SYNC: return "sync";
|
||||
case READ_CLIENT_DATA: return "read_client_data";
|
||||
case WRITE_CLIENT_DATA: return "write_client_data";
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_file.construct(_helper.state, file);
|
||||
_helper.state = SYNC;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
void Block_io_channel::_generated_req_completed(State_uint state_uint)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("block io: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
void Block_io_channel::_mark_req_failed(bool &progress, Error_string str)
|
||||
{
|
||||
error("request failed: failed to ", str);
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Block_io_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
req._success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == req._pba)) {
|
||||
switch (req._type) {
|
||||
case Request::READ:
|
||||
case Request::WRITE:
|
||||
log("block_io: ", req.type_to_string(req._type), " pba ", req._pba, " hash ", hash(req._blk));
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Block_io_channel::_read(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _file.read(READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); break;
|
||||
case READ_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
case SYNC: _file->sync(SYNC_OK, FILE_ERR, progress); break;
|
||||
case SYNC_OK: _helper.mark_succeeded(progress); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void Block_io_channel::_read_client_data(bool &progress)
|
||||
bool Block_io::Read::execute(Vfs::Vfs_handle &file)
|
||||
{
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _file.read(READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); break;
|
||||
_file.construct(_helper.state, file);
|
||||
_helper.state = READ;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case READ: _file->read(READ_OK, FILE_ERR, _attr.in_pba * BLOCK_SIZE, { (char *)&_attr.out_block, BLOCK_SIZE }, progress); break;
|
||||
case READ_OK:
|
||||
|
||||
calc_hash(_blk, req._hash);
|
||||
_generate_req<Crypto_request>(
|
||||
PLAINTEXT_BLK_SUPPLIED, progress, Crypto_request::DECRYPT_CLIENT_DATA, req._client_req_offset,
|
||||
req._client_req_tag, req._key_id, *(Key_value *)0, req._pba, req._vba, _blk);
|
||||
return;
|
||||
|
||||
case PLAINTEXT_BLK_SUPPLIED: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Block_io_channel::_write_client_data(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
_generate_req<Crypto_request>(
|
||||
CIPHERTEXT_BLK_OBTAINED, progress, Crypto_request::ENCRYPT_CLIENT_DATA, req._client_req_offset,
|
||||
req._client_req_tag, req._key_id, *(Key_value *)0, req._pba, req._vba, _blk);
|
||||
_helper.mark_succeeded(progress);
|
||||
if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == _attr.in_pba))
|
||||
log("block_io: ", *this, " hash ", hash(_attr.out_block));
|
||||
break;
|
||||
|
||||
case CIPHERTEXT_BLK_OBTAINED:
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
calc_hash(_blk, req._hash);
|
||||
_file.write(WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress); break;
|
||||
|
||||
bool Block_io::Write::execute(Vfs::Vfs_handle &file)
|
||||
{
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_file.construct(_helper.state, file);
|
||||
_helper.state = WRITE;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case WRITE_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
case WRITE: _file->write(WRITE_OK, FILE_ERR, _attr.in_pba * BLOCK_SIZE, { (char *)&_attr.in_block, BLOCK_SIZE }, progress); break;
|
||||
case WRITE_OK:
|
||||
|
||||
_helper.mark_succeeded(progress);
|
||||
if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == _attr.in_pba))
|
||||
log("block_io: ", *this, " hash ", hash(_attr.in_block));
|
||||
break;
|
||||
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Block_io_channel::_write(bool &progress)
|
||||
{
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _file.write(WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress); break;
|
||||
case WRITE_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Block_io_channel::_sync(bool &progress)
|
||||
{
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _file.sync(SYNC_OK, FILE_ERR, progress); break;
|
||||
case SYNC_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Block_io_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
switch (_req_ptr->_type) {
|
||||
case Request::READ: _read(progress); break;
|
||||
case Request::WRITE: _write(progress); break;
|
||||
case Request::SYNC: _sync(progress); break;
|
||||
case Request::READ_CLIENT_DATA: _read_client_data(progress); break;
|
||||
case Request::WRITE_CLIENT_DATA: _write_client_data(progress); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Block_io::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
}
|
||||
|
||||
|
||||
void Block_io_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
Block_io_channel::Block_io_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node)
|
||||
:
|
||||
Module_channel { BLOCK_IO, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) }
|
||||
{ }
|
||||
|
||||
|
||||
Block_io::Block_io(Vfs::Env &vfs_env, Xml_node const &xml_node)
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++, vfs_env, xml_node);
|
||||
add_channel(*chan);
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
@ -13,317 +13,101 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/crypto.h>
|
||||
#include <tresor/client_data.h>
|
||||
#include <tresor/hash.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Crypto_request::Crypto_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type,
|
||||
Request_offset client_req_offset, Request_tag client_req_tag, Key_id key_id,
|
||||
Key_value const &key_plaintext, Physical_block_address pba, Virtual_block_address vba,
|
||||
Block &blk, bool &success)
|
||||
:
|
||||
Module_request { src_module_id, src_chan_id, CRYPTO }, _type { type }, _client_req_offset { client_req_offset },
|
||||
_client_req_tag { client_req_tag }, _pba { pba }, _vba { vba }, _key_id { key_id }, _key_plaintext { key_plaintext },
|
||||
_blk { blk }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
void Crypto_request::print(Output &out) const
|
||||
bool Crypto::Add_key::execute(Crypto::Attr const &crypto_attr)
|
||||
{
|
||||
Genode::print(out, type_to_string(_type));
|
||||
switch (_type) {
|
||||
case ADD_KEY:
|
||||
case REMOVE_KEY: Genode::print(out, " ", _key_id); break;
|
||||
case DECRYPT:
|
||||
case ENCRYPT:
|
||||
case DECRYPT_CLIENT_DATA:
|
||||
case ENCRYPT_CLIENT_DATA: Genode::print(out, " pba ", _pba); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
bool progress { false };
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
|
||||
char const *Crypto_request::type_to_string(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case ADD_KEY: return "add_key";
|
||||
case REMOVE_KEY: return "remove_key";
|
||||
case ENCRYPT_CLIENT_DATA: return "encrypt_client_data";
|
||||
case DECRYPT_CLIENT_DATA: return "decrypt_client_data";
|
||||
case ENCRYPT: return "encrypt";
|
||||
case DECRYPT: return "decrypt";
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_generated_req_completed(State_uint state_uint)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("crypto: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
Constructible<Crypto_channel::Key_directory> &Crypto_channel::_key_dir(Key_id key_id)
|
||||
{
|
||||
for (Constructible<Key_directory> &key_dir : _key_dirs)
|
||||
if (key_dir.constructed() && key_dir->key_id == key_id)
|
||||
return key_dir;
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_mark_req_failed(bool &progress, char const *str)
|
||||
{
|
||||
error("crypto: request (", *_req_ptr, ") failed at step \"", str, "\"");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
req._success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
if (VERBOSE_WRITE_VBA && req._type == Request::ENCRYPT_CLIENT_DATA)
|
||||
log(" encrypt leaf data: plaintext ", _blk, " hash ", hash(_blk),
|
||||
"\n update branch:\n ", Branch_lvl_prefix("leaf data: "), req._blk);
|
||||
|
||||
if (VERBOSE_READ_VBA && req._type == Request::DECRYPT_CLIENT_DATA)
|
||||
log(" ", Branch_lvl_prefix("leaf data: "), req._blk,
|
||||
"\n decrypt leaf data: plaintext ", _blk, " hash ", hash(_blk));
|
||||
|
||||
if (VERBOSE_CRYPTO) {
|
||||
switch (req._type) {
|
||||
case Request::DECRYPT_CLIENT_DATA:
|
||||
case Request::ENCRYPT_CLIENT_DATA:
|
||||
log("crypto: ", req.type_to_string(req._type), " pba ", req._pba, " vba ", req._vba,
|
||||
" plain ", _blk, " cipher ", req._blk);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
if (VERBOSE_BLOCK_IO && (!VERBOSE_BLOCK_IO_PBA_FILTER || VERBOSE_BLOCK_IO_PBA == req._pba)) {
|
||||
switch (req._type) {
|
||||
case Request::DECRYPT_CLIENT_DATA:
|
||||
log("block_io: read pba ", req._pba, " hash ", hash(req._blk), " (plaintext hash ", hash(_blk), ")");
|
||||
break;
|
||||
case Request::ENCRYPT_CLIENT_DATA:
|
||||
log("block_io: write pba ", req._pba, " hash ", hash(req._blk), " (plaintext hash ", hash(_blk), ")");
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_add_key(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
memcpy(_add_key_buf, &req._key_id, sizeof(Key_id));
|
||||
memcpy(_add_key_buf + sizeof(Key_id), &req._key_plaintext, KEY_SIZE);
|
||||
_add_key_file.write(WRITE_OK, FILE_ERR, 0, { _add_key_buf, sizeof(_add_key_buf) }, progress);
|
||||
_file.construct(_helper.state, crypto_attr.add_key_file);
|
||||
memcpy(_write_buf, &_attr.in_key.id, sizeof(Key_id));
|
||||
memcpy(_write_buf + sizeof(Key_id), &_attr.in_key.value, sizeof(Key_value));
|
||||
_helper.state = WRITE;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case WRITE_OK:
|
||||
{
|
||||
Constructible<Key_directory> *key_dir_ptr { nullptr };
|
||||
for (Constructible<Key_directory> &key_dir : _key_dirs)
|
||||
if (!key_dir.constructed())
|
||||
key_dir_ptr = &key_dir;
|
||||
if (!key_dir_ptr) {
|
||||
_mark_req_failed(progress, "find unused key dir");
|
||||
break;
|
||||
}
|
||||
key_dir_ptr->construct(*this, req._key_id);
|
||||
_mark_req_successful(progress);
|
||||
break;
|
||||
}
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_remove_key(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _remove_key_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._key_id, sizeof(Key_id) }, progress); break;
|
||||
case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { _write_buf, sizeof(_write_buf) }, progress); break;
|
||||
case WRITE_OK:
|
||||
|
||||
_key_dir(req._key_id).destruct();
|
||||
_mark_req_successful(progress);
|
||||
crypto_attr.key_files.add_crypto_key(_attr.in_key.id);
|
||||
_helper.mark_succeeded(progress);
|
||||
break;
|
||||
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_encrypt_client_data(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
_generate_req<Client_data_request>(
|
||||
PLAINTEXT_BLK_OBTAINED, progress, Client_data_request::OBTAIN_PLAINTEXT_BLK,
|
||||
req._client_req_offset, req._client_req_tag, req._pba, req._vba, _blk);;
|
||||
break;
|
||||
|
||||
case PLAINTEXT_BLK_OBTAINED:
|
||||
|
||||
_key_dir(req._key_id)->encrypt_file.write(
|
||||
WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress);
|
||||
break;
|
||||
|
||||
case WRITE_OK:
|
||||
|
||||
_key_dir(req._key_id)->encrypt_file.read(
|
||||
READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress);
|
||||
break;
|
||||
|
||||
case READ_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation"); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_encrypt(bool &progress)
|
||||
bool Crypto::Remove_key::execute(Crypto::Attr const &crypto_attr)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
bool progress { false };
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_key_dir(req._key_id)->encrypt_file.write(
|
||||
WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress);
|
||||
_file.construct(_helper.state, crypto_attr.remove_key_file);
|
||||
_helper.state = WRITE;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_key_id, sizeof(Key_id) }, progress); break;
|
||||
case WRITE_OK:
|
||||
|
||||
_key_dir(req._key_id)->encrypt_file.read(
|
||||
READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress);
|
||||
crypto_attr.key_files.remove_crypto_key(_attr.in_key_id);
|
||||
_helper.mark_succeeded(progress);
|
||||
break;
|
||||
|
||||
case READ_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation"); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_decrypt(bool &progress)
|
||||
bool Crypto::Encrypt::execute(Crypto::Attr const &crypto_attr)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
bool progress { false };
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_key_dir(req._key_id)->decrypt_file.write(
|
||||
WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress);
|
||||
_file.construct(_helper.state, crypto_attr.key_files.encrypt_file(_attr.in_key_id));
|
||||
_offset = _attr.in_pba * BLOCK_SIZE;
|
||||
_helper.state = WRITE;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case WRITE_OK:
|
||||
|
||||
_key_dir(req._key_id)->decrypt_file.read(
|
||||
READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress);
|
||||
break;
|
||||
|
||||
case READ_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation"); break;
|
||||
case WRITE: _file->write(WRITE_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break;
|
||||
case WRITE_OK: _file->read(READ_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break;
|
||||
case READ_OK: _helper.mark_succeeded(progress); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file-operation error"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_decrypt_client_data(bool &progress)
|
||||
bool Crypto::Decrypt::execute(Crypto::Attr const &crypto_attr)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
bool progress { false };
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_key_dir(req._key_id)->decrypt_file.write(
|
||||
WRITE_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&req._blk, BLOCK_SIZE }, progress);
|
||||
_file.construct(_helper.state, crypto_attr.key_files.decrypt_file(_attr.in_key_id));
|
||||
_offset = _attr.in_pba * BLOCK_SIZE;
|
||||
_helper.state = WRITE;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case WRITE_OK:
|
||||
|
||||
_key_dir(req._key_id)->decrypt_file.read(
|
||||
READ_OK, FILE_ERR, req._pba * BLOCK_SIZE, { (char *)&_blk, BLOCK_SIZE }, progress);
|
||||
break;
|
||||
|
||||
case READ_OK:
|
||||
|
||||
_generate_req<Client_data_request>(
|
||||
PLAINTEXT_BLK_SUPPLIED, progress, Client_data_request::SUPPLY_PLAINTEXT_BLK,
|
||||
req._client_req_offset, req._client_req_tag, req._pba, req._vba, _blk);;
|
||||
break;
|
||||
|
||||
case PLAINTEXT_BLK_SUPPLIED: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
case WRITE: _file->write(WRITE_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break;
|
||||
case WRITE_OK: _file->read(READ_OK, FILE_ERR, _offset, { (char *)&_attr.in_out_blk, BLOCK_SIZE }, progress); break;
|
||||
case READ_OK: _helper.mark_succeeded(progress); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file-operation error"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
void Crypto_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
switch (_req_ptr->_type) {
|
||||
case Request::ADD_KEY: _add_key(progress); break;
|
||||
case Request::REMOVE_KEY: _remove_key(progress); break;
|
||||
case Request::DECRYPT: _decrypt(progress); break;
|
||||
case Request::ENCRYPT: _encrypt(progress); break;
|
||||
case Request::DECRYPT_CLIENT_DATA: _decrypt_client_data(progress); break;
|
||||
case Request::ENCRYPT_CLIENT_DATA: _encrypt_client_data(progress); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Crypto::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
}
|
||||
|
||||
|
||||
Crypto_channel::Crypto_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node)
|
||||
:
|
||||
Module_channel { CRYPTO, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) }
|
||||
{ }
|
||||
|
||||
|
||||
Crypto::Crypto(Vfs::Env &vfs_env, Xml_node const &xml_node)
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++, vfs_env, xml_node);
|
||||
add_channel(*chan);
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
@ -13,62 +13,22 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/free_tree.h>
|
||||
#include <tresor/meta_tree.h>
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/hash.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
char const *Free_tree_request::type_to_string(Type type)
|
||||
bool Free_tree::Allocate_pbas::_can_alloc_pba_of(Type_2_node &node)
|
||||
{
|
||||
switch (type) {
|
||||
case ALLOC_FOR_NON_RKG: return "alloc_for_non_rkg";
|
||||
case ALLOC_FOR_RKG_CURR_GEN_BLKS: return "alloc_for_rkg_curr_gen_blks";
|
||||
case ALLOC_FOR_RKG_OLD_GEN_BLKS: return "alloc_for_rkg_old_gen_blks";
|
||||
case EXTENSION_STEP: return "extension_step";
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
|
||||
Free_tree_request::Free_tree_request(Module_id src_module_id, Module_channel_id src_chan_id, Type type,
|
||||
Tree_root &ft, Tree_root &mt, Snapshots const &snapshots, Generation last_secured_gen,
|
||||
Generation curr_gen, Generation free_gen, Number_of_blocks num_required_pbas,
|
||||
Tree_walk_pbas &new_blocks, Type_1_node_walk const &old_blocks,
|
||||
Tree_level_index max_lvl, Virtual_block_address vba, Tree_degree vbd_degree,
|
||||
Virtual_block_address vbd_max_vba, bool rekeying, Key_id prev_key_id,
|
||||
Key_id curr_key_id, Virtual_block_address rekeying_vba, Physical_block_address &pba,
|
||||
Number_of_blocks &num_pbas, bool &success)
|
||||
|
||||
:
|
||||
Module_request { src_module_id, src_chan_id, FREE_TREE }, _type { type }, _ft { ft }, _mt { mt },
|
||||
_curr_gen { curr_gen }, _free_gen { free_gen }, _num_required_pbas { num_required_pbas }, _new_blocks { new_blocks },
|
||||
_old_blocks { old_blocks }, _max_lvl { max_lvl }, _vba { vba }, _vbd_degree { vbd_degree }, _vbd_max_vba { vbd_max_vba },
|
||||
_rekeying { rekeying }, _prev_key_id { prev_key_id }, _curr_key_id { curr_key_id }, _rekeying_vba { rekeying_vba },
|
||||
_success { success }, _snapshots { snapshots }, _last_secured_gen { last_secured_gen }, _pba { pba }, _num_pbas { num_pbas }
|
||||
{ }
|
||||
|
||||
|
||||
void Free_tree::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
}
|
||||
|
||||
|
||||
bool Free_tree_channel::_can_alloc_pba_of(Type_2_node &node)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
if (node.pba == 0 || node.pba == INVALID_PBA || node.free_gen > req._last_secured_gen)
|
||||
if (node.pba == 0 || node.pba == INVALID_PBA || node.free_gen > _attr.in_last_secured_gen)
|
||||
return false;
|
||||
|
||||
if (!node.reserved)
|
||||
return true;
|
||||
|
||||
if (req._rekeying && node.last_key_id == req._prev_key_id && node.last_vba < req._rekeying_vba)
|
||||
if (_attr.in_rekeying && node.last_key_id == _attr.in_prev_key_id && node.last_vba < _attr.in_rekeying_vba)
|
||||
return true;
|
||||
|
||||
for (Snapshot const &snap : req._snapshots.items)
|
||||
for (Snapshot const &snap : _attr.in_snapshots.items)
|
||||
if (snap.valid && node.free_gen > snap.gen && node.alloc_gen < snap.gen + 1)
|
||||
return false;
|
||||
|
||||
@ -76,62 +36,48 @@ bool Free_tree_channel::_can_alloc_pba_of(Type_2_node &node)
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_generated_req_completed(State_uint state_uint)
|
||||
void Free_tree::Allocate_pbas::_alloc_pba_of(Type_2_node &t2_node)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("free tree: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_alloc_pba_of(Type_2_node &t2_node)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
Tree_level_index vbd_lvl { 0 };
|
||||
for (; vbd_lvl <= req._max_lvl && req._new_blocks.pbas[vbd_lvl]; vbd_lvl++);
|
||||
for (; vbd_lvl <= _attr.in_max_lvl && _attr.in_out_new_blocks.pbas[vbd_lvl]; vbd_lvl++);
|
||||
|
||||
Virtual_block_address node_min_vba { vbd_node_min_vba(_vbd_degree_log_2, vbd_lvl, req._vba) };
|
||||
req._new_blocks.pbas[vbd_lvl] = t2_node.pba;
|
||||
t2_node.alloc_gen = req._old_blocks.nodes[vbd_lvl].gen;
|
||||
t2_node.free_gen = req._free_gen;
|
||||
Virtual_block_address rkg_vba { req._rekeying_vba };
|
||||
switch (req._type) {
|
||||
case Request::ALLOC_FOR_NON_RKG:
|
||||
Virtual_block_address node_min_vba { vbd_node_min_vba(_vbd_degree_log_2, vbd_lvl, _attr.in_vba) };
|
||||
_attr.in_out_new_blocks.pbas[vbd_lvl] = t2_node.pba;
|
||||
t2_node.alloc_gen = _attr.in_old_blocks.nodes[vbd_lvl].gen;
|
||||
t2_node.free_gen = _attr.in_free_gen;
|
||||
Virtual_block_address rkg_vba { _attr.in_rekeying_vba };
|
||||
switch (_attr.in_application) {
|
||||
case NON_REKEYING:
|
||||
|
||||
t2_node.reserved = true;
|
||||
t2_node.pba = req._old_blocks.nodes[vbd_lvl].pba;
|
||||
t2_node.pba = _attr.in_old_blocks.nodes[vbd_lvl].pba;
|
||||
t2_node.last_vba = node_min_vba;
|
||||
if (req._rekeying) {
|
||||
if (req._vba < rkg_vba)
|
||||
t2_node.last_key_id = req._curr_key_id;
|
||||
if (_attr.in_rekeying) {
|
||||
if (_attr.in_vba < rkg_vba)
|
||||
t2_node.last_key_id = _attr.in_curr_key_id;
|
||||
else
|
||||
t2_node.last_key_id = req._prev_key_id;
|
||||
t2_node.last_key_id = _attr.in_prev_key_id;
|
||||
} else
|
||||
t2_node.last_key_id = req._curr_key_id;
|
||||
t2_node.last_key_id = _attr.in_curr_key_id;
|
||||
break;
|
||||
|
||||
case Request::ALLOC_FOR_RKG_CURR_GEN_BLKS:
|
||||
case REKEYING_IN_CURRENT_GENERATION:
|
||||
|
||||
t2_node.reserved = false;
|
||||
t2_node.pba = req._old_blocks.nodes[vbd_lvl].pba;
|
||||
t2_node.pba = _attr.in_old_blocks.nodes[vbd_lvl].pba;
|
||||
t2_node.last_vba = node_min_vba;
|
||||
t2_node.last_key_id = req._prev_key_id;
|
||||
t2_node.last_key_id = _attr.in_prev_key_id;
|
||||
break;
|
||||
|
||||
case Request::ALLOC_FOR_RKG_OLD_GEN_BLKS:
|
||||
case REKEYING_IN_OLDER_GENERATION:
|
||||
{
|
||||
t2_node.reserved = true;
|
||||
Virtual_block_address node_max_vba { vbd_node_max_vba(_vbd_degree_log_2, vbd_lvl, req._vba) };
|
||||
if (rkg_vba < node_max_vba && rkg_vba < req._vbd_max_vba) {
|
||||
t2_node.last_key_id = req._prev_key_id;
|
||||
Virtual_block_address node_max_vba { vbd_node_max_vba(_vbd_degree_log_2, vbd_lvl, _attr.in_vba) };
|
||||
if (rkg_vba < node_max_vba && rkg_vba < _attr.in_vbd_max_vba) {
|
||||
t2_node.last_key_id = _attr.in_prev_key_id;
|
||||
t2_node.last_vba = rkg_vba + 1;
|
||||
} else if (rkg_vba == node_max_vba || rkg_vba == req._vbd_max_vba) {
|
||||
t2_node.last_key_id = req._curr_key_id;
|
||||
} else if (rkg_vba == node_max_vba || rkg_vba == _attr.in_vbd_max_vba) {
|
||||
t2_node.last_key_id = _attr.in_curr_key_id;
|
||||
t2_node.last_vba = node_min_vba;
|
||||
} else
|
||||
ASSERT_NEVER_REACHED;
|
||||
@ -142,78 +88,59 @@ void Free_tree_channel::_alloc_pba_of(Type_2_node &t2_node)
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_mark_req_failed(bool &progress, char const *str)
|
||||
{
|
||||
error(Request::type_to_string(_req_ptr->_type), " request failed, reason: \"", str, "\"");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
_req_ptr->_success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_start_tree_traversal(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
_num_pbas = 0;
|
||||
_lvl = req._ft.max_lvl;
|
||||
_node_idx[_lvl] = 0;
|
||||
_t1_blks[_lvl].nodes[_node_idx[_lvl]] = req._ft.t1_node();
|
||||
_generate_req<Block_io::Read>(SEEK_DOWN, progress, req._ft.pba, _blk);
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_traverse_curr_node(bool &progress)
|
||||
void Free_tree::Allocate_pbas::_traverse_curr_node(bool &progress)
|
||||
{
|
||||
if (_lvl) {
|
||||
Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] };
|
||||
if (t1_node.pba)
|
||||
_generate_req<Block_io::Read>(SEEK_DOWN, progress, t1_node.pba, _blk);
|
||||
_read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, t1_node.pba, _blk);
|
||||
else {
|
||||
_state = SEEK_LEFT_OR_UP;
|
||||
_helper.state = SEEK_LEFT_OR_UP;
|
||||
progress = true;
|
||||
}
|
||||
} else {
|
||||
Type_2_node &t2_node { _t2_blk.nodes[_node_idx[_lvl]] };
|
||||
if (_num_pbas < _req_ptr->_num_required_pbas && _can_alloc_pba_of(t2_node)) {
|
||||
if (_num_pbas < _attr.in_num_required_pbas && _can_alloc_pba_of(t2_node)) {
|
||||
if (_apply_allocation)
|
||||
_alloc_pba_of(t2_node);
|
||||
_num_pbas++;
|
||||
}
|
||||
_state = SEEK_LEFT_OR_UP;
|
||||
_helper.state = SEEK_LEFT_OR_UP;
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_alloc_pbas(bool &progress)
|
||||
void Free_tree::Allocate_pbas::_start_tree_traversal(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
_num_pbas = 0;
|
||||
_lvl = _attr.in_out_ft.max_lvl;
|
||||
_node_idx[_lvl] = 0;
|
||||
_t1_blks[_lvl].nodes[_node_idx[_lvl]] = _attr.in_out_ft.t1_node();
|
||||
_read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, _attr.in_out_ft.pba, _blk);
|
||||
}
|
||||
|
||||
_vbd_degree_log_2 = log2<Tree_degree_log_2>(req._vbd_degree);
|
||||
|
||||
bool Free_tree::Allocate_pbas::execute(Block_io &block_io, Meta_tree &meta_tree)
|
||||
{
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_vbd_degree_log_2 = log2<Tree_degree_log_2>(_attr.in_vbd_degree);
|
||||
_apply_allocation = false;
|
||||
_start_tree_traversal(progress);
|
||||
break;
|
||||
|
||||
case READ_BLK: progress |= _read_block.execute(block_io); break;
|
||||
case SEEK_DOWN:
|
||||
{
|
||||
if (!check_hash(_blk, _t1_blks[_lvl].nodes[_node_idx[_lvl]].hash)) {
|
||||
_mark_req_failed(progress, "hash mismatch");
|
||||
_helper.mark_failed(progress, "hash mismatch");
|
||||
break;
|
||||
}
|
||||
_lvl--;
|
||||
_node_idx[_lvl] = req._ft.degree - 1;
|
||||
_node_idx[_lvl] = _attr.in_out_ft.degree - 1;
|
||||
if (_lvl)
|
||||
_t1_blks[_lvl].decode_from_blk(_blk);
|
||||
else
|
||||
@ -223,31 +150,31 @@ void Free_tree_channel::_alloc_pbas(bool &progress)
|
||||
}
|
||||
case SEEK_LEFT_OR_UP:
|
||||
|
||||
if (_lvl < req._ft.max_lvl) {
|
||||
if (_node_idx[_lvl] && _num_pbas < _req_ptr->_num_required_pbas) {
|
||||
if (_lvl < _attr.in_out_ft.max_lvl) {
|
||||
if (_node_idx[_lvl] && _num_pbas < _attr.in_num_required_pbas) {
|
||||
_node_idx[_lvl]--;
|
||||
_traverse_curr_node(progress);
|
||||
} else {
|
||||
_lvl++;
|
||||
Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] };
|
||||
if (_apply_allocation)
|
||||
if (t1_node.is_volatile(req._curr_gen)) {
|
||||
_state = WRITE_BLK;
|
||||
if (t1_node.is_volatile(_attr.in_curr_gen)) {
|
||||
_helper.state = ALLOC_PBA_SUCCEEDED;
|
||||
progress = true;
|
||||
} else
|
||||
_generate_req<Meta_tree::Alloc_pba>(WRITE_BLK, progress, req._mt, req._curr_gen, t1_node.pba);
|
||||
_allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, t1_node.pba);
|
||||
else {
|
||||
_state = SEEK_LEFT_OR_UP;
|
||||
_helper.state = SEEK_LEFT_OR_UP;
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (_apply_allocation) {
|
||||
req._ft.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]);
|
||||
_mark_req_successful(progress);
|
||||
_attr.in_out_ft.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]);
|
||||
_helper.mark_succeeded(progress);
|
||||
} else {
|
||||
if (_num_pbas < req._num_required_pbas)
|
||||
_mark_req_failed(progress, "not enough free pbas");
|
||||
if (_num_pbas < _attr.in_num_required_pbas)
|
||||
_helper.mark_failed(progress, "not enough free pbas");
|
||||
else {
|
||||
_apply_allocation = true;
|
||||
_start_tree_traversal(progress);
|
||||
@ -256,68 +183,55 @@ void Free_tree_channel::_alloc_pbas(bool &progress)
|
||||
}
|
||||
break;
|
||||
|
||||
case WRITE_BLK:
|
||||
case ALLOC_PBA: progress |= _allocate_pba.execute(meta_tree, block_io); break;
|
||||
case ALLOC_PBA_SUCCEEDED:
|
||||
{
|
||||
if (_lvl > 1)
|
||||
_t1_blks[_lvl - 1].encode_to_blk(_blk);
|
||||
else
|
||||
_t2_blk.encode_to_blk(_blk);
|
||||
Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] };
|
||||
t1_node.gen = req._curr_gen;
|
||||
t1_node.gen = _attr.in_curr_gen;
|
||||
calc_hash(_blk, t1_node.hash);
|
||||
_generate_req<Block_io::Write>(SEEK_LEFT_OR_UP, progress, t1_node.pba, _blk);
|
||||
_write_block.generate(_helper, WRITE_BLK, SEEK_LEFT_OR_UP, progress, t1_node.pba, _blk);
|
||||
break;
|
||||
}
|
||||
case WRITE_BLK: progress |= _write_block.execute(block_io); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
switch(_req_ptr->_type) {
|
||||
case Request::ALLOC_FOR_NON_RKG:
|
||||
case Request::ALLOC_FOR_RKG_CURR_GEN_BLKS:
|
||||
case Request::ALLOC_FOR_RKG_OLD_GEN_BLKS: _alloc_pbas(progress); break;
|
||||
case Request::EXTENSION_STEP: _extension_step(progress); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_generate_write_blk_req(bool &progress)
|
||||
void Free_tree::Extend_tree::_generate_write_blk_req(bool &progress)
|
||||
{
|
||||
if (_lvl > 1)
|
||||
_t1_blks[_lvl].encode_to_blk(_blk);
|
||||
else
|
||||
_t2_blk.encode_to_blk(_blk);
|
||||
|
||||
_generate_req<Block_io::Write>(WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _blk);
|
||||
_write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _new_pbas.pbas[_lvl], _blk);
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" lvl ", _lvl, " write to pba ", _new_pbas.pbas[_lvl]);
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_add_new_root_lvl()
|
||||
void Free_tree::Extend_tree::_add_new_root_lvl()
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
ASSERT(req._ft.max_lvl < TREE_MAX_LEVEL);
|
||||
req._ft.max_lvl++;
|
||||
_t1_blks[req._ft.max_lvl] = { };
|
||||
_t1_blks[req._ft.max_lvl].nodes[0] = req._ft.t1_node();
|
||||
_new_pbas.pbas[req._ft.max_lvl] = alloc_pba_from_range(req._pba, req._num_pbas);
|
||||
req._ft.t1_node({ _new_pbas.pbas[req._ft.max_lvl], req._curr_gen });
|
||||
ASSERT(_attr.in_out_ft.max_lvl < TREE_MAX_LEVEL);
|
||||
_attr.in_out_ft.max_lvl++;
|
||||
_t1_blks[_attr.in_out_ft.max_lvl] = { };
|
||||
_t1_blks[_attr.in_out_ft.max_lvl].nodes[0] = _attr.in_out_ft.t1_node();
|
||||
_new_pbas.pbas[_attr.in_out_ft.max_lvl] = alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas);
|
||||
_attr.in_out_ft.t1_node({ _new_pbas.pbas[_attr.in_out_ft.max_lvl], _attr.in_curr_gen });
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" set root: ", req._ft, "\n set lvl ", req._ft.max_lvl, " node 0: ",
|
||||
_t1_blks[req._ft.max_lvl].nodes[0]);
|
||||
log(" set root: ", _attr.in_out_ft, "\n set lvl ", _attr.in_out_ft.max_lvl, " node 0: ",
|
||||
_t1_blks[_attr.in_out_ft.max_lvl].nodes[0]);
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_index dst_node_idx)
|
||||
void Free_tree::Extend_tree::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_index dst_node_idx)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
_num_leaves = 0;
|
||||
_lvl = dst_lvl;
|
||||
if (dst_lvl > 1) {
|
||||
@ -331,17 +245,17 @@ void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_i
|
||||
log(" reset lvl ", lvl);
|
||||
}
|
||||
}
|
||||
for (; _lvl && req._num_pbas; _lvl--) {
|
||||
for (; _lvl && _attr.in_out_num_pbas; _lvl--) {
|
||||
Tree_node_index node_idx = (_lvl == dst_lvl) ? dst_node_idx : 0;
|
||||
if (_lvl > 1) {
|
||||
_new_pbas.pbas[_lvl - 1] = alloc_pba_from_range(req._pba, req._num_pbas);
|
||||
_t1_blks[_lvl].nodes[node_idx] = { _new_pbas.pbas[_lvl - 1], req._curr_gen };
|
||||
_new_pbas.pbas[_lvl - 1] = alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas);
|
||||
_t1_blks[_lvl].nodes[node_idx] = { _new_pbas.pbas[_lvl - 1], _attr.in_curr_gen };
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" set _lvl d ", _lvl, " node ", node_idx, ": ", _t1_blks[_lvl].nodes[node_idx]);
|
||||
|
||||
} else {
|
||||
for (; node_idx < req._ft.degree && req._num_pbas; node_idx++) {
|
||||
_t2_blk.nodes[node_idx] = { alloc_pba_from_range(req._pba, req._num_pbas) };
|
||||
for (; node_idx < _attr.in_out_ft.degree && _attr.in_out_num_pbas; node_idx++) {
|
||||
_t2_blk.nodes[node_idx] = { alloc_pba_from_range(_attr.in_out_first_pba, _attr.in_out_num_pbas) };
|
||||
_num_leaves++;
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" set _lvl e ", _lvl, " node ", node_idx, ": ", _t2_blk.nodes[node_idx]);
|
||||
@ -353,80 +267,80 @@ void Free_tree_channel::_add_new_branch_at(Tree_level_index dst_lvl, Tree_node_i
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_extension_step(bool &progress)
|
||||
bool Free_tree::Extend_tree::execute(Block_io &block_io, Meta_tree &meta_tree)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_num_leaves = 0;
|
||||
_vba = req._ft.num_leaves;
|
||||
_vba = _attr.in_out_ft.num_leaves;
|
||||
_old_pbas = { };
|
||||
_old_generations = { };
|
||||
_new_pbas = { };
|
||||
_lvl = req._ft.max_lvl;
|
||||
_old_pbas.pbas[_lvl] = req._ft.pba;
|
||||
_old_generations.items[_lvl] = req._ft.gen;
|
||||
if (_vba <= tree_max_max_vba(req._ft.degree, req._ft.max_lvl)) {
|
||||
_lvl = _attr.in_out_ft.max_lvl;
|
||||
_old_pbas.pbas[_lvl] = _attr.in_out_ft.pba;
|
||||
_old_generations.items[_lvl] = _attr.in_out_ft.gen;
|
||||
if (_vba <= tree_max_max_vba(_attr.in_out_ft.degree, _attr.in_out_ft.max_lvl)) {
|
||||
|
||||
_generate_req<Block_io::Read>(READ_BLK_SUCCEEDED, progress, req._ft.pba, _blk);
|
||||
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _attr.in_out_ft.pba, _blk);
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" root (", req._ft, "): load to lvl ", _lvl);
|
||||
log(" root (", _attr.in_out_ft, "): load to lvl ", _lvl);
|
||||
} else {
|
||||
_add_new_root_lvl();
|
||||
_add_new_branch_at(req._ft.max_lvl, 1);
|
||||
_add_new_branch_at(_attr.in_out_ft.max_lvl, 1);
|
||||
_generate_write_blk_req(progress);
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" pbas allocated: curr gen ", req._curr_gen);
|
||||
log(" pbas allocated: curr gen ", _attr.in_curr_gen);
|
||||
}
|
||||
break;
|
||||
|
||||
case READ_BLK: progress |= _read_block.execute(block_io); break;
|
||||
case READ_BLK_SUCCEEDED:
|
||||
|
||||
if (_lvl > 1) {
|
||||
|
||||
_t1_blks[_lvl].decode_from_blk(_blk);
|
||||
if (_lvl < req._ft.max_lvl) {
|
||||
Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree);
|
||||
if (_lvl < _attr.in_out_ft.max_lvl) {
|
||||
Tree_node_index node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree);
|
||||
if (!check_hash(_blk, _t1_blks[_lvl + 1].nodes[node_idx].hash))
|
||||
_mark_req_failed(progress, "hash mismatch");
|
||||
_helper.mark_failed(progress, "hash mismatch");
|
||||
} else
|
||||
if (!check_hash(_blk, req._ft.hash))
|
||||
_mark_req_failed(progress, "hash mismatch");
|
||||
if (!check_hash(_blk, _attr.in_out_ft.hash))
|
||||
_helper.mark_failed(progress, "hash mismatch");
|
||||
|
||||
Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl, req._ft.degree);
|
||||
Tree_node_index node_idx = tree_node_index(_vba, _lvl, _attr.in_out_ft.degree);
|
||||
Type_1_node &t1_node = _t1_blks[_lvl].nodes[node_idx];
|
||||
if (t1_node.valid()) {
|
||||
|
||||
_lvl--;
|
||||
_old_pbas.pbas [_lvl] = t1_node.pba;
|
||||
_old_generations.items[_lvl] = t1_node.gen;
|
||||
_generate_req<Block_io::Read>(READ_BLK_SUCCEEDED, progress, t1_node.pba, _blk);
|
||||
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, t1_node.pba, _blk);
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" lvl ", _lvl + 1, " node ", node_idx, " (", t1_node, "): load to lvl ", _lvl);
|
||||
} else {
|
||||
_alloc_lvl = _lvl;
|
||||
_add_new_branch_at(_lvl, node_idx);
|
||||
if (_old_generations.items[_alloc_lvl] == req._curr_gen) {
|
||||
if (_old_generations.items[_alloc_lvl] == _attr.in_curr_gen) {
|
||||
|
||||
_alloc_pba = _old_pbas.pbas[_alloc_lvl];
|
||||
_state = ALLOC_PBA_SUCCEEDED;
|
||||
_helper.state = ALLOC_PBA_SUCCEEDED;
|
||||
progress = true;
|
||||
} else {
|
||||
_alloc_pba = _old_pbas.pbas[_alloc_lvl];
|
||||
_generate_req<Meta_tree_request>(
|
||||
ALLOC_PBA_SUCCEEDED, progress, Meta_tree_request::ALLOC_PBA, req._mt, req._curr_gen, _alloc_pba);
|
||||
_allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, _alloc_pba);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_t2_blk.decode_from_blk(_blk);
|
||||
Tree_node_index t1_node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree);
|
||||
Tree_node_index t1_node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree);
|
||||
if (!check_hash(_blk, _t1_blks[_lvl + 1].nodes[t1_node_idx].hash))
|
||||
_mark_req_failed(progress, "hash mismatch");
|
||||
_helper.mark_failed(progress, "hash mismatch");
|
||||
|
||||
Tree_node_index t2_node_idx = t2_node_idx_for_vba(_vba, req._ft.degree);
|
||||
Tree_node_index t2_node_idx = tree_node_index(_vba, _lvl, _attr.in_out_ft.degree);
|
||||
if (_t2_blk.nodes[t2_node_idx].valid())
|
||||
_mark_req_failed(progress, "t2 node valid");
|
||||
_helper.mark_failed(progress, "t2 node valid");
|
||||
|
||||
_add_new_branch_at(_lvl, t2_node_idx);
|
||||
_alloc_lvl = _lvl;
|
||||
@ -434,41 +348,41 @@ void Free_tree_channel::_extension_step(bool &progress)
|
||||
log(" alloc lvl ", _alloc_lvl);
|
||||
|
||||
_alloc_pba = _old_pbas.pbas[_alloc_lvl];
|
||||
_generate_req<Meta_tree_request>(
|
||||
ALLOC_PBA_SUCCEEDED, progress, Meta_tree_request::ALLOC_PBA, req._mt, req._curr_gen, _alloc_pba);
|
||||
_allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, _alloc_pba);
|
||||
}
|
||||
break;
|
||||
|
||||
case ALLOC_PBA: progress |= _allocate_pba.execute(meta_tree, block_io); break;
|
||||
case ALLOC_PBA_SUCCEEDED:
|
||||
|
||||
_new_pbas.pbas[_alloc_lvl] = _alloc_pba;
|
||||
if (_alloc_lvl < req._ft.max_lvl) {
|
||||
if (_alloc_lvl < _attr.in_out_ft.max_lvl) {
|
||||
|
||||
_alloc_lvl++;
|
||||
if (_old_generations.items[_alloc_lvl] == req._curr_gen) {
|
||||
if (_old_generations.items[_alloc_lvl] == _attr.in_curr_gen) {
|
||||
|
||||
_alloc_pba = _old_pbas.pbas[_alloc_lvl];
|
||||
_state = ALLOC_PBA_SUCCEEDED;
|
||||
_helper.state = ALLOC_PBA_SUCCEEDED;
|
||||
progress = true;
|
||||
} else {
|
||||
_alloc_pba = _old_pbas.pbas[_alloc_lvl];
|
||||
_generate_req<Meta_tree_request>(
|
||||
ALLOC_PBA_SUCCEEDED, progress, Meta_tree_request::ALLOC_PBA, req._mt, req._curr_gen, _alloc_pba);
|
||||
_allocate_pba.generate(_helper, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, progress, _attr.in_out_mt, _attr.in_curr_gen, _alloc_pba);
|
||||
}
|
||||
} else {
|
||||
_generate_write_blk_req(progress);
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" pbas allocated: curr gen ", req._curr_gen);
|
||||
log(" pbas allocated: curr gen ", _attr.in_curr_gen);
|
||||
}
|
||||
break;
|
||||
|
||||
case WRITE_BLK: progress |= _write_block.execute(block_io); break;
|
||||
case WRITE_BLK_SUCCEEDED:
|
||||
|
||||
if (_lvl < req._ft.max_lvl) {
|
||||
if (_lvl < _attr.in_out_ft.max_lvl) {
|
||||
if (_lvl > 1) {
|
||||
Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree);
|
||||
Tree_node_index node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree);
|
||||
Type_1_node &t1_node { _t1_blks[_lvl + 1].nodes[node_idx] };
|
||||
t1_node = { _new_pbas.pbas[_lvl], req._curr_gen };
|
||||
t1_node = { _new_pbas.pbas[_lvl], _attr.in_curr_gen };
|
||||
calc_hash(_blk, t1_node.hash);
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" set lvl ", _lvl + 1, " node ", node_idx, ": ", t1_node);
|
||||
@ -476,9 +390,9 @@ void Free_tree_channel::_extension_step(bool &progress)
|
||||
_lvl++;
|
||||
_generate_write_blk_req(progress);
|
||||
} else {
|
||||
Tree_node_index node_idx = t1_node_idx_for_vba(_vba, _lvl + 1, req._ft.degree);
|
||||
Tree_node_index node_idx = tree_node_index(_vba, _lvl + 1, _attr.in_out_ft.degree);
|
||||
Type_1_node &t1_node = _t1_blks[_lvl + 1].nodes[node_idx];
|
||||
t1_node = { _new_pbas.pbas[_lvl], req._curr_gen };
|
||||
t1_node = { _new_pbas.pbas[_lvl], _attr.in_curr_gen };
|
||||
calc_hash(_blk, t1_node.hash);
|
||||
if (VERBOSE_FT_EXTENSION)
|
||||
log(" set lvl ", _lvl + 1, " t1_node ", node_idx, ": ", t1_node);
|
||||
@ -487,30 +401,14 @@ void Free_tree_channel::_extension_step(bool &progress)
|
||||
_generate_write_blk_req(progress);
|
||||
}
|
||||
} else {
|
||||
req._ft.t1_node({ _new_pbas.pbas[_lvl], req._curr_gen });
|
||||
calc_hash(_blk, req._ft.hash);
|
||||
req._ft.num_leaves += _num_leaves;
|
||||
_mark_req_successful(progress);
|
||||
_attr.in_out_ft.t1_node({ _new_pbas.pbas[_lvl], _attr.in_curr_gen });
|
||||
calc_hash(_blk, _attr.in_out_ft.hash);
|
||||
_attr.in_out_ft.num_leaves += _num_leaves;
|
||||
_helper.mark_succeeded(progress);
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Free_tree_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
Free_tree::Free_tree()
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++);
|
||||
add_channel(*chan);
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
@ -13,73 +13,66 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/ft_check.h>
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/hash.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Ft_check_request::Ft_check_request(Module_id src_mod, Module_channel_id src_chan, Tree_root const &ft, bool &success)
|
||||
:
|
||||
Module_request { src_mod, src_chan, FT_CHECK }, _ft { ft }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress)
|
||||
bool Ft_check::Check::_execute_node(Block_io &block_io, Tree_level_index lvl, Tree_node_index node_idx, bool &progress)
|
||||
{
|
||||
bool &check_node { _check_node[lvl][node_idx] };
|
||||
|
||||
if (check_node == false)
|
||||
return false;
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_IN_PROGRESS:
|
||||
switch (_helper.state) {
|
||||
case IN_PROGRESS:
|
||||
|
||||
if (lvl == 1) {
|
||||
Type_2_node const &node { _t2_blk.nodes[node_idx] };
|
||||
if (!_num_remaining_leaves) {
|
||||
if (node.valid()) {
|
||||
_mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node,
|
||||
") valid but no leaves remaining" });
|
||||
_helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node,
|
||||
") valid but no leaves remaining" });
|
||||
break;
|
||||
}
|
||||
check_node = false;
|
||||
progress = true;
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused");
|
||||
log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused");
|
||||
break;
|
||||
}
|
||||
_num_remaining_leaves--;
|
||||
check_node = false;
|
||||
progress = true;
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " done");
|
||||
log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " done");
|
||||
} else {
|
||||
Type_1_node const &node { _t1_blks.items[lvl].nodes[node_idx] };
|
||||
if (!node.valid()) {
|
||||
if (_num_remaining_leaves) {
|
||||
_mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ",
|
||||
_num_remaining_leaves, " leaves remaining" });
|
||||
_helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ",
|
||||
_num_remaining_leaves, " leaves remaining" });
|
||||
break;
|
||||
}
|
||||
check_node = false;
|
||||
progress = true;
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused");
|
||||
log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " unused");
|
||||
break;
|
||||
}
|
||||
_generate_req<Block_io::Read>(READ_BLK_SUCCEEDED, progress, node.pba, _blk);
|
||||
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _blk);
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx,
|
||||
log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx,
|
||||
" (", node, "): load to lvl ", lvl - 1);
|
||||
}
|
||||
break;
|
||||
|
||||
case READ_BLK: progress |= _read_block.execute(block_io); break;
|
||||
case READ_BLK_SUCCEEDED:
|
||||
{
|
||||
Type_1_node const &node { _t1_blks.items[lvl].nodes[node_idx] };
|
||||
if (node.gen != INITIAL_GENERATION && !check_hash(_blk, node.hash)) {
|
||||
_mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" });
|
||||
_helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" });
|
||||
break;
|
||||
}
|
||||
if (lvl == 2)
|
||||
@ -89,11 +82,11 @@ bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_
|
||||
for (bool &cn : _check_node[lvl - 1])
|
||||
cn = true;
|
||||
|
||||
_state = REQ_IN_PROGRESS;
|
||||
_helper.state = IN_PROGRESS;
|
||||
check_node = false;
|
||||
progress = true;
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " has good hash");
|
||||
log(Level_indent { lvl, _attr.in_ft.max_lvl }, " lvl ", lvl, " node ", node_idx, " has good hash");
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
@ -102,81 +95,24 @@ bool Ft_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_
|
||||
}
|
||||
|
||||
|
||||
void Ft_check_channel::execute(bool &progress)
|
||||
bool Ft_check::Check::execute(Block_io &block_io)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
if (_state == REQ_SUBMITTED) {
|
||||
for (Tree_level_index lvl { 1 }; lvl <= _req_ptr->_ft.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx { 0 }; node_idx < _req_ptr->_ft.degree; node_idx++)
|
||||
bool progress = false;
|
||||
if (_helper.state == INIT) {
|
||||
for (Tree_level_index lvl { 1 }; lvl <= _attr.in_ft.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_ft.degree; node_idx++)
|
||||
_check_node[lvl][node_idx] = false;
|
||||
|
||||
_num_remaining_leaves = _req_ptr->_ft.num_leaves;
|
||||
_t1_blks.items[_req_ptr->_ft.max_lvl + 1].nodes[0] = _req_ptr->_ft.t1_node();
|
||||
_check_node[_req_ptr->_ft.max_lvl + 1][0] = true;
|
||||
_state = REQ_IN_PROGRESS;
|
||||
_num_remaining_leaves = _attr.in_ft.num_leaves;
|
||||
_t1_blks.items[_attr.in_ft.max_lvl + 1].nodes[0] = _attr.in_ft.t1_node();
|
||||
_check_node[_attr.in_ft.max_lvl + 1][0] = true;
|
||||
_helper.state = IN_PROGRESS;
|
||||
}
|
||||
for (Tree_level_index lvl { 1 }; lvl <= _req_ptr->_ft.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx { 0 }; node_idx < _req_ptr->_ft.degree; node_idx++)
|
||||
if (_execute_node(lvl, node_idx, progress))
|
||||
return;
|
||||
for (Tree_level_index lvl { 1 }; lvl <= _attr.in_ft.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_ft.degree; node_idx++)
|
||||
if (_execute_node(block_io, lvl, node_idx, progress))
|
||||
return progress;
|
||||
|
||||
_mark_req_successful(progress);
|
||||
}
|
||||
|
||||
|
||||
void Ft_check_channel::_generated_req_completed(State_uint state_uint)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("ft check: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
void Ft_check_channel::_mark_req_failed(bool &progress, Error_string str)
|
||||
{
|
||||
error("ft check request (", *_req_ptr, ") failed: ", str);
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Ft_check_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
_req_ptr->_success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Ft_check_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
Ft_check::Ft_check()
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++);
|
||||
add_channel(*chan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ft_check::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
_helper.mark_succeeded(progress);
|
||||
return progress;
|
||||
}
|
||||
|
@ -13,20 +13,67 @@
|
||||
*/
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/hash.h>
|
||||
#include <tresor/ft_initializer.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Ft_initializer_request::Ft_initializer_request(Module_id src_mod, Module_channel_id src_chan,
|
||||
Tree_root &ft, Pba_allocator &pba_alloc, bool &success)
|
||||
:
|
||||
Module_request { src_mod, src_chan, FT_INITIALIZER }, _ft { ft }, _pba_alloc { pba_alloc }, _success { success }
|
||||
{ }
|
||||
void Ft_initializer::Initialize::_reset_level(Tree_level_index lvl, Node_state node_state)
|
||||
{
|
||||
if (lvl == 1)
|
||||
for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) {
|
||||
_t2_blk.nodes[idx] = { };
|
||||
_t2_node_states[idx] = node_state;
|
||||
}
|
||||
else
|
||||
for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) {
|
||||
_t1_blks.items[lvl].nodes[idx] = { };
|
||||
_t1_node_states[lvl][idx] = node_state;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &progress)
|
||||
bool Ft_initializer::Initialize::execute(Block_io &block_io)
|
||||
{
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_num_remaining_leaves = _attr.in_tree_cfg.num_leaves;
|
||||
for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++)
|
||||
_reset_level(lvl, DONE);
|
||||
|
||||
_t1_node_states[_attr.in_tree_cfg.max_lvl + 1][0] = INIT_BLOCK;
|
||||
_helper.state = EXECUTE_NODES;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case EXECUTE_NODES:
|
||||
|
||||
for (Tree_node_index node_idx = 0; node_idx < _attr.in_tree_cfg.degree; node_idx++)
|
||||
if (_execute_t2_node(node_idx, progress))
|
||||
return progress;
|
||||
|
||||
for (Tree_level_index lvl = 1; lvl <= _attr.in_tree_cfg.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx = 0; node_idx < _attr.in_tree_cfg.degree; node_idx++)
|
||||
if (_execute_t1_node(lvl, node_idx, progress))
|
||||
return progress;
|
||||
|
||||
if (_num_remaining_leaves)
|
||||
_helper.mark_failed(progress, "leaves remaining");
|
||||
else {
|
||||
_attr.out_tree_root = _t1_blks.items[_attr.in_tree_cfg.max_lvl + 1].nodes[0];
|
||||
_helper.mark_succeeded(progress);
|
||||
}
|
||||
break;
|
||||
|
||||
case WRITE_BLOCK: progress |= _write_block.execute(block_io); break;
|
||||
default: break;;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
bool Ft_initializer::Initialize::_execute_t2_node(Tree_node_index node_idx, bool &progress)
|
||||
{
|
||||
Node_state &node_state { _t2_node_states[node_idx] };
|
||||
Type_2_node &node { _t2_blk.nodes[node_idx] };
|
||||
@ -42,8 +89,8 @@ bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &pr
|
||||
|
||||
if (_num_remaining_leaves) {
|
||||
node = { };
|
||||
if (!_req_ptr->_pba_alloc.alloc(node.pba)) {
|
||||
_mark_req_failed(progress, "allocate pba");
|
||||
if (!_attr.in_out_pba_alloc.alloc(node.pba)) {
|
||||
_helper.mark_failed(progress, "allocate pba");
|
||||
break;
|
||||
}
|
||||
node_state = DONE;
|
||||
@ -60,13 +107,13 @@ bool Ft_initializer_channel::_execute_t2_node(Tree_node_index node_idx, bool &pr
|
||||
}
|
||||
break;
|
||||
|
||||
case WRITE_BLK: ASSERT_NEVER_REACHED;
|
||||
case WRITING_BLOCK: ASSERT_NEVER_REACHED;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress)
|
||||
bool Ft_initializer::Initialize::_execute_t1_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress)
|
||||
{
|
||||
Type_1_node &node { _t1_blks.items[lvl].nodes[node_idx] };
|
||||
Node_state &node_state { _t1_node_states[lvl][node_idx] };
|
||||
@ -92,8 +139,8 @@ bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_in
|
||||
case INIT_NODE:
|
||||
{
|
||||
node = { };
|
||||
if (!_req_ptr->_pba_alloc.alloc(node.pba)) {
|
||||
_mark_req_failed(progress, "allocate pba");
|
||||
if (!_attr.in_out_pba_alloc.alloc(node.pba)) {
|
||||
_helper.mark_failed(progress, "allocate pba");
|
||||
break;
|
||||
}
|
||||
if (lvl == 2)
|
||||
@ -101,15 +148,13 @@ bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_in
|
||||
else
|
||||
_t1_blks.items[lvl - 1].encode_to_blk(_blk);
|
||||
calc_hash(_blk, node.hash);
|
||||
generate_req<Block_io::Write>(EXECUTE_NODES, progress, node.pba, _blk, _generated_req_success);
|
||||
_state = REQ_GENERATED;
|
||||
node_state = WRITE_BLK;
|
||||
progress = true;
|
||||
_write_block.generate(_helper, WRITE_BLOCK, EXECUTE_NODES, progress, node.pba, _blk);
|
||||
node_state = WRITING_BLOCK;
|
||||
if (VERBOSE_FT_INIT)
|
||||
log("[ft_init] node: ", lvl, " ", node_idx, " assign pba: ", node.pba);
|
||||
break;
|
||||
}
|
||||
case WRITE_BLK:
|
||||
case WRITING_BLOCK:
|
||||
|
||||
node_state = DONE;
|
||||
progress = true;
|
||||
@ -119,115 +164,3 @@ bool Ft_initializer_channel::_execute_t1_node(Tree_level_index lvl, Tree_node_in
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void Ft_initializer_channel::_generated_req_completed(State_uint state_uint)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("ft initializer request (", *_req_ptr, ") failed because generated request failed");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
void Ft_initializer_channel::_mark_req_failed(bool &progress, char const *str)
|
||||
{
|
||||
error("ft initializer request (", *_req_ptr, ") failed because: ", str);
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Ft_initializer_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
_req_ptr->_ft.t1_node(_t1_blks.items[_req_ptr->_ft.max_lvl + 1].nodes[0]);
|
||||
_req_ptr->_success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Ft_initializer_channel::_reset_level(Tree_level_index lvl, Node_state node_state)
|
||||
{
|
||||
if (lvl == 1)
|
||||
for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) {
|
||||
_t2_blk.nodes[idx] = { };
|
||||
_t2_node_states[idx] = node_state;
|
||||
}
|
||||
else
|
||||
for (Tree_node_index idx = 0; idx < NUM_NODES_PER_BLK; idx++) {
|
||||
_t1_blks.items[lvl].nodes[idx] = { };
|
||||
_t1_node_states[lvl][idx] = node_state;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ft_initializer_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
_num_remaining_leaves = req._ft.num_leaves;
|
||||
for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++)
|
||||
_reset_level(lvl, DONE);
|
||||
|
||||
_t1_node_states[req._ft.max_lvl + 1][0] = INIT_BLOCK;
|
||||
_state = EXECUTE_NODES;
|
||||
progress = true;
|
||||
return;
|
||||
|
||||
case EXECUTE_NODES:
|
||||
|
||||
for (Tree_node_index node_idx = 0; node_idx < req._ft.degree; node_idx++)
|
||||
if (_execute_t2_node(node_idx, progress))
|
||||
return;
|
||||
|
||||
for (Tree_level_index lvl = 1; lvl <= req._ft.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx = 0; node_idx < req._ft.degree; node_idx++)
|
||||
if (_execute_t1_node(lvl, node_idx, progress))
|
||||
return;
|
||||
|
||||
if (_num_remaining_leaves)
|
||||
_mark_req_failed(progress, "leaves remaining");
|
||||
else
|
||||
_mark_req_successful(progress);
|
||||
return;
|
||||
|
||||
default: return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ft_initializer_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
Ft_initializer::Ft_initializer()
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++);
|
||||
add_channel(*chan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Ft_initializer::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
}
|
||||
|
@ -18,147 +18,132 @@
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/file.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Block_io; }
|
||||
|
||||
class Block_io;
|
||||
class Block_io_request;
|
||||
class Block_io_channel;
|
||||
}
|
||||
|
||||
class Tresor::Block_io_request : public Module_request
|
||||
{
|
||||
friend class Block_io_channel;
|
||||
|
||||
public:
|
||||
|
||||
enum Type { READ, WRITE, SYNC, READ_CLIENT_DATA, WRITE_CLIENT_DATA };
|
||||
|
||||
private:
|
||||
|
||||
Type const _type;
|
||||
Request_offset const _client_req_offset;
|
||||
Request_tag const _client_req_tag;
|
||||
Key_id const _key_id;
|
||||
Physical_block_address const _pba;
|
||||
Virtual_block_address const _vba;
|
||||
Block &_blk;
|
||||
Hash &_hash;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Block_io_request);
|
||||
|
||||
public:
|
||||
|
||||
Block_io_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Key_id,
|
||||
Physical_block_address, Virtual_block_address, Block &, Hash &, bool &);
|
||||
|
||||
static char const *type_to_string(Type);
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, type_to_string(_type), " pba ", _pba); }
|
||||
};
|
||||
|
||||
class Tresor::Block_io_channel : public Module_channel
|
||||
class Tresor::Block_io : Noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
using Request = Block_io_request;
|
||||
Vfs::Vfs_handle &_file;
|
||||
addr_t _user { };
|
||||
|
||||
enum State {
|
||||
REQ_SUBMITTED, REQ_COMPLETE, CIPHERTEXT_BLK_OBTAINED, PLAINTEXT_BLK_SUPPLIED, REQ_GENERATED,
|
||||
READ_OK, WRITE_OK, SYNC_OK, FILE_ERR };
|
||||
public:
|
||||
|
||||
State _state { REQ_COMPLETE };
|
||||
Block _blk { };
|
||||
bool _generated_req_success { false };
|
||||
Block_io_request *_req_ptr { };
|
||||
Vfs::Env &_vfs_env;
|
||||
Tresor::Path const _path;
|
||||
Read_write_file<State> _file { _state, _vfs_env, _path };
|
||||
class Read;
|
||||
class Write;
|
||||
class Sync;
|
||||
|
||||
NONCOPYABLE(Block_io_channel);
|
||||
Block_io(Vfs::Vfs_handle &file) : _file(file) { }
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint state, bool &progress, ARGS &&... args)
|
||||
template <typename REQ>
|
||||
bool execute(REQ &req)
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<REQUEST>(state, progress, args..., _generated_req_success);
|
||||
if (!_user)
|
||||
_user = (addr_t)&req;
|
||||
|
||||
if (_user != (addr_t)&req)
|
||||
return false;
|
||||
|
||||
bool progress = req.execute(_file);
|
||||
if (req.complete())
|
||||
_user = 0;
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
void _read(bool &);
|
||||
|
||||
void _write(bool &);
|
||||
|
||||
void _read_client_data(bool &);
|
||||
|
||||
void _write_client_data(bool &);
|
||||
|
||||
void _sync(bool &);
|
||||
|
||||
void _mark_req_failed(bool &, Error_string);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
public:
|
||||
|
||||
Block_io_channel(Module_channel_id, Vfs::Env &, Xml_node const &);
|
||||
|
||||
void execute(bool &);
|
||||
static constexpr char const *name() { return "block_io"; }
|
||||
};
|
||||
|
||||
class Tresor::Block_io : public Module
|
||||
class Tresor::Block_io::Read : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Block_io;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Physical_block_address const in_pba;
|
||||
Block &out_block;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
using Request = Block_io_request;
|
||||
using Channel = Block_io_channel;
|
||||
enum State { INIT, COMPLETE, READ, READ_OK, FILE_ERR };
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Block_io);
|
||||
Request_helper<Read, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
public:
|
||||
|
||||
struct Read : Request
|
||||
Read(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "read pba ", _attr.in_pba); }
|
||||
|
||||
bool execute(Vfs::Vfs_handle &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Block_io::Write : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Block_io;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Read(Module_id m, Module_channel_id c, Physical_block_address a, Block &b, bool &s)
|
||||
: Request(m, c, Request::READ, 0, 0, 0, a, 0, b, *(Hash*)0, s) { }
|
||||
Physical_block_address const in_pba;
|
||||
Block const &in_block;
|
||||
};
|
||||
|
||||
struct Write : Request
|
||||
{
|
||||
Write(Module_id m, Module_channel_id c, Physical_block_address a, Block const &b, bool &s)
|
||||
: Request(m, c, Request::WRITE, 0, 0, 0, a, 0, *const_cast<Block*>(&b), *(Hash*)0, s) { }
|
||||
};
|
||||
private:
|
||||
|
||||
struct Sync : Request
|
||||
{
|
||||
Sync(Module_id m, Module_channel_id c, bool &s)
|
||||
: Request(m, c, Request::SYNC, 0, 0, 0, 0, 0, *(Block*)0, *(Hash*)0, s) { }
|
||||
};
|
||||
enum State { INIT, COMPLETE, WRITE, WRITE_OK, FILE_ERR };
|
||||
|
||||
struct Write_client_data : Request
|
||||
{
|
||||
Write_client_data(Module_id m, Module_channel_id c, Physical_block_address p, Virtual_block_address v,
|
||||
Key_id k, Request_tag t, Request_offset o, Hash &h, bool &s)
|
||||
: Request(m, c, Request::WRITE_CLIENT_DATA, o, t, k, p, v, *(Block*)0, h, s) { }
|
||||
};
|
||||
Request_helper<Write, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
struct Read_client_data : Request
|
||||
{
|
||||
Read_client_data(Module_id m, Module_channel_id c, Physical_block_address p, Virtual_block_address v,
|
||||
Key_id k, Request_tag t, Request_offset o, Hash &h, bool &s)
|
||||
: Request(m, c, Request::READ_CLIENT_DATA, o, t, k, p, v, *(Block*)0, h, s) { }
|
||||
};
|
||||
public:
|
||||
|
||||
Block_io(Vfs::Env &, Xml_node const &);
|
||||
Write(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void execute(bool &) override;
|
||||
void print(Output &out) const { Genode::print(out, "write pba ", _attr.in_pba); }
|
||||
|
||||
bool execute(Vfs::Vfs_handle &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Block_io::Sync : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Block_io;
|
||||
|
||||
struct Attr { };
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, SYNC, SYNC_OK, FILE_ERR };
|
||||
|
||||
Request_helper<Sync, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
public:
|
||||
|
||||
Sync(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "sync"); }
|
||||
|
||||
bool execute(Vfs::Vfs_handle &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__BLOCK_IO_H_ */
|
||||
|
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* \brief Module that provides access to the client request data
|
||||
* \author Martin Stein
|
||||
* \date 2023-02-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _TRESOR__CLIENT_DATA_H_
|
||||
#define _TRESOR__CLIENT_DATA_H_
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
|
||||
namespace Tresor { class Client_data_request; }
|
||||
|
||||
namespace Vfs_tresor { class Client_data; }
|
||||
|
||||
namespace Tresor_tester { class Client_data; }
|
||||
|
||||
class Tresor::Client_data_request : public Module_request
|
||||
{
|
||||
friend class ::Vfs_tresor::Client_data;
|
||||
friend class ::Tresor_tester::Client_data;
|
||||
|
||||
public:
|
||||
|
||||
enum Type { OBTAIN_PLAINTEXT_BLK, SUPPLY_PLAINTEXT_BLK };
|
||||
|
||||
private:
|
||||
|
||||
Type const _type;
|
||||
Request_offset const _req_off;
|
||||
Request_tag const _req_tag;
|
||||
Physical_block_address const _pba;
|
||||
Virtual_block_address const _vba;
|
||||
Block &_blk;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Client_data_request);
|
||||
|
||||
public:
|
||||
|
||||
Client_data_request(Module_id src_mod_id, Module_channel_id src_chan_id, Type type,
|
||||
Request_offset req_off, Request_tag req_tag, Physical_block_address pba,
|
||||
Virtual_block_address vba, Block &blk, bool &success)
|
||||
:
|
||||
Module_request { src_mod_id, src_chan_id, CLIENT_DATA }, _type { type }, _req_off { req_off },
|
||||
_req_tag { req_tag }, _pba { pba }, _vba { vba }, _blk { blk }, _success { success }
|
||||
{ }
|
||||
|
||||
static char const *type_to_string(Type type)
|
||||
{
|
||||
switch (type) {
|
||||
case OBTAIN_PLAINTEXT_BLK: return "obtain_plaintext_blk";
|
||||
case SUPPLY_PLAINTEXT_BLK: return "supply_plaintext_blk";
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, type_to_string(_type)); }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__CLIENT_DATA_H_ */
|
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* \brief Interface for providing access to the client request data
|
||||
* \author Martin Stein
|
||||
* \date 2023-02-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _TRESOR__CLIENT_DATA_INTERFACE_H_
|
||||
#define _TRESOR__CLIENT_DATA_INTERFACE_H_
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
|
||||
namespace Tresor { class Client_data_interface; }
|
||||
|
||||
struct Tresor::Client_data_interface : Interface
|
||||
{
|
||||
struct Obtain_data_attr
|
||||
{
|
||||
Request_offset const in_req_off;
|
||||
Request_tag const in_req_tag;
|
||||
Physical_block_address const in_pba;
|
||||
Virtual_block_address const in_vba;
|
||||
Block &out_blk;
|
||||
};
|
||||
|
||||
virtual void obtain_data(Obtain_data_attr const &) = 0;
|
||||
|
||||
struct Supply_data_attr
|
||||
{
|
||||
Request_offset const in_req_off;
|
||||
Request_tag const in_req_tag;
|
||||
Physical_block_address const in_pba;
|
||||
Virtual_block_address const in_vba;
|
||||
Block const &in_blk;
|
||||
};
|
||||
|
||||
virtual void supply_data(Supply_data_attr const &) = 0;
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__CLIENT_DATA_INTERFACE_H_ */
|
@ -21,155 +21,187 @@
|
||||
namespace Tresor {
|
||||
|
||||
class Crypto;
|
||||
class Crypto_request;
|
||||
class Crypto_channel;
|
||||
class Crypto_key_files_interface;
|
||||
}
|
||||
|
||||
class Tresor::Crypto_request : public Module_request
|
||||
struct Tresor::Crypto_key_files_interface : Interface
|
||||
{
|
||||
friend class Crypto_channel;
|
||||
virtual void add_crypto_key(Key_id) = 0;
|
||||
|
||||
public:
|
||||
virtual void remove_crypto_key(Key_id) = 0;
|
||||
|
||||
enum Type { ADD_KEY, REMOVE_KEY, DECRYPT, ENCRYPT, DECRYPT_CLIENT_DATA, ENCRYPT_CLIENT_DATA };
|
||||
virtual Vfs::Vfs_handle &encrypt_file(Key_id) = 0;
|
||||
|
||||
private:
|
||||
|
||||
Type const _type;
|
||||
Request_offset const _client_req_offset;
|
||||
Request_tag const _client_req_tag;
|
||||
Physical_block_address const _pba;
|
||||
Virtual_block_address const _vba;
|
||||
Key_id const _key_id;
|
||||
Key_value const &_key_plaintext;
|
||||
Block &_blk;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Crypto_request);
|
||||
|
||||
public:
|
||||
|
||||
Crypto_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Key_id,
|
||||
Key_value const &, Physical_block_address, Virtual_block_address, Block &, bool &);
|
||||
|
||||
static const char *type_to_string(Type);
|
||||
|
||||
void print(Output &) const override;
|
||||
virtual Vfs::Vfs_handle &decrypt_file(Key_id) = 0;
|
||||
};
|
||||
|
||||
class Tresor::Crypto_channel : public Module_channel
|
||||
class Tresor::Crypto : Noncopyable
|
||||
{
|
||||
private:
|
||||
public:
|
||||
|
||||
using Request = Crypto_request;
|
||||
|
||||
enum State {
|
||||
REQ_SUBMITTED, REQ_COMPLETE, PLAINTEXT_BLK_OBTAINED, PLAINTEXT_BLK_SUPPLIED, REQ_GENERATED,
|
||||
READ_OK, WRITE_OK, FILE_ERR };
|
||||
|
||||
struct Key_directory
|
||||
struct Attr
|
||||
{
|
||||
Crypto_channel &chan;
|
||||
Key_id key_id;
|
||||
Read_write_file<State> encrypt_file { chan._state, chan._vfs_env, { chan._path, "/keys/", key_id, "/encrypt" } };
|
||||
Read_write_file<State> decrypt_file { chan._state, chan._vfs_env, { chan._path, "/keys/", key_id, "/decrypt" } };
|
||||
|
||||
NONCOPYABLE(Key_directory);
|
||||
|
||||
Key_directory(Crypto_channel &chan, Key_id key_id) : chan { chan }, key_id { key_id } { }
|
||||
Crypto_key_files_interface &key_files;
|
||||
Vfs::Vfs_handle &add_key_file;
|
||||
Vfs::Vfs_handle &remove_key_file;
|
||||
};
|
||||
|
||||
Vfs::Env &_vfs_env;
|
||||
Tresor::Path const _path;
|
||||
char _add_key_buf[sizeof(Key_id) + KEY_SIZE] { };
|
||||
Write_only_file<State> _add_key_file { _state, _vfs_env, { _path, "/add_key" } };
|
||||
Write_only_file<State> _remove_key_file { _state, _vfs_env, { _path, "/remove_key" } };
|
||||
Constructible<Key_directory> _key_dirs[2] { };
|
||||
State _state { REQ_COMPLETE };
|
||||
bool _generated_req_success { false };
|
||||
Block _blk { };
|
||||
Request *_req_ptr { };
|
||||
private:
|
||||
|
||||
NONCOPYABLE(Crypto_channel);
|
||||
Attr const _attr;
|
||||
addr_t _user { };
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
public:
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
class Encrypt;
|
||||
class Decrypt;
|
||||
class Add_key;
|
||||
class Remove_key;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
Crypto(Attr const &attr) : _attr(attr) { }
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint state, bool &progress, ARGS &&... args)
|
||||
template <typename REQ>
|
||||
bool execute(REQ &req)
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<REQUEST>(state, progress, args..., _generated_req_success);
|
||||
if (!_user)
|
||||
_user = (addr_t)&req;
|
||||
|
||||
if (_user != (addr_t)&req)
|
||||
return false;
|
||||
|
||||
bool progress = req.execute(_attr);
|
||||
if (req.complete())
|
||||
_user = 0;
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
void _add_key(bool &);
|
||||
|
||||
void _remove_key(bool &);
|
||||
|
||||
void _decrypt(bool &);
|
||||
|
||||
void _encrypt(bool &);
|
||||
|
||||
void _encrypt_client_data(bool &);
|
||||
|
||||
void _decrypt_client_data(bool &);
|
||||
|
||||
void _mark_req_failed(bool &, char const *);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
Constructible<Key_directory> &_key_dir(Key_id key_id);
|
||||
|
||||
public:
|
||||
|
||||
Crypto_channel(Module_channel_id, Vfs::Env &, Xml_node const &);
|
||||
|
||||
void execute(bool &);
|
||||
static constexpr char const *name() { return "crypto"; }
|
||||
};
|
||||
|
||||
class Tresor::Crypto : public Module
|
||||
class Tresor::Crypto::Encrypt : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Crypto;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Key_id const in_key_id;
|
||||
Physical_block_address const in_pba;
|
||||
Block &in_out_blk;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
using Request = Crypto_request;
|
||||
using Channel = Crypto_channel;
|
||||
enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR };
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Crypto);
|
||||
Request_helper<Encrypt, State> _helper;
|
||||
Attr const _attr;
|
||||
off_t _offset { };
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
public:
|
||||
|
||||
struct Add_key : Request
|
||||
Encrypt(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "encrypt pba ", _attr.in_pba); }
|
||||
|
||||
bool execute(Crypto::Attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Crypto::Decrypt : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Crypto;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Add_key(Module_id src_mod, Module_channel_id src_chan, Key &key, bool &succ)
|
||||
: Request(src_mod, src_chan, Request::ADD_KEY, 0, 0, key.id, key.value, 0, 0, *(Block*)0, succ) { }
|
||||
Key_id const in_key_id;
|
||||
Physical_block_address const in_pba;
|
||||
Block &in_out_blk;
|
||||
};
|
||||
|
||||
struct Remove_key : Request
|
||||
{
|
||||
Remove_key(Module_id src_mod, Module_channel_id src_chan, Key_id key, bool &succ)
|
||||
: Request(src_mod, src_chan, Request::REMOVE_KEY, 0, 0, key, *(Key_value*)0, 0, 0, *(Block*)0, succ) { }
|
||||
};
|
||||
private:
|
||||
|
||||
struct Decrypt : Request
|
||||
{
|
||||
Decrypt(Module_id src_mod, Module_channel_id src_chan, Key_id key, Physical_block_address pba, Block &blk, bool &succ)
|
||||
: Request(src_mod, src_chan, Request::DECRYPT, 0, 0, key, *(Key_value*)0, pba, 0, blk, succ) { }
|
||||
};
|
||||
enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR };
|
||||
|
||||
struct Encrypt : Request
|
||||
{
|
||||
Encrypt(Module_id src_mod, Module_channel_id src_chan, Key_id key, Physical_block_address pba, Block &blk, bool &succ)
|
||||
: Request(src_mod, src_chan, Request::ENCRYPT, 0, 0, key, *(Key_value*)0, pba, 0, blk, succ) { }
|
||||
};
|
||||
Request_helper<Decrypt, State> _helper;
|
||||
Attr const _attr;
|
||||
off_t _offset { };
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
Crypto(Vfs::Env &, Xml_node const &);
|
||||
public:
|
||||
|
||||
void execute(bool &) override;
|
||||
Decrypt(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "decrypt pba ", _attr.in_pba); }
|
||||
|
||||
bool execute(Crypto::Attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Crypto::Add_key : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Crypto;
|
||||
|
||||
struct Attr { Key const &in_key; };
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, WRITE, WRITE_OK, FILE_ERR };
|
||||
|
||||
Request_helper<Add_key, State> _helper;
|
||||
Attr const _attr;
|
||||
char _write_buf[sizeof(Key_id) + sizeof(Key_value)] { };
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
public:
|
||||
|
||||
Add_key(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "add key id ", _attr.in_key.id); }
|
||||
|
||||
bool execute(Crypto::Attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Crypto::Remove_key : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Crypto;
|
||||
|
||||
struct Attr { Key_id const in_key_id; };
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, WRITE, WRITE_OK, FILE_ERR };
|
||||
|
||||
Request_helper<Remove_key, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
public:
|
||||
|
||||
Remove_key(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "remove key id ", _attr.in_key_id); }
|
||||
|
||||
bool execute(Crypto::Attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__CRYPTO_H_ */
|
||||
|
@ -33,8 +33,17 @@ namespace Tresor {
|
||||
template <typename> class File;
|
||||
template <typename> class Read_write_file;
|
||||
template <typename> class Write_only_file;
|
||||
|
||||
inline Vfs::Vfs_handle &open_file(Vfs::Env &env, Tresor::Path const &path, Vfs::Directory_service::Open_mode mode)
|
||||
{
|
||||
using Open_result = Vfs::Directory_service::Open_result;
|
||||
Vfs::Vfs_handle *handle { nullptr };
|
||||
ASSERT(env.root_dir().open(path.string(), mode, &handle, env.alloc()) == Open_result::OPEN_OK);
|
||||
return *handle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template <typename HOST_STATE>
|
||||
class Tresor::File
|
||||
{
|
||||
@ -43,34 +52,34 @@ class Tresor::File
|
||||
using Read_result = Vfs::File_io_service::Read_result;
|
||||
using Write_result = Vfs::File_io_service::Write_result;
|
||||
using Sync_result = Vfs::File_io_service::Sync_result;
|
||||
using Open_result = Vfs::Directory_service::Open_result;
|
||||
|
||||
enum State { IDLE, SYNC_QUEUED, READ_QUEUED, READ_INITIALIZED, WRITE_INITIALIZED, WRITE_OFFSET_APPLIED };
|
||||
|
||||
Vfs::Env &_env;
|
||||
Vfs::Env *_env { };
|
||||
Tresor::Path const *_path { };
|
||||
HOST_STATE &_host_state;
|
||||
State _state { IDLE };
|
||||
Vfs::Vfs_handle &_handle;
|
||||
Vfs::file_size _num_processed_bytes { 0 };
|
||||
|
||||
Vfs::Vfs_handle &_open(Tresor::Path path, Vfs::Directory_service::Open_mode mode)
|
||||
{
|
||||
Vfs::Vfs_handle *handle { nullptr };
|
||||
ASSERT(_env.root_dir().open(path.string(), mode, &handle, _env.alloc()) == Open_result::OPEN_OK);
|
||||
return *handle;
|
||||
}
|
||||
/*
|
||||
* Noncopyable
|
||||
*/
|
||||
File(File const &) = delete;
|
||||
File &operator = (File const &) = delete;
|
||||
|
||||
public:
|
||||
|
||||
File(HOST_STATE &host_state, Vfs::Vfs_handle &handle) : _host_state { host_state }, _handle { handle } { }
|
||||
File(HOST_STATE &host_state, Vfs::Vfs_handle &handle) : _host_state(host_state), _handle(handle) { }
|
||||
|
||||
File(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path path, Vfs::Directory_service::Open_mode mode)
|
||||
: _env { env }, _host_state { host_state }, _handle { _open(path, mode) } { }
|
||||
File(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path const &path, Vfs::Directory_service::Open_mode mode)
|
||||
: _env(&env), _path(&path), _host_state(host_state), _handle(open_file(*_env, *_path, mode)) { }
|
||||
|
||||
~File()
|
||||
{
|
||||
ASSERT(_state == IDLE);
|
||||
_env.root_dir().close(&_handle);
|
||||
if (_env)
|
||||
_env->root_dir().close(&_handle);
|
||||
}
|
||||
|
||||
void read(HOST_STATE succeeded, HOST_STATE failed, Vfs::file_offset off, Byte_range_ptr dst, bool &progress)
|
||||
@ -116,7 +125,7 @@ class Tresor::File
|
||||
|
||||
default:
|
||||
|
||||
error("read failed");
|
||||
error("file: read failed");
|
||||
_host_state = failed;
|
||||
_state = IDLE;
|
||||
progress = true;
|
||||
@ -167,7 +176,7 @@ class Tresor::File
|
||||
|
||||
default:
|
||||
|
||||
error("write failed");
|
||||
error("file: write failed");
|
||||
_host_state = failed;
|
||||
_state = IDLE;
|
||||
progress = true;
|
||||
@ -204,7 +213,7 @@ class Tresor::File
|
||||
|
||||
default:
|
||||
|
||||
error("sync failed");
|
||||
error("file: sync failed");
|
||||
_host_state = failed;
|
||||
_state = IDLE;
|
||||
progress = true;
|
||||
@ -218,15 +227,15 @@ class Tresor::File
|
||||
template <typename HOST_STATE>
|
||||
struct Tresor::Read_write_file : public File<HOST_STATE>
|
||||
{
|
||||
Read_write_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path path)
|
||||
: File<HOST_STATE> { host_state, env, path, Vfs::Directory_service::OPEN_MODE_RDWR } { }
|
||||
Read_write_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path const &path)
|
||||
: File<HOST_STATE>(host_state, env, path, Vfs::Directory_service::OPEN_MODE_RDWR) { }
|
||||
};
|
||||
|
||||
template <typename HOST_STATE>
|
||||
struct Tresor::Write_only_file : public File<HOST_STATE>
|
||||
{
|
||||
Write_only_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path path)
|
||||
: File<HOST_STATE> { host_state, env, path, Vfs::Directory_service::OPEN_MODE_WRONLY } { }
|
||||
Write_only_file(HOST_STATE &host_state, Vfs::Env &env, Tresor::Path const &path)
|
||||
: File<HOST_STATE>(host_state, env, path, Vfs::Directory_service::OPEN_MODE_WRONLY) { }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__FILE_H_ */
|
||||
|
@ -16,80 +16,68 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/meta_tree.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Free_tree; }
|
||||
|
||||
class Free_tree;
|
||||
class Free_tree_request;
|
||||
class Free_tree_channel;
|
||||
}
|
||||
|
||||
class Tresor::Free_tree_request : public Module_request
|
||||
class Tresor::Free_tree : Noncopyable
|
||||
{
|
||||
friend class Free_tree_channel;
|
||||
|
||||
public:
|
||||
|
||||
enum Type { ALLOC_FOR_NON_RKG, ALLOC_FOR_RKG_CURR_GEN_BLKS, ALLOC_FOR_RKG_OLD_GEN_BLKS, EXTENSION_STEP };
|
||||
class Allocate_pbas;
|
||||
class Extend_tree;
|
||||
|
||||
private:
|
||||
template <typename REQUEST>
|
||||
bool execute(REQUEST &req, Block_io &block_io, Meta_tree &meta_tree) { return req.execute(block_io, meta_tree); }
|
||||
|
||||
Type const _type;
|
||||
Tree_root &_ft;
|
||||
Tree_root &_mt;
|
||||
Generation const _curr_gen;
|
||||
Generation const _free_gen;
|
||||
Number_of_blocks const _num_required_pbas;
|
||||
Tree_walk_pbas &_new_blocks;
|
||||
Type_1_node_walk const &_old_blocks;
|
||||
Tree_level_index const _max_lvl;
|
||||
Virtual_block_address const _vba;
|
||||
Tree_degree const _vbd_degree;
|
||||
Virtual_block_address const _vbd_max_vba;
|
||||
bool const _rekeying;
|
||||
Key_id const _prev_key_id;
|
||||
Key_id const _curr_key_id;
|
||||
Virtual_block_address const _rekeying_vba;
|
||||
bool &_success;
|
||||
Snapshots const &_snapshots;
|
||||
Generation const _last_secured_gen;
|
||||
Physical_block_address &_pba;
|
||||
Number_of_blocks &_num_pbas;
|
||||
|
||||
NONCOPYABLE(Free_tree_request);
|
||||
|
||||
public:
|
||||
|
||||
Free_tree_request(Module_id, Module_channel_id, Type, Tree_root &, Tree_root &, Snapshots const &,
|
||||
Generation, Generation, Generation, Number_of_blocks, Tree_walk_pbas &, Type_1_node_walk const &,
|
||||
Tree_level_index, Virtual_block_address, Tree_degree, Virtual_block_address,
|
||||
bool, Key_id, Key_id, Virtual_block_address, Physical_block_address &, Number_of_blocks &, bool &);
|
||||
|
||||
static char const *type_to_string(Type);
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, type_to_string(_type)); }
|
||||
static constexpr char const *name() { return "free_tree"; }
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Free_tree_channel : public Module_channel
|
||||
class Tresor::Free_tree::Allocate_pbas : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Free_tree;
|
||||
|
||||
enum Application { NON_REKEYING, REKEYING_IN_CURRENT_GENERATION, REKEYING_IN_OLDER_GENERATION };
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Tree_root &in_out_ft;
|
||||
Tree_root &in_out_mt;
|
||||
Snapshots const &in_snapshots;
|
||||
Generation const in_last_secured_gen;
|
||||
Generation const in_curr_gen;
|
||||
Generation const in_free_gen;
|
||||
Number_of_blocks const in_num_required_pbas;
|
||||
Tree_walk_pbas &in_out_new_blocks;
|
||||
Type_1_node_walk const &in_old_blocks;
|
||||
Tree_level_index const in_max_lvl;
|
||||
Virtual_block_address const in_vba;
|
||||
Tree_degree const in_vbd_degree;
|
||||
Virtual_block_address const in_vbd_max_vba;
|
||||
bool const in_rekeying;
|
||||
Key_id const in_prev_key_id;
|
||||
Key_id const in_curr_key_id;
|
||||
Virtual_block_address const in_rekeying_vba;
|
||||
Application const in_application;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
using Request = Free_tree_request;
|
||||
|
||||
enum State {
|
||||
REQ_SUBMITTED, REQ_GENERATED, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, READ_BLK_SUCCEEDED,
|
||||
ALLOC_PBA_SUCCEEDED, WRITE_BLK_SUCCEEDED, REQ_COMPLETE };
|
||||
INIT, COMPLETE, SEEK_DOWN, SEEK_LEFT_OR_UP, READ_BLK, READ_BLK_SUCCEEDED,
|
||||
ALLOC_PBA, ALLOC_PBA_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED };
|
||||
|
||||
Request *_req_ptr { nullptr };
|
||||
State _state { REQ_COMPLETE };
|
||||
using Helper = Request_helper<Allocate_pbas, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Virtual_block_address _vba { };
|
||||
Tree_walk_pbas _old_pbas { };
|
||||
Tree_walk_pbas _new_pbas { };
|
||||
Tree_walk_generations _old_generations { };
|
||||
Number_of_leaves _num_leaves { 0 };
|
||||
Physical_block_address _alloc_pba { 0 };
|
||||
Tree_level_index _alloc_lvl { 0 };
|
||||
Number_of_blocks _num_pbas { 0 };
|
||||
Block _blk { };
|
||||
Tree_node_index _node_idx[TREE_MAX_NR_OF_LEVELS] { };
|
||||
@ -98,36 +86,71 @@ class Tresor::Free_tree_channel : public Module_channel
|
||||
Type_2_node_block _t2_blk { };
|
||||
Tree_degree_log_2 _vbd_degree_log_2 { 0 };
|
||||
Tree_level_index _lvl { 0 };
|
||||
bool _generated_req_success { false };
|
||||
|
||||
NONCOPYABLE(Free_tree_channel);
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint state, bool &progress, ARGS &&... args)
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<REQUEST>(state, progress, args..., _generated_req_success);
|
||||
}
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
void _mark_req_failed(bool &, char const *);
|
||||
|
||||
bool _can_alloc_pba_of(Type_2_node &);
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
Generatable_request<Helper, State, Meta_tree::Allocate_pba> _allocate_pba { };
|
||||
|
||||
void _alloc_pba_of(Type_2_node &);
|
||||
|
||||
void _traverse_curr_node(bool &);
|
||||
bool _can_alloc_pba_of(Type_2_node &);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
void _traverse_curr_node(bool &);
|
||||
|
||||
void _start_tree_traversal(bool &);
|
||||
|
||||
void _advance_to_next_node();
|
||||
public:
|
||||
|
||||
Allocate_pbas(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Allocate_pbas() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "allocate pbas"); }
|
||||
|
||||
bool execute(Block_io &, Meta_tree &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Free_tree::Extend_tree : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Free_tree;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Generation const in_curr_gen;
|
||||
Tree_root &in_out_ft;
|
||||
Tree_root &in_out_mt;
|
||||
Physical_block_address &in_out_first_pba;
|
||||
Number_of_blocks &in_out_num_pbas;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, ALLOC_PBA, ALLOC_PBA_SUCCEEDED, WRITE_BLK,
|
||||
WRITE_BLK_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Extend_tree, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Number_of_leaves _num_leaves { 0 };
|
||||
Virtual_block_address _vba { };
|
||||
Tree_walk_pbas _old_pbas { };
|
||||
Tree_walk_generations _old_generations { };
|
||||
Tree_walk_pbas _new_pbas { };
|
||||
Tree_level_index _lvl { 0 };
|
||||
Block _blk { };
|
||||
Type_1_node_block _t1_blks[TREE_MAX_NR_OF_LEVELS] { };
|
||||
Type_2_node_block _t2_blk { };
|
||||
Tree_level_index _alloc_lvl { 0 };
|
||||
Physical_block_address _alloc_pba { 0 };
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
Generatable_request<Helper, State, Meta_tree::Allocate_pba> _allocate_pba { };
|
||||
|
||||
void _add_new_branch_at(Tree_level_index, Tree_node_index);
|
||||
|
||||
@ -135,41 +158,18 @@ class Tresor::Free_tree_channel : public Module_channel
|
||||
|
||||
void _generate_write_blk_req(bool &);
|
||||
|
||||
void _extension_step(bool &);
|
||||
|
||||
void _alloc_pbas(bool &);
|
||||
|
||||
public:
|
||||
|
||||
Free_tree_channel(Module_channel_id id) : Module_channel { FREE_TREE, id } { }
|
||||
Extend_tree(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
~Extend_tree() { }
|
||||
|
||||
class Tresor::Free_tree : public Module
|
||||
{
|
||||
private:
|
||||
void print(Output &out) const { Genode::print(out, "extend tree"); }
|
||||
|
||||
using Channel = Free_tree_channel;
|
||||
using Request = Free_tree_request;
|
||||
bool execute(Block_io &, Meta_tree &);
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Free_tree);
|
||||
|
||||
void execute(bool &) override;
|
||||
|
||||
public:
|
||||
|
||||
struct Extension_step : Request
|
||||
{
|
||||
Extension_step(Module_id mod_id, Module_channel_id chan_id, Generation curr_gen, Tree_root &ft, Tree_root &mt,
|
||||
Physical_block_address &pba, Number_of_blocks &num_pbas, bool &succ)
|
||||
: Request(mod_id, chan_id, Request::EXTENSION_STEP, ft, mt, *(Snapshots *)0, 0, curr_gen, 0, 0, *(Tree_walk_pbas*)0,
|
||||
*(Type_1_node_walk*)0, 0, 0, 0, 0, 0, 0, 0, 0, pba, num_pbas, succ) { }
|
||||
};
|
||||
|
||||
Free_tree();
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__FREE_TREE_H_ */
|
||||
|
@ -16,95 +16,54 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/block_io.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Ft_check; }
|
||||
|
||||
class Ft_check;
|
||||
class Ft_check_request;
|
||||
class Ft_check_channel;
|
||||
}
|
||||
|
||||
|
||||
class Tresor::Ft_check_request : public Module_request
|
||||
struct Tresor::Ft_check : Noncopyable
|
||||
{
|
||||
friend class Ft_check_channel;
|
||||
class Check : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
private:
|
||||
using Module = Ft_check;
|
||||
|
||||
Tree_root const &_ft;
|
||||
bool &_success;
|
||||
struct Attr { Tree_root const &in_ft; };
|
||||
|
||||
NONCOPYABLE(Ft_check_request);
|
||||
private:
|
||||
|
||||
public:
|
||||
enum State { INIT, IN_PROGRESS, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED };
|
||||
|
||||
Ft_check_request(Module_id, Module_channel_id, Tree_root const &, bool &);
|
||||
using Helper = Request_helper<Check, State>;
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, "check ", _ft); }
|
||||
};
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Type_2_node_block _t2_blk { };
|
||||
bool _check_node[TREE_MAX_NR_OF_LEVELS + 1][NUM_NODES_PER_BLK] { };
|
||||
Number_of_leaves _num_remaining_leaves { 0 };
|
||||
Block _blk { };
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
|
||||
bool _execute_node(Block_io &, Tree_level_index, Tree_node_index, bool &);
|
||||
|
||||
class Tresor::Ft_check_channel : public Module_channel
|
||||
{
|
||||
private:
|
||||
public:
|
||||
|
||||
using Request = Ft_check_request;
|
||||
Check(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
enum State : State_uint { REQ_SUBMITTED, REQ_IN_PROGRESS, REQ_COMPLETE, REQ_GENERATED, READ_BLK_SUCCEEDED };
|
||||
void print(Output &out) const { Genode::print(out, "check ", _attr.in_ft); }
|
||||
|
||||
State _state { REQ_COMPLETE };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Type_2_node_block _t2_blk { };
|
||||
bool _check_node[TREE_MAX_NR_OF_LEVELS + 1][NUM_NODES_PER_BLK] { };
|
||||
Number_of_leaves _num_remaining_leaves { 0 };
|
||||
Request *_req_ptr { };
|
||||
Block _blk { };
|
||||
bool _generated_req_success { false };
|
||||
bool execute(Block_io &);
|
||||
|
||||
NONCOPYABLE(Ft_check_channel);
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
Ft_check() { }
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
bool execute(Check &req, Block_io &block_io) { return req.execute(block_io); }
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
void _mark_req_failed(bool &, Error_string);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
bool _execute_node(Tree_level_index, Tree_node_index, bool &);
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint state, bool &progress, ARGS &&... args)
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<REQUEST>(state, progress, args..., _generated_req_success);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Ft_check_channel(Module_channel_id id) : Module_channel { FT_CHECK, id } { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Ft_check : public Module
|
||||
{
|
||||
private:
|
||||
|
||||
using Channel = Ft_check_channel;
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Ft_check);
|
||||
|
||||
public:
|
||||
|
||||
Ft_check();
|
||||
|
||||
void execute(bool &) override;
|
||||
static constexpr char const *name() { return "ft_check"; }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__FT_CHECK_H_ */
|
||||
|
@ -17,97 +17,68 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/block_io.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Ft_initializer; }
|
||||
|
||||
class Ft_initializer;
|
||||
class Ft_initializer_request;
|
||||
class Ft_initializer_channel;
|
||||
}
|
||||
|
||||
|
||||
class Tresor::Ft_initializer_request : public Module_request
|
||||
class Tresor::Ft_initializer : Noncopyable
|
||||
{
|
||||
friend class Ft_initializer_channel;
|
||||
|
||||
private:
|
||||
|
||||
Tree_root &_ft;
|
||||
Pba_allocator &_pba_alloc;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Ft_initializer_request);
|
||||
|
||||
public:
|
||||
|
||||
Ft_initializer_request(Module_id, Module_channel_id, Tree_root &, Pba_allocator &, bool &);
|
||||
class Initialize : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, "init"); }
|
||||
};
|
||||
using Module = Ft_initializer;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Tree_configuration const in_tree_cfg;
|
||||
Type_1_node &out_tree_root;
|
||||
Pba_allocator &in_out_pba_alloc;
|
||||
};
|
||||
|
||||
class Tresor::Ft_initializer_channel : public Module_channel
|
||||
{
|
||||
private:
|
||||
private:
|
||||
|
||||
using Request = Ft_initializer_request;
|
||||
enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITING_BLOCK };
|
||||
|
||||
enum State { REQ_GENERATED, REQ_SUBMITTED, EXECUTE_NODES, REQ_COMPLETE };
|
||||
enum State { INIT, COMPLETE, EXECUTE_NODES, WRITE_BLOCK };
|
||||
|
||||
enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLK };
|
||||
using Helper = Request_helper<Initialize, State>;
|
||||
|
||||
State _state { REQ_COMPLETE };
|
||||
Request *_req_ptr { };
|
||||
Type_2_node_block _t2_blk { };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Node_state _t1_node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { };
|
||||
Node_state _t2_node_states[NUM_NODES_PER_BLK] { };
|
||||
Number_of_leaves _num_remaining_leaves { 0 };
|
||||
bool _generated_req_success { false };
|
||||
Block _blk { };
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Type_2_node_block _t2_blk { };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Node_state _t1_node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { };
|
||||
Node_state _t2_node_states[NUM_NODES_PER_BLK] { };
|
||||
Number_of_leaves _num_remaining_leaves { 0 };
|
||||
Block _blk { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
|
||||
NONCOPYABLE(Ft_initializer_channel);
|
||||
void _reset_level(Tree_level_index, Node_state);
|
||||
|
||||
void _reset_level(Tree_level_index, Node_state);
|
||||
bool _execute_t2_node(Tree_node_index, bool &);
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
bool _execute_t1_node(Tree_level_index, Tree_node_index, bool &);
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
public:
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
Initialize(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
bool _execute_t2_node(Tree_node_index, bool &);
|
||||
~Initialize() { }
|
||||
|
||||
bool _execute_t1_node(Tree_level_index, Tree_node_index, bool &);
|
||||
void print(Output &out) const { Genode::print(out, "initialize"); }
|
||||
|
||||
void _mark_req_failed(bool &, char const *);
|
||||
bool execute(Block_io &);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
public:
|
||||
|
||||
Ft_initializer_channel(Module_channel_id id) : Module_channel { FT_INITIALIZER, id } { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Ft_initializer : public Module
|
||||
{
|
||||
private:
|
||||
|
||||
using Channel = Ft_initializer_channel;
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Ft_initializer);
|
||||
|
||||
public:
|
||||
|
||||
Ft_initializer();
|
||||
|
||||
void execute(bool &) override;
|
||||
bool execute(Initialize &req, Block_io &block_io) { return req.execute(block_io); }
|
||||
|
||||
static constexpr char const *name() { return "ft_initializer"; }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__FT_INITIALIZER_H_ */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Module for doing VBD COW allocations on the meta tree
|
||||
* \brief Module for doing PBA allocations for the Free Tree via the Meta Tree
|
||||
* \author Martin Stein
|
||||
* \date 2023-02-13
|
||||
*/
|
||||
@ -16,74 +16,49 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/block_io.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Meta_tree; }
|
||||
|
||||
class Meta_tree;
|
||||
class Meta_tree_request;
|
||||
class Meta_tree_channel;
|
||||
}
|
||||
|
||||
class Tresor::Meta_tree_request : public Module_request
|
||||
class Tresor::Meta_tree : Noncopyable
|
||||
{
|
||||
friend class Meta_tree_channel;
|
||||
|
||||
public:
|
||||
|
||||
enum Type { ALLOC_PBA };
|
||||
class Allocate_pba;
|
||||
|
||||
private:
|
||||
bool execute(Allocate_pba &, Block_io &);
|
||||
|
||||
Type const _type;
|
||||
Tree_root &_mt;
|
||||
Generation const _curr_gen;
|
||||
Physical_block_address &_pba;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Meta_tree_request);
|
||||
|
||||
public:
|
||||
|
||||
Meta_tree_request(Module_id, Module_channel_id, Type, Tree_root &, Generation, Physical_block_address &, bool &);
|
||||
|
||||
static char const *type_to_string(Type);
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, type_to_string(_type)); }
|
||||
static constexpr char const *name() { return "meta_tree"; }
|
||||
};
|
||||
|
||||
class Tresor::Meta_tree_channel : public Module_channel
|
||||
class Tresor::Meta_tree::Allocate_pba : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Meta_tree;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Tree_root &in_out_mt;
|
||||
Generation const in_curr_gen;
|
||||
Physical_block_address &in_out_pba;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
using Request = Meta_tree_request;
|
||||
enum State { INIT, COMPLETE, READ_BLK, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, WRITE_BLK_SUCCEEDED };
|
||||
|
||||
enum State { REQ_SUBMITTED, REQ_GENERATED, SEEK_DOWN, SEEK_LEFT_OR_UP, WRITE_BLK, COMPLETE };
|
||||
using Helper = Request_helper<Allocate_pba, State>;
|
||||
|
||||
State _state { COMPLETE };
|
||||
Request *_req_ptr { nullptr };
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Block _blk { };
|
||||
Tree_node_index _node_idx[TREE_MAX_NR_OF_LEVELS] { };
|
||||
Type_1_node_block _t1_blks[TREE_MAX_NR_OF_LEVELS] { };
|
||||
Type_2_node_block _t2_blk { };
|
||||
Tree_level_index _lvl { 0 };
|
||||
bool _generated_req_success { false };
|
||||
|
||||
NONCOPYABLE(Meta_tree_channel);
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint state, bool &progress, ARGS &&... args)
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<REQUEST>(state, progress, args..., _generated_req_success);
|
||||
}
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
|
||||
bool _request_complete() override { return _state == COMPLETE; }
|
||||
|
||||
void _mark_req_failed(bool &, char const *);
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
|
||||
bool _can_alloc_pba_of(Type_2_node &);
|
||||
|
||||
@ -91,38 +66,20 @@ class Tresor::Meta_tree_channel : public Module_channel
|
||||
|
||||
void _traverse_curr_node(bool &);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
void _start_tree_traversal(bool &);
|
||||
|
||||
public:
|
||||
|
||||
Meta_tree_channel(Module_channel_id id) : Module_channel { META_TREE, id } { }
|
||||
Allocate_pba(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
~Allocate_pba() { }
|
||||
|
||||
class Tresor::Meta_tree : public Module
|
||||
{
|
||||
private:
|
||||
void print(Output &out) const { Genode::print(out, "allocate pba"); }
|
||||
|
||||
using Channel = Meta_tree_channel;
|
||||
bool execute(Block_io &);
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Meta_tree);
|
||||
|
||||
void execute(bool &) override;
|
||||
|
||||
public:
|
||||
|
||||
struct Alloc_pba : Meta_tree_request
|
||||
{
|
||||
Alloc_pba(Module_id src_mod, Module_channel_id src_chan, Tree_root &mt, Generation gen, Physical_block_address &pba, bool &succ)
|
||||
: Meta_tree_request(src_mod, src_chan, Meta_tree_request::ALLOC_PBA, mt, gen, pba, succ) { }
|
||||
};
|
||||
|
||||
Meta_tree();
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__META_TREE_H_ */
|
||||
|
@ -1,223 +0,0 @@
|
||||
/*
|
||||
* \brief Framework for component internal modularization
|
||||
* \author Martin Stein
|
||||
* \date 2023-02-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _TRESOR__MODULE_H_
|
||||
#define _TRESOR__MODULE_H_
|
||||
|
||||
/* base includes */
|
||||
#include <util/avl_tree.h>
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/verbosity.h>
|
||||
#include <tresor/noncopyable.h>
|
||||
#include <tresor/assertion.h>
|
||||
|
||||
namespace Tresor {
|
||||
|
||||
using namespace Genode;
|
||||
|
||||
using Module_id = uint64_t;
|
||||
using Module_channel_id = uint64_t;
|
||||
|
||||
enum { INVALID_MODULE_ID = ~(Module_id)0, INVALID_MODULE_CHANNEL_ID = ~(Module_channel_id)0 };
|
||||
|
||||
enum Module_id_enum : Module_id {
|
||||
CRYPTO = 0, CLIENT_DATA = 1, TRUST_ANCHOR = 2, COMMAND_POOL = 3, BLOCK_IO = 4, CACHE = 5, META_TREE = 6,
|
||||
FREE_TREE = 7, VIRTUAL_BLOCK_DEVICE = 8, SUPERBLOCK_CONTROL = 9, VBD_INITIALIZER = 10, FT_INITIALIZER = 11,
|
||||
SB_INITIALIZER = 12, REQUEST_POOL = 13, SB_CHECK = 14, VBD_CHECK = 15, FT_CHECK = 16, SPLITTER = 17, MAX_MODULE_ID = 17 };
|
||||
|
||||
char const *module_name(Module_id module_id);
|
||||
|
||||
class Module_request;
|
||||
class Module_channel;
|
||||
class Module;
|
||||
class Module_composition;
|
||||
}
|
||||
|
||||
|
||||
class Tresor::Module_request : public Interface
|
||||
{
|
||||
private:
|
||||
|
||||
Module_id _src_module_id;
|
||||
Module_channel_id _src_chan_id;
|
||||
Module_id _dst_module_id;
|
||||
Module_channel_id _dst_chan_id { INVALID_MODULE_CHANNEL_ID };
|
||||
|
||||
NONCOPYABLE(Module_request);
|
||||
|
||||
public:
|
||||
|
||||
Module_request(Module_id, Module_channel_id, Module_id);
|
||||
|
||||
void dst_chan_id(Module_channel_id id) { _dst_chan_id = id; }
|
||||
|
||||
Module_id src_module_id() const { return _src_module_id; }
|
||||
Module_channel_id src_chan_id() const { return _src_chan_id; }
|
||||
Module_id dst_module_id() const { return _dst_module_id; }
|
||||
Module_channel_id dst_chan_id() const { return _dst_chan_id; }
|
||||
|
||||
virtual void print(Output &) const = 0;
|
||||
|
||||
virtual ~Module_request() { }
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Module_channel : private Avl_node<Module_channel>
|
||||
{
|
||||
friend class Module;
|
||||
friend class Avl_node<Module_channel>;
|
||||
friend class Avl_tree<Module_channel>;
|
||||
|
||||
public:
|
||||
|
||||
using State_uint = uint64_t;
|
||||
|
||||
private:
|
||||
|
||||
enum { GEN_REQ_BUF_SIZE = 4000 };
|
||||
|
||||
enum Generated_request_state { NONE, PENDING, IN_PROGRESS };
|
||||
|
||||
Module_request *_req_ptr { nullptr };
|
||||
Module_id _module_id;
|
||||
Module_channel_id _id;
|
||||
Generated_request_state _gen_req_state { NONE };
|
||||
uint8_t _gen_req_buf[GEN_REQ_BUF_SIZE] { };
|
||||
State_uint _gen_req_complete_state { 0 };
|
||||
|
||||
NONCOPYABLE(Module_channel);
|
||||
|
||||
bool higher(Module_channel *ptr) { return ptr->_id > _id; }
|
||||
|
||||
virtual void _generated_req_completed(State_uint) { ASSERT_NEVER_REACHED; }
|
||||
|
||||
virtual void _request_submitted(Module_request &) { ASSERT_NEVER_REACHED; }
|
||||
|
||||
virtual bool _request_complete() { ASSERT_NEVER_REACHED; }
|
||||
|
||||
public:
|
||||
|
||||
Module_channel(Module_id module_id, Module_channel_id id) : _module_id { module_id }, _id { id } { };
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void generate_req(State_uint complete_state, bool &progress, ARGS &&... args)
|
||||
{
|
||||
ASSERT(_gen_req_state == NONE);
|
||||
static_assert(sizeof(REQUEST) <= GEN_REQ_BUF_SIZE);
|
||||
construct_at<REQUEST>(_gen_req_buf, _module_id, _id, args...);
|
||||
_gen_req_state = PENDING;
|
||||
_gen_req_complete_state = complete_state;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
template <typename CHAN, typename FUNC>
|
||||
void with_channel(Module_channel_id id, FUNC && func)
|
||||
{
|
||||
if (id != _id) {
|
||||
Module_channel *chan_ptr { Avl_node<Module_channel>::child(id > _id) };
|
||||
ASSERT(chan_ptr);
|
||||
chan_ptr->with_channel<CHAN>(id, func);
|
||||
} else
|
||||
func(*static_cast<CHAN *>(this));
|
||||
}
|
||||
|
||||
void generated_req_completed();
|
||||
|
||||
bool try_submit_request(Module_request &);
|
||||
|
||||
Module_channel_id id() const { return _id; }
|
||||
|
||||
virtual ~Module_channel() { }
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Module : public Interface
|
||||
{
|
||||
private:
|
||||
|
||||
Avl_tree<Module_channel> _channels { };
|
||||
|
||||
NONCOPYABLE(Module);
|
||||
|
||||
public:
|
||||
|
||||
template <typename CHAN = Module_channel, typename FUNC>
|
||||
void with_channel(Module_channel_id id, FUNC && func)
|
||||
{
|
||||
ASSERT(_channels.first());
|
||||
_channels.first()->with_channel<CHAN>(id, func);
|
||||
}
|
||||
|
||||
template <typename CHAN = Module_channel, typename FUNC>
|
||||
void for_each_channel(FUNC && func)
|
||||
{
|
||||
_channels.for_each([&] (Module_channel const &const_chan) {
|
||||
func(*static_cast<CHAN *>(const_cast<Module_channel *>(&const_chan))); });
|
||||
}
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each_generated_request(FUNC && handle_request)
|
||||
{
|
||||
for_each_channel([&] (Module_channel &chan) {
|
||||
if (chan._gen_req_state != Module_channel::PENDING)
|
||||
return;
|
||||
|
||||
Module_request &req = *(Module_request *)chan._gen_req_buf;
|
||||
if (handle_request(req)) {
|
||||
chan._gen_req_state = Module_channel::IN_PROGRESS;
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
template <typename FUNC>
|
||||
void for_each_completed_request(FUNC && handle_request)
|
||||
{
|
||||
for_each_channel([&] (Module_channel &chan) {
|
||||
if (chan._req_ptr && chan._request_complete()) {
|
||||
handle_request(*chan._req_ptr);
|
||||
chan._req_ptr = nullptr;
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
bool try_submit_request(Module_request &);
|
||||
|
||||
void add_channel(Module_channel &chan) { _channels.insert(&chan); }
|
||||
|
||||
Module() { }
|
||||
|
||||
virtual ~Module() { }
|
||||
|
||||
virtual void execute(bool &) { }
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Module_composition
|
||||
{
|
||||
private:
|
||||
|
||||
Module *_module_ptrs[MAX_MODULE_ID + 1] { };
|
||||
|
||||
public:
|
||||
|
||||
void add_module(Module_id module_id, Module &mod);
|
||||
|
||||
void remove_module(Module_id module_id);
|
||||
|
||||
void execute_modules();
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__MODULE_H_ */
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* \brief Macro to make a class non-copyable
|
||||
* \author Martin Stein
|
||||
* \date 2023-06-09
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _TRESOR__NONCOPYABLE_H_
|
||||
#define _TRESOR__NONCOPYABLE_H_
|
||||
|
||||
#define NONCOPYABLE(class_name) \
|
||||
class_name(class_name const &) = delete; \
|
||||
class_name &operator = (class_name const &) = delete; \
|
||||
|
||||
#endif /* _TRESOR__NONCOPYABLE_H_ */
|
@ -1,180 +0,0 @@
|
||||
/*
|
||||
* \brief Module for scheduling requests for processing
|
||||
* \author Martin Stein
|
||||
* \date 2023-03-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
#ifndef _TRESOR__REQUEST_POOL_H_
|
||||
#define _TRESOR__REQUEST_POOL_H_
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/superblock_control.h>
|
||||
|
||||
namespace Tresor {
|
||||
|
||||
class Request;
|
||||
class Request_pool;
|
||||
class Request_pool_channel;
|
||||
class Request_pool_channel_queue;
|
||||
}
|
||||
|
||||
class Tresor::Request : public Module_request
|
||||
{
|
||||
NONCOPYABLE(Request);
|
||||
|
||||
friend class Request_pool_channel;
|
||||
|
||||
public:
|
||||
|
||||
enum Operation {
|
||||
READ, WRITE, SYNC, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, REKEY, EXTEND_VBD,
|
||||
EXTEND_FT, RESUME_REKEYING, DEINITIALIZE, INITIALIZE, };
|
||||
|
||||
private:
|
||||
|
||||
Operation _op;
|
||||
Virtual_block_address const _vba;
|
||||
Request_offset const _offset;
|
||||
Number_of_blocks const _count;
|
||||
Key_id const _key_id;
|
||||
Request_tag const _tag;
|
||||
Generation &_gen;
|
||||
bool &_success;
|
||||
|
||||
public:
|
||||
|
||||
static char const *op_to_string(Operation);
|
||||
|
||||
Request(Module_id, Module_channel_id, Operation, Virtual_block_address, Request_offset,
|
||||
Number_of_blocks, Key_id, Request_tag, Generation &, bool &);
|
||||
|
||||
void print(Output &) const override;
|
||||
};
|
||||
|
||||
class Tresor::Request_pool_channel : public Module_channel
|
||||
{
|
||||
private:
|
||||
|
||||
enum State : State_uint {
|
||||
INVALID, REQ_SUBMITTED, REQ_RESUMED, REQ_GENERATED, REKEY_INIT_SUCCEEDED, PREPONED_REQUESTS_COMPLETE,
|
||||
TREE_EXTENSION_STEP_SUCCEEDED, FORWARD_TO_SB_CTRL_SUCCEEDED, ACCESS_VBA_AT_SB_CTRL_SUCCEEDED,
|
||||
REKEY_VBA_SUCCEEDED, INITIALIZE_SB_CTRL_SUCCEEDED, DEINITIALIZE_SB_CTRL_SUCCEEDED, REQ_COMPLETE };
|
||||
|
||||
State _state { INVALID };
|
||||
Number_of_blocks _num_blks { 0 };
|
||||
Superblock::State _sb_state { Superblock::INVALID };
|
||||
uint32_t _num_requests_preponed { 0 };
|
||||
bool _request_finished { false };
|
||||
bool _generated_req_success { false };
|
||||
Request_pool_channel_queue &_chan_queue;
|
||||
Request *_req_ptr { nullptr };
|
||||
|
||||
NONCOPYABLE(Request_pool_channel);
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
|
||||
void _request_submitted(Module_request &req) override;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
void _access_vbas(bool &, Superblock_control_request::Type);
|
||||
|
||||
void _forward_to_sb_ctrl(bool &, Superblock_control_request::Type);
|
||||
|
||||
void _gen_sb_control_req(bool &, Superblock_control_request::Type, State, Virtual_block_address);
|
||||
|
||||
void _rekey(bool &);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
void _reset();
|
||||
|
||||
void _try_prepone_requests(bool &);
|
||||
|
||||
void _extend_tree(Superblock_control_request::Type, bool &);
|
||||
|
||||
void _initialize(bool &);
|
||||
|
||||
void _resume_request(bool &, Request::Operation);
|
||||
|
||||
public:
|
||||
|
||||
Request_pool_channel(Module_channel_id id, Request_pool_channel_queue &chan_queue) : Module_channel { REQUEST_POOL, id }, _chan_queue { chan_queue } { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Request_pool_channel_queue
|
||||
{
|
||||
NONCOPYABLE(Request_pool_channel_queue);
|
||||
|
||||
public:
|
||||
|
||||
enum { NUM_SLOTS = 16 };
|
||||
|
||||
private:
|
||||
|
||||
using Channel = Request_pool_channel;
|
||||
using Slot_index = uint64_t;
|
||||
using Number_of_slots = uint64_t;
|
||||
|
||||
Slot_index _head { 0 };
|
||||
Slot_index _tail { 0 };
|
||||
Number_of_slots _num_used_slots { 0 };
|
||||
Channel *_slots[NUM_SLOTS] { 0 };
|
||||
|
||||
public:
|
||||
|
||||
Request_pool_channel_queue() { }
|
||||
|
||||
bool empty() const { return _num_used_slots == 0; }
|
||||
|
||||
bool full() const { return _num_used_slots >= NUM_SLOTS; }
|
||||
|
||||
Channel &head() const;
|
||||
|
||||
void enqueue(Channel &);
|
||||
|
||||
void move_one_slot_towards_tail(Channel const &);
|
||||
|
||||
bool is_tail(Channel const &) const;
|
||||
|
||||
Channel &next(Channel const &) const;
|
||||
|
||||
void dequeue(Channel const &);
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Request_pool : public Module
|
||||
{
|
||||
NONCOPYABLE(Request_pool);
|
||||
|
||||
private:
|
||||
|
||||
using Channel = Request_pool_channel;
|
||||
|
||||
enum { NUM_CHANNELS = Request_pool_channel_queue::NUM_SLOTS };
|
||||
|
||||
bool _init_success { false };
|
||||
Generation _init_gen { INVALID_GENERATION };
|
||||
Request _init_req { INVALID_MODULE_ID, INVALID_MODULE_CHANNEL_ID, Request::INITIALIZE, 0, 0, 0, 0, 0, _init_gen, _init_success };
|
||||
Constructible<Channel> _channels[NUM_CHANNELS] { };
|
||||
Request_pool_channel_queue _chan_queue { };
|
||||
|
||||
public:
|
||||
|
||||
void execute(bool &) override;
|
||||
|
||||
Request_pool();
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__REQUEST_POOL_H_ */
|
@ -16,95 +16,60 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/vbd_check.h>
|
||||
#include <tresor/ft_check.h>
|
||||
#include <tresor/block_io.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Sb_check; }
|
||||
|
||||
class Sb_check;
|
||||
class Sb_check_request;
|
||||
class Sb_check_channel;
|
||||
}
|
||||
|
||||
|
||||
class Tresor::Sb_check_request : public Module_request
|
||||
struct Tresor::Sb_check : Noncopyable
|
||||
{
|
||||
friend class Sb_check_channel;
|
||||
class Check : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
private:
|
||||
using Module = Sb_check;
|
||||
|
||||
bool &_success;
|
||||
private:
|
||||
|
||||
NONCOPYABLE(Sb_check_request);
|
||||
enum State {
|
||||
INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, CHECK_VBD, CHECK_VBD_SUCCEEDED, CHECK_FT, CHECK_FT_SUCCEEDED,
|
||||
CHECK_MT, CHECK_MT_SUCCEEDED};
|
||||
|
||||
public:
|
||||
using Helper = Request_helper<Check, State>;
|
||||
|
||||
Sb_check_request(Module_id, Module_channel_id, bool &);
|
||||
Helper _helper;
|
||||
Generation _highest_gen { 0 };
|
||||
Superblock_index _highest_gen_sb_idx { 0 };
|
||||
bool _scan_for_highest_gen_sb_done { false };
|
||||
Superblock_index _sb_idx { 0 };
|
||||
Superblock _sb { };
|
||||
Snapshot_index _snap_idx { 0 };
|
||||
Constructible<Tree_root> _tree_root { };
|
||||
Block _blk { };
|
||||
Generatable_request<Helper, State, Vbd_check::Check> _check_vbd { };
|
||||
Generatable_request<Helper, State, Ft_check::Check> _check_ft { };
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, "check"); }
|
||||
};
|
||||
public:
|
||||
|
||||
Check() : _helper(*this) { }
|
||||
|
||||
class Tresor::Sb_check_channel : public Module_channel
|
||||
{
|
||||
private:
|
||||
~Check() { }
|
||||
|
||||
using Request = Sb_check_request;
|
||||
void print(Output &out) const { Genode::print(out, "check"); }
|
||||
|
||||
enum State { REQ_SUBMITTED, REQ_COMPLETE, READ_BLK_SUCCESSFUL, REQ_GENERATED, CHECK_VBD_SUCCESSFUL, CHECK_FT_SUCCESSFUL, CHECK_MT_SUCCESSFUL};
|
||||
bool execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io);
|
||||
|
||||
State _state { REQ_COMPLETE };
|
||||
Request *_req_ptr { };
|
||||
Generation _highest_gen { 0 };
|
||||
Superblock_index _highest_gen_sb_idx { 0 };
|
||||
bool _scan_for_highest_gen_sb_done { false };
|
||||
Superblock_index _sb_idx { 0 };
|
||||
Superblock _sb { };
|
||||
Snapshot_index _snap_idx { 0 };
|
||||
Constructible<Tree_root> _tree_root { };
|
||||
Block _blk { };
|
||||
bool _generated_req_success { false };
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
NONCOPYABLE(Sb_check_channel);
|
||||
Sb_check() { }
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
bool execute(Check &check, Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io) { return check.execute(vbd_check, ft_check, block_io); };
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint state, bool &progress, ARGS &&... args)
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<REQUEST>(state, progress, args..., _generated_req_success);
|
||||
}
|
||||
|
||||
void _mark_req_failed(bool &, char const *);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
public:
|
||||
|
||||
Sb_check_channel(Module_channel_id id) : Module_channel { SB_CHECK, id } { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Sb_check : public Module
|
||||
{
|
||||
private:
|
||||
|
||||
using Channel = Sb_check_channel;
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Sb_check);
|
||||
|
||||
public:
|
||||
|
||||
Sb_check();
|
||||
|
||||
void execute(bool &) override;
|
||||
static constexpr char const *name() { return "sb_check"; }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__SB_CHECK_H_ */
|
||||
|
@ -17,107 +17,78 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/vbd_initializer.h>
|
||||
#include <tresor/ft_initializer.h>
|
||||
#include <tresor/trust_anchor.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Sb_initializer; }
|
||||
|
||||
class Sb_initializer;
|
||||
class Sb_initializer_request;
|
||||
class Sb_initializer_channel;
|
||||
}
|
||||
|
||||
|
||||
class Tresor::Sb_initializer_request : public Module_request
|
||||
class Tresor::Sb_initializer : Noncopyable
|
||||
{
|
||||
friend class Sb_initializer_channel;
|
||||
|
||||
private:
|
||||
|
||||
Tree_level_index _vbd_max_lvl;
|
||||
Tree_degree _vbd_degree;
|
||||
Number_of_leaves _vbd_num_leaves;
|
||||
Tree_level_index _ft_max_lvl;
|
||||
Tree_degree _ft_degree;
|
||||
Number_of_leaves _ft_num_leaves;
|
||||
Tree_level_index _mt_max_lvl;
|
||||
Tree_degree _mt_degree;
|
||||
Number_of_leaves _mt_num_leaves;
|
||||
Pba_allocator &_pba_alloc;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Sb_initializer_request);
|
||||
|
||||
public:
|
||||
|
||||
Sb_initializer_request(Module_id, Module_channel_id, Tree_level_index, Tree_degree, Number_of_leaves,
|
||||
Tree_level_index, Tree_degree, Number_of_leaves, Tree_level_index, Tree_degree,
|
||||
Number_of_leaves, Pba_allocator &, bool &);
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, "init"); }
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Sb_initializer_channel : public Module_channel
|
||||
{
|
||||
private:
|
||||
|
||||
using Request = Sb_initializer_request;
|
||||
|
||||
enum State {
|
||||
REQ_SUBMITTED, START_NEXT_SB, SB_COMPLETE, REQ_COMPLETE, INIT_FT_SUCCEEDED, INIT_MT_SUCCEEDED,
|
||||
WRITE_HASH_TO_TA, CREATE_KEY_SUCCEEDED, ENCRYPT_KEY_SUCCEEDED, SECURE_SB_SUCCEEDED, INIT_VBD_SUCCEEDED,
|
||||
WRITE_BLK_SUCCEEDED, REQ_GENERATED };
|
||||
|
||||
State _state { REQ_COMPLETE };
|
||||
Request *_req_ptr { };
|
||||
Superblock_index _sb_idx { 0 };
|
||||
Superblock _sb { };
|
||||
Block _blk { };
|
||||
Hash _hash { };
|
||||
Constructible<Tree_root> _vbd { };
|
||||
Constructible<Tree_root> _mt { };
|
||||
Constructible<Tree_root> _ft { };
|
||||
bool _generated_req_success { false };
|
||||
|
||||
NONCOPYABLE(Sb_initializer_channel);
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint state, bool &progress, ARGS &&... args)
|
||||
class Initialize : Noncopyable
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<REQUEST>(state, progress, args..., _generated_req_success);
|
||||
public:
|
||||
|
||||
using Module = Sb_initializer;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Tree_configuration const in_vbd_cfg;
|
||||
Tree_configuration const in_ft_cfg;
|
||||
Tree_configuration const in_mt_cfg;
|
||||
Pba_allocator &in_out_pba_alloc;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
INIT, COMPLETE, START_NEXT_SB, SB_COMPLETE, INIT_FT, INIT_FT_SUCCEEDED, INIT_MT_SUCCEEDED,
|
||||
WRITE_HASH_TO_TA, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, ENCRYPT_KEY, ENCRYPT_KEY_SUCCEEDED,
|
||||
SECURE_SB_SUCCEEDED, INIT_VBD, INIT_VBD_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED,
|
||||
SYNC_BLOCK_IO, WRITE_SB_HASH };
|
||||
|
||||
using Helper = Request_helper<Initialize, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Superblock_index _sb_idx { 0 };
|
||||
Superblock _sb { };
|
||||
Block _blk { };
|
||||
Hash _hash { };
|
||||
Type_1_node _vbd_root { };
|
||||
Type_1_node _ft_root { };
|
||||
Type_1_node _mt_root { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
Generatable_request<Helper, State, Block_io::Sync> _sync_block_io { };
|
||||
Generatable_request<Helper, State, Trust_anchor::Generate_key> _generate_key { };
|
||||
Generatable_request<Helper, State, Trust_anchor::Write_hash> _write_sb_hash { };
|
||||
Generatable_request<Helper, State, Trust_anchor::Encrypt_key> _encrypt_key { };
|
||||
Generatable_request<Helper, State, Ft_initializer::Initialize> _init_ft { };
|
||||
Generatable_request<Helper, State, Vbd_initializer::Initialize> _init_vbd { };
|
||||
|
||||
public:
|
||||
|
||||
Initialize(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Initialize() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "initialize"); }
|
||||
|
||||
bool execute(Block_io &, Trust_anchor &, Vbd_initializer &, Ft_initializer &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
bool execute(Initialize &req, Block_io &block_io, Trust_anchor &trust_anchor, Vbd_initializer &vbd_initializer, Ft_initializer &ft_initializer)
|
||||
{
|
||||
return req.execute(block_io, trust_anchor, vbd_initializer, ft_initializer);
|
||||
}
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
public:
|
||||
|
||||
Sb_initializer_channel(Module_channel_id id) : Module_channel { SB_INITIALIZER, id } { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Sb_initializer : public Module
|
||||
{
|
||||
private:
|
||||
|
||||
using Channel = Sb_initializer_channel;
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Sb_initializer);
|
||||
|
||||
public:
|
||||
|
||||
Sb_initializer();
|
||||
|
||||
void execute(bool &) override;
|
||||
static constexpr char const *name() { return "sb_initializer"; }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__SB_INITIALIZER_H_ */
|
||||
|
@ -20,153 +20,558 @@
|
||||
#include <tresor/trust_anchor.h>
|
||||
#include <tresor/block_io.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Superblock_control; }
|
||||
|
||||
class Superblock_control;
|
||||
class Superblock_control_request;
|
||||
class Superblock_control_channel;
|
||||
}
|
||||
|
||||
class Tresor::Superblock_control_request : Module_request, Noncopyable
|
||||
{
|
||||
friend class Superblock_control_channel;
|
||||
|
||||
public:
|
||||
|
||||
enum Type {
|
||||
READ_VBA, WRITE_VBA, SYNC, INITIALIZE, DEINITIALIZE, VBD_EXTENSION_STEP,
|
||||
FT_EXTENSION_STEP, CREATE_SNAPSHOT, DISCARD_SNAPSHOT, INITIALIZE_REKEYING,
|
||||
REKEY_VBA };
|
||||
|
||||
private:
|
||||
|
||||
Type const _type;
|
||||
Request_offset const _client_req_offset;
|
||||
Request_tag const _client_req_tag;
|
||||
Number_of_blocks _nr_of_blks;
|
||||
Virtual_block_address const _vba;
|
||||
bool &_success;
|
||||
bool &_client_req_finished;
|
||||
Superblock::State &_sb_state;
|
||||
Generation &_gen;
|
||||
|
||||
public:
|
||||
|
||||
Superblock_control_request(Module_id, Module_channel_id, Type, Request_offset,
|
||||
Request_tag, Number_of_blocks, Virtual_block_address,
|
||||
bool &, bool &, Superblock::State &, Generation &);
|
||||
|
||||
static char const *type_to_string(Type);
|
||||
|
||||
void print(Output &) const override;
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Superblock_control_channel : public Module_channel
|
||||
class Tresor::Superblock_control : Noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
using Request = Superblock_control_request;
|
||||
|
||||
enum State : State_uint {
|
||||
INACTIVE, REQ_SUBMITTED, ACCESS_VBA_AT_VBD_SUCCEEDED,
|
||||
REKEY_VBA_AT_VBD_SUCCEEDED, CREATE_KEY_SUCCEEDED,
|
||||
TREE_EXT_STEP_IN_TREE_SUCCEEDED, DECRYPT_CURR_KEY_SUCCEEDED,
|
||||
DECRYPT_PREV_KEY_SUCCEEDED, READ_SB_HASH_SUCCEEDED, ADD_PREV_KEY_SUCCEEDED,
|
||||
ADD_CURR_KEY_SUCCEEDED, REMOVE_PREV_KEY_SUCCEEDED, REMOVE_CURR_KEY_SUCCEEDED,
|
||||
READ_SB_SUCCEEDED, REQ_COMPLETE, REQ_GENERATED, SECURE_SB, SECURE_SB_SUCCEEDED };
|
||||
|
||||
enum Secure_sb_state : State_uint {
|
||||
SECURE_SB_INACTIVE, STARTED, ENCRYPT_CURR_KEY_SUCCEEDED,
|
||||
SECURE_SB_REQ_GENERATED, ENCRYPT_PREV_KEY_SUCCEEDED, SYNC_CACHE_SUCCEEDED,
|
||||
WRITE_SB_SUCCEEDED, SYNC_BLK_IO_SUCCEEDED, WRITE_SB_HASH_SUCCEEDED };
|
||||
|
||||
State _state { INACTIVE };
|
||||
Constructible<Tree_root> _ft { };
|
||||
Constructible<Tree_root> _mt { };
|
||||
Secure_sb_state _secure_sb_state { SECURE_SB_INACTIVE };
|
||||
Superblock _sb_ciphertext { };
|
||||
Block _blk { };
|
||||
Generation _gen { INVALID_GENERATION };
|
||||
Hash _hash { };
|
||||
Physical_block_address _pba { INVALID_PBA };
|
||||
Number_of_blocks _nr_of_leaves { 0 };
|
||||
Request *_req_ptr { nullptr };
|
||||
bool _gen_req_success { false };
|
||||
Superblock &_sb;
|
||||
Superblock_index &_sb_idx;
|
||||
Generation &_curr_gen;
|
||||
|
||||
NONCOPYABLE(Superblock_control_channel);
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
void _mark_req_failed(bool &, char const *);
|
||||
|
||||
void _access_vba(Virtual_block_device_request::Type, bool &);
|
||||
|
||||
void _generate_vbd_req(Virtual_block_device_request::Type, State_uint, bool &, Key_id, Virtual_block_address);
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint complete_state, bool &progress, ARGS &&... args)
|
||||
class Secure_superblock : Noncopyable
|
||||
{
|
||||
generate_req<REQUEST>(complete_state, progress, args..., _gen_req_success);
|
||||
if (_state == SECURE_SB)
|
||||
_secure_sb_state = SECURE_SB_REQ_GENERATED;
|
||||
else
|
||||
_state = REQ_GENERATED;
|
||||
}
|
||||
public:
|
||||
|
||||
void _start_secure_sb(bool &);
|
||||
using Module = Superblock_control;
|
||||
|
||||
void _secure_sb(bool &);
|
||||
struct Attr { };
|
||||
|
||||
void _tree_ext_step(Superblock::State, bool, String<4>, bool &);
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock &sb;
|
||||
Superblock_index &sb_idx;
|
||||
Generation &curr_gen;
|
||||
Block_io &block_io;
|
||||
Trust_anchor &trust_anchor;
|
||||
};
|
||||
|
||||
void _rekey_vba(bool &);
|
||||
private:
|
||||
|
||||
void _init_rekeying(bool &);
|
||||
enum State {
|
||||
INIT, COMPLETE, WRITE_BLOCK, WRITE_BLOCK_SUCCEEDED, SYNC_BLOCK_IO, SYNC_BLOCK_IO_SUCCEEDED,
|
||||
ENCRYPT_KEY, ENCRYPT_CURR_KEY_SUCCEEDED, ENCRYPT_PREV_KEY_SUCCEEDED, WRITE_SB_HASH,
|
||||
WRITE_SB_HASH_SUCCEEDED };
|
||||
|
||||
void _discard_snap(bool &);
|
||||
using Helper = Request_helper<Secure_superblock, State>;
|
||||
|
||||
void _create_snap(bool &);
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Superblock _sb_ciphertext { };
|
||||
Block _blk { };
|
||||
Hash _hash { };
|
||||
Generation _gen { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
Generatable_request<Helper, State, Block_io::Sync> _sync_block_io { };
|
||||
Generatable_request<Helper, State, Trust_anchor::Encrypt_key> _encrypt_key { };
|
||||
Generatable_request<Helper, State, Trust_anchor::Write_hash> _write_sb_hash { };
|
||||
|
||||
void _sync(bool &);
|
||||
public:
|
||||
|
||||
void _initialize(bool &);
|
||||
Secure_superblock(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void _deinitialize(bool &);
|
||||
~Secure_superblock() { }
|
||||
|
||||
public:
|
||||
void print(Output &out) const { Genode::print(out, "secure sb"); }
|
||||
|
||||
void execute(bool &);
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
Superblock_control_channel(Module_channel_id, Superblock &, Superblock_index &, Generation &);
|
||||
};
|
||||
|
||||
class Tresor::Superblock_control : public Module
|
||||
{
|
||||
private:
|
||||
|
||||
using Channel = Superblock_control_channel;
|
||||
|
||||
enum { NUM_CHANNELS = 1 };
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
Superblock _sb { };
|
||||
Superblock_index _sb_idx { INVALID_SB_IDX };
|
||||
Generation _curr_gen { INVALID_GENERATION };
|
||||
Constructible<Channel> _channels[NUM_CHANNELS] { };
|
||||
|
||||
void execute(bool &) override;
|
||||
Superblock_index _sb_idx { };
|
||||
Generation _curr_gen { };
|
||||
|
||||
public:
|
||||
|
||||
class Write_vbas : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Virtual_block_address const in_first_vba;
|
||||
Number_of_blocks const in_num_vbas;
|
||||
Request_offset const in_client_req_offset;
|
||||
Request_tag const in_client_req_tag;
|
||||
};
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Virtual_block_device &vbd;
|
||||
Client_data_interface &client_data;
|
||||
Block_io &block_io;
|
||||
Free_tree &free_tree;
|
||||
Meta_tree &meta_tree;
|
||||
Crypto &crypto;
|
||||
Superblock &sb;
|
||||
Generation const &curr_gen;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, WRITE_VBA, WRITE_VBA_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Write_vbas, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Number_of_blocks _num_written_vbas { };
|
||||
Constructible<Tree_root> _ft { };
|
||||
Constructible<Tree_root> _mt { };
|
||||
Generatable_request<Helper, State, Virtual_block_device::Write_vba> _write_vba { };
|
||||
|
||||
void _start_write_vba(Execute_attr const &, bool &);
|
||||
|
||||
public:
|
||||
|
||||
Write_vbas(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Write_vbas() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "write vba"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Extend_free_tree : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Number_of_blocks const in_num_pbas;
|
||||
bool &out_extension_finished;
|
||||
};
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock_control &sb_control;
|
||||
Free_tree &free_tree;
|
||||
Meta_tree &meta_tree;
|
||||
Block_io &block_io;
|
||||
Trust_anchor &trust_anchor;
|
||||
Superblock &sb;
|
||||
Generation const &curr_gen;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, EXTEND_FREE_TREE, EXTEND_FREE_TREE_SUCCEEDED, SECURE_SB, SECURE_SB_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Extend_free_tree, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Number_of_blocks _num_pbas { };
|
||||
Physical_block_address _pba { };
|
||||
Number_of_blocks _nr_of_leaves { };
|
||||
Constructible<Tree_root> _ft { };
|
||||
Constructible<Tree_root> _mt { };
|
||||
Generatable_request<Helper, State, Secure_superblock> _secure_sb { };
|
||||
Generatable_request<Helper, State, Free_tree::Extend_tree> _extend_free_tree { };
|
||||
|
||||
public:
|
||||
|
||||
Extend_free_tree(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Extend_free_tree() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "rekey vba"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Extend_vbd : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Number_of_blocks const in_num_pbas;
|
||||
bool &out_extension_finished;
|
||||
};
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock_control &sb_control;
|
||||
Virtual_block_device &vbd;
|
||||
Free_tree &free_tree;
|
||||
Meta_tree &meta_tree;
|
||||
Block_io &block_io;
|
||||
Trust_anchor &trust_anchor;
|
||||
Superblock &sb;
|
||||
Generation const &curr_gen;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, EXTEND_VBD, EXTEND_VBD_SUCCEEDED, SECURE_SB, SECURE_SB_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Extend_vbd, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Number_of_blocks _num_pbas { };
|
||||
Physical_block_address _pba { };
|
||||
Number_of_blocks _nr_of_leaves { };
|
||||
Constructible<Tree_root> _ft { };
|
||||
Constructible<Tree_root> _mt { };
|
||||
Generatable_request<Helper, State, Secure_superblock> _secure_sb { };
|
||||
Generatable_request<Helper, State, Virtual_block_device::Extend_tree> _extend_vbd { };
|
||||
|
||||
public:
|
||||
|
||||
Extend_vbd(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Extend_vbd() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "extend vbd"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Rekey : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr { bool &out_rekeying_finished; };
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock &sb;
|
||||
Generation const &curr_gen;
|
||||
Block_io &block_io;
|
||||
Crypto &crypto;
|
||||
Trust_anchor &trust_anchor;
|
||||
Free_tree &free_tree;
|
||||
Meta_tree &meta_tree;
|
||||
Virtual_block_device &vbd;
|
||||
Superblock_control &sb_control;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
INIT, COMPLETE, REKEY_VBA, REKEY_VBA_SUCCEEDED, SECURE_SB, SECURE_SB_SUCCEEDED, REMOVE_KEY,
|
||||
REMOVE_KEY_SUCCEEDED, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, ADD_KEY, ADD_KEY_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Rekey, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Constructible<Tree_root> _ft { };
|
||||
Constructible<Tree_root> _mt { };
|
||||
Generation _gen { };
|
||||
Generatable_request<Helper, State, Virtual_block_device::Rekey_vba> _rekey_vba { };
|
||||
Generatable_request<Helper, State, Crypto::Remove_key> _remove_key { };
|
||||
Generatable_request<Helper, State, Secure_superblock> _secure_sb { };
|
||||
Generatable_request<Helper, State, Crypto::Add_key> _add_key { };
|
||||
Generatable_request<Helper, State, Trust_anchor::Generate_key> _generate_key { };
|
||||
|
||||
public:
|
||||
|
||||
Rekey(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Rekey() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "continue rekeying"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Read_vbas : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Virtual_block_address const in_first_vba;
|
||||
Number_of_blocks const in_num_vbas;
|
||||
Request_offset const in_client_req_offset;
|
||||
Request_tag const in_client_req_tag;
|
||||
};
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Virtual_block_device &vbd;
|
||||
Client_data_interface &client_data;
|
||||
Block_io &block_io;
|
||||
Crypto &crypto;
|
||||
Superblock const &sb;
|
||||
Generation const &curr_gen;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, READ_VBA, READ_VBA_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Read_vbas, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Number_of_blocks _num_read_vbas { };
|
||||
Generatable_request<Helper, State, Virtual_block_device::Read_vba> _read_vba { };
|
||||
|
||||
void _start_read_vba(Execute_attr const &, bool &progress);
|
||||
|
||||
public:
|
||||
|
||||
Read_vbas(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Read_vbas() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "read vbas"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Create_snapshot : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr { Generation &out_gen; };
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock &sb;
|
||||
Generation &curr_gen;
|
||||
Block_io &block_io;
|
||||
Trust_anchor &trust_anchor;
|
||||
Superblock_control &sb_control;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Create_snapshot, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Generation _gen { };
|
||||
Generatable_request<Helper, State, Secure_superblock> _secure_sb { };
|
||||
|
||||
public:
|
||||
|
||||
Create_snapshot(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Create_snapshot() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "create snapshot"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Synchronize : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr { };
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock &sb;
|
||||
Generation const &curr_gen;
|
||||
Block_io &block_io;
|
||||
Trust_anchor &trust_anchor;
|
||||
Superblock_control &sb_control;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Synchronize, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Generatable_request<Helper, State, Secure_superblock> _secure_sb { };
|
||||
|
||||
public:
|
||||
|
||||
Synchronize(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Synchronize() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "sync"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Deinitialize : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr { };
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock &sb;
|
||||
Generation const &curr_gen;
|
||||
Block_io &block_io;
|
||||
Crypto &crypto;
|
||||
Trust_anchor &trust_anchor;
|
||||
Superblock_control &sb_control;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED, REMOVE_KEY,
|
||||
REMOVE_CURR_KEY_SUCCEEDED, REMOVE_PREV_KEY_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Deinitialize, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Generatable_request<Helper, State, Secure_superblock> _secure_sb { };
|
||||
Generatable_request<Helper, State, Crypto::Remove_key> _remove_key { };
|
||||
|
||||
public:
|
||||
|
||||
Deinitialize(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Deinitialize() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "deinitialize"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Initialize : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr { Superblock::State &out_sb_state; };
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock &sb;
|
||||
Superblock_index &sb_idx;
|
||||
Generation &curr_gen;
|
||||
Block_io &block_io;
|
||||
Crypto &crypto;
|
||||
Trust_anchor &trust_anchor;
|
||||
Superblock_control &sb_control;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
INIT, COMPLETE, READ_SB_HASH, READ_SB_HASH_SUCCEEDED, READ_BLOCK, READ_BLOCK_SUCCEEDED,
|
||||
DECRYPT_KEY, DECRYPT_CURR_KEY_SUCCEEDED, DECRYPT_PREV_KEY_SUCCEEDED, ADD_KEY,
|
||||
ADD_CURR_KEY_SUCCEEDED, ADD_PREV_KEY_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Initialize, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Generation _gen { };
|
||||
Hash _hash { };
|
||||
Block _blk { };
|
||||
Superblock _sb_ciphertext { };
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
Generatable_request<Helper, State, Trust_anchor::Read_hash> _read_sb_hash { };
|
||||
Generatable_request<Helper, State, Trust_anchor::Decrypt_key> _decrypt_key { };
|
||||
Generatable_request<Helper, State, Crypto::Add_key> _add_key { };
|
||||
|
||||
public:
|
||||
|
||||
Initialize(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Initialize() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "initialize"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Discard_snapshot : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Superblock_control;
|
||||
|
||||
struct Attr { Generation const in_gen; };
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock &sb;
|
||||
Generation &curr_gen;
|
||||
Block_io &block_io;
|
||||
Trust_anchor &trust_anchor;
|
||||
Superblock_control &sb_control;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, SECURE_SB, SECURE_SB_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Discard_snapshot, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Generatable_request<Helper, State, Secure_superblock> _secure_sb { };
|
||||
|
||||
public:
|
||||
|
||||
Discard_snapshot(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Discard_snapshot() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "discard snapshot"); }
|
||||
|
||||
bool execute(Execute_attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
Virtual_block_address max_vba() const { return _sb.valid() ? _sb.max_vba() : 0; };
|
||||
|
||||
Virtual_block_address resizing_nr_of_pbas() const { return _sb.resizing_nr_of_pbas; }
|
||||
@ -177,7 +582,62 @@ class Tresor::Superblock_control : public Module
|
||||
|
||||
Superblock_info sb_info() const;
|
||||
|
||||
Superblock_control();
|
||||
bool execute(Extend_free_tree &req, Free_tree &free_tree, Meta_tree &meta_tree, Block_io &block_io, Trust_anchor &trust_anchor)
|
||||
{
|
||||
return req.execute({ *this, free_tree, meta_tree, block_io, trust_anchor, _sb, _curr_gen });
|
||||
}
|
||||
|
||||
bool execute(Extend_vbd &req, Virtual_block_device &vbd, Free_tree &free_tree, Meta_tree &meta_tree, Block_io &block_io, Trust_anchor &trust_anchor)
|
||||
{
|
||||
return req.execute({ *this, vbd, free_tree, meta_tree, block_io, trust_anchor, _sb, _curr_gen });
|
||||
}
|
||||
|
||||
bool execute(Rekey &req, Virtual_block_device &vbd, Free_tree &free_tree, Meta_tree &meta_tree, Block_io &block_io, Crypto &crypto, Trust_anchor &trust_anchor)
|
||||
{
|
||||
return req.execute({ _sb, _curr_gen, block_io, crypto, trust_anchor, free_tree, meta_tree, vbd, *this });
|
||||
}
|
||||
|
||||
bool execute(Secure_superblock &req, Block_io &block_io, Trust_anchor &trust_anchor)
|
||||
{
|
||||
return req.execute({_sb, _sb_idx, _curr_gen, block_io, trust_anchor });
|
||||
}
|
||||
|
||||
bool execute(Synchronize &req, Block_io &block_io, Trust_anchor &trust_anchor)
|
||||
{
|
||||
return req.execute({_sb, _curr_gen, block_io, trust_anchor, *this });
|
||||
}
|
||||
|
||||
bool execute(Deinitialize &req, Block_io &block_io, Crypto &crypto, Trust_anchor &trust_anchor)
|
||||
{
|
||||
return req.execute({_sb, _curr_gen, block_io, crypto, trust_anchor, *this });
|
||||
}
|
||||
|
||||
bool execute(Initialize &req, Block_io &block_io, Crypto &crypto, Trust_anchor &trust_anchor)
|
||||
{
|
||||
return req.execute({_sb, _sb_idx, _curr_gen, block_io, crypto, trust_anchor, *this });
|
||||
}
|
||||
|
||||
bool execute(Create_snapshot &req, Block_io &block_io, Trust_anchor &trust_anchor)
|
||||
{
|
||||
return req.execute({_sb, _curr_gen, block_io, trust_anchor, *this });
|
||||
}
|
||||
|
||||
bool execute(Discard_snapshot &req, Block_io &block_io, Trust_anchor &trust_anchor)
|
||||
{
|
||||
return req.execute({_sb, _curr_gen, block_io, trust_anchor, *this });
|
||||
}
|
||||
|
||||
bool execute(Read_vbas &req, Virtual_block_device &vbd, Client_data_interface &client_data, Block_io &block_io, Crypto &crypto)
|
||||
{
|
||||
return req.execute({ vbd, client_data, block_io, crypto, _sb, _curr_gen });
|
||||
}
|
||||
|
||||
bool execute(Write_vbas &req, Virtual_block_device &vbd, Client_data_interface &client_data, Block_io &block_io, Free_tree &free_tree, Meta_tree &meta_tree, Crypto &crypto)
|
||||
{
|
||||
return req.execute({ vbd, client_data, block_io, free_tree, meta_tree, crypto, _sb, _curr_gen });
|
||||
}
|
||||
|
||||
static constexpr char const *name() { return "sb_control"; }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__SUPERBLOCK_CONTROL_H_ */
|
||||
|
@ -18,141 +18,232 @@
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/file.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Trust_anchor; }
|
||||
|
||||
class Trust_anchor;
|
||||
class Trust_anchor_request;
|
||||
class Trust_anchor_channel;
|
||||
}
|
||||
|
||||
class Tresor::Trust_anchor_request : public Module_request
|
||||
class Tresor::Trust_anchor : Noncopyable
|
||||
{
|
||||
friend class Trust_anchor_channel;
|
||||
|
||||
public:
|
||||
|
||||
enum Type { CREATE_KEY, ENCRYPT_KEY, DECRYPT_KEY, WRITE_HASH, READ_HASH, INITIALIZE };
|
||||
struct Attr
|
||||
{
|
||||
Vfs::Vfs_handle &decrypt_file;
|
||||
Vfs::Vfs_handle &encrypt_file;
|
||||
Vfs::Vfs_handle &generate_key_file;
|
||||
Vfs::Vfs_handle &initialize_file;
|
||||
Vfs::Vfs_handle &hash_file;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Type const _type;
|
||||
Key_value &_key_plaintext;
|
||||
Key_value &_key_ciphertext;
|
||||
Hash &_hash;
|
||||
Passphrase const _pass;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Trust_anchor_request);
|
||||
Attr const _attr;
|
||||
addr_t _user { };
|
||||
|
||||
public:
|
||||
|
||||
Trust_anchor_request(Module_id src, Module_channel_id, Type, Key_value &, Key_value &, Hash &, Passphrase, bool &);
|
||||
class Encrypt_key;
|
||||
class Decrypt_key;
|
||||
class Generate_key;
|
||||
class Initialize;
|
||||
class Read_hash;
|
||||
class Write_hash;
|
||||
|
||||
static char const *type_to_string(Type);
|
||||
Trust_anchor(Attr const &attr) : _attr(attr) { }
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, type_to_string(_type)); }
|
||||
template <typename REQ>
|
||||
bool execute(REQ &req)
|
||||
{
|
||||
if (!_user)
|
||||
_user = (addr_t)&req;
|
||||
|
||||
if (_user != (addr_t)&req)
|
||||
return false;
|
||||
|
||||
bool progress = req.execute(_attr);
|
||||
if (req.complete())
|
||||
_user = 0;
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
static constexpr char const *name() { return "trust_anchor"; }
|
||||
};
|
||||
|
||||
class Tresor::Trust_anchor_channel : public Module_channel
|
||||
class Tresor::Trust_anchor::Encrypt_key : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Trust_anchor;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Key_value &out_key_ciphertext;
|
||||
Key_value const &in_key_plaintext;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
using Request = Trust_anchor_request;
|
||||
enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR };
|
||||
|
||||
enum State { REQ_SUBMITTED, REQ_COMPLETE, READ_OK, WRITE_OK, FILE_ERR };
|
||||
Request_helper<Encrypt_key, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
State _state { REQ_COMPLETE };
|
||||
Vfs::Env &_vfs_env;
|
||||
public:
|
||||
|
||||
Encrypt_key(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "encrypt key"); }
|
||||
|
||||
bool execute(Trust_anchor::Attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Trust_anchor::Decrypt_key : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Trust_anchor;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Key_value &out_key_plaintext;
|
||||
Key_value const &in_key_ciphertext;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR };
|
||||
|
||||
Request_helper<Decrypt_key, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
public:
|
||||
|
||||
Decrypt_key(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "decrypt key"); }
|
||||
|
||||
bool execute(Trust_anchor::Attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Trust_anchor::Initialize : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Trust_anchor;
|
||||
|
||||
struct Attr { Passphrase const &in_passphrase; };
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR };
|
||||
|
||||
Request_helper<Initialize, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
char _result_buf[3];
|
||||
Tresor::Path const _path;
|
||||
Read_write_file<State> _decrypt_file { _state, _vfs_env, { _path, "/decrypt" } };
|
||||
Read_write_file<State> _encrypt_file { _state, _vfs_env, { _path, "/encrypt" } };
|
||||
Read_write_file<State> _generate_key_file { _state, _vfs_env, { _path, "/generate_key" } };
|
||||
Read_write_file<State> _initialize_file { _state, _vfs_env, { _path, "/initialize" } };
|
||||
Read_write_file<State> _hashsum_file { _state, _vfs_env, { _path, "/hashsum" } };
|
||||
Trust_anchor_request *_req_ptr { nullptr };
|
||||
|
||||
NONCOPYABLE(Trust_anchor_channel);
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
void _create_key(bool &);
|
||||
|
||||
void _read_hash(bool &);
|
||||
|
||||
void _initialize(bool &);
|
||||
|
||||
void _write_hash(bool &);
|
||||
|
||||
void _encrypt_key(bool &);
|
||||
|
||||
void _decrypt_key(bool &);
|
||||
|
||||
void _mark_req_failed(bool &, Error_string);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
public:
|
||||
|
||||
void execute(bool &);
|
||||
Initialize(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
Trust_anchor_channel(Module_channel_id, Vfs::Env &, Xml_node const &);
|
||||
void print(Output &out) const { Genode::print(out, "initialize"); }
|
||||
|
||||
bool execute(Trust_anchor::Attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Trust_anchor : public Module
|
||||
class Tresor::Trust_anchor::Generate_key : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Trust_anchor;
|
||||
|
||||
struct Attr { Key_value &out_key_plaintext; };
|
||||
|
||||
private:
|
||||
|
||||
using Request = Trust_anchor_request;
|
||||
using Channel = Trust_anchor_channel;
|
||||
enum State { INIT, COMPLETE, READ, READ_OK, FILE_ERR };
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Trust_anchor);
|
||||
Request_helper<Generate_key, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
public:
|
||||
|
||||
struct Create_key : Request
|
||||
{
|
||||
Create_key(Module_id m, Module_channel_id c, Key_value &k, bool &s)
|
||||
: Request(m, c, Request::CREATE_KEY, k, *(Key_value*)0, *(Hash*)0, Passphrase(), s) { }
|
||||
};
|
||||
Generate_key(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
struct Encrypt_key : Request
|
||||
{
|
||||
Encrypt_key(Module_id m, Module_channel_id c, Key_value const &kp, Key_value &kc, bool &s)
|
||||
: Request(m, c, Request::ENCRYPT_KEY, *const_cast<Key_value*>(&kp), kc, *(Hash*)0, Passphrase(), s) { }
|
||||
};
|
||||
void print(Output &out) const { Genode::print(out, "generate key"); }
|
||||
|
||||
struct Decrypt_key : Request
|
||||
{
|
||||
Decrypt_key(Module_id m, Module_channel_id c, Key_value &kp, Key_value const &kc, bool &s)
|
||||
: Request(m, c, Request::DECRYPT_KEY, kp, *const_cast<Key_value*>(&kc), *(Hash*)0, Passphrase(), s) { }
|
||||
};
|
||||
bool execute(Trust_anchor::Attr const &);
|
||||
|
||||
struct Write_hash : Request
|
||||
{
|
||||
Write_hash(Module_id m, Module_channel_id c, Hash const &h, bool &s)
|
||||
: Request(m, c, Request::WRITE_HASH, *(Key_value*)0, *(Key_value*)0, *const_cast<Hash*>(&h), Passphrase(), s) { }
|
||||
};
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
struct Read_hash : Request
|
||||
{
|
||||
Read_hash(Module_id m, Module_channel_id c, Hash &h, bool &s)
|
||||
: Request(m, c, Request::READ_HASH, *(Key_value*)0, *(Key_value*)0, h, Passphrase(), s) { }
|
||||
};
|
||||
class Tresor::Trust_anchor::Write_hash : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
struct Initialize : Request
|
||||
{
|
||||
Initialize(Module_id src_mod, Module_channel_id src_chan, Passphrase pass, bool &succ)
|
||||
: Request(src_mod, src_chan, Request::INITIALIZE, *(Key_value*)0, *(Key_value*)0, *(Hash*)0, pass, succ) { }
|
||||
};
|
||||
using Module = Trust_anchor;
|
||||
|
||||
Trust_anchor(Vfs::Env &, Xml_node const &);
|
||||
struct Attr { Hash const &in_hash; };
|
||||
|
||||
void execute(bool &) override;
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, WRITE, WRITE_OK, READ_OK, FILE_ERR };
|
||||
|
||||
Request_helper<Write_hash, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
char _result_buf[3];
|
||||
|
||||
public:
|
||||
|
||||
Write_hash(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "write hash"); }
|
||||
|
||||
bool execute(Trust_anchor::Attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Trust_anchor::Read_hash : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Trust_anchor;
|
||||
|
||||
struct Attr { Hash &out_hash; };
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, READ, READ_OK, FILE_ERR };
|
||||
|
||||
Request_helper<Read_hash, State> _helper;
|
||||
Attr const _attr;
|
||||
Constructible<File<State> > _file { };
|
||||
|
||||
public:
|
||||
|
||||
Read_hash(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "read hash"); }
|
||||
|
||||
bool execute(Trust_anchor::Attr const &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__TRUST_ANCHOR_H_ */
|
||||
|
@ -23,7 +23,7 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/math.h>
|
||||
#include <tresor/module.h>
|
||||
#include <tresor/verbosity.h>
|
||||
|
||||
namespace Tresor {
|
||||
|
||||
@ -101,8 +101,15 @@ namespace Tresor {
|
||||
struct Tree_walk_generations;
|
||||
struct Level_indent;
|
||||
struct Tree_root;
|
||||
struct Tree_configuration;
|
||||
class Pba_allocator;
|
||||
|
||||
template <typename, typename>
|
||||
class Request_helper;
|
||||
|
||||
template <typename, typename, typename>
|
||||
class Generatable_request;
|
||||
|
||||
template <size_t LEN>
|
||||
class Fixed_length;
|
||||
|
||||
@ -124,8 +131,7 @@ namespace Tresor {
|
||||
return first_pba - 1;
|
||||
}
|
||||
|
||||
inline Tree_node_index
|
||||
t1_node_idx_for_vba_typed(Virtual_block_address vba, Tree_level_index lvl, Tree_degree degr)
|
||||
inline Tree_node_index tree_node_index(Virtual_block_address vba, Tree_level_index lvl, Tree_degree degr)
|
||||
{
|
||||
uint64_t const degr_log_2 { log2(degr) };
|
||||
uint64_t const degr_mask { ((uint64_t)1 << degr_log_2) - 1 };
|
||||
@ -133,19 +139,6 @@ namespace Tresor {
|
||||
return (Tree_node_index)(degr_mask & (vba >> vba_rshift));
|
||||
}
|
||||
|
||||
template <typename T1, typename T2, typename T3>
|
||||
inline Tree_node_index t1_node_idx_for_vba(T1 vba, T2 lvl, T3 degr)
|
||||
{
|
||||
return t1_node_idx_for_vba_typed((Virtual_block_address)vba, (Tree_level_index)lvl, (Tree_degree)degr);
|
||||
}
|
||||
|
||||
inline Tree_node_index t2_node_idx_for_vba(Virtual_block_address vba, Tree_degree degr)
|
||||
{
|
||||
uint64_t const degr_log_2 { log2(degr) };
|
||||
uint64_t const degr_mask { ((uint64_t)1 << degr_log_2) - 1 };
|
||||
return (Tree_node_index)((uint64_t)vba & degr_mask);
|
||||
}
|
||||
|
||||
inline Virtual_block_address vbd_node_min_vba(Tree_degree_log_2 vbd_degr_log_2,
|
||||
Tree_level_index vbd_lvl,
|
||||
Virtual_block_address vbd_leaf_vba)
|
||||
@ -167,6 +160,120 @@ namespace Tresor {
|
||||
}
|
||||
|
||||
|
||||
template <typename REQ, typename STATE>
|
||||
class Tresor::Request_helper : Noncopyable
|
||||
{
|
||||
private:
|
||||
|
||||
REQ const &_req;
|
||||
bool _success { false };
|
||||
|
||||
public:
|
||||
|
||||
using Module = REQ::Module;
|
||||
|
||||
STATE state { STATE::INIT };
|
||||
|
||||
Request_helper(REQ &req) : _req(req) { }
|
||||
|
||||
bool complete() const { return state == STATE::COMPLETE; }
|
||||
|
||||
void mark_failed(bool &progress, Error_string const &err_str)
|
||||
{
|
||||
error(Module::name(), ": request (", _req, ") failed: ", err_str);
|
||||
_success = false;
|
||||
state = STATE::COMPLETE;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
void mark_succeeded(bool &progress)
|
||||
{
|
||||
_success = true;
|
||||
state = STATE::COMPLETE;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
void generated_req_failed(bool &progress) { mark_failed(progress, "generated request failed"); }
|
||||
|
||||
void generated_req_succeeded(STATE target_state, bool &progress)
|
||||
{
|
||||
state = target_state;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
void req_generated(STATE target_state, bool &progress)
|
||||
{
|
||||
state = target_state;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
bool success() const { return _success; }
|
||||
};
|
||||
|
||||
|
||||
template <typename OWNER, typename OWNER_STATE, typename REQUEST>
|
||||
class Tresor::Generatable_request
|
||||
{
|
||||
private:
|
||||
|
||||
struct Generated_request
|
||||
{
|
||||
OWNER &owner;
|
||||
OWNER_STATE succeeded_state;
|
||||
REQUEST req;
|
||||
|
||||
template <typename... ARGS>
|
||||
Generated_request(OWNER &owner, OWNER_STATE generated_state, OWNER_STATE succeeded_state,
|
||||
bool &progress, ARGS &&... args)
|
||||
:
|
||||
owner(owner), succeeded_state(succeeded_state), req(typename REQUEST::Attr(args...))
|
||||
{
|
||||
owner.req_generated(generated_state, progress);
|
||||
if (VERBOSE_MODULE_COMMUNICATION)
|
||||
log(OWNER::Module::name(), " --", req, "--> ", REQUEST::Module::name());
|
||||
}
|
||||
|
||||
template <typename... ARGS>
|
||||
bool execute(REQUEST::Module &dst_mod, ARGS &&... args)
|
||||
{
|
||||
bool progress = false;
|
||||
progress |= dst_mod.execute(req, args...);
|
||||
if (req.complete()) {
|
||||
if (VERBOSE_MODULE_COMMUNICATION)
|
||||
log(OWNER::Module::name(), " <--", req, "-- ", REQUEST::Module::name());
|
||||
|
||||
if (!req.success()) {
|
||||
owner.generated_req_failed(progress);
|
||||
return progress;
|
||||
}
|
||||
owner.generated_req_succeeded(succeeded_state, progress);
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
};
|
||||
|
||||
Constructible<Generated_request> _generated_req { };
|
||||
|
||||
public:
|
||||
|
||||
template <typename... ARGS>
|
||||
void generate(ARGS &&... args)
|
||||
{
|
||||
_generated_req.construct(args...);
|
||||
}
|
||||
|
||||
template <typename... ARGS>
|
||||
bool execute(REQUEST::Module &dst_mod, ARGS &&... args)
|
||||
{
|
||||
bool progress = _generated_req->execute(dst_mod, args...);
|
||||
if (_generated_req->req.complete())
|
||||
_generated_req.destruct();
|
||||
|
||||
return progress;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Pba_allocator
|
||||
{
|
||||
private:
|
||||
@ -176,7 +283,7 @@ class Tresor::Pba_allocator
|
||||
|
||||
public:
|
||||
|
||||
Pba_allocator(Physical_block_address const first_pba) : _first_pba { first_pba } { }
|
||||
Pba_allocator(Physical_block_address const first_pba) : _first_pba(first_pba) { }
|
||||
|
||||
Number_of_blocks num_used_pbas() { return _num_used_pbas; }
|
||||
|
||||
@ -317,10 +424,7 @@ class Tresor::Block_scanner
|
||||
|
||||
public:
|
||||
|
||||
Block_scanner(Block const &blk)
|
||||
:
|
||||
_blk { blk }
|
||||
{ }
|
||||
Block_scanner(Block const &blk) : _blk(blk) { }
|
||||
|
||||
template<typename T>
|
||||
void fetch(T &dst);
|
||||
@ -387,10 +491,7 @@ class Tresor::Block_generator
|
||||
|
||||
public:
|
||||
|
||||
Block_generator(Block &blk)
|
||||
:
|
||||
_blk { blk }
|
||||
{ }
|
||||
Block_generator(Block &blk) : _blk(blk) { }
|
||||
|
||||
template<typename T>
|
||||
void append(T const &src);
|
||||
@ -503,6 +604,14 @@ struct Tresor::Tree_root
|
||||
};
|
||||
|
||||
|
||||
struct Tresor::Tree_configuration
|
||||
{
|
||||
Tree_level_index max_lvl;
|
||||
Tree_degree degree;
|
||||
Number_of_leaves num_leaves;
|
||||
};
|
||||
|
||||
|
||||
struct Tresor::Type_1_node_block
|
||||
{
|
||||
Type_1_node nodes[NUM_NODES_PER_BLK] { };
|
||||
@ -526,6 +635,11 @@ struct Tresor::Type_1_node_block
|
||||
struct Tresor::Type_1_node_block_walk
|
||||
{
|
||||
Type_1_node_block items[TREE_MAX_NR_OF_LEVELS] { };
|
||||
|
||||
Type_1_node &node(Virtual_block_address vba, Tree_level_index lvl, Tree_degree degr)
|
||||
{
|
||||
return items[lvl].nodes[tree_node_index(vba, lvl, degr)];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -685,8 +799,8 @@ struct Tresor::Snapshots
|
||||
snap.encode_to_blk(generator);
|
||||
}
|
||||
|
||||
void discard_disposable_snapshots(Generation curr_gen,
|
||||
Generation last_secured_gen)
|
||||
void discard_disposable_snapshots(Generation last_secured_gen,
|
||||
Generation curr_gen)
|
||||
{
|
||||
for (Snapshot &snap : items) {
|
||||
|
||||
@ -752,31 +866,31 @@ struct Tresor::Superblock
|
||||
enum State {
|
||||
INVALID, NORMAL, REKEYING, EXTENDING_VBD, EXTENDING_FT };
|
||||
|
||||
State state { INVALID }; // offset 0
|
||||
Virtual_block_address rekeying_vba { 0 }; // offset 1
|
||||
Number_of_blocks resizing_nr_of_pbas { 0 }; // offset 9
|
||||
Number_of_leaves resizing_nr_of_leaves { 0 }; // offset 17
|
||||
Key previous_key { }; // offset 25
|
||||
Key current_key { }; // offset 61
|
||||
Snapshots snapshots { }; // offset 97
|
||||
Generation last_secured_generation { 0 }; // offset 3553
|
||||
Snapshot_index curr_snap_idx { 0 }; // offset 3561
|
||||
Tree_degree degree { TREE_MIN_DEGREE }; // offset 3565
|
||||
Physical_block_address first_pba { 0 }; // offset 3569
|
||||
Number_of_blocks nr_of_pbas { 0 }; // offset 3577
|
||||
Generation free_gen { 0 }; // offset 3585
|
||||
Physical_block_address free_number { 0 }; // offset 3593
|
||||
Hash free_hash { }; // offset 3601
|
||||
Tree_level_index free_max_level { 0 }; // offset 3633
|
||||
Tree_degree free_degree { TREE_MIN_DEGREE }; // offset 3637
|
||||
Number_of_leaves free_leaves { 0 }; // offset 3641
|
||||
Generation meta_gen { 0 }; // offset 3649
|
||||
Physical_block_address meta_number { 0 }; // offset 3657
|
||||
Hash meta_hash { }; // offset 3665
|
||||
Tree_level_index meta_max_level { 0 }; // offset 3697
|
||||
Tree_degree meta_degree { TREE_MIN_DEGREE }; // offset 3701
|
||||
Number_of_leaves meta_leaves { 0 }; // offset 3705
|
||||
// offset 3713
|
||||
State state { INVALID }; /* offset 0 */
|
||||
Virtual_block_address rekeying_vba { 0 }; /* offset 1 */
|
||||
Number_of_blocks resizing_nr_of_pbas { 0 }; /* offset 9 */
|
||||
Number_of_leaves resizing_nr_of_leaves { 0 }; /* offset 17 */
|
||||
Key previous_key { }; /* offset 25 */
|
||||
Key current_key { }; /* offset 61 */
|
||||
Snapshots snapshots { }; /* offset 97 */
|
||||
Generation last_secured_generation { 0 }; /* offset 3553 */
|
||||
Snapshot_index curr_snap_idx { 0 }; /* offset 3561 */
|
||||
Tree_degree degree { TREE_MIN_DEGREE }; /* offset 3565 */
|
||||
Physical_block_address first_pba { 0 }; /* offset 3569 */
|
||||
Number_of_blocks nr_of_pbas { 0 }; /* offset 3577 */
|
||||
Generation free_gen { 0 }; /* offset 3585 */
|
||||
Physical_block_address free_number { 0 }; /* offset 3593 */
|
||||
Hash free_hash { }; /* offset 3601 */
|
||||
Tree_level_index free_max_level { 0 }; /* offset 3633 */
|
||||
Tree_degree free_degree { TREE_MIN_DEGREE }; /* offset 3637 */
|
||||
Number_of_leaves free_leaves { 0 }; /* offset 3641 */
|
||||
Generation meta_gen { 0 }; /* offset 3649 */
|
||||
Physical_block_address meta_number { 0 }; /* offset 3657 */
|
||||
Hash meta_hash { }; /* offset 3665 */
|
||||
Tree_level_index meta_max_level { 0 }; /* offset 3697 */
|
||||
Tree_degree meta_degree { TREE_MIN_DEGREE }; /* offset 3701 */
|
||||
Number_of_leaves meta_leaves { 0 }; /* offset 3705 */
|
||||
/* offset 3713 */
|
||||
|
||||
static State decode_state(On_disc_state val)
|
||||
{
|
||||
@ -981,6 +1095,19 @@ struct Tresor::Snapshots_info
|
||||
for (Generation &gen : generations)
|
||||
gen = INVALID_GENERATION;
|
||||
}
|
||||
|
||||
void print(Output &out) const
|
||||
{
|
||||
bool first { true };
|
||||
for (unsigned idx { 0 }; idx < MAX_NR_OF_SNAPSHOTS; idx++) {
|
||||
|
||||
if (!generations[idx])
|
||||
continue;
|
||||
|
||||
Genode::print(out, "snapshot ", first ? "" : "\n", idx, ": ", generations[idx]);
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -1028,8 +1155,7 @@ class Tresor::Pba_allocation {
|
||||
Pba_allocation(Type_1_node_walk const &t1_node_walk,
|
||||
Tree_walk_pbas const &new_pbas)
|
||||
:
|
||||
_t1_node_walk { t1_node_walk },
|
||||
_new_pbas { new_pbas }
|
||||
_t1_node_walk(t1_node_walk), _new_pbas(new_pbas)
|
||||
{ }
|
||||
|
||||
void print(Output &out) const
|
||||
|
@ -16,94 +16,51 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/block_io.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Vbd_check; }
|
||||
|
||||
class Vbd_check;
|
||||
class Vbd_check_request;
|
||||
class Vbd_check_channel;
|
||||
}
|
||||
|
||||
|
||||
class Tresor::Vbd_check_request : public Module_request
|
||||
struct Tresor::Vbd_check : Noncopyable
|
||||
{
|
||||
friend class Vbd_check_channel;
|
||||
class Check : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
private:
|
||||
using Module = Vbd_check;
|
||||
|
||||
Tree_root const &_vbd;
|
||||
bool &_success;
|
||||
struct Attr { Tree_root const &in_vbd; };
|
||||
|
||||
NONCOPYABLE(Vbd_check_request);
|
||||
private:
|
||||
|
||||
public:
|
||||
enum State { INIT, IN_PROGRESS, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED };
|
||||
|
||||
Vbd_check_request(Module_id, Module_channel_id, Tree_root const &, bool &);
|
||||
Request_helper<Check, State> _helper;
|
||||
Attr const _attr;
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
bool _check_node[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { };
|
||||
Block _blk { };
|
||||
Number_of_leaves _num_remaining_leaves { 0 };
|
||||
Generatable_request<Request_helper<Check, State>, State, Block_io::Read> _read_block { };
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, "check ", _vbd); }
|
||||
};
|
||||
bool _execute_node(Block_io &, Tree_level_index, Tree_node_index, bool &);
|
||||
|
||||
public:
|
||||
|
||||
class Tresor::Vbd_check_channel : public Module_channel
|
||||
{
|
||||
private:
|
||||
Check(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
using Request = Vbd_check_request;
|
||||
void print(Output &out) const { Genode::print(out, "check ", _attr.in_vbd); }
|
||||
|
||||
enum State : State_uint { REQ_SUBMITTED, REQ_IN_PROGRESS, REQ_COMPLETE, REQ_GENERATED, READ_BLK_SUCCEEDED };
|
||||
bool execute(Block_io &);
|
||||
|
||||
State _state { REQ_COMPLETE };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
bool _check_node[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { };
|
||||
Block _blk { };
|
||||
Request *_req_ptr { };
|
||||
Number_of_leaves _num_remaining_leaves { 0 };
|
||||
bool _generated_req_success { false };
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
NONCOPYABLE(Vbd_check_channel);
|
||||
Vbd_check() { }
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
bool execute(Check &req, Block_io &block_io) { return req.execute(block_io); }
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
void _mark_req_failed(bool &, Error_string);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
|
||||
bool _execute_node(Tree_level_index, Tree_node_index, bool &);
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint state, bool &progress, ARGS &&... args)
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<REQUEST>(state, progress, args..., _generated_req_success);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Vbd_check_channel(Module_channel_id id) : Module_channel { VBD_CHECK, id } { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Vbd_check : public Module
|
||||
{
|
||||
private:
|
||||
|
||||
using Channel = Vbd_check_channel;
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Vbd_check);
|
||||
|
||||
public:
|
||||
|
||||
Vbd_check();
|
||||
|
||||
void execute(bool &) override;
|
||||
static constexpr char const *name() { return "vbd_check"; }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__VBD_CHECK_H_ */
|
||||
|
@ -17,92 +17,65 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/block_io.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Vbd_initializer; }
|
||||
|
||||
class Vbd_initializer;
|
||||
class Vbd_initializer_request;
|
||||
class Vbd_initializer_channel;
|
||||
}
|
||||
|
||||
|
||||
class Tresor::Vbd_initializer_request : public Module_request
|
||||
class Tresor::Vbd_initializer : Noncopyable
|
||||
{
|
||||
friend class Vbd_initializer_channel;
|
||||
|
||||
private:
|
||||
|
||||
Tree_root &_vbd;
|
||||
Pba_allocator &_pba_alloc;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Vbd_initializer_request);
|
||||
|
||||
public:
|
||||
|
||||
Vbd_initializer_request(Module_id, Module_channel_id, Tree_root &, Pba_allocator &, bool &);
|
||||
class Initialize : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, "init"); }
|
||||
};
|
||||
using Module = Vbd_initializer;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Tree_configuration const in_tree_cfg;
|
||||
Type_1_node &out_tree_root;
|
||||
Pba_allocator &in_out_pba_alloc;
|
||||
};
|
||||
|
||||
class Tresor::Vbd_initializer_channel : public Module_channel
|
||||
{
|
||||
private:
|
||||
private:
|
||||
|
||||
using Request = Vbd_initializer_request;
|
||||
enum State { INIT, COMPLETE, WRITE_BLOCK, EXECUTE_NODES };
|
||||
|
||||
enum State { REQ_GENERATED, SUBMITTED, COMPLETE, EXECUTE_NODES };
|
||||
enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITING_BLOCK };
|
||||
|
||||
enum Node_state { DONE, INIT_BLOCK, INIT_NODE, WRITE_BLOCK };
|
||||
using Helper = Request_helper<Initialize, State>;
|
||||
|
||||
State _state { COMPLETE };
|
||||
Vbd_initializer_request *_req_ptr { };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Node_state _node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { DONE };
|
||||
bool _generated_req_success { false };
|
||||
Block _blk { };
|
||||
Number_of_leaves _num_remaining_leaves { };
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Node_state _node_states[TREE_MAX_NR_OF_LEVELS][NUM_NODES_PER_BLK] { DONE };
|
||||
bool _generated_req_success { false };
|
||||
Block _blk { };
|
||||
Number_of_leaves _num_remaining_leaves { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
|
||||
NONCOPYABLE(Vbd_initializer_channel);
|
||||
void _reset_level(Tree_level_index, Node_state);
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
bool _execute_node(Tree_level_index, Tree_node_index, bool &);
|
||||
|
||||
bool _request_complete() override { return _state == COMPLETE; }
|
||||
public:
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
Initialize(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void _reset_level(Tree_level_index, Node_state);
|
||||
~Initialize() { }
|
||||
|
||||
bool _execute_node(Tree_level_index, Tree_node_index, bool &);
|
||||
void print(Output &out) const { Genode::print(out, "initialize"); }
|
||||
|
||||
void _mark_req_failed(bool &, char const *);
|
||||
bool execute(Block_io &);
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
public:
|
||||
bool execute(Initialize &req, Block_io &block_io) { return req.execute(block_io); }
|
||||
|
||||
Vbd_initializer_channel(Module_channel_id id) : Module_channel { VBD_INITIALIZER, id } { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Vbd_initializer : public Module
|
||||
{
|
||||
private:
|
||||
|
||||
using Channel = Vbd_initializer_channel;
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Vbd_initializer);
|
||||
|
||||
public:
|
||||
|
||||
Vbd_initializer();
|
||||
|
||||
void execute(bool &) override;
|
||||
static constexpr char const *name() { return "vbd_initializer"; }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__VBD_INITIALIZER_H_ */
|
||||
|
@ -24,7 +24,6 @@ namespace Tresor {
|
||||
enum { VERBOSE_REKEYING = 0 };
|
||||
enum { VERBOSE_READ_VBA = 0 };
|
||||
enum { VERBOSE_WRITE_VBA = 0 };
|
||||
enum { VERBOSE_CRYPTO = 0 };
|
||||
enum { VERBOSE_BLOCK_IO = 0 };
|
||||
enum { VERBOSE_BLOCK_IO_PBA_FILTER = 0 };
|
||||
enum { VERBOSE_BLOCK_IO_PBA = 0 };
|
||||
|
@ -17,134 +17,270 @@
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/free_tree.h>
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/client_data_interface.h>
|
||||
#include <tresor/crypto.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Virtual_block_device; }
|
||||
|
||||
class Virtual_block_device;
|
||||
class Virtual_block_device_request;
|
||||
class Virtual_block_device_channel;
|
||||
}
|
||||
|
||||
class Tresor::Virtual_block_device_request : public Module_request
|
||||
class Tresor::Virtual_block_device : Noncopyable
|
||||
{
|
||||
friend class Virtual_block_device_channel;
|
||||
|
||||
public:
|
||||
|
||||
enum Type { REKEY_VBA, READ_VBA, WRITE_VBA, EXTENSION_STEP };
|
||||
|
||||
private:
|
||||
|
||||
Type const _type;
|
||||
Virtual_block_address const _vba;
|
||||
Snapshots &_snapshots;
|
||||
Snapshot_index const _curr_snap_idx;
|
||||
Tree_degree const _snap_degr;
|
||||
Generation const _curr_gen;
|
||||
Key_id const _curr_key_id;
|
||||
Key_id const _prev_key_id;
|
||||
Tree_root &_ft;
|
||||
Tree_root &_mt;
|
||||
Tree_degree const _vbd_degree;
|
||||
Virtual_block_address const _vbd_highest_vba;
|
||||
bool const _rekeying;
|
||||
Request_offset const _client_req_offset;
|
||||
Request_tag const _client_req_tag;
|
||||
Generation const _last_secured_gen;
|
||||
Physical_block_address &_pba;
|
||||
Number_of_blocks &_num_pbas;
|
||||
Number_of_leaves &_num_leaves;
|
||||
Virtual_block_address const _rekeying_vba;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Virtual_block_device_request);
|
||||
|
||||
public:
|
||||
|
||||
Virtual_block_device_request(Module_id, Module_channel_id, Type, Request_offset, Request_tag, Generation,
|
||||
Tree_root &, Tree_root &, Tree_degree, Virtual_block_address, bool,
|
||||
Virtual_block_address, Snapshot_index, Snapshots &, Tree_degree, Key_id,
|
||||
Key_id, Generation, Physical_block_address &, bool &, Number_of_leaves &,
|
||||
Number_of_blocks &, Virtual_block_address);
|
||||
|
||||
static char const *type_to_string(Type);
|
||||
|
||||
void print(Output &out) const override { Genode::print(out, type_to_string(_type)); }
|
||||
};
|
||||
|
||||
class Tresor::Virtual_block_device_channel : public Module_channel
|
||||
{
|
||||
private:
|
||||
|
||||
using Request = Virtual_block_device_request;
|
||||
|
||||
enum State {
|
||||
SUBMITTED, REQ_GENERATED, REQ_COMPLETE, READ_BLK_SUCCEEDED, WRITE_BLK_SUCCEEDED,
|
||||
DECRYPT_LEAF_DATA_SUCCEEDED, ENCRYPT_LEAF_DATA_SUCCEEDED, ALLOC_PBAS_SUCCEEDED };
|
||||
|
||||
Request *_req_ptr { nullptr };
|
||||
State _state { REQ_COMPLETE };
|
||||
Snapshot_index _snap_idx { 0 };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Type_1_node_walk _t1_nodes { };
|
||||
Tree_level_index _lvl { 0 };
|
||||
Virtual_block_address _vba { 0 };
|
||||
Tree_walk_pbas _old_pbas { };
|
||||
Tree_walk_pbas _new_pbas { };
|
||||
Hash _hash { };
|
||||
Number_of_blocks _num_blks { 0 };
|
||||
Generation _free_gen { 0 };
|
||||
Block _encoded_blk { };
|
||||
Block _data_blk { };
|
||||
bool _first_snapshot { false };
|
||||
bool _gen_req_success { false };
|
||||
|
||||
NONCOPYABLE(Virtual_block_device_channel);
|
||||
class Rekey_vba;
|
||||
class Read_vba;
|
||||
class Write_vba;
|
||||
class Extend_tree;
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint complete_state, bool &progress, ARGS &&... args)
|
||||
bool execute(REQUEST &req, ARGS &&... args) { return req.execute(args...); }
|
||||
|
||||
static constexpr char const *name() { return "vbd"; }
|
||||
};
|
||||
|
||||
class Tresor::Virtual_block_device::Rekey_vba : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Virtual_block_device;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
generate_req<REQUEST>(complete_state, progress, args..., _gen_req_success);
|
||||
_state = REQ_GENERATED;
|
||||
}
|
||||
Snapshots &in_out_snapshots;
|
||||
Tree_root &in_out_ft;
|
||||
Tree_root &in_out_mt;
|
||||
Virtual_block_address const in_vba;
|
||||
Generation const in_curr_gen;
|
||||
Generation const in_last_secured_gen;
|
||||
Key_id const in_curr_key_id;
|
||||
Key_id const in_prev_key_id;
|
||||
Tree_degree const in_vbd_degree;
|
||||
Virtual_block_address const in_vbd_highest_vba;
|
||||
};
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
private:
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
enum State {
|
||||
INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED,
|
||||
DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED,
|
||||
ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED };
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
using Helper = Request_helper<Rekey_vba, State>;
|
||||
|
||||
void _generate_ft_req(State, bool, Free_tree_request::Type);
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Tree_level_index _lvl { 0 };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Block _encoded_blk { };
|
||||
Block _data_blk { };
|
||||
Generation _free_gen { 0 };
|
||||
Tree_walk_pbas _old_pbas { };
|
||||
Tree_walk_pbas _new_pbas { };
|
||||
Snapshot_index _snap_idx { 0 };
|
||||
Type_1_node_walk _t1_nodes { };
|
||||
Number_of_blocks _num_blks { 0 };
|
||||
Hash _hash { };
|
||||
bool _first_snapshot { false };
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
Generatable_request<Helper, State, Crypto::Encrypt> _encrypt_block { };
|
||||
Generatable_request<Helper, State, Crypto::Decrypt> _decrypt_block { };
|
||||
Generatable_request<Helper, State, Free_tree::Allocate_pbas> _alloc_pbas { };
|
||||
|
||||
Snapshot &snap() { return _req_ptr->_snapshots.items[_snap_idx]; }
|
||||
bool _check_and_decode_read_blk(bool &);
|
||||
|
||||
void _start_alloc_pbas(bool &, Free_tree::Allocate_pbas::Application);
|
||||
|
||||
void _generate_write_blk_req(bool &);
|
||||
|
||||
bool _find_next_snap_to_rekey_vba_at(Snapshot_index &) const;
|
||||
|
||||
void _read_vba(bool &);
|
||||
void _generate_ft_alloc_req_for_rekeying(Tree_level_index, bool &);
|
||||
|
||||
public:
|
||||
|
||||
Rekey_vba(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Rekey_vba() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "rekey vba"); }
|
||||
|
||||
bool execute(Block_io &, Crypto &, Free_tree &, Meta_tree &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Virtual_block_device::Read_vba : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Virtual_block_device;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Snapshot const &in_snap;
|
||||
Virtual_block_address const in_vba;
|
||||
Key_id const in_key_id;
|
||||
Tree_degree const in_vbd_degree;
|
||||
Request_offset const in_client_req_offset;
|
||||
Request_tag const in_client_req_tag;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State { INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Read_vba, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Tree_level_index _lvl { 0 };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Hash _hash { };
|
||||
Block _blk { };
|
||||
Tree_walk_pbas _new_pbas { };
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
Generatable_request<Helper, State, Crypto::Decrypt> _decrypt_block { };
|
||||
|
||||
bool _check_and_decode_read_blk(bool &);
|
||||
|
||||
Tree_node_index _node_idx(Tree_level_index, Virtual_block_address) const;
|
||||
public:
|
||||
|
||||
Type_1_node &_node(Tree_level_index, Virtual_block_address);
|
||||
Read_vba(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
~Read_vba() { }
|
||||
|
||||
void _mark_req_failed(bool &, char const *);
|
||||
void print(Output &out) const { Genode::print(out, "read vba"); }
|
||||
|
||||
bool execute(Client_data_interface &, Block_io &, Crypto &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Virtual_block_device::Write_vba : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Virtual_block_device;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Snapshot &in_out_snap;
|
||||
Snapshots const &in_snapshots;
|
||||
Tree_root &in_out_ft;
|
||||
Tree_root &in_out_mt;
|
||||
Virtual_block_address const in_vba;
|
||||
Key_id const in_curr_key_id;
|
||||
Key_id const in_prev_key_id;
|
||||
Tree_degree const in_vbd_degree;
|
||||
Virtual_block_address const in_vbd_highest_vba;
|
||||
Request_offset const in_client_req_offset;
|
||||
Request_tag const in_client_req_tag;
|
||||
Generation const in_curr_gen;
|
||||
Generation const in_last_secured_gen;
|
||||
bool in_rekeying;
|
||||
Virtual_block_address const in_rekeying_vba;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, DECRYPT_BLOCK, DECRYPT_BLOCK_SUCCEEDED,
|
||||
WRITE_BLK, WRITE_BLK_SUCCEEDED, ENCRYPT_BLOCK, ENCRYPT_BLOCK_SUCCEEDED, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Write_vba, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Tree_level_index _lvl { 0 };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Hash _hash { };
|
||||
Type_1_node_walk _t1_nodes { };
|
||||
Block _data_blk { };
|
||||
Block _encoded_blk { };
|
||||
Tree_walk_pbas _new_pbas { };
|
||||
Number_of_blocks _num_blks { 0 };
|
||||
Generation _free_gen { 0 };
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
Generatable_request<Helper, State, Crypto::Decrypt> _decrypt_block { };
|
||||
Generatable_request<Helper, State, Crypto::Encrypt> _encrypt_block { };
|
||||
Generatable_request<Helper, State, Free_tree::Allocate_pbas> _alloc_pbas { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
|
||||
bool _check_and_decode_read_blk(bool &);
|
||||
|
||||
void _set_new_pbas_and_num_blks_for_alloc();
|
||||
|
||||
void _generate_ft_alloc_req_for_write_vba(bool &);
|
||||
|
||||
void _write_vba(bool &);
|
||||
|
||||
void _update_nodes_of_branch_of_written_vba();
|
||||
|
||||
void _rekey_vba(bool &);
|
||||
void _generate_ft_alloc_req_for_write_vba(bool &);
|
||||
|
||||
void _generate_ft_alloc_req_for_rekeying(Tree_level_index, bool &);
|
||||
void _generate_write_blk_req(bool &);
|
||||
|
||||
public:
|
||||
|
||||
Write_vba(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
~Write_vba() { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "write vba"); }
|
||||
|
||||
bool execute(Client_data_interface &, Block_io &, Free_tree &, Meta_tree &, Crypto &);
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Tresor::Virtual_block_device::Extend_tree : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Virtual_block_device;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Number_of_leaves &out_num_leaves;
|
||||
Snapshots &in_out_snapshots;
|
||||
Tree_degree const in_snap_degr;
|
||||
Generation const in_curr_gen;
|
||||
Generation const in_last_secured_gen;
|
||||
Physical_block_address &in_out_first_pba;
|
||||
Number_of_blocks &in_out_num_pbas;
|
||||
Tree_root &in_out_ft;
|
||||
Tree_root &in_out_mt;
|
||||
Tree_degree const in_vbd_degree;
|
||||
Virtual_block_address const in_vbd_highest_vba;
|
||||
Key_id const in_curr_key_id;
|
||||
Key_id const in_prev_key_id;
|
||||
bool in_rekeying;
|
||||
Virtual_block_address const in_rekeying_vba;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
INIT, COMPLETE, READ_BLK, READ_BLK_SUCCEEDED, WRITE_BLK, WRITE_BLK_SUCCEEDED, ALLOC_PBAS, ALLOC_PBAS_SUCCEEDED };
|
||||
|
||||
using Helper = Request_helper<Extend_tree, State>;
|
||||
|
||||
Helper _helper;
|
||||
Attr const _attr;
|
||||
Tree_level_index _lvl { 0 };
|
||||
Snapshot_index _snap_idx { 0 };
|
||||
Virtual_block_address _vba { 0 };
|
||||
Tree_walk_pbas _old_pbas { };
|
||||
Block _encoded_blk { };
|
||||
Tree_walk_pbas _new_pbas { };
|
||||
Type_1_node_block_walk _t1_blks { };
|
||||
Number_of_blocks _num_blks { 0 };
|
||||
Type_1_node_walk _t1_nodes { };
|
||||
Block _data_blk { };
|
||||
Generation _free_gen { 0 };
|
||||
Generatable_request<Helper, State, Block_io::Read> _read_block { };
|
||||
Generatable_request<Helper, State, Block_io::Write> _write_block { };
|
||||
Generatable_request<Helper, State, Free_tree::Allocate_pbas> _alloc_pbas { };
|
||||
|
||||
void _add_new_root_lvl_to_snap();
|
||||
|
||||
@ -152,32 +288,22 @@ class Tresor::Virtual_block_device_channel : public Module_channel
|
||||
|
||||
void _set_new_pbas_identical_to_curr_pbas();
|
||||
|
||||
void _generate_write_blk_req(bool &);
|
||||
|
||||
void _generate_ft_alloc_req_for_resizing(Tree_level_index, bool &);
|
||||
|
||||
void _extension_step(bool &);
|
||||
|
||||
public:
|
||||
|
||||
Virtual_block_device_channel(Module_channel_id id) : Module_channel { VIRTUAL_BLOCK_DEVICE, id } { }
|
||||
Extend_tree(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void execute(bool &);
|
||||
};
|
||||
~Extend_tree() { }
|
||||
|
||||
class Tresor::Virtual_block_device : public Module
|
||||
{
|
||||
private:
|
||||
void print(Output &out) const { Genode::print(out, "extend tree"); }
|
||||
|
||||
using Channel = Virtual_block_device_channel;
|
||||
bool execute(Block_io &, Free_tree &, Meta_tree &);
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Virtual_block_device);
|
||||
|
||||
void execute(bool &) override;
|
||||
|
||||
public:
|
||||
|
||||
Virtual_block_device();
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
#endif /* _TRESOR__VIRTUAL_BLOCK_DEVICE_H_ */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* \brief Module for doing VBD COW allocations on the meta tree
|
||||
* \brief Module for doing PBA allocations for the Free Tree via the Meta Tree
|
||||
* \author Martin Stein
|
||||
* \date 2023-02-13
|
||||
*/
|
||||
@ -13,149 +13,32 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/meta_tree.h>
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/hash.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
char const *Meta_tree_request::type_to_string(Type type)
|
||||
bool Meta_tree::execute(Allocate_pba &req, Block_io &block_io) { return req.execute(block_io); }
|
||||
|
||||
|
||||
void Meta_tree::Allocate_pba::_start_tree_traversal(bool &progress)
|
||||
{
|
||||
switch (type) {
|
||||
case ALLOC_PBA: return "alloc pba";
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
|
||||
Meta_tree_request::Meta_tree_request(Module_id src_module_id, Module_channel_id src_channel_id,
|
||||
Type type, Tree_root &mt, Generation curr_gen,
|
||||
Physical_block_address &pba, bool &success)
|
||||
:
|
||||
Module_request { src_module_id, src_channel_id, META_TREE }, _type { type }, _mt { mt },
|
||||
_curr_gen { curr_gen }, _pba { pba }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
void Meta_tree::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
}
|
||||
|
||||
|
||||
bool Meta_tree_channel::_can_alloc_pba_of(Type_2_node &node)
|
||||
{
|
||||
return node.valid() && node.alloc_gen != _req_ptr->_curr_gen;
|
||||
}
|
||||
|
||||
|
||||
void Meta_tree_channel::_generated_req_completed(State_uint state_uint)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("meta tree: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
void Meta_tree_channel::_alloc_pba_of(Type_2_node &t2_node, Physical_block_address &pba)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
Physical_block_address old_pba { pba };
|
||||
pba = t2_node.pba;
|
||||
t2_node.pba = old_pba;
|
||||
t2_node.alloc_gen = req._curr_gen;
|
||||
t2_node.free_gen = req._curr_gen;
|
||||
t2_node.reserved = false;
|
||||
}
|
||||
|
||||
|
||||
void Meta_tree_channel::_mark_req_failed(bool &progress, char const *str)
|
||||
{
|
||||
error(Request::type_to_string(_req_ptr->_type), " request failed, reason: \"", str, "\"");
|
||||
_req_ptr->_success = false;
|
||||
_state = COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Meta_tree_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
_req_ptr->_success = true;
|
||||
_state = COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Meta_tree_channel::_start_tree_traversal(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
_lvl = req._mt.max_lvl;
|
||||
_lvl = _attr.in_out_mt.max_lvl;
|
||||
_node_idx[_lvl] = 0;
|
||||
_t1_blks[_lvl].nodes[_node_idx[_lvl]] = req._mt.t1_node();
|
||||
_generate_req<Block_io::Read>(SEEK_DOWN, progress, req._mt.pba, _blk);
|
||||
_t1_blks[_lvl].nodes[_node_idx[_lvl]] = _attr.in_out_mt.t1_node();
|
||||
_read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, _attr.in_out_mt.pba, _blk);
|
||||
}
|
||||
|
||||
|
||||
void Meta_tree_channel::_traverse_curr_node(bool &progress)
|
||||
bool Meta_tree::Allocate_pba::execute(Block_io &block_io)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
if (_lvl) {
|
||||
Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] };
|
||||
if (t1_node.pba)
|
||||
_generate_req<Block_io::Read>(SEEK_DOWN, progress, t1_node.pba, _blk);
|
||||
else {
|
||||
_state = SEEK_LEFT_OR_UP;
|
||||
progress = true;
|
||||
}
|
||||
} else {
|
||||
Type_2_node &t2_node { _t2_blk.nodes[_node_idx[_lvl]] };
|
||||
if (_can_alloc_pba_of(t2_node)) {
|
||||
_alloc_pba_of(t2_node, _req_ptr->_pba);
|
||||
for (Tree_level_index lvl { 1 }; lvl <= req._mt.max_lvl; lvl++) {
|
||||
Type_1_node &t1_node { _t1_blks[lvl].nodes[_node_idx[lvl]] };
|
||||
if (!t1_node.is_volatile(req._curr_gen)) {
|
||||
bool pba_allocated { false };
|
||||
for (Type_2_node &t2_node : _t2_blk.nodes) {
|
||||
if (_can_alloc_pba_of(t2_node)) {
|
||||
_alloc_pba_of(t2_node, t1_node.pba);
|
||||
pba_allocated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(pba_allocated);
|
||||
}
|
||||
}
|
||||
_state = WRITE_BLK;
|
||||
} else
|
||||
_state = SEEK_LEFT_OR_UP;
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Meta_tree_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
_start_tree_traversal(progress);
|
||||
break;
|
||||
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT: _start_tree_traversal(progress); break;
|
||||
case READ_BLK: progress |= _read_block.execute(block_io); break;
|
||||
case SEEK_DOWN:
|
||||
|
||||
if (!check_hash(_blk, _t1_blks[_lvl].nodes[_node_idx[_lvl]].hash)) {
|
||||
_mark_req_failed(progress, "hash mismatch");
|
||||
_helper.mark_failed(progress, "hash mismatch");
|
||||
break;
|
||||
}
|
||||
_lvl--;
|
||||
@ -169,54 +52,91 @@ void Meta_tree_channel::execute(bool &progress)
|
||||
|
||||
case SEEK_LEFT_OR_UP:
|
||||
|
||||
if (_lvl < req._mt.max_lvl) {
|
||||
if (_node_idx[_lvl] < req._mt.degree - 1) {
|
||||
if (_lvl < _attr.in_out_mt.max_lvl) {
|
||||
if (_node_idx[_lvl] < _attr.in_out_mt.degree - 1) {
|
||||
_node_idx[_lvl]++;
|
||||
_traverse_curr_node(progress);
|
||||
} else {
|
||||
_lvl++;
|
||||
_state = SEEK_LEFT_OR_UP;
|
||||
_helper.state = SEEK_LEFT_OR_UP;
|
||||
progress = true;
|
||||
}
|
||||
} else
|
||||
_mark_req_failed(progress, "not enough free pbas");
|
||||
_helper.mark_failed(progress, "not enough free pbas");
|
||||
break;
|
||||
|
||||
case WRITE_BLK:
|
||||
case WRITE_BLK: progress |= _write_block.execute(block_io); break;
|
||||
case WRITE_BLK_SUCCEEDED:
|
||||
|
||||
if (_lvl < req._mt.max_lvl) {
|
||||
if (_lvl < _attr.in_out_mt.max_lvl) {
|
||||
if (_lvl)
|
||||
_t1_blks[_lvl].encode_to_blk(_blk);
|
||||
else
|
||||
_t2_blk.encode_to_blk(_blk);
|
||||
_lvl++;
|
||||
Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] };
|
||||
t1_node.gen = req._curr_gen;
|
||||
t1_node.gen = _attr.in_curr_gen;
|
||||
calc_hash(_blk, t1_node.hash);
|
||||
_generate_req<Block_io::Write>(WRITE_BLK, progress, t1_node.pba, _blk);
|
||||
_write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, t1_node.pba, _blk);
|
||||
} else {
|
||||
req._mt.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]);
|
||||
_mark_req_successful(progress);
|
||||
_attr.in_out_mt.t1_node(_t1_blks[_lvl].nodes[_node_idx[_lvl]]);
|
||||
_helper.mark_succeeded(progress);
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void Meta_tree_channel::_request_submitted(Module_request &mod_req)
|
||||
bool Meta_tree::Allocate_pba::_can_alloc_pba_of(Type_2_node &node)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
return node.valid() && node.alloc_gen != _attr.in_curr_gen;
|
||||
}
|
||||
|
||||
|
||||
Meta_tree::Meta_tree()
|
||||
void Meta_tree::Allocate_pba::_alloc_pba_of(Type_2_node &t2_node, Physical_block_address &pba)
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++);
|
||||
add_channel(*chan);
|
||||
Physical_block_address old_pba { pba };
|
||||
pba = t2_node.pba;
|
||||
t2_node.pba = old_pba;
|
||||
t2_node.alloc_gen = _attr.in_curr_gen;
|
||||
t2_node.free_gen = _attr.in_curr_gen;
|
||||
t2_node.reserved = false;
|
||||
}
|
||||
|
||||
void Meta_tree::Allocate_pba::_traverse_curr_node(bool &progress)
|
||||
{
|
||||
if (_lvl) {
|
||||
Type_1_node &t1_node { _t1_blks[_lvl].nodes[_node_idx[_lvl]] };
|
||||
if (t1_node.pba)
|
||||
_read_block.generate(_helper, READ_BLK, SEEK_DOWN, progress, t1_node.pba, _blk);
|
||||
else {
|
||||
_helper.state = SEEK_LEFT_OR_UP;
|
||||
progress = true;
|
||||
}
|
||||
} else {
|
||||
Type_2_node &t2_node { _t2_blk.nodes[_node_idx[_lvl]] };
|
||||
if (_can_alloc_pba_of(t2_node)) {
|
||||
_alloc_pba_of(t2_node, _attr.in_out_pba);
|
||||
for (Tree_level_index lvl { 1 }; lvl <= _attr.in_out_mt.max_lvl; lvl++) {
|
||||
Type_1_node &t1_node { _t1_blks[lvl].nodes[_node_idx[lvl]] };
|
||||
if (!t1_node.is_volatile(_attr.in_curr_gen)) {
|
||||
bool pba_allocated { false };
|
||||
for (Type_2_node &t2_node : _t2_blk.nodes) {
|
||||
if (_can_alloc_pba_of(t2_node)) {
|
||||
_alloc_pba_of(t2_node, t1_node.pba);
|
||||
pba_allocated = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ASSERT(pba_allocated);
|
||||
}
|
||||
}
|
||||
_helper.state = WRITE_BLK_SUCCEEDED;
|
||||
} else
|
||||
_helper.state = SEEK_LEFT_OR_UP;
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
|
@ -1,145 +0,0 @@
|
||||
/*
|
||||
* \brief Framework for component internal modularization
|
||||
* \author Martin Stein
|
||||
* \date 2023-02-13
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/types.h>
|
||||
#include <tresor/module.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
|
||||
Module_request::Module_request(Module_id src_module_id, Module_channel_id src_chan_id, Module_id dst_module_id)
|
||||
:
|
||||
_src_module_id { src_module_id }, _src_chan_id { src_chan_id }, _dst_module_id { dst_module_id }
|
||||
{ }
|
||||
|
||||
|
||||
char const *Tresor::module_name(Module_id id)
|
||||
{
|
||||
switch (id) {
|
||||
case CRYPTO: return "crypto";
|
||||
case BLOCK_IO: return "block_io";
|
||||
case CACHE: return "cache";
|
||||
case META_TREE: return "meta_tree";
|
||||
case FREE_TREE: return "free_tree";
|
||||
case VIRTUAL_BLOCK_DEVICE: return "vbd";
|
||||
case SUPERBLOCK_CONTROL: return "sb_control";
|
||||
case CLIENT_DATA: return "client_data";
|
||||
case TRUST_ANCHOR: return "trust_anchor";
|
||||
case COMMAND_POOL: return "command_pool";
|
||||
case VBD_INITIALIZER: return "vbd_initializer";
|
||||
case FT_INITIALIZER: return "ft_initializer";
|
||||
case SB_INITIALIZER: return "sb_initializer";
|
||||
case SB_CHECK: return "sb_check";
|
||||
case VBD_CHECK: return "vbd_check";
|
||||
case FT_CHECK: return "ft_check";
|
||||
case SPLITTER: return "splitter";
|
||||
case REQUEST_POOL: return "request_pool";
|
||||
default: break;
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
|
||||
void Module_channel::generated_req_completed()
|
||||
{
|
||||
ASSERT(_gen_req_state == IN_PROGRESS);
|
||||
_gen_req_state = NONE;
|
||||
_generated_req_completed(_gen_req_complete_state);
|
||||
}
|
||||
|
||||
|
||||
bool Module_channel::try_submit_request(Module_request &req)
|
||||
{
|
||||
if (_req_ptr)
|
||||
return false;
|
||||
|
||||
req.dst_chan_id(_id);
|
||||
_req_ptr = &req;
|
||||
_request_submitted(req);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool Module::try_submit_request(Module_request &req)
|
||||
{
|
||||
bool success { false };
|
||||
for_each_channel([&] (Module_channel &chan) {
|
||||
if (success)
|
||||
return;
|
||||
|
||||
success = chan.try_submit_request(req);
|
||||
});
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
void Module_composition::execute_modules()
|
||||
{
|
||||
bool progress { true };
|
||||
while (progress) {
|
||||
|
||||
progress = false;
|
||||
for (Module_id id { 0 }; id <= MAX_MODULE_ID; id++) {
|
||||
if (!_module_ptrs[id])
|
||||
continue;
|
||||
|
||||
Module &mod { *_module_ptrs[id] };
|
||||
mod.execute(progress);
|
||||
mod.for_each_generated_request([&] (Module_request &req) {
|
||||
ASSERT(req.dst_module_id() <= MAX_MODULE_ID);
|
||||
ASSERT(_module_ptrs[req.dst_module_id()]);
|
||||
Module &dst_module { *_module_ptrs[req.dst_module_id()] };
|
||||
if (dst_module.try_submit_request(req)) {
|
||||
if (VERBOSE_MODULE_COMMUNICATION)
|
||||
log(module_name(id), " ", req.src_chan_id(), " --", req, "--> ",
|
||||
module_name(req.dst_module_id()), " ", req.dst_chan_id());
|
||||
|
||||
progress = true;
|
||||
return true;
|
||||
}
|
||||
if (VERBOSE_MODULE_COMMUNICATION)
|
||||
log(module_name(id), " ", req.src_chan_id(), " --", req, "-| ", module_name(req.dst_module_id()));
|
||||
|
||||
return false;
|
||||
});
|
||||
mod.for_each_completed_request([&] (Module_request &req) {
|
||||
ASSERT(req.src_module_id() <= MAX_MODULE_ID);
|
||||
if (VERBOSE_MODULE_COMMUNICATION)
|
||||
log(module_name(req.src_module_id()), " ", req.src_chan_id(), " <--", req,
|
||||
"-- ", module_name(id), " ", req.dst_chan_id());
|
||||
|
||||
Module &src_module { *_module_ptrs[req.src_module_id()] };
|
||||
src_module.with_channel(req.src_chan_id(), [&] (Module_channel &chan) {
|
||||
chan.generated_req_completed(); });
|
||||
progress = true;
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
void Module_composition::add_module(Module_id module_id, Module &mod)
|
||||
{
|
||||
ASSERT(module_id <= MAX_MODULE_ID);
|
||||
ASSERT(!_module_ptrs[module_id]);
|
||||
_module_ptrs[module_id] = &mod;
|
||||
}
|
||||
|
||||
|
||||
void Module_composition::remove_module(Module_id module_id)
|
||||
{
|
||||
ASSERT(module_id <= MAX_MODULE_ID);
|
||||
ASSERT(_module_ptrs[module_id]);
|
||||
_module_ptrs[module_id] = nullptr;
|
||||
}
|
@ -1,381 +0,0 @@
|
||||
/*
|
||||
* \brief Module for scheduling requests for processing
|
||||
* \author Martin Stein
|
||||
* \date 2023-03-17
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/request_pool.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Request::Request(Module_id src_module_id, Module_channel_id src_chan_id, Operation op, Virtual_block_address vba,
|
||||
Request_offset offset, Number_of_blocks count, Key_id key_id, Request_tag tag, Generation &gen, bool &success)
|
||||
:
|
||||
Module_request { src_module_id, src_chan_id, REQUEST_POOL }, _op { op }, _vba { vba }, _offset { offset },
|
||||
_count { count }, _key_id { key_id }, _tag { tag }, _gen { gen }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
void Request::print(Output &out) const
|
||||
{
|
||||
Genode::print(out, op_to_string(_op));
|
||||
switch (_op) {
|
||||
case READ:
|
||||
case WRITE:
|
||||
case SYNC:
|
||||
if (_count > 1)
|
||||
Genode::print(out, " vbas ", _vba, "..", _vba + _count - 1);
|
||||
else
|
||||
Genode::print(out, " vba ", _vba);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
char const *Request::op_to_string(Operation op)
|
||||
{
|
||||
switch (op) {
|
||||
case Request::READ: return "read";
|
||||
case Request::WRITE: return "write";
|
||||
case Request::SYNC: return "sync";
|
||||
case Request::CREATE_SNAPSHOT: return "create_snapshot";
|
||||
case Request::DISCARD_SNAPSHOT: return "discard_snapshot";
|
||||
case Request::REKEY: return "rekey";
|
||||
case Request::EXTEND_VBD: return "extend_vbd";
|
||||
case Request::EXTEND_FT: return "extend_ft";
|
||||
case Request::RESUME_REKEYING: return "resume_rekeying";
|
||||
case Request::DEINITIALIZE: return "deinitialize";
|
||||
case Request::INITIALIZE: return "initialize";
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_gen_sb_control_req(bool &progress, Superblock_control_request::Type type,
|
||||
State complete_state, Virtual_block_address vba = 0)
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<Superblock_control_request>(
|
||||
complete_state, progress, type, _req_ptr->_offset, _req_ptr->_tag, _req_ptr->_count, vba, _generated_req_success,
|
||||
_request_finished, _sb_state, _req_ptr->_gen);
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_access_vbas(bool &progress, Superblock_control_request::Type type)
|
||||
{
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
_gen_sb_control_req(progress, type, ACCESS_VBA_AT_SB_CTRL_SUCCEEDED, _req_ptr->_vba + _num_blks);
|
||||
break;
|
||||
case ACCESS_VBA_AT_SB_CTRL_SUCCEEDED:
|
||||
if (++_num_blks < _req_ptr->_count)
|
||||
_gen_sb_control_req(progress, type, ACCESS_VBA_AT_SB_CTRL_SUCCEEDED, _req_ptr->_vba + _num_blks);
|
||||
else
|
||||
_mark_req_successful(progress);
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
_req_ptr->_success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_chan_queue.dequeue(*this);
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_try_prepone_requests(bool &progress)
|
||||
{
|
||||
enum { MAX_NUM_REQUESTS_PREPONED = 8 };
|
||||
bool requests_preponed { false };
|
||||
bool at_req_that_cannot_be_preponed { false };
|
||||
_num_requests_preponed = 0;
|
||||
|
||||
while (_num_requests_preponed < MAX_NUM_REQUESTS_PREPONED &&
|
||||
!at_req_that_cannot_be_preponed &&
|
||||
!_chan_queue.is_tail(*this)) {
|
||||
|
||||
switch (_chan_queue.next(*this)._req_ptr->_op) {
|
||||
case Request::READ:
|
||||
case Request::WRITE:
|
||||
case Request::SYNC:
|
||||
case Request::DISCARD_SNAPSHOT:
|
||||
|
||||
_chan_queue.move_one_slot_towards_tail(*this);
|
||||
_num_requests_preponed++;
|
||||
requests_preponed = true;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
at_req_that_cannot_be_preponed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!requests_preponed) {
|
||||
_state = PREPONED_REQUESTS_COMPLETE;
|
||||
progress = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_extend_tree(Superblock_control_request::Type type, bool &progress)
|
||||
{
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
_gen_sb_control_req(progress, type, TREE_EXTENSION_STEP_SUCCEEDED);
|
||||
break;
|
||||
|
||||
case TREE_EXTENSION_STEP_SUCCEEDED:
|
||||
|
||||
if (_request_finished)
|
||||
_mark_req_successful(progress);
|
||||
else
|
||||
_try_prepone_requests(progress);
|
||||
break;
|
||||
|
||||
case PREPONED_REQUESTS_COMPLETE:
|
||||
|
||||
_gen_sb_control_req(progress, type, TREE_EXTENSION_STEP_SUCCEEDED);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_rekey(bool &progress)
|
||||
{
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
_gen_sb_control_req(progress, Superblock_control_request::INITIALIZE_REKEYING, REKEY_INIT_SUCCEEDED);
|
||||
break;
|
||||
|
||||
case REQ_RESUMED:
|
||||
case REKEY_INIT_SUCCEEDED: _try_prepone_requests(progress); break;
|
||||
case REKEY_VBA_SUCCEEDED:
|
||||
|
||||
if (_request_finished)
|
||||
_mark_req_successful(progress);
|
||||
else
|
||||
_try_prepone_requests(progress);
|
||||
break;
|
||||
|
||||
case PREPONED_REQUESTS_COMPLETE:
|
||||
|
||||
_gen_sb_control_req(progress, Superblock_control_request::REKEY_VBA, REKEY_VBA_SUCCEEDED);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_resume_request(bool &progress, Request::Operation op)
|
||||
{
|
||||
_state = REQ_RESUMED;
|
||||
_req_ptr->_op = op;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_initialize(bool &progress)
|
||||
{
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
_gen_sb_control_req(progress, Superblock_control_request::INITIALIZE, INITIALIZE_SB_CTRL_SUCCEEDED);
|
||||
break;
|
||||
|
||||
case INITIALIZE_SB_CTRL_SUCCEEDED:
|
||||
|
||||
switch (_sb_state) {
|
||||
case Superblock::INVALID: ASSERT_NEVER_REACHED;
|
||||
case Superblock::NORMAL:
|
||||
|
||||
_chan_queue.dequeue(*this);
|
||||
_reset();
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case Superblock::REKEYING: _resume_request(progress, Request::REKEY); break;
|
||||
case Superblock::EXTENDING_VBD: _resume_request(progress, Request::EXTEND_VBD); break;
|
||||
case Superblock::EXTENDING_FT: _resume_request(progress, Request::EXTEND_FT); break;
|
||||
}
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_forward_to_sb_ctrl(bool &progress, Superblock_control_request::Type type)
|
||||
{
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _gen_sb_control_req(progress, type, FORWARD_TO_SB_CTRL_SUCCEEDED); break;
|
||||
case FORWARD_TO_SB_CTRL_SUCCEEDED: _mark_req_successful(progress); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Request_pool::execute(bool &progress)
|
||||
{
|
||||
if (!_chan_queue.empty())
|
||||
_chan_queue.head().execute(progress);
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::execute(bool &progress)
|
||||
{
|
||||
switch (_req_ptr->_op) {
|
||||
case Request::READ: _access_vbas(progress, Superblock_control_request::READ_VBA); break;
|
||||
case Request::WRITE: _access_vbas(progress, Superblock_control_request::WRITE_VBA); break;
|
||||
case Request::SYNC: _forward_to_sb_ctrl(progress, Superblock_control_request::SYNC); break;
|
||||
case Request::REKEY: _rekey(progress); break;
|
||||
case Request::EXTEND_VBD: _extend_tree(Superblock_control_request::VBD_EXTENSION_STEP, progress); break;
|
||||
case Request::EXTEND_FT: _extend_tree(Superblock_control_request::FT_EXTENSION_STEP, progress); break;
|
||||
case Request::INITIALIZE: _initialize(progress); break;
|
||||
case Request::DEINITIALIZE: _forward_to_sb_ctrl(progress, Superblock_control_request::DEINITIALIZE); break;
|
||||
case Request::CREATE_SNAPSHOT: _forward_to_sb_ctrl(progress, Superblock_control_request::CREATE_SNAPSHOT); break;
|
||||
case Request::DISCARD_SNAPSHOT: _forward_to_sb_ctrl(progress, Superblock_control_request::DISCARD_SNAPSHOT); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Request_pool::Request_pool()
|
||||
{
|
||||
for (Module_channel_id id { 0 }; id < NUM_CHANNELS; id++) {
|
||||
_channels[id].construct(id, _chan_queue);
|
||||
add_channel(*_channels[id]);
|
||||
}
|
||||
ASSERT(try_submit_request(_init_req));
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_generated_req_completed(State_uint state_uint)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("request_pool: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_chan_queue.dequeue(*this);
|
||||
_req_ptr = nullptr;
|
||||
} else
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_reset()
|
||||
{
|
||||
_state = INVALID;
|
||||
_sb_state = Superblock::INVALID;
|
||||
_num_blks = _num_requests_preponed = 0;
|
||||
_request_finished = false;
|
||||
}
|
||||
|
||||
|
||||
Request_pool_channel &Request_pool_channel_queue::head() const
|
||||
{
|
||||
ASSERT(!empty());
|
||||
return *_slots[_head];
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel_queue::enqueue(Channel &chan)
|
||||
{
|
||||
ASSERT(!full());
|
||||
_slots[_tail] = &chan;
|
||||
_tail = (_tail + 1) % NUM_SLOTS;
|
||||
_num_used_slots++;
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel_queue::move_one_slot_towards_tail(Channel const &chan)
|
||||
{
|
||||
Slot_index slot_idx { _head };
|
||||
Slot_index next_slot_idx;
|
||||
ASSERT(!empty());
|
||||
while (1) {
|
||||
if (slot_idx < NUM_SLOTS - 1)
|
||||
next_slot_idx = slot_idx + 1;
|
||||
else
|
||||
next_slot_idx = 0;
|
||||
|
||||
ASSERT(next_slot_idx != _tail);
|
||||
if (_slots[slot_idx] == &chan) {
|
||||
Channel *chan_ptr = _slots[next_slot_idx];
|
||||
_slots[next_slot_idx] = _slots[slot_idx];
|
||||
_slots[slot_idx] = chan_ptr;
|
||||
return;
|
||||
}
|
||||
slot_idx = next_slot_idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Request_pool_channel_queue::is_tail(Channel const &chan) const
|
||||
{
|
||||
Slot_index slot_idx;
|
||||
ASSERT(!empty());
|
||||
if (_tail)
|
||||
slot_idx = _tail - 1;
|
||||
else
|
||||
slot_idx = NUM_SLOTS - 1;
|
||||
|
||||
return _slots[slot_idx] == &chan;
|
||||
}
|
||||
|
||||
|
||||
Request_pool_channel &Request_pool_channel_queue::next(Channel const &chan) const
|
||||
{
|
||||
Slot_index slot_idx { _head };
|
||||
Slot_index next_slot_idx;
|
||||
ASSERT(!empty());
|
||||
while (1) {
|
||||
if (slot_idx < NUM_SLOTS - 1)
|
||||
next_slot_idx = slot_idx + 1;
|
||||
else
|
||||
next_slot_idx = 0;
|
||||
|
||||
ASSERT(next_slot_idx != _tail);
|
||||
if (_slots[slot_idx] == &chan)
|
||||
return *_slots[next_slot_idx];
|
||||
else
|
||||
slot_idx = next_slot_idx;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel_queue::dequeue(Channel const &chan)
|
||||
{
|
||||
ASSERT(!empty() && &head() == &chan);
|
||||
_head = (_head + 1) % NUM_SLOTS;
|
||||
_num_used_slots--;
|
||||
}
|
||||
|
||||
|
||||
void Request_pool_channel::_request_submitted(Module_request &req)
|
||||
{
|
||||
_reset();
|
||||
_req_ptr = static_cast<Request *>(&req);
|
||||
_state = REQ_SUBMITTED;
|
||||
_chan_queue.enqueue(*this);
|
||||
}
|
@ -13,64 +13,41 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/sb_check.h>
|
||||
#include <tresor/vbd_check.h>
|
||||
#include <tresor/ft_check.h>
|
||||
#include <tresor/block_io.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Sb_check_request::Sb_check_request(Module_id src_mod, Module_channel_id src_chan, bool &success)
|
||||
:
|
||||
Module_request { src_mod, src_chan, SB_CHECK }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
void Sb_check_channel::_generated_req_completed(State_uint state_uint)
|
||||
bool Sb_check::Check::execute(Vbd_check &vbd_check, Ft_check &ft_check, Block_io &block_io)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("sb check: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
void Sb_check_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_highest_gen = 0;
|
||||
_highest_gen_sb_idx = 0;
|
||||
_snap_idx = 0;
|
||||
_sb_idx = 0;
|
||||
_scan_for_highest_gen_sb_done = false;
|
||||
_generate_req<Block_io::Read>(READ_BLK_SUCCESSFUL, progress, _sb_idx, _blk);
|
||||
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _sb_idx, _blk);
|
||||
break;
|
||||
|
||||
case READ_BLK_SUCCESSFUL:
|
||||
case READ_BLK: progress |= _read_block.execute(block_io); break;
|
||||
case READ_BLK_SUCCEEDED:
|
||||
|
||||
_sb.decode_from_blk(_blk);
|
||||
if (_scan_for_highest_gen_sb_done) {
|
||||
if (!_sb.valid()) {
|
||||
_mark_req_failed(progress, "no valid superblock");;
|
||||
_helper.mark_failed(progress, "no valid superblock");;
|
||||
break;
|
||||
}
|
||||
Snapshot &snap { _sb.snapshots.items[_snap_idx] };
|
||||
if (snap.valid) {
|
||||
Snapshot &snap { _sb.snapshots.items[_snap_idx] };
|
||||
_tree_root.construct(snap.pba, snap.gen, snap.hash, snap.max_level, _sb.degree, snap.nr_of_leaves);
|
||||
_generate_req<Vbd_check_request>(CHECK_VBD_SUCCESSFUL, progress, *_tree_root);
|
||||
_check_vbd.generate(_helper, CHECK_VBD, CHECK_VBD_SUCCEEDED, progress, *_tree_root);
|
||||
if (VERBOSE_CHECK)
|
||||
log(" check snap ", _snap_idx, " (", snap, ")");
|
||||
} else {
|
||||
_state = CHECK_VBD_SUCCESSFUL;
|
||||
_helper.state = CHECK_VBD_SUCCEEDED;
|
||||
progress = true;
|
||||
if (VERBOSE_CHECK)
|
||||
log(" skip snap ", _snap_idx, " as it is unused");
|
||||
@ -83,85 +60,45 @@ void Sb_check_channel::execute(bool &progress)
|
||||
}
|
||||
if (_sb_idx < MAX_SUPERBLOCK_INDEX) {
|
||||
_sb_idx++;
|
||||
_generate_req<Block_io::Read>(READ_BLK_SUCCESSFUL, progress, _sb_idx, _blk);
|
||||
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _sb_idx, _blk);
|
||||
progress = true;
|
||||
} else {
|
||||
_scan_for_highest_gen_sb_done = true;
|
||||
_generate_req<Block_io::Read>(READ_BLK_SUCCESSFUL, progress, _highest_gen_sb_idx, _blk);
|
||||
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, _highest_gen_sb_idx, _blk);
|
||||
if (VERBOSE_CHECK)
|
||||
log("check superblock ", _highest_gen_sb_idx, "\n read superblock");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case CHECK_VBD_SUCCESSFUL:
|
||||
case CHECK_VBD: progress |= _check_vbd.execute(vbd_check, block_io); break;
|
||||
case CHECK_VBD_SUCCEEDED:
|
||||
|
||||
if (_snap_idx < MAX_SNAP_IDX) {
|
||||
_snap_idx++;
|
||||
_state = READ_BLK_SUCCESSFUL;
|
||||
_helper.state = READ_BLK_SUCCEEDED;
|
||||
progress = true;
|
||||
} else {
|
||||
_snap_idx = 0;
|
||||
_tree_root.construct(_sb.free_number, _sb.free_gen, _sb.free_hash, _sb.free_max_level, _sb.free_degree, _sb.free_leaves);
|
||||
_generate_req<Ft_check_request>(CHECK_FT_SUCCESSFUL, progress, *_tree_root);
|
||||
_check_ft.generate(_helper, CHECK_FT, CHECK_FT_SUCCEEDED, progress, *_tree_root);
|
||||
if (VERBOSE_CHECK)
|
||||
log(" check free tree");
|
||||
}
|
||||
break;
|
||||
|
||||
case CHECK_FT_SUCCESSFUL:
|
||||
case CHECK_FT: progress |= _check_ft.execute(ft_check, block_io); break;
|
||||
case CHECK_FT_SUCCEEDED:
|
||||
|
||||
_tree_root.construct(_sb.meta_number, _sb.meta_gen, _sb.meta_hash, _sb.meta_max_level, _sb.meta_degree, _sb.meta_leaves);
|
||||
_generate_req<Ft_check_request>(CHECK_MT_SUCCESSFUL, progress, *_tree_root);
|
||||
_check_ft.generate(_helper, CHECK_MT, CHECK_MT_SUCCEEDED, progress, *_tree_root);
|
||||
if (VERBOSE_CHECK)
|
||||
log(" check meta tree");
|
||||
break;
|
||||
|
||||
case CHECK_MT_SUCCESSFUL: _mark_req_successful(progress); break;
|
||||
case CHECK_MT: progress |= _check_ft.execute(ft_check, block_io); break;
|
||||
case CHECK_MT_SUCCEEDED: _helper.mark_succeeded(progress); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Sb_check_channel::_mark_req_failed(bool &progress, char const *str)
|
||||
{
|
||||
error("sb check: request (", *_req_ptr, ") failed at step \"", str, "\"");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Sb_check_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
req._success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Sb_check_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
Sb_check::Sb_check()
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++);
|
||||
add_channel(*chan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Sb_check::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
return progress;
|
||||
}
|
||||
|
@ -14,158 +14,100 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/hash.h>
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/vbd_initializer.h>
|
||||
#include <tresor/ft_initializer.h>
|
||||
#include <tresor/trust_anchor.h>
|
||||
#include <tresor/sb_initializer.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Sb_initializer_request::
|
||||
Sb_initializer_request(Module_id src_mod, Module_channel_id src_chan, Tree_level_index vbd_max_lvl,
|
||||
Tree_degree vbd_degree, Number_of_leaves vbd_num_leaves, Tree_level_index ft_max_lvl,
|
||||
Tree_degree ft_degree, Number_of_leaves ft_num_leaves, Tree_level_index mt_max_lvl,
|
||||
Tree_degree mt_degree, Number_of_leaves mt_num_leaves, Pba_allocator &pba_alloc, bool &success)
|
||||
:
|
||||
Module_request { src_mod, src_chan, SB_INITIALIZER }, _vbd_max_lvl { vbd_max_lvl },
|
||||
_vbd_degree { vbd_degree }, _vbd_num_leaves { vbd_num_leaves }, _ft_max_lvl { ft_max_lvl },
|
||||
_ft_degree { ft_degree }, _ft_num_leaves { ft_num_leaves }, _mt_max_lvl { mt_max_lvl },
|
||||
_mt_degree { mt_degree }, _mt_num_leaves { mt_num_leaves }, _pba_alloc { pba_alloc }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
void Sb_initializer_channel::_generated_req_completed(State_uint state_uint)
|
||||
bool Sb_initializer::Initialize::execute(Block_io &block_io, Trust_anchor &trust_anchor, Vbd_initializer &vbd_initializer, Ft_initializer &ft_initializer)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("sb initializer: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
void Sb_initializer_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
void Sb_initializer_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
_req_ptr->_success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Sb_initializer_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
{
|
||||
_sb_idx = 0;
|
||||
_sb = { };
|
||||
Snapshot &snap = _sb.snapshots.items[0];
|
||||
_vbd.construct(snap.pba, snap.gen, snap.hash, req._vbd_max_lvl, req._vbd_degree, req._vbd_num_leaves);
|
||||
_generate_req<Vbd_initializer_request>(INIT_VBD_SUCCEEDED, progress, *_vbd, req._pba_alloc);
|
||||
progress = true;
|
||||
_init_vbd.generate(_helper, INIT_VBD, INIT_VBD_SUCCEEDED, progress, _attr.in_vbd_cfg, _vbd_root, _attr.in_out_pba_alloc);
|
||||
break;
|
||||
}
|
||||
case INIT_VBD: progress |= _init_vbd.execute(vbd_initializer, block_io); break;
|
||||
case INIT_VBD_SUCCEEDED:
|
||||
|
||||
_ft.construct(_sb.free_number, _sb.free_gen, _sb.free_hash, req._ft_max_lvl, req._ft_degree, req._ft_num_leaves);
|
||||
_generate_req<Ft_initializer_request>(INIT_FT_SUCCEEDED, progress, *_ft, req._pba_alloc);
|
||||
_init_ft.generate(_helper, INIT_FT, INIT_FT_SUCCEEDED, progress, _attr.in_ft_cfg, _ft_root, _attr.in_out_pba_alloc);
|
||||
break;
|
||||
|
||||
case INIT_FT: progress |= _init_ft.execute(ft_initializer, block_io); break;
|
||||
case INIT_FT_SUCCEEDED:
|
||||
|
||||
_mt.construct(_sb.meta_number, _sb.meta_gen, _sb.meta_hash, req._ft_max_lvl, req._ft_degree, req._ft_num_leaves);
|
||||
_generate_req<Ft_initializer_request>(INIT_MT_SUCCEEDED, progress, *_mt, req._pba_alloc);
|
||||
_init_ft.generate(_helper, INIT_FT, INIT_MT_SUCCEEDED, progress, _attr.in_mt_cfg, _mt_root, _attr.in_out_pba_alloc);
|
||||
break;
|
||||
|
||||
case INIT_MT_SUCCEEDED:
|
||||
|
||||
_generate_req<Trust_anchor::Create_key>(CREATE_KEY_SUCCEEDED, progress, _sb.current_key.value);
|
||||
_generate_key.generate(_helper, GENERATE_KEY, GENERATE_KEY_SUCCEEDED, progress, _sb.current_key.value);
|
||||
break;
|
||||
|
||||
case CREATE_KEY_SUCCEEDED:
|
||||
case GENERATE_KEY: progress |= _generate_key.execute(trust_anchor); break;
|
||||
case GENERATE_KEY_SUCCEEDED:
|
||||
|
||||
_generate_req<Trust_anchor::Encrypt_key>(ENCRYPT_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb.current_key.value);
|
||||
_encrypt_key.generate(_helper, ENCRYPT_KEY, ENCRYPT_KEY_SUCCEEDED, progress, _sb.current_key.value, _sb.current_key.value);
|
||||
break;
|
||||
|
||||
case ENCRYPT_KEY: progress |= _encrypt_key.execute(trust_anchor); break;
|
||||
case ENCRYPT_KEY_SUCCEEDED:
|
||||
{
|
||||
Snapshot &snap = _sb.snapshots.items[0];
|
||||
snap.gen = 0;
|
||||
snap.nr_of_leaves = req._vbd_num_leaves;
|
||||
snap.max_level = req._vbd_max_lvl;
|
||||
snap.pba = _vbd_root.pba;
|
||||
snap.gen = _vbd_root.gen;
|
||||
snap.hash = _vbd_root.hash;
|
||||
snap.nr_of_leaves = _attr.in_vbd_cfg.num_leaves;
|
||||
snap.max_level = _attr.in_vbd_cfg.max_lvl;
|
||||
snap.valid = true;
|
||||
snap.id = 0;
|
||||
_sb.current_key.id = 1;
|
||||
_sb.state = Superblock::NORMAL;
|
||||
_sb.degree = req._vbd_degree;
|
||||
_sb.first_pba = req._pba_alloc.first_pba() - NR_OF_SUPERBLOCK_SLOTS;
|
||||
_sb.nr_of_pbas = req._pba_alloc.num_used_pbas() + NR_OF_SUPERBLOCK_SLOTS;
|
||||
_sb.free_max_level = _ft->max_lvl;
|
||||
_sb.free_degree = _ft->degree;
|
||||
_sb.free_leaves = _ft->num_leaves;
|
||||
_sb.meta_max_level = _mt->max_lvl;
|
||||
_sb.meta_degree = _mt->degree;
|
||||
_sb.meta_leaves = _mt->num_leaves;
|
||||
_sb.degree = _attr.in_vbd_cfg.degree;
|
||||
_sb.first_pba = _attr.in_out_pba_alloc.first_pba() - NR_OF_SUPERBLOCK_SLOTS;
|
||||
_sb.nr_of_pbas = _attr.in_out_pba_alloc.num_used_pbas() + NR_OF_SUPERBLOCK_SLOTS;
|
||||
_sb.free_number = _ft_root.pba;
|
||||
_sb.free_gen = _ft_root.gen;
|
||||
_sb.free_hash = _ft_root.hash;
|
||||
_sb.free_max_level = _attr.in_ft_cfg.max_lvl;
|
||||
_sb.free_degree = _attr.in_ft_cfg.degree;
|
||||
_sb.free_leaves = _attr.in_ft_cfg.num_leaves;
|
||||
_sb.meta_number = _mt_root.pba;
|
||||
_sb.meta_gen = _mt_root.gen;
|
||||
_sb.meta_hash = _mt_root.hash;
|
||||
_sb.meta_max_level = _attr.in_mt_cfg.max_lvl;
|
||||
_sb.meta_degree = _attr.in_mt_cfg.degree;
|
||||
_sb.meta_leaves = _attr.in_mt_cfg.num_leaves;
|
||||
_sb.encode_to_blk(_blk);
|
||||
_generate_req<Block_io::Write>(WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk);
|
||||
_write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk);
|
||||
break;
|
||||
}
|
||||
case WRITE_BLK: progress |= _write_block.execute(block_io); break;
|
||||
case WRITE_BLK_SUCCEEDED:
|
||||
|
||||
_generate_req<Block_io::Sync>(_sb_idx ? SB_COMPLETE : WRITE_HASH_TO_TA, progress);
|
||||
progress = true;
|
||||
_sync_block_io.generate(_helper, SYNC_BLOCK_IO, _sb_idx ? SB_COMPLETE : WRITE_HASH_TO_TA, progress);
|
||||
break;
|
||||
|
||||
case SYNC_BLOCK_IO: progress |= _sync_block_io.execute(block_io); break;
|
||||
case WRITE_HASH_TO_TA:
|
||||
|
||||
calc_hash(_blk, _hash);
|
||||
_generate_req<Trust_anchor::Write_hash>(SB_COMPLETE, progress, _hash);
|
||||
_write_sb_hash.generate(_helper, WRITE_SB_HASH, SB_COMPLETE, progress, _hash);
|
||||
break;
|
||||
|
||||
case WRITE_SB_HASH: progress |= _write_sb_hash.execute(trust_anchor); break;
|
||||
case SB_COMPLETE:
|
||||
|
||||
if (_sb_idx < NR_OF_SUPERBLOCK_SLOTS - 1) {
|
||||
_sb_idx++;
|
||||
_sb = { };
|
||||
_sb.encode_to_blk(_blk);
|
||||
_generate_req<Block_io::Write>(WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk);
|
||||
_write_block.generate(_helper, WRITE_BLK, WRITE_BLK_SUCCEEDED, progress, _sb_idx, _blk);
|
||||
} else
|
||||
_mark_req_successful(progress);
|
||||
_helper.mark_succeeded(progress);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Sb_initializer::Sb_initializer()
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++);
|
||||
add_channel(*chan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Sb_initializer::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
return progress;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,174 +16,132 @@
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Trust_anchor_request::Trust_anchor_request(Module_id src_module_id, Module_channel_id src_chan_id,
|
||||
Type type, Key_value &key_plaintext, Key_value &key_ciphertext,
|
||||
Hash &hash, Passphrase passphrase, bool &success)
|
||||
:
|
||||
Module_request { src_module_id, src_chan_id, TRUST_ANCHOR }, _type { type }, _key_plaintext { key_plaintext },
|
||||
_key_ciphertext { key_ciphertext }, _hash { hash }, _pass { passphrase }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
char const *Trust_anchor_request::type_to_string(Type type)
|
||||
bool Trust_anchor::Encrypt_key::execute(Trust_anchor::Attr const &ta_attr)
|
||||
{
|
||||
switch (type) {
|
||||
case CREATE_KEY: return "create_key";
|
||||
case ENCRYPT_KEY: return "encrypt_key";
|
||||
case DECRYPT_KEY: return "decrypt_key";
|
||||
case WRITE_HASH: return "write_hash";
|
||||
case READ_HASH: return "read_hash";
|
||||
case INITIALIZE: return "initialize";
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_file.construct(_helper.state, ta_attr.encrypt_file);
|
||||
_helper.state = WRITE;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
void Trust_anchor_channel::_mark_req_failed(bool &progress, Error_string str)
|
||||
{
|
||||
error("trust_anchor: request (", *_req_ptr, ") failed: ", str);
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
req._success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor_channel::_read_hash(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _hashsum_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._hash, HASH_SIZE }, progress); break;
|
||||
case READ_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_key_plaintext, KEY_SIZE }, progress); break;
|
||||
case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_key_ciphertext, KEY_SIZE }, progress); break;
|
||||
case READ_OK: _helper.mark_succeeded(progress); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor_channel::_create_key(bool &progress)
|
||||
bool Trust_anchor::Decrypt_key::execute(Trust_anchor::Attr const &ta_attr)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _generate_key_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._key_plaintext, KEY_SIZE }, progress); break;
|
||||
case READ_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_file.construct(_helper.state, ta_attr.decrypt_file);
|
||||
_helper.state = WRITE;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_key_ciphertext, KEY_SIZE }, progress); break;
|
||||
case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_key_plaintext, KEY_SIZE }, progress); break;
|
||||
case READ_OK: _helper.mark_succeeded(progress); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor_channel::_initialize(bool &progress)
|
||||
bool Trust_anchor::Write_hash::execute(Trust_anchor::Attr const &ta_attr)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _initialize_file.write(WRITE_OK, FILE_ERR, 0, { req._pass.string(), req._pass.length() - 1 }, progress); break;
|
||||
case WRITE_OK: _initialize_file.read(READ_OK, FILE_ERR, 0, { _result_buf, sizeof(_result_buf) }, progress); break;
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_file.construct(_helper.state, ta_attr.hash_file);
|
||||
_helper.state = WRITE;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { (char *)&_attr.in_hash, HASH_SIZE }, progress); break;
|
||||
case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { _result_buf, sizeof(_result_buf) }, progress); break;
|
||||
case READ_OK: _helper.mark_succeeded(progress); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
bool Trust_anchor::Read_hash::execute(Trust_anchor::Attr const &ta_attr)
|
||||
{
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_file.construct(_helper.state, ta_attr.hash_file);
|
||||
_helper.state = READ;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case READ: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_hash, HASH_SIZE }, progress); break;
|
||||
case READ_OK: _helper.mark_succeeded(progress); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
bool Trust_anchor::Generate_key::execute(Trust_anchor::Attr const &ta_attr)
|
||||
{
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_file.construct(_helper.state, ta_attr.generate_key_file);
|
||||
_helper.state = READ;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case READ: _file->read(READ_OK, FILE_ERR, 0, { (char *)&_attr.out_key_plaintext, KEY_SIZE }, progress); break;
|
||||
case READ_OK: _helper.mark_succeeded(progress); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
bool Trust_anchor::Initialize::execute(Trust_anchor::Attr const &ta_attr)
|
||||
{
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_file.construct(_helper.state, ta_attr.initialize_file);
|
||||
_helper.state = WRITE;
|
||||
progress = true;
|
||||
break;
|
||||
|
||||
case WRITE: _file->write(WRITE_OK, FILE_ERR, 0, { _attr.in_passphrase.string(), _attr.in_passphrase.length() - 1 }, progress); break;
|
||||
case WRITE_OK: _file->read(READ_OK, FILE_ERR, 0, { _result_buf, sizeof(_result_buf) }, progress); break;
|
||||
case READ_OK:
|
||||
|
||||
if (strcmp(_result_buf, "ok", sizeof(_result_buf)))
|
||||
_mark_req_failed(progress, { "trust anchor did not return \"ok\""});
|
||||
_helper.mark_failed(progress, {"trust anchor did not return \"ok\""});
|
||||
else
|
||||
_mark_req_successful(progress);
|
||||
_helper.mark_succeeded(progress);
|
||||
break;
|
||||
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
case FILE_ERR: _helper.mark_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor_channel::_write_hash(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _hashsum_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._hash, HASH_SIZE }, progress); break;
|
||||
case WRITE_OK: _hashsum_file.read(READ_OK, FILE_ERR, 0, { _result_buf, 0 }, progress); break;
|
||||
case READ_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor_channel::_encrypt_key(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _encrypt_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._key_plaintext, KEY_SIZE }, progress); break;
|
||||
case WRITE_OK: _encrypt_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._key_ciphertext, KEY_SIZE }, progress); break;
|
||||
case READ_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor_channel::_decrypt_key(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED: _decrypt_file.write(WRITE_OK, FILE_ERR, 0, { (char *)&req._key_ciphertext, KEY_SIZE }, progress); break;
|
||||
case WRITE_OK: _decrypt_file.read(READ_OK, FILE_ERR, 0, { (char *)&req._key_plaintext, KEY_SIZE }, progress); break;
|
||||
case READ_OK: _mark_req_successful(progress); break;
|
||||
case FILE_ERR: _mark_req_failed(progress, "file operation failed"); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
switch (req._type) {
|
||||
case Request::INITIALIZE: _initialize(progress); break;
|
||||
case Request::WRITE_HASH: _write_hash(progress); break;
|
||||
case Request::READ_HASH: _read_hash(progress); break;
|
||||
case Request::CREATE_KEY: _create_key(progress); break;
|
||||
case Request::ENCRYPT_KEY: _encrypt_key(progress); break;
|
||||
case Request::DECRYPT_KEY: _decrypt_key(progress); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Trust_anchor_channel::Trust_anchor_channel(Module_channel_id id, Vfs::Env &vfs_env, Xml_node const &xml_node)
|
||||
:
|
||||
Module_channel { TRUST_ANCHOR, id }, _vfs_env { vfs_env }, _path { xml_node.attribute_value("path", Tresor::Path()) }
|
||||
{ }
|
||||
|
||||
|
||||
Trust_anchor::Trust_anchor(Vfs::Env &vfs_env, Xml_node const &xml_node)
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++, vfs_env, xml_node);
|
||||
add_channel(*chan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
void Trust_anchor::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
return progress;
|
||||
}
|
||||
|
@ -13,52 +13,31 @@
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/vbd_check.h>
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/hash.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Vbd_check_request::Vbd_check_request(Module_id src_mod, Module_channel_id src_chan, Tree_root const &vbd, bool &success)
|
||||
:
|
||||
Module_request { src_mod, src_chan, VBD_CHECK }, _vbd { vbd }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
void Vbd_check_channel::_generated_req_completed(State_uint state_uint)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("vbd check: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress)
|
||||
bool Vbd_check::Check::_execute_node(Block_io &block_io, Tree_level_index lvl, Tree_node_index node_idx, bool &progress)
|
||||
{
|
||||
bool &check_node = _check_node[lvl][node_idx];
|
||||
if (!check_node)
|
||||
return false;
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
Type_1_node const &node = _t1_blks.items[lvl].nodes[node_idx];
|
||||
switch (_state) {
|
||||
case REQ_IN_PROGRESS:
|
||||
switch (_helper.state) {
|
||||
case IN_PROGRESS:
|
||||
|
||||
if (lvl == 1) {
|
||||
if (!_num_remaining_leaves) {
|
||||
if (node.valid()) {
|
||||
_mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node,
|
||||
") valid but no leaves remaining" });
|
||||
_helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node,
|
||||
") valid but no leaves remaining" });
|
||||
break;
|
||||
}
|
||||
check_node = false;
|
||||
progress = true;
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid");
|
||||
log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid");
|
||||
break;
|
||||
}
|
||||
if (node.gen == INITIAL_GENERATION) {
|
||||
@ -66,33 +45,34 @@ bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node
|
||||
check_node = false;
|
||||
progress = true;
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": uninitialized");
|
||||
log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": uninitialized");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (!node.valid()) {
|
||||
if (_num_remaining_leaves) {
|
||||
_mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ",
|
||||
_num_remaining_leaves, " leaves remaining" });
|
||||
_helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " invalid but ",
|
||||
_num_remaining_leaves, " leaves remaining" });
|
||||
break;
|
||||
}
|
||||
check_node = false;
|
||||
progress = true;
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid");
|
||||
log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": expectedly invalid");
|
||||
break;
|
||||
}
|
||||
}
|
||||
_generate_req<Block_io::Read>(READ_BLK_SUCCEEDED, progress, node.pba, _blk);
|
||||
_read_block.generate(_helper, READ_BLK, READ_BLK_SUCCEEDED, progress, node.pba, _blk);
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, " (", node,
|
||||
log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, " (", node,
|
||||
"): load to lvl ", lvl - 1);
|
||||
break;
|
||||
|
||||
case READ_BLK: progress |= _read_block.execute(block_io); break;
|
||||
case READ_BLK_SUCCEEDED:
|
||||
|
||||
if (!(lvl > 1 && node.gen == INITIAL_GENERATION) && !check_hash(_blk, node.hash)) {
|
||||
_mark_req_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" });
|
||||
_helper.mark_failed(progress, { "lvl ", lvl, " node ", node_idx, " (", node, ") has bad hash" });
|
||||
break;
|
||||
}
|
||||
if (lvl == 1)
|
||||
@ -103,10 +83,10 @@ bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node
|
||||
cn = true;
|
||||
}
|
||||
check_node = false;
|
||||
_state = REQ_IN_PROGRESS;
|
||||
_helper.state = IN_PROGRESS;
|
||||
progress = true;
|
||||
if (VERBOSE_CHECK)
|
||||
log(Level_indent { lvl, req._vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": good hash");
|
||||
log(Level_indent { lvl, _attr.in_vbd.max_lvl }, " lvl ", lvl, " node ", node_idx, ": good hash");
|
||||
break;
|
||||
|
||||
default: break;
|
||||
@ -115,69 +95,24 @@ bool Vbd_check_channel::_execute_node(Tree_level_index lvl, Tree_node_index node
|
||||
}
|
||||
|
||||
|
||||
void Vbd_check_channel::execute(bool &progress)
|
||||
bool Vbd_check::Check::execute(Block_io &block_io)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
if (_state == REQ_SUBMITTED) {
|
||||
for (Tree_level_index lvl { 1 }; lvl <= req._vbd.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx { 0 }; node_idx < req._vbd.degree; node_idx++)
|
||||
bool progress = false;
|
||||
if (_helper.state == INIT) {
|
||||
for (Tree_level_index lvl { 1 }; lvl <= _attr.in_vbd.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_vbd.degree; node_idx++)
|
||||
_check_node[lvl][node_idx] = false;
|
||||
|
||||
_num_remaining_leaves = req._vbd.num_leaves;
|
||||
_t1_blks.items[req._vbd.max_lvl + 1].nodes[0] = req._vbd.t1_node();
|
||||
_check_node[req._vbd.max_lvl + 1][0] = true;
|
||||
_state = REQ_IN_PROGRESS;
|
||||
_num_remaining_leaves = _attr.in_vbd.num_leaves;
|
||||
_t1_blks.items[_attr.in_vbd.max_lvl + 1].nodes[0] = _attr.in_vbd.t1_node();
|
||||
_check_node[_attr.in_vbd.max_lvl + 1][0] = true;
|
||||
_helper.state = IN_PROGRESS;
|
||||
}
|
||||
for (Tree_level_index lvl { 1 }; lvl <= req._vbd.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx { 0 }; node_idx < req._vbd.degree; node_idx++)
|
||||
if (_execute_node(lvl, node_idx, progress))
|
||||
return;
|
||||
for (Tree_level_index lvl { 1 }; lvl <= _attr.in_vbd.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx { 0 }; node_idx < _attr.in_vbd.degree; node_idx++)
|
||||
if (_execute_node(block_io, lvl, node_idx, progress))
|
||||
return progress;
|
||||
|
||||
_mark_req_successful(progress);
|
||||
}
|
||||
|
||||
|
||||
void Vbd_check_channel::_mark_req_failed(bool &progress, Error_string str)
|
||||
{
|
||||
error("vbd check request (", *_req_ptr, ") failed: ", str);
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Vbd_check_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
_req_ptr->_success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Vbd_check_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
Vbd_check::Vbd_check()
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++);
|
||||
add_channel(*chan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Vbd_check::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
_helper.mark_succeeded(progress);
|
||||
return progress;
|
||||
}
|
||||
|
@ -13,20 +13,12 @@
|
||||
*/
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/block_io.h>
|
||||
#include <tresor/hash.h>
|
||||
#include <tresor/vbd_initializer.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Vbd_initializer_request::Vbd_initializer_request(Module_id src_mod, Module_channel_id src_chan, Tree_root &vbd,
|
||||
Pba_allocator &pba_alloc, bool &success)
|
||||
:
|
||||
Module_request { src_mod, src_chan, VBD_INITIALIZER }, _vbd { vbd }, _pba_alloc { pba_alloc }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress)
|
||||
bool Vbd_initializer::Initialize::_execute_node(Tree_level_index lvl, Tree_node_index node_idx, bool &progress)
|
||||
{
|
||||
Type_1_node &node = _t1_blks.items[lvl].nodes[node_idx];
|
||||
Node_state &node_state = _node_states[lvl][node_idx];
|
||||
@ -58,8 +50,8 @@ bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_inde
|
||||
if (lvl == 1)
|
||||
if (_num_remaining_leaves) {
|
||||
node = { };
|
||||
if (!_req_ptr->_pba_alloc.alloc(node.pba)) {
|
||||
_mark_req_failed(progress, "allocate pba");
|
||||
if (!_attr.in_out_pba_alloc.alloc(node.pba)) {
|
||||
_helper.mark_failed(progress, "allocate pba");
|
||||
break;
|
||||
}
|
||||
node_state = DONE;
|
||||
@ -76,21 +68,20 @@ bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_inde
|
||||
}
|
||||
else {
|
||||
node = { };
|
||||
if (!_req_ptr->_pba_alloc.alloc(node.pba)) {
|
||||
_mark_req_failed(progress, "allocate pba");
|
||||
if (!_attr.in_out_pba_alloc.alloc(node.pba)) {
|
||||
_helper.mark_failed(progress, "allocate pba");
|
||||
break;
|
||||
}
|
||||
_t1_blks.items[lvl - 1].encode_to_blk(_blk);
|
||||
calc_hash(_blk, node.hash);
|
||||
node_state = WRITE_BLOCK;
|
||||
generate_req<Block_io::Write>(EXECUTE_NODES, progress, node.pba, _blk, _generated_req_success);
|
||||
_state = REQ_GENERATED;
|
||||
_write_block.generate(_helper, WRITE_BLOCK, EXECUTE_NODES, progress, node.pba, _blk);
|
||||
node_state = WRITING_BLOCK;
|
||||
if (VERBOSE_VBD_INIT)
|
||||
log("[vbd_init] node: ", lvl, " ", node_idx, " assign pba: ", node.pba);
|
||||
}
|
||||
break;
|
||||
|
||||
case WRITE_BLOCK:
|
||||
case WRITING_BLOCK:
|
||||
|
||||
ASSERT(lvl > 1);
|
||||
node_state = DONE;
|
||||
@ -103,103 +94,47 @@ bool Vbd_initializer_channel::_execute_node(Tree_level_index lvl, Tree_node_inde
|
||||
}
|
||||
|
||||
|
||||
void Vbd_initializer_channel::_generated_req_completed(State_uint state_uint)
|
||||
bool Vbd_initializer::Initialize::execute(Block_io &block_io)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("vbd initializer: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
|
||||
void Vbd_initializer_channel::_mark_req_failed(bool &progress, char const *str)
|
||||
{
|
||||
error("vbd_initializer request (", *_req_ptr, ") failed because: ", str);
|
||||
_req_ptr->_success = false;
|
||||
_state = COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Vbd_initializer_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
_req_ptr->_vbd.t1_node(_t1_blks.items[_req_ptr->_vbd.max_lvl + 1].nodes[0]);
|
||||
_req_ptr->_success = true;
|
||||
_state = COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Vbd_initializer_channel::_request_submitted(Module_request &mod_req)
|
||||
{
|
||||
_req_ptr = static_cast<Request *>(&mod_req);
|
||||
_state = SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
void Vbd_initializer_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
Request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case SUBMITTED:
|
||||
|
||||
_num_remaining_leaves = req._vbd.num_leaves;
|
||||
_num_remaining_leaves = _attr.in_tree_cfg.num_leaves;
|
||||
for (Tree_level_index lvl = 0; lvl < TREE_MAX_LEVEL; lvl++)
|
||||
_reset_level(lvl, Vbd_initializer_channel::DONE);
|
||||
_reset_level(lvl, Vbd_initializer::Initialize::DONE);
|
||||
|
||||
_node_states[req._vbd.max_lvl + 1][0] = Vbd_initializer_channel::INIT_BLOCK;
|
||||
_state = EXECUTE_NODES;
|
||||
_node_states[_attr.in_tree_cfg.max_lvl + 1][0] = Vbd_initializer::Initialize::INIT_BLOCK;
|
||||
_helper.state = EXECUTE_NODES;
|
||||
progress = true;
|
||||
return;
|
||||
break;
|
||||
|
||||
case EXECUTE_NODES:
|
||||
|
||||
for (Tree_level_index lvl = 0; lvl <= req._vbd.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx = 0; node_idx < req._vbd.degree; node_idx++)
|
||||
for (Tree_level_index lvl = 0; lvl <= _attr.in_tree_cfg.max_lvl + 1; lvl++)
|
||||
for (Tree_node_index node_idx = 0; node_idx < _attr.in_tree_cfg.degree; node_idx++)
|
||||
if (_execute_node(lvl, node_idx, progress))
|
||||
return;
|
||||
return progress;
|
||||
|
||||
if (_num_remaining_leaves)
|
||||
_mark_req_failed(progress, "leaves remaining");
|
||||
else
|
||||
_mark_req_successful(progress);
|
||||
return;
|
||||
_helper.mark_failed(progress, "leaves remaining");
|
||||
else {
|
||||
_attr.out_tree_root = _t1_blks.items[_attr.in_tree_cfg.max_lvl + 1].nodes[0];
|
||||
_helper.mark_succeeded(progress);
|
||||
}
|
||||
break;
|
||||
|
||||
default: return;
|
||||
case WRITE_BLOCK: progress |= _write_block.execute(block_io); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
|
||||
void Vbd_initializer_channel::_reset_level(Tree_level_index lvl, Node_state state)
|
||||
void Vbd_initializer::Initialize::_reset_level(Tree_level_index lvl, Node_state state)
|
||||
{
|
||||
for (unsigned int idx = 0; idx < NUM_NODES_PER_BLK; idx++) {
|
||||
_t1_blks.items[lvl].nodes[idx] = { };
|
||||
_node_states[lvl][idx] = state;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Vbd_initializer::Vbd_initializer()
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++);
|
||||
add_channel(*chan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Vbd_initializer::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Channel>([&] (Channel &chan) {
|
||||
chan.execute(progress); });
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,225 +0,0 @@
|
||||
/*
|
||||
* \brief Module for splitting unaligned/uneven I/O requests
|
||||
* \author Martin Stein
|
||||
* \author Josef Soentgen
|
||||
* \date 2023-09-11
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2023 Genode Labs GmbH
|
||||
*
|
||||
* This file is part of the Genode OS framework, which is distributed
|
||||
* under the terms of the GNU Affero General Public License version 3.
|
||||
*/
|
||||
|
||||
/* vfs tresor includes */
|
||||
#include <splitter.h>
|
||||
|
||||
using namespace Tresor;
|
||||
|
||||
Splitter_request::Splitter_request(Module_id src_mod, Module_channel_id src_chan, Operation op, bool &success,
|
||||
Request_offset off, Byte_range_ptr const &buf, Key_id key_id, Generation gen)
|
||||
:
|
||||
Module_request { src_mod, src_chan, SPLITTER }, _op { op }, _off { off }, _key_id { key_id }, _gen { gen },
|
||||
_buf { buf.start, buf.num_bytes }, _success { success }
|
||||
{ }
|
||||
|
||||
|
||||
char const *Splitter_request::op_to_string(Operation op)
|
||||
{
|
||||
switch (op) {
|
||||
case Operation::READ: return "read";
|
||||
case Operation::WRITE: return "write";
|
||||
}
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
|
||||
void Splitter_channel::_generated_req_completed(State_uint state_uint)
|
||||
{
|
||||
if (!_generated_req_success) {
|
||||
error("splitter: request (", *_req_ptr, ") failed because generated request failed)");
|
||||
_req_ptr->_success = false;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
return;
|
||||
}
|
||||
_state = (State)state_uint;
|
||||
}
|
||||
|
||||
|
||||
void Splitter_channel::_mark_req_successful(bool &progress)
|
||||
{
|
||||
Request &req { *_req_ptr };
|
||||
req._success = true;
|
||||
_state = REQ_COMPLETE;
|
||||
_req_ptr = nullptr;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
|
||||
void Splitter_channel::_request_submitted(Module_request &req)
|
||||
{
|
||||
_req_ptr = static_cast<Request*>(&req);
|
||||
_state = REQ_SUBMITTED;
|
||||
}
|
||||
|
||||
|
||||
void Splitter_channel::_advance_curr_off(addr_t advance, Tresor::Request::Operation op, bool &progress)
|
||||
{
|
||||
Splitter_request &req { *_req_ptr };
|
||||
_curr_off += advance;
|
||||
if (!_num_remaining_bytes()) {
|
||||
_mark_req_successful(progress);
|
||||
} else if (_curr_off % BLOCK_SIZE) {
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_req<Tresor::Request>(
|
||||
PROTRUDING_FIRST_BLK_READ, progress, Tresor::Request::READ, _curr_vba(), 0, 1, req._key_id, id(), _gen);
|
||||
} else if (_num_remaining_bytes() < BLOCK_SIZE) {
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_req<Tresor::Request>(
|
||||
PROTRUDING_LAST_BLK_READ, progress, Tresor::Request::READ, _curr_vba(), 0, 1, req._key_id, id(), _gen);
|
||||
} else {
|
||||
_curr_buf_addr = (addr_t)req._buf.start + _curr_buf_off();
|
||||
_generate_req<Tresor::Request>(
|
||||
INSIDE_BLKS_ACCESSED, progress, op, _curr_vba(), 0, _num_remaining_bytes() / BLOCK_SIZE, req._key_id, id(), _gen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Splitter_channel::_write(bool &progress)
|
||||
{
|
||||
Splitter_request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
_curr_off = 0;
|
||||
_gen = req._gen;
|
||||
_advance_curr_off(req._off, Tresor::Request::WRITE, progress);
|
||||
break;
|
||||
|
||||
case PROTRUDING_FIRST_BLK_READ:
|
||||
{
|
||||
size_t num_outside_bytes { _curr_off % BLOCK_SIZE };
|
||||
size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) };
|
||||
memcpy((void *)((addr_t)&_blk + num_outside_bytes), req._buf.start, num_inside_bytes);
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_req<Tresor::Request>(
|
||||
PROTRUDING_FIRST_BLK_WRITTEN, progress, Tresor::Request::WRITE, _curr_vba(), 0, 1, req._key_id, id(), _gen);
|
||||
break;
|
||||
}
|
||||
case PROTRUDING_FIRST_BLK_WRITTEN:
|
||||
{
|
||||
size_t num_outside_bytes { _curr_off % BLOCK_SIZE };
|
||||
size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) };
|
||||
_advance_curr_off(num_inside_bytes, Tresor::Request::WRITE, progress);
|
||||
break;
|
||||
}
|
||||
case INSIDE_BLKS_ACCESSED:
|
||||
|
||||
_advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, Tresor::Request::WRITE, progress);
|
||||
break;
|
||||
|
||||
case PROTRUDING_LAST_BLK_READ:
|
||||
|
||||
memcpy(&_blk, (void *)((addr_t)req._buf.start + _curr_buf_off()), _num_remaining_bytes());
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_req<Tresor::Request>(
|
||||
PROTRUDING_LAST_BLK_WRITTEN, progress, Tresor::Request::WRITE, _curr_vba(), 0, 1, req._key_id, id(), _gen);
|
||||
break;
|
||||
|
||||
case PROTRUDING_LAST_BLK_WRITTEN: _advance_curr_off(_num_remaining_bytes(), Tresor::Request::WRITE, progress); break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Splitter_channel::_read(bool &progress)
|
||||
{
|
||||
Splitter_request &req { *_req_ptr };
|
||||
switch (_state) {
|
||||
case REQ_SUBMITTED:
|
||||
|
||||
_curr_off = 0;
|
||||
_gen = req._gen;
|
||||
_advance_curr_off(req._off, Tresor::Request::READ, progress);
|
||||
break;
|
||||
|
||||
case PROTRUDING_FIRST_BLK_READ:
|
||||
{
|
||||
size_t num_outside_bytes { _curr_off % BLOCK_SIZE };
|
||||
size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) };
|
||||
memcpy(req._buf.start, (void *)((addr_t)&_blk + num_outside_bytes), num_inside_bytes);
|
||||
_advance_curr_off(num_inside_bytes, Tresor::Request::READ, progress);
|
||||
break;
|
||||
}
|
||||
case INSIDE_BLKS_ACCESSED:
|
||||
|
||||
_advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, Tresor::Request::READ, progress);
|
||||
break;
|
||||
|
||||
case PROTRUDING_LAST_BLK_READ:
|
||||
|
||||
memcpy((void *)((addr_t)req._buf.start + _curr_buf_off()), &_blk, _num_remaining_bytes());
|
||||
_advance_curr_off(_num_remaining_bytes(), Tresor::Request::READ, progress);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Splitter_channel::execute(bool &progress)
|
||||
{
|
||||
if (!_req_ptr)
|
||||
return;
|
||||
|
||||
switch (_req_ptr->_op) {
|
||||
case Request::READ: _read(progress); break;
|
||||
case Request::WRITE: _write(progress); break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Block &Splitter_channel::_blk_buf_for_vba(Virtual_block_address vba)
|
||||
{
|
||||
ASSERT(_state == REQ_GENERATED);
|
||||
return *(Block *)(_curr_buf_addr + (vba - _curr_vba()) * BLOCK_SIZE);
|
||||
}
|
||||
|
||||
|
||||
Block const &Splitter::src_for_writing_vba(Request_tag tag, Virtual_block_address vba)
|
||||
{
|
||||
Block const *blk_ptr { };
|
||||
with_channel<Splitter_channel>(tag, [&] (Splitter_channel &chan) {
|
||||
blk_ptr = &chan.src_for_writing_vba(vba); });
|
||||
ASSERT(blk_ptr);
|
||||
return *blk_ptr;
|
||||
}
|
||||
|
||||
|
||||
Block &Splitter::dst_for_reading_vba(Request_tag tag, Virtual_block_address vba)
|
||||
{
|
||||
Block *blk_ptr { };
|
||||
with_channel<Splitter_channel>(tag, [&] (Splitter_channel &chan) {
|
||||
blk_ptr = &chan.dst_for_reading_vba(vba); });
|
||||
ASSERT(blk_ptr);
|
||||
return *blk_ptr;
|
||||
}
|
||||
|
||||
|
||||
Splitter::Splitter()
|
||||
{
|
||||
Module_channel_id id { 0 };
|
||||
for (Constructible<Channel> &chan : _channels) {
|
||||
chan.construct(id++);
|
||||
add_channel(*chan);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Splitter::execute(bool &progress)
|
||||
{
|
||||
for_each_channel<Splitter_channel>([&] (Splitter_channel &chan) {
|
||||
chan.execute(progress); });
|
||||
}
|
@ -16,141 +16,393 @@
|
||||
#define _TRESOR__IO_SPLITTER_H_
|
||||
|
||||
/* tresor includes */
|
||||
#include <tresor/request_pool.h>
|
||||
#include <tresor/superblock_control.h>
|
||||
|
||||
namespace Tresor {
|
||||
namespace Tresor { class Splitter; }
|
||||
|
||||
struct Lookup_buffer : Genode::Interface
|
||||
{
|
||||
virtual Block const &src_for_writing_vba(Request_tag, Virtual_block_address) = 0;
|
||||
virtual Block &dst_for_reading_vba(Request_tag, Virtual_block_address) = 0;
|
||||
};
|
||||
|
||||
class Splitter_request;
|
||||
class Splitter_channel;
|
||||
class Splitter;
|
||||
}
|
||||
|
||||
|
||||
class Tresor::Splitter_request : public Tresor::Module_request
|
||||
struct Tresor::Splitter : Noncopyable
|
||||
{
|
||||
friend class Splitter_channel;
|
||||
|
||||
public:
|
||||
|
||||
enum Operation { READ, WRITE };
|
||||
class Read : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Splitter;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Request_offset const in_off;
|
||||
Generation const in_gen;
|
||||
char *const in_buf_start;
|
||||
size_t const in_buf_num_bytes;
|
||||
};
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock_control &sb_control;
|
||||
Virtual_block_device &vbd;
|
||||
Client_data_interface &client_data;
|
||||
Block_io &block_io;
|
||||
Crypto &crypto;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
INIT, COMPLETE, READ_FIRST_VBA, READ_FIRST_VBA_SUCCEEDED, READ_LAST_VBA, READ_LAST_VBA_SUCCEEDED,
|
||||
READ_MIDDLE_VBAS, READ_MIDDLE_VBAS_SUCCEEDED };
|
||||
|
||||
Request_helper<Read, State> _helper;
|
||||
Attr const _attr;
|
||||
addr_t _curr_off { };
|
||||
addr_t _curr_buf_addr { };
|
||||
Block _blk { };
|
||||
Generation _gen { };
|
||||
Constructible<Superblock_control::Read_vbas> _read_vbas { };
|
||||
|
||||
Virtual_block_address _curr_vba() const { return (Virtual_block_address)(_curr_off / BLOCK_SIZE); }
|
||||
|
||||
void _generate_read(State target_state, bool &progress)
|
||||
{
|
||||
Number_of_blocks num_blocks =
|
||||
target_state == READ_MIDDLE_VBAS ? _num_remaining_bytes() / BLOCK_SIZE : 1;
|
||||
|
||||
_read_vbas.construct(Superblock_control::Read_vbas::Attr{_curr_vba(), num_blocks, 0, 0});
|
||||
_helper.state = target_state;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
bool _execute_read(State succeeded_state, Execute_attr const &attr)
|
||||
{
|
||||
bool progress = attr.sb_control.execute(*_read_vbas, attr.vbd, attr.client_data, attr.block_io, attr.crypto);
|
||||
if (_read_vbas->complete()) {
|
||||
if (_read_vbas->success())
|
||||
_helper.generated_req_succeeded(succeeded_state, progress);
|
||||
else
|
||||
_helper.generated_req_failed(progress);
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
addr_t _curr_buf_off() const
|
||||
{
|
||||
ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes);
|
||||
return _curr_off - _attr.in_off;
|
||||
}
|
||||
|
||||
addr_t _num_remaining_bytes() const
|
||||
{
|
||||
ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes);
|
||||
return _attr.in_off + _attr.in_buf_num_bytes - _curr_off;
|
||||
}
|
||||
|
||||
void _advance_curr_off(size_t advance, bool &progress)
|
||||
{
|
||||
_curr_off += advance;
|
||||
if (!_num_remaining_bytes()) {
|
||||
_helper.mark_succeeded(progress);
|
||||
} else if (_curr_off % BLOCK_SIZE) {
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_read(READ_FIRST_VBA, progress);
|
||||
} else if (_num_remaining_bytes() < BLOCK_SIZE) {
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_read(READ_LAST_VBA, progress);
|
||||
} else {
|
||||
_curr_buf_addr = (addr_t)_attr.in_buf_start + _curr_buf_off();
|
||||
_generate_read(READ_MIDDLE_VBAS, progress);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Read(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "read"); }
|
||||
|
||||
bool execute(Execute_attr const &attr)
|
||||
{
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_gen = _attr.in_gen;
|
||||
_advance_curr_off(_attr.in_off, progress);
|
||||
break;
|
||||
|
||||
case READ_FIRST_VBA: progress |= _execute_read(READ_FIRST_VBA_SUCCEEDED, attr); break;
|
||||
case READ_FIRST_VBA_SUCCEEDED:
|
||||
{
|
||||
size_t num_outside_bytes { _curr_off % BLOCK_SIZE };
|
||||
size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) };
|
||||
memcpy(_attr.in_buf_start, (void *)((addr_t)&_blk + num_outside_bytes), num_inside_bytes);
|
||||
_advance_curr_off(num_inside_bytes, progress);
|
||||
break;
|
||||
}
|
||||
case READ_MIDDLE_VBAS: progress |= _execute_read(READ_MIDDLE_VBAS_SUCCEEDED, attr); break;
|
||||
case READ_MIDDLE_VBAS_SUCCEEDED:
|
||||
|
||||
_advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, progress);
|
||||
break;
|
||||
|
||||
case READ_LAST_VBA: progress |= _execute_read(READ_LAST_VBA_SUCCEEDED, attr); break;
|
||||
case READ_LAST_VBA_SUCCEEDED:
|
||||
|
||||
memcpy((void *)((addr_t)_attr.in_buf_start + _curr_buf_off()), &_blk, _num_remaining_bytes());
|
||||
_advance_curr_off(_num_remaining_bytes(), progress);
|
||||
break;
|
||||
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
Block &destination_buffer(Virtual_block_address vba)
|
||||
{
|
||||
return *(Block *)(_curr_buf_addr + (vba - _curr_vba()) * BLOCK_SIZE);
|
||||
}
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
class Write : Noncopyable
|
||||
{
|
||||
public:
|
||||
|
||||
using Module = Splitter;
|
||||
|
||||
struct Attr
|
||||
{
|
||||
Request_offset const in_off;
|
||||
Generation const in_gen;
|
||||
char const *const in_buf_start;
|
||||
size_t const in_buf_num_bytes;
|
||||
};
|
||||
|
||||
struct Execute_attr
|
||||
{
|
||||
Superblock_control &sb_control;
|
||||
Virtual_block_device &vbd;
|
||||
Client_data_interface &client_data;
|
||||
Block_io &block_io;
|
||||
Free_tree &free_tree;
|
||||
Meta_tree &meta_tree;
|
||||
Crypto &crypto;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
enum State {
|
||||
INIT, COMPLETE, READ_FIRST_VBA, READ_FIRST_VBA_SUCCEEDED, READ_LAST_VBA, READ_LAST_VBA_SUCCEEDED,
|
||||
WRITE_FIRST_VBA, WRITE_FIRST_VBA_SUCCEEDED, WRITE_LAST_VBA, WRITE_LAST_VBA_SUCCEEDED,
|
||||
WRITE_MIDDLE_VBAS, WRITE_MIDDLE_VBAS_SUCCEEDED };
|
||||
|
||||
|
||||
Request_helper<Write, State> _helper;
|
||||
Attr const _attr;
|
||||
addr_t _curr_off { };
|
||||
addr_t _curr_buf_addr { };
|
||||
Block _blk { };
|
||||
Generation _gen { };
|
||||
Constructible<Superblock_control::Read_vbas> _read_vbas { };
|
||||
Constructible<Superblock_control::Write_vbas> _write_vbas { };
|
||||
|
||||
Virtual_block_address _curr_vba() const { return (Virtual_block_address)(_curr_off / BLOCK_SIZE); }
|
||||
|
||||
addr_t _curr_buf_off() const
|
||||
{
|
||||
ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes);
|
||||
return _curr_off - _attr.in_off;
|
||||
}
|
||||
|
||||
addr_t _num_remaining_bytes() const
|
||||
{
|
||||
ASSERT(_curr_off >= _attr.in_off && _curr_off <= _attr.in_off + _attr.in_buf_num_bytes);
|
||||
return _attr.in_off + _attr.in_buf_num_bytes - _curr_off;
|
||||
}
|
||||
|
||||
void _generate_sb_control_request(State target_state, bool &progress)
|
||||
{
|
||||
Number_of_blocks num_blocks =
|
||||
target_state == WRITE_MIDDLE_VBAS ? _num_remaining_bytes() / BLOCK_SIZE : 1;
|
||||
|
||||
switch (target_state) {
|
||||
case READ_FIRST_VBA:
|
||||
case READ_LAST_VBA: _read_vbas.construct(Superblock_control::Read_vbas::Attr{_curr_vba(), num_blocks, 0, 0}); break;
|
||||
case WRITE_FIRST_VBA:
|
||||
case WRITE_MIDDLE_VBAS:
|
||||
case WRITE_LAST_VBA: _write_vbas.construct(Superblock_control::Write_vbas::Attr{_curr_vba(), num_blocks, 0, 0}); break;
|
||||
default: ASSERT_NEVER_REACHED;
|
||||
}
|
||||
_helper.state = target_state;
|
||||
progress = true;
|
||||
}
|
||||
|
||||
void _advance_curr_off(size_t advance, bool &progress)
|
||||
{
|
||||
_curr_off += advance;
|
||||
if (!_num_remaining_bytes()) {
|
||||
_helper.mark_succeeded(progress);
|
||||
} else if (_curr_off % BLOCK_SIZE) {
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_sb_control_request(READ_FIRST_VBA, progress);
|
||||
} else if (_num_remaining_bytes() < BLOCK_SIZE) {
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_sb_control_request(READ_LAST_VBA, progress);
|
||||
} else {
|
||||
_curr_buf_addr = (addr_t)_attr.in_buf_start + _curr_buf_off();
|
||||
_generate_sb_control_request(WRITE_MIDDLE_VBAS, progress);
|
||||
}
|
||||
}
|
||||
|
||||
bool _execute_read(State succeeded_state, Execute_attr const &attr)
|
||||
{
|
||||
bool progress = attr.sb_control.execute(*_read_vbas, attr.vbd, attr.client_data, attr.block_io, attr.crypto);
|
||||
if (_read_vbas->complete()) {
|
||||
if (_read_vbas->success())
|
||||
_helper.generated_req_succeeded(succeeded_state, progress);
|
||||
else
|
||||
_helper.generated_req_failed(progress);
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
bool _execute_write(State succeeded_state, Execute_attr const &attr)
|
||||
{
|
||||
bool progress = attr.sb_control.execute(*_write_vbas, attr.vbd, attr.client_data, attr.block_io, attr.free_tree, attr.meta_tree, attr.crypto);
|
||||
if (_write_vbas->complete()) {
|
||||
if (_write_vbas->success())
|
||||
_helper.generated_req_succeeded(succeeded_state, progress);
|
||||
else
|
||||
_helper.generated_req_failed(progress);
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Write(Attr const &attr) : _helper(*this), _attr(attr) { }
|
||||
|
||||
void print(Output &out) const { Genode::print(out, "write"); }
|
||||
|
||||
bool execute(Execute_attr const &attr)
|
||||
{
|
||||
bool progress = false;
|
||||
switch (_helper.state) {
|
||||
case INIT:
|
||||
|
||||
_gen = _attr.in_gen;
|
||||
_advance_curr_off(_attr.in_off, progress);
|
||||
break;
|
||||
|
||||
case READ_FIRST_VBA: progress |= _execute_read(READ_FIRST_VBA_SUCCEEDED, attr); break;
|
||||
case READ_FIRST_VBA_SUCCEEDED:
|
||||
{
|
||||
size_t num_outside_bytes { _curr_off % BLOCK_SIZE };
|
||||
size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) };
|
||||
memcpy((void *)((addr_t)&_blk + num_outside_bytes), _attr.in_buf_start, num_inside_bytes);
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_sb_control_request(WRITE_FIRST_VBA, progress);
|
||||
break;
|
||||
}
|
||||
case WRITE_FIRST_VBA: progress |= _execute_write(WRITE_FIRST_VBA_SUCCEEDED, attr); break;
|
||||
case WRITE_FIRST_VBA_SUCCEEDED:
|
||||
{
|
||||
size_t num_outside_bytes { _curr_off % BLOCK_SIZE };
|
||||
size_t num_inside_bytes { min(_num_remaining_bytes(), BLOCK_SIZE - num_outside_bytes) };
|
||||
_advance_curr_off(num_inside_bytes, progress);
|
||||
break;
|
||||
}
|
||||
case WRITE_MIDDLE_VBAS: progress |= _execute_write(WRITE_MIDDLE_VBAS_SUCCEEDED, attr); break;
|
||||
case WRITE_MIDDLE_VBAS_SUCCEEDED:
|
||||
|
||||
_advance_curr_off((_num_remaining_bytes() / BLOCK_SIZE) * BLOCK_SIZE, progress);
|
||||
break;
|
||||
|
||||
case READ_LAST_VBA: progress |= _execute_read(READ_LAST_VBA_SUCCEEDED, attr); break;
|
||||
case READ_LAST_VBA_SUCCEEDED:
|
||||
|
||||
memcpy(&_blk, (void *)((addr_t)_attr.in_buf_start + _curr_buf_off()), _num_remaining_bytes());
|
||||
_curr_buf_addr = (addr_t)&_blk;
|
||||
_generate_sb_control_request(WRITE_LAST_VBA, progress);
|
||||
break;
|
||||
|
||||
case WRITE_LAST_VBA: progress |= _execute_write(WRITE_LAST_VBA_SUCCEEDED, attr); break;
|
||||
case WRITE_LAST_VBA_SUCCEEDED: _advance_curr_off(_num_remaining_bytes(), progress); break;
|
||||
default: break;
|
||||
}
|
||||
return progress;
|
||||
}
|
||||
|
||||
Block const &source_buffer(Virtual_block_address vba)
|
||||
{
|
||||
return *(Block *)(_curr_buf_addr + (vba - _curr_vba()) * BLOCK_SIZE);
|
||||
}
|
||||
|
||||
Block &destination_buffer()
|
||||
{
|
||||
ASSERT(_helper.state == READ_FIRST_VBA || _helper.state == READ_LAST_VBA);
|
||||
return _blk;
|
||||
}
|
||||
|
||||
bool complete() const { return _helper.complete(); }
|
||||
bool success() const { return _helper.success(); }
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Operation const _op;
|
||||
Request_offset const _off;
|
||||
Key_id const _key_id;
|
||||
Generation const _gen;
|
||||
Byte_range_ptr const _buf;
|
||||
bool &_success;
|
||||
|
||||
NONCOPYABLE(Splitter_request);
|
||||
Read *_read_ptr { };
|
||||
Write *_write_ptr { };
|
||||
|
||||
public:
|
||||
|
||||
Splitter_request(Module_id, Module_channel_id, Operation, bool &, Request_offset, Byte_range_ptr const &, Key_id, Generation);
|
||||
|
||||
static char const *op_to_string(Operation);
|
||||
|
||||
void print(Genode::Output &out) const override { Genode::print(out, op_to_string(_op), " off ", _off, " size ", _buf.num_bytes); }
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Splitter_channel : public Tresor::Module_channel
|
||||
{
|
||||
private:
|
||||
|
||||
using Request = Splitter_request;
|
||||
|
||||
|
||||
enum State : State_uint {
|
||||
PROTRUDING_FIRST_BLK_WRITTEN, PROTRUDING_LAST_BLK_WRITTEN, PROTRUDING_FIRST_BLK_READ, PROTRUDING_LAST_BLK_READ, INSIDE_BLKS_ACCESSED,
|
||||
REQ_SUBMITTED, REQ_GENERATED, REQ_COMPLETE };
|
||||
|
||||
State _state { };
|
||||
Request *_req_ptr { };
|
||||
addr_t _curr_off { };
|
||||
addr_t _curr_buf_addr { };
|
||||
Block _blk { };
|
||||
Generation _gen { };
|
||||
bool _generated_req_success { };
|
||||
|
||||
NONCOPYABLE(Splitter_channel);
|
||||
|
||||
void _generated_req_completed(State_uint) override;
|
||||
|
||||
void _request_submitted(Module_request &) override;
|
||||
|
||||
bool _request_complete() override { return _state == REQ_COMPLETE; }
|
||||
|
||||
Virtual_block_address _curr_vba() const { return (Virtual_block_address)(_curr_off / BLOCK_SIZE); }
|
||||
|
||||
addr_t _curr_buf_off() const
|
||||
bool execute(Read &req, Read::Execute_attr const &attr)
|
||||
{
|
||||
ASSERT(_curr_off >= _req_ptr->_off && _curr_off <= _req_ptr->_off + _req_ptr->_buf.num_bytes);
|
||||
return _curr_off - _req_ptr->_off;
|
||||
if (!_read_ptr && !_write_ptr)
|
||||
_read_ptr = &req;
|
||||
|
||||
if (_read_ptr != &req)
|
||||
return false;
|
||||
|
||||
bool progress = req.execute(attr);
|
||||
if (req.complete())
|
||||
_read_ptr = nullptr;
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
addr_t _num_remaining_bytes() const
|
||||
bool execute(Write &req, Write::Execute_attr const &attr)
|
||||
{
|
||||
ASSERT(_curr_off >= _req_ptr->_off && _curr_off <= _req_ptr->_off + _req_ptr->_buf.num_bytes);
|
||||
return _req_ptr->_off + _req_ptr->_buf.num_bytes - _curr_off;
|
||||
if (!_write_ptr && !_write_ptr)
|
||||
_write_ptr = &req;
|
||||
|
||||
if (_write_ptr != &req)
|
||||
return false;
|
||||
|
||||
bool progress = req.execute(attr);
|
||||
if (req.complete())
|
||||
_write_ptr = nullptr;
|
||||
|
||||
return progress;
|
||||
}
|
||||
|
||||
template <typename REQUEST, typename... ARGS>
|
||||
void _generate_req(State_uint state, bool &progress, ARGS &&... args)
|
||||
Block const &source_buffer(Virtual_block_address vba)
|
||||
{
|
||||
_state = REQ_GENERATED;
|
||||
generate_req<REQUEST>(state, progress, args..., _generated_req_success);
|
||||
ASSERT(_write_ptr);
|
||||
return _write_ptr->source_buffer(vba);
|
||||
}
|
||||
|
||||
void _mark_req_successful(bool &);
|
||||
Block &destination_buffer(Virtual_block_address vba)
|
||||
{
|
||||
if (_read_ptr)
|
||||
return _read_ptr->destination_buffer(vba);
|
||||
if (_write_ptr)
|
||||
return _write_ptr->destination_buffer();
|
||||
ASSERT_NEVER_REACHED;
|
||||
}
|
||||
|
||||
void _advance_curr_off(addr_t, Tresor::Request::Operation, bool &);
|
||||
|
||||
void _read(bool &progress);
|
||||
|
||||
void _write(bool &progress);
|
||||
|
||||
Block &_blk_buf_for_vba(Virtual_block_address);
|
||||
|
||||
public:
|
||||
|
||||
Splitter_channel(Module_channel_id id) : Module_channel { SPLITTER, id } { }
|
||||
|
||||
void execute(bool &progress);
|
||||
|
||||
Block const &src_for_writing_vba(Virtual_block_address vba) { return _blk_buf_for_vba(vba); }
|
||||
|
||||
Block &dst_for_reading_vba(Virtual_block_address vba) { return _blk_buf_for_vba(vba); }
|
||||
static constexpr char const *name() { return "sb_control"; }
|
||||
};
|
||||
|
||||
|
||||
class Tresor::Splitter : public Tresor::Module, public Tresor::Lookup_buffer
|
||||
{
|
||||
private:
|
||||
|
||||
using Channel = Splitter_channel;
|
||||
|
||||
Constructible<Channel> _channels[1] { };
|
||||
|
||||
NONCOPYABLE(Splitter);
|
||||
|
||||
public:
|
||||
|
||||
Splitter();
|
||||
|
||||
void execute(bool &) override;
|
||||
|
||||
Block const &src_for_writing_vba(Request_tag, Virtual_block_address) override;
|
||||
|
||||
Block &dst_for_reading_vba(Request_tag, Virtual_block_address) override;
|
||||
};
|
||||
|
||||
|
||||
#endif /* _TRESOR__IO_SPLITTER_H_ */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -65,10 +65,7 @@ class Vfs_tresor_crypto::Encrypt_file_system : public Vfs::Single_file_system
|
||||
Tresor_crypto::Interface &crypto,
|
||||
uint32_t key_id)
|
||||
:
|
||||
Single_vfs_handle { ds, fs, alloc, 0 },
|
||||
_crypto { crypto },
|
||||
_key_id { key_id },
|
||||
_state { State::NONE }
|
||||
Single_vfs_handle(ds, fs, alloc, 0), _crypto(crypto), _key_id(key_id), _state(State::NONE)
|
||||
{ }
|
||||
|
||||
Read_result read(Byte_range_ptr const &dst, size_t &out_count) override
|
||||
@ -130,10 +127,8 @@ class Vfs_tresor_crypto::Encrypt_file_system : public Vfs::Single_file_system
|
||||
|
||||
Encrypt_file_system(Tresor_crypto::Interface &crypto, uint32_t key_id)
|
||||
:
|
||||
Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||
Node_rwx::rw(), Xml_node("<encrypt/>") },
|
||||
_crypto { crypto },
|
||||
_key_id { key_id }
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("<encrypt/>")),
|
||||
_crypto(crypto), _key_id(key_id)
|
||||
{ }
|
||||
|
||||
static char const *type_name() { return "encrypt"; }
|
||||
@ -199,10 +194,7 @@ class Vfs_tresor_crypto::Decrypt_file_system : public Vfs::Single_file_system
|
||||
Tresor_crypto::Interface &crypto,
|
||||
uint32_t key_id)
|
||||
:
|
||||
Single_vfs_handle { ds, fs, alloc, 0 },
|
||||
_crypto { crypto },
|
||||
_key_id { key_id },
|
||||
_state { State::NONE }
|
||||
Single_vfs_handle(ds, fs, alloc, 0), _crypto(crypto), _key_id(key_id), _state(State::NONE)
|
||||
{ }
|
||||
|
||||
Read_result read(Byte_range_ptr const &dst, size_t &out_count) override
|
||||
@ -261,10 +253,8 @@ class Vfs_tresor_crypto::Decrypt_file_system : public Vfs::Single_file_system
|
||||
|
||||
Decrypt_file_system(Tresor_crypto::Interface &crypto, uint32_t key_id)
|
||||
:
|
||||
Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||
Node_rwx::rw(), Xml_node("<decrypt/>") },
|
||||
_crypto { crypto },
|
||||
_key_id { key_id }
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("<decrypt/>")),
|
||||
_crypto(crypto), _key_id(key_id)
|
||||
{ }
|
||||
|
||||
static char const *type_name() { return "decrypt"; }
|
||||
@ -317,8 +307,7 @@ struct Vfs_tresor_crypto::Key_local_factory : File_system_factory
|
||||
Key_local_factory(Tresor_crypto::Interface &crypto,
|
||||
uint32_t key_id)
|
||||
:
|
||||
_encrypt_fs { crypto, key_id },
|
||||
_decrypt_fs { crypto, key_id }
|
||||
_encrypt_fs(crypto, key_id), _decrypt_fs(crypto, key_id)
|
||||
{ }
|
||||
|
||||
Vfs::File_system *create(Vfs::Env&, Xml_node node) override
|
||||
@ -364,11 +353,8 @@ class Vfs_tresor_crypto::Key_file_system : private Key_local_factory,
|
||||
Tresor_crypto::Interface &crypto,
|
||||
uint32_t key_id)
|
||||
:
|
||||
Key_local_factory { crypto, key_id },
|
||||
Vfs::Dir_file_system { vfs_env,
|
||||
Xml_node(_config(key_id).string()),
|
||||
*this },
|
||||
_key_id { key_id }
|
||||
Key_local_factory(crypto, key_id),
|
||||
Vfs::Dir_file_system(vfs_env, Xml_node(_config(key_id).string()), *this), _key_id(key_id)
|
||||
{ }
|
||||
|
||||
static char const *type_name() { return "keys"; }
|
||||
@ -405,8 +391,7 @@ class Vfs_tresor_crypto::Keys_file_system : public Vfs::File_system
|
||||
|
||||
Key_registry(Genode::Allocator &alloc, Tresor_crypto::Interface &crypto)
|
||||
:
|
||||
_alloc { alloc },
|
||||
_crypto { crypto }
|
||||
_alloc(alloc), _crypto(crypto)
|
||||
{ }
|
||||
|
||||
void update(Vfs::Env &vfs_env)
|
||||
@ -652,8 +637,7 @@ class Vfs_tresor_crypto::Keys_file_system : public Vfs::File_system
|
||||
Keys_file_system(Vfs::Env &vfs_env,
|
||||
Tresor_crypto::Interface &crypto)
|
||||
:
|
||||
_vfs_env { vfs_env },
|
||||
_key_reg { vfs_env.alloc(), crypto }
|
||||
_vfs_env(vfs_env), _key_reg(vfs_env.alloc(), crypto)
|
||||
{ }
|
||||
|
||||
static char const *type_name() { return "keys"; }
|
||||
@ -940,9 +924,7 @@ class Vfs_tresor_crypto::Management_file_system : public Vfs::Single_file_system
|
||||
Type type,
|
||||
Tresor_crypto::Interface &crypto)
|
||||
:
|
||||
Single_vfs_handle { ds, fs, alloc, 0 },
|
||||
_type { type },
|
||||
_crypto { crypto }
|
||||
Single_vfs_handle(ds, fs, alloc, 0), _type(type), _crypto(crypto)
|
||||
{ }
|
||||
|
||||
Read_result read(Byte_range_ptr const &, size_t &) override
|
||||
@ -1010,11 +992,8 @@ class Vfs_tresor_crypto::Management_file_system : public Vfs::Single_file_system
|
||||
|
||||
Management_file_system(Tresor_crypto::Interface &crypto, Type type, char const *type_name)
|
||||
:
|
||||
Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name,
|
||||
Node_rwx::wo(), Xml_node("<manage_keys/>") },
|
||||
_type { type },
|
||||
_crypto { crypto },
|
||||
_type_name { type_name }
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name, Node_rwx::wo(), Xml_node("<manage_keys/>")),
|
||||
_type(type), _crypto(crypto), _type_name(type_name)
|
||||
{ }
|
||||
|
||||
char const *type() override { return _type_name; }
|
||||
@ -1090,9 +1069,7 @@ struct Vfs_tresor_crypto::Local_factory : File_system_factory
|
||||
Local_factory(Vfs::Env &env,
|
||||
Tresor_crypto::Interface &crypto)
|
||||
:
|
||||
_keys_fs { env, crypto },
|
||||
_add_key_fs { crypto },
|
||||
_remove_key_fs { crypto }
|
||||
_keys_fs(env, crypto), _add_key_fs(crypto), _remove_key_fs(crypto)
|
||||
{ }
|
||||
|
||||
Vfs::File_system *create(Vfs::Env&, Xml_node node) override
|
||||
@ -1142,9 +1119,8 @@ class Vfs_tresor_crypto::File_system : private Local_factory,
|
||||
|
||||
File_system(Vfs::Env &vfs_env, Genode::Xml_node node)
|
||||
:
|
||||
Local_factory { vfs_env, Tresor_crypto::get_interface() },
|
||||
Vfs::Dir_file_system { vfs_env, Xml_node(_config(node).string()),
|
||||
*this }
|
||||
Local_factory(vfs_env, Tresor_crypto::get_interface()),
|
||||
Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), *this)
|
||||
{ }
|
||||
|
||||
~File_system() { }
|
||||
|
@ -257,16 +257,10 @@ namespace Util {
|
||||
Vfs::file_offset base_offset,
|
||||
Partial_result partial_result = Partial_result::DENY)
|
||||
:
|
||||
_handle { handle },
|
||||
_op { op },
|
||||
_state { _initial_state(op) },
|
||||
_data { buffer.base },
|
||||
_base_offset { base_offset },
|
||||
_current_offset { 0 },
|
||||
_current_count { buffer.size },
|
||||
_allow_partial { partial_result == Partial_result::ALLOW },
|
||||
_success { false },
|
||||
_complete { false }
|
||||
_handle(handle), _op(op), _state(_initial_state(op)), _data(buffer.base),
|
||||
_base_offset(base_offset), _current_offset(0), _current_count(buffer.size),
|
||||
_allow_partial(partial_result == Partial_result::ALLOW), _success(false),
|
||||
_complete(false)
|
||||
{ }
|
||||
|
||||
bool completed() const { return _complete; }
|
||||
|
@ -712,7 +712,7 @@ class Trust_anchor
|
||||
return true;
|
||||
}
|
||||
|
||||
// XXX trigger sync
|
||||
/* XXX trigger sync */
|
||||
|
||||
bool const progress = _private_key_io_job->execute();
|
||||
bool const completed = _private_key_io_job->completed();
|
||||
@ -731,7 +731,7 @@ class Trust_anchor
|
||||
return true;
|
||||
}
|
||||
|
||||
// XXX trigger sync
|
||||
/* XXX trigger sync */
|
||||
|
||||
bool const progress = _jitterentropy_io_job->execute();
|
||||
bool const completed = _jitterentropy_io_job->completed();
|
||||
@ -750,7 +750,7 @@ class Trust_anchor
|
||||
return true;
|
||||
}
|
||||
|
||||
// XXX trigger sync
|
||||
/* XXX trigger sync */
|
||||
|
||||
bool const progress = _key_io_job->execute();
|
||||
bool const completed = _key_io_job->completed();
|
||||
@ -960,10 +960,7 @@ class Trust_anchor
|
||||
|
||||
public:
|
||||
|
||||
Trust_anchor(Vfs::Env &vfs_env, Path const &path)
|
||||
:
|
||||
_vfs_env { vfs_env },
|
||||
_base_path { path }
|
||||
Trust_anchor(Vfs::Env &vfs_env, Path const &path) : _vfs_env(vfs_env), _base_path(path)
|
||||
{
|
||||
if (_check_key_file(_base_path)) {
|
||||
|
||||
@ -1275,8 +1272,7 @@ class Vfs_tresor_trust_anchor::Hashsum_file_system : public Vfs::Single_file_sys
|
||||
Genode::Allocator &alloc,
|
||||
Trust_anchor &ta)
|
||||
:
|
||||
Single_vfs_handle { ds, fs, alloc, 0 },
|
||||
_trust_anchor { ta }
|
||||
Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta)
|
||||
{ }
|
||||
|
||||
Read_result read(Byte_range_ptr const &src, size_t &out_count) override
|
||||
@ -1367,12 +1363,11 @@ class Vfs_tresor_trust_anchor::Hashsum_file_system : public Vfs::Single_file_sys
|
||||
|
||||
Hashsum_file_system(Trust_anchor &ta)
|
||||
:
|
||||
Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||
Node_rwx::ro(), Xml_node("<hashsum/>") },
|
||||
_trust_anchor { ta }
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::ro(), Xml_node("<hash/>")),
|
||||
_trust_anchor(ta)
|
||||
{ }
|
||||
|
||||
static char const *type_name() { return "hashsum"; }
|
||||
static char const *type_name() { return "hash"; }
|
||||
|
||||
char const *type() override { return type_name(); }
|
||||
|
||||
@ -1433,8 +1428,7 @@ class Vfs_tresor_trust_anchor::Generate_key_file_system : public Vfs::Single_fil
|
||||
Genode::Allocator &alloc,
|
||||
Trust_anchor &ta)
|
||||
:
|
||||
Single_vfs_handle { ds, fs, alloc, 0 },
|
||||
_trust_anchor { ta }
|
||||
Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta)
|
||||
{ }
|
||||
|
||||
Read_result read(Byte_range_ptr const &dst, size_t &out_count) override
|
||||
@ -1473,9 +1467,8 @@ class Vfs_tresor_trust_anchor::Generate_key_file_system : public Vfs::Single_fil
|
||||
|
||||
Generate_key_file_system(Trust_anchor &ta)
|
||||
:
|
||||
Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||
Node_rwx::ro(), Xml_node("<generate_key/>") },
|
||||
_trust_anchor { ta }
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::ro(), Xml_node("<generate_key/>")),
|
||||
_trust_anchor(ta)
|
||||
{ }
|
||||
|
||||
static char const *type_name() { return "generate_key"; }
|
||||
@ -1539,9 +1532,7 @@ class Vfs_tresor_trust_anchor::Encrypt_file_system : public Vfs::Single_file_sys
|
||||
Genode::Allocator &alloc,
|
||||
Trust_anchor &ta)
|
||||
:
|
||||
Single_vfs_handle { ds, fs, alloc, 0 },
|
||||
_trust_anchor { ta },
|
||||
_state { State::NONE }
|
||||
Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta), _state(State::NONE)
|
||||
{ }
|
||||
|
||||
Read_result read(Byte_range_ptr const &dst, size_t &out_count) override
|
||||
@ -1600,9 +1591,8 @@ class Vfs_tresor_trust_anchor::Encrypt_file_system : public Vfs::Single_file_sys
|
||||
|
||||
Encrypt_file_system(Trust_anchor &ta)
|
||||
:
|
||||
Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||
Node_rwx::rw(), Xml_node("<encrypt/>") },
|
||||
_trust_anchor { ta }
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("<encrypt/>")),
|
||||
_trust_anchor(ta)
|
||||
{ }
|
||||
|
||||
static char const *type_name() { return "encrypt"; }
|
||||
@ -1665,9 +1655,7 @@ class Vfs_tresor_trust_anchor::Decrypt_file_system : public Vfs::Single_file_sys
|
||||
Genode::Allocator &alloc,
|
||||
Trust_anchor &ta)
|
||||
:
|
||||
Single_vfs_handle { ds, fs, alloc, 0 },
|
||||
_trust_anchor { ta },
|
||||
_state { State::NONE }
|
||||
Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta), _state(State::NONE)
|
||||
{ }
|
||||
|
||||
Read_result read(Byte_range_ptr const &dst, size_t &out_count) override
|
||||
@ -1726,9 +1714,8 @@ class Vfs_tresor_trust_anchor::Decrypt_file_system : public Vfs::Single_file_sys
|
||||
|
||||
Decrypt_file_system(Trust_anchor &ta)
|
||||
:
|
||||
Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||
Node_rwx::rw(), Xml_node("<decrypt/>") },
|
||||
_trust_anchor { ta }
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("<decrypt/>")),
|
||||
_trust_anchor(ta)
|
||||
{ }
|
||||
|
||||
static char const *type_name() { return "decrypt"; }
|
||||
@ -1793,8 +1780,7 @@ class Vfs_tresor_trust_anchor::Initialize_file_system : public Vfs::Single_file_
|
||||
Genode::Allocator &alloc,
|
||||
Trust_anchor &ta)
|
||||
:
|
||||
Single_vfs_handle { ds, fs, alloc, 0 },
|
||||
_trust_anchor { ta }
|
||||
Single_vfs_handle(ds, fs, alloc, 0), _trust_anchor(ta)
|
||||
{ }
|
||||
|
||||
Read_result read(Byte_range_ptr const &buf,
|
||||
@ -1867,9 +1853,8 @@ class Vfs_tresor_trust_anchor::Initialize_file_system : public Vfs::Single_file_
|
||||
|
||||
Initialize_file_system(Trust_anchor &ta)
|
||||
:
|
||||
Single_file_system { Node_type::TRANSACTIONAL_FILE, type_name(),
|
||||
Node_rwx::rw(), Xml_node("<initialize/>") },
|
||||
_trust_anchor { ta }
|
||||
Single_file_system(Node_type::TRANSACTIONAL_FILE, type_name(), Node_rwx::rw(), Xml_node("<initialize/>")),
|
||||
_trust_anchor(ta)
|
||||
{ }
|
||||
|
||||
static char const *type_name() { return "initialize"; }
|
||||
@ -1938,12 +1923,9 @@ struct Vfs_tresor_trust_anchor::Local_factory : File_system_factory
|
||||
|
||||
Local_factory(Vfs::Env &vfs_env, Xml_node config)
|
||||
:
|
||||
_trust_anchor { vfs_env, _storage_path(config).string() },
|
||||
_decrypt_fs { _trust_anchor },
|
||||
_encrypt_fs { _trust_anchor },
|
||||
_gen_key_fs { _trust_anchor },
|
||||
_hash_fs { _trust_anchor },
|
||||
_init_fs { _trust_anchor }
|
||||
_trust_anchor(vfs_env, _storage_path(config).string()),
|
||||
_decrypt_fs(_trust_anchor), _encrypt_fs(_trust_anchor),
|
||||
_gen_key_fs(_trust_anchor), _hash_fs(_trust_anchor), _init_fs(_trust_anchor)
|
||||
{ }
|
||||
|
||||
Vfs::File_system *create(Vfs::Env&, Xml_node node) override
|
||||
@ -1990,7 +1972,7 @@ class Vfs_tresor_trust_anchor::File_system : private Local_factory,
|
||||
xml.node("decrypt", [&] () { });
|
||||
xml.node("encrypt", [&] () { });
|
||||
xml.node("generate_key", [&] () { });
|
||||
xml.node("hashsum", [&] () { });
|
||||
xml.node("hash", [&] () { });
|
||||
xml.node("initialize", [&] () { });
|
||||
});
|
||||
|
||||
@ -2001,8 +1983,7 @@ class Vfs_tresor_trust_anchor::File_system : private Local_factory,
|
||||
|
||||
File_system(Vfs::Env &vfs_env, Genode::Xml_node node)
|
||||
:
|
||||
Local_factory { vfs_env, node },
|
||||
Vfs::Dir_file_system { vfs_env, Xml_node(_config(node).string()), *this }
|
||||
Local_factory(vfs_env, node), Vfs::Dir_file_system(vfs_env, Xml_node(_config(node).string()), *this)
|
||||
{ }
|
||||
|
||||
~File_system() { }
|
||||
|
@ -97,6 +97,7 @@ vbox5_win7_64_share
|
||||
verify
|
||||
vfs_cfg
|
||||
vfs_import
|
||||
vfs_tresor
|
||||
vm_stress_seoul-debian32
|
||||
vm_stress_vbox5-debian32
|
||||
vm_stress_vbox5-debian64
|
||||
|
Loading…
Reference in New Issue
Block a user