VHD Encryption
This page is for general data on encrypted VHDs. I'm starting out with simple things like how to manually create an encrypted VHD, how to load one directly using blktap2
and tap-ctl
and whatever else comes to mind. Feel free to add relevant content.
Supported Algorithms
To create an encrypted VHD we've extended vhd-util
with the key
command. It's pretty simple to use but first things first: we need an encryption key. We support what is typically referred to as AES-XTS-PLAIN. That means that AES is the encryption, XTS is the 'mode' for the AES algorithm, and PLAIN refers to the method by which initialization vectors are created. Since VHDs have a 2TB limit we use plain instead of plain64.
Keys
Further we support either AES 128 or 256. blktap2
selects the algorithm on start-up based on the size of the key used. One of the fun things about AES is that the key size needs to be twice that of the number associated with the algorithm. So for AES 256 you'll need a 512 bit key. So since the dd
command operates in bytes we need either a key 32 or 64 bytes in size.
Let's assume our VHD is going to be called 'crypt.vhd
'. From a shell in dom0:
$ dd if=/dev/urandom of=/config/platform-crypto-keys/crypt,aes-xts-plain,512.key bs=64 count=1
In this example I made a 512 bit key by reading 64 bytes from /dev/urandom
. This key will cause blktap2
to use AES 256. If you want to use AES 128 read 32 bytes and substtitue 256 for 512 in the file name for the key. This format of this file name is significant so don't mess it up.
Create an Encrypted VHD
To create an encrypted VHD you only need to associate a key with the VHD and blktap2
will do the rest. So first things first we need to create a VHD. Let's make a 512MB VHD and call it 'crypt.vhd
'. We'll put it in /storage/disks
for good form:
$ vhd-util create -n /storage/disks/crypt.vhd -s 512
Now we take the key we created in the the previous section and associate it with the VHD. We'll start out with the easy way:
$ vhd-util key -s -n /storage/disks/crypt.vhd -k /config/platform-crypto-keys/crypt,aes-xts-plain,512.key
The command above takes the sha256
hash of the key and stores this hash in the VHD header. This allows blktap2
be sure it's using the right key when loading an encrypted VHD. Additionally we can use what vhd-util
calls a nonce
. This is really called a 'salt
' in all the literature. Your salt should be the same size as the output of the hash function so for sha256
it should be 32 bytes. Using a salt is left as an exercise for the interested reader. Take a look at the help output by vhd-util key
for other possibilities.
Note: TODO
Mount an Encrypted VHD in dom0
There are a few command sequences you can go through to accomplish this. We'll start with the simple approach and then go into a more complicated approach that's useful if you're debugging blktap2
.
The Easy Way
There are a number of steps required to get blktap2
to set everything up and give us a device node in /dev/xen/blktap-2
that's attached to our VHD. There's a command that wraps all of these into a single step for ease of use and we'll start there:
$ tap-ctl create -a vhd:/storage/disks/crypt.vhd
Check your return status and you'll probably get a '126
'. Look in /var/log/messages
and you'll see that blktap2
requires that the environment variable 'TAPDISK2_CRYPTO_KEYDIR
' be set to the directory where it should look for key files. So export this and the above command should work as expected but this time it will output the path to the device node that's been created for our VHD. You can partition this / make filesystems on it / mount and interact with it like any other block device.
The Hard Way
Say you're debugging some stuff in the tapdisk
daemon and you've added some test code that dumps a bunch of stuff to the terminal to help you trace through some code path. The Easy Way shown above causes tapdisk2
to daemonize itself and run in the background so you won't be able to see any of your output. Alternatively you can manually kick off your tapdisk2
process keeping it in the foreground and attached to the console:
TAPDISK2_CRYPTO_KEYDIR=/config/platform-crypto-keys tapdisk2 -D
Now you'll get your output but you can no longer use the shortcut tap-ctl create
command. Instead we need to manually walk through the steps that are wrapped by tap-ctl create
in a new shell. The command above will output the PID of the tapdisk2
process we've started and we'll just call this PID
from here on. Scripting this would look like so:
$ MINOR=$(tap-ctl allocate | sed -e 's&^\/dev\/xen\/blktap-2\/tapdev\([0-9]\+\)$&\1') $ tap-ctl attach -p ${PID} -m ${MINOR} $ tap-ctl open -p ${PID} -m ${MINOR} -a vhd:/storage/disks/crypto.vhd
First we allocate a device node that initially will have no storage backing it. The allocate
command will output the path to the device node and we run that through sed to get the minor device number. Next we attach the tapdisk2
process we started on the other terminal to this device node with the attach
command. Then we tell that tapdisk2
daemon to open our VHD and associate it with the same device that we just attached it to with the open
command.
Once you're done with your debugging you can run the inverse of these commands in the reverse order: close
, detach
and deallocate
. Once you detach
your tapdisk2
daemon from the device node it will shutdown so fair warning.
This approach gives us the most flexibility but really isn't necessary unless you're gonna be debugging tapdisk2
.