On Tue, Dec 5, 2023 at 1:44 AM Daniel P. Berrangé <berra...@redhat.com> wrote:
> On Tue, Dec 05, 2023 at 01:32:51AM +0800, Yong Huang wrote: > > On Tue, Dec 5, 2023 at 12:51 AM Daniel P. Berrangé <berra...@redhat.com> > > wrote: > > > > > On Tue, Dec 05, 2023 at 12:41:16AM +0800, Yong Huang wrote: > > > > On Tue, Dec 5, 2023 at 12:24 AM Daniel P. Berrangé < > berra...@redhat.com> > > > > wrote: > > > > > > > > > On Tue, Dec 05, 2023 at 12:06:17AM +0800, Hyman Huang wrote: > > > > > > This functionality was motivated by the following to-do list seen > > > > > > in crypto documents: > > > > > > https://wiki.qemu.org/Features/Block/Crypto > > > > > > > > > > > > The last chapter says we should "separate header volume": > > > > > > > > > > > > The LUKS format has ability to store the header in a separate > volume > > > > > > from the payload. We should extend the LUKS driver in QEMU to > support > > > > > > this use case. > > > > > > > > > > > > As a proof-of-concept, I've created this patchset, which I've > named > > > > > > the Gluks: generic luks. As their name suggests, they offer > > > encryption > > > > > > for any format that QEMU theoretically supports. > > > > > > > > > > I don't see the point in creating a new driver. > > > > > > > > > > I would expect detached header support to be implemented via an > > > > > optional new 'header' field in the existing driver. ie > > > > > > > > > > diff --git a/qapi/block-core.json b/qapi/block-core.json > > > > > index ca390c5700..48d1f2a974 100644 > > > > > --- a/qapi/block-core.json > > > > > +++ b/qapi/block-core.json > > > > > @@ -3352,11 +3352,15 @@ > > > > > # decryption key (since 2.6). Mandatory except when doing a > > > > > # metadata-only probe of the image. > > > > > # > > > > > +# @header: optional reference to the location of a blockdev > > > > > +# storing a detached LUKS heaer > > > > > +# > > > > > # Since: 2.9 > > > > > ## > > > > > { 'struct': 'BlockdevOptionsLUKS', > > > > > 'base': 'BlockdevOptionsGenericFormat', > > > > > - 'data': { '*key-secret': 'str' } } > > > > > + 'data': { '*key-secret': 'str', > > > > > + "*header-file': 'BlockdevRef'} } > > > > > > > > > > ## > > > > > # @BlockdevOptionsGenericCOWFormat: > > > > > @@ -4941,9 +4945,18 @@ > > > > > # > > > > > # Driver specific image creation options for LUKS. > > > > > # > > > > > -# @file: Node to create the image format on > > > > > +# @file: Node to create the image format on. Mandatory > > > > > +# unless a detached header file is specified using > > > > > +# @header. > > > > > # > > > > > -# @size: Size of the virtual disk in bytes > > > > > +# @size: Size of the virtual disk in bytes. Mandatory > > > > > +# unless a detached header file is specified using > > > > > +# @header. > > > > > +# > > > > > +# @header: optional reference to the location of a blockdev > > > > > +# storing a detached LUKS heaer. The @file option is > > > > > +# is optional when this is given, unless it is desired > > > > > +# to perform pre-allocation > > > > > # > > > > > # @preallocation: Preallocation mode for the new image (since: > 4.2) > > > > > # (default: off; allowed values: off, metadata, falloc, full) > > > > > @@ -4952,8 +4965,9 @@ > > > > > ## > > > > > { 'struct': 'BlockdevCreateOptionsLUKS', > > > > > 'base': 'QCryptoBlockCreateOptionsLUKS', > > > > > - 'data': { 'file': 'BlockdevRef', > > > > > - 'size': 'size', > > > > > + 'data': { '*file': 'BlockdevRef', > > > > > + '*size': 'size', > > > > > + '*header': 'BlockdevRef' > > > > > '*preallocation': 'PreallocMode' } } > > > > > > > > > > ## > > > > > > > > > > It ends up giving basicallly the same workflow as you outline, > > > > > without needing the new block driver > > > > > > > > > > > > > How about the design and usage, could it be simpler? Any advice? :) > > > > > > > > > > > > As you can see below, the Gluks format block layer driver's design is > > > > quite simple. > > > > > > > > virtio-blk/vhost-user-blk...(front-end device) > > > > ^ > > > > | > > > > Gluks (format-like disk node) > > > > / \ > > > > file header (blockdev reference) > > > > / \ > > > > file file (protocol node) > > > > | | > > > > disk data Luks data > > > > > > What I suggested above ends up with the exact same block driver > > > graph, unless I'm missing something. > > > > > > > I could overlook something or fail to adequately convey the goal of the > > patchset. :( > > > > Indeed, utilizing the same block driver might be effective if our only > goal > > is to divide the header volume, giving us an additional way to use Luks. > > > > While supporting encryption for any disk format that QEMU is capable of > > supporting is another feature of this patchset. This implies that we > might > > link the Luks header to other blockdev references, which might alter how > > the Luks are used and make them incompatible with it. It's not > > user-friendly in my opinion, and I'm not aware of a more elegant > solution. > > That existing LUKS driver can already be used in combination with > any QEMU block driver, and in the case of disk formats, can be used > either above or below the format, depending on whether you want to > encrypt just the image payload, or the payload and metadata ie. > > We can do > > luks -> qcow2 -> file (qcow2 header and qcow2 payload protected) > OK, I prefer this solution so that we can support any format implemented by the QEMU block driver. > > or > > qcow2 -> luks -> file (only qcow2 payload protected) > > And in the qcow2 case, we also have support for LUKS integrated natively > into the qcow2 format, which is similar to the 2nd case, with the > benefit that we're explicit that the image requires encryption. > > With regards, > Daniel > -- > |: https://berrange.com -o- > https://www.flickr.com/photos/dberrange :| > |: https://libvirt.org -o- > https://fstop138.berrange.com :| > |: https://entangle-photo.org -o- > https://www.instagram.com/dberrange :| > > Let me make a conclusion about our discussion, if i misunderstand something, point that out please: 1. To achieve the generic encryption, extending the pre-existing LUKS QEMU block driver is suggested in practice. 2. Introducing a optional field called "header-file" that store the LUKS header independently, and once "header-file" was specified, we should use it to encrypt/decrypt the blockdev node referenced by the "file" field. The blockdev tree is like: virtio-blk/vhost-user-blk...(frontend device) ^ | LUKS / \ file header-file / \ data protocol node LUKS header protocol node 3. The usage of the generic LUKS is like: Take the qcow2 as an example: 1. add a protocol blockdev node of data disk $ virsh qemu-monitor-command vm '{"execute":"blockdev-add", "arguments":{"node-name": "libvirt-1-storage", "driver": "file", "filename": "/path/to/test_disk.qcow2"}}' 2. add a protocol blockdev node of Luks header as above. $ virsh qemu-monitor-command vm '{"execute":"blockdev-add", "arguments":{"node-name": "libvirt-2-storage", "driver": "file", "filename": "/path/to/cipher.gluks" }}' 3. add the secret for decrypting the cipher stored in Gluks header as above $ virsh qemu-monitor-command vm '{"execute":"object-add", "arguments":{"qom-type": "secret", "id": "libvirt-2-storage-secret0", "data": "abc123"}}' 4. add the qcow2-drived blockdev format node: $ virsh qemu-monitor-command vm '{"execute":"blockdev-add", "arguments":{"node-name": "libvirt-1-format", "driver": "qcow2", "file": "libvirt-1-storage"}}' 5. add the luks-drived blockdev to connect the qcow2 disk with Luks header by specifying the field "header-file" $ virsh qemu-monitor-command vm '{"execute":"blockdev-add", "arguments":{"node-name": "libvirt-2-format", "driver": "luks", "file": "libvirt-1-format", "header-file": "libvirt-2-storage", "key-secret": "libvirt-2-format-secret0"}}' 6. add the device finally $ virsh qemu-monitor-command vm '{"execute":"device_add", "arguments": {"num-queues": "1", "driver": "virtio-blk-pci", "scsi": "off", "drive": "libvirt-2-format", "id": "virtio-disk2"}}' Anyway, thanks for the comments. Yong. -- Best regards