docs/devel/luks-detached-header.rst
This document gives an overview of the design of LUKS volume with detached header and how to use it.
The LUKS format has ability to store the header in a separate volume from the payload. We could extend the LUKS driver in QEMU to support this use case.
Normally a LUKS volume has a layout:
::
+-----------------------------------------------+
| | | |
disk | header | key material | disk payload data | | | | | +-----------------------------------------------+
With a detached LUKS header, you need 2 disks so getting:
::
+--------------------------+
disk1 | header | key material | +--------------------------+ +---------------------+ disk2 | disk payload data | +---------------------+
There are a variety of benefits to doing this:
Take the qcow2 encryption, for example. The architecture of the LUKS volume with detached header is shown in the diagram below.
There are two children of the root node: a file and a header. Data from the disk payload is stored in the file node. The LUKS header and key material are located in the header node, as previously mentioned.
::
+-----------------------------+
Root node | foo[luks] | +-----------------------------+ | | file | header | | | +---------------------+ +------------------+ Child node |payload-format[qcow2]| |header-format[raw]| +---------------------+ +------------------+ | | file | file | | | +----------------------+ +---------------------+ Child node |payload-protocol[file]| |header-protocol[file]| +----------------------+ +---------------------+ | | | | | | Host storage Host storage
Shell commandline::
-o cipher-alg=aes-256,cipher-mode=xts -o key-secret=sec0 \
-o detached-header=true test-header.img
"test-payload.img"},"header":{"filename":"test-header.img"}}'
Qemu commandline::
-object '{"qom-type":"secret","id":"libvirt-3-format-secret", \
"data":"abc123"}' \
-blockdev '{"driver":"file","filename":"/path/to/test-header.img", \
"node-name":"libvirt-1-storage"}' \
-blockdev '{"node-name":"libvirt-1-format","read-only":false, \
"driver":"raw","file":"libvirt-1-storage"}' \
-blockdev '{"driver":"file","filename":"/path/to/test-payload.qcow2", \
"node-name":"libvirt-2-storage"}' \
-blockdev '{"node-name":"libvirt-2-format","read-only":false, \
"driver":"qcow2","file":"libvirt-2-storage"}' \
-blockdev '{"node-name":"libvirt-3-format","driver":"luks", \
"file":"libvirt-2-format","header":"libvirt-1-format","key-secret": \
"libvirt-3-format-secret"}' \
-device '{"driver":"virtio-blk-pci","bus":XXX,"addr":YYY,"drive": \
"libvirt-3-format","id":"virtio-disk1"}'
object-add the secret for decrypting the cipher stored in LUKS header above::
"arguments":{"qom-type":"secret", "id":
"libvirt-4-format-secret", "data":"abc123"}}'
block-add the protocol node for LUKS header::
"arguments":{"node-name":"libvirt-1-storage", "driver":"file",
"filename": "/path/to/test-header.img" }}'
block-add the raw-drived node for LUKS header::
"arguments":{"node-name":"libvirt-1-format", "driver":"raw",
"file":"libvirt-1-storage"}}'
block-add the protocol node for disk payload image::
"arguments":{"node-name":"libvirt-2-storage", "driver":"file",
"filename":"/path/to/test-payload.qcow2"}}'
block-add the qcow2-drived format node for disk payload data::
"arguments":{"node-name":"libvirt-2-format", "driver":"qcow2",
"file":"libvirt-2-storage"}}'
block-add the luks-drived format node to link the qcow2 disk with the LUKS header by specifying the field "header"::
"arguments":{"node-name":"libvirt-3-format", "driver":"luks",
"file":"libvirt-2-format", "header":"libvirt-1-format",
"key-secret":"libvirt-2-format-secret"}}'
hot-plug the virtio-blk device finally::
"arguments": {"driver":"virtio-blk-pci",
"drive": "libvirt-3-format", "id":"virtio-disk2"}}