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 <key> -F ext2fs /path/to/disk_image

To use this disk image the following config snippet can be used:

! <start name="rump_cgd">
! 	<resource name="RAM" quantum="8M" />
! 	<provides><service name="Block"/></provides>
! 	<config action="configure">
! 		<params>
! 			<method>key</method>}
! 			<key>AAABAJhpB2Y2UvVjkFdlP4m44449Pi3A/uW211mkanSulJo8</key>
! 		</params>
! 	</config>
! 	<route>
! 		<service name="Block"> <child name="ahci"/> </service>
! 		<any-service> <parent/> <any-child/> </any-service>
! 	</route>
! </start>

the Block service provided by rump_cgd may be used by a file system
server in return:

! <start name="rump_fs">
! 	<resource name="RAM" quantum="16M"/>
! 	<provides><service name="File_system"/></provides>
! 	<config fs="ext2fs">
! 		<policy label="" root="/" writeable="yes"/>
! 	</config>
! 	<route>
! 		<service name="Block"> <child name="rump_cgd"/> </service>
! 		<any-service> <parent/> <any-child/> </any-service>
! 	</route>
! </start>

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.
This commit is contained in:
Josef Söntgen 2014-04-16 15:06:27 +02:00 committed by Norman Feske
parent aaf0454956
commit e777165090
12 changed files with 1044 additions and 0 deletions

View File

@ -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_ */

View File

@ -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 <rump_cgd/device.h>
/**
* 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_ */

View File

@ -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_ */

View File

@ -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))

View File

@ -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 {
<config>
<parent-provides>
<service name="ROM"/>
<service name="RAM"/>
<service name="IRQ"/>
<service name="IO_MEM"/>
<service name="IO_PORT"/>
<service name="CAP"/>
<service name="PD"/>
<service name="RM"/>
<service name="CPU"/>
<service name="LOG"/>
<service name="SIGNAL" />
</parent-provides>
<default-route>
<any-service> <parent/> <any-child/> </any-service>
</default-route>
<start name="timer">
<resource name="RAM" quantum="1M"/>
<provides><service name="Timer"/></provides>
</start>
<start name="ram_blk">
<resource name="RAM" quantum="20M"/>
<provides><service name="Block"/></provides>}
append config "
<config file=\"$disk_image\" block_size=\"512\"/>"
append config {
</start>
<start name="rump_cgd">
<resource name="RAM" quantum="8M" />
<provides><service name="Block"/></provides>
<config action="configure">
<params>
<method>key</method>}
append config "
<key>$cgd_key</key>"
append config {
</params>
</config>
<route>
<service name="Block"> <child name="ram_blk"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="rump_fs">
<resource name="RAM" quantum="16M"/>
<provides><service name="File_system"/></provides>
<config fs="ext2fs">
<policy label="" root="/" writeable="yes"/>
</config>
<route>
<service name="Block"> <child name="rump_cgd"/> </service>
<any-service> <parent/> <any-child/> </any-service>
</route>
</start>
<start name="test-libc_vfs">
<resource name="RAM" quantum="2M"/>
<config>
<libc stdout="/dev/log">
<vfs>
<dir name="dev"> <log/> </dir>
<fs/>
</vfs>
</libc>
</config>
</start>
</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 :

View File

@ -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 <base/printf.h>
#include <block_session/connection.h>
#include <block/component.h>
#include <os/packet_allocator.h>
/* 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_ */

View File

@ -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 <os/config.h>
/* repo includes */
#include <rump_cgd/cgd.h>
/* local includes */
#include "cgd.h"
/* rump includes */
extern "C" {
#include <sys/cdefs.h>
#include <sys/errno.h>
#include <fcntl.h>
#include <sys/dirent.h>
#include <sys/disklabel.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/ioctl.h>
#include <sys/reboot.h>
#include <dev/cgdvar.h>
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
}
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<unsigned char const*>(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<unsigned char*>(&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<unsigned *>(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 <params> 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);
}

View File

@ -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 <base/signal.h>
#include <os/server.h>
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_ */

View File

@ -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 <base/env.h>
#include <os/server.h>
/* 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); }
}

View File

@ -0,0 +1,3 @@
TARGET = rump_cgd
SRC_CC = cgd.cc main.cc
LIBS = rump rump_cgd server startup

View File

@ -0,0 +1,47 @@
/**
* \brief Block encryption test
* \author Josef Soentgen
* \date 2014-04-16
*/
#include <base/allocator_avl.h>
#include <block_session/connection.h>
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;
}

View File

@ -0,0 +1,3 @@
TARGET = test-blk_crypt
SRC_CC = main.cc
LIBS = base