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