xref: /openbmc/qemu/docs/devel/luks-detached-header.rst (revision 9726687f2fdfe7ae4a3014d78c2b2f639f75e303)
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