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