diff mbox series

docs/devel: Add introduction to LUKS volume with detached header

Message ID c2049499aa05758b4cf18dcec942694ed454a980.1708358310.git.yong.huang@smartx.com (mailing list archive)
State New, archived
Headers show
Series docs/devel: Add introduction to LUKS volume with detached header | expand

Commit Message

Yong Huang Feb. 19, 2024, 4:04 p.m. UTC
Signed-off-by: Hyman Huang <yong.huang@smartx.com>
---
 MAINTAINERS                         |   1 +
 docs/devel/luks-detached-header.rst | 182 ++++++++++++++++++++++++++++
 2 files changed, 183 insertions(+)
 create mode 100644 docs/devel/luks-detached-header.rst

Comments

Markus Armbruster May 6, 2024, 6:26 a.m. UTC | #1
Looks like this fell through the cracks.  Is anyone familiar with LUKS
willing to review it?

Hyman Huang <yong.huang@smartx.com> writes:

> Signed-off-by: Hyman Huang <yong.huang@smartx.com>
> ---
>  MAINTAINERS                         |   1 +
>  docs/devel/luks-detached-header.rst | 182 ++++++++++++++++++++++++++++
>  2 files changed, 183 insertions(+)
>  create mode 100644 docs/devel/luks-detached-header.rst
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a24c2b51b6..e8b03032ab 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3422,6 +3422,7 @@ Detached LUKS header
>  M: Hyman Huang <yong.huang@smartx.com>
>  S: Maintained
>  F: tests/qemu-iotests/tests/luks-detached-header
> +F: docs/devel/luks-detached-header.rst
>  
>  D-Bus
>  M: Marc-André Lureau <marcandre.lureau@redhat.com>
> diff --git a/docs/devel/luks-detached-header.rst b/docs/devel/luks-detached-header.rst
> new file mode 100644
> index 0000000000..15e9ccde1d
> --- /dev/null
> +++ b/docs/devel/luks-detached-header.rst
> @@ -0,0 +1,182 @@
> +================================
> +LUKS volume with detached header
> +================================
> +
> +Introduction
> +============
> +
> +This document gives an overview of the design of LUKS volume with detached
> +header and how to use it.
> +
> +Background
> +==========
> +
> +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:
> +
> + * Secrecy - the disk2 cannot be identified as containing LUKS
> +             volume since there's no header
> + * Control - if access to the disk1 is restricted, then even
> +             if someone has access to disk2 they can't unlock
> +             it. Might be useful if you have disks on NFS but
> +             want to restrict which host can launch a VM
> +             instance from it, by dynamically providing access
> +             to the header to a designated host
> + * Flexibility - your application data volume may be a given
> +                 size and it is inconvenient to resize it to
> +                 add encryption.You can store the LUKS header
> +                 separately and use the existing storage
> +                 volume for payload
> + * Recovery - corruption of a bit in the header may make the
> +              entire payload inaccessible. It might be
> +              convenient to take backups of the header. If
> +              your primary disk header becomes corrupt, you
> +              can unlock the data still by pointing to the
> +              backup detached header
> +
> +Architecture
> +============
> +
> +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
> +
> +Usage
> +=====
> +
> +Create a LUKS disk with a detached header using qemu-img
> +--------------------------------------------------------
> +
> +Shell commandline::
> +
> +# qemu-img create --object secret,id=sec0,data=abc123 -f luks \
> +> -o cipher-alg=aes-256,cipher-mode=xts -o key-secret=sec0 \
> +> -o detached-header=true test-header.img
> +# qemu-img create -f qcow2 test-payload.qcow2 200G
> +# qemu-img info 'json:{"driver":"luks","file":{"filename": \
> +> "test-payload.img"},"header":{"filename":"test-header.img"}}'
> +
> +Set up a VM's LUKS volume with a detached header
> +------------------------------------------------
> +
> +Qemu commandline::
> +
> +# qemu-system-x86_64 ... \
> +> -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"}'
> +
> +Add LUKS volume to a VM with a detached header
> +----------------------------------------------
> +
> +1. object-add the secret for decrypting the cipher stored in
> +   LUKS header above::
> +
> +# virsh qemu-monitor-command vm '{"execute":"object-add", \
> +> "arguments":{"qom-type":"secret", "id": \
> +> "libvirt-4-format-secret", "data":"abc123"}}'
> +
> +2. block-add the protocol node for LUKS header::
> +
> +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> +> "arguments":{"node-name":"libvirt-1-storage", "driver":"file", \
> +> "filename": "/path/to/test-header.img" }}'
> +
> +3. block-add the raw-drived node for LUKS header::
> +
> +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> +> "arguments":{"node-name":"libvirt-1-format", "driver":"raw", \
> +> "file":"libvirt-1-storage"}}'
> +
> +4. block-add the protocol node for disk payload image::
> +
> +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> +> "arguments":{"node-name":"libvirt-2-storage", "driver":"file", \
> +> "filename":"/path/to/test-payload.qcow2"}}'
> +
> +5. block-add the qcow2-drived format node for disk payload data::
> +
> +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> +> "arguments":{"node-name":"libvirt-2-format", "driver":"qcow2", \
> +> "file":"libvirt-2-storage"}}'
> +
> +6. block-add the luks-drived format node to link the qcow2 disk
> +   with the LUKS header by specifying the field "header"::
> +
> +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> +> "arguments":{"node-name":"libvirt-3-format", "driver":"luks", \
> +> "file":"libvirt-2-format", "header":"libvirt-1-format", \
> +> "key-secret":"libvirt-2-format-secret"}}'
> +
> +7. hot-plug the virtio-blk device finally::
> +
> +# virsh qemu-monitor-command vm '{"execute":"device_add", \
> +> "arguments": {"driver":"virtio-blk-pci", \
> +> "drive": "libvirt-3-format", "id":"virtio-disk2"}}
> +
> +TODO
> +====
> +
> +1. Support the shared detached LUKS header within the VM.
Yong Huang July 9, 2024, 8:18 a.m. UTC | #2
On Mon, May 6, 2024 at 2:26 PM Markus Armbruster <armbru@redhat.com> wrote:

> Looks like this fell through the cracks.  Is anyone familiar with LUKS
> willing to review it?
>
:) Ping?


>
> Hyman Huang <yong.huang@smartx.com> writes:
>
> > Signed-off-by: Hyman Huang <yong.huang@smartx.com>
> > ---
> >  MAINTAINERS                         |   1 +
> >  docs/devel/luks-detached-header.rst | 182 ++++++++++++++++++++++++++++
> >  2 files changed, 183 insertions(+)
> >  create mode 100644 docs/devel/luks-detached-header.rst
> >
> > diff --git a/MAINTAINERS b/MAINTAINERS
> > index a24c2b51b6..e8b03032ab 100644
> > --- a/MAINTAINERS
> > +++ b/MAINTAINERS
> > @@ -3422,6 +3422,7 @@ Detached LUKS header
> >  M: Hyman Huang <yong.huang@smartx.com>
> >  S: Maintained
> >  F: tests/qemu-iotests/tests/luks-detached-header
> > +F: docs/devel/luks-detached-header.rst
> >
> >  D-Bus
> >  M: Marc-André Lureau <marcandre.lureau@redhat.com>
> > diff --git a/docs/devel/luks-detached-header.rst
> b/docs/devel/luks-detached-header.rst
> > new file mode 100644
> > index 0000000000..15e9ccde1d
> > --- /dev/null
> > +++ b/docs/devel/luks-detached-header.rst
> > @@ -0,0 +1,182 @@
> > +================================
> > +LUKS volume with detached header
> > +================================
> > +
> > +Introduction
> > +============
> > +
> > +This document gives an overview of the design of LUKS volume with
> detached
> > +header and how to use it.
> > +
> > +Background
> > +==========
> > +
> > +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:
> > +
> > + * Secrecy - the disk2 cannot be identified as containing LUKS
> > +             volume since there's no header
> > + * Control - if access to the disk1 is restricted, then even
> > +             if someone has access to disk2 they can't unlock
> > +             it. Might be useful if you have disks on NFS but
> > +             want to restrict which host can launch a VM
> > +             instance from it, by dynamically providing access
> > +             to the header to a designated host
> > + * Flexibility - your application data volume may be a given
> > +                 size and it is inconvenient to resize it to
> > +                 add encryption.You can store the LUKS header
> > +                 separately and use the existing storage
> > +                 volume for payload
> > + * Recovery - corruption of a bit in the header may make the
> > +              entire payload inaccessible. It might be
> > +              convenient to take backups of the header. If
> > +              your primary disk header becomes corrupt, you
> > +              can unlock the data still by pointing to the
> > +              backup detached header
> > +
> > +Architecture
> > +============
> > +
> > +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
> > +
> > +Usage
> > +=====
> > +
> > +Create a LUKS disk with a detached header using qemu-img
> > +--------------------------------------------------------
> > +
> > +Shell commandline::
> > +
> > +# qemu-img create --object secret,id=sec0,data=abc123 -f luks \
> > +> -o cipher-alg=aes-256,cipher-mode=xts -o key-secret=sec0 \
> > +> -o detached-header=true test-header.img
> > +# qemu-img create -f qcow2 test-payload.qcow2 200G
> > +# qemu-img info 'json:{"driver":"luks","file":{"filename": \
> > +> "test-payload.img"},"header":{"filename":"test-header.img"}}'
> > +
> > +Set up a VM's LUKS volume with a detached header
> > +------------------------------------------------
> > +
> > +Qemu commandline::
> > +
> > +# qemu-system-x86_64 ... \
> > +> -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"}'
> > +
> > +Add LUKS volume to a VM with a detached header
> > +----------------------------------------------
> > +
> > +1. object-add the secret for decrypting the cipher stored in
> > +   LUKS header above::
> > +
> > +# virsh qemu-monitor-command vm '{"execute":"object-add", \
> > +> "arguments":{"qom-type":"secret", "id": \
> > +> "libvirt-4-format-secret", "data":"abc123"}}'
> > +
> > +2. block-add the protocol node for LUKS header::
> > +
> > +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> > +> "arguments":{"node-name":"libvirt-1-storage", "driver":"file", \
> > +> "filename": "/path/to/test-header.img" }}'
> > +
> > +3. block-add the raw-drived node for LUKS header::
> > +
> > +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> > +> "arguments":{"node-name":"libvirt-1-format", "driver":"raw", \
> > +> "file":"libvirt-1-storage"}}'
> > +
> > +4. block-add the protocol node for disk payload image::
> > +
> > +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> > +> "arguments":{"node-name":"libvirt-2-storage", "driver":"file", \
> > +> "filename":"/path/to/test-payload.qcow2"}}'
> > +
> > +5. block-add the qcow2-drived format node for disk payload data::
> > +
> > +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> > +> "arguments":{"node-name":"libvirt-2-format", "driver":"qcow2", \
> > +> "file":"libvirt-2-storage"}}'
> > +
> > +6. block-add the luks-drived format node to link the qcow2 disk
> > +   with the LUKS header by specifying the field "header"::
> > +
> > +# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
> > +> "arguments":{"node-name":"libvirt-3-format", "driver":"luks", \
> > +> "file":"libvirt-2-format", "header":"libvirt-1-format", \
> > +> "key-secret":"libvirt-2-format-secret"}}'
> > +
> > +7. hot-plug the virtio-blk device finally::
> > +
> > +# virsh qemu-monitor-command vm '{"execute":"device_add", \
> > +> "arguments": {"driver":"virtio-blk-pci", \
> > +> "drive": "libvirt-3-format", "id":"virtio-disk2"}}
> > +
> > +TODO
> > +====
> > +
> > +1. Support the shared detached LUKS header within the VM.
>
>
Daniel P. Berrangé July 12, 2024, 1:39 p.m. UTC | #3
On Tue, Feb 20, 2024 at 12:04:42AM +0800, Hyman Huang wrote:
> Signed-off-by: Hyman Huang <yong.huang@smartx.com>
> ---
>  MAINTAINERS                         |   1 +
>  docs/devel/luks-detached-header.rst | 182 ++++++++++++++++++++++++++++
>  2 files changed, 183 insertions(+)
>  create mode 100644 docs/devel/luks-detached-header.rst
> 
> diff --git a/MAINTAINERS b/MAINTAINERS
> index a24c2b51b6..e8b03032ab 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -3422,6 +3422,7 @@ Detached LUKS header
>  M: Hyman Huang <yong.huang@smartx.com>
>  S: Maintained
>  F: tests/qemu-iotests/tests/luks-detached-header
> +F: docs/devel/luks-detached-header.rst
>  
>  D-Bus
>  M: Marc-André Lureau <marcandre.lureau@redhat.com>
> diff --git a/docs/devel/luks-detached-header.rst b/docs/devel/luks-detached-header.rst
> new file mode 100644
> index 0000000000..15e9ccde1d
> --- /dev/null
> +++ b/docs/devel/luks-detached-header.rst

The new file neeeds adding to an index. We don't have anywhere for crypto
yet, so I'm starting a crypto section thus:

    diff --git a/docs/devel/crypto.rst b/docs/devel/crypto.rst
    new file mode 100644
    index 0000000000..39b1c910e7
    --- /dev/null
    +++ b/docs/devel/crypto.rst
    @@ -0,0 +1,10 @@
    +.. _crypto-ref:
    +
    +====================
    +Cryptography in QEMU
    +====================
    +
    +.. toctree::
    +   :maxdepth: 2
    +
    +   luks-detached-header
    diff --git a/docs/devel/index-internals.rst b/docs/devel/index-internals.rst
    index 5636e9cf1d..4ac7725d72 100644
    --- a/docs/devel/index-internals.rst
    +++ b/docs/devel/index-internals.rst
    @@ -20,3 +20,4 @@ Details about QEMU's various subsystems including how to add features to them.
        vfio-iommufd
        writing-monitor-commands
        virtio-backends
    +   crypto


> @@ -0,0 +1,182 @@
> +================================
> +LUKS volume with detached header
> +================================
> +
> +Introduction
> +============
> +
> +This document gives an overview of the design of LUKS volume with detached
> +header and how to use it.
> +
> +Background
> +==========
> +
> +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:
> +
> + * Secrecy - the disk2 cannot be identified as containing LUKS
> +             volume since there's no header
> + * Control - if access to the disk1 is restricted, then even
> +             if someone has access to disk2 they can't unlock
> +             it. Might be useful if you have disks on NFS but
> +             want to restrict which host can launch a VM
> +             instance from it, by dynamically providing access
> +             to the header to a designated host
> + * Flexibility - your application data volume may be a given
> +                 size and it is inconvenient to resize it to
> +                 add encryption.You can store the LUKS header
> +                 separately and use the existing storage
> +                 volume for payload
> + * Recovery - corruption of a bit in the header may make the
> +              entire payload inaccessible. It might be
> +              convenient to take backups of the header. If
> +              your primary disk header becomes corrupt, you
> +              can unlock the data still by pointing to the
> +              backup detached header
> +
> +Architecture
> +============
> +
> +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
> +
> +Usage
> +=====
> +
> +Create a LUKS disk with a detached header using qemu-img
> +--------------------------------------------------------
> +
> +Shell commandline::
> +
> +# qemu-img create --object secret,id=sec0,data=abc123 -f luks \
> +> -o cipher-alg=aes-256,cipher-mode=xts -o key-secret=sec0 \
> +> -o detached-header=true test-header.img
> +# qemu-img create -f qcow2 test-payload.qcow2 200G
> +# qemu-img info 'json:{"driver":"luks","file":{"filename": \
> +> "test-payload.img"},"header":{"filename":"test-header.img"}}'

This needs indentation by 2 spaces, and the ">" can be dropped.
The same for all examples that follow.

I'm going to make those changes and queue this patch, since
they're trivial.


With regards,
Daniel
diff mbox series

Patch

diff --git a/MAINTAINERS b/MAINTAINERS
index a24c2b51b6..e8b03032ab 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3422,6 +3422,7 @@  Detached LUKS header
 M: Hyman Huang <yong.huang@smartx.com>
 S: Maintained
 F: tests/qemu-iotests/tests/luks-detached-header
+F: docs/devel/luks-detached-header.rst
 
 D-Bus
 M: Marc-André Lureau <marcandre.lureau@redhat.com>
diff --git a/docs/devel/luks-detached-header.rst b/docs/devel/luks-detached-header.rst
new file mode 100644
index 0000000000..15e9ccde1d
--- /dev/null
+++ b/docs/devel/luks-detached-header.rst
@@ -0,0 +1,182 @@ 
+================================
+LUKS volume with detached header
+================================
+
+Introduction
+============
+
+This document gives an overview of the design of LUKS volume with detached
+header and how to use it.
+
+Background
+==========
+
+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:
+
+ * Secrecy - the disk2 cannot be identified as containing LUKS
+             volume since there's no header
+ * Control - if access to the disk1 is restricted, then even
+             if someone has access to disk2 they can't unlock
+             it. Might be useful if you have disks on NFS but
+             want to restrict which host can launch a VM
+             instance from it, by dynamically providing access
+             to the header to a designated host
+ * Flexibility - your application data volume may be a given
+                 size and it is inconvenient to resize it to
+                 add encryption.You can store the LUKS header
+                 separately and use the existing storage
+                 volume for payload
+ * Recovery - corruption of a bit in the header may make the
+              entire payload inaccessible. It might be
+              convenient to take backups of the header. If
+              your primary disk header becomes corrupt, you
+              can unlock the data still by pointing to the
+              backup detached header
+
+Architecture
+============
+
+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
+
+Usage
+=====
+
+Create a LUKS disk with a detached header using qemu-img
+--------------------------------------------------------
+
+Shell commandline::
+
+# qemu-img create --object secret,id=sec0,data=abc123 -f luks \
+> -o cipher-alg=aes-256,cipher-mode=xts -o key-secret=sec0 \
+> -o detached-header=true test-header.img
+# qemu-img create -f qcow2 test-payload.qcow2 200G
+# qemu-img info 'json:{"driver":"luks","file":{"filename": \
+> "test-payload.img"},"header":{"filename":"test-header.img"}}'
+
+Set up a VM's LUKS volume with a detached header
+------------------------------------------------
+
+Qemu commandline::
+
+# qemu-system-x86_64 ... \
+> -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"}'
+
+Add LUKS volume to a VM with a detached header
+----------------------------------------------
+
+1. object-add the secret for decrypting the cipher stored in
+   LUKS header above::
+
+# virsh qemu-monitor-command vm '{"execute":"object-add", \
+> "arguments":{"qom-type":"secret", "id": \
+> "libvirt-4-format-secret", "data":"abc123"}}'
+
+2. block-add the protocol node for LUKS header::
+
+# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
+> "arguments":{"node-name":"libvirt-1-storage", "driver":"file", \
+> "filename": "/path/to/test-header.img" }}'
+
+3. block-add the raw-drived node for LUKS header::
+
+# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
+> "arguments":{"node-name":"libvirt-1-format", "driver":"raw", \
+> "file":"libvirt-1-storage"}}'
+
+4. block-add the protocol node for disk payload image::
+
+# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
+> "arguments":{"node-name":"libvirt-2-storage", "driver":"file", \
+> "filename":"/path/to/test-payload.qcow2"}}'
+
+5. block-add the qcow2-drived format node for disk payload data::
+
+# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
+> "arguments":{"node-name":"libvirt-2-format", "driver":"qcow2", \
+> "file":"libvirt-2-storage"}}'
+
+6. block-add the luks-drived format node to link the qcow2 disk
+   with the LUKS header by specifying the field "header"::
+
+# virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
+> "arguments":{"node-name":"libvirt-3-format", "driver":"luks", \
+> "file":"libvirt-2-format", "header":"libvirt-1-format", \
+> "key-secret":"libvirt-2-format-secret"}}'
+
+7. hot-plug the virtio-blk device finally::
+
+# virsh qemu-monitor-command vm '{"execute":"device_add", \
+> "arguments": {"driver":"virtio-blk-pci", \
+> "drive": "libvirt-3-format", "id":"virtio-disk2"}}
+
+TODO
+====
+
+1. Support the shared detached LUKS header within the VM.