[libvirt] [Qemu-devel] libvirt/QEMU/SEV interaction

Dr. David Alan Gilbert dgilbert at redhat.com
Wed Sep 27 11:06:27 UTC 2017


* Michael S. Tsirkin (mst at redhat.com) wrote:
> On Fri, Sep 08, 2017 at 06:57:30AM -0500, Brijesh Singh wrote:
> > Hi All,
> 
> Sorry if below comment doesn't make sense, I might be misunderstanding
> something basic about SEV. Also sorry about the delay, I've been on
> vacation.
> 
> 
> > (sorry for the long message)
> > 
> > CPUs from AMD EPYC family supports Secure Encrypted Virtualization (SEV)
> > feature - the feature allows running encrypted VMs. To enable the feature,
> > I have been submitting patches to Linux kernel [1], Qemu [2] and OVMF [3].
> > We have been making some good progress in getting patches accepted upstream
> > in Linux and OVMF trees. SEV builds upon SME (Secure Memory Encryption)
> > feature -- SME support just got pulled into 4.14 merge window. The base
> > SEV patches are accepted in OVMF tree -- now we have SEV aware guest BIOS.
> > I am getting ready to take off "RFC" tag from remaining patches to get them
> > reviewed and accepted.
> > 
> > The boot flow for launching an SEV guest is a bit different from a typical
> > guest launch. In order to launch SEV guest from virt-manager or other
> > high-level VM management tools, we need to design and implement new
> > interface between libvirt and qemu, and probably add new APIs in libvirt
> > to be used by VM management tools. I am new to the libvirt and need some
> > expert advice while designing this interface. A pictorial representation
> > for a SEV guest launch flow is available in SEV Spec Appendix A [4].
> > 
> > A typical flow looks like this:
> > 
> > 1. Guest owner (GO) asks the cloud provider to launch SEV guest.
> > 2. VM tool asks libvirt to provide its Platform Diffie-Hellman (PDH) key.
> > 3. libvirt opens /dev/sev device to get its PDH and return the blob to the
> >    caller.
> > 4. VM tool gives its PDH to GO.
> > 5. GO provides its DH key, session-info and guest policy.
> > 6. VM tool somehow communicates the GO provided information to libvirt.
> > 7. libvirt adds "sev-guest" object in its xml file with all the information
> >    obtained from #5
> > 
> >    (currently my xml file looks like this)
> > 
> >    <qemu:arg value='-object'>
> >    <qemu:arg
> > value='sev-guest,id=sev0,policy=<GO_policy>,dh-key-file=<filename>,session-file=<filename>/>
> >    <qemu:arg value='-machine'/>
> >    <qemu:arg value='memory-encryption=sev0'/>
> > 
> > 8. libvirt launches the guest with "-S"
> > 9. While creating the SEV guest qemu does the following
> >  i) create encryption context using GO's DH, session-info and guest policy
> >     (LAUNCH_START)
> >  ii) encrypts the guest bios (LAUNCH_UPDATE_DATA)
> >  iii) calls LAUNCH_MEASUREMENT to get the encrypted bios measurement
> 
> This part troubles me. This seems to mean that the guest being launched
> must know what the measurement of the bios is going to be.  This means
> that the cloud provider can not update the bios without breaking guests.
> Also, while in practice you typically can run an old bios image on a new
> qemu instance, this is not really tested so would be very hard to
> support properly in QEMU.
> 
> 
> And this looks like a fundamental problem with the hash based
> measurement that's in hardware. So below I suggest that we layer
> some software on top to rely on the hash as little as possible.

I think the normal way to solve this is that the Distro would
provide a list of the signatures, and the GO would check the bios
measurement against that list.  The GO needs to keep that list
up to date; either directly downloading it from the Distro or
a copy signed by the Distro.

Dave

> 
> > 10. By some interface we must propagate the measurement all the way to GO
> >   before libvirt starts the guest.
> > 11. GO verifies the measurement and if measurement matches then it may
> >  give a secret blob -- which must be injected into the guest before
> >  libvirt starts the VM. If verification failed, GO will request cloud
> >  provider to destroy the VM.
> > 12. After secret blob is injected into guest, we call LAUNCH_FINISH
> >   to destory the encryption context.
> > 13. libvirt issues "continue" command to resume the guest boot.
> > 
> > Please note that the measurement value is protected with transport
> > encryption key (TIK) and it changes on each run. Similarly the secret blob
> > provided by GO does not need to be protected using libvirt/qemu APIs. The
> > secret is protected by TIK. From qemu and libvirt point of view these are
> > blobs and must be passed as-is to the SEV FW.
> 
> So here's an alternative idea for starting guests:
> 
> How about building a minimal shim firmware that
> runs on a single CPU and uses no hardware at all,
> it just contains the secret blob.
> 
> That firmware just immediately stops and signals
> hypervisor that it is ready to be run in the cloud.
> 
> Have user generate and start this shim firmware as a guest in a private
> setup, then export it out using SEND_* commands.
> 
> Then instead of asking to launch guest, you ask provider
> to load it with RECEIVE_* commands.
> 
> Unlike bios the shim firmware
> can hopefully be static so supporting it across qemu
> versions should be easy.
> 
> The shim firmware then loads bios from qemu, verifies
> it in any way it sees fit (e.g. it could check a signature, version, etc:
> it is not limited to a hardware hash anymore).
> It then jumps to the bios.
> 
> 
> While not exactly the same, there is some similarity
> here with how people solved the issues around secureboot -
> by using a shim.
> 
> Thanks!
> 
> 
> > Questions:
> > a) Do we need to add a new set of APIs in libvirt to return the PDH from
> > libvirt and VM tool ? Or can we use some pre-existing APIs to pass the
> > opaque blobs ? (this is mainly for step 3 and 6)
> > b) do we need to define a new xml tag to for memory-encryption ? or just
> > use the qemu:args tag ? (step 6)
> > c) what existing communicate interface can be used between libvirt and qemu
> > to get the measurement ? can we add a new qemu monitor command
> > 'get_sev_measurement' to get the measurement ? (step 10)
> > d) how to pass the secret blob from libvirt to qemu ? should we consider
> > adding a new object (sev-guest-secret) -- libvirt can add the object through
> > qemu monitor.
> > 
> > 
> > [1] https://marc.info/?l=kvm&m=150092661105069&w=2
> > [2] https://marc.info/?l=qemu-devel&m=148901186615642&w=2
> > [3] https://lists.01.org/pipermail/edk2-devel/2017-July/012220.html
> > [4] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf
> > 
> > Thanks
> > 
> > Brijesh
> > 
> 
--
Dr. David Alan Gilbert / dgilbert at redhat.com / Manchester, UK




More information about the libvir-list mailing list