file_vault_gui: dialog-based file_vault front end

* adds rekeying and resizing controls to config+report api of file vault
* moves common types of file vault to file_vault/include/file_vault/types.h
  to be included by other components
* fixes wrong type of nr_of_clients fields in file_vault
* introduces the file_vault_gui component that is a minimal graphical front end
  for the file vault based on the dialog lib and that uses the
  config+report api of the file vault as back end

Ref #5190
This commit is contained in:
Martin Stein 2024-04-19 07:05:38 +02:00 committed by Christian Helmuth
parent 9d78356885
commit 483fe18c4d
40 changed files with 1944 additions and 5207 deletions

View File

@ -1,9 +1,7 @@
_/src/init
_/src/libc
_/src/libpng
_/src/zlib
_/src/fs_query
_/src/menu_view
_/src/tresor
_/src/vfs_block
_/src/vfs_jitterentropy
@ -15,3 +13,7 @@ _/src/posix
_/src/rump
_/src/sandbox
_/src/file_vault
_/src/file_vault_gui
_/src/report_rom
_/src/menu_view
_/src/libpng

View File

@ -1,15 +1,15 @@
<runtime ram="220M" caps="2200" binary="init">
<runtime ram="120M" caps="2000" binary="init">
<provides>
<file_system/>
</provides>
<requires>
<file_system label="data" writeable="yes"/>
<file_system label="data" writeable="yes"/>
<file_system label="trust_anchor" writeable="yes"/>
<file_system label="fonts" writeable="no"/>
<rm/>
<file_system label="fonts" writeable="yes"/>
<gui/>
<rm/>
<timer/>
</requires>
@ -18,10 +18,8 @@
<rom label="ld.lib.so"/>
<rom label="libc.lib.so"/>
<rom label="libm.lib.so"/>
<rom label="libpng.lib.so"/>
<rom label="zlib.lib.so"/>
<rom label="fs_query"/>
<rom label="menu_view"/>
<rom label="vfs"/>
<rom label="vfs.lib.so"/>
<rom label="vfs_block"/>
@ -43,7 +41,11 @@
<rom label="file_vault"/>
<rom label="file_vault-sync_to_tresor_vfs_init"/>
<rom label="file_vault-truncate_file"/>
<rom label="file_vault_gui"/>
<rom label="report_rom"/>
<rom label="menu_view"/>
<rom label="menu_view_styles.tar"/>
<rom label="libpng.lib.so"/>
</content>
<config>
@ -65,35 +67,61 @@
</default-policy>
</service>
<start name="file_vault" caps="2000">
<resource name="RAM" quantum="200M"/>
<start name="report_rom" caps="100">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config>
<policy label="gui -> ui_report" report="file_vault -> ui_report"/>
<policy label="file_vault -> ui_config" report="gui -> ui_config"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="file_vault" caps="1200">
<resource name="RAM" quantum="100M"/>
<provides>
<service name="File_system"/>
</provides>
<config user_interface="menu_view">
<vfs>
<dir name="tresor">
<fs label="tresor"/>
</dir>
</vfs>
<config>
<vfs> <dir name="tresor"> <fs label="tresor"/> </dir> </vfs>
</config>
<route>
<service name="ROM" label="ui_config"> <child name="report_rom"/> </service>
<service name="Report" label="ui_report"> <child name="report_rom"/> </service>
<service name="File_system" label="tresor_trust_anchor_vfs -> storage_dir"> <parent label="trust_anchor"/> </service>
<service name="File_system" label="vfs_block -> "> <parent label="data"/> </service>
<service name="File_system" label="tresor_init -> "> <parent label="data"/> </service>
<service name="File_system" label="tresor"> <parent label="data"/> </service>
<service name="File_system" label="fs_query -> "> <parent label="data"/> </service>
<service name="File_system" label="image_fs_query -> "> <parent label="data"/> </service>
<service name="File_system" label="tresor_vfs -> tresor_fs"> <parent label="data"/> </service>
<service name="File_system" label="truncate_file -> tresor"> <parent label="data"/> </service>
<service name="File_system" label="menu_view -> fonts"> <parent label="fonts"/> </service>
<service name="Timer"> <parent/> </service>
<service name="Gui"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="File_system" label="tresor_init -> "> <parent label="data"/> </service>
<service name="File_system" label="tresor"> <parent label="data"/> </service>
<service name="File_system" label="image_fs_query -> "> <parent label="data"/> </service>
<service name="File_system" label="tresor_vfs -> tresor_fs"> <parent label="data"/> </service>
<service name="File_system" label="truncate_file -> tresor"> <parent label="data"/> </service>
<service name="Timer"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>
<start name="gui" caps="400">
<binary name="file_vault_gui"/>
<resource name="RAM" quantum="8M"/>
<route>
<service name="ROM" label="ui_report"> <child name="report_rom"/> </service>
<service name="Report" label="ui_config"> <child name="report_rom"/> </service>
<service name="File_system" label_last="fonts"> <parent label="fonts"/> </service>
<service name="Gui"> <parent/> </service>
<service name="Timer"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>

View File

@ -1 +0,0 @@
See repos/gems/src/app/file_vault/README.

View File

@ -1,15 +0,0 @@
_/src/init
_/src/libc
_/src/zlib
_/src/fs_query
_/src/tresor
_/src/vfs_block
_/src/vfs_jitterentropy
_/src/vfs
_/src/openssl
_/src/fs_tool
_/src/fs_utils
_/src/posix
_/src/rump
_/src/sandbox
_/src/file_vault

View File

@ -1 +0,0 @@
2024-04-18 119c76ec69dc9094ec8ff6e5fab286c74bc3e255

View File

@ -1,98 +0,0 @@
<runtime ram="220M" caps="2200" binary="init">
<provides>
<file_system/>
</provides>
<requires>
<file_system label="data" writeable="yes"/>
<file_system label="trust_anchor" writeable="yes"/>
<report label="ui_report"/>
<rom label="ui_config"/>
<rm/>
<timer/>
</requires>
<content>
<rom label="init"/>
<rom label="ld.lib.so"/>
<rom label="libc.lib.so"/>
<rom label="libm.lib.so"/>
<rom label="zlib.lib.so"/>
<rom label="fs_query"/>
<rom label="vfs"/>
<rom label="vfs.lib.so"/>
<rom label="vfs_block"/>
<rom label="vfs_jitterentropy.lib.so"/>
<rom label="vfs_tresor.lib.so"/>
<rom label="vfs_tresor_crypto_aes_cbc.lib.so"/>
<rom label="vfs_tresor_trust_anchor.lib.so"/>
<rom label="tresor_init"/>
<rom label="tresor_init_trust_anchor"/>
<rom label="libcrypto.lib.so"/>
<rom label="rump.lib.so"/>
<rom label="vfs_rump.lib.so"/>
<rom label="rump_fs.lib.so"/>
<rom label="sandbox.lib.so"/>
<rom label="fs_tool"/>
<rom label="mke2fs"/>
<rom label="resize2fs"/>
<rom label="posix.lib.so"/>
<rom label="file_vault"/>
<rom label="file_vault-sync_to_tresor_vfs_init"/>
<rom label="file_vault-truncate_file"/>
</content>
<config>
<parent-provides>
<service name="ROM"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="Gui"/>
<service name="Timer"/>
<service name="File_system"/>
</parent-provides>
<service name="File_system">
<default-policy>
<child name="file_vault"/>
</default-policy>
</service>
<start name="file_vault" caps="2000">
<resource name="RAM" quantum="200M"/>
<provides>
<service name="File_system"/>
</provides>
<config user_interface="menu_view">
<vfs>
<dir name="tresor">
<fs label="tresor"/>
</dir>
</vfs>
</config>
<route>
<service name="Report" label="ui_report"> <parent/> </service>
<service name="ROM" label="ui_config"> <parent/> </service>
<service name="File_system" label="tresor_trust_anchor_vfs -> storage_dir"> <parent label="trust_anchor"/> </service>
<service name="File_system" label="vfs_block -> "> <parent label="data"/> </service>
<service name="File_system" label="tresor"> <parent label="data"/> </service>
<service name="File_system" label="fs_query -> "> <parent label="data"/> </service>
<service name="File_system" label="image_fs_query -> "> <parent label="data"/> </service>
<service name="File_system" label="tresor_vfs -> tresor_fs"> <parent label="data"/> </service>
<service name="File_system" label="truncate_file -> tresor"> <parent label="data"/> </service>
<service name="Timer"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>
</config>
</runtime>

View File

@ -1,4 +1,4 @@
_/pkg/file_vault_config_report
_/pkg/file_vault
_/src/report_rom
_/src/dynamic_rom
_/src/vfs

View File

@ -6,11 +6,11 @@
<fail after_seconds="70"/>
<succeed>
&lt;ui_report version="step_*" state="uninitialized"/>*
&lt;ui_report version="step_*" state="initializing"/>*
&lt;ui_report version="step_*" state="unlocked"/>*
&lt;ui_report version="step_*" state="locked"/>*
&lt;ui_report version="step_*" state="unlocked"/>*
&lt;ui_report version="step_*" state="uninitialized"*
&lt;ui_report version="step_*" state="initializing"*
&lt;ui_report version="step_*" state="unlocked"*
&lt;ui_report version="step_*" state="locked"*
&lt;ui_report version="step_*" state="unlocked"*
</succeed>
<content>
@ -145,7 +145,7 @@
<start name="file_vault" caps="1500">
<resource name="RAM" quantum="180M"/>
<config user_interface="config_and_report">
<config>
<vfs>
<dir name="tresor">
<fs label="tresor"/>

View File

@ -1,4 +1,4 @@
_/pkg/file_vault_config_report
_/pkg/file_vault
_/src/report_rom
_/src/dynamic_rom
_/src/vfs

View File

@ -6,11 +6,11 @@
<fail after_seconds="70"/>
<succeed>
&lt;ui_report version="step_*" state="uninitialized"/>*
&lt;ui_report version="step_*" state="initializing"/>*
&lt;ui_report version="step_*" state="unlocked"/>*
&lt;ui_report version="step_*" state="locked"/>*
&lt;ui_report version="step_*" state="unlocked"/>*
&lt;ui_report version="step_*" state="uninitialized"*
&lt;ui_report version="step_*" state="initializing"*
&lt;ui_report version="step_*" state="unlocked"*
&lt;ui_report version="step_*" state="locked"*
&lt;ui_report version="step_*" state="unlocked"*
</succeed>
<content>
@ -145,7 +145,7 @@
<start name="file_vault" caps="1500">
<resource name="RAM" quantum="180M"/>
<config user_interface="config_and_report" jitterentropy_available="no">
<config jitterentropy_available="no">
<vfs>
<dir name="tresor">
<fs label="tresor"/>

View File

@ -0,0 +1,14 @@
SRC_DIR := src/app/file_vault_gui
MIRROR_FROM_REP_DIR := \
lib/mk/dialog.mk src/lib/dialog include/dialog src/app/file_vault/include \
src/lib/tresor/include/tresor/types.h \
src/lib/tresor/include/tresor/assertion.h \
src/lib/tresor/include/tresor/verbosity.h \
src/lib/tresor/include/tresor/math.h
content: $(MIRROR_FROM_REP_DIR)
$(MIRROR_FROM_REP_DIR):
$(mirror_from_rep_dir)
include $(GENODE_DIR)/repos/base/recipes/src/content.inc

View File

@ -0,0 +1 @@
2024-04-23-l 9b6c3e2457e3cc22233bd9f82aa191bdff79cfdf

View File

@ -0,0 +1,8 @@
base
os
gems
report_session
gui_session
input_session
framebuffer_session
sandbox

View File

@ -662,8 +662,8 @@ set default_test_pkgs {
test-entrypoint
test-expat
test-fault_detection
test-file_vault_config_report
test-file_vault_config_report_no_entropy
test-file_vault
test-file_vault_no_entropy
test-fs_packet
test-fs_report
test-fs_rom_update
@ -775,12 +775,12 @@ proc skip_test_if { condition test } {
#
# pbxa9 and zynq_qemu don't support jitterentropy
#
skip_test_if [expr ([have_board pbxa9] || [have_board zynq_qemu])] test-file_vault_config_report
skip_test_if [expr !([have_board pbxa9] || [have_board zynq_qemu])] test-file_vault_config_report_no_entropy
skip_test_if [expr ([have_board pbxa9] || [have_board zynq_qemu])] test-file_vault
skip_test_if [expr !([have_board pbxa9] || [have_board zynq_qemu])] test-file_vault_no_entropy
# rpi has a quite limited amount of RAM
skip_test_if [have_board rpi] test-file_vault_config_report
skip_test_if [have_board rpi] test-file_vault_config_report_no_entropy
skip_test_if [have_board rpi] test-file_vault
skip_test_if [have_board rpi] test-file_vault_no_entropy
set skip_test(test-fault_detection) [expr [have_spec pistachio] || [have_spec fiasco]]
set skip_test(test-fs_packet) [expr ![interactive] && [have_include "power_on/qemu"]]
@ -800,8 +800,8 @@ if {[have_spec foc]} {
set skip_test(test-libc) [have_board pbxa9]
set skip_test(test-tcp_bulk_lxip) [have_board pbxa9]
# foc on pbxa9 caps RAM at 256 MiB - skip tests with excessive RAM demand
skip_test_if [have_board pbxa9] test-file_vault_config_report
skip_test_if [have_board pbxa9] test-file_vault_config_report_no_entropy
skip_test_if [have_board pbxa9] test-file_vault
skip_test_if [have_board pbxa9] test-file_vault_no_entropy
}
if {[have_spec riscv]} {
set skip_test(gcov) true
@ -814,7 +814,7 @@ if {[have_spec riscv]} {
set skip_test(test-tcp_bulk_lxip) true
set skip_test(test-trace_logger) true
set skip_test(test-xml_generator) true
set skip_test(test-file_vault_config_report) true
set skip_test(test-file_vault) true
}
#

View File

@ -1,423 +0,0 @@
proc ui_is { arg } {
global ui
return [string equal $arg $ui ]
}
proc jent_avail { } {
if {[have_board pbxa9]} { return 0 }
if {[have_board zynq_qemu]} { return 0 }
return 1
}
proc jent_avail_attr { } {
if {[jent_avail]} { return "yes" }
return "no"
}
build { app/file_vault }
create_boot_directory
append archives "
[depot_user]/src/[base_src]
[depot_user]/src/init
[depot_user]/src/libc
[depot_user]/src/zlib
[depot_user]/src/fs_query
[depot_user]/src/tresor
[depot_user]/src/vfs_block
[depot_user]/src/vfs
[depot_user]/src/openssl
[depot_user]/src/fs_tool
[depot_user]/src/fs_utils
[depot_user]/src/posix
[depot_user]/src/rump
[depot_user]/src/sandbox
"
append_if [jent_avail] archives " [depot_user]/src/vfs_jitterentropy "
lappend_if [ui_is menu_view] archives [depot_user]/src/nitpicker
lappend_if [ui_is menu_view] archives [depot_user]/src/menu_view
lappend_if [ui_is menu_view] archives [depot_user]/src/libpng
lappend_if [ui_is menu_view] archives [depot_user]/pkg/fonts_fs
lappend_if [ui_is menu_view] archives [depot_user]/pkg/[drivers_interactive_pkg]
lappend_if [ui_is config_and_report] archives [depot_user]/src/report_rom
lappend_if [ui_is config_and_report] archives [depot_user]/src/dynamic_rom
lappend_if [have_board linux] archives [depot_user]/src/lx_fs
import_from_depot $archives
append config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="LOG"/>
<service name="RM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
</parent-provides>
<start name="timer" caps="200">
<resource name="RAM" quantum="1M"/>
<resource name="CPU" quantum="5"/>
<provides> <service name="Timer"/> </provides>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
</route>
</start>
}
append_if [ui_is menu_view] config {
<start name="drivers" caps="1500" managing_system="yes">
<resource name="RAM" quantum="64M"/>
<binary name="init"/>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="Capture"> <child name="nitpicker"/> </service>
<service name="Event"> <child name="nitpicker"/> </service>
<service name="ROM" label="config"> <parent label="drivers.config"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
</route>
</start>
<start name="nitpicker" caps="100">
<resource name="RAM" quantum="4M"/>
<provides>
<service name="Gui"/> <service name="Capture"/> <service name="Event"/>
</provides>
<config focus="rom">
<capture/> <event/>
<background color="#123456"/>
<domain name="pointer" layer="1" content="client" label="no" origin="pointer" />
<domain name="default" layer="3" content="client" label="no" hover="always" />
<domain name="second" layer="2" xpos="200" ypos="300" content="client" label="no" hover="always" />
<policy label_prefix="pointer" domain="pointer"/>
<policy label_prefix="text_area.2" domain="second"/>
<default-policy domain="default"/>
</config>
<route>
<service name="Timer"> <child name="timer" /> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="pointer" caps="100">
<resource name="RAM" quantum="1M"/>
<route>
<service name="Gui"> <child name="nitpicker" /> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="fonts_fs" caps="150">
<binary name="vfs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<vfs>
<rom name="Vera.ttf"/>
<rom name="VeraMono.ttf"/>
<dir name="fonts">
<dir name="title">
<ttf name="regular" path="/Vera.ttf" size_px="18" cache="256K"/>
</dir>
<dir name="text">
<ttf name="regular" path="/Vera.ttf" size_px="14" cache="256K"/>
</dir>
<dir name="annotation">
<ttf name="regular" path="/Vera.ttf" size_px="11" cache="256K"/>
</dir>
<dir name="monospace">
<ttf name="regular" path="/VeraMono.ttf" size_px="14" cache="256K"/>
</dir>
</dir>
</vfs>
<policy label="file_vault -> fonts" root="/fonts" />
</config>
<route>
<service name="ROM" label="config"> <parent label="fonts_fs.config"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
}
append_if [ui_is config_and_report] config {
<start name="dynamic_rom" caps="100">
<resource name="RAM" quantum="4M"/>
<provides><service name="ROM"/> </provides>
<config verbose="no">
<rom name="file_vault_ui_config">
<inline>
<ui_config version="step_1_wait"/>
</inline>
<sleep milliseconds="6000"/>
<inline>
<ui_config version="step_2_init" passphrase="abcdefgh"
client_fs_size="1M"
journaling_buf_size="1M"/>
</inline>
<sleep milliseconds="10000"/>
<inline>
<ui_config version="step_3_lock"/>
</inline>
<sleep milliseconds="6000"/>
<inline>
<ui_config version="step_4_bad_unlock" passphrase="00000001"/>
</inline>
<sleep milliseconds="6000"/>
<inline>
<ui_config version="step_5_wait"/>
</inline>
<sleep milliseconds="6000"/>
<inline>
<ui_config version="step_6_unlock" passphrase="abcdefgh"/>
</inline>
<sleep milliseconds="600000"/>
</rom>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="report_rom" caps="70">
<resource name="RAM" quantum="1M"/>
<provides>
<service name="ROM" />
<service name="Report" />
</provides>
<config verbose="yes"/>
<route>
<service name="LOG"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="ROM"> <parent/> </service>
</route>
</start>
}
if {[have_board linux]} {
append config {
<start name="data_fs" caps="200" ld="no">
<binary name="lx_fs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<policy label="file_vault -> data"
root="/file_vault_dir/data"
writeable="yes"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="trust_anchor_fs" caps="200" ld="no">
<binary name="lx_fs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<policy label="file_vault -> trust_anchor"
root="/file_vault_dir/trust_anchor"
writeable="yes"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
}
} else {
append config {
<start name="data_fs" caps="2000">
<binary name="vfs"/>
<resource name="RAM" quantum="200M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs>
<dir name="data">
<ram/>
</dir>
</vfs>
<policy label="file_vault -> data" root="/data" writeable="yes"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="trust_anchor_fs" caps="100">
<binary name="vfs"/>
<resource name="RAM" quantum="5M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs>
<dir name="trust_anchor">
<ram/>
</dir>
</vfs>
<policy label="file_vault -> trust_anchor" root="/trust_anchor" writeable="yes"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
}
}
append config {
<start name="file_vault" caps="2000">
<resource name="RAM" quantum="200M"/>
<config user_interface="} $ui {" jitterentropy_available="} [jent_avail_attr] {">
<vfs>
<dir name="tresor">
<fs label="tresor"/>
</dir>
</vfs>
</config>
<route>
}
append_if [ui_is menu_view] config {
<service name="File_system" label="menu_view -> fonts"> <child name="fonts_fs" label="file_vault -> fonts"/> </service>
<service name="Gui"> <child name="nitpicker"/> </service>
}
append_if [ui_is config_and_report] config {
<service name="ROM" label="ui_config"> <child name="dynamic_rom" label="file_vault_ui_config"/> </service>
<service name="Report" label="ui_report"> <child name="report_rom"/> </service>
}
append config {
<service name="File_system" label="tresor_trust_anchor_vfs -> storage_dir"> <child name="trust_anchor_fs" label="file_vault -> trust_anchor"/> </service>
<service name="File_system" label="tresor_init -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="tresor"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="fs_query -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="image_fs_query -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="tresor_vfs -> tresor_fs"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="truncate_file -> tresor"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>
</config>
}
install_config $config
if {[have_board linux]} {
if {[ui_is config_and_report]} {
exec rm -rf bin/file_vault_dir
}
exec mkdir -p bin/file_vault_dir/data
exec mkdir -p bin/file_vault_dir/trust_anchor
}
append boot_modules [build_artifacts]
lappend_if [have_board linux] boot_modules file_vault_dir
if {[ui_is menu_view]} {
set fd [open [run_dir]/genode/focus w]
puts $fd "<focus label=\"file_vault -> \"/>"
close $fd
append qemu_args " -display gtk "
build_boot_image $boot_modules
run_genode_until forever
}
if {[ui_is config_and_report]} {
build_boot_image $boot_modules
append exp_output {.*<ui_report version=\"step_.*\" state=\"uninitialized\"/>.*\n}
append exp_output {.*<ui_report version=\"step_.*\" state=\"initializing\"/>.*\n}
append exp_output {.*<ui_report version=\"step_.*\" state=\"unlocked\"/>.*\n}
append exp_output {.*<ui_report version=\"step_.*\" state=\"locked\"/>.*\n}
append exp_output {.*<ui_report version=\"step_.*\" state=\"unlocked\"/>.*\n}
append qemu_args " -display none "
run_genode_until $exp_output 70
}

View File

@ -1,2 +1,279 @@
set ui "menu_view"
source ${genode_dir}/repos/gems/run/file_vault.inc
proc jent_avail { } {
if {[have_board pbxa9]} { return 0 }
if {[have_board zynq_qemu]} { return 0 }
return 1
}
proc jent_avail_attr { } {
if {[jent_avail]} { return "yes" }
return "no"
}
build { app/file_vault }
create_boot_directory
append archives "
[depot_user]/src/[base_src]
[depot_user]/src/init
[depot_user]/src/libc
[depot_user]/src/zlib
[depot_user]/src/fs_query
[depot_user]/src/tresor
[depot_user]/src/vfs_block
[depot_user]/src/vfs
[depot_user]/src/openssl
[depot_user]/src/fs_tool
[depot_user]/src/fs_utils
[depot_user]/src/posix
[depot_user]/src/rump
[depot_user]/src/sandbox
[depot_user]/src/report_rom
[depot_user]/src/dynamic_rom
"
append_if [jent_avail] archives " [depot_user]/src/vfs_jitterentropy "
lappend_if [have_board linux] archives [depot_user]/src/lx_fs
import_from_depot $archives
append config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="LOG"/>
<service name="RM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
</parent-provides>
<start name="timer" caps="200">
<resource name="RAM" quantum="1M"/>
<resource name="CPU" quantum="5"/>
<provides> <service name="Timer"/> </provides>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
</route>
</start>
<start name="dynamic_rom" caps="100">
<resource name="RAM" quantum="4M"/>
<provides><service name="ROM"/> </provides>
<config verbose="no">
<rom name="file_vault_ui_config">
<inline>
<ui_config version="step_1_wait"/>
</inline>
<sleep milliseconds="6000"/>
<inline>
<ui_config version="step_2_init" passphrase="abcdefgh"
client_fs_size="1M"
journaling_buf_size="1M"/>
</inline>
<sleep milliseconds="10000"/>
<inline>
<ui_config version="step_3_lock"/>
</inline>
<sleep milliseconds="6000"/>
<inline>
<ui_config version="step_4_bad_unlock" passphrase="00000001"/>
</inline>
<sleep milliseconds="6000"/>
<inline>
<ui_config version="step_5_wait"/>
</inline>
<sleep milliseconds="6000"/>
<inline>
<ui_config version="step_6_unlock" passphrase="abcdefgh"/>
</inline>
<sleep milliseconds="600000"/>
</rom>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="report_rom" caps="70">
<resource name="RAM" quantum="1M"/>
<provides>
<service name="ROM" />
<service name="Report" />
</provides>
<config verbose="yes"/>
<route>
<service name="LOG"> <parent/> </service>
<service name="PD"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="ROM"> <parent/> </service>
</route>
</start> }
append_if [have_board linux] config {
<start name="data_fs" caps="200" ld="no">
<binary name="lx_fs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<policy label="file_vault -> data"
root="/file_vault_dir/data"
writeable="yes"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="trust_anchor_fs" caps="200" ld="no">
<binary name="lx_fs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<policy label="file_vault -> trust_anchor"
root="/file_vault_dir/trust_anchor"
writeable="yes"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start> }
append_if [expr ![have_board linux]] config {
<start name="data_fs" caps="2000">
<binary name="vfs"/>
<resource name="RAM" quantum="200M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs>
<dir name="data">
<ram/>
</dir>
</vfs>
<policy label="file_vault -> data" root="/data" writeable="yes"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="trust_anchor_fs" caps="100">
<binary name="vfs"/>
<resource name="RAM" quantum="5M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs>
<dir name="trust_anchor">
<ram/>
</dir>
</vfs>
<policy label="file_vault -> trust_anchor" root="/trust_anchor" writeable="yes"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start> }
append config {
<start name="file_vault" caps="2000">
<resource name="RAM" quantum="200M"/>
<config jitterentropy_available="} [jent_avail_attr] {">
<vfs>
<dir name="tresor">
<fs label="tresor"/>
</dir>
</vfs>
</config>
<route>
<service name="ROM" label="ui_config"> <child name="dynamic_rom" label="file_vault_ui_config"/> </service>
<service name="Report" label="ui_report"> <child name="report_rom"/> </service>
<service name="File_system" label="tresor_trust_anchor_vfs -> storage_dir"> <child name="trust_anchor_fs" label="file_vault -> trust_anchor"/> </service>
<service name="File_system" label="tresor_init -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="tresor"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="fs_query -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="image_fs_query -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="tresor_vfs -> tresor_fs"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="truncate_file -> tresor"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>
</config> }
install_config $config
if {[have_board linux]} {
exec rm -rf bin/file_vault_dir
exec mkdir -p bin/file_vault_dir/data
exec mkdir -p bin/file_vault_dir/trust_anchor
}
append boot_modules [build_artifacts]
lappend_if [have_board linux] boot_modules file_vault_dir
build_boot_image $boot_modules
append exp_output {.*<ui_report.* state=\"uninitialized\".*\n}
append exp_output {.*<ui_report.* state=\"initializing\".*\n}
append exp_output {.*<ui_report.* state=\"unlocked\".*\n}
append exp_output {.*<ui_report.* state=\"locked\".*\n}
append exp_output {.*<ui_report.* state=\"unlocked\".*\n}
append qemu_args " -display none "
run_genode_until $exp_output 70

View File

@ -372,7 +372,7 @@ append config {
<provides>
<service name="File_system"/>
</provides>
<config user_interface="config_and_report" jitterentropy_available="} [jent_avail_attr] {">
<config jitterentropy_available="} [jent_avail_attr] {">
<vfs>
<dir name="tresor">
<fs label="tresor"/>
@ -437,7 +437,7 @@ lappend_if [have_board linux] boot_modules [file tail [lx_fs_dir]]
build_boot_image $boot_modules
append qemu_args " -display none "
run_genode_until "<ui_report version=\"step_3_lock\" state=\"locked\"/>.*\n" 100
run_genode_until "<ui_report version=\"step_3_lock\" state=\"locked\".*\n" 100
grep_output {\[init -> dynamic_init -> log_terminal\].*}

View File

@ -1,2 +0,0 @@
set ui "config_and_report"
source ${genode_dir}/repos/gems/run/file_vault.inc

View File

@ -0,0 +1,311 @@
proc jent_avail { } {
if {[have_board pbxa9]} { return 0 }
if {[have_board zynq_qemu]} { return 0 }
return 1
}
proc jent_avail_attr { } {
if {[jent_avail]} { return "yes" }
return "no"
}
build { app/file_vault app/file_vault_gui }
create_boot_directory
append archives "
[depot_user]/src/[base_src]
[depot_user]/src/init
[depot_user]/src/libc
[depot_user]/src/zlib
[depot_user]/src/fs_query
[depot_user]/src/tresor
[depot_user]/src/vfs_block
[depot_user]/src/report_rom
[depot_user]/src/vfs
[depot_user]/src/openssl
[depot_user]/src/fs_tool
[depot_user]/src/fs_utils
[depot_user]/src/posix
[depot_user]/src/rump
[depot_user]/src/sandbox"
append_if [jent_avail] archives " [depot_user]/src/vfs_jitterentropy "
lappend archives [depot_user]/src/nitpicker
lappend archives [depot_user]/src/menu_view
lappend archives [depot_user]/src/libpng
lappend archives [depot_user]/pkg/fonts_fs
lappend archives [depot_user]/pkg/[drivers_interactive_pkg]
lappend_if [have_board linux] archives [depot_user]/src/lx_fs
import_from_depot $archives
append config {
<config>
<parent-provides>
<service name="ROM"/>
<service name="LOG"/>
<service name="RM"/>
<service name="CPU"/>
<service name="PD"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
</parent-provides>
<start name="timer" caps="200">
<resource name="RAM" quantum="1M"/>
<resource name="CPU" quantum="5"/>
<provides> <service name="Timer"/> </provides>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
</route>
</start>
<start name="drivers" caps="1500" managing_system="yes">
<resource name="RAM" quantum="64M"/>
<binary name="init"/>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="Capture"> <child name="nitpicker"/> </service>
<service name="Event"> <child name="nitpicker"/> </service>
<service name="ROM" label="config"> <parent label="drivers.config"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="RM"> <parent/> </service>
<service name="IO_MEM"> <parent/> </service>
<service name="IO_PORT"> <parent/> </service>
<service name="IRQ"> <parent/> </service>
</route>
</start>
<start name="nitpicker" caps="100">
<resource name="RAM" quantum="4M"/>
<provides>
<service name="Gui"/> <service name="Capture"/> <service name="Event"/>
</provides>
<config focus="rom">
<capture/> <event/>
<background color="#123456"/>
<domain name="pointer" layer="1" content="client" label="no" origin="pointer" />
<domain name="default" layer="3" content="client" label="no" hover="always" />
<domain name="second" layer="2" xpos="200" ypos="300" content="client" label="no" hover="always" />
<policy label_prefix="pointer" domain="pointer"/>
<policy label_prefix="file_vault_gui" domain="second"/>
<default-policy domain="default"/>
</config>
<route>
<service name="Timer"> <child name="timer" /> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="pointer" caps="100">
<resource name="RAM" quantum="1M"/>
<route>
<service name="Gui"> <child name="nitpicker" /> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="fonts_fs" caps="150">
<binary name="vfs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<vfs>
<rom name="Vera.ttf"/>
<rom name="VeraMono.ttf"/>
<dir name="fonts">
<dir name="title">
<ttf name="regular" path="/Vera.ttf" size_px="18" cache="256K"/>
</dir>
<dir name="text">
<ttf name="regular" path="/Vera.ttf" size_px="14" cache="256K"/>
</dir>
<dir name="annotation">
<ttf name="regular" path="/Vera.ttf" size_px="11" cache="256K"/>
</dir>
<dir name="monospace">
<ttf name="regular" path="/VeraMono.ttf" size_px="14" cache="256K"/>
</dir>
</dir>
</vfs>
<policy label="file_vault_gui -> fonts" root="/fonts" />
</config>
<route>
<service name="ROM" label="config"> <parent label="fonts_fs.config"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start> }
append_if [have_board linux] config {
<start name="data_fs" caps="200" ld="no">
<binary name="lx_fs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<policy label="file_vault -> data" root="/file_vault_gui_dir/data" writeable="yes"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="trust_anchor_fs" caps="200" ld="no">
<binary name="lx_fs"/>
<resource name="RAM" quantum="4M"/>
<provides>
<service name="File_system"/>
</provides>
<config>
<policy label="file_vault -> trust_anchor" root="/file_vault_gui_dir/trust_anchor" writeable="yes"/>
</config>
<route>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start> }
append_if [expr ![have_board linux]] config {
<start name="data_fs" caps="2000">
<binary name="vfs"/>
<resource name="RAM" quantum="200M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs> <dir name="data"> <ram/> </dir> </vfs>
<policy label="file_vault -> data" root="/data" writeable="yes"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="trust_anchor_fs" caps="100">
<binary name="vfs"/>
<resource name="RAM" quantum="5M"/>
<provides><service name="File_system"/></provides>
<config>
<vfs> <dir name="trust_anchor"> <ram/> </dir> </vfs>
<policy label="file_vault -> trust_anchor" root="/trust_anchor" writeable="yes"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start> }
append config {
<start name="report_rom" caps="100">
<resource name="RAM" quantum="1M"/>
<provides> <service name="Report"/> <service name="ROM"/> </provides>
<config verbose="yes">
<policy label="file_vault_gui -> ui_report" report="file_vault -> ui_report"/>
<policy label="file_vault -> ui_config" report="file_vault_gui -> ui_config"/>
</config>
<route>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="CPU"> <parent/> </service>
</route>
</start>
<start name="file_vault" caps="1200">
<resource name="RAM" quantum="100M"/>
<config jitterentropy_available="} [jent_avail_attr] {">
<vfs> <dir name="tresor"> <fs label="tresor"/> </dir> </vfs>
</config>
<route>
<service name="ROM" label="ui_config"> <child name="report_rom"/> </service>
<service name="Report" label="ui_report"> <child name="report_rom"/> </service>
<service name="File_system" label="tresor_trust_anchor_vfs -> storage_dir"> <child name="trust_anchor_fs" label="file_vault -> trust_anchor"/> </service>
<service name="File_system" label="tresor_init -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="tresor"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="image_fs_query -> "> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="tresor_vfs -> tresor_fs"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="File_system" label="truncate_file -> tresor"> <child name="data_fs" label="file_vault -> data"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>
<start name="file_vault_gui" caps="400">
<resource name="RAM" quantum="8M"/>
<route>
<service name="File_system" label_last="fonts"> <child name="fonts_fs"/> </service>
<service name="Gui"> <child name="nitpicker"/> </service>
<service name="ROM" label="ui_report"> <child name="report_rom"/> </service>
<service name="Report" label="ui_config"> <child name="report_rom"/> </service>
<service name="Timer"> <child name="timer"/> </service>
<service name="PD"> <parent/> </service>
<service name="ROM"> <parent/> </service>
<service name="CPU"> <parent/> </service>
<service name="LOG"> <parent/> </service>
<service name="RM"> <parent/> </service>
</route>
</start>
</config> }
install_config $config
if {[have_board linux]} {
exec mkdir -p bin/file_vault_gui_dir/data
exec mkdir -p bin/file_vault_gui_dir/trust_anchor
}
append boot_modules [build_artifacts]
lappend_if [have_board linux] boot_modules file_vault_gui_dir
set fd [open [run_dir]/genode/focus w]
puts $fd "<focus label=\"file_vault_gui -> \"/>"
close $fd
append qemu_args " -display gtk "
build_boot_image $boot_modules
run_genode_until forever

View File

@ -32,10 +32,7 @@ The file vault doesn't consider runtime modifications to its "normal"
configuration (in contrast to modifications to the UI configuration in "config
and report" mode). This is an example File Vault configuration:
! <config user_interface="menu_view"
! verbose_state="no"
! verbose_ui_config="no">
!
! <config verbose_state="no">
! <vfs>
! <dir name="tresor">
! <fs label="tresor"/>
@ -43,12 +40,9 @@ and report" mode). This is an example File Vault configuration:
! </vfs>
! </config>
The "user_interface" attribute knows the two values "config_and_report" and
"menu_view" with the latter being the default. The verbosity attributes are all
The verbosity attributes are all
set to "no" by default. If "verbose_state" is set to "yes" the vault will
reflect its internal state at the LOG session. If "verbose_ui_config" is set to
"yes" the vault will reflect the state of the applied UI config at the LOG
session (user passphrases are not exposed to the LOG session).
reflect its internal state at the LOG session.
The vault currently still requires a directory named "tresor" to be present in its
local VFS. The vault will store a very small file "./file_vault/state" inside
@ -150,8 +144,7 @@ configuration and one Report session for UI reports.
Further resources
~~~~~~~~~~~~~~~~~
The test scripts _gems/recipes/pkg/test-file_vault_config_report_,
_gems/run/file_vault.run_, and_gems/run/file_vault_config_report.run_
The test scripts _gems/recipes/pkg/test-file_vault_ and _gems/run/file_vault.run_
provide examples on how to manually integrate the file vault. The latter can
also be used for analyzing and developing the vault - when targeting native
Linux execution even with a persistent storage back-end. The file vault was

View File

@ -1,58 +0,0 @@
/*
* \brief Printable byte capacity
* \author Norman Feske
* \author Martin Stein
* \date 2018-04-30
*/
/*
* Copyright (C) 2018 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* local includes */
#include <capacity.h>
/**************
** Capacity_**
**************/
void File_vault::Capacity::print(Output &out) const
{
static constexpr uint64_t KB = 1024;
static constexpr uint64_t MB = 1024 * KB;
static constexpr uint64_t GB = 1024 * MB;
Text const text {
(_value >= GB) ? Text((float)_value/GB, " GiB") :
(_value >= MB) ? Text((float)_value/MB, " MiB") :
(_value >= KB) ? Text((float)_value/KB, " KiB") :
Text(_value, " bytes") };
Genode::print(out, text);
}
File_vault::Capacity::Capacity(uint64_t value)
:
_value { value }
{ }
/*********************
** Capacity_string **
*********************/
File_vault::Capacity_string::Capacity_string(uint64_t value)
:
Capacity::Text { Capacity { value } }
{ }
File_vault::Capacity_string::operator char const *()
{
return Capacity::Text::string();
}

View File

@ -1,51 +0,0 @@
/*
* \brief Printable byte capacity
* \author Norman Feske
* \author Martin Stein
* \date 2018-04-30
*/
/*
* Copyright (C) 2018 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 _CAPACITY_H_
#define _CAPACITY_H_
/* local includes */
#include <types.h>
namespace File_vault {
class Capacity;
class Capacity_string;
}
class File_vault::Capacity
{
private:
uint64_t const _value;
public:
using Text = String<64>;
Capacity(uint64_t value);
void print(Output &out) const;
};
class File_vault::Capacity_string : public Capacity::Text
{
public:
Capacity_string(uint64_t value);
operator char const *();
};
#endif /* _CAPACITY_H_ */

View File

@ -1,194 +0,0 @@
/*
* \brief Dynamically growing array
* \author Norman Feske
* \date 2020-01-12
*/
/*
* Copyright (C) 2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _DYNAMIC_ARRAY_H_
#define _DYNAMIC_ARRAY_H_
/* Genode includes */
#include <base/allocator.h>
namespace File_vault {
using namespace Genode;
template <typename>
struct Dynamic_array;
}
template <typename ET>
struct File_vault::Dynamic_array
{
public:
struct Index { unsigned value; };
private:
Allocator &_alloc;
using Element = Constructible<ET>;
Element *_array = nullptr;
unsigned _capacity = 0;
unsigned _upper_bound = 0; /* index after last used element */
bool _index_valid(Index at) const
{
return (at.value < _upper_bound) && _array[at.value].constructed();
}
/*
* Noncopyable
*/
Dynamic_array(Dynamic_array const &other);
void operator = (Dynamic_array const &);
public:
/**
* Moving constructor
*/
Dynamic_array(Dynamic_array &other)
:
_alloc(other._alloc), _array(other._array),
_capacity(other._capacity), _upper_bound(other._upper_bound)
{
other._array = nullptr;
other._capacity = 0;
other._upper_bound = 0;
}
Dynamic_array(Allocator &alloc) : _alloc(alloc) { }
~Dynamic_array()
{
if (!_array)
return;
clear();
_alloc.free(_array, _capacity*sizeof(Element));
}
void clear()
{
if (_upper_bound > 0)
for (unsigned i = _upper_bound; i > 0; i--)
destruct(Index{i - 1});
}
template <typename... ARGS>
void insert(Index at, ARGS &&... args)
{
/* grow array if index exceeds current capacity or if it's full */
if (at.value >= _capacity || _upper_bound == _capacity) {
size_t const new_capacity =
2 * max(_capacity, max(8U, at.value));
Element *new_array = nullptr;
try {
(void)_alloc.alloc(sizeof(Element)*new_capacity, &new_array);
for (unsigned i = 0; i < new_capacity; i++)
construct_at<Element>(&new_array[i]);
}
catch (... /* Out_of_ram, Out_of_caps */ ) { throw; }
if (_array) {
for (unsigned i = 0; i < _upper_bound; i++)
new_array[i].construct(*_array[i]);
_alloc.free(_array, sizeof(Element)*_capacity);
}
_array = new_array;
_capacity = new_capacity;
}
/* make room for new element */
if (_upper_bound > 0)
for (unsigned i = _upper_bound; i > at.value; i--)
_array[i].construct(*_array[i - 1]);
_array[at.value].construct(args...);
_upper_bound = max(at.value + 1, _upper_bound + 1);
}
template <typename... ARGS>
void append(ARGS &&... args) { insert(Index{_upper_bound}, args...); }
bool exists(Index at) const { return _index_valid(at); }
Index upper_bound() const { return Index { _upper_bound }; }
void destruct(Index at)
{
if (!_index_valid(at))
return;
_array[at.value].destruct();
if (_upper_bound > 0)
for (unsigned i = at.value; i < _upper_bound - 1; i++)
_array[i].construct(*_array[i + 1]);
_upper_bound--;
_array[_upper_bound].destruct();
}
template <typename FN>
void apply(Index at, FN const &fn)
{
if (_index_valid(at))
fn(*_array[at.value]);
}
template <typename FN>
void apply(Index at, FN const &fn) const
{
if (_index_valid(at))
fn(*_array[at.value]);
}
struct Range { Index at; unsigned length; };
template <typename FN>
void for_each(Range range, FN const &fn) const
{
unsigned const first = range.at.value;
unsigned const limit = min(_upper_bound, first + range.length);
for (unsigned i = first; i < limit; i++)
if (_array[i].constructed())
fn(Index{i}, *_array[i]);
}
template <typename FN>
void for_each(FN const &fn) const
{
for_each(Range { .at = { 0U }, .length = ~0U }, fn);
}
void print(Output &out) const
{
for (unsigned i = 0; i < _upper_bound; i++)
if (_array[i].constructed())
Genode::print(out, *_array[i]);
}
};
#endif /* _DYNAMIC_ARRAY_H_ */

View File

@ -1,28 +0,0 @@
/*
* \brief Interface for handling input events
* \author Norman Feske
* \date 2018-05-02
*/
/*
* Copyright (C) 2018 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 _GUI_INPUT_EVENT_HANDLER_H_
#define _GUI_INPUT_EVENT_HANDLER_H_
/* Genode includes */
#include <util/interface.h>
#include <input/event.h>
namespace Gui { struct Input_event_handler; }
struct Gui::Input_event_handler : Genode::Interface
{
virtual void handle_input_event(Input::Event const &) = 0;
};
#endif /* _GUI_INPUT_EVENT_HANDLER_H_ */

View File

@ -1,122 +0,0 @@
/*
* \brief GUI wrapper for monitoring the user input of GUI components
* \author Norman Feske
* \date 2020-01-12
*/
/*
* Copyright (C) 2020 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _GUI_SESSION_COMPONENT_H_
#define _GUI_SESSION_COMPONENT_H_
/* Genode includes */
#include <input/component.h>
#include <base/session_object.h>
#include <gui_session/connection.h>
/* local includes */
#include <gui_input_event_handler.h>
namespace Gui {
using namespace Genode;
struct Session_component;
}
struct Gui::Session_component : Session_object<Gui::Session>
{
Env &_env;
Input_event_handler &_event_handler;
Gui::Connection _connection;
Input::Session_component _input_component { _env, _env.ram() };
Signal_handler<Session_component> _input_handler {
_env.ep(), *this, &Session_component::_handle_input };
void _handle_input()
{
_connection.input()->for_each_event([&] (Input::Event ev) {
/* handle event locally within the sculpt manager */
_event_handler.handle_input_event(ev);
_input_component.submit(ev);
});
}
template <typename... ARGS>
Session_component(Env &env, Input_event_handler &event_handler, ARGS &&... args)
:
Session_object(args...),
_env(env), _event_handler(event_handler),
_connection(env, _label.string())
{
_connection.input()->sigh(_input_handler);
_env.ep().manage(_input_component);
_input_component.event_queue().enabled(true);
}
~Session_component() { _env.ep().dissolve(_input_component); }
void upgrade(Session::Resources const &resources)
{
_connection.upgrade(resources);
}
Framebuffer::Session_capability framebuffer_session() override {
return _connection.framebuffer_session(); }
Input::Session_capability input_session() override {
return _input_component.cap(); }
View_handle create_view(View_handle parent) override {
return _connection.create_view(parent); }
void destroy_view(View_handle view) override {
_connection.destroy_view(view); }
View_handle view_handle(View_capability view_cap, View_handle handle) override {
return _connection.view_handle(view_cap, handle); }
View_capability view_capability(View_handle view) override {
return _connection.view_capability(view); }
void release_view_handle(View_handle view) override {
_connection.release_view_handle(view); }
Dataspace_capability command_dataspace() override {
return _connection.command_dataspace(); }
void execute() override {
_connection.execute(); }
Framebuffer::Mode mode() override {
return _connection.mode(); }
void mode_sigh(Signal_context_capability sigh) override {
_connection.mode_sigh(sigh); }
void buffer(Framebuffer::Mode mode, bool use_alpha) override
{
/*
* Do not call 'Connection::buffer' to avoid paying session quota
* from our own budget.
*/
_connection.Client::buffer(mode, use_alpha);
}
void focus(Capability<Gui::Session> session) override {
_connection.focus(session); }
};
#endif /* _GUI_SESSION_COMPONENT_H_ */

View File

@ -0,0 +1,297 @@
/*
* \brief Common types
* \author Martin Stein
* \date 2021-02-25
*/
/*
* Copyright (C) 2021 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 _FILE_VAULT__TYPES_H_
#define _FILE_VAULT__TYPES_H_
/* Genode includes */
#include <tresor/types.h>
namespace File_vault {
using namespace Tresor;
using namespace Genode;
static constexpr Tree_degree TRESOR_VBD_DEGREE = 64;
static constexpr Tree_level_index TRESOR_VBD_MAX_LVL = 5;
static constexpr Tree_degree TRESOR_FREE_TREE_DEGREE = 64;
static constexpr Tree_level_index TRESOR_FREE_TREE_MAX_LVL = 5;
static constexpr size_t MIN_CLIENT_FS_SIZE = 100 * 1024;
static constexpr size_t MIN_PASSPHRASE_LENGTH = 8;
struct Number_of_clients { uint64_t value; };
struct Operation_id { uint64_t value; };
using Version_string = String<80>;
template <typename T>
static void read_optional_attr(Xml_node const &node, char const *attr, Constructible<T> &dst)
{
if (node.has_attribute(attr))
dst.construct(node.attribute_value(attr, T { }));
}
struct Ui_report
{
using State_string = String<32>;
enum State {
INVALID, UNINITIALIZED, INITIALIZING, LOCKED, UNLOCKING, UNLOCKED, LOCKING };
static State_string state_to_string(State state)
{
switch (state) {
case INVALID: return "invalid";
case UNINITIALIZED: return "uninitialized";
case INITIALIZING: return "initializing";
case LOCKED: return "locked";
case UNLOCKING: return "unlocking";
case UNLOCKED: return "unlocked";
case LOCKING: return "locking";
}
ASSERT_NEVER_REACHED;
}
static State string_to_state(State_string str)
{
if (str == "uninitialized") return UNINITIALIZED;
if (str == "initializing") return INITIALIZING;
if (str == "locked") return LOCKED;
if (str == "unlocking") return UNLOCKING;
if (str == "unlocked") return UNLOCKED;
if (str == "locking") return LOCKING;
return INVALID;
}
struct Rekey
{
Operation_id id;
bool finished;
Rekey(Xml_node const &node)
: id(node.attribute_value("id", 0ULL)), finished(node.attribute_value("finished", false)) { }
Rekey(Operation_id id, bool finished) : id(id), finished(finished) { }
void generate(Xml_generator &xml)
{
xml.attribute("id", id.value);
xml.attribute("finished", finished);
}
};
struct Extend
{
Operation_id id { };
bool finished { };
Extend(Xml_node const &node)
: id(node.attribute_value("id", 0ULL)), finished(node.attribute_value("finished", false)) { }
Extend(Operation_id id, bool finished) : id(id), finished(finished) { }
void generate(Xml_generator &xml)
{
xml.attribute("id", id.value);
xml.attribute("finished", finished);
}
};
State state { INVALID };
Version_string version { };
Number_of_bytes image_size { };
Number_of_bytes capacity { };
Number_of_clients num_clients { };
Constructible<Rekey> rekey { };
Constructible<Extend> extend { };
Ui_report() { }
Ui_report(Xml_node const &node)
:
state(string_to_state(node.attribute_value("state", State_string()))),
version(node.attribute_value("version", Version_string())),
image_size(node.attribute_value("image_size", Number_of_bytes())),
capacity(node.attribute_value("capacity", Number_of_bytes())),
num_clients(node.attribute_value("num_clients", 0ULL))
{
node.with_optional_sub_node("rekey", [&] (Xml_node const &n) { rekey.construct(n); });
node.with_optional_sub_node("extend", [&] (Xml_node const &n) { extend.construct(n); });
}
void generate(Xml_generator &xml)
{
xml.attribute("state", state_to_string(state));
xml.attribute("version", version);
xml.attribute("image_size", image_size);
xml.attribute("capacity", capacity);
xml.attribute("num_clients", num_clients.value);
if (rekey.constructed())
xml.node("rekey", [&] { rekey->generate(xml); });
if (extend.constructed())
xml.node("extend", [&] { extend->generate(xml); });
}
};
struct Ui_config
{
struct Extend
{
using Tree_string = String<4>;
enum Tree { VIRTUAL_BLOCK_DEVICE, FREE_TREE };
Operation_id id;
Tree tree;
Number_of_bytes num_bytes;
static Tree string_to_tree(Tree_string const &str)
{
if (str == "vbd") return VIRTUAL_BLOCK_DEVICE;
if (str == "ft") return FREE_TREE;
ASSERT_NEVER_REACHED;
}
static Tree_string tree_to_string(Tree tree_arg)
{
switch (tree_arg) {
case VIRTUAL_BLOCK_DEVICE: return "vbd";
case FREE_TREE: return "ft"; }
ASSERT_NEVER_REACHED;
}
Extend(Xml_node const &node)
:
id(node.attribute_value("id", 0ULL)),
tree(string_to_tree(node.attribute_value("tree", Tree_string()))),
num_bytes(node.attribute_value("num_bytes", 0UL))
{ }
Extend(Operation_id id, Tree tree, Number_of_bytes num_bytes) : id(id), tree(tree), num_bytes(num_bytes) { }
void generate(Xml_generator &xml)
{
xml.attribute("id", id.value);
xml.attribute("tree", tree_to_string(tree));
xml.attribute("num_bytes", num_bytes);
}
};
struct Rekey
{
Operation_id id;
Rekey(Xml_node const &node) : id(node.attribute_value("id", 0ULL)) { }
Rekey(Operation_id id) : id(id) { }
void generate(Xml_generator &xml) { xml.attribute("id", id.value); }
};
Version_string version { };
Passphrase passphrase { };
Number_of_bytes client_fs_size { };
Number_of_bytes journaling_buf_size { };
Constructible<Rekey> rekey { };
Constructible<Extend> extend { };
Ui_config(Xml_node const &node)
:
version(node.attribute_value("version", Version_string())),
passphrase(node.attribute_value("passphrase", Passphrase())),
client_fs_size(node.attribute_value("client_fs_size", Number_of_bytes())),
journaling_buf_size(node.attribute_value("journaling_buf_size", Number_of_bytes()))
{
node.with_optional_sub_node("rekey", [&] (Xml_node const &n) { rekey.construct(n); });
node.with_optional_sub_node("extend", [&] (Xml_node const &n) { extend.construct(n); });
}
Ui_config() { }
void generate(Xml_generator &xml)
{
xml.attribute("passphrase", passphrase);
xml.attribute("client_fs_size", client_fs_size);
xml.attribute("journaling_buf_size", journaling_buf_size);
if (rekey.constructed())
xml.node("rekey", [&] { rekey->generate(xml); });
if (extend.constructed())
xml.node("extend", [&] { extend->generate(xml); });
}
bool passphrase_long_enough() const { return passphrase.length() >= MIN_PASSPHRASE_LENGTH + 1; }
};
inline Number_of_blocks tresor_tree_num_blocks(size_t num_lvls,
size_t num_children,
Number_of_leaves num_leaves)
{
Number_of_blocks num_blks { 0 };
Number_of_blocks num_last_lvl_blks { num_leaves };
for (size_t lvl_idx { 0 }; lvl_idx < num_lvls; lvl_idx++) {
num_blks += num_last_lvl_blks;
if (num_last_lvl_blks % num_children) {
num_last_lvl_blks = num_last_lvl_blks / num_children + 1;
} else {
num_last_lvl_blks = num_last_lvl_blks / num_children;
}
}
return num_blks;
}
inline Number_of_blocks tresor_num_blocks(Number_of_blocks num_superblocks,
size_t num_vbd_lvls,
size_t num_vbd_children,
Number_of_leaves num_vbd_leaves,
size_t num_ft_lvls,
size_t num_ft_children,
Number_of_leaves num_ft_leaves)
{
Number_of_blocks const num_vbd_blks {
tresor_tree_num_blocks(num_vbd_lvls, num_vbd_children, num_vbd_leaves) };
Number_of_blocks const num_ft_blks {
tresor_tree_num_blocks(num_ft_lvls, num_ft_children, num_ft_leaves) };
/* FIXME
*
* This would be the correct way to calculate the number of MT blocks
* but the Tresor still uses an MT the same size as the FT for simplicity
* reasons. As soon as the Tresor does it right we should fix also this path.
*
* size_t const num_mt_leaves {
* num_ft_blks - num_ft_leaves };
*
* size_t const num_mt_blks {
* _tree_num_blocks(
* num_mt_lvls,
* num_mt_children,
* num_mt_leaves) };
*/
Number_of_blocks const num_mt_blks { num_ft_blks };
return num_superblocks + num_vbd_blks + num_ft_blks + num_mt_blks;
}
inline Number_of_blocks tresor_tree_num_leaves(uint64_t payload_size)
{
Number_of_blocks num_leaves { payload_size / BLOCK_SIZE };
if (payload_size % BLOCK_SIZE) {
num_leaves++;
}
return num_leaves;
}
}
#endif /* _FILE_VAULT__TYPES_H_ */

View File

@ -1,251 +0,0 @@
/*
* \brief Text buffer for a passphrase
* \author Norman Feske
* \author Martin Stein
* \date 2021-03-02
*/
/*
* Copyright (C) 2021 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 _INPUT_H_
#define _INPUT_H_
/* Genode includes */
#include <base/output.h>
#include <util/utf8.h>
#include <base/buffered_output.h>
/* local includes */
#include <types.h>
namespace File_vault {
class Input_single_line;
class Input_passphrase;
class Input_number_of_bytes;
class Input_number_of_blocks;
}
class File_vault::Input_single_line
{
public:
enum { MAX_LENGTH = 64 };
protected:
Codepoint _characters[MAX_LENGTH] { };
unsigned _length = 0;
void _print_characters(Output &out) const
{
/*
* FIXME This was copied from gems/src/server/terminal/main.cc
*/
struct Utf8 { char b0, b1, b2, b3, b4; };
auto utf8_from_codepoint = [] (unsigned c) {
/* extract 'n' bits 'at' bit position of value 'c' */
auto bits = [c] (unsigned at, unsigned n) {
return (c >> at) & ((1 << n) - 1); };
return (c < 2<<7) ? Utf8 { char(bits( 0, 7)), 0, 0, 0, 0 }
: (c < 2<<11) ? Utf8 { char(bits( 6, 5) | 0xc0),
char(bits( 0, 6) | 0x80), 0, 0, 0 }
: (c < 2<<16) ? Utf8 { char(bits(12, 4) | 0xe0),
char(bits( 6, 6) | 0x80),
char(bits( 0, 6) | 0x80), 0, 0 }
: (c < 2<<21) ? Utf8 { char(bits(18, 3) | 0xf0),
char(bits(12, 6) | 0x80),
char(bits( 6, 6) | 0x80),
char(bits( 0, 6) | 0x80), 0 }
: Utf8 { };
};
for (unsigned i = 0; i < _length; i++) {
Utf8 const utf8 = utf8_from_codepoint(_characters[i].value);
auto _print = [&] (char c) {
if (c)
Genode::print(out, Char(c)); };
_print(utf8.b0); _print(utf8.b1); _print(utf8.b2);
_print(utf8.b3); _print(utf8.b4);
}
}
public:
void append_character(Codepoint c)
{
if (_length < MAX_LENGTH) {
_characters[_length] = c;
_length++;
}
}
void remove_last_character()
{
if (_length > 0) {
_length--;
_characters[_length].value = 0;
}
}
bool equals(Input_single_line const &other) const
{
if (other._length != _length) {
return false;
}
if (memcmp(other._characters, _characters, _length) != 0) {
return false;
}
return true;
}
unsigned length() const { return _length; }
};
class File_vault::Input_passphrase : public Input_single_line
{
private:
bool _hide { true };
void _print_bullets(Output &out) const
{
char const bullet_utf8[4] {
(char)0xe2, (char)0x80, (char)0xa2, 0 };
for (unsigned i = 0; i < _length; i++)
Genode::print(out, bullet_utf8);
}
public:
void print(Output &out) const
{
if (_hide) {
_print_bullets(out);
} else {
_print_characters(out);
}
}
void hide(bool value)
{
_hide = value;
}
bool hide() const
{
return _hide;
}
bool appendable_character(Codepoint code)
{
if (!code.valid()) {
return false;
}
bool const is_printable {
code.value >= 0x20 && code.value < 0xf000 };
return is_printable;
}
String<MAX_LENGTH * 3> plaintext() const
{
String<MAX_LENGTH * 3> result { };
auto write = [&] (char const *str)
{
result = Cstring(str, strlen(str));
};
Buffered_output<MAX_LENGTH * 3, decltype(write)> output(write);
_print_characters(output);
return result;
}
};
class File_vault::Input_number_of_bytes : public Input_single_line
{
public:
void print(Output &out) const
{
_print_characters(out);
}
size_t value() const
{
String<32> const str { *this };
Number_of_bytes result { 0 };
ascii_to(str.string(), result);
return result;
}
bool appendable_character(Codepoint code)
{
if (!code.valid()) {
return false;
}
bool const is_number {
code.value >= 48 && code.value <= 57 };
bool const is_unit_prefix {
code.value == 71 || code.value == 75 || code.value == 77 };
return is_number || is_unit_prefix;
}
};
class File_vault::Input_number_of_blocks : public Input_single_line
{
public:
void print(Output &out) const
{
_print_characters(out);
}
unsigned long to_unsigned_long() const
{
String<32> const str { *this };
unsigned long result { 0 };
ascii_to(str.string(), result);
return result;
}
bool is_nr_greater_than_zero() const
{
return (size_t)to_unsigned_long() > 0;
}
bool appendable_character(Codepoint code)
{
if (!code.valid()) {
return false;
}
bool const is_number {
code.value >= 48 && code.value <= 57 };
return is_number;
}
};
#endif /* _INPUT_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,404 +0,0 @@
/*
* \brief Local utilities for the menu view dialog
* \author Martin Stein
* \date 2021-02-24
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* local includes */
#include <menu_view_dialog.h>
#include <capacity.h>
using namespace File_vault;
void File_vault::gen_normal_font_attribute(Xml_generator &xml)
{
xml.attribute("font", "text/regular");
}
void File_vault::gen_frame_title(Xml_generator &xml,
char const *name,
unsigned long min_width,
bool jent_avail)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.attribute("west", "yes");
xml.attribute("north", "yes");
if (jent_avail) {
xml.node("label", [&] () {
xml.attribute("text", "" );
xml.attribute("min_ex", min_width);
});
} else {
xml.node("vbox", [&] () {
xml.node("label", [&] () {
xml.attribute("name", "warning_0");
xml.attribute("font", "title/regular");
xml.attribute("text", " Warning: Insecure mode, no entropy source! " );
xml.attribute("min_ex", min_width);
});
xml.node("label", [&] () {
xml.attribute("name", "warning_1");
xml.attribute("text", " " );
});
});
}
});
}
void File_vault::gen_info_frame(Xml_generator &xml,
bool jent_avail,
char const *name,
char const *info,
unsigned long min_width)
{
gen_main_frame(xml, jent_avail, name, min_width, [&] (Xml_generator &xml) {
gen_centered_info_line(xml, "info", info);
gen_info_line(xml, "pad_1", "");
});
}
void File_vault::gen_action_button_at_bottom(Xml_generator &xml,
char const *name,
char const *label,
bool hovered,
bool selected)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.attribute("east", "yes");
xml.attribute("west", "yes");
xml.attribute("south", "yes");
xml.node("button", [&] () {
if (hovered) {
xml.attribute("hovered", "yes");
}
if (selected) {
xml.attribute("selected", "yes");
}
xml.node("float", [&] () {
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", label);
});
});
});
});
}
void File_vault::gen_action_button_at_bottom(Xml_generator &xml,
char const *label,
bool hovered,
bool selected)
{
gen_action_button_at_bottom(xml, label, label, hovered, selected);
}
void File_vault::gen_action_button(Xml_generator &xml,
char const *name,
char const *label,
bool hovered,
bool selected,
size_t min_ex)
{
xml.node("button", [&] () {
xml.attribute("name", name);
if (hovered) {
xml.attribute("hovered", "yes");
}
if (selected) {
xml.attribute("selected", "yes");
}
xml.node("label", [&] () {
if (min_ex != 0) {
xml.attribute("min_ex", min_ex);
}
xml.attribute("text", label);
});
});
}
void File_vault::gen_text_input(Xml_generator &xml,
char const *name,
String<256> const &text,
bool selected)
{
String<256> const padded_text { " ", text };
xml.node("frame", [&] () {
xml.attribute("name", name);
xml.node("float", [&] () {
xml.attribute("west", "yes");
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", padded_text);
if (selected) {
xml.node("cursor", [&] () {
xml.attribute("at", padded_text.length() - 1 );
});
}
});
});
});
}
void
File_vault::
gen_input_passphrase(Xml_generator &xml,
size_t max_width,
Input_passphrase const &passphrase,
bool input_selected,
bool show_hide_button_hovered,
bool show_hide_button_selected)
{
char const *show_hide_button_label;
size_t cursor_at;
if (passphrase.hide()) {
show_hide_button_label = "Show";
cursor_at = passphrase.length() + 1;
} else {
show_hide_button_label = "Hide";
cursor_at = passphrase.length() + 1;
}
xml.node("float", [&] () {
xml.attribute("name", "Passphrase Label");
xml.attribute("west", "yes");
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", " Passphrase: ");
});
});
xml.node("hbox", [&] () {
String<256> const padded_text { " ", passphrase, " " };
xml.node("frame", [&] () {
xml.attribute("name", "Passphrase");
xml.node("float", [&] () {
xml.attribute("west", "yes");
xml.node("label", [&] () {
xml.attribute("min_ex", max_width - 11);
gen_normal_font_attribute(xml);
xml.attribute("text", padded_text);
if (input_selected) {
xml.node("cursor", [&] () {
xml.attribute("at", cursor_at );
});
}
});
});
});
xml.node("float", [&] () {
xml.attribute("name", "1");
xml.attribute("east", "yes");
gen_action_button(
xml, "Show Hide", show_hide_button_label,
show_hide_button_hovered, show_hide_button_selected, 5);
});
});
}
void File_vault::gen_titled_text_input(Xml_generator &xml,
char const *name,
char const *title,
String<256> const &text,
bool selected)
{
xml.node("float", [&] () {
xml.attribute("name", String<64> { name, "_label" });
xml.attribute("west", "yes");
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", String<64> { " ", title, ": " });
});
});
gen_text_input(xml, name, text, selected);
}
void File_vault::gen_empty_line(Xml_generator &xml,
char const *name,
size_t min_width)
{
xml.node("label", [&] () {
xml.attribute("name", name);
xml.attribute("min_ex", min_width);
xml.attribute("text", "");
});
}
void File_vault::gen_info_line(Xml_generator &xml,
char const *name,
char const *text)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.attribute("west", "yes");
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", String<256> { " ", text, " "});
});
});
}
void File_vault::gen_centered_info_line(Xml_generator &xml,
char const *name,
char const *text)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", String<256> { " ", text, " "});
});
});
}
void File_vault::gen_multiple_choice_entry(Xml_generator &xml,
char const *name,
char const *text,
bool hovered,
bool selected)
{
xml.node("float", [&] () {
xml.attribute("name", name);
xml.attribute("west", "yes");
xml.node("hbox", [&] () {
xml.node("button", [&] () {
if (selected) {
xml.attribute("selected", "yes");
}
if (hovered) {
xml.attribute("hovered", "yes");
}
xml.attribute("style", "radio");
xml.node("hbox", [&] () { });
});
xml.node("label", [&] () {
gen_normal_font_attribute(xml);
xml.attribute("text", String<64> { " ", text });
});
});
});
}
void File_vault::gen_menu_title(Xml_generator &xml,
char const *name,
char const *label,
char const *label_annex,
bool hovered,
bool selected)
{
xml.node("hbox", [&] () {
xml.attribute("name", name);
xml.node("float", [&] () {
xml.attribute("name", "0");
xml.attribute("west", "yes");
xml.node("hbox", [&] () {
xml.node("button", [&] () {
if (selected) {
xml.attribute("style", "back");
xml.attribute("selected", "yes");
} else {
xml.attribute("style", "radio");
}
if (hovered) {
xml.attribute("hovered", "yes");
}
xml.attribute("hovered", "no");
xml.node("hbox", [&] () { });
});
xml.node("label", [&] () {
if (selected) {
xml.attribute("font", "title/regular");
}
xml.attribute("text", String<64> { " ", label });
});
});
});
xml.node("float", [&] () {
xml.attribute("name", "2");
xml.attribute("east", "yes");
xml.node("label", [&] () {
xml.attribute("font", "title/regular");
xml.attribute(
"text", label_annex);
});
});
});
}
void File_vault::gen_closed_menu(Xml_generator &xml,
char const *label,
char const *label_annex,
bool hovered)
{
xml.node("vbox", [&] () {
xml.attribute("name", label);
gen_menu_title(xml, "Enter", label, label_annex, hovered, false);
});
}
void File_vault::gen_global_controls(Xml_generator &xml,
size_t min_width,
size_t tresor_image_size,
size_t client_fs_size,
size_t nr_of_clients,
bool lock_button_hovered,
bool lock_button_selected)
{
gen_empty_line(xml, "Status 0", min_width);
gen_centered_info_line(xml, "Status 1",
String<256> {
" Image: ",
Capacity_string { tresor_image_size },
", Client FS: ",
Capacity_string { client_fs_size },
", Clients: ",
nr_of_clients
}.string()
);
gen_empty_line(xml, "Status 3", 0);
xml.node("hbox", [&] () {
gen_action_button(
xml, "Lock", "Lock", lock_button_hovered, lock_button_selected);
});
}

View File

@ -1,188 +0,0 @@
/*
* \brief Local utilities for the menu view dialog
* \author Martin Stein
* \date 2021-02-24
*/
/*
* Copyright (C) 2021 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 _MENU_VIEW_DIALOG_H_
#define _MENU_VIEW_DIALOG_H_
/* Genode includes */
#include <util/xml_generator.h>
/* local includes */
#include <types.h>
#include <input.h>
namespace File_vault {
void gen_normal_font_attribute(Xml_generator &xml);
void gen_frame_title(Xml_generator &xml,
char const *name,
unsigned long min_width,
bool jent_avail);
template <typename GEN_FRAME_CONTENT>
void gen_main_frame(Xml_generator &xml,
bool jent_avail,
char const *name,
unsigned long min_width,
GEN_FRAME_CONTENT const &gen_frame_content)
{
xml.node("frame", [&] () {
xml.attribute("name", name);
xml.node("vbox", [&] () {
gen_frame_title(xml, "title", min_width, jent_avail);
gen_frame_content(xml);
});
});
}
template <typename GEN_FRAME_CONTENT>
void gen_controls_frame(Xml_generator &xml,
bool jent_avail,
char const *name,
GEN_FRAME_CONTENT const &gen_frame_content)
{
xml.node("frame", [&] () {
xml.attribute("name", name);
xml.node("vbox", [&] () {
if (!jent_avail)
gen_frame_title(xml, "title", 0, jent_avail);
gen_frame_content(xml);
});
});
}
template <typename GEN_FRAME_CONTENT>
void gen_untitled_frame(Xml_generator &xml,
char const *name,
GEN_FRAME_CONTENT const &gen_frame_content)
{
xml.node("frame", [&] () {
xml.attribute("name", name);
xml.node("float", [&] () {
xml.attribute("name", "xxx");
xml.attribute("east", "yes");
xml.attribute("west", "yes");
xml.attribute("north", "yes");
xml.node("vbox", [&] () {
gen_frame_content(xml);
});
});
});
}
void gen_info_frame(Xml_generator &xml,
bool jent_avail,
char const *name,
char const *info,
unsigned long min_width);
void gen_action_button_at_bottom(Xml_generator &xml,
char const *name,
char const *label,
bool hovered,
bool selected);
void gen_action_button_at_bottom(Xml_generator &xml,
char const *label,
bool hovered,
bool selected);
void gen_text_input(Xml_generator &xml,
char const *name,
String<256> const &text,
bool selected);
void gen_titled_text_input(Xml_generator &xml,
char const *name,
char const *title,
String<256> const &text,
bool selected);
void gen_info_line(Xml_generator &xml,
char const *name,
char const *text);
void gen_centered_info_line(Xml_generator &xml,
char const *name,
char const *text);
void gen_empty_line(Xml_generator &xml,
char const *name,
size_t min_width);
void gen_multiple_choice_entry(Xml_generator &xml,
char const *name,
char const *text,
bool hovered,
bool selected);
void gen_menu_title(Xml_generator &xml,
char const *name,
char const *label,
char const *label_annex,
bool hovered,
bool selected);
void gen_closed_menu(Xml_generator &xml,
char const *label,
char const *label_annex,
bool hovered);
template <typename GEN_CONTENT>
void gen_opened_menu(Xml_generator &xml,
char const *label,
char const *label_annex,
bool hovered,
GEN_CONTENT const &gen_content)
{
xml.node("vbox", [&] () {
xml.attribute("name", label);
gen_menu_title(xml, "Leave", label, label_annex, hovered, true);
gen_content(xml);
});
}
void gen_input_passphrase(Xml_generator &xml,
size_t max_width,
Input_passphrase const &passphrase,
bool input_selected,
bool show_hide_button_hovered,
bool show_hide_button_selected);
void gen_action_button(Xml_generator &xml,
char const *name,
char const *label,
bool hovered,
bool selected,
size_t min_ex = 0);
void gen_global_controls(Xml_generator &xml,
size_t min_width,
size_t tresor_image_size,
size_t client_fs_size,
size_t nr_of_clients,
bool lock_button_hovered,
bool lock_button_selected);
}
#endif /* _MENU_VIEW_DIALOG_H_ */

View File

@ -18,9 +18,6 @@
#include <util/string.h>
#include <sandbox/sandbox.h>
/* local includes */
#include <input.h>
namespace File_vault {
template <typename ARG>

View File

@ -1,6 +1,6 @@
TARGET := file_vault
SRC_CC += main.cc menu_view_dialog.cc capacity.cc
SRC_CC += main.cc
INC_DIR += $(PRG_DIR)
INC_DIR += $(call select_from_repositories,/src/lib/tresor/include)

View File

@ -15,15 +15,10 @@
#define _TYPES_H_
/* Genode includes */
#include <tresor/types.h>
namespace Genode { }
#include <include/file_vault/types.h>
namespace File_vault {
using namespace Tresor;
using namespace Genode;
using Node_name = String<32>;
using File_path = String<32>;

View File

@ -1,32 +0,0 @@
/*
* \brief Local extension of Genodes UTF8 utilities
* \author Norman Feske
* \author Martin Stein
* \date 2021-03-04
*/
/*
* Copyright (C) 2021 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 _UTF8_H_
#define _UTF8_H_
/* Genode includes */
#include <util/utf8.h>
/* local includes */
#include <types.h>
namespace File_vault {
enum {
CODEPOINT_BACKSPACE = 8,
CODEPOINT_TAB = 9,
};
}
#endif /* _UTF8_H_ */

View File

@ -0,0 +1,758 @@
/*
* \brief Test for Genode's dialog API
* \author Norman Feske
* \date 2023-03-25
*/
/*
* 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.
*/
#include <base/component.h>
#include <base/attached_rom_dataspace.h>
#include <os/reporter.h>
#include <dialog/runtime.h>
#include <dialog/widgets.h>
#include <file_vault/types.h>
using namespace Dialog;
using namespace File_vault;
using Text = String<32>;
struct Back_button : Widget<Float>
{
void view(Scope<Float> &s) const
{
s.sub_scope<Button>([&] (Scope<Float, Button> &s) {
if (s.hovered()) s.attribute("hovered", "yes");
s.attribute("style", "back");
s.sub_scope<Hbox>();
});
}
void click(Clicked_at const &, auto const &fn) { fn(); }
};
struct Left_align : Sub_scope
{
static void view_sub_scope(auto &s, auto const &text)
{
s.node("float", [&] {
s.attribute("west", "yes");
s.named_sub_node("label", "label", [&] {
s.attribute("text", text); }); });
}
static void with_narrowed_at(auto const &, auto const &) { }
};
struct Switch : Widget<Button>
{
bool &on;
Switch(bool &on) : on(on) { }
void view(Scope<Button> &s, Text const &on_text, Text const &off_text) const
{
bool const hovered = (s.hovered() && (!s.dragged() || on));
if (hovered) s.attribute("hovered", "yes");
s.sub_scope<Label>(on ? on_text : off_text);
}
void click(Clicked_at const &) { on = !on; }
};
struct Prompt : Widget<Button>
{
struct Action : Interface, Noncopyable { virtual void refresh_prompt() = 0; };
Text text { };
void handle_event(Event const &event, Action &action, auto const &appendable)
{
event.event.handle_press([&] (Input::Keycode key, Codepoint code) {
if (key == Input::KEY_BACKSPACE) {
text = Cstring(text.string(), text.length() - 2);
action.refresh_prompt();
} else if (code.valid()) {
if (appendable(code)) {
text = { text, code };
action.refresh_prompt();
}
}
});
}
void view(Scope<Button> &s, bool selected, auto const &viewed_text) const
{
if (s.hovered())
s.attribute("hovered", "yes");
s.sub_scope<Float>([&] (Scope<Button, Float> &s) {
s.attribute("west", "yes");
s.sub_scope<Vbox>([&] (Scope<Button, Float, Vbox> &s) {
s.sub_scope<Min_ex>(20);
s.node("float", [&] {
s.attribute("west", "yes");
s.sub_scope<Label>(viewed_text(), [&] (Scope<Button, Float, Vbox, Label> &s) {
if (selected)
s.sub_node("cursor", [&] {
s.attribute("name", "cursor");
s.attribute("at", text.length()); });
});
});
});
});
}
void click(Clicked_at const &, auto const &fn) { fn(); }
};
struct Passphrase_prompt : Prompt
{
bool show_text { false };
void view(Scope<Button> &s, bool selected) const
{
Prompt::view(s, selected, [&] {
using Result = String<Text::size()*3>;
if (show_text)
return Result(text);
Result bullets { };
if (text.valid()) {
auto fn = [&] (char const *str) { bullets = Cstring(str, strlen(str)); };
Buffered_output<bullets.size(), decltype(fn)> out(fn);
for (size_t i = 0; i++ < text.length() - 1;)
print(out, "\u2022");
}
return bullets; });
}
void handle_event(Event const &event, Action &action)
{
Prompt::handle_event(event, action, [&] (Codepoint code) {
return code.value >= 0x20 && code.value < 0xf000; });
}
};
struct Size_prompt : Prompt
{
void view(Scope<Button> &s, bool selected) const { Prompt::view(s, selected, [&] { return text; }); }
void handle_event(Event const &event, Action &action)
{
Prompt::handle_event(event, action, [&] (Codepoint code) {
return (code.value >= '0' && code.value <= '9') || code.value == 'K' || code.value == 'M' || code.value == 'G'; });
}
Number_of_bytes as_num_bytes() const
{
Number_of_bytes ret { };
ascii_to(text.string(), ret);
return ret;
}
};
struct Main : Prompt::Action
{
enum Dialog_type { NONE, SETUP, WAIT, CONTROLS, UNLOCK };
struct Unlock_frame : Widget<Frame>
{
Main &main;
Hosted<Frame, Vbox, Hbox, Passphrase_prompt> passphrase { Id("Passphrase") };
Hosted<Frame, Vbox, Hbox, Switch> show_passphrase { Id("Show Passphrase"), passphrase.show_text };
Hosted<Frame, Vbox, Action_button> unlock_button { Id("Unlock") };
Unlock_frame(Main &main) : main(main) { }
bool passphrase_long_enough() const { return passphrase.text.length() >= MIN_PASSPHRASE_LENGTH + 1; }
void view(Scope<Frame> &s) const
{
s.sub_scope<Vbox>([&] (Scope<Frame, Vbox> &s) {
s.sub_scope<Left_align>(" Passphrase: ");
s.sub_scope<Hbox>([&] (Scope<Frame, Vbox, Hbox> &s) {
s.widget(passphrase, true);
s.widget(show_passphrase, "Hide", "Show");
});
if (passphrase_long_enough())
s.widget(unlock_button);
else
s.sub_scope<Left_align>(Text(" Minimum length: ", (size_t)MIN_PASSPHRASE_LENGTH));
});
}
void click(Clicked_at const &at)
{
passphrase.propagate(at, [&] { });
show_passphrase.propagate(at);
unlock_button.propagate(at, [&] { unlock(); });
}
void unlock()
{
main.unlock(*this);
passphrase.text = "";
}
void handle_event(Dialog::Event const &event)
{
event.event.handle_press([&] (Input::Keycode key, Codepoint) {
switch (key) {
case Input::KEY_ENTER:
if (passphrase_long_enough())
unlock();
break;
case Input::KEY_TAB: break;
default: passphrase.handle_event(event, main); break;
}
});
}
};
struct Setup_frame : Widget<Frame>
{
enum { MIN_CAPACITY = 100 * 1024 };
enum Prompt_type { PASSPHRASE, CAPACITY, JOURNALING_BUFFER };
Main &main;
Prompt_type selected = PASSPHRASE;
Hosted<Frame, Vbox, Hbox, Passphrase_prompt> passphrase { Id("Passphrase") };
Hosted<Frame, Vbox, Hbox, Switch> show_passphrase { Id("Show Passphrase"), passphrase.show_text };
Hosted<Frame, Vbox, Size_prompt> capacity { Id("Capacity") };
Hosted<Frame, Vbox, Size_prompt> journal_buf { Id("Journaling Buffer") };
Hosted<Frame, Vbox, Action_button> start_button { Id("Start") };
Setup_frame(Main &main) : main(main) { }
size_t min_journal_buf() const
{
size_t result { (size_t)capacity.as_num_bytes() >> 8 };
if (result < MIN_CAPACITY)
result = MIN_CAPACITY;
return result;
}
bool passphrase_long_enough() const { return passphrase.text.length() >= MIN_PASSPHRASE_LENGTH + 1; }
bool capacity_sufficient() const { return capacity.as_num_bytes() >= MIN_CAPACITY; }
bool journal_buf_sufficient() const { return journal_buf.as_num_bytes() >= min_journal_buf(); }
bool ready_to_setup() const { return passphrase_long_enough() && capacity_sufficient() && journal_buf_sufficient(); }
Number_of_bytes image_size() const
{
return (size_t)(BLOCK_SIZE * tresor_num_blocks(
NR_OF_SUPERBLOCK_SLOTS, TRESOR_VBD_MAX_LVL + 1, TRESOR_VBD_DEGREE,
tresor_tree_num_leaves(capacity.as_num_bytes()), TRESOR_FREE_TREE_MAX_LVL + 1,
TRESOR_FREE_TREE_DEGREE, tresor_tree_num_leaves(journal_buf.as_num_bytes())));
}
void view(Scope<Frame> &s) const
{
s.sub_scope<Vbox>([&] (Scope<Frame, Vbox> &s) {
s.sub_scope<Left_align>(" Passphrase: ");
s.sub_scope<Hbox>([&] (Scope<Frame, Vbox, Hbox> &s) {
s.widget(passphrase, selected == PASSPHRASE);
s.widget(show_passphrase, "Hide", "Show");
});
if (!passphrase_long_enough())
s.sub_scope<Left_align>(Text(" Minimum length: ", (size_t)MIN_PASSPHRASE_LENGTH, " "));
s.sub_scope<Left_align>("");
s.sub_scope<Left_align>(" Capacity: ");
s.widget(capacity, selected == CAPACITY);
if (!capacity_sufficient())
s.sub_scope<Left_align>(Text(" Minimum: ", Number_of_bytes(MIN_CAPACITY), " "));
s.sub_scope<Left_align>("");
s.sub_scope<Left_align>(" Journaling buffer: ");
s.widget(journal_buf, selected == JOURNALING_BUFFER);
if (!journal_buf_sufficient())
s.sub_scope<Left_align>(Text(" Minimum: ", min_journal_buf(), " "));
if (capacity_sufficient() && journal_buf_sufficient()) {
s.sub_scope<Left_align>("");
s.sub_scope<Left_align>(Text(" Image size: ", image_size(), " "));
}
if (ready_to_setup()) {
s.sub_scope<Left_align>("");
s.widget(start_button);
}
});
}
void click(Clicked_at const &at)
{
passphrase.propagate(at, [&] { selected = PASSPHRASE; });
show_passphrase.propagate(at);
capacity.propagate(at, [&] { selected = CAPACITY; });
journal_buf.propagate(at, [&] { selected = JOURNALING_BUFFER; });
start_button.propagate(at, [&] { setup(); });
}
void select_next()
{
switch (selected) {
case PASSPHRASE: selected = CAPACITY; break;
case CAPACITY: selected = JOURNALING_BUFFER; break;
case JOURNALING_BUFFER: selected = PASSPHRASE; break;
}
main.main_view.refresh();
}
void forward_to_selected(Dialog::Event const &event)
{
switch (selected) {
case PASSPHRASE: passphrase.handle_event(event, main); break;
case CAPACITY: capacity.handle_event(event, main); break;
case JOURNALING_BUFFER: journal_buf.handle_event(event, main); break;
}
}
void setup()
{
main.setup(*this);
passphrase.text = "";
capacity.text = "";
journal_buf.text = "";
}
void handle_event(Dialog::Event const &event)
{
event.event.handle_press([&] (Input::Keycode key, Codepoint) {
switch (key) {
case Input::KEY_ENTER:
if (ready_to_setup())
setup();
break;
case Input::KEY_TAB: select_next(); break;
default: forward_to_selected(event); break;
}
});
}
};
struct Wait_frame : Widget<Frame>
{
void view(Scope<Frame> &s) const
{
s.sub_scope<Label>(" Please wait ... ");
}
};
struct Controls_frame : Widget<Frame>
{
enum Tab { HOME, ENCRYPTION_KEY, CAPACITY, JOURNALING_BUFFER };
struct Navigation_bar : Widget<Float>
{
Controls_frame &controls;
Hosted<Float, Hbox, Back_button> back_button { Id("Back") };
Navigation_bar(Controls_frame &controls) : controls(controls) { }
void view(Scope<Float> &s, Text const &text) const
{
s.attribute("west", "yes");
s.sub_scope<Hbox>([&] (Scope<Float, Hbox> &s) {
s.widget(back_button);
s.node("float", [&] {
s.attribute("west", "yes");
s.named_sub_node("label", "label", [&] {
s.attribute("font", "title/regular");
s.attribute("text", text); }); }); });
}
void click(Clicked_at const &at) { back_button.propagate(at, [&] { controls.visible_tab = HOME; }); }
};
struct Home : Widget<Vbox>
{
Controls_frame &controls;
Hosted<Vbox, Action_button> capacity_button { Id("Capacity") };
Hosted<Vbox, Action_button> journal_buf_button { Id("Journaling Buffer") };
Hosted<Vbox, Action_button> encrypt_key_button { Id("Encryption Key") };
Home(Controls_frame &controls) : controls(controls) { }
void view(Scope<Vbox> &s) const
{
if (!controls.main.ui_report->num_clients.value)
s.widget(capacity_button);
s.widget(journal_buf_button);
s.widget(encrypt_key_button);
if (controls.main.ui_report->num_clients.value) {
s.sub_scope<Left_align>("");
s.sub_scope<Left_align>(" Capacity unchangeable when in use! ");
}
}
void click(Clicked_at const &at)
{
capacity_button.propagate(at, [&] { controls.visible_tab = CAPACITY; });
journal_buf_button.propagate(at, [&] { controls.visible_tab = JOURNALING_BUFFER; });
encrypt_key_button.propagate(at, [&] { controls.visible_tab = ENCRYPTION_KEY; });
}
void handle_event(Dialog::Event const &event)
{
event.event.handle_press([&] (Input::Keycode, Codepoint code) {
switch (code.value) {
case 'c': controls.switch_to_tab(CAPACITY); break;
case 'j': controls.switch_to_tab(JOURNALING_BUFFER); break;
case 'e': controls.switch_to_tab(ENCRYPTION_KEY); break;
default: break;
}
});
}
};
template <Ui_config::Extend::Tree TREE>
struct Dimension_tab : Widget<Vbox>
{
enum { MIN_NUM_BYTES = 4096 };
Controls_frame &controls;
Hosted<Vbox, Navigation_bar> navigation_bar { Id("Navigation Bar"), controls };
Hosted<Vbox, Size_prompt> num_bytes_prompt { Id("Number Of Bytes") };
Hosted<Vbox, Action_button> extend_button { Id("Extend") };
Dimension_tab(Controls_frame &controls) : controls(controls) { }
void view(Scope<Vbox> &s) const
{
s.widget(navigation_bar,
TREE == Ui_config::Extend::VIRTUAL_BLOCK_DEVICE ? "Capacity " :
TREE == Ui_config::Extend::FREE_TREE ? "Journaling Buffer " : "");
if (controls.main.ready_to_extend()) {
s.widget(num_bytes_prompt, true);
if (num_bytes_prompt.as_num_bytes() >= MIN_NUM_BYTES)
s.widget(extend_button);
else
s.sub_scope<Left_align>(Text(" Minimum: ", Number_of_bytes(MIN_NUM_BYTES), " "));
} else
s.sub_scope<Left_align>(" Please wait ... ");
}
void extend()
{
controls.main.extend<TREE>(*this);
num_bytes_prompt.text = "";
}
void click(Clicked_at const &at)
{
navigation_bar.propagate(at);
extend_button.propagate(at, [&] { extend(); });
}
void handle_event(Dialog::Event const &event)
{
event.event.handle_press([&] (Input::Keycode key, Codepoint) {
switch (key) {
case Input::KEY_ENTER:
if (controls.main.ready_to_extend() && num_bytes_prompt.as_num_bytes() >= MIN_NUM_BYTES)
extend();
break;
case Input::KEY_ESC: controls.switch_to_tab(HOME); break;
case Input::KEY_TAB: break;
default:
if (controls.main.ready_to_extend())
num_bytes_prompt.handle_event(event, controls.main);
break;
}
});
}
};
struct Encryption_key : Widget<Vbox>
{
Controls_frame &controls;
Hosted<Vbox, Navigation_bar> navigation_bar { Id("Navigation Bar"), controls };
Hosted<Vbox, Action_button> replace_button { Id("Replace") };
Encryption_key(Controls_frame &controls) : controls(controls) { }
void view(Scope<Vbox> &s) const
{
s.widget(navigation_bar, "Encryption Key ");
if (controls.main.ready_to_rekey())
s.widget(replace_button);
else
s.sub_scope<Left_align>(" Please wait ... ");
}
void click(Clicked_at const &at)
{
navigation_bar.propagate(at);
replace_button.propagate(at, [&] { controls.main.rekey(); });
}
void handle_event(Dialog::Event const &event)
{
event.event.handle_press([&] (Input::Keycode key, Codepoint) {
switch (key) {
case Input::KEY_ENTER:
if (controls.main.ready_to_rekey())
controls.main.rekey();
break;
case Input::KEY_ESC: controls.switch_to_tab(HOME); break;
default: break;
}
});
}
};
Main &main;
Tab visible_tab { HOME };
Hosted<Frame, Vbox, Home> home { Id("Home"), *this };
Hosted<Frame, Vbox, Dimension_tab<Ui_config::Extend::VIRTUAL_BLOCK_DEVICE> > capacity { Id("Capacity"), *this };
Hosted<Frame, Vbox, Dimension_tab<Ui_config::Extend::FREE_TREE> > journal_buf { Id("Journaling Buffer"), *this };
Hosted<Frame, Vbox, Encryption_key> encryption_key { Id("Encryption Key"), *this };
Hosted<Frame, Vbox, Action_button> lock_button { Id("Lock") };
Controls_frame(Main &main) : main(main) { }
void switch_to_tab(Tab tab)
{
visible_tab = tab;
main.main_view.refresh();
}
void view(Scope<Frame> &s) const
{
s.sub_scope<Vbox>([&] (Scope<Frame, Vbox> &s) {
switch (visible_tab) {
case HOME: s.widget(home); break;
case ENCRYPTION_KEY: s.widget(encryption_key); break;
case CAPACITY: s.widget(capacity); break;
case JOURNALING_BUFFER: s.widget(journal_buf); break;
}
s.sub_scope<Left_align>("");
s.sub_scope<Left_align>(Text(" Image: ", main.ui_report->image_size, " "));
s.sub_scope<Left_align>(Text(" Capacity: ", main.ui_report->capacity, " "));
s.sub_scope<Left_align>(Text(" Clients: ", main.ui_report->num_clients.value, " "));
s.sub_scope<Left_align>("");
s.widget(lock_button);
});
}
void lock()
{
main.lock();
visible_tab = HOME;
capacity.num_bytes_prompt.text = "";
journal_buf.num_bytes_prompt.text = "";
}
void click(Clicked_at const &at)
{
switch (visible_tab) {
case HOME: home.propagate(at); break;
case ENCRYPTION_KEY: encryption_key.propagate(at); break;
case CAPACITY: capacity.propagate(at); break;
case JOURNALING_BUFFER: journal_buf.propagate(at); break;
default: break;
}
lock_button.propagate(at, [&] { lock(); });
}
void handle_event(Dialog::Event const &event)
{
event.event.handle_press([&] (Input::Keycode, Codepoint code) {
switch (code.value) {
case 'l': lock(); break;
default:
switch (visible_tab) {
case HOME: home.handle_event(event); break;
case CAPACITY: capacity.handle_event(event); break;
case JOURNALING_BUFFER: journal_buf.handle_event(event); break;
case ENCRYPTION_KEY: encryption_key.handle_event(event); break;
}
break;
}
});
}
void handle_signal()
{
if (visible_tab == CAPACITY && main.ui_report->num_clients.value)
visible_tab = HOME;
}
};
struct Main_dialog : Top_level_dialog
{
Main &main;
Hosted<Unlock_frame> unlock_frame { Id("unlock"), main };
Hosted<Setup_frame> setup_frame { Id("setup"), main };
Hosted<Wait_frame> wait_frame { Id("wait") };
Hosted<Controls_frame> controls_frame { Id("controls"), main };
Main_dialog(Name const &name, Main &main) : Top_level_dialog(name), main(main) { }
void handle_event(Dialog::Event const &event)
{
switch (main.active_dialog) {
case SETUP: setup_frame.handle_event(event); break;
case UNLOCK: unlock_frame.handle_event(event); break;
case CONTROLS: controls_frame.handle_event(event); break;
default: break;
}
}
void handle_signal()
{
if (main.active_dialog == CONTROLS)
controls_frame.handle_signal();
}
void view(Scope<> &s) const override
{
switch (main.active_dialog) {
case UNLOCK: s.widget(unlock_frame); break;
case SETUP: s.widget(setup_frame); break;
case WAIT: s.widget(wait_frame); break;
case CONTROLS: s.widget(controls_frame); break;
case NONE: s.node("empty", [&] { }); break;
}
}
void click(Clicked_at const &at) override
{
switch (main.active_dialog) {
case SETUP: setup_frame.click(at); break;
case CONTROLS: controls_frame.click(at); break;
case UNLOCK: unlock_frame.click(at); break;
default: break;
}
}
};
Env &env;
Dialog_type active_dialog { NONE };
Heap heap { env.ram(), env.rm() };
Runtime runtime { env, heap };
Main_dialog main_dialog { "main", *this };
Runtime::View main_view { runtime, main_dialog };
Runtime::Event_handler<Main> event_handler { runtime, *this, &Main::handle_event };
Ui_config ui_config { };
Expanding_reporter ui_config_reporter { env, "ui_config", "ui_config" };
Attached_rom_dataspace ui_report_rom { env, "ui_report" };
Signal_handler<Main> signal_handler { env.ep(), *this, &Main::handle_signal };
Constructible<Ui_report> ui_report { };
void handle_event(Dialog::Event const &event)
{
main_dialog.handle_event(event);
}
void setup(Setup_frame const &setup_frame)
{
ui_config.client_fs_size = setup_frame.capacity.as_num_bytes();
ui_config.journaling_buf_size = setup_frame.journal_buf.as_num_bytes();
ui_config.passphrase = setup_frame.passphrase.text;
ui_config_reporter.generate([&] (Xml_generator &xml) { ui_config.generate(xml); });
}
void unlock(Unlock_frame const &unlock_frame)
{
ui_config.passphrase = unlock_frame.passphrase.text;
ui_config_reporter.generate([&] (Xml_generator &xml) { ui_config.generate(xml); });
}
void lock()
{
ui_config.passphrase = "";
ui_config_reporter.generate([&] (Xml_generator &xml) { ui_config.generate(xml); });
}
bool ready_to_extend() const
{
if (!ui_config.extend.constructed())
return true;
if (!ui_report->extend.constructed())
return false;
return ui_report->extend->id.value == ui_config.extend->id.value && ui_report->extend->finished;
}
bool ready_to_rekey() const
{
if (!ui_config.rekey.constructed())
return true;
if (!ui_report->rekey.constructed())
return false;
return ui_report->rekey->id.value == ui_config.rekey->id.value && ui_report->rekey->finished;
}
void rekey()
{
Operation_id id { ui_report->rekey.constructed() ? ui_report->rekey->id.value + 1 : 0 };
ui_config.rekey.construct(id);
ui_config_reporter.generate([&] (Xml_generator &xml) { ui_config.generate(xml); });
}
template <Ui_config::Extend::Tree TREE>
void extend(Controls_frame::Dimension_tab<TREE> const &dimension_tab)
{
Operation_id id { ui_report->extend.constructed() ? ui_report->extend->id.value + 1 : 0 };
ui_config.extend.construct(id, TREE, dimension_tab.num_bytes_prompt.as_num_bytes());
ui_config_reporter.generate([&] (Xml_generator &xml) { ui_config.generate(xml); });
}
void handle_signal()
{
ui_report_rom.update();
ui_report.construct(ui_report_rom.xml());
switch (ui_report->state) {
case Ui_report::INVALID: active_dialog = WAIT; break;
case Ui_report::UNINITIALIZED: active_dialog = SETUP; break;
case Ui_report::INITIALIZING: active_dialog = WAIT; break;
case Ui_report::UNLOCKING: active_dialog = WAIT; break;
case Ui_report::UNLOCKED: active_dialog = CONTROLS; break;
case Ui_report::LOCKING: active_dialog = WAIT; break;
case Ui_report::LOCKED: active_dialog = UNLOCK; break;
}
main_dialog.handle_signal();
main_view.refresh();
}
Main(Env &env) : env(env)
{
ui_report_rom.sigh(signal_handler);
handle_signal();
}
void refresh_prompt() override { main_view.refresh(); }
};
void Component::construct(Genode::Env &env) { static Main main(env); }

View File

@ -0,0 +1,6 @@
TARGET = file_vault_gui
SRC_CC = main.cc
LIBS += base dialog
INC_DIR += $(call select_from_repositories,/src/app/file_vault/include)
INC_DIR += $(call select_from_repositories,/src/lib/tresor/include)