[libvirt] TPM support in libvirt

Hello! I'd like to start a discussion and get some feedback on support for TPM (Trusted Platform Module) management in libvirt. I have been posting patches to the Qemu and SeaBIOS mailing lists that will provide the ground work for TPM support in Qemu, though I anticipate that it will take a while until the code goes into those repositories. So everything I am saying related to command lines etc. can still change. Nevertheless, the next obvious layer for support is libvirt. Well, and I do have patches... First some background: the TPM is a crypto device built into many modern laptops and desktops. It's a chip connected to the motherboard and has firmware for running the TPM specifications. I would say it has a full processor on its own to run this firmware. It also has some very limited space for persistent storage to permanently store for example the owner's password (that he can establish with the TPM), store private keys and it also has some area for NVRAM spaces where the user can put any data into it he wants to. So now, on the qemu command line the TPM support (currently) looks as follows: ... -tpm ? displays: Supported TPM types (choose only one): builtin Qemu's built-in TPM; requires 63kb of block storage I use this for reading the size of the necessary (QCoW2) blockstorage from it, 63kb. To start a VM with TPM support: ... -tpm type=builtin,path=/tmp/tpmstate.bin The above indicates the type of TPM to use. Currently there is only one type available, which is the 'builtin' one. It also provides a path to persistent storage, here /tmp/tpmstate.bin. The persistent storage file is actually a Qcow2 file so we can properly support snapshotting of the image and the TPM and go back to different states. Obviously we are now adding another 'disk' to the VM, so that the TPM can store its own persistent data. Now a user has to make sure to always keep his image file and this TPM 'disk' together, particularly once he stores vital keys in the TPM. So now for modeling this in libvirt I thought of this XML here for a user-provided Qcow2 image: <tpm type='built-in'> <storage file='/tmp/tpmstate.bin'/> </tpm> In this case the user would create the above QCoW2 /tmp/tmpstate.bin at the appropriate size (63kb). This XML here is for a libvirt-created QCoW2 image: <tpm type='built-in'> <storage/> </tpm> This then causes libvirt to create a QCoW2 image of 63kb size (reads the 63kb from .. tpm ?) once the VM is about to start and produces for example this command line: -tpm type=builtin,path=/var/lib/libvirt/tpm/a4d7cd22-da89-3094-6212-079a48a309a1.bin The UUID then corresponds to the UUID of the VM. Since only one TPM per VM is supported, this should work just fine. Now to support an encrypted QCoW2 image, the following XML could be used: <tpm type='built-in'> <storage> <encryption format='qcow'> <secret type='passphrase' uuid='13ea49f7-2553-7308-5168-e337ade36232'/> </encryption> </storage> </tpm> Here the user has created a 'secret' and passes that secret's UUID into the XML above. So this is similar to how storage is dealt with with the difference that no path to the storage is provided and also internally no comparisons for storage paths are being made. I did also not want to force the user to create storage spaces (volumes) on his own, but let libvirt handle this implicitly for the TPM (use qemu-img to create the QCoW2). Also, multiple VMs' TPMs could share the same secret. Please let me know of any comments regarding this. I'll post the patches as RFC later on. Regards, Stefan

On Thu, Mar 31, 2011 at 09:41:44AM -0400, Stefan Berger wrote:
Hello!
I'd like to start a discussion and get some feedback on support for TPM (Trusted Platform Module) management in libvirt. I have been posting patches to the Qemu and SeaBIOS mailing lists that will provide the ground work for TPM support in Qemu, though I anticipate that it will take a while until the code goes into those repositories. So everything I am saying related to command lines etc. can still change. Nevertheless, the next obvious layer for support is libvirt. Well, and I do have patches...
First some background: the TPM is a crypto device built into many modern laptops and desktops. It's a chip connected to the motherboard and has firmware for running the TPM specifications. I would say it has a full processor on its own to run this firmware. It also has some very limited space for persistent storage to permanently store for example the owner's password (that he can establish with the TPM), store private keys and it also has some area for NVRAM spaces where the user can put any data into it he wants to.
So now, on the qemu command line the TPM support (currently) looks as follows:
... -tpm ?
displays:
Supported TPM types (choose only one): builtin Qemu's built-in TPM; requires 63kb of block storage
I use this for reading the size of the necessary (QCoW2) blockstorage from it, 63kb.
To start a VM with TPM support:
... -tpm type=builtin,path=/tmp/tpmstate.bin
The above indicates the type of TPM to use. Currently there is only one type available, which is the 'builtin' one. It also provides a path to persistent storage, here /tmp/tpmstate.bin. The persistent storage file is actually a Qcow2 file so we can properly support snapshotting of the image and the TPM and go back to different states.
Obviously we are now adding another 'disk' to the VM, so that the TPM can store its own persistent data. Now a user has to make sure to always keep his image file and this TPM 'disk' together, particularly once he stores vital keys in the TPM.
So now for modeling this in libvirt I thought of this XML here for a user-provided Qcow2 image:
<tpm type='built-in'> <storage file='/tmp/tpmstate.bin'/> </tpm>
In this case the user would create the above QCoW2 /tmp/tmpstate.bin at the appropriate size (63kb).
This XML here is for a libvirt-created QCoW2 image:
<tpm type='built-in'> <storage/> </tpm>
This then causes libvirt to create a QCoW2 image of 63kb size (reads the 63kb from .. tpm ?) once the VM is about to start and produces for example this command line:
-tpm type=builtin,path=/var/lib/libvirt/tpm/a4d7cd22-da89-3094-6212-079a48a309a1.bin
The UUID then corresponds to the UUID of the VM. Since only one TPM per VM is supported, this should work just fine.
Now to support an encrypted QCoW2 image, the following XML could be used:
<tpm type='built-in'> <storage> <encryption format='qcow'> <secret type='passphrase' uuid='13ea49f7-2553-7308-5168-e337ade36232'/> </encryption> </storage> </tpm>
Here the user has created a 'secret' and passes that secret's UUID into the XML above. So this is similar to how storage is dealt with with the difference that no path to the storage is provided and also internally no comparisons for storage paths are being made. I did also not want to force the user to create storage spaces (volumes) on his own, but let libvirt handle this implicitly for the TPM (use qemu-img to create the QCoW2). Also, multiple VMs' TPMs could share the same secret.
I'm not sure I'm a fan of the idea of libvirt creating the TPM qcow2 file itself at VM startup, since that's at odds with the way we deal with other host OS resources where the app is required to create everything the VM needs upfront. Also, why QCow2 ? It seems like rather a large hammer, if all we really need is to ensure the data is encrypted on disk. Might it be better to just use a raw 64kb file and just give QEMU a decryption key to use for it. It should be trivial for QEMU to have a variant on the raw block driver which passes all data writes/reads through an encrypt/decrypt API. QCow2 is not exactly everyone's favourite bit of QEMU code, being rather complex and unreliable at times.
Please let me know of any comments regarding this.
My other main thought is how does the Xen TPM model fit in ? That has been around for quite a while, but not supported in libvirt. If we add TPM to libvirt we need to make sure the way we model it works for Xen too. Not sure if anyone else like VMWare/VirtualBox does any TPM stuff yet. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On Thu, Mar 31, 2011 at 09:41:44AM -0400, Stefan Berger wrote:
<tpm type='built-in'> <storage> <encryption format='qcow'> <secret type='passphrase' uuid='13ea49f7-2553-7308-5168-e337ade36232'/> </encryption> </storage> </tpm>
Here the user has created a 'secret' and passes that secret's UUID into the XML above. So this is similar to how storage is dealt with with the difference that no path to the storage is provided and also internally no comparisons for storage paths are being made. I did also not want to force the user to create storage spaces (volumes) on his own, but let libvirt handle this implicitly for the TPM (use qemu-img to create the QCoW2). Also, multiple VMs' TPMs could share the same secret. I'm not sure I'm a fan of the idea of libvirt creating the TPM qcow2 file itself at VM startup, since that's at odds with the way we deal with other host OS resources where the app is required to create everything the VM needs upfront. One fact is that the TPM Qemu works with will have a certain space requirement, i.e., the QCoW2 will have to be of a certain size so that all state that needs to be persisted fits on it. So, I thought I'd make it easier on the user to not have to think of the persistent storage of
On 03/31/2011 10:15 AM, Daniel P. Berrange wrote: the TPM and its size requirements when he wants to have a TPM connected to the VM, but let libvirt handle it transparently. Mostly I think it's the convenience factor, but I do find it compelling. The code does support both models with and without user-provided storage.
Also, why QCow2 ? It seems like rather a large hammer, if all we really need is to ensure the data is encrypted on disk. QCoW2 is currently the only file format that allows the most wide range of operations, i.e., supports snapshotting of the TPM parallel to the VM. Any other format would prevent snapshotting VMs with attached TPM. I don't think that would be a good choice.
Please let me know of any comments regarding this. My other main thought is how does the Xen TPM model fit in ? That has been around for quite a while, but not supported in libvirt. If we add TPM to
Might it be better to just use a raw 64kb file and just give QEMU a decryption key to use for it. It should be trivial for QEMU to have a variant on the raw block driver which passes all data writes/reads through an encrypt/decrypt API. QCow2 is not exactly everyone's favourite bit of QEMU code, being rather complex and unreliable at times. To me this was about supporting the widest variety of VM operations possible. QCoW2 does that, then there is also the FVD proposed format, which we could also use in the future. Maybe that would address the QCoW2 concerns, but that decision on that format is up to the QEmu community, of course. libvirt we need to make sure the way we model it works for Xen too. Not sure if anyone else like VMWare/VirtualBox does any TPM stuff yet. I think for the current Xen TPM model the XML not supporting encryption would be sufficient. It maybe possible to support it with or without provided filename - not sure about that, but libvirt could refuse to start the VM if in the Xen case the filename was not explicitly provided by the user. As for an encryption key, I believe it could be pulled from the 'secret' storage.
I cannot speak (at all) for the other technologies whether and how they may support it in the future. Regards, Stefan
participants (2)
-
Daniel P. Berrange
-
Stefan Berger