1================================
2LUKS volume with detached header
3================================
4
5Introduction
6============
7
8This document gives an overview of the design of LUKS volume with detached
9header and how to use it.
10
11Background
12==========
13
14The LUKS format has ability to store the header in a separate volume from
15the payload. We could extend the LUKS driver in QEMU to support this use
16case.
17
18Normally a LUKS volume has a layout:
19
20::
21
22         +-----------------------------------------------+
23         |         |                |                    |
24 disk    | header  |  key material  |  disk payload data |
25         |         |                |                    |
26         +-----------------------------------------------+
27
28With a detached LUKS header, you need 2 disks so getting:
29
30::
31
32         +--------------------------+
33 disk1   |   header  | key material |
34         +--------------------------+
35         +---------------------+
36 disk2   |  disk payload data  |
37         +---------------------+
38
39There are a variety of benefits to doing this:
40
41 * Secrecy - the disk2 cannot be identified as containing LUKS
42             volume since there's no header
43 * Control - if access to the disk1 is restricted, then even
44             if someone has access to disk2 they can't unlock
45             it. Might be useful if you have disks on NFS but
46             want to restrict which host can launch a VM
47             instance from it, by dynamically providing access
48             to the header to a designated host
49 * Flexibility - your application data volume may be a given
50                 size and it is inconvenient to resize it to
51                 add encryption.You can store the LUKS header
52                 separately and use the existing storage
53                 volume for payload
54 * Recovery - corruption of a bit in the header may make the
55              entire payload inaccessible. It might be
56              convenient to take backups of the header. If
57              your primary disk header becomes corrupt, you
58              can unlock the data still by pointing to the
59              backup detached header
60
61Architecture
62============
63
64Take the qcow2 encryption, for example. The architecture of the
65LUKS volume with detached header is shown in the diagram below.
66
67There are two children of the root node: a file and a header.
68Data from the disk payload is stored in the file node. The
69LUKS header and key material are located in the header node,
70as previously mentioned.
71
72::
73
74                       +-----------------------------+
75  Root node            |          foo[luks]          |
76                       +-----------------------------+
77                          |                       |
78                     file |                header |
79                          |                       |
80               +---------------------+    +------------------+
81  Child node   |payload-format[qcow2]|    |header-format[raw]|
82               +---------------------+    +------------------+
83                          |                       |
84                     file |                 file  |
85                          |                       |
86               +----------------------+  +---------------------+
87  Child node   |payload-protocol[file]|  |header-protocol[file]|
88               +----------------------+  +---------------------+
89                          |                       |
90                          |                       |
91                          |                       |
92                     Host storage            Host storage
93
94Usage
95=====
96
97Create a LUKS disk with a detached header using qemu-img
98--------------------------------------------------------
99
100Shell commandline::
101
102  # qemu-img create --object secret,id=sec0,data=abc123 -f luks \
103    -o cipher-alg=aes-256,cipher-mode=xts -o key-secret=sec0 \
104    -o detached-header=true test-header.img
105  # qemu-img create -f qcow2 test-payload.qcow2 200G
106  # qemu-img info 'json:{"driver":"luks","file":{"filename": \
107    "test-payload.img"},"header":{"filename":"test-header.img"}}'
108
109Set up a VM's LUKS volume with a detached header
110------------------------------------------------
111
112Qemu commandline::
113
114  # qemu-system-x86_64 ... \
115    -object '{"qom-type":"secret","id":"libvirt-3-format-secret", \
116    "data":"abc123"}' \
117    -blockdev '{"driver":"file","filename":"/path/to/test-header.img", \
118    "node-name":"libvirt-1-storage"}' \
119    -blockdev '{"node-name":"libvirt-1-format","read-only":false, \
120    "driver":"raw","file":"libvirt-1-storage"}' \
121    -blockdev '{"driver":"file","filename":"/path/to/test-payload.qcow2", \
122    "node-name":"libvirt-2-storage"}' \
123    -blockdev '{"node-name":"libvirt-2-format","read-only":false, \
124    "driver":"qcow2","file":"libvirt-2-storage"}' \
125    -blockdev '{"node-name":"libvirt-3-format","driver":"luks", \
126    "file":"libvirt-2-format","header":"libvirt-1-format","key-secret": \
127    "libvirt-3-format-secret"}' \
128    -device '{"driver":"virtio-blk-pci","bus":XXX,"addr":YYY,"drive": \
129    "libvirt-3-format","id":"virtio-disk1"}'
130
131Add LUKS volume to a VM with a detached header
132----------------------------------------------
133
1341. object-add the secret for decrypting the cipher stored in
135   LUKS header above::
136
137    # virsh qemu-monitor-command vm '{"execute":"object-add", \
138      "arguments":{"qom-type":"secret", "id": \
139      "libvirt-4-format-secret", "data":"abc123"}}'
140
1412. block-add the protocol node for LUKS header::
142
143    # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
144      "arguments":{"node-name":"libvirt-1-storage", "driver":"file", \
145      "filename": "/path/to/test-header.img" }}'
146
1473. block-add the raw-drived node for LUKS header::
148
149    # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
150      "arguments":{"node-name":"libvirt-1-format", "driver":"raw", \
151      "file":"libvirt-1-storage"}}'
152
1534. block-add the protocol node for disk payload image::
154
155    # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
156      "arguments":{"node-name":"libvirt-2-storage", "driver":"file", \
157      "filename":"/path/to/test-payload.qcow2"}}'
158
1595. block-add the qcow2-drived format node for disk payload data::
160
161    # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
162      "arguments":{"node-name":"libvirt-2-format", "driver":"qcow2", \
163      "file":"libvirt-2-storage"}}'
164
1656. block-add the luks-drived format node to link the qcow2 disk
166   with the LUKS header by specifying the field "header"::
167
168    # virsh qemu-monitor-command vm '{"execute":"blockdev-add", \
169      "arguments":{"node-name":"libvirt-3-format", "driver":"luks", \
170      "file":"libvirt-2-format", "header":"libvirt-1-format", \
171      "key-secret":"libvirt-2-format-secret"}}'
172
1737. hot-plug the virtio-blk device finally::
174
175    # virsh qemu-monitor-command vm '{"execute":"device_add", \
176      "arguments": {"driver":"virtio-blk-pci", \
177      "drive": "libvirt-3-format", "id":"virtio-disk2"}}
178
179TODO
180====
181
1821. Support the shared detached LUKS header within the VM.
183