From e777165090becc09d882032ee39bedcea8e53cc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Wed, 16 Apr 2014 15:06:27 +0200 Subject: [PATCH] dde_rump: block encryption server using cgd(4) The 'rump_cgd' server provides block level encryption for a block session by employing the 'cgd(4)' device provided by the rumpkernel. 'rump_cgd' uses a Block_session to get access to an existing block device and provides another Block_session to its clients. Each block written or read by the client is transperently encrypted or decrypted by the server. For now 'rump_cgd' may only _configure_ a 'cgd' device but is unable to generate a configuration. The used cipher is hardcoded to _aes-cbc_ with a keysize of 256 bit. Furthermore the server is able to serve one client only. To ease the usage, its interface is modelled after the interface of 'cgdconfig(8)'. As implications thereof the key must have the same format as used by 'cgdconfig'. That means the key is a base 64 encoded string in which the first 4 bytes denote the actual length of the key in bits (these 4 bytes are stored in big endian order). Preparing a raw (e.g. without partition table) encrypted Ext2 disk image is done by executing 'tool/rump': ! dd if=/dev/urandom of=/path/to/disk_image ! rump -c /path/to/disk_image # key is printed to stdout ! rump -c -k -F ext2fs /path/to/disk_image To use this disk image the following config snippet can be used: ! ! ! ! ! ! key} ! AAABAJhpB2Y2UvVjkFdlP4m44449Pi3A/uW211mkanSulJo8 ! ! ! ! ! ! ! the Block service provided by rump_cgd may be used by a file system server in return: ! ! ! ! ! ! ! ! ! ! ! Since 'tool/rump' just utilizes the rumpkernel running on the host system to do its duty there is a script called 'tool/cgdconf' that extracts the key from a 'cgdconfig(8)' generated configuration file and also is able to generade such a file from a given key. Thereby the interoperabilty between 'rump_cgd' and the general rumpkernel based tools is secured. --- repos/dde_rump/include/arm/rump_cgd/device.h | 21 + repos/dde_rump/include/rump_cgd/cgd.h | 48 ++ repos/dde_rump/include/x86/rump_cgd/device.h | 21 + repos/dde_rump/lib/mk/rump_cgd.mk | 12 + repos/dde_rump/run/rump_cgd_ext2.run | 136 +++++ .../src/server/rump_cgd/block_driver.h | 119 ++++ repos/dde_rump/src/server/rump_cgd/cgd.cc | 511 ++++++++++++++++++ repos/dde_rump/src/server/rump_cgd/cgd.h | 59 ++ repos/dde_rump/src/server/rump_cgd/main.cc | 64 +++ repos/dde_rump/src/server/rump_cgd/target.mk | 3 + repos/dde_rump/src/test/blk_crypt/main.cc | 47 ++ repos/dde_rump/src/test/blk_crypt/target.mk | 3 + 12 files changed, 1044 insertions(+) create mode 100644 repos/dde_rump/include/arm/rump_cgd/device.h create mode 100644 repos/dde_rump/include/rump_cgd/cgd.h create mode 100644 repos/dde_rump/include/x86/rump_cgd/device.h create mode 100644 repos/dde_rump/lib/mk/rump_cgd.mk create mode 100644 repos/dde_rump/run/rump_cgd_ext2.run create mode 100644 repos/dde_rump/src/server/rump_cgd/block_driver.h create mode 100644 repos/dde_rump/src/server/rump_cgd/cgd.cc create mode 100644 repos/dde_rump/src/server/rump_cgd/cgd.h create mode 100644 repos/dde_rump/src/server/rump_cgd/main.cc create mode 100644 repos/dde_rump/src/server/rump_cgd/target.mk create mode 100644 repos/dde_rump/src/test/blk_crypt/main.cc create mode 100644 repos/dde_rump/src/test/blk_crypt/target.mk diff --git a/repos/dde_rump/include/arm/rump_cgd/device.h b/repos/dde_rump/include/arm/rump_cgd/device.h new file mode 100644 index 000000000..d1d5b59d3 --- /dev/null +++ b/repos/dde_rump/include/arm/rump_cgd/device.h @@ -0,0 +1,21 @@ +/** + * \brief ARM specific definitions for RUMP cgd + * \author Josef Soentgen + * \date 2014-04-11 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ +#ifndef _INCLUDE__ARM_RUMP_CGD__DEVICE_H_ +#define _INCLUDE__ARM_RUMP_CGD__DEVICE_H_ + +/** + * Cgd raw device used within rump + */ +#define CGD_RAW_DEVICE "/dev/rcgd0c" + +#endif /* _INCLUDE__ARM_RUMP_CGD__DEVICE_H_ */ diff --git a/repos/dde_rump/include/rump_cgd/cgd.h b/repos/dde_rump/include/rump_cgd/cgd.h new file mode 100644 index 000000000..2ff099a7f --- /dev/null +++ b/repos/dde_rump/include/rump_cgd/cgd.h @@ -0,0 +1,48 @@ +/** + * \brief Definitions for RUMP cgd + * \author Josef Soentgen + * \date 2014-04-11 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ +#ifndef _INCLUDE__RUMP_CGD__CGD_H_ +#define _INCLUDE__RUMP_CGD__CGD_H_ + +#include + +/** + * File to upon the back-end will open a block session + */ +#define GENODE_BLOCK_SESSION "block_session" + +/** + * Device to create within rump + */ +#define GENODE_DEVICE "/genode" + +/** + * Encryption algorithm used by cgd + */ +#define CGD_ALGORITHM "aes-cbc" + +/** + * Initialization vector method used by cgd + */ +#define CGD_IVMETHOD "encblkno1" + +/** + * Key length in bits + */ +#define CGD_KEYLEN 256 + +/** + * Sync I/O back-end with underlying Genode subsystems + */ +void rump_io_backend_sync(); + +#endif /* _INCLUDE__RUMP_CGD__CGD_H_ */ diff --git a/repos/dde_rump/include/x86/rump_cgd/device.h b/repos/dde_rump/include/x86/rump_cgd/device.h new file mode 100644 index 000000000..a0ba8b19a --- /dev/null +++ b/repos/dde_rump/include/x86/rump_cgd/device.h @@ -0,0 +1,21 @@ +/** + * \brief x86 specific definitions for RUMP cgd + * \author Josef Soentgen + * \date 2014-04-11 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ +#ifndef _INCLUDE__X86_RUMP_CGD__DEVICE_H_ +#define _INCLUDE__X86_RUMP_CGD__DEVICE_H_ + +/** + * Cgd raw device used within rump + */ +#define CGD_RAW_DEVICE "/dev/rcgd0d" + +#endif /* _INCLUDE__X86_RUMP_CGD__DEVICE_H_ */ diff --git a/repos/dde_rump/lib/mk/rump_cgd.mk b/repos/dde_rump/lib/mk/rump_cgd.mk new file mode 100644 index 000000000..05a636ddf --- /dev/null +++ b/repos/dde_rump/lib/mk/rump_cgd.mk @@ -0,0 +1,12 @@ +include $(REP_DIR)/lib/mk/rump.inc + +LIBS += rump + +RUMP_LIBS = librumpdev.a \ + librumpdev_cgd.a \ + librumpdev_disk.a \ + librumpdev_rnd.a \ + librumpkern_crypto.a \ + librumpvfs.a + +ARCHIVE += $(addprefix $(RUMP_LIB)/,$(RUMP_LIBS)) diff --git a/repos/dde_rump/run/rump_cgd_ext2.run b/repos/dde_rump/run/rump_cgd_ext2.run new file mode 100644 index 000000000..071bad8b0 --- /dev/null +++ b/repos/dde_rump/run/rump_cgd_ext2.run @@ -0,0 +1,136 @@ +# +# Check used commands +# +set dd [check_installed dd] + +# +# Build +# +set build_components { + core init + drivers/timer + server/ram_blk + server/rump_cgd + server/rump_fs + test/libc_vfs +} + +build $build_components + +# +# Prepare image +# +set disk_image "cgd.raw" + +puts "preparing bin/$disk_image..." + +if {![file exists $disk_image]} { + catch { exec $dd if=/dev/zero of=bin/$disk_image bs=1M count=16 } +} + +set cgd_key [exec [genode_dir]/tool/rump -c bin/$disk_image] + +if {[catch { exec [genode_dir]/tool/rump -c -d "/dev/rcgd0a" -f -F ext2fs -k "$cgd_key" bin/$disk_image }]} { + puts stderr "could not format crypto device." + exit 1 +} + +create_boot_directory + +# +# Generate config +# +append config { + + + + + + + + + + + + + + + + + + + + + + + + } +append config " + " +append config { + + + + + + + key} +append config " + $cgd_key" +append config { + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +} + +install_config $config + +# +# Boot modules +# + +# generic modules +set boot_modules { + core init timer ram_blk rump_cgd rump_fs test-libc_vfs + ld.lib.so libc.lib.so + rump.lib.so rump_cgd.lib.so rump_fs.lib.so +} + +append boot_modules "$disk_image" + +build_boot_image $boot_modules + +append qemu_args " -m 256 -nographic" + +run_genode_until {.*child exited with exit value 0.*} 60 + +exec rm -f bin/$disk_image +puts "\nTest succeeded\n" + +# vi: set ft=tcl : diff --git a/repos/dde_rump/src/server/rump_cgd/block_driver.h b/repos/dde_rump/src/server/rump_cgd/block_driver.h new file mode 100644 index 000000000..519b0ed05 --- /dev/null +++ b/repos/dde_rump/src/server/rump_cgd/block_driver.h @@ -0,0 +1,119 @@ +/* + * \brief Block driver + * \author Josef Söntgen + * \date 2014-04-16 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _BLOCK_DRIVER_H_ +#define _BLOCK_DRIVER_H_ + +/* General includes */ +#include +#include +#include +#include + +/* local includes */ +#include "cgd.h" + + +class Driver : public Block::Driver +{ + private: + + Block::Session::Operations _ops; + Genode::size_t _blk_sz; + Block::sector_t _blk_cnt; + + Cgd::Device *_cgd_device; + + + public: + + Driver(Server::Entrypoint &ep) + : + _blk_sz(0), _blk_cnt(0), _cgd_device(0) + { + try { + _cgd_device = Cgd::init(Genode::env()->heap(), ep); + } catch (...) { + PERR("could not initialize cgd device."); + throw Genode::Root::Unavailable(); + } + + _blk_cnt = _cgd_device->block_count(); + _blk_sz = _cgd_device->block_size(); + + /* + * XXX We need write access to satisfy RUMP but we have to check + * the client policy in the session interface. + */ + _ops.set_operation(Block::Packet_descriptor::READ); + _ops.set_operation(Block::Packet_descriptor::WRITE); + } + + ~Driver() + { + Cgd::deinit(Genode::env()->heap(), _cgd_device); + } + + bool _range_valid(Block::sector_t num, Genode::size_t count) + { + if (num + count > _blk_cnt) { + PERR("requested block %llu-%llu out of range!", num, num + count); + return false; + } + + return true; + } + + + /**************************** + ** Block-driver interface ** + ****************************/ + + Genode::size_t block_size() { return _blk_sz; } + Block::sector_t block_count() { return _blk_cnt; } + Block::Session::Operations ops() { return _ops; } + + void read(Block::sector_t block_number, + Genode::size_t block_count, + char* buffer, + Block::Packet_descriptor &packet) + { + if (!_ops.supported(Block::Packet_descriptor::READ)) + throw Io_error(); + + if(!_range_valid(block_number, block_count)) + throw Io_error(); + + _cgd_device->read(buffer, block_count * _blk_sz, block_number * _blk_sz); + ack_packet(packet); + } + + void write(Block::sector_t block_number, + Genode::size_t block_count, + const char * buffer, + Block::Packet_descriptor &packet) + { + if (!_ops.supported(Block::Packet_descriptor::WRITE)) + throw Io_error(); + + if(!_range_valid(block_number, block_count)) + throw Io_error(); + + _cgd_device->write(buffer, block_count * _blk_sz, block_number * _blk_sz); + ack_packet(packet); + } + + void sync() { } +}; + +#endif /* _BLOCK_DRIVER_H_ */ diff --git a/repos/dde_rump/src/server/rump_cgd/cgd.cc b/repos/dde_rump/src/server/rump_cgd/cgd.cc new file mode 100644 index 000000000..928f00c7e --- /dev/null +++ b/repos/dde_rump/src/server/rump_cgd/cgd.cc @@ -0,0 +1,511 @@ +/** + * \brief RUMP cgd + * \author Josef Soentgen + * \date 2014-04-11 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include + +/* repo includes */ +#include + +/* local includes */ +#include "cgd.h" + +/* rump includes */ +extern "C" { +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +} + + +static const bool verbose = false; +#define PDBGV(...) if (verbose) PDBG(__VA_ARGS__) + + +/** + * Miscellaneous methods used for converting the key string + */ +namespace { + + /** + * Decode base64 encoding + */ + class Base64 + { + private: + + /* initialize the lookup table */ + static constexpr const unsigned char _ascii_to_value[256] + { + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63, + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64, + 64, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, + 64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, + 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64 + }; + + + public: + + static size_t decode(char *dst, char const *src, size_t src_len) + { + unsigned char const *usrc = reinterpret_cast(src); + + size_t i; + for (i = 0; i < src_len; i += 4) { + *(dst++) = _ascii_to_value[usrc[i]] << 2 | _ascii_to_value[usrc[i + 1]] >> 4; + *(dst++) = _ascii_to_value[usrc[i + 1]] << 4 | _ascii_to_value[usrc[i + 2]] >> 2; + *(dst++) = _ascii_to_value[usrc[i + 2]] << 6 | _ascii_to_value[usrc[i + 3]]; + } + + return src_len * 3/4; + } + }; + + + /* lookup table instance */ + constexpr unsigned char Base64::_ascii_to_value[256]; + + + /** + * Convert unsigned big endian value to host endianess + */ + unsigned read_big_endian(unsigned val) + { + unsigned char *p = reinterpret_cast(&val); + + return (p[3]<<0) | (p[2]<<8) | (p[1]<<16) | (p[0]<<24); + } +} + + +/** + * cgd(4) wrapper + */ +namespace Cgd { + + struct Params + { + enum { + ALGORITHM_LEN = 16, + IVMETHOD_LEN = 16, + KEY_LEN = 64, + PASSPHRASE_LEN = 64, + SALT_LEN = 29, + }; + + char algorithm[ALGORITHM_LEN]; + char ivmethod[IVMETHOD_LEN]; + char key[KEY_LEN]; + + Genode::size_t keylen = 0; + Genode::size_t blocksize = 0; + + Params() + { + Genode::memset(algorithm, 0, sizeof(*algorithm)); + Genode::memset(ivmethod, 0, sizeof(*ivmethod)); + Genode::memset(key, 0, sizeof(*key)); + } + + static Params *generate() + { + return 0; + } + }; + + + /** + * Configuration of the cgd device + * + * cgdconfig(8) saves the key as base 64 encoded string. The first 4 bytes + * of this string are the length of the key in bits stored as big endian. + */ + class Config + { + public: + + /* same as in cgdconfig(8) */ + typedef enum { ACTION_INVALID, ACTION_CONFIGURE, ACTION_GENERATE } Action; + + + private: + + enum { ACTION_VALUE_LEN = 16, /* action attribute value length */ + ENCODED_KEY_LEN = 64, /* encoded key string buffer */ + DECODED_KEY_LEN = 36, /* decoded key string buffer */ + VALID_ENCODED_KEY_LEN = 48, /* length of 256Bit key */ + }; + + Genode::Config &_cfg; + Action _action; + Params *_params; + + /** + * Get action from config attribute + * + * \return action + */ + Action _get_action() + { + char action_val[ACTION_VALUE_LEN]; + + if (_cfg.xml_node().has_attribute("action")) + _cfg.xml_node().attribute("action").value(action_val, sizeof (action_val)); + else + return ACTION_INVALID; + + if (Genode::strcmp(action_val, "configure") == 0) + return ACTION_CONFIGURE; + if (Genode::strcmp(action_val, "generate") == 0) + return ACTION_GENERATE; + + return ACTION_INVALID; + } + + /** + * Decode key string in cgdconfig(8) format + * + * \param dst pointer to buffer to store decoded key + * \param src pointer to buffer with encoded key string + * \param src_len length of encoded key string buffer + * + * \return true if decoding was successful and false otherwise + */ + bool _decode_key_string(char *dst, char const *src, size_t src_len) + { + char dec_key[DECODED_KEY_LEN]; + + /* check that buffer is large enough */ + if (sizeof (dec_key) < (src_len*3/4)) + return false; + + (void) Base64::decode(dec_key, src, src_len); + + unsigned *p = reinterpret_cast(dec_key); + unsigned bits = read_big_endian(*p); + Genode::memcpy(dst, p + 1, bits / 8); + + return true; + } + + /** + * Parse given configuration + * + * This method throws a Genode::Exception if an error in the given + * configuration is found. + */ + void _parse_config() + { + if (_cfg.xml_node().has_sub_node("params")) { + Genode::Xml_node pnode = _cfg.xml_node().sub_node("params"); + + char method_val[4]; + pnode.sub_node("method").value(method_val, sizeof (method_val)); + bool use_key = Genode::strcmp(method_val, "key") == 0 ? true : false; + + if (!use_key) { + PERR("no valid method specified."); + throw Genode::Exception(); + } + + _params = new (Genode::env()->heap()) Params(); + + Genode::strncpy(_params->algorithm, CGD_ALGORITHM, + Params::ALGORITHM_LEN); + Genode::strncpy(_params->ivmethod, CGD_IVMETHOD, + Params::IVMETHOD_LEN); + + char enc_key[ENCODED_KEY_LEN]; + pnode.sub_node("key").value(enc_key, sizeof (enc_key)); + size_t enc_key_len = Genode::strlen(enc_key); + + if (enc_key_len != VALID_ENCODED_KEY_LEN) { + PERR("incorrect encoded key found."); + throw Genode::Exception(); + } + + if (!_decode_key_string(_params->key, enc_key, enc_key_len)) { + PERR("could not decode key string."); + throw Genode::Exception(); + } + + _params->keylen = CGD_KEYLEN; + + /* let cgd(4) figure out the right blocksize */ + _params->blocksize = -1; + } else { + PERR("no node found."); + throw Genode::Exception(); + } + } + + + public: + + Config() + : + _cfg(*Genode::config()), + _action(_get_action()), + _params(0) + { + _parse_config(); + } + + ~Config() { destroy(Genode::env()->heap(), _params); } + + Action action() { return _action; } + Params* params() { return _params; } + }; +} + + +/** + * Constructor + * + * \param fd used by the rumpkernel to execute syscalls on + */ +Cgd::Device::Device(int fd) +: + _fd(fd), + _blk_sz(0), _blk_cnt(0) +{ + /** + * We query the disklabel(5) on CGD_RAW_DEVICE to get the + * actual block size and the number of blocks in the + * first partition. Though there may be more partitions + * we always use the first one. + */ + disklabel dl; + Genode::memset(&dl, 0, sizeof (dl)); + int err = rump_sys_ioctl(_fd, DIOCGDINFO, &dl); + if (err) { + cgd_ioctl ci; + rump_sys_ioctl(_fd, CGDIOCCLR, &ci); + rump_sys_close(_fd); + + PERR("could not read geometry of '%s'", CGD_RAW_DEVICE); + throw Genode::Exception(); + } + + _blk_sz = dl.d_secsize; + _blk_cnt = dl.d_partitions[0].p_size; +} + + +/** + * Destructor + */ +Cgd::Device::~Device() +{ + /* unconfigure cgd(4) device to explicitly clean up buffers */ + cgd_ioctl ci; + rump_sys_ioctl(_fd, CGDIOCCLR, &ci); + rump_sys_close(_fd); +} + + +/** + * Get name of the actual cgd device + * + * \return name + */ +char const *Cgd::Device::name() const { return CGD_RAW_DEVICE; } + + +/** + * Read from the cgd device + * + * \param dst pointer to buffer + * \param len size of the buffer + * \param seek_offset offset from where to start reading + * + * \return bytes read + */ +size_t Cgd::Device::read(char *dst, size_t len, seek_off_t seek_offset) +{ + ssize_t ret = rump_sys_pread(_fd, dst, len, seek_offset); + + return ret == -1 ? 0 : ret; +} + + +/** + * Write to cgd device + * + * \param src pointer to buffer + * \param len size of the buffer + * \param seek_offset offset from where to start writing + * + * \return bytes written + */ +size_t Cgd::Device::write(char const *src, size_t len, seek_off_t seek_offset) +{ + /* should we append? */ + if (seek_offset == ~0ULL) { + off_t off = rump_sys_lseek(_fd, 0, SEEK_END); + if (off == -1) + return 0; + seek_offset = off; + } + + ssize_t ret = rump_sys_pwrite(_fd, src, len, seek_offset); + return ret == -1 ? 0 : ret; +} + + +/** + * Configure the actual cgd device + * + * \param alloc memory allocator for metadata + * \param p pointer to parameters + * \param dev name of the block device used as backing device for cgd + * + * \return configured cgd device + */ +Cgd::Device *Cgd::Device::configure(Genode::Allocator *alloc, Cgd::Params const *p, + char const *dev) +{ + int fd = rump_sys_open(CGD_RAW_DEVICE, O_RDWR); + if (fd == -1) { + PERR("could not open '%s'", CGD_RAW_DEVICE); + throw Genode::Exception(); + } + + PDBGV("dev: '%s' alg: '%s' ivmethod: '%s' blocksize: %zu keylen: %zu", + dev, p->algorithm, p->ivmethod, p->blocksize, p->keylen); + + /* perform configuration of cgd device */ + cgd_ioctl ci; + Genode::memset(&ci, 0, sizeof (ci)); + + ci.ci_disk = dev; + ci.ci_alg = p->algorithm; + ci.ci_ivmethod = p->ivmethod; + ci.ci_key = p->key; + ci.ci_keylen = p->keylen; + ci.ci_blocksize = p->blocksize; + + int err = rump_sys_ioctl(fd, CGDIOCSET, &ci); + if (err == -1) { + rump_sys_close(fd); + + PERR("could not configure '%s'", CGD_RAW_DEVICE); + throw Genode::Exception(); + } + + cgd_user cu; + Genode::memset(&cu, 0, sizeof (cu)); + + err = rump_sys_ioctl(fd, CGDIOCGET, &cu); + if (err == -1) { /* unlikely */ + + /** + * Reuse former cgd_ioctl struct because it is not used by this + * ioctl() anyway. + */ + rump_sys_ioctl(fd, CGDIOCCLR, &ci); + rump_sys_close(fd); + + PERR("could not get cgd information."); + throw Genode::Exception(); + } + + Cgd::Device *cgd = new (alloc) Cgd::Device(fd); + + return cgd; +} + + +/** + * Initialize a new Cgd::Device + */ +Cgd::Device *Cgd::init(Genode::Allocator *alloc, Server::Entrypoint &ep) +{ + /* start rumpkernel */ + rump_init(); + + /* register block device */ + if (rump_pub_etfs_register(GENODE_DEVICE, GENODE_BLOCK_SESSION, + RUMP_ETFS_BLK)) { + PERR("could not register '%s' within rumpkernel", GENODE_DEVICE); + throw Genode::Exception(); + } + + Cgd::Config cfg; + + Cgd::Config::Action action = cfg.action(); + + Cgd::Device *cgd_dev = 0; + + switch (action) { + case Cgd::Config::ACTION_CONFIGURE: + { + Cgd::Params *p = cfg.params(); + if (!p) + throw Genode::Exception(); + + cgd_dev = Cgd::Device::configure(alloc, p, GENODE_DEVICE); + + break; + } + case Cgd::Config::ACTION_GENERATE: + { + Cgd::Params *params = Cgd::Params::generate(); + (void)params; + + break; + } + case Cgd::Config::ACTION_INVALID: + PERR("invalid action declared"); + throw Genode::Exception(); + break; + } + + PINF("exporting '%s' as Block_session", cgd_dev->name()); + + return cgd_dev; +} + + +/** + * Deinitialize a Cgd::Device + */ +void Cgd::deinit(Genode::Allocator *alloc, Cgd::Device *dev) +{ + destroy(alloc, dev); + + /* halt rumpkernel */ + rump_sys_reboot(RB_HALT, 0); +} diff --git a/repos/dde_rump/src/server/rump_cgd/cgd.h b/repos/dde_rump/src/server/rump_cgd/cgd.h new file mode 100644 index 000000000..4dca19609 --- /dev/null +++ b/repos/dde_rump/src/server/rump_cgd/cgd.h @@ -0,0 +1,59 @@ +/** + * \brief Rump cgd header + * \author Josef Soentgen + * \date 2014-04-11 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +#ifndef _CGD_H_ +#define _CGD_H_ + +#include +#include + +namespace Cgd { + + typedef Genode::uint64_t seek_off_t; + + class Params; + + class Device + { + private: + + int _fd; /* fd for cgd (raw) device */ + Genode::size_t _blk_sz; /* block size of cgd device */ + Genode::uint64_t _blk_cnt; /* block count of cgd device */ + + + public: + + Device(int fd); + + ~Device(); + + char const *name() const; + + Genode::size_t block_size() const { return _blk_sz; } + + Genode::uint64_t block_count() const { return _blk_cnt; } + + Genode::size_t read(char *dst, Genode::size_t len, seek_off_t seek_offset); + + Genode::size_t write(char const *src, Genode::size_t len, seek_off_t seek_offset); + + static Device *configure(Genode::Allocator *alloc, Params const *p, char const *dev); + }; + + + Device *init(Genode::Allocator *alloc, Server::Entrypoint &ep); + void deinit(Genode::Allocator *alloc, Device *dev); +} + +#endif /* _CGD_H_ */ diff --git a/repos/dde_rump/src/server/rump_cgd/main.cc b/repos/dde_rump/src/server/rump_cgd/main.cc new file mode 100644 index 000000000..1b963800e --- /dev/null +++ b/repos/dde_rump/src/server/rump_cgd/main.cc @@ -0,0 +1,64 @@ +/** + * \brief Block device encryption via cgd + * \author Josef Soentgen + * \date 2014-04-11 + */ + +/* + * Copyright (C) 2014 Genode Labs GmbH + * + * This file is part of the Genode OS framework, which is distributed + * under the terms of the GNU General Public License version 2. + */ + +/* Genode includes */ +#include +#include + +/* local includes */ +#include "block_driver.h" +#include "cgd.h" + + +struct Main +{ + Server::Entrypoint &ep; + + struct Factory : Block::Driver_factory + { + Server::Entrypoint &ep; + + Factory(Server::Entrypoint &ep) : ep(ep) { } + + Block::Driver *create() + { + return new (Genode::env()->heap()) Driver(ep); + } + + void destroy(Block::Driver *driver) + { + Genode::destroy(Genode::env()->heap(), driver); + } + + } factory; + + Block::Root root; + + Main(Server::Entrypoint &ep) + : + ep(ep), factory(ep), root(ep, Genode::env()->heap(), factory) + { + Genode::env()->parent()->announce(ep.manage(root)); + } +}; + + +/********************** + ** Server framework ** + **********************/ + +namespace Server { + char const *name() { return "rump_cgd_ep"; } + size_t stack_size() { return 4 * 1024 * sizeof(long); } + void construct(Entrypoint &ep) { static Main inst(ep); } +} diff --git a/repos/dde_rump/src/server/rump_cgd/target.mk b/repos/dde_rump/src/server/rump_cgd/target.mk new file mode 100644 index 000000000..390129156 --- /dev/null +++ b/repos/dde_rump/src/server/rump_cgd/target.mk @@ -0,0 +1,3 @@ +TARGET = rump_cgd +SRC_CC = cgd.cc main.cc +LIBS = rump rump_cgd server startup diff --git a/repos/dde_rump/src/test/blk_crypt/main.cc b/repos/dde_rump/src/test/blk_crypt/main.cc new file mode 100644 index 000000000..3c157eb65 --- /dev/null +++ b/repos/dde_rump/src/test/blk_crypt/main.cc @@ -0,0 +1,47 @@ +/** + * \brief Block encryption test + * \author Josef Soentgen + * \date 2014-04-16 + */ + +#include +#include + +int main(int argc, char *argv[]) +{ + try { + char buffer[512]; + Block::Session::Operations blk_ops; + Genode::size_t blk_sz; + Block::sector_t blk_cnt; + + Genode::Allocator_avl alloc(Genode::env()->heap()); + Block::Connection blk(&alloc); + blk.info(&blk_cnt, &blk_sz, &blk_ops); + + PINF("block device with block size %zd sector count %lld", + blk_sz, blk_cnt); + PLOG("read first block"); + + Block::Packet_descriptor p(blk.tx()->alloc_packet(blk_sz), + Block::Packet_descriptor::READ, 0, 1); + blk.tx()->submit_packet(p); + p = blk.tx()->get_acked_packet(); + + if (!p.succeeded()) { + PERR("could not read first block"); + blk.tx()->release_packet(p); + return 1; + } + + Genode::memcpy(buffer, blk.tx()->packet_content(p), blk_sz); + + /* XXX compare content */ + /* PERR("block content: '%s'", buffer); */ + } catch(Genode::Parent::Service_denied) { + PERR("Opening block session was denied!"); + return -1; + } + + return 0; +} diff --git a/repos/dde_rump/src/test/blk_crypt/target.mk b/repos/dde_rump/src/test/blk_crypt/target.mk new file mode 100644 index 000000000..f92ae8912 --- /dev/null +++ b/repos/dde_rump/src/test/blk_crypt/target.mk @@ -0,0 +1,3 @@ +TARGET = test-blk_crypt +SRC_CC = main.cc +LIBS = base