Re: [PATCH 3/6] qemu: check if AMD secure guest support is enabled

2020-05-13 Thread Brijesh Singh


On 5/13/20 5:40 AM, Boris Fiuczynski wrote:
> On 5/12/20 7:52 PM, Brijesh Singh wrote:
>>
>> On 5/12/20 10:32 AM, Erik Skultety wrote:
>>> On Tue, May 12, 2020 at 09:08:38AM +0200, Boris Fiuczynski wrote:
>>>> On 5/11/20 9:40 PM, Brijesh Singh wrote:
>>>>> Thanks for the patch Paulo, Few comments.
>>>>>
>>>>> On 5/11/20 11:41 AM, Boris Fiuczynski wrote:
>>>>>> From: Paulo de Rezende Pinatti 
>>>>>>
>>>>>> Implement secure guest check for AMD SEV (Secure Encrypted
>>>>>> Virtualization) in order to invalidate the qemu capabilities
>>>>>> cache in case the availability of the feature changed.
>>>>>>
>>>>>> For AMD SEV the verification consists of:
>>>>>> - checking if /sys/module/kvm_amd/parameters/sev contains the
>>>>>> value '1': meaning SEV is enabled in the host kernel;
>>>>>> - checking if the kernel cmdline contains 'mem_encrypt=on': meaning
>>>>>> SME memory encryption feature on the host is enabled
>>>>>
>>>>> In addition to the kernel module parameter, we probably also need to
>>>>> check whether QEMU supports the feature. e.g, what if user has newer
>>>>> kernel but older qemu. e.g kernel > 4.18 but Qemu < 2.12.  To
>>>>> check the
>>>>> SEV feature support, we should verify the following conditions:
>>>>>
>>>>> 1) check kernel module parameter is set
>>>> Paulo implemented the checks following the documentation in
>>>> docs/kbase/launch_security_sev.rst. The check for the module
>>>> parameter sev
>>>> is included. Is the check for the kernel cmdline parameter
>>>> "mem_encrypt" not
>>>> necessary? Or would that be covered by your suggested check in 2)?
>>> Brijesh correct me here please, but IIRC having mem_encrypt set is
>>> merely
>>> a good security recommendation but is orthogonal with kvm.amd_sev
>>> feature, IOW
>>> SEV should work without SME. If my memory serves well here, we don't
>>> need
>>> and also should not parse the kernel cmdline in this case.
>>>
>>
>> Yes, that is correct.  mem_encrypt=on is not required for the SEV to
>> work. The mem_encrypt=on option is meant to enable the SME feature on
>> the host machine. In addition to the guest, if customer wants to protect
>> the Hypervsior memory from physical attacks then they can use SME or
>> TSME.  The SME can be enabled using mem_encrypt=on, whereas the TSME can
>> be enabled in the BIOS and does not require any kernel changes. AMD is
>> mostly recommending TSME to protect against the physical attacks.
>>
>>
>>>>> 2) check if /dev/sev device exist (aka firmware is detected)
>>>> This seems reasonable. Shouldn't it have been documented in
>>>> docs/kbase/launch_security_sev.rst?
>>> Sure, we can add a mention about this. Although, doesn't 1 imply 2?
>>> IOW can
>>> you have the kernel module parameter set to 1 and yet kernel doesn't
>>> expose the
>>> /dev/sev node?
>>
>>
>> Currently, 1 does not imply 2, KVM driver does not initialize the
>> firmware during the feature probe (i.e does not access the /dev/sev).
>> The firmware initialization is delayed until the first guest launch. So
>> only sane way to know whether firmware is been detected is check the
>> existence of the /dev/sev or issue a query-sev command . The query-sev
>> command will send the platform_status request to the firmware, if the
>> firmware is not ready then this command will fail.
>>
>>
>
> Just to summarize the checks you want implemented for AMD SEV support:
> 1) check kernel module parameter is set (as already implemented)
> 2) check if /dev/sev device exist
>
> Please note that these checks will also go into virt-host-validate in
> patch 5.
>

Sounds good to me, thanks.


>
>
>>>>> 3) Check if Qemu supports SEV feature (maybe we can detect the
>>>>> existence
>>>>> of the query-sev QMP command or detect Qemu version >= 2.12)
>>> ^This is already achieved by qemuMonitorJSONGetSEVCapabilities
>>>
>>>> The idea is to check the host capabilities to detect if qemus
>>>> capabilities
>>>> need to be reprobed. Therefore this would be a result if checks 1+2
>>>> change
>>>> but it would not be a cache invalidation trigger.
>>> I agree in the sense that the SEV support that is currently being
>>> reported in
>>> QEMU capabilities wasn't a good choice because it reports only
>>> platform data
>>> which are constant to the host and have nothing to do with QEMU. It
>>> would be
>>> okay to just say  in qemu capabilities and
>>> report the
>>> rest in host capabilities. I haven't added this info into host
>>> capabilities
>>> when I realized the mistake because I didn't want to duplicate the
>>> platform
>>> info on 2 places.  For the IBM secure guest feature, it makes total
>>> sense to
>>> report support within host capabilities, I'm just not sure whether
>>> we should do
>>> the same for SEV and try really hard to "fix" the mess.
>>>
>>> Regards,
>>
>>
>
>




Re: [PATCH 3/6] qemu: check if AMD secure guest support is enabled

2020-05-13 Thread Brijesh Singh


On 5/13/20 1:21 AM, Erik Skultety wrote:
> 2) check if /dev/sev device exist (aka firmware is detected)
 This seems reasonable. Shouldn't it have been documented in
 docs/kbase/launch_security_sev.rst?
>>> Sure, we can add a mention about this. Although, doesn't 1 imply 2? IOW can
>>> you have the kernel module parameter set to 1 and yet kernel doesn't expose 
>>> the
>>> /dev/sev node?
>>
>> Currently, 1 does not imply 2, KVM driver does not initialize the
>> firmware during the feature probe (i.e does not access the /dev/sev).
>> The firmware initialization is delayed until the first guest launch. So
>> only sane way to know whether firmware is been detected is check the
>> existence of the /dev/sev or issue a query-sev command . The query-sev
>> command will send the platform_status request to the firmware, if the
>> firmware is not ready then this command will fail.
> I see. Can query-sev fail or return that it's disabled, aka {"enabled":
> false,...} in the SevInfo QMP response, but at the same time succeed in
> returning the platform capabilities via query-sev-capabilities? I'm asking,
> because libvirt only issues the latter to fill in the QEMU capabilities
> structure.

Just looked at qemu code, If /dev/sev does not exist then
query-sev-capabilities should fail, and if SEV is not enabled in the
guest then query-sev should returns false. So, basically what libvirt is
doing correct, it should be using query-sev-capabilities to populate
QEMU capabilities. It was my bad, I should have mentioned the
query-sev-capabilities and not the query-sev check.

thanks



Re: [PATCH 3/6] qemu: check if AMD secure guest support is enabled

2020-05-12 Thread Brijesh Singh


On 5/12/20 10:32 AM, Erik Skultety wrote:
> On Tue, May 12, 2020 at 09:08:38AM +0200, Boris Fiuczynski wrote:
>> On 5/11/20 9:40 PM, Brijesh Singh wrote:
>>> Thanks for the patch Paulo, Few comments.
>>>
>>> On 5/11/20 11:41 AM, Boris Fiuczynski wrote:
>>>> From: Paulo de Rezende Pinatti 
>>>>
>>>> Implement secure guest check for AMD SEV (Secure Encrypted
>>>> Virtualization) in order to invalidate the qemu capabilities
>>>> cache in case the availability of the feature changed.
>>>>
>>>> For AMD SEV the verification consists of:
>>>> - checking if /sys/module/kvm_amd/parameters/sev contains the
>>>> value '1': meaning SEV is enabled in the host kernel;
>>>> - checking if the kernel cmdline contains 'mem_encrypt=on': meaning
>>>> SME memory encryption feature on the host is enabled
>>>
>>> In addition to the kernel module parameter, we probably also need to
>>> check whether QEMU supports the feature. e.g, what if user has newer
>>> kernel but older qemu. e.g kernel > 4.18 but Qemu < 2.12.  To check the
>>> SEV feature support, we should verify the following conditions:
>>>
>>> 1) check kernel module parameter is set
>> Paulo implemented the checks following the documentation in
>> docs/kbase/launch_security_sev.rst. The check for the module parameter sev
>> is included. Is the check for the kernel cmdline parameter "mem_encrypt" not
>> necessary? Or would that be covered by your suggested check in 2)?
> Brijesh correct me here please, but IIRC having mem_encrypt set is merely
> a good security recommendation but is orthogonal with kvm.amd_sev feature, IOW
> SEV should work without SME. If my memory serves well here, we don't need
> and also should not parse the kernel cmdline in this case.
>

Yes, that is correct.  mem_encrypt=on is not required for the SEV to
work. The mem_encrypt=on option is meant to enable the SME feature on
the host machine. In addition to the guest, if customer wants to protect
the Hypervsior memory from physical attacks then they can use SME or
TSME.  The SME can be enabled using mem_encrypt=on, whereas the TSME can
be enabled in the BIOS and does not require any kernel changes. AMD is
mostly recommending TSME to protect against the physical attacks.


>>> 2) check if /dev/sev device exist (aka firmware is detected)
>> This seems reasonable. Shouldn't it have been documented in
>> docs/kbase/launch_security_sev.rst?
> Sure, we can add a mention about this. Although, doesn't 1 imply 2? IOW can
> you have the kernel module parameter set to 1 and yet kernel doesn't expose 
> the
> /dev/sev node?


Currently, 1 does not imply 2, KVM driver does not initialize the
firmware during the feature probe (i.e does not access the /dev/sev).
The firmware initialization is delayed until the first guest launch. So
only sane way to know whether firmware is been detected is check the
existence of the /dev/sev or issue a query-sev command . The query-sev
command will send the platform_status request to the firmware, if the
firmware is not ready then this command will fail.


>>> 3) Check if Qemu supports SEV feature (maybe we can detect the existence
>>> of the query-sev QMP command or detect Qemu version >= 2.12)
> ^This is already achieved by qemuMonitorJSONGetSEVCapabilities
>
>> The idea is to check the host capabilities to detect if qemus capabilities
>> need to be reprobed. Therefore this would be a result if checks 1+2 change
>> but it would not be a cache invalidation trigger.
> I agree in the sense that the SEV support that is currently being reported in
> QEMU capabilities wasn't a good choice because it reports only platform data
> which are constant to the host and have nothing to do with QEMU. It would be
> okay to just say  in qemu capabilities and report the
> rest in host capabilities. I haven't added this info into host capabilities
> when I realized the mistake because I didn't want to duplicate the platform
> info on 2 places.  For the IBM secure guest feature, it makes total sense to
> report support within host capabilities, I'm just not sure whether we should 
> do
> the same for SEV and try really hard to "fix" the mess.
>
> Regards,




Re: [PATCH 3/6] qemu: check if AMD secure guest support is enabled

2020-05-12 Thread Brijesh Singh
Thanks for the patch Paulo, Few comments.

On 5/11/20 11:41 AM, Boris Fiuczynski wrote:
> From: Paulo de Rezende Pinatti 
>
> Implement secure guest check for AMD SEV (Secure Encrypted
> Virtualization) in order to invalidate the qemu capabilities
> cache in case the availability of the feature changed.
>
> For AMD SEV the verification consists of:
> - checking if /sys/module/kvm_amd/parameters/sev contains the
> value '1': meaning SEV is enabled in the host kernel;
> - checking if the kernel cmdline contains 'mem_encrypt=on': meaning
> SME memory encryption feature on the host is enabled


In addition to the kernel module parameter, we probably also need to
check whether QEMU supports the feature. e.g, what if user has newer
kernel but older qemu. e.g kernel > 4.18 but Qemu < 2.12.  To check the
SEV feature support, we should verify the following conditions:

1) check kernel module parameter is set

2) check if /dev/sev device exist (aka firmware is detected)

3) Check if Qemu supports SEV feature (maybe we can detect the existence
of the query-sev QMP command or detect Qemu version >= 2.12)

thanks

> Signed-off-by: Paulo de Rezende Pinatti 
> Reviewed-by: Bjoern Walk 
> Reviewed-by: Boris Fiuczynski 
> ---
>  docs/kbase/launch_security_sev.rst |  2 +-
>  src/qemu/qemu_capabilities.c   | 27 +++
>  2 files changed, 28 insertions(+), 1 deletion(-)
>
> diff --git a/docs/kbase/launch_security_sev.rst 
> b/docs/kbase/launch_security_sev.rst
> index 65f258587d..fa602c7432 100644
> --- a/docs/kbase/launch_security_sev.rst
> +++ b/docs/kbase/launch_security_sev.rst
> @@ -109,7 +109,7 @@ following:
>   
> 
>  
> -Note that if libvirt was already installed and libvirtd running before
> +Note that if libvirt (<6.4.0) was already installed and libvirtd running 
> before
>  enabling SEV in the kernel followed by the host reboot you need to force
>  libvirtd to re-probe both the host and QEMU capabilities. First stop
>  libvirtd:
> diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
> index 2874bb1e7c..6cf926d52d 100644
> --- a/src/qemu/qemu_capabilities.c
> +++ b/src/qemu/qemu_capabilities.c
> @@ -4604,6 +4604,31 @@ virQEMUCapsKVMSupportsSecureGuestS390(void)
>  }
>  
>  
> +/*
> + * Check whether AMD Secure Encrypted Virtualization (x86) is enabled
> + */
> +static bool
> +virQEMUCapsKVMSupportsSecureGuestAMD(void)
> +{
> +g_autofree char *cmdline = NULL;
> +g_autofree char *modValue = NULL;
> +static const char *kValues[] = {"on"};
> +
> +if (virFileReadValueString(&modValue, 
> "/sys/module/kvm_amd/parameters/sev") < 0)
> +return false;
> +if (modValue[0] != '1')
> +return false;
> +if (virFileReadValueString(&cmdline, "/proc/cmdline") < 0)
> +return false;
> +if (virKernelCmdlineMatchParam(cmdline, "mem_encrypt", kValues,
> +   G_N_ELEMENTS(kValues),
> +   VIR_KERNEL_CMDLINE_FLAGS_SEARCH_LAST |
> +   VIR_KERNEL_CMDLINE_FLAGS_CMP_EQ))
> +return true;
> +return false;
> +}
> +
> +
>  /*
>   * Check whether the secure guest functionality is enabled.
>   * See the specific architecture function for details on the verifications 
> made.
> @@ -4615,6 +4640,8 @@ virQEMUCapsKVMSupportsSecureGuest(void)
>  
>  if (ARCH_IS_S390(arch))
>  return virQEMUCapsKVMSupportsSecureGuestS390();
> +if (ARCH_IS_X86(arch))
> +return virQEMUCapsKVMSupportsSecureGuestAMD();
>  return false;
>  }
>  




Re: [libvirt] [PATCH v2] docs: Provide documentation for SEV launch security

2019-07-02 Thread Brijesh Singh
Hi Erik,

I am having difficulty with IT folks while subscribing to libvirt ML, I am
working with them to get it fixed, In the meantime can you please copy me
in future SEV related patches/post? Overall the patch looks good, I have
few minor comments. Please see below.

thanks

On Mon, Jul 1, 2019 at 4:00 AM Erik Skultety  wrote:

> Signed-off-by: Erik Skultety 
> ---
>  docs/launch_security_sev.html.in | 516 +++
>  1 file changed, 516 insertions(+)
>  create mode 100644 docs/launch_security_sev.html.in
>
> diff --git a/docs/launch_security_sev.html.in b/docs/
> launch_security_sev.html.in
> new file mode 100644
> index 00..2f0f89d714
> --- /dev/null
> +++ b/docs/launch_security_sev.html.in
> @@ -0,0 +1,516 @@
> +
> +
> +http://www.w3.org/1999/xhtml";>
> +  
> +Launch security with AMD SEV
> +
> +
> +
> +
> +Storage encryption in modern public cloud computing is a common
> practice.
> +However, from the point of view of a user of these cloud
> workloads, a
> +significant amount of trust needs to be put in the cloud platform
> security as
> +well as integrity (was the hypervisor tampered?). For this reason
> there's ever
> +rising demand for securing data in use, i.e. memory encryption.
> +One of the solutions addressing this matter is AMD SEV.
> +
> +
> +AMD SEV
> +
> +SEV (Secure Encrypted Virtualization) is a feature extension of
> AMD's SME (Secure
> +Memory Encryption) intended for KVM virtual machines which is
> supported
> +primarily on AMD's EPYC CPU line. In contrast to SME, SEV uses a
> unique memory encryption
> +key for each VM. The whole encryption of memory pages is
> completely transparent
> +to the hypervisor and happens


Encryption does not happen inside the PSP, instead we should say

" happens inside dedicated hardware in the on-die memory controller.
Each controller includes a high-performance Advanced Encryption Standard
(AES) engine that encrypts data when it is written to DRAM and decrypts it
when read."



> in the AMD firmware.
> +For more details about the technology itself, you can visit
> +  https://developer.amd.com/sev/";>AMD's developer
> portal.
> +
> +
> +Enabling SEV on the host
> +  
> +  Before VMs can make use of the SEV feature you need to make
> sure your
> +  AMD CPU does support SEV. You can check whether SEV is among
> the CPU
> +  flags with:
> +  
> +
> +  
> +$ cat /proc/cpuinfo | grep sev
> +...
> +sme ssbd sev ibpb
> +
> +  
> +  Next step is to enable SEV in the kernel, because it is
> disabled by default.
> +  This is done by putting the following onto the kernel command
> line:
> +  
> +
> +  
> +mem_encrypt=on kvm_amd.sev=1
> +  
> +
> +  
> +  To make the changes persistent, append the above to the
> variable holding
> +  parameters of the kernel command line in
> +  /etc/default/grub to preserve SEV settings across
> reboots
> +  
> +
> +  
> +$ cat /etc/default/grub
> +...
> +GRUB_CMDLINE_LINUX="... mem_encrypt=on kvm_amd.sev=1"
> +$ grub2-mkconfig -o /boot/efi/EFI//grub.cfg
> +
> +  
> +mem_encrypt=on turns on the SME memory encryption
> feature on
> +the host which is required for SEV to work.


SME is not required for SEV to work in the host. We should recommend users
to enable the SME so that they are protected against the physical attacks
on hypervisor memory.

" on the host which protects against the physical attack on hypervisor
memory."



> The kvm_amd.sev
> +parameter actually enables SEV in the kvm module. It can be set
> on the
> +command line alongside mem_encrypt like shown above,
> or it
> +can be put into a module config under
> /etc/modprobe.d/
> +  
> +
> +  
> +$ cat /etc/modprobe.d/sev.conf
> +options kvm_amd sev=1
> +  
> +
> +  
> +  After rebooting the host, you should see SEV being enabled in
> the kernel:
> +  
> +
> +  
> +$ cat /sys/module/kvm_amd/parameters/sev
> +1
> +  
> +
> +  Checking SEV support in the virt stack
> +  
> +Note: All of the commands bellow need to be run with root
> privileges.
> +  
> +
> +  
> +  First make sure you have the following packages in the
> specified versions:
> +  
> +
> +  
> +
> +libvirt >= 4.5.0 (>5.1.0 recommended due to additional SEV
> bugfixes)
> +
> +
> +QEMU >= 2.12.0
> +
> +  
> +  
> +  To confirm that the virtualization stack supports SEV, run the
> following:
> +  
> +
> +  
> +# virsh domcapabilities
> +
> +...
> +  
> +...
> +
> +  47
> +  1
> +
> +...
> +  

Re: [libvirt] [PATCH 0/4] Fix a SIGSEGV in libvirtd when querying AMD SEV info

2018-08-16 Thread Brijesh Singh

Hi Erik,

On 08/15/2018 10:02 AM, Erik Skultety wrote:

This series fixes the following BZ:
https://bugzilla.redhat.com/show_bug.cgi?id=1612009

TL;DR:
We don't format SEV platform data (PDH, certificate chain,...) into our qemu
caps cache which poses a problem after libvirtd restart when we restore from
the cache and get a segfault upon issuing virNodeGetSEVInfo.

I performed some tests on an AMD machine, but CC'ing Brijesh, he might give it
a test too.



I tested this series on my EPYC system (which supports SEV) and
everything seems to be working fine. I have verified the below
code snippet from BZ

import libvirt
conn = libvirt.open()
conn.getSEVInfo()

And I can confirm that getSEVInfo is able to get the PDH certificates etc.

Tested-by: Brijesh Singh 


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] CPU Support

2018-07-18 Thread Brijesh Singh


On 7/18/18 8:49 AM, Eduardo Habkost wrote:
> CCing the AMD people who worked on this.
>
> On Wed, Jul 18, 2018 at 12:18:45PM +0200, Pavel Hrdina wrote:
>> On Wed, Jul 18, 2018 at 10:50:34AM +0100, Daniel P. Berrangé wrote:
>>> On Wed, Jul 18, 2018 at 12:41:48PM +0300, Hetz Ben Hamo wrote:
 Hi,

 I've been looking at the CPU list and although I see lots of CPU's, I
 cannot find 2 CPU families:

 * AMD Ryzen
 * AMD Threadripper

 Although EPYC has been added recently.

 Are there any missing details which preventing adding those CPU's to the
 list?
>>> Libvirt adds CPU models based on what QEMU supports. So from libvirt side 
>>> the
>>> answer is simply that QEMU doesn't expose any models for Ryzen/Threadripper,
>>> but I'm not clear why it doesn't...

EPYC model should work just fine on Ryzen/Threadripper. Are we seeing
some issues?

>>> For a while I thought Ryzen/Threadripper would have same feature set as
>>> EPYC, but I've seen bugs recently suggesting that is not in fact the
>>> case. So it does look like having those models exposed by QEMU might
>>> be useful.
>>>
>>> Copy'ing QEMU devel & the CPU model maintainers for opinions.
>> I think that QEMU should figure out some pattern for naming CPU models
>> because it's one big mess.  EPYC and Ryzen are bad names for QEMU as
>> Core/Xeon would be for Intel CPUs.  It's the name of a model families
>> and it will probably remain the same but with different
>> microarchitecture.
>> Better name would be similarly like for the latest Inter CPUs,
>> Skylake-Client and Skylake-Server.  Currently AMD has already two
>> microarchitectures, Zen and Zen+ and there is third one Zen 2 planned.
>>
>> Zen has AMD Ryzen, AMD Ryzen Threadripper and AMD Epyc.
>> Zen+ has AMD Ryzen, AMD Ryzen Threadripper
>>
>> And I bet that Zen 2 will follow the same model families.


My guess is same as your :) I hope sales/marketing does not come up with
different names for Soc's based Zen 2 core.


>> We probably cannot rename EPYC now, but before we introduce Ryzen and
>> Threadripper let's thing about it and come up with better names, for
>> example Zen-Client/Zen-Server Zen+-Client or something like that.

Zen-Client/Zen-Server naming convention looks better.

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH 00/10] SEV: use camelCase in XMLs and other cleanups

2018-06-12 Thread Brijesh Singh



On 06/12/2018 07:00 AM, Ján Tomko wrote:

The first two patches tune up the XML elements to use camelCase
instead of dashes as the word separators.

Hopefully our QEMU capability probing is right and we can fix error
reporting in patch 3.

The rest are minor cleanups and renames to use SEV instead of Sev
in internal identifier names.




Thanks for the series, In addition to looking at the changes I  did a 
quick build and run tests. All seems to be working fine. thanks


Reviewed-by: Brijesh Singh 
Tested-by: Brijesh Singh 




I did not touch virNodeGetSevInfoEnsureACL - not sure if it's all right
since the public API uses SEV.

Ján Tomko (10):
   domaincaps: rename reduced-phys-bits to reducedPhysBits
   conf: prefer camelCase for launchSecurity
   qemu: fail if virQEMUCapsProbeQMPSEVCapabilities fails
   remove virQEMUCapsSetSEVCapabilities
   qemuDomainGetSEVMeasurement: fix possible leak
   rename qemuBuildSevCreateFile to qemuProcessSEVCreateFile
   qemuProcessSEVCreateFile: use a cleanup label
   Rename virDomainSevDefPtr to virDomainSEVDefPtr
   rename more Sev functions to SEV
   qemuMonitorJSONGetSEVCapabilities: remove redundant whitespace

  docs/formatdomain.html.in  | 22 +++
  docs/formatdomaincaps.html.in  |  2 +-
  docs/schemas/domaincaps.rng|  2 +-
  docs/schemas/domaincommon.rng  | 10 +++
  src/conf/domain_capabilities.c |  2 +-
  src/conf/domain_conf.c | 32 +++---
  src/conf/domain_conf.h |  8 +++---
  src/qemu/qemu_capabilities.c   | 16 ++-
  src/qemu/qemu_command.c|  6 ++--
  src/qemu/qemu_driver.c |  2 +-
  src/qemu/qemu_monitor_json.c   |  1 -
  src/qemu/qemu_process.c| 26 --
  tests/genericxml2xmlindata/launch-security-sev.xml |  8 +++---
  tests/qemuxml2argvdata/launch-security-sev.xml |  8 +++---
  14 files changed, 66 insertions(+), 79 deletions(-)



--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v9 00/11] x86: Secure Encrypted Virtualization (AMD)

2018-06-11 Thread Brijesh Singh

Hi Erik,


On 06/11/2018 09:10 AM, Erik Skultety wrote:

On Fri, Jun 08, 2018 at 10:14:35AM -0500, Brijesh Singh wrote:


Re: Jano's below comment

(Also, some of the patches have double "<< >>" around your e-mail,
how did that happen?)

I am not sure what I am doing that is causing the double "<< >>" around my
email address in some patches. I tried fixing it after I saw Jano note but
it somehow happens again...I have no explanation on what is going on.
Whoever commits the series, can you please remove one of the quote from the
my email address, Or I can try fixing it and resend the series. Please let
me know. thanks


For the whole series (I'll make the tiny change in patch 5):
Reviewed-by: Erik Skultety 

I'll also tweak the double angle brackets, at first I thought you were adding
the SoB manually and this was a typo, but it clearly isn't the case, it would
be pointless to bikeshed about that, so as I said, I'll take care of that
before merging.

Also, now that this is done, would take also take care of extending the other
language bindings for the new APIs, or shall I do that?




Thanks for all your help in reviews. Any help on language bindings for 
the new APIs are appreciated. I think I may able to do python but will 
certainly need help with others (I am not very familiar with other 
languages).


-Brijesh

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v9 00/11] x86: Secure Encrypted Virtualization (AMD)

2018-06-08 Thread Brijesh Singh



Re: Jano's below comment

(Also, some of the patches have double "<< >>" around your e-mail,
how did that happen?)

I am not sure what I am doing that is causing the double "<< >>" around 
my email address in some patches. I tried fixing it after I saw Jano 
note but it somehow happens again...I have no explanation on what is 
going on. Whoever commits the series, can you please remove one of the 
quote from the my email address, Or I can try fixing it and resend the 
series. Please let me know. thanks



On 06/08/2018 09:40 AM, Brijesh Singh wrote:

This patch series provides support for launching an encrypted guest using
AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV feature
allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
that includes the following


...
   
  
  
   


If  is provided then we indicate that hypervisor is capable of launching
SEV guest. mgmt tool can call virNodeGetSEVCapabilities() to get the additional
informations like PDH and certificate chain etc.

2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in 
case
if guest owner wish to establish a secure connection with SEV firmware to
negotiate a key used for validating the measurement.

3. mgmt tool requests to start a guest calling virCreateXML(), passing \
VIR_DOMAIN_START_PAUSED. The xml would include


   47
   1
   0x1

   (optional)
 /* Guest owners Diffie-Hellman key */
 /* Guest owners Session blob */


4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
args looks like this:

# $QEMU ..
-machine memory-encryption=sev0 \
-object sev-guest,id=sev0,dh-cert-file=

5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event

6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls \
virDomainGetLaunchSecretInfo() to retrieve the measurement of encrypted memory.

7. (optional) mgmt tool can provide the measurement value to guest owner, which 
can
validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
it resumes the guest otherwise it calls destroy() to kill the guest.

8. mgmt tool resumes the guest

TODO:
* SEV guest require to use DMA apis for the virtio devices. In order to use the 
DMA
apis the virtio devices must have this tag



It is a bit unclear to me where these changes need to go. Do we need to
modify the libvirt to automatically add these when SEV is enabled or
we ask mgmt tool to make sure that it creates XML with right tag to enable
the DMA APIs for virtio devices. I am looking for some suggestions.

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

SEV Firmware API spec is available at:
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Changes sicne v8:
* rename qemuGetSEVInfo -> qemuGetSEVInfoToParams
* use virQEMUCapsCacheLookupByArch to get qemuCaps

Change since v7:
* rename virNodeSEVCapability() -> virNodeSEVInfo()
* rebase the series

Changes since v6:
* add API to get SEV PDH and Certificate chain data
* drop virsh command changes. We can revisit this later when we have
   more visibility on setter.

Change since v5:
* drop the seperate test patch and merge the code with other patches.
* rename the xml from sev -> launch-security-sev
* make policy field mandatory
* address multiple feedback from previous reviews.

Changes since v4:
* add /dev/sev in shared device list

Changes since v3:
* rename QEMU_CAPS_SEV -> QEMU_CAPS_SEV_GUEST
* update caps_2.12.0.x86_64.replies to include query-sev-capabilities data

Changes since v2:
* make cbitpos, policy and reduced-phys-bits as unsigned int
* update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr *params
instead of virTypedParameterPtr params.

Changes since v1:
* rename  ->  for domain
* add more information about policy and other fields in domaincaps.html
* split the domain_conf support in two patches
* add virDomainGetLaunchInfo() to retrieve the SEV measurement
* extend virsh command to show the domain's launch security information
* add test cases to validate newly added  element
* fix issues reported with 'make check' and 'make syntax-check'

The complete git tree is available at:
https://github.com/codomania/libvirt/tree/v9

Brijesh Singh (11):
   qemu: provide support to query the SEV capability
   conf: expose SEV feature in domain capabilities
   libvirt: Introduce virNodeGetSEVInfo public API
   remote: implement the remote protocol for virNodeGetSEVInfo()
   qemu: Implement the driver backend for virNodeGetSEVInfo()
   conf: introduce

[libvirt] [PATCH v9 03/11] libvirt: Introduce virNodeGetSEVInfo public API

2018-06-08 Thread Brijesh Singh
The API can be used by application to retrieve the Platform Diffie-Hellman
Key and Platform Certificate chain.

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 include/libvirt/libvirt-host.h | 42 
 src/driver-hypervisor.h|  6 ++
 src/libvirt-host.c | 49 ++
 src/libvirt_public.syms|  1 +
 4 files changed, 98 insertions(+)

diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
index 84f4858..a04d669 100644
--- a/include/libvirt/libvirt-host.h
+++ b/include/libvirt/libvirt-host.h
@@ -432,6 +432,48 @@ typedef virNodeCPUStats *virNodeCPUStatsPtr;
 
 typedef virNodeMemoryStats *virNodeMemoryStatsPtr;
 
+
+/**
+ *
+ * SEV Parameters
+ */
+
+/**
+ * VIR_NODE_SEV_PDH:
+ *
+ * Macro represents the Platform Diffie-Hellman key, as 
VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_PDH "pdh"
+
+/**
+ * VIR_NODE_SEV_CERT_CHAIN:
+ *
+ * Macro represents the platform certificate chain that includes the platform
+ * endorsement key (PEK), owner certificate authority (OCD) and chip
+ * endorsement key (CEK), as VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_CERT_CHAIN "cert-chain"
+
+/**
+ * VIR_NODE_SEV_CBITPOS:
+ *
+ * Macro represents the CBit Position used by hypervisor when SEV is enabled.
+ */
+# define VIR_NODE_SEV_CBITPOS "cbitpos"
+
+/**
+ * VIR_NODE_SEV_REDUCED_PHYS_BITS:
+ *
+ * Macro represents the number of bits we lose in physical address space
+ * when SEV is enabled in the guest.
+ */
+# define VIR_NODE_SEV_REDUCED_PHYS_BITS "reduced-phys-bits"
+
+int virNodeGetSEVInfo (virConnectPtr conn,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags);
+
 /**
  * virConnectFlags
  *
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index aa99cbb..c50d2a0 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1309,6 +1309,11 @@ typedef int
   unsigned int action,
   unsigned int flags);
 
+typedef int
+(*virDrvNodeGetSEVInfo)(virConnectPtr conn,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags);
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1558,6 +1563,7 @@ struct _virHypervisorDriver {
 virDrvDomainSetLifecycleAction domainSetLifecycleAction;
 virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU;
 virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
+virDrvNodeGetSEVInfo nodeGetSEVInfo;
 };
 
 
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
index 3aaf558..e20d6ee 100644
--- a/src/libvirt-host.c
+++ b/src/libvirt-host.c
@@ -1639,3 +1639,52 @@ virNodeAllocPages(virConnectPtr conn,
 virDispatchError(conn);
 return -1;
 }
+
+
+/*
+ * virNodeGetSEVInfo:
+ * @conn: pointer to the hypervisor connection
+ * @params: where to store  SEV information
+ * @nparams: pointer to number of SEV parameters returned in @params
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * If hypervisor supports AMD's SEV feature, then @params will contain various
+ * platform specific information like PDH and certificate chain. Caller is
+ * responsible for freeing @params.
+ *
+ * Returns 0 in case of success, and -1 in case of failure.
+ */
+int
+virNodeGetSEVInfo(virConnectPtr conn,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags)
+{
+VIR_DEBUG("conn=%p, params=%p, nparams=%p, flags=0x%x",
+  conn, params, nparams, flags);
+
+virResetLastError();
+
+virCheckConnectReturn(conn, -1);
+virCheckNonNullArgGoto(nparams, error);
+virCheckNonNegativeArgGoto(*nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(conn->driver, conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->nodeGetSEVInfo) {
+int ret;
+ret = conn->driver->nodeGetSEVInfo(conn, params, nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+
+virReportUnsupportedError();
+
+ error:
+virDispatchError(conn);
+return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 4f54b84..524d5fd 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -796,6 +796,7 @@ LIBVIRT_4.5.0 {
 global:
 virGetLastErrorCode;
 virGetLastErrorDomain;
+virNodeGetSEVInfo;
 } LIBVIRT_4.4.0;
 
 #  define new API here using predicted next version number 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v9 10/11] remote: implement the remote protocol for launch security

2018-06-08 Thread Brijesh Singh
Add remote support for launch security info.

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 src/remote/remote_daemon_dispatch.c | 47 +
 src/remote/remote_driver.c  | 40 +++
 src/remote/remote_protocol.x| 19 ++-
 src/remote_protocol-structs | 11 +
 4 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index 959367f..f1a5ba2 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -3110,6 +3110,53 @@ remoteDispatchNodeGetMemoryStats(virNetServerPtr server 
ATTRIBUTE_UNUSED,
 }
 
 static int
+remoteDispatchDomainGetLaunchSecurityInfo(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+  virNetMessagePtr msg 
ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  
remote_domain_get_launch_security_info_args *args,
+  
remote_domain_get_launch_security_info_ret *ret)
+{
+virDomainPtr dom = NULL;
+virTypedParameterPtr params = NULL;
+int nparams = 0;
+int rv = -1;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, args->flags) < 
0)
+goto cleanup;
+
+if (nparams > REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+goto cleanup;
+}
+
+if (virTypedParamsSerialize(params, nparams,
+(virTypedParameterRemotePtr *) 
&ret->params.params_val,
+&ret->params.params_len,
+args->flags) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0)
+virNetMessageSaveError(rerr);
+virTypedParamsFree(params, nparams);
+virObjectUnref(dom);
+return rv;
+}
+
+static int
 remoteDispatchDomainGetPerfEvents(virNetServerPtr server ATTRIBUTE_UNUSED,
   virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
   virNetMessagePtr msg ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 8ac7264..995d440 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1966,6 +1966,45 @@ remoteDomainGetNumaParameters(virDomainPtr domain,
 }
 
 static int
+remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags)
+{
+int rv = -1;
+remote_domain_get_launch_security_info_args args;
+remote_domain_get_launch_security_info_ret ret;
+struct private_data *priv = domain->conn->privateData;
+
+remoteDriverLock(priv);
+
+make_nonnull_domain(&args.dom, domain);
+args.flags = flags;
+
+memset(&ret, 0, sizeof(ret));
+if (call(domain->conn, priv, 0, 
REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_args, 
(char *) &args,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_ret, (char 
*) &ret) == -1)
+goto done;
+
+if (virTypedParamsDeserialize((virTypedParameterRemotePtr) 
ret.params.params_val,
+  ret.params.params_len,
+  
REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX,
+  params,
+  nparams) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+xdr_free((xdrproc_t) xdr_remote_domain_get_launch_security_info_ret,
+ (char *) &ret);
+ done:
+remoteDriverUnlock(priv);
+return rv;
+}
+
+static int
 remoteDomainGetPerfEvents(virDomainPtr domain,
   virTypedParameterPtr *params,
   int *nparams,
@@ -8491,6 +8530,7 @@ static virHypervisorDriver hypervisor_driver = {
 .connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 
*/
 .connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 
4.4.0 */
 .nodeGetSEVInfo = remoteNodeGetSEVInfo, /* 4.5.0 */
+.domainGetLaunchSecurityInfo = remoteDomainGetLaunchSecurityInfo /* 4.5.0 
*/
 };
 
 static virNetworkDriver netw

[libvirt] [PATCH v9 02/11] conf: expose SEV feature in domain capabilities

2018-06-08 Thread Brijesh Singh
Extend hypervisor capabilities to include sev feature. When available,
hypervisor supports launching an encrypted VM on AMD platform. The
sev feature tag provides additional details like Platform Diffie-Hellman
(PDH) key and certificate chain which can be used by the guest owner to
establish a cryptographic session with the SEV firmware to negotiate
keys used for attestation or to provide secret during launch.

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 docs/formatdomaincaps.html.in  | 30 +++
 docs/schemas/domaincaps.rng| 14 +
 src/conf/domain_capabilities.c | 18 +
 src/conf/domain_capabilities.h |  1 +
 src/qemu/qemu_capabilities.c   | 46 +-
 5 files changed, 108 insertions(+), 1 deletion(-)

diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index e0814cb..6be553a 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -435,6 +435,10 @@
 </gic>
 <vmcoreinfo supported='yes'/>
 <genid supported='yes'/>
+<sev>
+  <cbitpos>47</cbitpos>
+  <reduced-phys-bits>1</reduced-phys-bits>
+</sev>
   </features>
 </domainCapabilities>
 
@@ -467,5 +471,31 @@
 
 Reports whether the genid feature can be used by the domain.
 
+SEV capabilities
+
+AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under
+the sev element.
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When supported,
+guest owner can create a VM whose memory contents will be transparently
+encrypted with a key unique to that VM.
+
+
+For more details on SEV feature see:
+  https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";>
+SEV API spec and http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf";>
+SEV White Paper
+
+
+
+  cbitpos
+  When memory encryption is enabled, one of the physical address bits
+  (aka the C-bit) is utilized to mark if a memory page is protected. The
+  C-bit position is Hypervisor dependent.
+  reduced-phys-bits
+  When memory encryption is enabled, we lose certain bits in physical
+  address space. The number of bits we lose is hypervisor dependent.
+
+
   
 
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 5ceabb0..1d0a2e1 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -185,6 +185,9 @@
 
 
 
+
+  
+
   
 
   
@@ -208,6 +211,17 @@
 
   
 
+  
+
+  
+
+  
+  
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 3589777..ec469bf 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -88,6 +88,7 @@ virDomainCapsDispose(void *obj)
 VIR_FREE(caps->machine);
 virObjectUnref(caps->cpu.custom);
 virCPUDefFree(caps->cpu.hostModel);
+virSEVCapabilitiesFree(caps->sev);
 
 virDomainCapsStringValuesFree(&caps->os.loader.values);
 }
@@ -554,6 +555,22 @@ virDomainCapsFeatureGICFormat(virBufferPtr buf,
 FORMAT_EPILOGUE(gic);
 }
 
+static void
+virDomainCapsFeatureSEVFormat(virBufferPtr buf,
+  virSEVCapabilityPtr const sev)
+{
+if (!sev)
+return;
+
+virBufferAddLit(buf, "\n");
+virBufferAdjustIndent(buf, 2);
+virBufferAsprintf(buf, "%d\n", sev->cbitpos);
+virBufferAsprintf(buf, "%d\n",
+  sev->reduced_phys_bits);
+virBufferAdjustIndent(buf, -2);
+virBufferAddLit(buf, "\n");
+}
+
 
 char *
 virDomainCapsFormat(virDomainCapsPtr const caps)
@@ -600,6 +617,7 @@ virDomainCapsFormat(virDomainCapsPtr const caps)
 
 virBufferAsprintf(&buf, "\n",
   caps->genid ? "yes" : "no");
+virDomainCapsFeatureSEVFormat(&buf, caps->sev);
 
 virBufferAdjustIndent(&buf, -2);
 virBufferAddLit(&buf, "\n");
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 56c1903..755de13 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -169,6 +169,7 @@ struct _virDomainCaps {
 virDomainCapsFeatureGIC gic;
 bool vmcoreinfo;
 bool genid;
+virSEVCapabilityPtr sev;
 /* add new domain features here */
 };
 
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 8b3ffe1..1803ed9 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -5157,6 +5157,48 @@ virQEMUCapsFillDomainFeatur

[libvirt] [PATCH v9 07/11] qemu/cgroup: add /dev/sev in shared devices list

2018-06-08 Thread Brijesh Singh
QEMU uses /dev/sev device while creating the SEV guest, lets add /dev/sev
in the list of devices allowed to be accessed by the QEMU.

Signed-off-by: Brijesh Singh <>
Reviewed-by: Erik Skultety 
---
 docs/drvqemu.html.in   | 3 ++-
 src/qemu/qemu.conf | 2 +-
 src/qemu/qemu_cgroup.c | 2 +-
 src/qemu/test_libvirtd_qemu.aug.in | 1 +
 4 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/docs/drvqemu.html.in b/docs/drvqemu.html.in
index cbd159d..13adb5c 100644
--- a/docs/drvqemu.html.in
+++ b/docs/drvqemu.html.in
@@ -396,7 +396,8 @@ chmod o+x /path/to/directory
 /dev/null, /dev/full, /dev/zero,
 /dev/random, /dev/urandom,
 /dev/ptmx, /dev/kvm, /dev/kqemu,
-/dev/rtc, /dev/hpet, /dev/net/tun
+/dev/rtc, /dev/hpet, /dev/net/tun,
+/dev/sev
 
 
 
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 76afe88..cd57b3c 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -485,7 +485,7 @@
 #"/dev/null", "/dev/full", "/dev/zero",
 #"/dev/random", "/dev/urandom",
 #"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-#"/dev/rtc","/dev/hpet"
+#"/dev/rtc","/dev/hpet", "/dev/sev"
 #]
 #
 # RDMA migration requires the following extra files to be added to the list:
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 12b3f3b..43c5ae8 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -48,7 +48,7 @@ const char *const defaultDeviceACL[] = {
 "/dev/null", "/dev/full", "/dev/zero",
 "/dev/random", "/dev/urandom",
 "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-"/dev/rtc", "/dev/hpet",
+"/dev/rtc", "/dev/hpet", "/dev/sev",
 NULL,
 };
 #define DEVICE_PTY_MAJOR 136
diff --git a/src/qemu/test_libvirtd_qemu.aug.in 
b/src/qemu/test_libvirtd_qemu.aug.in
index 61690ee..f1e8806 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -62,6 +62,7 @@ module Test_libvirtd_qemu =
 { "8" = "/dev/kqemu" }
 { "9" = "/dev/rtc" }
 { "10" = "/dev/hpet" }
+{ "11" = "/dev/sev" }
 }
 { "save_image_format" = "raw" }
 { "dump_image_format" = "raw" }
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v9 11/11] qemu: Implement the driver backend for virDomainGetLaunchSecurityInfo

2018-06-08 Thread Brijesh Singh
This patch implements the internal driver API for launch event into
qemu driver. When SEV is enabled, execute 'query-sev-launch-measurement'
to get the measurement of memory encrypted through launch sequence.

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 src/qemu/qemu_driver.c   | 69 
 src/qemu/qemu_monitor.c  |  8 +
 src/qemu/qemu_monitor.h  |  3 ++
 src/qemu/qemu_monitor_json.c | 42 +++
 src/qemu/qemu_monitor_json.h |  2 ++
 5 files changed, 124 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 264c47d..3f1eb8a 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21505,6 +21505,74 @@ qemuNodeGetSEVInfo(virConnectPtr conn,
 }
 
 
+static int
+qemuDomainGetSEVMeasurement(virQEMUDriverPtr driver,
+virDomainObjPtr vm,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+int ret = -1;
+char *tmp;
+int maxpar = 0;
+
+virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+return -1;
+
+if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
+goto endjob;
+
+tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
+if (tmp == NULL)
+goto endjob;
+
+if (qemuDomainObjExitMonitor(driver, vm) < 0)
+goto endjob;
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
+tmp) < 0)
+goto endjob;
+
+VIR_FREE(tmp);
+ret = 0;
+
+ endjob:
+qemuDomainObjEndJob(driver, vm);
+return ret;
+}
+
+
+static int
+qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+virQEMUDriverPtr driver = domain->conn->privateData;
+virDomainObjPtr vm;
+int ret = -1;
+
+if (!(vm = qemuDomObjFromDomain(domain)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
+goto cleanup;
+
+if (vm->def->sev) {
+if (qemuDomainGetSEVMeasurement(driver, vm, params, nparams, flags) < 
0)
+goto cleanup;
+}
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 static virHypervisorDriver qemuHypervisorDriver = {
 .name = QEMU_DRIVER_NAME,
 .connectURIProbe = qemuConnectURIProbe,
@@ -21729,6 +21797,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
 .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
 .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 
*/
 .nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
+.domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.5.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index fd6bce9..6e0cdca 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4297,3 +4297,11 @@ qemuMonitorBlockdevDel(qemuMonitorPtr mon,
 
 return qemuMonitorJSONBlockdevDel(mon, nodename);
 }
+
+char *
+qemuMonitorGetSEVMeasurement(qemuMonitorPtr mon)
+{
+QEMU_CHECK_MONITOR_NULL(mon);
+
+return qemuMonitorJSONGetSEVMeasurement(mon);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 75d5d98..7432997 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1142,4 +1142,7 @@ int qemuMonitorBlockdevAdd(qemuMonitorPtr mon,
 int qemuMonitorBlockdevDel(qemuMonitorPtr mon,
const char *nodename);
 
+char *
+qemuMonitorGetSEVMeasurement(qemuMonitorPtr mon);
+
 #endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ba0da9a..c5480a2 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -7994,3 +7994,45 @@ qemuMonitorJSONBlockdevDel(qemuMonitorPtr mon,
 virJSONValueFree(reply);
 return ret;
 }
+
+/**
+ * The function is used to retrieve the measurement of a SEV guest.
+ * The measurement is signature of the memory contents that was encrypted
+ * through the SEV launch flow.
+ *
+ * A example JSON output:
+ *
+ * { "execute" : "query-sev-launch-measure" }
+ * { "return" : { "data" : "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
+ */
+char *
+qemuMonitorJSONGetSEVMeasurement(qemuMonitorPtr mon)
+{
+const char *tmp;
+char *measurement = NULL;
+virJSONValuePtr cmd;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr data;
+
+if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NUL

[libvirt] [PATCH v9 09/11] libvirt: Introduce virDomainGetLaunchSecurityInfo public API

2018-06-08 Thread Brijesh Singh
The API can be used outside the libvirt to get the launch security
information. When SEV is enabled, the API can be used to get the
measurement of the launch process.

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 include/libvirt/libvirt-domain.h | 17 ++
 src/driver-hypervisor.h  |  8 +++
 src/libvirt-domain.c | 48 
 src/libvirt_public.syms  |  1 +
 4 files changed, 74 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index da773b7..3ef7c24 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4767,4 +4767,21 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 unsigned int action,
 unsigned int flags);
 
+/**
+ * Launch Security API
+ */
+
+/**
+ * VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT:
+ *
+ * Macro represents the launch measurement of the SEV guest,
+ * as VIR_TYPED_PARAM_STRING.
+ */
+# define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement"
+
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags);
+
 #endif /* __VIR_LIBVIRT_DOMAIN_H__ */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index c50d2a0..eef31eb 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1315,6 +1315,13 @@ typedef int
 int *nparams,
 unsigned int flags);
 
+typedef int
+(*virDrvDomainGetLaunchSecurityInfo)(virDomainPtr domain,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags);
+
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
 
@@ -1564,6 +1571,7 @@ struct _virHypervisorDriver {
 virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU;
 virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
 virDrvNodeGetSEVInfo nodeGetSEVInfo;
+virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
 };
 
 
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index d44b553..dcfc7d4 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12154,3 +12154,51 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 virDispatchError(domain->conn);
 return -1;
 }
+
+/**
+ * virDomainGetLaunchSecurityInfo:
+ * @domain: a domain object
+ * @params: where to store security info
+ * @nparams: number of items in @params
+ * @flags: currently used, set to 0.
+ *
+ * Get the launch security info. In case of the SEV guest, this will
+ * return the launch measurement.
+ *
+ * Returns -1 in case of failure, 0 in case of success.
+ */
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+virConnectPtr conn = domain->conn;
+
+VIR_DOMAIN_DEBUG(domain, "params=%p, nparams=%p flags=0x%x",
+ params, nparams, flags);
+
+virResetLastError();
+
+virCheckDomainReturn(domain, -1);
+virCheckNonNullArgGoto(params, error);
+virCheckNonNullArgGoto(nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->domainGetLaunchSecurityInfo) {
+int ret;
+ret = conn->driver->domainGetLaunchSecurityInfo(domain, params,
+nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+virReportUnsupportedError();
+
+ error:
+virDispatchError(domain->conn);
+return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 524d5fd..3bf3c3f 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -797,6 +797,7 @@ LIBVIRT_4.5.0 {
 virGetLastErrorCode;
 virGetLastErrorDomain;
 virNodeGetSEVInfo;
+virDomainGetLaunchSecurityInfo;
 } LIBVIRT_4.4.0;
 
 #  define new API here using predicted next version number 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v9 08/11] qemu: add support to launch SEV guest

2018-06-08 Thread Brijesh Singh
QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted
VMs on AMD platform using SEV feature. The various inputs required to
launch SEV guest is provided through the  tag. A typical
SEV guest launch command line looks like this:

# $QEMU ...\
  -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
  -machine memory-encryption=sev0 \

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 src/qemu/qemu_command.c | 41 
 src/qemu/qemu_process.c | 62 +
 tests/qemuxml2argvdata/launch-security-sev.args | 29 
 tests/qemuxml2argvdata/launch-security-sev.xml  | 37 +++
 tests/qemuxml2argvtest.c|  4 ++
 5 files changed, 173 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.args
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.xml

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index bd54d17..6a95344 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7287,6 +7287,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
 qemuAppendLoadparmMachineParm(&buf, def);
 
+if (def->sev)
+virBufferAddLit(&buf, ",memory-encryption=sev0");
+
 virCommandAddArgBuffer(cmd, &buf);
 
 ret = 0;
@@ -9687,6 +9690,41 @@ qemuBuildTPMCommandLine(virCommandPtr cmd,
 return 0;
 }
 
+static int
+qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
+virDomainSevDefPtr sev)
+{
+virBuffer obj = VIR_BUFFER_INITIALIZER;
+qemuDomainObjPrivatePtr priv = vm->privateData;
+char *path = NULL;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
+  sev->policy, sev->cbitpos, sev->reduced_phys_bits);
+
+virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
+virBufferAsprintf(&obj, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
+virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
+
+if (sev->dh_cert) {
+if (virAsprintf(&path, "%s/dh_cert.base64", priv->libDir) < 0)
+return -1;
+virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
+VIR_FREE(path);
+}
+
+if (sev->session) {
+if (virAsprintf(&path, "%s/session.base64", priv->libDir) < 0)
+return -1;
+virBufferAsprintf(&obj, ",session-file=%s", path);
+VIR_FREE(path);
+}
+
+virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), NULL);
+return 0;
+}
 
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
@@ -10283,6 +10321,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
 if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
 goto error;
 
+if (qemuBuildSevCommandLine(vm, cmd, def->sev) < 0)
+goto error;
+
 if (snapshot)
 virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1606f4c..480bc8c 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5826,6 +5826,65 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
 
 
 static int
+qemuBuildSevCreateFile(const char *configDir,
+   const char *name,
+   const char *data)
+{
+char *configFile;
+
+if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
+return -1;
+
+if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+virReportSystemError(errno, _("failed to write data to config '%s'"),
+ configFile);
+goto error;
+}
+
+VIR_FREE(configFile);
+return 0;
+
+ error:
+VIR_FREE(configFile);
+return -1;
+}
+
+
+static int
+qemuProcessPrepareSevGuestInput(virDomainObjPtr vm)
+{
+qemuDomainObjPrivatePtr priv = vm->privateData;
+virDomainDefPtr def = vm->def;
+virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+virDomainSevDefPtr sev = def->sev;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("Prepare SEV guest");
+
+if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+_("Domain %s asked for 'sev' launch but this "
+  "QEMU does not support SEV feature"), vm->def->name);
+return -1;
+}
+
+if (sev->dh_cert) {
+if (qemuBuildSevCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
+return -1;
+}
+
+if (se

[libvirt] [PATCH v9 06/11] conf: introduce launch-security element in domain

2018-06-08 Thread Brijesh Singh
The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 docs/formatdomain.html.in  | 115 ++
 docs/schemas/domaincommon.rng  |  37 ++
 src/conf/domain_conf.c | 133 +
 src/conf/domain_conf.h |  27 +
 tests/genericxml2xmlindata/launch-security-sev.xml |  24 
 tests/genericxml2xmltest.c |   2 +
 6 files changed, 338 insertions(+)
 create mode 100644 tests/genericxml2xmlindata/launch-security-sev.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 6912762..77845fe 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8458,6 +8458,121 @@ qemu-kvm -net nic,model=? /dev/null
 
 Note: DEA/TDEA is synonymous with DES/TDES.
 
+Secure Encrypted Virtualization (SEV)
+
+
+   The contents of the <launch-security type='sev'> 
element
+   is used to provide the guest owners input used for creating an encrypted
+   VM using the AMD SEV feature.
+
+   SEV is an extension to the AMD-V architecture which supports running
+   encrypted virtual machine (VMs) under the control of KVM. Encrypted
+   VMs have their pages (code and data) secured such that only the guest
+   itself has access to the unencrypted version. Each encrypted VM is
+   associated with a unique encryption key; if its data is accessed to a
+   different entity using a different key the encrypted guests data will
+   be incorrectly decrypted, leading to unintelligible data.
+
+   For more information see various input parameters and its format see 
the SEV API spec
+   https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";> 
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf 
+   Since 4.4.0
+   
+
+<domain>
+  ...
+  <launch-security type='sev'>
+<policy> 0x0001 </policy>
+<cbitpos> 47 </cbitpos>
+<reduced-phys-bits> 1 </reduced-phys-bits>
+<session> AAACCCDD=FFFCCCDSDS </session>
+<dh-cert> RBBBSDDD=FDDCCCDDDG </dh>
+  </sev>
+  ...
+</domain>
+
+
+
+  cbitpos
+  The required cbitpos element provides the C-bit (aka 
encryption bit)
+  location in guest page table entry. The value of cbitpos is
+  hypervisor dependent and can be obtained through the sev 
element
+  from the domain capabilities.
+  
+  reduced-phys-bits
+  The required reduced-phys-bits element provides the 
physical
+  address bit reducation. Similar to cbitpos the value of 

+  reduced-phys-bit is hypervisor dependent and can be obtained
+  through the sev element from the domain capabilities.
+  
+  policy
+  The required policy element provides the guest policy
+  which must be maintained by the SEV firmware. This policy is enforced by
+  the firmware and restricts what configuration and operational commands
+  can be performed on this guest by the hypervisor. The guest policy
+  provided during guest launch is bound to the guest and cannot be changed
+  throughout the lifetime of the guest. The policy is also transmitted
+  during snapshot and migration flows and enforced on the destination 
platform.
+
+  The guest policy is a 4 unsigned byte with the fields shown in Table:
+
+  
+
+   Bit(s) 
+   Description 
+
+
+   0 
+   Debugging of the guest is disallowed when set 
+
+
+   1 
+   Sharing keys with other guests is disallowed when set 
+
+
+   2 
+   SEV-ES is required when set
+
+
+   3 
+   Sending the guest to another platform is disallowed when 
set
+
+
+   4 
+   The guest must not be transmitted to another platform that is
+   not in the domain when set. 
+
+
+   5 
+   The guest must not be transmitted to another platform that is
+   not SEV capable when set. 
+
+
+   6:15 
+   reserved 
+
+ 

[libvirt] [PATCH v9 05/11] qemu: Implement the driver backend for virNodeGetSEVInfo()

2018-06-08 Thread Brijesh Singh
Signed-off-by: Brijesh Singh <>
---
 src/qemu/qemu_capabilities.c |  7 
 src/qemu/qemu_capabilities.h |  4 +++
 src/qemu/qemu_driver.c   | 82 
 3 files changed, 93 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 1803ed9..7a245a5 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -2094,6 +2094,13 @@ virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+virSEVCapabilityPtr
+virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps)
+{
+return qemuCaps->sevCapabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
 qemuMonitorPtr mon)
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index f80da91..3519a19 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -618,4 +618,8 @@ bool virQEMUCapsGuestIsNative(virArch host,
 
 bool virQEMUCapsCPUFilterFeatures(const char *name,
   void *opaque);
+
+virSEVCapabilityPtr
+virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps);
+
 #endif /* __QEMU_CAPABILITIES_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 2876987..264c47d 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21424,6 +21424,87 @@ qemuDomainSetLifecycleAction(virDomainPtr dom,
 }
 
 
+static int
+qemuGetSEVInfoToParams(virQEMUCapsPtr qemuCaps,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+int maxpar = 0;
+int n = 0;
+virSEVCapabilityPtr sev = virQEMUCapsGetSEVCapabilities(qemuCaps);
+virTypedParameterPtr sevParams = NULL;
+
+virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (virTypedParamsAddString(&sevParams, &n, &maxpar,
+VIR_NODE_SEV_PDH, sev->pdh) < 0)
+return -1;
+
+if (virTypedParamsAddString(&sevParams, &n, &maxpar,
+VIR_NODE_SEV_CERT_CHAIN, sev->cert_chain) < 0)
+goto cleanup;
+
+if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
+VIR_NODE_SEV_CBITPOS, sev->cbitpos) < 0)
+goto cleanup;
+
+if (virTypedParamsAddUInt(&sevParams, &n, &maxpar,
+VIR_NODE_SEV_REDUCED_PHYS_BITS,
+sev->reduced_phys_bits) < 0)
+goto cleanup;
+
+VIR_STEAL_PTR(*params, sevParams);
+*nparams = n;
+return 0;
+
+ cleanup:
+virTypedParamsFree(sevParams, n);
+return -1;
+}
+
+
+static int
+qemuNodeGetSEVInfo(virConnectPtr conn,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+virQEMUDriverPtr driver = conn->privateData;
+virCapsPtr caps = NULL;
+virQEMUCapsPtr qemucaps = NULL;
+int ret = -1;
+
+if (virNodeGetSevInfoEnsureACL(conn) < 0)
+return ret;
+
+if (!(caps = virQEMUDriverGetCapabilities(driver, true)))
+return ret;
+
+qemucaps = virQEMUCapsCacheLookupByArch(driver->qemuCapsCache,
+virArchFromHost());
+if (!qemucaps)
+goto cleanup;
+
+if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_GUEST)) {
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+   _("QEMU does not support SEV guest"));
+goto cleanup;
+}
+
+if (qemuGetSEVInfoToParams(qemucaps, params, nparams, flags) < 0)
+goto cleanup;
+
+ret = 0;
+
+ cleanup:
+virObjectUnref(qemucaps);
+virObjectUnref(caps);
+
+return ret;
+}
+
+
 static virHypervisorDriver qemuHypervisorDriver = {
 .name = QEMU_DRIVER_NAME,
 .connectURIProbe = qemuConnectURIProbe,
@@ -21647,6 +21728,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
 .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
 .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
 .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 
*/
+.nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
 };
 
 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v9 04/11] remote: implement the remote protocol for virNodeGetSEVInfo()

2018-06-08 Thread Brijesh Singh
Add remote support for virNodeGetSEVInfo().

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 src/remote/remote_daemon_dispatch.c | 44 +
 src/remote/remote_driver.c  | 40 +
 src/remote/remote_protocol.x| 22 ++-
 src/remote_protocol-structs | 12 ++
 4 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index 81d0445..959367f 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -5001,6 +5001,50 @@ remoteDispatchDomainGetDiskErrors(virNetServerPtr server 
ATTRIBUTE_UNUSED,
 
 
 static int
+remoteDispatchNodeGetSevInfo(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client ATTRIBUTE_UNUSED,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ remote_node_get_sev_info_args *args,
+ remote_node_get_sev_info_ret *ret)
+{
+virTypedParameterPtr params = NULL;
+int nparams = 0;
+int rv = -1;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (virNodeGetSEVInfo(priv->conn, ¶ms, &nparams, args->flags) < 0)
+goto cleanup;
+
+if (nparams > REMOTE_NODE_SEV_INFO_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+goto cleanup;
+}
+
+
+if (virTypedParamsSerialize(params, nparams,
+(virTypedParameterRemotePtr *) 
&ret->params.params_val,
+&ret->params.params_len,
+args->flags) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0)
+virNetMessageSaveError(rerr);
+virTypedParamsFree(params, nparams);
+return rv;
+}
+
+
+static int
 remoteDispatchNodeGetMemoryParameters(virNetServerPtr server ATTRIBUTE_UNUSED,
   virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
   virNetMessagePtr msg ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index c22993c..8ac7264 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6775,6 +6775,45 @@ remoteNodeGetMemoryParameters(virConnectPtr conn,
 return rv;
 }
 
+
+static int
+remoteNodeGetSEVInfo(virConnectPtr conn,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags)
+{
+int rv = -1;
+remote_node_get_sev_info_args args;
+remote_node_get_sev_info_ret ret;
+struct private_data *priv = conn->privateData;
+
+remoteDriverLock(priv);
+
+args.flags = flags;
+
+memset(&ret, 0, sizeof(ret));
+if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_SEV_INFO,
+ (xdrproc_t) xdr_remote_node_get_sev_info_args, (char *) &args,
+ (xdrproc_t) xdr_remote_node_get_sev_info_ret, (char *) &ret) == 
-1)
+goto done;
+
+if (virTypedParamsDeserialize((virTypedParameterRemotePtr) 
ret.params.params_val,
+  ret.params.params_len,
+  REMOTE_NODE_SEV_INFO_MAX,
+  params,
+  nparams) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+xdr_free((xdrproc_t) xdr_remote_node_get_sev_info_ret, (char *) &ret);
+ done:
+remoteDriverUnlock(priv);
+return rv;
+}
+
+
 static int
 remoteNodeGetCPUMap(virConnectPtr conn,
 unsigned char **cpumap,
@@ -8451,6 +8490,7 @@ static virHypervisorDriver hypervisor_driver = {
 .domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */
 .connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 
*/
 .connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 
4.4.0 */
+.nodeGetSEVInfo = remoteNodeGetSEVInfo, /* 4.5.0 */
 };
 
 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index a0ab7e9..ec72afa 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -253,6 +253,9 @@ const REMOTE_DOMAIN_IP_ADDR_MAX = 2048;
 /* Upper limit on number of guest vcpu information entries */
 const REMOTE_DOMAIN_GUEST_VCPU_PARAMS_MAX = 64;
 
+/* Upper limit on number of SEV parameters */
+const REMOTE_NODE_SEV_INFO_MAX = 64;
+
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];
 
@

[libvirt] [PATCH v9 00/11] x86: Secure Encrypted Virtualization (AMD)

2018-06-08 Thread Brijesh Singh
This patch series provides support for launching an encrypted guest using
AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV feature
allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
that includes the following


...
  
 
 
  


If  is provided then we indicate that hypervisor is capable of launching
SEV guest. mgmt tool can call virNodeGetSEVCapabilities() to get the additional
informations like PDH and certificate chain etc.

2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in 
case
if guest owner wish to establish a secure connection with SEV firmware to
negotiate a key used for validating the measurement.

3. mgmt tool requests to start a guest calling virCreateXML(), passing \
VIR_DOMAIN_START_PAUSED. The xml would include


  47 
  1
  0x1

  (optional)
/* Guest owners Diffie-Hellman key */
/* Guest owners Session blob */


4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
args looks like this:

# $QEMU ..
-machine memory-encryption=sev0 \
-object sev-guest,id=sev0,dh-cert-file=

5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event

6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls \
virDomainGetLaunchSecretInfo() to retrieve the measurement of encrypted memory.

7. (optional) mgmt tool can provide the measurement value to guest owner, which 
can
validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
it resumes the guest otherwise it calls destroy() to kill the guest.

8. mgmt tool resumes the guest

TODO:
* SEV guest require to use DMA apis for the virtio devices. In order to use the 
DMA
apis the virtio devices must have this tag



It is a bit unclear to me where these changes need to go. Do we need to
modify the libvirt to automatically add these when SEV is enabled or
we ask mgmt tool to make sure that it creates XML with right tag to enable
the DMA APIs for virtio devices. I am looking for some suggestions.

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

SEV Firmware API spec is available at:
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Changes sicne v8:
* rename qemuGetSEVInfo -> qemuGetSEVInfoToParams
* use virQEMUCapsCacheLookupByArch to get qemuCaps

Change since v7:
* rename virNodeSEVCapability() -> virNodeSEVInfo()
* rebase the series

Changes since v6:
* add API to get SEV PDH and Certificate chain data
* drop virsh command changes. We can revisit this later when we have
  more visibility on setter.

Change since v5:
* drop the seperate test patch and merge the code with other patches.
* rename the xml from sev -> launch-security-sev
* make policy field mandatory
* address multiple feedback from previous reviews.

Changes since v4:
* add /dev/sev in shared device list

Changes since v3:
* rename QEMU_CAPS_SEV -> QEMU_CAPS_SEV_GUEST
* update caps_2.12.0.x86_64.replies to include query-sev-capabilities data

Changes since v2:
* make cbitpos, policy and reduced-phys-bits as unsigned int
* update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr *params
instead of virTypedParameterPtr params.

Changes since v1:
* rename  ->  for domain
* add more information about policy and other fields in domaincaps.html
* split the domain_conf support in two patches
* add virDomainGetLaunchInfo() to retrieve the SEV measurement
* extend virsh command to show the domain's launch security information
* add test cases to validate newly added  element
* fix issues reported with 'make check' and 'make syntax-check'

The complete git tree is available at:
https://github.com/codomania/libvirt/tree/v9

Brijesh Singh (11):
  qemu: provide support to query the SEV capability
  conf: expose SEV feature in domain capabilities
  libvirt: Introduce virNodeGetSEVInfo public API
  remote: implement the remote protocol for virNodeGetSEVInfo()
  qemu: Implement the driver backend for virNodeGetSEVInfo()
  conf: introduce launch-security element in domain
  qemu/cgroup: add /dev/sev in shared devices list
  qemu: add support to launch SEV guest
  libvirt: Introduce virDomainGetLaunchSecurityInfo public API
  remote: implement the remote protocol for launch security
  qemu: Implement the driver backend for virDomainGetLaunchSecurityInfo

 docs/drvqemu.html.in   |   3 +-
 docs/formatdomain.html.in  | 115 
 docs/formatdomaincaps.html.in  |  30 
 docs/schemas/domaincaps.rng|  14 ++
 docs/schemas/domaincommon.rng 

[libvirt] [PATCH v9 01/11] qemu: provide support to query the SEV capability

2018-06-08 Thread Brijesh Singh
QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 src/conf/domain_capabilities.c | 12 
 src/conf/domain_capabilities.h | 12 
 src/libvirt_private.syms   |  1 +
 src/qemu/qemu_capabilities.c   | 37 ++
 src/qemu/qemu_capabilities.h   |  4 +-
 src/qemu/qemu_capspriv.h   |  4 ++
 src/qemu/qemu_monitor.c| 10 +++
 src/qemu/qemu_monitor.h|  3 +
 src/qemu/qemu_monitor_json.c   | 79 ++
 src/qemu/qemu_monitor_json.h   |  3 +
 .../caps_2.12.0.x86_64.replies | 10 +++
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |  3 +-
 12 files changed, 176 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index c20358e..3589777 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -67,6 +67,18 @@ virDomainCapsStringValuesFree(virDomainCapsStringValuesPtr 
values)
 }
 
 
+void
+virSEVCapabilitiesFree(virSEVCapability *cap)
+{
+if (!cap)
+return;
+
+VIR_FREE(cap->pdh);
+VIR_FREE(cap->cert_chain);
+VIR_FREE(cap);
+}
+
+
 static void
 virDomainCapsDispose(void *obj)
 {
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index b0eb4aa..56c1903 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -137,6 +137,15 @@ struct _virDomainCapsCPU {
 virDomainCapsCPUModelsPtr custom;
 };
 
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+char *pdh;
+char *cert_chain;
+unsigned int cbitpos;
+unsigned int reduced_phys_bits;
+};
+
 struct _virDomainCaps {
 virObjectLockable parent;
 
@@ -202,4 +211,7 @@ int virDomainCapsEnumSet(virDomainCapsEnumPtr capsEnum,
 void virDomainCapsEnumClear(virDomainCapsEnumPtr capsEnum);
 
 char * virDomainCapsFormat(virDomainCapsPtr const caps);
+
+void
+virSEVCapabilitiesFree(virSEVCapability *capabilities);
 #endif /* __DOMAIN_CAPABILITIES_H__ */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 2245101..ea24f28 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -185,6 +185,7 @@ virDomainCapsEnumClear;
 virDomainCapsEnumSet;
 virDomainCapsFormat;
 virDomainCapsNew;
+virSEVCapabilitiesFree;
 
 
 # conf/domain_conf.h
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index a673709..8b3ffe1 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -497,6 +497,9 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
   "tpm-emulator",
   "mch",
   "mch.extended-tseg-mbytes",
+
+  /* 310 */
+  "sev-guest",
 );
 
 
@@ -563,6 +566,8 @@ struct _virQEMUCaps {
 size_t ngicCapabilities;
 virGICCapability *gicCapabilities;
 
+virSEVCapability *sevCapabilities;
+
 virQEMUCapsHostCPUData kvmCPU;
 virQEMUCapsHostCPUData tcgCPU;
 };
@@ -1135,6 +1140,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
 { "vmgenid", QEMU_CAPS_DEVICE_VMGENID },
 { "vhost-vsock-device", QEMU_CAPS_DEVICE_VHOST_VSOCK },
 { "mch", QEMU_CAPS_DEVICE_MCH },
+{ "sev-guest", QEMU_CAPS_SEV_GUEST },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
@@ -2078,6 +2084,16 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+  virSEVCapability *capabilities)
+{
+virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
+
+qemuCaps->sevCapabilities = capabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
 qemuMonitorPtr mon)
@@ -2665,6 +2681,21 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr 
qemuCaps,
 }
 
 
+static int
+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+   qemuMonitorPtr mon)
+{
+virSEVCapability *caps = NULL;
+
+if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+return -1;
+
+virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+return 0;
+}
+
+
 bool
 virQEMUCapsCPUFilterFeatures(const char *name,
  void *opaque)
@@ -4064,6 +4095,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
 virQEMUCapsClear(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW);
 }
 
+/* Probe for SEV capabilities */
+  

[libvirt] [PATCH] nwfilter: fix build error when pcap-config is not present

2018-06-07 Thread Brijesh Singh
The compilation fails with the following error when pcap-config
is not present on the host:

nwfilter/nwfilter_learnipaddr.c:824:1: error: conflicting types for 
'virNWFilterLearnIPAddress'
 virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver ATTRIBUTE_UNUSED,

 In file included from nwfilter/nwfilter_learnipaddr.c:57:0:
 nwfilter/nwfilter_learnipaddr.h:38:5: note: previous declaration of 
'virNWFilterLearnIPAddress' was here
  int virNWFilterLearnIPAddress(virNWFilterTechDriverPtr techdriver,

Signed-off-by: Brijesh Singh 
---
 src/nwfilter/nwfilter_learnipaddr.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/nwfilter/nwfilter_learnipaddr.c 
b/src/nwfilter/nwfilter_learnipaddr.c
index 52adc37..ce58f66 100644
--- a/src/nwfilter/nwfilter_learnipaddr.c
+++ b/src/nwfilter/nwfilter_learnipaddr.c
@@ -829,7 +829,7 @@ virNWFilterLearnIPAddress(virNWFilterTechDriverPtr 
techdriver ATTRIBUTE_UNUSED,
   const char *filtername ATTRIBUTE_UNUSED,
   virHashTablePtr filterparams ATTRIBUTE_UNUSED,
   virNWFilterDriverStatePtr driver ATTRIBUTE_UNUSED,
-  enum howDetect howDetect ATTRIBUTE_UNUSED)
+  int howDetect ATTRIBUTE_UNUSED)
 {
 virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
_("IP parameter must be given since libvirt "
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v8 09/11] libvirt: add new public API to get launch security info

2018-06-07 Thread Brijesh Singh




On 06/07/2018 11:46 AM, Erik Skultety wrote:

Better commit subject would be:
libvirt: Introduce virDomainGetLaunchSecurityInfo public API

On Wed, Jun 06, 2018 at 12:50:15PM -0500, Brijesh Singh wrote:

The API can be used outside the libvirt to get the launch security
information. When SEV is enabled, the API can be used to get the
measurement of the launch process.

Signed-off-by: Brijesh Singh 
---
  include/libvirt/libvirt-domain.h | 17 ++
  src/driver-hypervisor.h  |  8 +++
  src/libvirt-domain.c | 48 
  src/libvirt_public.syms  |  1 +
  4 files changed, 74 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index da773b7..6a3d73f 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4767,4 +4767,21 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
  unsigned int action,
  unsigned int flags);

+/**
+ * Launch Security API
+ */
+
+/**
+ * VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT:
+ *
+ * Macro represents the launch measurement of the SEV guest,
+ * as VIR_TYPED_PARAM_STRING.
+ */
+#define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement"


^recurring, s/#define/# define/ otherwise fails the syntax-check...



I did ran through syntax-check but don't remember getting complain. I 
will fix in next rev.





With that:
Reviewed-by: Erik Skultety 



--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v8 05/11] qemu: Add support to get the SEV info

2018-06-07 Thread Brijesh Singh




On 06/07/2018 11:37 AM, Erik Skultety wrote:

more verbose commit subject:
qemu: Implement the driver backend for virNodeGetSEVInfo

On Wed, Jun 06, 2018 at 12:50:11PM -0500, Brijesh Singh wrote:

Signed-off-by: Brijesh Singh <>
---
  src/qemu/qemu_capabilities.c |  7 
  src/qemu/qemu_capabilities.h |  4 ++
  src/qemu/qemu_driver.c   | 91 
  3 files changed, 102 insertions(+)



...



+static int
+qemuGetSEVInfo(virQEMUCapsPtr qemuCaps,


qemuGetSEVInfoToParams would IMHO be a better (iow less confusing) name.



Agreed, its much better name.





+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+int maxpar = 0;
+virSEVCapabilityPtr sev = virQEMUCapsGetSEVCapabilities(qemuCaps);
+
+virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_NODE_SEV_PDH, sev->pdh) < 0)
+return -1;
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_NODE_SEV_CERT_CHAIN, sev->pdh) < 0)
+goto cleanup;
+
+if (virTypedParamsAddUInt(params, nparams, &maxpar,
+VIR_NODE_SEV_CBITPOS, sev->cbitpos) < 0)
+goto cleanup;
+
+if (virTypedParamsAddUInt(params, nparams, &maxpar,
+VIR_NODE_SEV_REDUCED_PHYS_BITS,
+sev->reduced_phys_bits) < 0)
+goto cleanup;
+
+return 0;
+
+ cleanup:
+return -1;


So ^this cleanup label is pretty much unnecessary. In order to avoid weird
errors, we usually create a local copy of the caller-provided argument - in this
case params - work on it the whole time and only once it's safe, we do a
VIR_STEAL_PTR to the original pointer, so we should do that here as well.




OK, will do so.



+}
+
+
+static int
+qemuNodeGetSEVInfo(virConnectPtr conn,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+virQEMUDriverPtr driver = conn->privateData;
+virCapsPtr caps = NULL;
+virQEMUCapsPtr qemucaps = NULL;
+virArch hostarch;
+virCapsDomainDataPtr capsdata;
+int ret = -1;
+
+if (virNodeGetSevInfoEnsureACL(conn) < 0)
+return ret;
+
+if (!(caps = virQEMUDriverGetCapabilities(driver, true)))
+return ret;
+
+hostarch = virArchFromHost();
+if (!(capsdata = virCapabilitiesDomainDataLookup(caps,
+VIR_DOMAIN_OSTYPE_HVM, hostarch, VIR_DOMAIN_VIRT_QEMU,
+NULL, NULL))) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Cannot find suitable emulator for %s"),
+   virArchToString(hostarch));
+goto UnrefCaps;
+}


If you use virQEMUCapsCacheLookupByArch below instead, we could drop ^this hunk
above, am I right?




Ah, I was looking through code to find out suitable APIs for this. 
thanks for suggestion, it seems like it will work for us in this case.





+
+qemucaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
+  capsdata->emulator);
+VIR_FREE(capsdata);


^this could be dropped...



If we use virQEMUCapsCacheLookupByArch() then we could drop this.



+if (!qemucaps)
+goto UnrefCaps;
+
+if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_GUEST)) {
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+   _("QEMU does not support SEV guest"));
+goto UnrefQemuCaps;
+}
+
+if (qemuGetSEVInfo(qemucaps, params, nparams, flags) < 0)
+goto UnrefQemuCaps;
+
+ret = 0;
+
+ UnrefQemuCaps:


s/UnrefQemuCaps/cleanup


+virObjectUnref(qemucaps);
+ UnrefCaps:
+virObjectUnref(caps);


..^this one too...

Erik



--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v8 11/11] qemu: Add support to launch security info

2018-06-06 Thread Brijesh Singh
This patch implements the internal driver API for launch event into
qemu driver. When SEV is enabled, execute 'query-sev-launch-measurement'
to get the measurement of memory encrypted through launch sequence.

Signed-off-by: Brijesh Singh 
---
 src/qemu/qemu_driver.c   | 69 
 src/qemu/qemu_monitor.c  |  8 +
 src/qemu/qemu_monitor.h  |  3 ++
 src/qemu/qemu_monitor_json.c | 42 +++
 src/qemu/qemu_monitor_json.h |  2 ++
 5 files changed, 124 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c289b21..c0785c9 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21527,6 +21527,74 @@ qemuNodeGetSEVInfo(virConnectPtr conn,
 }
 
 
+static int
+qemuDomainGetSEVMeasurement(virQEMUDriverPtr driver,
+virDomainObjPtr vm,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+int ret = -1;
+char *tmp;
+int maxpar = 0;
+
+virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+return -1;
+
+if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
+goto endjob;
+
+tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
+if (tmp == NULL)
+goto endjob;
+
+if (qemuDomainObjExitMonitor(driver, vm) < 0)
+goto endjob;
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
+tmp) < 0)
+goto endjob;
+
+VIR_FREE(tmp);
+ret = 0;
+
+ endjob:
+qemuDomainObjEndJob(driver, vm);
+return ret;
+}
+
+
+static int
+qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+virQEMUDriverPtr driver = domain->conn->privateData;
+virDomainObjPtr vm;
+int ret = -1;
+
+if (!(vm = qemuDomObjFromDomain(domain)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
+goto cleanup;
+
+if (vm->def->sev) {
+if (qemuDomainGetSEVMeasurement(driver, vm, params, nparams, flags) < 
0)
+goto cleanup;
+}
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 static virHypervisorDriver qemuHypervisorDriver = {
 .name = QEMU_DRIVER_NAME,
 .connectURIProbe = qemuConnectURIProbe,
@@ -21751,6 +21819,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
 .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
 .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 
*/
 .nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
+.domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.5.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index fd6bce9..6e0cdca 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4297,3 +4297,11 @@ qemuMonitorBlockdevDel(qemuMonitorPtr mon,
 
 return qemuMonitorJSONBlockdevDel(mon, nodename);
 }
+
+char *
+qemuMonitorGetSEVMeasurement(qemuMonitorPtr mon)
+{
+QEMU_CHECK_MONITOR_NULL(mon);
+
+return qemuMonitorJSONGetSEVMeasurement(mon);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 75d5d98..7432997 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1142,4 +1142,7 @@ int qemuMonitorBlockdevAdd(qemuMonitorPtr mon,
 int qemuMonitorBlockdevDel(qemuMonitorPtr mon,
const char *nodename);
 
+char *
+qemuMonitorGetSEVMeasurement(qemuMonitorPtr mon);
+
 #endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index ba0da9a..c5480a2 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -7994,3 +7994,45 @@ qemuMonitorJSONBlockdevDel(qemuMonitorPtr mon,
 virJSONValueFree(reply);
 return ret;
 }
+
+/**
+ * The function is used to retrieve the measurement of a SEV guest.
+ * The measurement is signature of the memory contents that was encrypted
+ * through the SEV launch flow.
+ *
+ * A example JSON output:
+ *
+ * { "execute" : "query-sev-launch-measure" }
+ * { "return" : { "data" : "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
+ */
+char *
+qemuMonitorJSONGetSEVMeasurement(qemuMonitorPtr mon)
+{
+const char *tmp;
+char *measurement = NULL;
+virJSONValuePtr cmd;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr data;
+
+if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NULL)))
+ return NULL;
+
+if 

[libvirt] [PATCH v8 07/11] qemu/cgroup: add /dev/sev in shared devices list

2018-06-06 Thread Brijesh Singh
QEMU uses /dev/sev device while creating the SEV guest, lets add /dev/sev
in the list of devices allowed to be accessed by the QEMU.

Signed-off-by: Brijesh Singh <>
Reviewed-by: Erik Skultety 
---
 docs/drvqemu.html.in   | 1 +
 src/qemu/qemu.conf | 2 +-
 src/qemu/qemu_cgroup.c | 2 +-
 src/qemu/test_libvirtd_qemu.aug.in | 1 +
 4 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/drvqemu.html.in b/docs/drvqemu.html.in
index cbd159d..7c33a18 100644
--- a/docs/drvqemu.html.in
+++ b/docs/drvqemu.html.in
@@ -397,6 +397,7 @@ chmod o+x /path/to/directory
 /dev/random, /dev/urandom,
 /dev/ptmx, /dev/kvm, /dev/kqemu,
 /dev/rtc, /dev/hpet, /dev/net/tun
+/dev/sev
 
 
 
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index c8e1a62..3a733b3 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -485,7 +485,7 @@
 #"/dev/null", "/dev/full", "/dev/zero",
 #"/dev/random", "/dev/urandom",
 #"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-#"/dev/rtc","/dev/hpet"
+#"/dev/rtc","/dev/hpet", "/dev/sev"
 #]
 #
 # RDMA migration requires the following extra files to be added to the list:
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 546a4c8..21dcb3c 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -47,7 +47,7 @@ const char *const defaultDeviceACL[] = {
 "/dev/null", "/dev/full", "/dev/zero",
 "/dev/random", "/dev/urandom",
 "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-"/dev/rtc", "/dev/hpet",
+"/dev/rtc", "/dev/hpet", "/dev/sev",
 NULL,
 };
 #define DEVICE_PTY_MAJOR 136
diff --git a/src/qemu/test_libvirtd_qemu.aug.in 
b/src/qemu/test_libvirtd_qemu.aug.in
index 912161c..f127726 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -62,6 +62,7 @@ module Test_libvirtd_qemu =
 { "8" = "/dev/kqemu" }
 { "9" = "/dev/rtc" }
 { "10" = "/dev/hpet" }
+{ "11" = "/dev/sev" }
 }
 { "save_image_format" = "raw" }
 { "dump_image_format" = "raw" }
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v8 06/11] conf: introduce launch-security element in domain

2018-06-06 Thread Brijesh Singh
The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Signed-off-by: Brijesh Singh 
---
 docs/formatdomain.html.in  | 115 ++
 docs/schemas/domaincommon.rng  |  37 ++
 src/conf/domain_conf.c | 133 +
 src/conf/domain_conf.h |  27 +
 tests/genericxml2xmlindata/launch-security-sev.xml |  24 
 tests/genericxml2xmltest.c |   2 +
 6 files changed, 338 insertions(+)
 create mode 100644 tests/genericxml2xmlindata/launch-security-sev.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 7f4de65..decd854 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8367,6 +8367,121 @@ qemu-kvm -net nic,model=? /dev/null
 
 Note: DEA/TDEA is synonymous with DES/TDES.
 
+Secure Encrypted Virtualization (SEV)
+
+
+   The contents of the <launch-security type='sev'> 
element
+   is used to provide the guest owners input used for creating an encrypted
+   VM using the AMD SEV feature.
+
+   SEV is an extension to the AMD-V architecture which supports running
+   encrypted virtual machine (VMs) under the control of KVM. Encrypted
+   VMs have their pages (code and data) secured such that only the guest
+   itself has access to the unencrypted version. Each encrypted VM is
+   associated with a unique encryption key; if its data is accessed to a
+   different entity using a different key the encrypted guests data will
+   be incorrectly decrypted, leading to unintelligible data.
+
+   For more information see various input parameters and its format see 
the SEV API spec
+   https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";> 
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf 
+   Since 4.4.0
+   
+
+<domain>
+  ...
+  <launch-security type='sev'>
+<policy> 0x0001 </policy>
+<cbitpos> 47 </cbitpos>
+<reduced-phys-bits> 1 </reduced-phys-bits>
+<session> AAACCCDD=FFFCCCDSDS </session>
+<dh-cert> RBBBSDDD=FDDCCCDDDG </dh>
+  </sev>
+  ...
+</domain>
+
+
+
+  cbitpos
+  The required cbitpos element provides the C-bit (aka 
encryption bit)
+  location in guest page table entry. The value of cbitpos is
+  hypervisor dependent and can be obtained through the sev 
element
+  from the domain capabilities.
+  
+  reduced-phys-bits
+  The required reduced-phys-bits element provides the 
physical
+  address bit reducation. Similar to cbitpos the value of 

+  reduced-phys-bit is hypervisor dependent and can be obtained
+  through the sev element from the domain capabilities.
+  
+  policy
+  The required policy element provides the guest policy
+  which must be maintained by the SEV firmware. This policy is enforced by
+  the firmware and restricts what configuration and operational commands
+  can be performed on this guest by the hypervisor. The guest policy
+  provided during guest launch is bound to the guest and cannot be changed
+  throughout the lifetime of the guest. The policy is also transmitted
+  during snapshot and migration flows and enforced on the destination 
platform.
+
+  The guest policy is a 4 unsigned byte with the fields shown in Table:
+
+  
+
+   Bit(s) 
+   Description 
+
+
+   0 
+   Debugging of the guest is disallowed when set 
+
+
+   1 
+   Sharing keys with other guests is disallowed when set 
+
+
+   2 
+   SEV-ES is required when set
+
+
+   3 
+   Sending the guest to another platform is disallowed when 
set
+
+
+   4 
+   The guest must not be transmitted to another platform that is
+   not in the domain when set. 
+
+
+   5 
+   The guest must not be transmitted to another platform that is
+   not SEV capable when set. 
+
+
+   6:15 
+   reserved 
+
+
+   16:32 
+   The guest must no

[libvirt] [PATCH v8 10/11] remote: implement the remote protocol for launch security

2018-06-06 Thread Brijesh Singh
Add remote support for launch security info.

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 src/remote/remote_daemon_dispatch.c | 47 +
 src/remote/remote_driver.c  | 40 +++
 src/remote/remote_protocol.x| 19 ++-
 src/remote_protocol-structs | 11 +
 4 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index 959367f..f1a5ba2 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -3110,6 +3110,53 @@ remoteDispatchNodeGetMemoryStats(virNetServerPtr server 
ATTRIBUTE_UNUSED,
 }
 
 static int
+remoteDispatchDomainGetLaunchSecurityInfo(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+  virNetMessagePtr msg 
ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  
remote_domain_get_launch_security_info_args *args,
+  
remote_domain_get_launch_security_info_ret *ret)
+{
+virDomainPtr dom = NULL;
+virTypedParameterPtr params = NULL;
+int nparams = 0;
+int rv = -1;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, args->flags) < 
0)
+goto cleanup;
+
+if (nparams > REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+goto cleanup;
+}
+
+if (virTypedParamsSerialize(params, nparams,
+(virTypedParameterRemotePtr *) 
&ret->params.params_val,
+&ret->params.params_len,
+args->flags) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0)
+virNetMessageSaveError(rerr);
+virTypedParamsFree(params, nparams);
+virObjectUnref(dom);
+return rv;
+}
+
+static int
 remoteDispatchDomainGetPerfEvents(virNetServerPtr server ATTRIBUTE_UNUSED,
   virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
   virNetMessagePtr msg ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 8ac7264..995d440 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1966,6 +1966,45 @@ remoteDomainGetNumaParameters(virDomainPtr domain,
 }
 
 static int
+remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags)
+{
+int rv = -1;
+remote_domain_get_launch_security_info_args args;
+remote_domain_get_launch_security_info_ret ret;
+struct private_data *priv = domain->conn->privateData;
+
+remoteDriverLock(priv);
+
+make_nonnull_domain(&args.dom, domain);
+args.flags = flags;
+
+memset(&ret, 0, sizeof(ret));
+if (call(domain->conn, priv, 0, 
REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_args, 
(char *) &args,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_ret, (char 
*) &ret) == -1)
+goto done;
+
+if (virTypedParamsDeserialize((virTypedParameterRemotePtr) 
ret.params.params_val,
+  ret.params.params_len,
+  
REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX,
+  params,
+  nparams) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+xdr_free((xdrproc_t) xdr_remote_domain_get_launch_security_info_ret,
+ (char *) &ret);
+ done:
+remoteDriverUnlock(priv);
+return rv;
+}
+
+static int
 remoteDomainGetPerfEvents(virDomainPtr domain,
   virTypedParameterPtr *params,
   int *nparams,
@@ -8491,6 +8530,7 @@ static virHypervisorDriver hypervisor_driver = {
 .connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 
*/
 .connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 
4.4.0 */
 .nodeGetSEVInfo = remoteNodeGetSEVInfo, /* 4.5.0 */
+.domainGetLaunchSecurityInfo = remoteDomainGetLaunchSecurityInfo /* 4.5.0 
*/
 };
 
 static virNetworkDriver netw

[libvirt] [PATCH v8 09/11] libvirt: add new public API to get launch security info

2018-06-06 Thread Brijesh Singh
The API can be used outside the libvirt to get the launch security
information. When SEV is enabled, the API can be used to get the
measurement of the launch process.

Signed-off-by: Brijesh Singh 
---
 include/libvirt/libvirt-domain.h | 17 ++
 src/driver-hypervisor.h  |  8 +++
 src/libvirt-domain.c | 48 
 src/libvirt_public.syms  |  1 +
 4 files changed, 74 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index da773b7..6a3d73f 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4767,4 +4767,21 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 unsigned int action,
 unsigned int flags);
 
+/**
+ * Launch Security API
+ */
+
+/**
+ * VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT:
+ *
+ * Macro represents the launch measurement of the SEV guest,
+ * as VIR_TYPED_PARAM_STRING.
+ */
+#define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement"
+
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags);
+
 #endif /* __VIR_LIBVIRT_DOMAIN_H__ */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index c50d2a0..eef31eb 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1315,6 +1315,13 @@ typedef int
 int *nparams,
 unsigned int flags);
 
+typedef int
+(*virDrvDomainGetLaunchSecurityInfo)(virDomainPtr domain,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags);
+
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
 
@@ -1564,6 +1571,7 @@ struct _virHypervisorDriver {
 virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU;
 virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
 virDrvNodeGetSEVInfo nodeGetSEVInfo;
+virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
 };
 
 
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index d44b553..dcfc7d4 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12154,3 +12154,51 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 virDispatchError(domain->conn);
 return -1;
 }
+
+/**
+ * virDomainGetLaunchSecurityInfo:
+ * @domain: a domain object
+ * @params: where to store security info
+ * @nparams: number of items in @params
+ * @flags: currently used, set to 0.
+ *
+ * Get the launch security info. In case of the SEV guest, this will
+ * return the launch measurement.
+ *
+ * Returns -1 in case of failure, 0 in case of success.
+ */
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+virConnectPtr conn = domain->conn;
+
+VIR_DOMAIN_DEBUG(domain, "params=%p, nparams=%p flags=0x%x",
+ params, nparams, flags);
+
+virResetLastError();
+
+virCheckDomainReturn(domain, -1);
+virCheckNonNullArgGoto(params, error);
+virCheckNonNullArgGoto(nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->domainGetLaunchSecurityInfo) {
+int ret;
+ret = conn->driver->domainGetLaunchSecurityInfo(domain, params,
+nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+virReportUnsupportedError();
+
+ error:
+virDispatchError(domain->conn);
+return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 524d5fd..3bf3c3f 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -797,6 +797,7 @@ LIBVIRT_4.5.0 {
 virGetLastErrorCode;
 virGetLastErrorDomain;
 virNodeGetSEVInfo;
+virDomainGetLaunchSecurityInfo;
 } LIBVIRT_4.4.0;
 
 #  define new API here using predicted next version number 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v8 05/11] qemu: Add support to get the SEV info

2018-06-06 Thread Brijesh Singh
Signed-off-by: Brijesh Singh <>
---
 src/qemu/qemu_capabilities.c |  7 
 src/qemu/qemu_capabilities.h |  4 ++
 src/qemu/qemu_driver.c   | 91 
 3 files changed, 102 insertions(+)

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index a2103e3..2b82da2 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -2081,6 +2081,13 @@ virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+virSEVCapabilityPtr
+virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps)
+{
+return qemuCaps->sevCapabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
 qemuMonitorPtr mon)
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 7390271..463d7d4 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -616,4 +616,8 @@ bool virQEMUCapsGuestIsNative(virArch host,
 
 bool virQEMUCapsCPUFilterFeatures(const char *name,
   void *opaque);
+
+virSEVCapabilityPtr
+virQEMUCapsGetSEVCapabilities(virQEMUCapsPtr qemuCaps);
+
 #endif /* __QEMU_CAPABILITIES_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 38ea865..c289b21 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21437,6 +21437,96 @@ qemuDomainSetLifecycleAction(virDomainPtr dom,
 }
 
 
+static int
+qemuGetSEVInfo(virQEMUCapsPtr qemuCaps,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+int maxpar = 0;
+virSEVCapabilityPtr sev = virQEMUCapsGetSEVCapabilities(qemuCaps);
+
+virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_NODE_SEV_PDH, sev->pdh) < 0)
+return -1;
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_NODE_SEV_CERT_CHAIN, sev->pdh) < 0)
+goto cleanup;
+
+if (virTypedParamsAddUInt(params, nparams, &maxpar,
+VIR_NODE_SEV_CBITPOS, sev->cbitpos) < 0)
+goto cleanup;
+
+if (virTypedParamsAddUInt(params, nparams, &maxpar,
+VIR_NODE_SEV_REDUCED_PHYS_BITS,
+sev->reduced_phys_bits) < 0)
+goto cleanup;
+
+return 0;
+
+ cleanup:
+return -1;
+}
+
+
+static int
+qemuNodeGetSEVInfo(virConnectPtr conn,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+virQEMUDriverPtr driver = conn->privateData;
+virCapsPtr caps = NULL;
+virQEMUCapsPtr qemucaps = NULL;
+virArch hostarch;
+virCapsDomainDataPtr capsdata;
+int ret = -1;
+
+if (virNodeGetSevInfoEnsureACL(conn) < 0)
+return ret;
+
+if (!(caps = virQEMUDriverGetCapabilities(driver, true)))
+return ret;
+
+hostarch = virArchFromHost();
+if (!(capsdata = virCapabilitiesDomainDataLookup(caps,
+VIR_DOMAIN_OSTYPE_HVM, hostarch, VIR_DOMAIN_VIRT_QEMU,
+NULL, NULL))) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+   _("Cannot find suitable emulator for %s"),
+   virArchToString(hostarch));
+goto UnrefCaps;
+}
+
+qemucaps = virQEMUCapsCacheLookup(driver->qemuCapsCache,
+  capsdata->emulator);
+VIR_FREE(capsdata);
+if (!qemucaps)
+goto UnrefCaps;
+
+if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_GUEST)) {
+virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+   _("QEMU does not support SEV guest"));
+goto UnrefQemuCaps;
+}
+
+if (qemuGetSEVInfo(qemucaps, params, nparams, flags) < 0)
+goto UnrefQemuCaps;
+
+ret = 0;
+
+ UnrefQemuCaps:
+virObjectUnref(qemucaps);
+ UnrefCaps:
+virObjectUnref(caps);
+
+return ret;
+}
+
+
 static virHypervisorDriver qemuHypervisorDriver = {
 .name = QEMU_DRIVER_NAME,
 .connectURIProbe = qemuConnectURIProbe,
@@ -21660,6 +21750,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
 .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
 .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
 .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 
*/
+.nodeGetSEVInfo = qemuNodeGetSEVInfo, /* 4.5.0 */
 };
 
 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v8 08/11] qemu: add support to launch SEV guest

2018-06-06 Thread Brijesh Singh
QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted
VMs on AMD platform using SEV feature. The various inputs required to
launch SEV guest is provided through the  tag. A typical
SEV guest launch command line looks like this:

# $QEMU ...\
  -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
  -machine memory-encryption=sev0 \

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 src/qemu/qemu_command.c | 41 
 src/qemu/qemu_process.c | 62 +
 tests/qemuxml2argvdata/launch-security-sev.args | 29 
 tests/qemuxml2argvdata/launch-security-sev.xml  | 37 +++
 tests/qemuxml2argvtest.c|  4 ++
 5 files changed, 173 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.args
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.xml

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 1324c67..6ffdf63 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7295,6 +7295,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
 qemuAppendLoadparmMachineParm(&buf, def);
 
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) && def->sev)
+virBufferAddLit(&buf, ",memory-encryption=sev0");
+
 virCommandAddArgBuffer(cmd, &buf);
 
 ret = 0;
@@ -9651,6 +9654,41 @@ qemuBuildTPMCommandLine(virCommandPtr cmd,
 return 0;
 }
 
+static int
+qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
+virDomainSevDefPtr sev)
+{
+virBuffer obj = VIR_BUFFER_INITIALIZER;
+qemuDomainObjPrivatePtr priv = vm->privateData;
+char *path = NULL;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
+  sev->policy, sev->cbitpos, sev->reduced_phys_bits);
+
+virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
+virBufferAsprintf(&obj, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
+virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
+
+if (sev->dh_cert) {
+if (virAsprintf(&path, "%s/dh_cert.base64", priv->libDir) < 0)
+return -1;
+virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
+VIR_FREE(path);
+}
+
+if (sev->session) {
+if (virAsprintf(&path, "%s/session.base64", priv->libDir) < 0)
+return -1;
+virBufferAsprintf(&obj, ",session-file=%s", path);
+VIR_FREE(path);
+}
+
+virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), NULL);
+return 0;
+}
 
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
@@ -10245,6 +10283,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
 if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
 goto error;
 
+if (qemuBuildSevCommandLine(vm, cmd, def->sev) < 0)
+goto error;
+
 if (snapshot)
 virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 9eb3ea0..5783627 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5825,6 +5825,65 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
 
 
 static int
+qemuBuildSevCreateFile(const char *configDir,
+   const char *name,
+   const char *data)
+{
+char *configFile;
+
+if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
+return -1;
+
+if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+virReportSystemError(errno, _("failed to write data to config '%s'"),
+ configFile);
+goto error;
+}
+
+VIR_FREE(configFile);
+return 0;
+
+ error:
+VIR_FREE(configFile);
+return -1;
+}
+
+
+static int
+qemuProcessPrepareSevGuestInput(virDomainObjPtr vm)
+{
+qemuDomainObjPrivatePtr priv = vm->privateData;
+virDomainDefPtr def = vm->def;
+virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+virDomainSevDefPtr sev = def->sev;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("Prepare SEV guest");
+
+if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+_("Domain %s asked for 'sev' launch but this "
+  "QEMU does not support SEV feature"), vm->def->name);
+return -1;
+}
+
+if (sev->dh_cert) {
+if (qemuBuildSevCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
+ 

[libvirt] [PATCH v8 04/11] remote: implement the remote protocol for virNodeSEVInfo()

2018-06-06 Thread Brijesh Singh
Add remote support for virNodeSEVInfo().

Signed-off-by: Brijesh Singh <>
---
 src/remote/remote_daemon_dispatch.c | 44 +
 src/remote/remote_driver.c  | 40 +
 src/remote/remote_protocol.x| 22 ++-
 src/remote_protocol-structs | 13 +++
 4 files changed, 118 insertions(+), 1 deletion(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index 81d0445..959367f 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -5001,6 +5001,50 @@ remoteDispatchDomainGetDiskErrors(virNetServerPtr server 
ATTRIBUTE_UNUSED,
 
 
 static int
+remoteDispatchNodeGetSevInfo(virNetServerPtr server ATTRIBUTE_UNUSED,
+ virNetServerClientPtr client ATTRIBUTE_UNUSED,
+ virNetMessagePtr msg ATTRIBUTE_UNUSED,
+ virNetMessageErrorPtr rerr,
+ remote_node_get_sev_info_args *args,
+ remote_node_get_sev_info_ret *ret)
+{
+virTypedParameterPtr params = NULL;
+int nparams = 0;
+int rv = -1;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (virNodeGetSEVInfo(priv->conn, ¶ms, &nparams, args->flags) < 0)
+goto cleanup;
+
+if (nparams > REMOTE_NODE_SEV_INFO_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+goto cleanup;
+}
+
+
+if (virTypedParamsSerialize(params, nparams,
+(virTypedParameterRemotePtr *) 
&ret->params.params_val,
+&ret->params.params_len,
+args->flags) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0)
+virNetMessageSaveError(rerr);
+virTypedParamsFree(params, nparams);
+return rv;
+}
+
+
+static int
 remoteDispatchNodeGetMemoryParameters(virNetServerPtr server ATTRIBUTE_UNUSED,
   virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
   virNetMessagePtr msg ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index c22993c..8ac7264 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -6775,6 +6775,45 @@ remoteNodeGetMemoryParameters(virConnectPtr conn,
 return rv;
 }
 
+
+static int
+remoteNodeGetSEVInfo(virConnectPtr conn,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags)
+{
+int rv = -1;
+remote_node_get_sev_info_args args;
+remote_node_get_sev_info_ret ret;
+struct private_data *priv = conn->privateData;
+
+remoteDriverLock(priv);
+
+args.flags = flags;
+
+memset(&ret, 0, sizeof(ret));
+if (call(conn, priv, 0, REMOTE_PROC_NODE_GET_SEV_INFO,
+ (xdrproc_t) xdr_remote_node_get_sev_info_args, (char *) &args,
+ (xdrproc_t) xdr_remote_node_get_sev_info_ret, (char *) &ret) == 
-1)
+goto done;
+
+if (virTypedParamsDeserialize((virTypedParameterRemotePtr) 
ret.params.params_val,
+  ret.params.params_len,
+  REMOTE_NODE_SEV_INFO_MAX,
+  params,
+  nparams) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+xdr_free((xdrproc_t) xdr_remote_node_get_sev_info_ret, (char *) &ret);
+ done:
+remoteDriverUnlock(priv);
+return rv;
+}
+
+
 static int
 remoteNodeGetCPUMap(virConnectPtr conn,
 unsigned char **cpumap,
@@ -8451,6 +8490,7 @@ static virHypervisorDriver hypervisor_driver = {
 .domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */
 .connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 
*/
 .connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 
4.4.0 */
+.nodeGetSEVInfo = remoteNodeGetSEVInfo, /* 4.5.0 */
 };
 
 static virNetworkDriver network_driver = {
diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x
index a0ab7e9..ec72afa 100644
--- a/src/remote/remote_protocol.x
+++ b/src/remote/remote_protocol.x
@@ -253,6 +253,9 @@ const REMOTE_DOMAIN_IP_ADDR_MAX = 2048;
 /* Upper limit on number of guest vcpu information entries */
 const REMOTE_DOMAIN_GUEST_VCPU_PARAMS_MAX = 64;
 
+/* Upper limit on number of SEV parameters */
+const REMOTE_NODE_SEV_INFO_MAX = 64;
+
 /* UUID.  VIR_UUID_BUFLEN definition comes from libvirt.h */
 typedef opaque remote_uuid[VIR_UUID_BUFLEN];
 
@@ -3480,6

[libvirt] [PATCH v8 02/11] conf: expose SEV feature in domain capabilities

2018-06-06 Thread Brijesh Singh
Extend hypervisor capabilities to include sev feature. When available,
hypervisor supports launching an encrypted VM on AMD platform. The
sev feature tag provides additional details like Platform Diffie-Hellman
(PDH) key and certificate chain which can be used by the guest owner to
establish a cryptographic session with the SEV firmware to negotiate
keys used for attestation or to provide secret during launch.

Signed-off-by: Brijesh Singh 
---
 docs/formatdomaincaps.html.in  | 30 ++
 docs/schemas/domaincaps.rng| 14 
 src/conf/domain_capabilities.c | 19 -
 src/conf/domain_capabilities.h |  1 +
 src/qemu/qemu_capabilities.c   | 48 +-
 5 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index e0814cb..6be553a 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -435,6 +435,10 @@
 </gic>
 <vmcoreinfo supported='yes'/>
 <genid supported='yes'/>
+<sev>
+  <cbitpos>47</cbitpos>
+  <reduced-phys-bits>1</reduced-phys-bits>
+</sev>
   </features>
 </domainCapabilities>
 
@@ -467,5 +471,31 @@
 
 Reports whether the genid feature can be used by the domain.
 
+SEV capabilities
+
+AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under
+the sev element.
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When supported,
+guest owner can create a VM whose memory contents will be transparently
+encrypted with a key unique to that VM.
+
+
+For more details on SEV feature see:
+  https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";>
+SEV API spec and http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf";>
+SEV White Paper
+
+
+
+  cbitpos
+  When memory encryption is enabled, one of the physical address bits
+  (aka the C-bit) is utilized to mark if a memory page is protected. The
+  C-bit position is Hypervisor dependent.
+  reduced-phys-bits
+  When memory encryption is enabled, we lose certain bits in physical
+  address space. The number of bits we lose is hypervisor dependent.
+
+
   
 
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 5ceabb0..1d0a2e1 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -185,6 +185,9 @@
 
 
 
+
+  
+
   
 
   
@@ -208,6 +211,17 @@
 
   
 
+  
+
+  
+
+  
+  
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 3589777..54b0878 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -88,6 +88,7 @@ virDomainCapsDispose(void *obj)
 VIR_FREE(caps->machine);
 virObjectUnref(caps->cpu.custom);
 virCPUDefFree(caps->cpu.hostModel);
+virSEVCapabilitiesFree(caps->sev);
 
 virDomainCapsStringValuesFree(&caps->os.loader.values);
 }
@@ -554,6 +555,22 @@ virDomainCapsFeatureGICFormat(virBufferPtr buf,
 FORMAT_EPILOGUE(gic);
 }
 
+static void
+virDomainCapsFeatureSEVFormat(virBufferPtr buf,
+  virSEVCapabilityPtr const sev)
+{
+if (!sev)
+return;
+
+virBufferAddLit(buf, "\n");
+virBufferAdjustIndent(buf, 2);
+virBufferAsprintf(buf, "%d\n", sev->cbitpos);
+virBufferAsprintf(buf, "%d\n",
+  sev->reduced_phys_bits);
+virBufferAdjustIndent(buf, -2);
+virBufferAddLit(buf, "\n");
+}
+
 
 char *
 virDomainCapsFormat(virDomainCapsPtr const caps)
@@ -597,9 +614,9 @@ virDomainCapsFormat(virDomainCapsPtr const caps)
 virDomainCapsFeatureGICFormat(&buf, &caps->gic);
 virBufferAsprintf(&buf, "\n",
   caps->vmcoreinfo ? "yes" : "no");
-
 virBufferAsprintf(&buf, "\n",
   caps->genid ? "yes" : "no");
+virDomainCapsFeatureSEVFormat(&buf, caps->sev);
 
 virBufferAdjustIndent(&buf, -2);
 virBufferAddLit(&buf, "\n");
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 30b3272..17c1f1c 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -176,6 +176,7 @@ struct _virDomainCaps {
 virDomainCapsFeatureGIC gic;
 bool vmcoreinfo;
 bool genid;
+virSEVCapabilityPtr sev;
 /* add new domain features here */
 };
 
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/

[libvirt] [PATCH v8 03/11] libvirt: add new public API to get SEV Info

2018-06-06 Thread Brijesh Singh
The API can be used by application to retrieve the Platform Diffie-Hellman
Key and Platform Certificate chain.

Signed-off-by: Brijesh Singh <>
---
 include/libvirt/libvirt-host.h | 42 +
 src/driver-hypervisor.h|  6 ++
 src/libvirt-host.c | 47 ++
 src/libvirt_public.syms|  1 +
 4 files changed, 96 insertions(+)

diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
index 84f4858..e46f88b 100644
--- a/include/libvirt/libvirt-host.h
+++ b/include/libvirt/libvirt-host.h
@@ -432,6 +432,48 @@ typedef virNodeCPUStats *virNodeCPUStatsPtr;
 
 typedef virNodeMemoryStats *virNodeMemoryStatsPtr;
 
+
+/**
+ *
+ * SEV Parameters
+ */
+
+/**
+ * VIR_NODE_SEV_PDH:
+ *
+ * Marco represents the Platform Diffie-Hellman key, as 
VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_PDH   "pdh"
+
+/**
+ * VIR_NODE_SEV_CERT_CHAIN:
+ *
+ * Marco represents the Platform certificate chain that includes the
+ * endorsement key (PEK), owner certificate authority (OCD) and chip
+ * endorsement key (CEK), as VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_CERT_CHAIN"cert-chain"
+
+/**
+ * VIR_NODE_SEV_CBITPOS:
+ *
+ * Marco represents the CBit Position used by hypervisor when SEV is enabled.
+ */
+# define VIR_NODE_SEV_CBITPOS"cbitpos"
+
+/**
+ * VIR_NODE_SEV_REDUCED_PHYS_BITS:
+ *
+ * Marco represents the number of bits we lose in physical address space
+ * when SEV is enabled in the guest.
+ */
+# define VIR_NODE_SEV_REDUCED_PHYS_BITS"reduced-phys-bits"
+
+int virNodeGetSEVInfo (virConnectPtr conn,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags);
+
 /**
  * virConnectFlags
  *
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index aa99cbb..c50d2a0 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1309,6 +1309,11 @@ typedef int
   unsigned int action,
   unsigned int flags);
 
+typedef int
+(*virDrvNodeGetSEVInfo)(virConnectPtr conn,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags);
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1558,6 +1563,7 @@ struct _virHypervisorDriver {
 virDrvDomainSetLifecycleAction domainSetLifecycleAction;
 virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU;
 virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
+virDrvNodeGetSEVInfo nodeGetSEVInfo;
 };
 
 
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
index 3aaf558..2a633f0 100644
--- a/src/libvirt-host.c
+++ b/src/libvirt-host.c
@@ -1639,3 +1639,50 @@ virNodeAllocPages(virConnectPtr conn,
 virDispatchError(conn);
 return -1;
 }
+
+/*
+ * virNodeGetSEVInfo:
+ * @conn: pointer to the hypervisor connection
+ * @params: where to store  SEV information; output
+ * @nparams: pointer to number of SEV parameters; output
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * If hypervisor supports SEV then @params will contains PDH and
+ * certificate chain.
+ *
+ * Returns 0 in case of success, and -1 in case of failure.
+ */
+int
+virNodeGetSEVInfo(virConnectPtr conn,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags)
+{
+VIR_DEBUG("conn=%p, params=%p, nparams=%p, flags=0x%x",
+  conn, params, nparams, flags);
+
+virResetLastError();
+
+virCheckConnectReturn(conn, -1);
+virCheckNonNullArgGoto(nparams, error);
+virCheckNonNegativeArgGoto(*nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(conn->driver, conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->nodeGetSEVInfo) {
+int ret;
+ret = conn->driver->nodeGetSEVInfo(conn, params, nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+
+virReportUnsupportedError();
+
+ error:
+virDispatchError(conn);
+return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 4f54b84..524d5fd 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -796,6 +796,7 @@ LIBVIRT_4.5.0 {
 global:
 virGetLastErrorCode;
 virGetLastErrorDomain;
+virNodeGetSEVInfo;
 } LIBVIRT_4.4.0;
 
 #  define new API here using predicted next version number 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v8 01/11] qemu: provide support to query the SEV capability

2018-06-06 Thread Brijesh Singh
QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Signed-off-by: Brijesh Singh 
---
 src/conf/domain_capabilities.c | 12 
 src/conf/domain_capabilities.h | 16 +
 src/libvirt_private.syms   |  2 +-
 src/qemu/qemu_capabilities.c   | 35 ++
 src/qemu/qemu_capabilities.h   |  2 +-
 src/qemu/qemu_capspriv.h   |  4 ++
 src/qemu/qemu_monitor.c| 10 +++
 src/qemu/qemu_monitor.h|  3 +
 src/qemu/qemu_monitor_json.c   | 79 ++
 src/qemu/qemu_monitor_json.h   |  3 +
 .../caps_2.12.0.x86_64.replies | 10 +++
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |  3 +-
 12 files changed, 176 insertions(+), 3 deletions(-)

diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index c20358e..3589777 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -67,6 +67,18 @@ virDomainCapsStringValuesFree(virDomainCapsStringValuesPtr 
values)
 }
 
 
+void
+virSEVCapabilitiesFree(virSEVCapability *cap)
+{
+if (!cap)
+return;
+
+VIR_FREE(cap->pdh);
+VIR_FREE(cap->cert_chain);
+VIR_FREE(cap);
+}
+
+
 static void
 virDomainCapsDispose(void *obj)
 {
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index b0eb4aa..30b3272 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -137,6 +137,22 @@ struct _virDomainCapsCPU {
 virDomainCapsCPUModelsPtr custom;
 };
 
+/*
+ * SEV capabilities
+ */
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+char *pdh;
+char *cert_chain;
+unsigned int cbitpos;
+unsigned int reduced_phys_bits;
+};
+
+void
+virSEVCapabilitiesFree(virSEVCapability *capabilities);
+
+
 struct _virDomainCaps {
 virObjectLockable parent;
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5540391..59a2efd 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -185,7 +185,7 @@ virDomainCapsEnumClear;
 virDomainCapsEnumSet;
 virDomainCapsFormat;
 virDomainCapsNew;
-
+virSEVCapabilitiesFree;
 
 # conf/domain_conf.h
 virBlkioDeviceArrayClear;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index b20149b..70cf1e5 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -494,6 +494,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
   /* 305 */
   "vhost-vsock",
   "chardev-fd-pass",
+  "sev-guest",
 );
 
 
@@ -560,6 +561,8 @@ struct _virQEMUCaps {
 size_t ngicCapabilities;
 virGICCapability *gicCapabilities;
 
+virSEVCapability *sevCapabilities;
+
 virQEMUCapsHostCPUData kvmCPU;
 virQEMUCapsHostCPUData tcgCPU;
 };
@@ -1131,6 +1134,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
 { "hda-output", QEMU_CAPS_HDA_OUTPUT },
 { "vmgenid", QEMU_CAPS_DEVICE_VMGENID },
 { "vhost-vsock-device", QEMU_CAPS_DEVICE_VHOST_VSOCK },
+{ "sev-guest", QEMU_CAPS_SEV_GUEST },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
@@ -2067,6 +2071,16 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+  virSEVCapability *capabilities)
+{
+virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
+
+qemuCaps->sevCapabilities = capabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
 qemuMonitorPtr mon)
@@ -2650,6 +2664,21 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr 
qemuCaps,
 }
 
 
+static int
+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+   qemuMonitorPtr mon)
+{
+virSEVCapability *caps = NULL;
+
+if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+return -1;
+
+virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+return 0;
+}
+
+
 bool
 virQEMUCapsCPUFilterFeatures(const char *name,
  void *opaque)
@@ -4049,6 +4078,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
 virQEMUCapsClear(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW);
 }
 
+/* Probe for SEV capabilities */
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
+virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
+}
+
 ret = 0;
  cleanup:
 return ret;

[libvirt] [PATCH v8 0/9] x86: Secure Encrypted Virtualization (AMD)

2018-06-06 Thread Brijesh Singh
This patch series provides support for launching an encrypted guest using
AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV feature
allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
that includes the following


...
  
 
 
  


If  is provided then we indicate that hypervisor is capable of launching
SEV guest. mgmt tool can call virNodeGetSEVCapabilities() to get the additional
informations like PDH and certificate chain etc.

2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in 
case
if guest owner wish to establish a secure connection with SEV firmware to
negotiate a key used for validating the measurement.

3. mgmt tool requests to start a guest calling virCreateXML(), passing \
VIR_DOMAIN_START_PAUSED. The xml would include


  47 
  1
  0x1

  (optional)
/* Guest owners Diffie-Hellman key */
/* Guest owners Session blob */


4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
args looks like this:

# $QEMU ..
-machine memory-encryption=sev0 \
-object sev-guest,id=sev0,dh-cert-file=

5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event

6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls \
virDomainGetLaunchSecretInfo() to retrieve the measurement of encrypted memory.

7. (optional) mgmt tool can provide the measurement value to guest owner, which 
can
validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
it resumes the guest otherwise it calls destroy() to kill the guest.

8. mgmt tool resumes the guest

TODO:
* SEV guest require to use DMA apis for the virtio devices. In order to use the 
DMA
apis the virtio devices must have this tag



It is a bit unclear to me where these changes need to go. Do we need to
modify the libvirt to automatically add these when SEV is enabled or
we ask mgmt tool to make sure that it creates XML with right tag to enable
the DMA APIs for virtio devices. I am looking for some suggestions.

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

SEV Firmware API spec is available at:
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Change since v7:
* rename virNodeSEVCapability() -> virNodeSEVInfo()
* rebase the series

Changes since v6:
* add API to get SEV PDH and Certificate chain data
* drop virsh command changes. We can revisit this later when we have
  more visibility on setter.

Change since v5:
* drop the seperate test patch and merge the code with other patches.
* rename the xml from sev -> launch-security-sev
* make policy field mandatory
* address multiple feedback from previous reviews.

Changes since v4:
* add /dev/sev in shared device list

Changes since v3:
* rename QEMU_CAPS_SEV -> QEMU_CAPS_SEV_GUEST
* update caps_2.12.0.x86_64.replies to include query-sev-capabilities data

Changes since v2:
* make cbitpos, policy and reduced-phys-bits as unsigned int
* update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr *params
instead of virTypedParameterPtr params.

Changes since v1:
* rename  ->  for domain
* add more information about policy and other fields in domaincaps.html
* split the domain_conf support in two patches
* add virDomainGetLaunchInfo() to retrieve the SEV measurement
* extend virsh command to show the domain's launch security information
* add test cases to validate newly added  element
* fix issues reported with 'make check' and 'make syntax-check'

The complete git tree is available at:
https://github.com/codomania/libvirt/tree/v8

Brijesh Singh (11):
  qemu: provide support to query the SEV capability
  conf: expose SEV feature in domain capabilities
  libvirt: add new public API to get SEV Info
  remote: implement the remote protocol for virNodeSEVInfo()
  qemu: Add support to get the SEV info
  conf: introduce launch-security element in domain
  qemu/cgroup: add /dev/sev in shared devices list
  qemu: add support to launch SEV guest
  libvirt: add new public API to get launch security info
  remote: implement the remote protocol for launch security
  qemu: Add support to launch security info

 docs/drvqemu.html.in   |   1 +
 docs/formatdomain.html.in  | 115 +++
 docs/formatdomaincaps.html.in  |  30 
 docs/schemas/domaincaps.rng|  14 ++
 docs/schemas/domaincommon.rng  |  37 +
 include/libvirt/libvirt-domain.h   |  17 +++
 include/libvirt/libvirt-host.h |  42 ++
 src/conf/domain_capabilities.

Re: [libvirt] [PATCH v7 3/9] expose virNodeGetSEVCapability API

2018-06-06 Thread Brijesh Singh




On 06/06/2018 03:45 AM, Erik Skultety wrote:

On Tue, Jun 05, 2018 at 12:59:25PM -0500, Brijesh Singh wrote:

The API can be used by application to query the SEV capability.

Signed-off-by: Brijesh Singh <>
---
  include/libvirt/libvirt-host.h  | 42 +
  src/driver-hypervisor.h |  6 +++
  src/libvirt-host.c  | 48 +++
  src/libvirt_public.syms |  5 ++
  src/qemu/qemu_capabilities.c|  7 +++
  src/qemu/qemu_capabilities.h|  4 ++
  src/qemu/qemu_driver.c  | 93 +
  src/remote/remote_daemon_dispatch.c | 44 ++
  src/remote/remote_driver.c  | 41 
  src/remote/remote_protocol.x| 22 -
  src/remote_protocol-structs | 13 ++
  11 files changed, 324 insertions(+), 1 deletion(-)


please split this patch into multiple patches introducing per-driver change,
just like you're doing it for the GetLaunchSecurityInfo.



OK, noted.






diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
index 84f4858..d020597 100644
--- a/include/libvirt/libvirt-host.h
+++ b/include/libvirt/libvirt-host.h
@@ -432,6 +432,48 @@ typedef virNodeCPUStats *virNodeCPUStatsPtr;

  typedef virNodeMemoryStats *virNodeMemoryStatsPtr;

+
+/**
+ *
+ * SEV Parameters
+ */
+
+/**
+ * VIR_NODE_SEV_PDH:
+ *
+ * Marco represents the Platform Diffie-Hellman key, as 
VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_PDH   "pdh"
+
+/**
+ * VIR_NODE_SEV_CERT_CHAIN:
+ *
+ * Marco represents the Platform certificate chain that includes the
+ * endorsement key (PEK), owner certificate authority (OCD) and chip
+ * endorsement key (CEK), as VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_CERT_CHAIN"cert-chain"
+
+/**
+ * VIR_NODE_SEV_CBITPOS:
+ *
+ * Marco represents the CBit Position used by hypervisor when SEV is enabled.
+ */
+# define VIR_NODE_SEV_CBITPOS"cbitpos"
+
+/**
+ * VIR_NODE_SEV_REDUCED_PHYS_BITS:
+ *
+ * Marco represents the number of bits we lose in physical address space
+ * when SEV is enabled in the guest.
+ */
+# define VIR_NODE_SEV_REDUCED_PHYS_BITS"reduced-phys-bits"
+
+int virNodeGetSEVCapability (virConnectPtr conn,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);


I'm not very convinced by having "Capability" in the name, PDH and cert-chain
represent information about the system, pretty much something dmi-decode would
report, let's use virNodeGetSEVInfo as I suggested in v6.




I will rename to virNodeGetSEVInfo(..)



...


  #endif /* __QEMU_CAPABILITIES_H__*/
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index c200c5a..7c619dd 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -137,6 +137,8 @@ VIR_LOG_INIT("qemu.qemu_driver");

  #define QEMU_NB_BANDWIDTH_PARAM 7

+#define QEMU_SEV_PARAMS 4


The difference between this patch and the next one is basically ^this bit which
I don't even see being used, so I assume the next patch in the series is the
one to be applied.




Ah this macro is not used, I will fix in v8.


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v7 8/9] remote: implement the remote protocol for launch security

2018-06-05 Thread Brijesh Singh
Add remote support for launch security info.

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 src/remote/remote_daemon_dispatch.c | 47 +
 src/remote/remote_driver.c  | 40 +++
 src/remote/remote_protocol.x| 19 ++-
 src/remote_protocol-structs | 11 +
 4 files changed, 116 insertions(+), 1 deletion(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index f974b71..e0e2850 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -3110,6 +3110,53 @@ remoteDispatchNodeGetMemoryStats(virNetServerPtr server 
ATTRIBUTE_UNUSED,
 }
 
 static int
+remoteDispatchDomainGetLaunchSecurityInfo(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+  virNetMessagePtr msg 
ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  
remote_domain_get_launch_security_info_args *args,
+  
remote_domain_get_launch_security_info_ret *ret)
+{
+virDomainPtr dom = NULL;
+virTypedParameterPtr params = NULL;
+int nparams = 0;
+int rv = -1;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, args->flags) < 
0)
+goto cleanup;
+
+if (nparams > REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+goto cleanup;
+}
+
+if (virTypedParamsSerialize(params, nparams,
+(virTypedParameterRemotePtr *) 
&ret->params.params_val,
+&ret->params.params_len,
+args->flags) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0)
+virNetMessageSaveError(rerr);
+virTypedParamsFree(params, nparams);
+virObjectUnref(dom);
+return rv;
+}
+
+static int
 remoteDispatchDomainGetPerfEvents(virNetServerPtr server ATTRIBUTE_UNUSED,
   virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
   virNetMessagePtr msg ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index cdc9a70..87b2455 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1966,6 +1966,45 @@ remoteDomainGetNumaParameters(virDomainPtr domain,
 }
 
 static int
+remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags)
+{
+int rv = -1;
+remote_domain_get_launch_security_info_args args;
+remote_domain_get_launch_security_info_ret ret;
+struct private_data *priv = domain->conn->privateData;
+
+remoteDriverLock(priv);
+
+make_nonnull_domain(&args.dom, domain);
+args.flags = flags;
+
+memset(&ret, 0, sizeof(ret));
+if (call(domain->conn, priv, 0, 
REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_args, 
(char *) &args,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_ret, (char 
*) &ret) == -1)
+goto done;
+
+if (virTypedParamsDeserialize((virTypedParameterRemotePtr) 
ret.params.params_val,
+  ret.params.params_len,
+  
REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX,
+  params,
+  nparams) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+xdr_free((xdrproc_t) xdr_remote_domain_get_launch_security_info_ret,
+ (char *) &ret);
+ done:
+remoteDriverUnlock(priv);
+return rv;
+}
+
+static int
 remoteDomainGetPerfEvents(virDomainPtr domain,
   virTypedParameterPtr *params,
   int *nparams,
@@ -8493,6 +8532,7 @@ static virHypervisorDriver hypervisor_driver = {
 .connectCompareHypervisorCPU = remoteConnectCompareHypervisorCPU, /* 4.4.0 
*/
 .connectBaselineHypervisorCPU = remoteConnectBaselineHypervisorCPU, /* 
4.4.0 */
 .nodeGetSEVCapability = remoteNodeGetSEVCapability, /* 4.5.0 */
+.domainGetLaunchSecurityInfo = remoteDomainGetLaunchSecurityInfo /* 4.5.0 
*/
 };
 
 static virNetworkDriv

[libvirt] [PATCH v7 9/9] qemu: Add support to launch security info

2018-06-05 Thread Brijesh Singh
This patch implements the internal driver API for launch event into
qemu driver. When SEV is enabled, execute 'query-sev-launch-measurement'
to get the measurement of memory encrypted through launch sequence.

Signed-off-by: Brijesh Singh 
---
 src/qemu/qemu_driver.c   | 69 
 src/qemu/qemu_monitor.c  |  8 +
 src/qemu/qemu_monitor.h  |  3 ++
 src/qemu/qemu_monitor_json.c | 42 +++
 src/qemu/qemu_monitor_json.h |  2 ++
 5 files changed, 124 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 0fb1aba..6813a42 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21528,6 +21528,74 @@ qemuNodeGetSEVCapability(virConnectPtr conn,
 }
 
 
+static int
+qemuDomainGetSEVMeasurement(virQEMUDriverPtr driver,
+virDomainObjPtr vm,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+int ret = -1;
+char *tmp;
+int maxpar = 0;
+
+virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+return -1;
+
+if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
+goto endjob;
+
+tmp = qemuMonitorGetSEVMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
+if (tmp == NULL)
+goto endjob;
+
+if (qemuDomainObjExitMonitor(driver, vm) < 0)
+goto endjob;
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
+tmp) < 0)
+goto endjob;
+
+VIR_FREE(tmp);
+ret = 0;
+
+ endjob:
+qemuDomainObjEndJob(driver, vm);
+return ret;
+}
+
+
+static int
+qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+virQEMUDriverPtr driver = domain->conn->privateData;
+virDomainObjPtr vm;
+int ret = -1;
+
+if (!(vm = qemuDomObjFromDomain(domain)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
+goto cleanup;
+
+if (vm->def->sev) {
+if (qemuDomainGetSEVMeasurement(driver, vm, params, nparams, flags) < 
0)
+goto cleanup;
+}
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 static virHypervisorDriver qemuHypervisorDriver = {
 .name = QEMU_DRIVER_NAME,
 .connectURIProbe = qemuConnectURIProbe,
@@ -21752,6 +21820,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
 .connectCompareHypervisorCPU = qemuConnectCompareHypervisorCPU, /* 4.4.0 */
 .connectBaselineHypervisorCPU = qemuConnectBaselineHypervisorCPU, /* 4.4.0 
*/
 .nodeGetSEVCapability = qemuNodeGetSEVCapability, /* 4.5.0 */
+.domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.5.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index d1e4d74..a782fdb 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4288,3 +4288,11 @@ qemuMonitorBlockdevDel(qemuMonitorPtr mon,
 
 return qemuMonitorJSONBlockdevDel(mon, nodename);
 }
+
+char *
+qemuMonitorGetSEVMeasurement(qemuMonitorPtr mon)
+{
+QEMU_CHECK_MONITOR_NULL(mon);
+
+return qemuMonitorJSONGetSEVMeasurement(mon);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 04abd92..1472224 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1141,4 +1141,7 @@ int qemuMonitorBlockdevAdd(qemuMonitorPtr mon,
 int qemuMonitorBlockdevDel(qemuMonitorPtr mon,
const char *nodename);
 
+char *
+qemuMonitorGetSEVMeasurement(qemuMonitorPtr mon);
+
 #endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index b50f719..c888a34 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -7994,3 +7994,45 @@ qemuMonitorJSONBlockdevDel(qemuMonitorPtr mon,
 virJSONValueFree(reply);
 return ret;
 }
+
+/**
+ * The function is used to retrieve the measurement of a SEV guest.
+ * The measurement is signature of the memory contents that was encrypted
+ * through the SEV launch flow.
+ *
+ * A example JSON output:
+ *
+ * { "execute" : "query-sev-launch-measure" }
+ * { "return" : { "data" : "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
+ */
+char *
+qemuMonitorJSONGetSEVMeasurement(qemuMonitorPtr mon)
+{
+const char *tmp;
+char *measurement = NULL;
+virJSONValuePtr cmd;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr data;
+
+if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NULL)))
+ return NULL;

[libvirt] [PATCH v7 7/9] libvirt: add new public API to get launch security info

2018-06-05 Thread Brijesh Singh
The API can be used outside the libvirt to get the launch security
information. When SEV is enabled, the API can be used to get the
measurement of the launch process.

Signed-off-by: Brijesh Singh 
---
 include/libvirt/libvirt-domain.h | 17 ++
 src/driver-hypervisor.h  |  8 +++
 src/libvirt-domain.c | 48 
 src/libvirt_public.syms  |  1 +
 4 files changed, 74 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index da773b7..6a3d73f 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4767,4 +4767,21 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 unsigned int action,
 unsigned int flags);
 
+/**
+ * Launch Security API
+ */
+
+/**
+ * VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT:
+ *
+ * Macro represents the launch measurement of the SEV guest,
+ * as VIR_TYPED_PARAM_STRING.
+ */
+#define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement"
+
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags);
+
 #endif /* __VIR_LIBVIRT_DOMAIN_H__ */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index cb2ab9c..070e7ce 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1315,6 +1315,13 @@ typedef int
   int *nparams,
   unsigned int flags);
 
+typedef int
+(*virDrvDomainGetLaunchSecurityInfo)(virDomainPtr domain,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags);
+
+
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
 
@@ -1564,6 +1571,7 @@ struct _virHypervisorDriver {
 virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU;
 virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
 virDrvNodeGetSEVCapability nodeGetSEVCapability;
+virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
 };
 
 
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index d44b553..dcfc7d4 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12154,3 +12154,51 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 virDispatchError(domain->conn);
 return -1;
 }
+
+/**
+ * virDomainGetLaunchSecurityInfo:
+ * @domain: a domain object
+ * @params: where to store security info
+ * @nparams: number of items in @params
+ * @flags: currently used, set to 0.
+ *
+ * Get the launch security info. In case of the SEV guest, this will
+ * return the launch measurement.
+ *
+ * Returns -1 in case of failure, 0 in case of success.
+ */
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+virConnectPtr conn = domain->conn;
+
+VIR_DOMAIN_DEBUG(domain, "params=%p, nparams=%p flags=0x%x",
+ params, nparams, flags);
+
+virResetLastError();
+
+virCheckDomainReturn(domain, -1);
+virCheckNonNullArgGoto(params, error);
+virCheckNonNullArgGoto(nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->domainGetLaunchSecurityInfo) {
+int ret;
+ret = conn->driver->domainGetLaunchSecurityInfo(domain, params,
+nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+virReportUnsupportedError();
+
+ error:
+virDispatchError(domain->conn);
+return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 438205f..9850c09 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -795,6 +795,7 @@ LIBVIRT_4.4.0 {
 LIBVIRT_4.5.0 {
 global:
 virNodeGetSEVCapability;
+virDomainGetLaunchSecurityInfo;
 } LIBVIRT_4.4.0;
 
 #  define new API here using predicted next version number 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v7 3/9] expose virNodeGetSEVCapability API

2018-06-05 Thread Brijesh Singh
The API can be used by application to query the SEV capability.

Signed-off-by: Brijesh Singh <>
---
 include/libvirt/libvirt-host.h  | 42 +
 src/driver-hypervisor.h |  6 +++
 src/libvirt-host.c  | 48 +++
 src/libvirt_public.syms |  5 ++
 src/qemu/qemu_capabilities.c|  7 +++
 src/qemu/qemu_capabilities.h|  4 ++
 src/qemu/qemu_driver.c  | 93 +
 src/remote/remote_daemon_dispatch.c | 44 ++
 src/remote/remote_driver.c  | 41 
 src/remote/remote_protocol.x| 22 -
 src/remote_protocol-structs | 13 ++
 11 files changed, 324 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
index 84f4858..d020597 100644
--- a/include/libvirt/libvirt-host.h
+++ b/include/libvirt/libvirt-host.h
@@ -432,6 +432,48 @@ typedef virNodeCPUStats *virNodeCPUStatsPtr;
 
 typedef virNodeMemoryStats *virNodeMemoryStatsPtr;
 
+
+/**
+ *
+ * SEV Parameters
+ */
+
+/**
+ * VIR_NODE_SEV_PDH:
+ *
+ * Marco represents the Platform Diffie-Hellman key, as 
VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_PDH   "pdh"
+
+/**
+ * VIR_NODE_SEV_CERT_CHAIN:
+ *
+ * Marco represents the Platform certificate chain that includes the
+ * endorsement key (PEK), owner certificate authority (OCD) and chip
+ * endorsement key (CEK), as VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_CERT_CHAIN"cert-chain"
+
+/**
+ * VIR_NODE_SEV_CBITPOS:
+ *
+ * Marco represents the CBit Position used by hypervisor when SEV is enabled.
+ */
+# define VIR_NODE_SEV_CBITPOS"cbitpos"
+
+/**
+ * VIR_NODE_SEV_REDUCED_PHYS_BITS:
+ *
+ * Marco represents the number of bits we lose in physical address space
+ * when SEV is enabled in the guest.
+ */
+# define VIR_NODE_SEV_REDUCED_PHYS_BITS"reduced-phys-bits"
+
+int virNodeGetSEVCapability (virConnectPtr conn,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);
+
 /**
  * virConnectFlags
  *
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index aa99cbb..cb2ab9c 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1309,6 +1309,11 @@ typedef int
   unsigned int action,
   unsigned int flags);
 
+typedef int
+(*virDrvNodeGetSEVCapability)(virConnectPtr conn,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags);
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1558,6 +1563,7 @@ struct _virHypervisorDriver {
 virDrvDomainSetLifecycleAction domainSetLifecycleAction;
 virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU;
 virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
+virDrvNodeGetSEVCapability nodeGetSEVCapability;
 };
 
 
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
index 3aaf558..0f78166 100644
--- a/src/libvirt-host.c
+++ b/src/libvirt-host.c
@@ -1639,3 +1639,51 @@ virNodeAllocPages(virConnectPtr conn,
 virDispatchError(conn);
 return -1;
 }
+
+/*
+ * virNodeGetSEVCapability:
+ * @conn: pointer to the hypervisor connection
+ * @params: where to store  SEV capability
+ * @nparams: pointer to number of SEV parameters; output
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Get the SEV host capabilities, If hypervisor supports SEV then it @params
+ * will contains PDH and certificate chain.
+ *
+ * Returns 0 in case of success, and -1 in case of failure.
+ */
+int
+virNodeGetSEVCapability(virConnectPtr conn,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+VIR_DEBUG("conn=%p, params=%p, nparams=%p (%d), flags=0x%x",
+  conn, params, nparams, *nparams, flags);
+
+virResetLastError();
+
+virCheckConnectReturn(conn, -1);
+virCheckNonNullArgGoto(nparams, error);
+virCheckNonNegativeArgGoto(*nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(conn->driver, conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->nodeGetSEVCapability) {
+int ret;
+ret = conn->driver->nodeGetSEVCapability(conn, params,
+ nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+
+virReportUnsupportedError();
+
+ error:
+virDispatchError(conn);
+return -1;
+}
diff --g

[libvirt] [PATCH v7 4/9] conf: introduce launch-security element in domain

2018-06-05 Thread Brijesh Singh
The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Signed-off-by: Brijesh Singh 
---
 docs/formatdomain.html.in  | 115 ++
 docs/schemas/domaincommon.rng  |  37 ++
 src/conf/domain_conf.c | 133 +
 src/conf/domain_conf.h |  27 +
 tests/genericxml2xmlindata/launch-security-sev.xml |  24 
 tests/genericxml2xmltest.c |   2 +
 6 files changed, 338 insertions(+)
 create mode 100644 tests/genericxml2xmlindata/launch-security-sev.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 7f4de65..decd854 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8367,6 +8367,121 @@ qemu-kvm -net nic,model=? /dev/null
 
 Note: DEA/TDEA is synonymous with DES/TDES.
 
+Secure Encrypted Virtualization (SEV)
+
+
+   The contents of the <launch-security type='sev'> 
element
+   is used to provide the guest owners input used for creating an encrypted
+   VM using the AMD SEV feature.
+
+   SEV is an extension to the AMD-V architecture which supports running
+   encrypted virtual machine (VMs) under the control of KVM. Encrypted
+   VMs have their pages (code and data) secured such that only the guest
+   itself has access to the unencrypted version. Each encrypted VM is
+   associated with a unique encryption key; if its data is accessed to a
+   different entity using a different key the encrypted guests data will
+   be incorrectly decrypted, leading to unintelligible data.
+
+   For more information see various input parameters and its format see 
the SEV API spec
+   https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";> 
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf 
+   Since 4.4.0
+   
+
+<domain>
+  ...
+  <launch-security type='sev'>
+<policy> 0x0001 </policy>
+<cbitpos> 47 </cbitpos>
+<reduced-phys-bits> 1 </reduced-phys-bits>
+<session> AAACCCDD=FFFCCCDSDS </session>
+<dh-cert> RBBBSDDD=FDDCCCDDDG </dh>
+  </sev>
+  ...
+</domain>
+
+
+
+  cbitpos
+  The required cbitpos element provides the C-bit (aka 
encryption bit)
+  location in guest page table entry. The value of cbitpos is
+  hypervisor dependent and can be obtained through the sev 
element
+  from the domain capabilities.
+  
+  reduced-phys-bits
+  The required reduced-phys-bits element provides the 
physical
+  address bit reducation. Similar to cbitpos the value of 

+  reduced-phys-bit is hypervisor dependent and can be obtained
+  through the sev element from the domain capabilities.
+  
+  policy
+  The required policy element provides the guest policy
+  which must be maintained by the SEV firmware. This policy is enforced by
+  the firmware and restricts what configuration and operational commands
+  can be performed on this guest by the hypervisor. The guest policy
+  provided during guest launch is bound to the guest and cannot be changed
+  throughout the lifetime of the guest. The policy is also transmitted
+  during snapshot and migration flows and enforced on the destination 
platform.
+
+  The guest policy is a 4 unsigned byte with the fields shown in Table:
+
+  
+
+   Bit(s) 
+   Description 
+
+
+   0 
+   Debugging of the guest is disallowed when set 
+
+
+   1 
+   Sharing keys with other guests is disallowed when set 
+
+
+   2 
+   SEV-ES is required when set
+
+
+   3 
+   Sending the guest to another platform is disallowed when 
set
+
+
+   4 
+   The guest must not be transmitted to another platform that is
+   not in the domain when set. 
+
+
+   5 
+   The guest must not be transmitted to another platform that is
+   not SEV capable when set. 
+
+
+   6:15 
+   reserved 
+
+
+   16:32 
+   The guest must no

[libvirt] [PATCH v7 1/9] qemu: provide support to query the SEV capability

2018-06-05 Thread Brijesh Singh
QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Signed-off-by: Brijesh Singh 
---
 src/conf/domain_capabilities.c | 12 
 src/conf/domain_capabilities.h | 16 +
 src/libvirt_private.syms   |  2 +-
 src/qemu/qemu_capabilities.c   | 35 ++
 src/qemu/qemu_capabilities.h   |  2 +-
 src/qemu/qemu_capspriv.h   |  4 ++
 src/qemu/qemu_monitor.c| 10 +++
 src/qemu/qemu_monitor.h|  3 +
 src/qemu/qemu_monitor_json.c   | 79 ++
 src/qemu/qemu_monitor_json.h   |  3 +
 .../caps_2.12.0.x86_64.replies | 10 +++
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |  3 +-
 12 files changed, 176 insertions(+), 3 deletions(-)

diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index c20358e..3589777 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -67,6 +67,18 @@ virDomainCapsStringValuesFree(virDomainCapsStringValuesPtr 
values)
 }
 
 
+void
+virSEVCapabilitiesFree(virSEVCapability *cap)
+{
+if (!cap)
+return;
+
+VIR_FREE(cap->pdh);
+VIR_FREE(cap->cert_chain);
+VIR_FREE(cap);
+}
+
+
 static void
 virDomainCapsDispose(void *obj)
 {
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index b0eb4aa..30b3272 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -137,6 +137,22 @@ struct _virDomainCapsCPU {
 virDomainCapsCPUModelsPtr custom;
 };
 
+/*
+ * SEV capabilities
+ */
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+char *pdh;
+char *cert_chain;
+unsigned int cbitpos;
+unsigned int reduced_phys_bits;
+};
+
+void
+virSEVCapabilitiesFree(virSEVCapability *capabilities);
+
+
 struct _virDomainCaps {
 virObjectLockable parent;
 
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 5540391..59a2efd 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -185,7 +185,7 @@ virDomainCapsEnumClear;
 virDomainCapsEnumSet;
 virDomainCapsFormat;
 virDomainCapsNew;
-
+virSEVCapabilitiesFree;
 
 # conf/domain_conf.h
 virBlkioDeviceArrayClear;
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 26969ed..2c3665d 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -493,6 +493,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
 
   /* 305 */
   "vhost-vsock",
+  "sev-guest",
 );
 
 
@@ -559,6 +560,8 @@ struct _virQEMUCaps {
 size_t ngicCapabilities;
 virGICCapability *gicCapabilities;
 
+virSEVCapability *sevCapabilities;
+
 virQEMUCapsHostCPUData kvmCPU;
 virQEMUCapsHostCPUData tcgCPU;
 };
@@ -1130,6 +1133,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
 { "hda-output", QEMU_CAPS_HDA_OUTPUT },
 { "vmgenid", QEMU_CAPS_DEVICE_VMGENID },
 { "vhost-vsock-device", QEMU_CAPS_DEVICE_VHOST_VSOCK },
+{ "sev-guest", QEMU_CAPS_SEV_GUEST },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
@@ -2066,6 +2070,16 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+  virSEVCapability *capabilities)
+{
+virSEVCapabilitiesFree(qemuCaps->sevCapabilities);
+
+qemuCaps->sevCapabilities = capabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
 qemuMonitorPtr mon)
@@ -2648,6 +2662,21 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr 
qemuCaps,
 }
 
 
+static int
+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+   qemuMonitorPtr mon)
+{
+virSEVCapability *caps = NULL;
+
+if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+return -1;
+
+virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+return 0;
+}
+
+
 bool
 virQEMUCapsCPUFilterFeatures(const char *name,
  void *opaque)
@@ -4043,6 +4072,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
 virQEMUCapsClear(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW);
 }
 
+/* Probe for SEV capabilities */
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
+virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
+}
+
 ret = 0;
  cleanup:
 return ret;
diff --git a/src/qemu/qemu_capab

[libvirt] [PATCH v7 2/9] conf: expose SEV feature in domain capabilities

2018-06-05 Thread Brijesh Singh
Extend hypervisor capabilities to include sev feature. When available,
hypervisor supports launching an encrypted VM on AMD platform. The
sev feature tag provides additional details like Platform Diffie-Hellman
(PDH) key and certificate chain which can be used by the guest owner to
establish a cryptographic session with the SEV firmware to negotiate
keys used for attestation or to provide secret during launch.

Signed-off-by: Brijesh Singh 
---
 docs/formatdomaincaps.html.in  | 30 ++
 docs/schemas/domaincaps.rng| 14 
 src/conf/domain_capabilities.c | 19 -
 src/conf/domain_capabilities.h |  1 +
 src/qemu/qemu_capabilities.c   | 48 +-
 5 files changed, 110 insertions(+), 2 deletions(-)

diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index e0814cb..6be553a 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -435,6 +435,10 @@
 </gic>
 <vmcoreinfo supported='yes'/>
 <genid supported='yes'/>
+<sev>
+  <cbitpos>47</cbitpos>
+  <reduced-phys-bits>1</reduced-phys-bits>
+</sev>
   </features>
 </domainCapabilities>
 
@@ -467,5 +471,31 @@
 
 Reports whether the genid feature can be used by the domain.
 
+SEV capabilities
+
+AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under
+the sev element.
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When supported,
+guest owner can create a VM whose memory contents will be transparently
+encrypted with a key unique to that VM.
+
+
+For more details on SEV feature see:
+  https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";>
+SEV API spec and http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf";>
+SEV White Paper
+
+
+
+  cbitpos
+  When memory encryption is enabled, one of the physical address bits
+  (aka the C-bit) is utilized to mark if a memory page is protected. The
+  C-bit position is Hypervisor dependent.
+  reduced-phys-bits
+  When memory encryption is enabled, we lose certain bits in physical
+  address space. The number of bits we lose is hypervisor dependent.
+
+
   
 
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 5ceabb0..1d0a2e1 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -185,6 +185,9 @@
 
 
 
+
+  
+
   
 
   
@@ -208,6 +211,17 @@
 
   
 
+  
+
+  
+
+  
+  
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 3589777..54b0878 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -88,6 +88,7 @@ virDomainCapsDispose(void *obj)
 VIR_FREE(caps->machine);
 virObjectUnref(caps->cpu.custom);
 virCPUDefFree(caps->cpu.hostModel);
+virSEVCapabilitiesFree(caps->sev);
 
 virDomainCapsStringValuesFree(&caps->os.loader.values);
 }
@@ -554,6 +555,22 @@ virDomainCapsFeatureGICFormat(virBufferPtr buf,
 FORMAT_EPILOGUE(gic);
 }
 
+static void
+virDomainCapsFeatureSEVFormat(virBufferPtr buf,
+  virSEVCapabilityPtr const sev)
+{
+if (!sev)
+return;
+
+virBufferAddLit(buf, "\n");
+virBufferAdjustIndent(buf, 2);
+virBufferAsprintf(buf, "%d\n", sev->cbitpos);
+virBufferAsprintf(buf, "%d\n",
+  sev->reduced_phys_bits);
+virBufferAdjustIndent(buf, -2);
+virBufferAddLit(buf, "\n");
+}
+
 
 char *
 virDomainCapsFormat(virDomainCapsPtr const caps)
@@ -597,9 +614,9 @@ virDomainCapsFormat(virDomainCapsPtr const caps)
 virDomainCapsFeatureGICFormat(&buf, &caps->gic);
 virBufferAsprintf(&buf, "\n",
   caps->vmcoreinfo ? "yes" : "no");
-
 virBufferAsprintf(&buf, "\n",
   caps->genid ? "yes" : "no");
+virDomainCapsFeatureSEVFormat(&buf, caps->sev);
 
 virBufferAdjustIndent(&buf, -2);
 virBufferAddLit(&buf, "\n");
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 30b3272..17c1f1c 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -176,6 +176,7 @@ struct _virDomainCaps {
 virDomainCapsFeatureGIC gic;
 bool vmcoreinfo;
 bool genid;
+virSEVCapabilityPtr sev;
 /* add new domain features here */
 };
 
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/

[libvirt] [PATCH v7 0/9] x86: Secure Encrypted Virtualization (AMD)

2018-06-05 Thread Brijesh Singh
This patch series provides support for launching an encrypted guest using
AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV feature
allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
that includes the following


...
  
 
 
  


If  is provided then we indicate that hypervisor is capable of launching
SEV guest. mgmt tool can call virNodeGetSEVCapabilities() to get the additional
informations like PDH and certificate chain etc.

2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in 
case
if guest owner wish to establish a secure connection with SEV firmware to
negotiate a key used for validating the measurement.

3. mgmt tool requests to start a guest calling virCreateXML(), passing \
VIR_DOMAIN_START_PAUSED. The xml would include


  47 
  1
  0x1

  (optional)
/* Guest owners Diffie-Hellman key */
/* Guest owners Session blob */


4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
args looks like this:

# $QEMU ..
-machine memory-encryption=sev0 \
-object sev-guest,id=sev0,dh-cert-file=

5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event

6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls
virDomainGetLaunchSecretInfo() to retrieve the measurement of encrypted memory.

7. (optional) mgmt tool can provide the measurement value to guest owner, which 
can
validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
it resumes the guest otherwise it calls destroy() to kill the guest.

8. mgmt tool resumes the guest

TODO:
* SEV guest require to use DMA apis for the virtio devices. In order to use the 
DMA
apis the virtio devices must have this tag



It is a bit unclear to me where these changes need to go. Do we need to
modify the libvirt to automatically add these when SEV is enabled or
we ask mgmt tool to make sure that it creates XML with right tag to enable
the DMA APIs for virtio devices. I am looking for some suggestions.

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

SEV Firmware API spec is available at:
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Changes since v6:
* add API to get SEV PDH and Certificate chain data
* drop virsh command changes. We can revisit this later when we have
  more visibility on setter.

Change since v5:
* drop the seperate test patch and merge the code with other patches.
* rename the xml from sev -> launch-security-sev
* make policy field mandatory
* address multiple feedback from previous reviews.

Changes since v4:
* add /dev/sev in shared device list

Changes since v3:
* rename QEMU_CAPS_SEV -> QEMU_CAPS_SEV_GUEST
* update caps_2.12.0.x86_64.replies to include query-sev-capabilities data

Changes since v2:
* make cbitpos, policy and reduced-phys-bits as unsigned int
* update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr *params
instead of virTypedParameterPtr params.

Changes since v1:
* rename  ->  for domain
* add more information about policy and other fields in domaincaps.html
* split the domain_conf support in two patches
* add virDomainGetLaunchInfo() to retrieve the SEV measurement
* extend virsh command to show the domain's launch security information
* add test cases to validate newly added  element
* fix issues reported with 'make check' and 'make syntax-check'

The complete git tree is available at:
https://github.com/codomania/libvirt/tree/v7

Brijesh Singh (9):
  qemu: provide support to query the SEV capability
  conf: expose SEV feature in domain capabilities
  libvirt-host: expose virNodeGetSEVCapability API
  conf: introduce launch-security element in domain
  qemu/cgroup: add /dev/sev in shared devices list
  qemu: add support to launch SEV guest
  libvirt: add new public API to get launch security info
  remote: implement the remote protocol for launch security
  qemu: Add support to launch security info

 docs/drvqemu.html.in   |   1 +
 docs/formatdomain.html.in  | 115 +++
 docs/formatdomaincaps.html.in  |  30 
 docs/schemas/domaincaps.rng|  14 ++
 docs/schemas/domaincommon.rng  |  37 +
 include/libvirt/libvirt-domain.h   |  17 +++
 include/libvirt/libvirt-host.h |  42 ++
 src/conf/domain_capabilities.c |  31 +++-
 src/conf/domain_capabilities.h |  17 +++
 src/conf/domain_conf.c | 133 +
 src/conf/domain_conf.h 

[libvirt] [PATCH v7 5/9] qemu/cgroup: add /dev/sev in shared devices list

2018-06-05 Thread Brijesh Singh
QEMU uses /dev/sev device while creating the SEV guest, lets add /dev/sev
in the list of devices allowed to be accessed by the QEMU.

Signed-off-by: Brijesh Singh <>
Reviewed-by: Erik Skultety 
---
 docs/drvqemu.html.in   | 1 +
 src/qemu/qemu.conf | 2 +-
 src/qemu/qemu_cgroup.c | 2 +-
 src/qemu/test_libvirtd_qemu.aug.in | 1 +
 4 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/drvqemu.html.in b/docs/drvqemu.html.in
index cbd159d..7c33a18 100644
--- a/docs/drvqemu.html.in
+++ b/docs/drvqemu.html.in
@@ -397,6 +397,7 @@ chmod o+x /path/to/directory
 /dev/random, /dev/urandom,
 /dev/ptmx, /dev/kvm, /dev/kqemu,
 /dev/rtc, /dev/hpet, /dev/net/tun
+/dev/sev
 
 
 
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index c8e1a62..3a733b3 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -485,7 +485,7 @@
 #"/dev/null", "/dev/full", "/dev/zero",
 #"/dev/random", "/dev/urandom",
 #"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-#"/dev/rtc","/dev/hpet"
+#"/dev/rtc","/dev/hpet", "/dev/sev"
 #]
 #
 # RDMA migration requires the following extra files to be added to the list:
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 546a4c8..21dcb3c 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -47,7 +47,7 @@ const char *const defaultDeviceACL[] = {
 "/dev/null", "/dev/full", "/dev/zero",
 "/dev/random", "/dev/urandom",
 "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-"/dev/rtc", "/dev/hpet",
+"/dev/rtc", "/dev/hpet", "/dev/sev",
 NULL,
 };
 #define DEVICE_PTY_MAJOR 136
diff --git a/src/qemu/test_libvirtd_qemu.aug.in 
b/src/qemu/test_libvirtd_qemu.aug.in
index 912161c..f127726 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -62,6 +62,7 @@ module Test_libvirtd_qemu =
 { "8" = "/dev/kqemu" }
 { "9" = "/dev/rtc" }
 { "10" = "/dev/hpet" }
+{ "11" = "/dev/sev" }
 }
 { "save_image_format" = "raw" }
 { "dump_image_format" = "raw" }
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v7 3/9] libvirt-host: expose virNodeGetSEVCapability API

2018-06-05 Thread Brijesh Singh
The API can be used by application to get the SEV capability
(which includes platform certificate chain and other releated information)

Signed-off-by: Brijesh Singh <>
---
 include/libvirt/libvirt-host.h  | 42 +
 src/driver-hypervisor.h |  6 +++
 src/libvirt-host.c  | 48 +++
 src/libvirt_public.syms |  5 ++
 src/qemu/qemu_capabilities.c|  7 +++
 src/qemu/qemu_capabilities.h|  4 ++
 src/qemu/qemu_driver.c  | 91 +
 src/remote/remote_daemon_dispatch.c | 44 ++
 src/remote/remote_driver.c  | 41 +
 src/remote/remote_protocol.x| 22 -
 src/remote_protocol-structs | 13 ++
 11 files changed, 322 insertions(+), 1 deletion(-)

diff --git a/include/libvirt/libvirt-host.h b/include/libvirt/libvirt-host.h
index 84f4858..d020597 100644
--- a/include/libvirt/libvirt-host.h
+++ b/include/libvirt/libvirt-host.h
@@ -432,6 +432,48 @@ typedef virNodeCPUStats *virNodeCPUStatsPtr;
 
 typedef virNodeMemoryStats *virNodeMemoryStatsPtr;
 
+
+/**
+ *
+ * SEV Parameters
+ */
+
+/**
+ * VIR_NODE_SEV_PDH:
+ *
+ * Marco represents the Platform Diffie-Hellman key, as 
VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_PDH   "pdh"
+
+/**
+ * VIR_NODE_SEV_CERT_CHAIN:
+ *
+ * Marco represents the Platform certificate chain that includes the
+ * endorsement key (PEK), owner certificate authority (OCD) and chip
+ * endorsement key (CEK), as VIR_TYPED_PARAMS_STRING.
+ */
+# define VIR_NODE_SEV_CERT_CHAIN"cert-chain"
+
+/**
+ * VIR_NODE_SEV_CBITPOS:
+ *
+ * Marco represents the CBit Position used by hypervisor when SEV is enabled.
+ */
+# define VIR_NODE_SEV_CBITPOS"cbitpos"
+
+/**
+ * VIR_NODE_SEV_REDUCED_PHYS_BITS:
+ *
+ * Marco represents the number of bits we lose in physical address space
+ * when SEV is enabled in the guest.
+ */
+# define VIR_NODE_SEV_REDUCED_PHYS_BITS"reduced-phys-bits"
+
+int virNodeGetSEVCapability (virConnectPtr conn,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);
+
 /**
  * virConnectFlags
  *
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index aa99cbb..cb2ab9c 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1309,6 +1309,11 @@ typedef int
   unsigned int action,
   unsigned int flags);
 
+typedef int
+(*virDrvNodeGetSEVCapability)(virConnectPtr conn,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags);
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1558,6 +1563,7 @@ struct _virHypervisorDriver {
 virDrvDomainSetLifecycleAction domainSetLifecycleAction;
 virDrvConnectCompareHypervisorCPU connectCompareHypervisorCPU;
 virDrvConnectBaselineHypervisorCPU connectBaselineHypervisorCPU;
+virDrvNodeGetSEVCapability nodeGetSEVCapability;
 };
 
 
diff --git a/src/libvirt-host.c b/src/libvirt-host.c
index 3aaf558..6c47b69 100644
--- a/src/libvirt-host.c
+++ b/src/libvirt-host.c
@@ -1639,3 +1639,51 @@ virNodeAllocPages(virConnectPtr conn,
 virDispatchError(conn);
 return -1;
 }
+
+/*
+ * virNodeGetSEVCapability:
+ * @conn: pointer to the hypervisor connection
+ * @params: where to store  SEV capabilities; output
+ * @nparams: pointer to number of SEV parameters; output
+ * @flags: extra flags; not used yet, so callers should always pass 0
+ *
+ * Get the SEV host capabilities, If hypervisor supports SEV then @params
+ * will contains PDH and certificate chain.
+ *
+ * Returns 0 in case of success, and -1 in case of failure.
+ */
+int
+virNodeGetSEVCapability(virConnectPtr conn,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+VIR_DEBUG("conn=%p, params=%p, nparams=%p (%d), flags=0x%x",
+  conn, params, nparams, *nparams, flags);
+
+virResetLastError();
+
+virCheckConnectReturn(conn, -1);
+virCheckNonNullArgGoto(nparams, error);
+virCheckNonNegativeArgGoto(*nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(conn->driver, conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->nodeGetSEVCapability) {
+int ret;
+ret = conn->driver->nodeGetSEVCapability(conn, params,
+ nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+
+virReportUnsupp

[libvirt] [PATCH v7 6/9] qemu: add support to launch SEV guest

2018-06-05 Thread Brijesh Singh
QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted
VMs on AMD platform using SEV feature. The various inputs required to
launch SEV guest is provided through the  tag. A typical
SEV guest launch command line looks like this:

# $QEMU ...\
  -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
  -machine memory-encryption=sev0 \

Signed-off-by: Brijesh Singh 
Reviewed-by: Erik Skultety 
---
 src/qemu/qemu_command.c | 41 
 src/qemu/qemu_process.c | 62 +
 tests/qemuxml2argvdata/launch-security-sev.args | 29 
 tests/qemuxml2argvdata/launch-security-sev.xml  | 37 +++
 tests/qemuxml2argvtest.c|  4 ++
 5 files changed, 173 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.args
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.xml

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 2f5cf4e..142455a 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7235,6 +7235,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
 qemuAppendLoadparmMachineParm(&buf, def);
 
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) && def->sev)
+virBufferAddLit(&buf, ",memory-encryption=sev0");
+
 virCommandAddArgBuffer(cmd, &buf);
 
 ret = 0;
@@ -9594,6 +9597,41 @@ qemuBuildTPMCommandLine(virCommandPtr cmd,
 return 0;
 }
 
+static int
+qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
+virDomainSevDefPtr sev)
+{
+virBuffer obj = VIR_BUFFER_INITIALIZER;
+qemuDomainObjPrivatePtr priv = vm->privateData;
+char *path = NULL;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
+  sev->policy, sev->cbitpos, sev->reduced_phys_bits);
+
+virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
+virBufferAsprintf(&obj, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
+virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
+
+if (sev->dh_cert) {
+if (virAsprintf(&path, "%s/dh_cert.base64", priv->libDir) < 0)
+return -1;
+virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
+VIR_FREE(path);
+}
+
+if (sev->session) {
+if (virAsprintf(&path, "%s/session.base64", priv->libDir) < 0)
+return -1;
+virBufferAsprintf(&obj, ",session-file=%s", path);
+VIR_FREE(path);
+}
+
+virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), NULL);
+return 0;
+}
 
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
@@ -10188,6 +10226,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
 if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
 goto error;
 
+if (qemuBuildSevCommandLine(vm, cmd, def->sev) < 0)
+goto error;
+
 if (snapshot)
 virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 3e97971..c624d63 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5818,6 +5818,65 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
 
 
 static int
+qemuBuildSevCreateFile(const char *configDir,
+   const char *name,
+   const char *data)
+{
+char *configFile;
+
+if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
+return -1;
+
+if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+virReportSystemError(errno, _("failed to write data to config '%s'"),
+ configFile);
+goto error;
+}
+
+VIR_FREE(configFile);
+return 0;
+
+ error:
+VIR_FREE(configFile);
+return -1;
+}
+
+
+static int
+qemuProcessPrepareSevGuestInput(virDomainObjPtr vm)
+{
+qemuDomainObjPrivatePtr priv = vm->privateData;
+virDomainDefPtr def = vm->def;
+virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+virDomainSevDefPtr sev = def->sev;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("Prepare SEV guest");
+
+if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+_("Domain %s asked for 'sev' launch but this "
+  "QEMU does not support SEV feature"), vm->def->name);
+return -1;
+}
+
+if (sev->dh_cert) {
+if (qemuBuildSevCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
+ 

Re: [libvirt] [PATCH v6 0/9] x86: Secure Encrypted Virtualization (AMD)

2018-06-04 Thread Brijesh Singh



On 05/29/2018 10:28 AM, Brijesh Singh wrote:

...




On 05/28/2018 05:06 AM, Erik Skultety wrote:

On Wed, May 23, 2018 at 04:18:25PM -0500, Brijesh Singh wrote:
This patch series provides support for launching an encrypted guest 
using

AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV 
feature

allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an 
XML document

that includes the following


...
   
  
  
  
  
o


It's sad that ^this didn't get more attention since Dan suggested a 
separate
API to get the certificates, because I myself don't feel like having 
2k/8k
base64 strings reported in domain capabilities is a good idea, it 
should only
report that the capability is supported with the given qemu and that 
the bit
stuff which is hypervisor specific. For the certificates,  which are 
not QEMU
specific, rather those are platform dependent and static, we should 
introduce a
virNodeGetSEVInfo (or something like that - I'm not good with names, 
but I
think we struggle with this in general) getter for that which would 
work on top
of virTypedParams so that it's extensible. Moreover, it would also be 
okay IMHO
to feed the return data of this new API not only with the certs but 
also with

the bit-related stuff, even though that's already obtained through
capabilities.







IIRC, Dan asked other folks to comment their preferences on APIs vs xml. 
I don't remember seeing any strong preferences hence I didn't rework on 
that code. But if majority of folks think that we should do APIs then I 
can certainly rework it in next patch.







I have not seen any other feedbacks, hence I will go with Erik's 
suggestions. I am reworking the patch to expose a new API 
"virNodeGetSEVParameters()". The API can be used to retrieve the SEV 
certificates etc. The signature looks like this:




# define VIR_NODE_SEV_PDH   "pdh"
# define VIR_NODE_SEV_CERT_CHAIN"cert-chain"
# define VIR_NODE_SEV_CBITPOS   "cbipos"
# define VIR_NODE_SEV_REDUCED_PHYS_BITS "reduced-phys-bits"

int  virNodeGetSEVParameters (virConnectPtr conn,
  virTypedParameterPtr params,
  int *nparams,
  unsigned int flags)

If anyone have better idea then please let me know. thanks

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v6 6/9] libvirt: add new public API to get launch security info

2018-06-01 Thread Brijesh Singh




On 05/28/2018 09:36 AM, Erik Skultety wrote:

On Wed, May 23, 2018 at 04:18:31PM -0500, Brijesh Singh wrote:

The API can be used outside the libvirt to get the launch security
information. When SEV is enabled, the API can be used to get the
measurement of the launch process.

Signed-off-by: Brijesh Singh 
---
  include/libvirt/libvirt-domain.h | 17 ++
  src/driver-hypervisor.h  |  7 ++
  src/libvirt-domain.c | 48 
  src/libvirt_public.syms  |  5 +
  4 files changed, 77 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index d7cbd187969d..f252d18da72f 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4764,4 +4764,21 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
  unsigned int action,
  unsigned int flags);

+/**
+ * Launch Security API
+ */
+
+/**
+ * VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT:
+ *
+ * Macro represents the launch measurement of the SEV guest,
+ * as VIR_TYPED_PARAM_STRING.
+ */
+#define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement"


fails make syntax-check because of indentation, should be "# define ..."

...


diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 95df3a0dbc7b..5ccae5da8883 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -785,4 +785,9 @@ LIBVIRT_4.1.0 {
  virStoragePoolLookupByTargetPath;
  } LIBVIRT_3.9.0;

+LIBVIRT_4.4.0 {
+global:
+virDomainGetLaunchSecurityInfo;
+} LIBVIRT_4.1.0;


Will most probably become 4.5.0 :(

Technically, I don't have any notes related to the functional changes,
therefore I'd give you my RB, however, I still find the naming confusing and I
can't think of something better. What if one day we'll actually be able to/need
to modify the configuration for some reason, we should reserve a name like this
for future modifications of launch-security data of the guest. Next, you're
preparing for adding support for some kind of setter in the virsh command, any
idea of what the setter data might be? Because I can imagine that you'd still
want to perform a measurement, but want to send additional arguments, to the
remote side's firmware to change the behaviour of the measurement and you can't
do this with a simple flag, you also need typed params for that which means
wou'd end up with something like:

int
virDomainLaunchSecurityMeasure(virDomainPtr domain,
virTypedParamsPtr send_params,
unsigned int nsend_params,
virTypedParamsPtr *recv_params,
unsigned int nrecv_params);




Actually we had similar API in previous patches but I followed the 
review feedback from earlier versions where it was hinted to use 
launch-security so that in future if any other architecture or platform 
provides the similar feature but with different naming then we don't 
have to introduce yet another APIs.


After guest owner validates the measurement, it will provide some 
additional information to VM. Typically this may include the some type 
of secret information and we may need to pass the following inputs via 
the API.


- secret blob
- length of the blob
- the memory address where the blob need to be copied




And you can both send additional arguments as well as receive arguments
according to the remote implementation, it's IMHO safer, but it's extremely
ugly at the same time and we're hitting the 'one function does all' kind of
scenario which we also shouldn't do. At the same time though, we could say that
any arguments that you might need to alter the result of the measurement should
be available prior to launching the guest in its XML config file, that way,
you'll never need anything apart from the recv_params,recv_nparams and the name
you're suggesting can stay, since only by using flags you can tell libvirt
daemon whether you want to work with the info in the config or take a
measurement or something else.

This was just me thinking out loud and would like to get some input from you
and/or other reviewer because even though I'm okay with the code, I don't want
to make a decision we can't take back just yet.

Erik



--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v6 3/9] conf: introduce launch-security element in domain

2018-05-29 Thread Brijesh Singh




On 05/28/2018 05:57 AM, Erik Skultety wrote:

On Wed, May 23, 2018 at 04:18:28PM -0500, Brijesh Singh wrote:

The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Signed-off-by: Brijesh Singh 
---
  docs/formatdomain.html.in  | 115 ++
  docs/schemas/domaincommon.rng  |  39 ++
  src/conf/domain_conf.c | 133 +
  src/conf/domain_conf.h |  27 +
  tests/genericxml2xmlindata/launch-security-sev.xml |  24 
  tests/genericxml2xmltest.c |   2 +
  6 files changed, 340 insertions(+)
  create mode 100644 tests/genericxml2xmlindata/launch-security-sev.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 665d0f25293e..cab08ea52003 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8310,6 +8310,121 @@ qemu-kvm -net nic,model=? /dev/null

  Note: DEA/TDEA is synonymous with DES/TDES.

+Secure Encrypted Virtualization (SEV)
+
+
+   The contents of the <launch-security type='sev'> 
element
+   is used to provide the guest owners input used for creating an encrypted
+   VM using the AMD SEV feature.
+
+   SEV is an extension to the AMD-V architecture which supports running
+   encrypted virtual machine (VMs) under the control of KVM. Encrypted
+   VMs have their pages (code and data) secured such that only the guest
+   itself has access to the unencrypted version. Each encrypted VM is
+   associated with a unique encryption key; if its data is accessed to a
+   different entity using a different key the encrypted guests data will
+   be incorrectly decrypted, leading to unintelligible data.
+
+   For more information see various input parameters and its format see 
the SEV API spec
+   https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";> 
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf 
+   Since 4.4.0
+   
+
+<domain>
+  ...
+  <launch-security type='sev'>
+<policy> 0x0001 </policy>
+<cbitpos> 47 </cbitpos>
+<reduced-phys-bits> 1 </reduced-phys-bits>
+<session> AAACCCDD=FFFCCCDSDS </session>
+<dh-cert> RBBBSDDD=FDDCCCDDDG </dh>
+  </sev>
+  ...
+</domain>
+
+
+
+  cbitpos
+  The required cbitpos element provides the C-bit (aka 
encryption bit)
+  location in guest page table entry. The value of cbitpos is
+  hypervisor dependent and can be obtained through the sev 
element
+  from the domain capabilities.


 From the cover letter it seemed like this is always the same as the value
reported in the domain capabilities and therefore I wrote what I wrote, but is
it always the same value as the one reported in capabilities as it's
hypervisor-dependent or can it in fact be configurable? Because if it can
change, then of course it makes sense to let user config this for a guest and
this is okay.



As I said in cover letter patch response, the value need to be user 
config to make the SEV launch migration safe. Consider the below example


1) user launches a guest on platform A.

On this platform hypervisor reports cbitpos=47 and reduced-phys-bit=1. 
While creating the guest QEMU requires caller to specify the cbitpos and 
reduced-phys-bit parameters. These params gets validate before creating 
the guest. If the user specified values are acceptable then QEMU will 
create the guest otherwise it will fail to create guest.


Typically cbitpos and reduced-phys-bit is platform and hypervisor 
dependent. If user does not know the value then it can query it with 
"virsh domcapabilities" before creating the domain XML file.



2) user tries to migrate the above guest to platform B.

a) If the platform B hypervisor supports the cbitpos and 
reduced-phys-bits value used in #1 then we have no issues.


b) if platform B hypervisor does not support those value then we should 
fail the migration. If we don't make the  and 
 user configurable then we will end up pick the 
different value compare to what was used during the launch flow.







+  
+  reduced-phys-bits
+  The required reduced-phys-bits element provides the 
physical
+  address

Re: [libvirt] [PATCH v6 2/9] qemu: introduce SEV feature in hypervisor capabilities

2018-05-29 Thread Brijesh Singh




On 05/28/2018 05:28 AM, Erik Skultety wrote:

On Wed, May 23, 2018 at 04:18:27PM -0500, Brijesh Singh wrote:

Extend hypervisor capabilities to include sev feature. When available,
hypervisor supports launching an encrypted VM on AMD platform. The
sev feature tag provides additional details like Platform Diffie-Hellman
(PDH) key and certificate chain which can be used by the guest owner to
establish a cryptographic session with the SEV firmware to negotiate
keys used for attestation or to provide secret during launch.

Signed-off-by: Brijesh Singh 
---


...and this one should be IMHO named
conf: Expose SEV in domain capabilities


  docs/formatdomaincaps.html.in  | 40 
  docs/schemas/domaincaps.rng| 20 
  src/conf/domain_capabilities.c | 20 
  src/conf/domain_capabilities.h |  1 +
  src/qemu/qemu_capabilities.c   |  2 ++
  5 files changed, 83 insertions(+)

diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index b68ae4b4f1f3..f37b059ba6b1 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -434,6 +434,12 @@
</enum>
  </gic>
  <vmcoreinfo supported='yes'/>
+<sev>
+  <pdh>UWxKSlNrVlRTRk5KVGtkSVFVMUU=</pdh>
+  
<cert-chain>VVd4S1NsTnJWbFJUUms1S1ZHdGtTVkZWTVVVPQ==</cert-chain>
+  <cbitpos>47</cbitpos>
+  <reduced-phys-bits>1</reduced-phys-bits>
+</sev>
</features>
  </domainCapabilities>
  
@@ -462,5 +468,39 @@

  Reports whether the vmcoreinfo feature can be enabled

+SEV capabilities
+
+AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under
+the sev element.
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When supported,
+guest owner can create a VM whose memory contents will be transparently
+encrypted with a key unique to that VM.
+
+
+For more details on SEV feature see:
+  https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";>
+SEV API spec and http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf";>
+SEV White Paper
+
+
+
+  pdh
+  A base64 encoded platform Diffie-Hellman public key which can be
+  exported to remote entities that desire to establish a secure transport
+  context with the SEV platform in order to transmit data securely.
+  cert-chain
+   A base64 encoded platform certificate chain that includes the 
platform
+  endorsement key (PEK), owners certificate authority (OCD), and chip
+  endorsement key (CEK).
+  cbitpos
+  When memory encryption is enabled, one of the physical address bits
+  (aka the C-bit) is utilized to mark if a memory page is protected. The
+  C-bit position is Hypervisor dependent.
+  reduced-phys-bits
+  When memory encryption is enabled, we lose certain bits in physical
+  address space. The number of bits we lose is hypervisor dependent.
+
+

  
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 5913d711a3fe..26265645b82a 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -184,6 +184,9 @@

  
  
+
+


needs 1 more level of indent...


Noted.





+

  

@@ -201,6 +204,23 @@
  


+  
+
+  
+
+  
+  
+
+  
+  
+
+  
+  
+
+  
+
+  
+

  

diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 6e2ab0a28796..3b767c45cbb3 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -542,6 +542,25 @@ virDomainCapsFeatureGICFormat(virBufferPtr buf,
  FORMAT_EPILOGUE(gic);
  }

+static void
+virDomainCapsFeatureSEVFormat(virBufferPtr buf,
+  virSEVCapabilityPtr const sev)
+{
+if (!sev)
+return;
+
+virBufferAddLit(buf, "\n");
+virBufferAdjustIndent(buf, 2);
+virBufferAsprintf(buf, "%d\n", sev->cbitpos);
+virBufferAsprintf(buf, "%d\n",
+  sev->reduced_phys_bits);
+virBufferEscapeString(buf, "%s\n", sev->pdh);
+virBufferEscapeString(buf, "%s\n",
+  sev->cert_chain);


As I said, I have to agree with Dan here that reporting the 8k string in
capabilities is a good idea, so we can store it, we just wouldn't format it
^here...




Sure, if decide to go with new APIs then this code need to be reworked.




+virBufferAdjustIndent(buf, -2);
+virBufferAddLit(buf, "\n");
+}
+

  char *
  virDomainCaps

Re: [libvirt] [PATCH v6 0/9] x86: Secure Encrypted Virtualization (AMD)

2018-05-29 Thread Brijesh Singh




On 05/28/2018 05:06 AM, Erik Skultety wrote:

On Wed, May 23, 2018 at 04:18:25PM -0500, Brijesh Singh wrote:

This patch series provides support for launching an encrypted guest using
AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV feature
allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
that includes the following


...
   
  
  
  
  
o


It's sad that ^this didn't get more attention since Dan suggested a separate
API to get the certificates, because I myself don't feel like having 2k/8k
base64 strings reported in domain capabilities is a good idea, it should only
report that the capability is supported with the given qemu and that the bit
stuff which is hypervisor specific. For the certificates,  which are not QEMU
specific, rather those are platform dependent and static, we should introduce a
virNodeGetSEVInfo (or something like that - I'm not good with names, but I
think we struggle with this in general) getter for that which would work on top
of virTypedParams so that it's extensible. Moreover, it would also be okay IMHO
to feed the return data of this new API not only with the certs but also with
the bit-related stuff, even though that's already obtained through
capabilities.







IIRC, Dan asked other folks to comment their preferences on APIs vs xml. 
I don't remember seeing any strong preferences hence I didn't rework on 
that code. But if majority of folks think that we should do APIs then I 
can certainly rework it in next patch.





If  is provided then we indicate that hypervisor is capable of launching
SEV guest.

2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in 
case
if guest owner wish to establish a secure connection with SEV firmware to
negotiate a key used for validating the measurement.

3. mgmt tool requests to start a guest calling virCreateXML(), passing 
VIR_DOMAIN_START_PAUSED.
The xml would include


  /* the value is same as what is obtained via 
virConnectGetDomainCapabilities()
  /* the value is same as what is 
obtained via virConnectGetDomainCapabilities()
..  /* guest owners diffie-hellman key */ (optional)
.. /* guest owners session blob */ (optional)
.. /* guest policy */ (optional)



Now that I'm looking at the design, why do we need to report ,
 in the domain XML if that is platform specific, it's static
and we already report it withing capabilities? If it can't be used for a
per-guest configuration, i.e. it can change, I don't think we should expose the
same information on multiple places.





We had some discussion about this on QEMU mailing list. To make SEV 
launch migration safe, we require user to provide the cbitpos and 
reduced-phys-bit in domain XML as an input to the launch flow. The 
launch flow should not make a platform dependent call to obtain these 
value. If user does not know the cbitpos for its given platform then it 
can obtain it through the domain capabilities.





Still, does anyone have another idea for an improvement?

Erik



--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v6 1/9] qemu: provide support to query the SEV capability

2018-05-29 Thread Brijesh Singh




On 05/28/2018 02:25 AM, Erik Skultety wrote:

On Wed, May 23, 2018 at 04:18:26PM -0500, Brijesh Singh wrote:

QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Signed-off-by: Brijesh Singh 
---
  src/conf/domain_capabilities.h | 13 
  src/qemu/qemu_capabilities.c   | 47 ++
  src/qemu/qemu_capabilities.h   |  4 ++
  src/qemu/qemu_capspriv.h   |  4 ++
  src/qemu/qemu_monitor.c|  9 +++
  src/qemu/qemu_monitor.h|  3 +
  src/qemu/qemu_monitor_json.c   | 74 ++
  src/qemu/qemu_monitor_json.h   |  3 +
  .../caps_2.12.0.x86_64.replies | 10 +++
  tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |  3 +-
  10 files changed, 169 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 9b852e8649bf..c1093234ceb8 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -137,6 +137,19 @@ struct _virDomainCapsCPU {
  virDomainCapsCPUModelsPtr custom;
  };

+/*
+ * SEV capabilities
+ */
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+char *pdh;
+char *cert_chain;
+unsigned int cbitpos;
+unsigned int reduced_phys_bits;
+};
+
+
  struct _virDomainCaps {
  virObjectLockable parent;

diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 8a63db5f4f33..49b74f7e12c1 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -489,6 +489,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"screendump_device",
"hda-output",
"blockdev-del",
+  "sev-guest",
  );


@@ -555,6 +556,8 @@ struct _virQEMUCaps {
  size_t ngicCapabilities;
  virGICCapability *gicCapabilities;

+virSEVCapability *sevCapabilities;
+
  virQEMUCapsHostCPUData kvmCPU;
  virQEMUCapsHostCPUData tcgCPU;
  };
@@ -1121,6 +1124,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
  { "virtual-css-bridge", QEMU_CAPS_CCW },
  { "vfio-ccw", QEMU_CAPS_DEVICE_VFIO_CCW },
  { "hda-output", QEMU_CAPS_HDA_OUTPUT },
+{ "sev-guest", QEMU_CAPS_SEV_GUEST },
  };

  static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
@@ -2050,6 +2054,28 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
  }


+void
+virQEMUSevCapabilitiesFree(virSEVCapability *cap)


Since virSEVCapability will be added to virDomainCaps too, you need to move
^this into domain_capabilities.c so it will become virSEVCapabilityFree, I've
got a further comment regarding this in patch 2 as well.

NOTE: notice the SEV in the function name, we should stay consistent in naming
and since SEV is the name of the feature...




Noted, I will make these changes in next rev.



+{
+if (!cap)
+return;
+
+VIR_FREE(cap->pdh);
+VIR_FREE(cap->cert_chain);
+VIR_FREE(cap);
+}
+
+
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+  virSEVCapability *capabilities)
+{
+virQEMUSevCapabilitiesFree(qemuCaps->sevCapabilities);


virSEVCapabilityFree(qemuCaps->sevCapabilities)


+
+qemuCaps->sevCapabilities = capabilities;
+}
+
+
  static int
  virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
  qemuMonitorPtr mon)
@@ -2580,6 +2606,21 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr 
qemuCaps,
  }


+static int
+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+   qemuMonitorPtr mon)
+{
+virSEVCapability *caps = NULL;
+
+if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+return -1;
+
+virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+return 0;
+}
+
+
  bool
  virQEMUCapsCPUFilterFeatures(const char *name,
   void *opaque)
@@ -3965,6 +4006,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
  virQEMUCapsClear(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW);
  }

+/* Probe for SEV capabilities */
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
+virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
+}
+
  ret = 0;
   cleanup:
  return ret;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 3e120e64c0b4..8b7eef4359b7 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -473,6 +473,7 @@ typedef enum { /* virQE

[libvirt] [PATCH v6 4/9] qemu/cgroup: add /dev/sev in shared devices list

2018-05-23 Thread Brijesh Singh
QEMU uses /dev/sev device while creating the SEV guest, lets add /dev/sev
in the list of devices allowed to be accessed by the QEMU.

Signed-off-by: Brijesh Singh <>
---
 docs/drvqemu.html.in   | 1 +
 src/qemu/qemu.conf | 2 +-
 src/qemu/qemu_cgroup.c | 2 +-
 src/qemu/test_libvirtd_qemu.aug.in | 1 +
 4 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/docs/drvqemu.html.in b/docs/drvqemu.html.in
index cbd159da3e10..7c33a1830c7b 100644
--- a/docs/drvqemu.html.in
+++ b/docs/drvqemu.html.in
@@ -397,6 +397,7 @@ chmod o+x /path/to/directory
 /dev/random, /dev/urandom,
 /dev/ptmx, /dev/kvm, /dev/kqemu,
 /dev/rtc, /dev/hpet, /dev/net/tun
+/dev/sev
 
 
 
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 31738ff19cfc..c6aeeb610310 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -451,7 +451,7 @@
 #"/dev/null", "/dev/full", "/dev/zero",
 #"/dev/random", "/dev/urandom",
 #"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-#"/dev/rtc","/dev/hpet"
+#"/dev/rtc","/dev/hpet", "/dev/sev"
 #]
 #
 # RDMA migration requires the following extra files to be added to the list:
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 546a4c8e6330..21dcb3cefe37 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -47,7 +47,7 @@ const char *const defaultDeviceACL[] = {
 "/dev/null", "/dev/full", "/dev/zero",
 "/dev/random", "/dev/urandom",
 "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-"/dev/rtc", "/dev/hpet",
+"/dev/rtc", "/dev/hpet", "/dev/sev",
 NULL,
 };
 #define DEVICE_PTY_MAJOR 136
diff --git a/src/qemu/test_libvirtd_qemu.aug.in 
b/src/qemu/test_libvirtd_qemu.aug.in
index 95885e9f06ae..847d77ae0622 100644
--- a/src/qemu/test_libvirtd_qemu.aug.in
+++ b/src/qemu/test_libvirtd_qemu.aug.in
@@ -60,6 +60,7 @@ module Test_libvirtd_qemu =
 { "8" = "/dev/kqemu" }
 { "9" = "/dev/rtc" }
 { "10" = "/dev/hpet" }
+{ "11" = "/dev/sev" }
 }
 { "save_image_format" = "raw" }
 { "dump_image_format" = "raw" }
-- 
2.14.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v6 7/9] remote: implement the remote protocol for launch security

2018-05-23 Thread Brijesh Singh
Add remote support for launch security info.

Signed-off-by: Brijesh Singh 
---
 src/remote/remote_daemon_dispatch.c | 47 +
 src/remote/remote_driver.c  | 42 -
 src/remote/remote_protocol.x| 20 +++-
 src/remote_protocol-structs | 11 +
 4 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index a8a5932d7134..30b22fbce092 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -3109,6 +3109,53 @@ remoteDispatchNodeGetMemoryStats(virNetServerPtr server 
ATTRIBUTE_UNUSED,
 return rv;
 }
 
+static int
+remoteDispatchDomainGetLaunchSecurityInfo(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+  virNetMessagePtr msg 
ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  
remote_domain_get_launch_security_info_args *args,
+  
remote_domain_get_launch_security_info_ret *ret)
+{
+virDomainPtr dom = NULL;
+virTypedParameterPtr params = NULL;
+int nparams = 0;
+int rv = -1;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, args->flags) < 
0)
+goto cleanup;
+
+if (nparams > REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+goto cleanup;
+}
+
+if (virTypedParamsSerialize(params, nparams,
+(virTypedParameterRemotePtr *) 
&ret->params.params_val,
+&ret->params.params_len,
+args->flags) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0)
+virNetMessageSaveError(rerr);
+virTypedParamsFree(params, nparams);
+virObjectUnref(dom);
+return rv;
+}
+
 static int
 remoteDispatchDomainGetPerfEvents(virNetServerPtr server ATTRIBUTE_UNUSED,
   virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 95437b43657e..fc649276799e 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1965,6 +1965,45 @@ remoteDomainGetNumaParameters(virDomainPtr domain,
 return rv;
 }
 
+static int
+remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags)
+{
+int rv = -1;
+remote_domain_get_launch_security_info_args args;
+remote_domain_get_launch_security_info_ret ret;
+struct private_data *priv = domain->conn->privateData;
+
+remoteDriverLock(priv);
+
+make_nonnull_domain(&args.dom, domain);
+args.flags = flags;
+
+memset(&ret, 0, sizeof(ret));
+if (call(domain->conn, priv, 0, 
REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_args, 
(char *) &args,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_ret, (char 
*) &ret) == -1)
+goto done;
+
+if (virTypedParamsDeserialize((virTypedParameterRemotePtr) 
ret.params.params_val,
+  ret.params.params_len,
+  
REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX,
+  params,
+  nparams) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+xdr_free((xdrproc_t) xdr_remote_domain_get_launch_security_info_ret,
+ (char *) &ret);
+ done:
+remoteDriverUnlock(priv);
+return rv;
+}
+
 static int
 remoteDomainGetPerfEvents(virDomainPtr domain,
   virTypedParameterPtr *params,
@@ -8448,7 +8487,8 @@ static virHypervisorDriver hypervisor_driver = {
 .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */
 .domainSetVcpu = remoteDomainSetVcpu, /* 3.1.0 */
 .domainSetBlockThreshold = remoteDomainSetBlockThreshold, /* 3.2.0 */
-.domainSetLifecycleAction = remoteDomainSetLifecycleAction /* 3.9.0 */
+.domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */
+.domainGetLaunchSecurityInfo = remoteDomainGetLaunchSecurityInfo 

[libvirt] [PATCH v6 9/9] virsh: implement new command for launch security

2018-05-23 Thread Brijesh Singh
Add new 'launch-security' command, the command can be used to get or set
the launch security information when booting encrypted VMs.

Signed-off-by: Brijesh Singh 
---
 tools/virsh-domain.c | 81 
 tools/virsh.pod  |  5 
 2 files changed, 86 insertions(+)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index cfbbf5a7bc39..27bb702c8bb7 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13870,6 +13870,81 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd)
 return ret >= 0;
 }
 
+/*
+ * "launch-security" command
+ */
+static const vshCmdInfo info_launch_security[] = {
+{.name = "help",
+.data = N_("Get or set launch-security information")
+},
+{.name = "desc",
+.data = N_("Get or set the current launch-security information for "
+   "a guest domain.\n"
+   "To get the launch-security information use following"
+   "command: \n\n"
+   "virsh # launch-security ")
+},
+{.name = NULL}
+};
+
+static const vshCmdOptDef opts_launch_security[] = {
+VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+VIRSH_COMMON_OPT_DOMAIN_CONFIG,
+VIRSH_COMMON_OPT_DOMAIN_LIVE,
+VIRSH_COMMON_OPT_DOMAIN_CURRENT,
+{.name = NULL}
+};
+
+static void
+virshPrintLaunchSecurityInfo(vshControl *ctl, virTypedParameterPtr params,
+ int nparams)
+{
+size_t i;
+
+for (i = 0; i < nparams; i++) {
+if (params[i].type == VIR_TYPED_PARAM_STRING)
+vshPrintExtra(ctl, "%-15s: %s\n", params[i].field, 
params[i].value.s);
+}
+}
+
+static bool
+cmdLaunchSecurity(vshControl *ctl, const vshCmd *cmd)
+{
+virDomainPtr dom;
+int nparams = 0;
+virTypedParameterPtr params = NULL;
+bool ret = false;
+unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+bool current = vshCommandOptBool(cmd, "current");
+bool config = vshCommandOptBool(cmd, "config");
+bool live = vshCommandOptBool(cmd, "live");
+
+VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
+VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+
+if (config)
+flags |= VIR_DOMAIN_AFFECT_CONFIG;
+if (live)
+flags |= VIR_DOMAIN_AFFECT_LIVE;
+
+if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+return false;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, flags) != 0) {
+vshError(ctl, "%s", _("Unable to get launch security info"));
+goto cleanup;
+}
+
+virshPrintLaunchSecurityInfo(ctl, params, nparams);
+
+ret = true;
+ cleanup:
+virTypedParamsFree(params, nparams);
+virshDomainFree(dom);
+return ret;
+}
+
+
 const vshCmdDef domManagementCmds[] = {
 {.name = "attach-device",
  .handler = cmdAttachDevice,
@@ -14485,5 +14560,11 @@ const vshCmdDef domManagementCmds[] = {
  .info = info_domblkthreshold,
  .flags = 0
 },
+{.name = "launch-security-info",
+ .handler = cmdLaunchSecurity,
+ .opts = opts_launch_security,
+ .info = info_launch_security,
+ .flags = 0
+},
 {.name = NULL}
 };
diff --git a/tools/virsh.pod b/tools/virsh.pod
index 929958a9533c..31bb26bda2ac 100644
--- a/tools/virsh.pod
+++ b/tools/virsh.pod
@@ -2899,6 +2899,11 @@ See B for information on I.
 Output the IP address and port number for the VNC display. If the information
 is not available the processes will provide an exit code of 1.
 
+=item B I
+
+Get the measurement of the memory contents encrypted through the launch
+sequence when I is provided.
+
 =back
 
 =head1 DEVICE COMMANDS
-- 
2.14.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v6 2/9] qemu: introduce SEV feature in hypervisor capabilities

2018-05-23 Thread Brijesh Singh
Extend hypervisor capabilities to include sev feature. When available,
hypervisor supports launching an encrypted VM on AMD platform. The
sev feature tag provides additional details like Platform Diffie-Hellman
(PDH) key and certificate chain which can be used by the guest owner to
establish a cryptographic session with the SEV firmware to negotiate
keys used for attestation or to provide secret during launch.

Signed-off-by: Brijesh Singh 
---
 docs/formatdomaincaps.html.in  | 40 
 docs/schemas/domaincaps.rng| 20 
 src/conf/domain_capabilities.c | 20 
 src/conf/domain_capabilities.h |  1 +
 src/qemu/qemu_capabilities.c   |  2 ++
 5 files changed, 83 insertions(+)

diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index b68ae4b4f1f3..f37b059ba6b1 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -434,6 +434,12 @@
   </enum>
 </gic>
 <vmcoreinfo supported='yes'/>
+<sev>
+  <pdh>UWxKSlNrVlRTRk5KVGtkSVFVMUU=</pdh>
+  
<cert-chain>VVd4S1NsTnJWbFJUUms1S1ZHdGtTVkZWTVVVPQ==</cert-chain>
+  <cbitpos>47</cbitpos>
+  <reduced-phys-bits>1</reduced-phys-bits>
+</sev>
   </features>
 </domainCapabilities>
 
@@ -462,5 +468,39 @@
 
 Reports whether the vmcoreinfo feature can be enabled
 
+SEV capabilities
+
+AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under
+the sev element.
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When supported,
+guest owner can create a VM whose memory contents will be transparently
+encrypted with a key unique to that VM.
+
+
+For more details on SEV feature see:
+  https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";>
+SEV API spec and http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf";>
+SEV White Paper
+
+
+
+  pdh
+  A base64 encoded platform Diffie-Hellman public key which can be
+  exported to remote entities that desire to establish a secure transport
+  context with the SEV platform in order to transmit data securely.
+  cert-chain
+   A base64 encoded platform certificate chain that includes the 
platform
+  endorsement key (PEK), owners certificate authority (OCD), and chip
+  endorsement key (CEK).
+  cbitpos
+  When memory encryption is enabled, one of the physical address bits
+  (aka the C-bit) is utilized to mark if a memory page is protected. The
+  C-bit position is Hypervisor dependent.
+  reduced-phys-bits
+  When memory encryption is enabled, we lose certain bits in physical
+  address space. The number of bits we lose is hypervisor dependent.
+
+
   
 
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 5913d711a3fe..26265645b82a 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -184,6 +184,9 @@
   
 
 
+
+
+
   
 
   
@@ -201,6 +204,23 @@
 
   
 
+  
+
+  
+
+  
+  
+
+  
+  
+
+  
+  
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index 6e2ab0a28796..3b767c45cbb3 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -542,6 +542,25 @@ virDomainCapsFeatureGICFormat(virBufferPtr buf,
 FORMAT_EPILOGUE(gic);
 }
 
+static void
+virDomainCapsFeatureSEVFormat(virBufferPtr buf,
+  virSEVCapabilityPtr const sev)
+{
+if (!sev)
+return;
+
+virBufferAddLit(buf, "\n");
+virBufferAdjustIndent(buf, 2);
+virBufferAsprintf(buf, "%d\n", sev->cbitpos);
+virBufferAsprintf(buf, "%d\n",
+  sev->reduced_phys_bits);
+virBufferEscapeString(buf, "%s\n", sev->pdh);
+virBufferEscapeString(buf, "%s\n",
+  sev->cert_chain);
+virBufferAdjustIndent(buf, -2);
+virBufferAddLit(buf, "\n");
+}
+
 
 char *
 virDomainCapsFormat(virDomainCapsPtr const caps)
@@ -585,6 +604,7 @@ virDomainCapsFormat(virDomainCapsPtr const caps)
 virDomainCapsFeatureGICFormat(&buf, &caps->gic);
 virBufferAsprintf(&buf, "\n",
   caps->vmcoreinfo ? "yes" : "no");
+virDomainCapsFeatureSEVFormat(&buf, caps->sev);
 
 virBufferAdjustIndent(&buf, -2);
 virBufferAddLit(&buf, "\n");
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index c

[libvirt] [PATCH v6 8/9] qemu: Add support to launch security info

2018-05-23 Thread Brijesh Singh
This patch implements the internal driver API for launch event into
qemu driver. When SEV is enabled, execute 'query-sev-launch-measurement'
to get the measurement of memory encrypted through launch sequence.

Signed-off-by: Brijesh Singh 
---
 src/qemu/qemu_driver.c   | 68 
 src/qemu/qemu_monitor.c  |  8 ++
 src/qemu/qemu_monitor.h  |  3 ++
 src/qemu/qemu_monitor_json.c | 42 +++
 src/qemu/qemu_monitor_json.h |  2 ++
 5 files changed, 123 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 3a328e5d4679..6569dea32fce 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21194,6 +21194,73 @@ qemuDomainSetLifecycleAction(virDomainPtr dom,
 }
 
 
+static int
+qemuDomainGetSevMeasurement(virQEMUDriverPtr driver,
+virDomainObjPtr vm,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+int ret = -1;
+char *tmp;
+int maxpar = 0;
+
+virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+return -1;
+
+if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
+goto endjob;
+
+tmp = qemuMonitorGetSevMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
+if (tmp == NULL)
+goto endjob;
+
+if (qemuDomainObjExitMonitor(driver, vm) < 0)
+goto endjob;
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
+tmp) < 0)
+goto endjob;
+
+ret = 0;
+
+ endjob:
+qemuDomainObjEndJob(driver, vm);
+return ret;
+}
+
+
+static int
+qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+virQEMUDriverPtr driver = domain->conn->privateData;
+virDomainObjPtr vm;
+int ret = -1;
+
+if (!(vm = qemuDomObjFromDomain(domain)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
+goto cleanup;
+
+if (vm->def->sev) {
+if (qemuDomainGetSevMeasurement(driver, vm, params, nparams, flags) < 
0)
+goto cleanup;
+}
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
+
 static virHypervisorDriver qemuHypervisorDriver = {
 .name = QEMU_DRIVER_NAME,
 .connectURIProbe = qemuConnectURIProbe,
@@ -21414,6 +21481,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
 .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */
 .domainSetBlockThreshold = qemuDomainSetBlockThreshold, /* 3.2.0 */
 .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
+.domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.2.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 3b034930408c..977cbe5a41f8 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4226,3 +4226,11 @@ qemuMonitorBlockdevDel(qemuMonitorPtr mon,
 
 return qemuMonitorJSONBlockdevDel(mon, nodename);
 }
+
+char *
+qemuMonitorGetSevMeasurement(qemuMonitorPtr mon)
+{
+QEMU_CHECK_MONITOR_NULL(mon);
+
+return qemuMonitorJSONGetSevMeasurement(mon);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index b1b7ef09c929..8a64ae5f3d96 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1137,4 +1137,7 @@ int qemuMonitorBlockdevAdd(qemuMonitorPtr mon,
 int qemuMonitorBlockdevDel(qemuMonitorPtr mon,
const char *nodename);
 
+char *
+qemuMonitorGetSevMeasurement(qemuMonitorPtr mon);
+
 #endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 24d3a2ff412f..041f595ca1e4 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -8024,3 +8024,45 @@ qemuMonitorJSONBlockdevDel(qemuMonitorPtr mon,
 virJSONValueFree(reply);
 return ret;
 }
+
+/**
+ * The function is used to retrieve the measurement of SEV guest.
+ * The measurement is signature of the memory contents that was encrypted
+ * through the SEV launch flow.
+ *
+ * A example jason output:
+ *
+ * { "execute" : "query-sev-launch-measure" }
+ * { "return" : { "data" : "4l8LXeNlSPUDlXPJG5966/8%YZ" } }
+ */
+char *
+qemuMonitorJSONGetSevMeasurement(qemuMonitorPtr mon)
+{
+const char *tmp;
+char *measurement = NULL;
+virJSONValuePtr cmd;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr data;
+
+if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NULL)))
+ return NULL;
+
+

[libvirt] [PATCH v6 3/9] conf: introduce launch-security element in domain

2018-05-23 Thread Brijesh Singh
The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Signed-off-by: Brijesh Singh 
---
 docs/formatdomain.html.in  | 115 ++
 docs/schemas/domaincommon.rng  |  39 ++
 src/conf/domain_conf.c | 133 +
 src/conf/domain_conf.h |  27 +
 tests/genericxml2xmlindata/launch-security-sev.xml |  24 
 tests/genericxml2xmltest.c |   2 +
 6 files changed, 340 insertions(+)
 create mode 100644 tests/genericxml2xmlindata/launch-security-sev.xml

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 665d0f25293e..cab08ea52003 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8310,6 +8310,121 @@ qemu-kvm -net nic,model=? /dev/null
 
 Note: DEA/TDEA is synonymous with DES/TDES.
 
+Secure Encrypted Virtualization (SEV)
+
+
+   The contents of the <launch-security type='sev'> 
element
+   is used to provide the guest owners input used for creating an encrypted
+   VM using the AMD SEV feature.
+
+   SEV is an extension to the AMD-V architecture which supports running
+   encrypted virtual machine (VMs) under the control of KVM. Encrypted
+   VMs have their pages (code and data) secured such that only the guest
+   itself has access to the unencrypted version. Each encrypted VM is
+   associated with a unique encryption key; if its data is accessed to a
+   different entity using a different key the encrypted guests data will
+   be incorrectly decrypted, leading to unintelligible data.
+
+   For more information see various input parameters and its format see 
the SEV API spec
+   https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";> 
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf 
+   Since 4.4.0
+   
+
+<domain>
+  ...
+  <launch-security type='sev'>
+<policy> 0x0001 </policy>
+<cbitpos> 47 </cbitpos>
+<reduced-phys-bits> 1 </reduced-phys-bits>
+<session> AAACCCDD=FFFCCCDSDS </session>
+<dh-cert> RBBBSDDD=FDDCCCDDDG </dh>
+  </sev>
+  ...
+</domain>
+
+
+
+  cbitpos
+  The required cbitpos element provides the C-bit (aka 
encryption bit)
+  location in guest page table entry. The value of cbitpos is
+  hypervisor dependent and can be obtained through the sev 
element
+  from the domain capabilities.
+  
+  reduced-phys-bits
+  The required reduced-phys-bits element provides the 
physical
+  address bit reducation. Similar to cbitpos the value of 

+  reduced-phys-bit is hypervisor dependent and can be obtained
+  through the sev element from the domain capabilities.
+  
+  policy
+  The required policy element provides the guest policy
+  which must be maintained by the SEV firmware. This policy is enforced by
+  the firmware and restricts what configuration and operational commands
+  can be performed on this guest by the hypervisor. The guest policy
+  provided during guest launch is bound to the guest and cannot be changed
+  throughout the lifetime of the guest. The policy is also transmitted
+  during snapshot and migration flows and enforced on the destination 
platform.
+
+  The guest policy is a 4 unsigned byte with the fields shown in Table:
+
+  
+
+   Bit(s) 
+   Description 
+
+
+   0 
+   Debugging of the guest is disallowed when set 
+
+
+   1 
+   Sharing keys with other guests is disallowed when set 
+
+
+   2 
+   SEV-ES is required when set
+
+
+   3 
+   Sending the guest to another platform is disallowed when 
set
+
+
+   4 
+   The guest must not be transmitted to another platform that is
+   not in the domain when set. 
+
+
+   5 
+   The guest must not be transmitted to another platform that is
+   not SEV capable when set. 
+
+
+   15:6 
+   reserved 
+
+
+   16:32 
+   The gu

[libvirt] [PATCH v6 1/9] qemu: provide support to query the SEV capability

2018-05-23 Thread Brijesh Singh
QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Signed-off-by: Brijesh Singh 
---
 src/conf/domain_capabilities.h | 13 
 src/qemu/qemu_capabilities.c   | 47 ++
 src/qemu/qemu_capabilities.h   |  4 ++
 src/qemu/qemu_capspriv.h   |  4 ++
 src/qemu/qemu_monitor.c|  9 +++
 src/qemu/qemu_monitor.h|  3 +
 src/qemu/qemu_monitor_json.c   | 74 ++
 src/qemu/qemu_monitor_json.h   |  3 +
 .../caps_2.12.0.x86_64.replies | 10 +++
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |  3 +-
 10 files changed, 169 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 9b852e8649bf..c1093234ceb8 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -137,6 +137,19 @@ struct _virDomainCapsCPU {
 virDomainCapsCPUModelsPtr custom;
 };
 
+/*
+ * SEV capabilities
+ */
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+char *pdh;
+char *cert_chain;
+unsigned int cbitpos;
+unsigned int reduced_phys_bits;
+};
+
+
 struct _virDomainCaps {
 virObjectLockable parent;
 
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index 8a63db5f4f33..49b74f7e12c1 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -489,6 +489,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
   "screendump_device",
   "hda-output",
   "blockdev-del",
+  "sev-guest",
 );
 
 
@@ -555,6 +556,8 @@ struct _virQEMUCaps {
 size_t ngicCapabilities;
 virGICCapability *gicCapabilities;
 
+virSEVCapability *sevCapabilities;
+
 virQEMUCapsHostCPUData kvmCPU;
 virQEMUCapsHostCPUData tcgCPU;
 };
@@ -1121,6 +1124,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
 { "virtual-css-bridge", QEMU_CAPS_CCW },
 { "vfio-ccw", QEMU_CAPS_DEVICE_VFIO_CCW },
 { "hda-output", QEMU_CAPS_HDA_OUTPUT },
+{ "sev-guest", QEMU_CAPS_SEV_GUEST },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsDevicePropsVirtioBalloon[] = {
@@ -2050,6 +2054,28 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
 }
 
 
+void
+virQEMUSevCapabilitiesFree(virSEVCapability *cap)
+{
+if (!cap)
+return;
+
+VIR_FREE(cap->pdh);
+VIR_FREE(cap->cert_chain);
+VIR_FREE(cap);
+}
+
+
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+  virSEVCapability *capabilities)
+{
+virQEMUSevCapabilitiesFree(qemuCaps->sevCapabilities);
+
+qemuCaps->sevCapabilities = capabilities;
+}
+
+
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
 qemuMonitorPtr mon)
@@ -2580,6 +2606,21 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr 
qemuCaps,
 }
 
 
+static int
+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+   qemuMonitorPtr mon)
+{
+virSEVCapability *caps = NULL;
+
+if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+return -1;
+
+virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+return 0;
+}
+
+
 bool
 virQEMUCapsCPUFilterFeatures(const char *name,
  void *opaque)
@@ -3965,6 +4006,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
 virQEMUCapsClear(qemuCaps, QEMU_CAPS_DEVICE_VFIO_CCW);
 }
 
+/* Probe for SEV capabilities */
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
+virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
+}
+
 ret = 0;
  cleanup:
 return ret;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 3e120e64c0b4..8b7eef4359b7 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -473,6 +473,7 @@ typedef enum { /* virQEMUCapsFlags grouping marker for 
syntax-check */
 QEMU_CAPS_SCREENDUMP_DEVICE, /* screendump command accepts device & head */
 QEMU_CAPS_HDA_OUTPUT, /* -device hda-output */
 QEMU_CAPS_BLOCKDEV_DEL, /* blockdev-del is supported */
+QEMU_CAPS_SEV_GUEST, /* -object sev-guest,... */
 
 QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
@@ -599,4 +600,7 @@ bool virQEMUCapsGuestIsNative(virArch host,
 bool virQEMUCapsCPUFilterFeatures(const char *name,
   void *opaque);
 
+void
+virQEMUSevCapabilitiesFree(virSEVCapab

[libvirt] [PATCH v6 0/9] x86: Secure Encrypted Virtualization (AMD)

2018-05-23 Thread Brijesh Singh
This patch series provides support for launching an encrypted guest using
AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV feature
allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
that includes the following


...
  
 
 
 
 


If  is provided then we indicate that hypervisor is capable of launching
SEV guest. 

2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in 
case
if guest owner wish to establish a secure connection with SEV firmware to
negotiate a key used for validating the measurement.

3. mgmt tool requests to start a guest calling virCreateXML(), passing 
VIR_DOMAIN_START_PAUSED.
The xml would include


 /* the value is same as what is obtained via 
virConnectGetDomainCapabilities()
 /* the value is same as what is 
obtained via virConnectGetDomainCapabilities()
   ..  /* guest owners diffie-hellman key */ (optional)
   .. /* guest owners session blob */ (optional)
   .. /* guest policy */ (optional)


4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
args looks like this:

# $QEMU ..
-machine memory-encryption=sev0 \
-object sev-guest,id=sev0,dh-cert-file=

5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event

6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls 
virDomainGetLaunchSecretInfo()
to retrieve the measurement of encrypted memory.

7. (optional) mgmt tool can provide the measurement value to guest owner, which 
can
validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
it resumes the guest otherwise it calls destroy() to kill the guest.

8. mgmt tool resumes the guest

TODO:
* SEV guest require to use DMA apis for the virtio devices. In order to use the 
DMA
apis the virtio devices must have this tag



It is a bit unclear to me where these changes need to go. Do we need to
modify the libvirt to automatically add these when SEV is enabled or
we ask mgmt tool to make sure that it creates XML with right tag to enable
the DMA APIs for virtio devices. I am looking for some suggestions.

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

SEV Firmware API spec is available at:
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Change since v5:
* drop the seperate test patch and merge the code with other patches.
* rename the xml from sev -> launch-security-sev
* make policy field mandatory
* address multiple feedback from previous reviews.

Changes since v4:
* add /dev/sev in shared device list

Changes since v3:
* rename QEMU_CAPS_SEV -> QEMU_CAPS_SEV_GUEST
* update caps_2.12.0.x86_64.replies to include query-sev-capabilities data

Changes since v2:
* make cbitpos, policy and reduced-phys-bits as unsigned int
* update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr *params
instead of virTypedParameterPtr params.

Changes since v1:
* rename  ->  for domain
* add more information about policy and other fields in domaincaps.html
* split the domain_conf support in two patches
* add virDomainGetLaunchInfo() to retrieve the SEV measurement
* extend virsh command to show the domain's launch security information
* add test cases to validate newly added  element
* fix issues reported with 'make check' and 'make syntax-check'

The complete git tree is available at:
https://github.com/codomania/libvirt/tree/v6

Brijesh Singh (9):
  qemu: provide support to query the SEV capability
  qemu: introduce SEV feature in hypervisor capabilities
  conf: introduce launch-security element in domain
  qemu/cgroup: add /dev/sev in shared devices list
  qemu: add support to launch SEV guest
  libvirt: add new public API to get launch security info
  remote: implement the remote protocol for launch security
  qemu: Add support to launch security info
  virsh: implement new command for launch security

 docs/drvqemu.html.in   |   1 +
 docs/formatdomain.html.in  | 115 ++
 docs/formatdomaincaps.html.in  |  40 +++
 docs/schemas/domaincaps.rng|  20 
 docs/schemas/domaincommon.rng  |  39 ++
 include/libvirt/libvirt-domain.h   |  17 +++
 src/conf/domain_capabilities.c |  20 
 src/conf/domain_capabilities.h |  14 +++
 src/conf/domain_conf.c | 133 +
 src/conf/domain_conf.h |  27 +
 src/driver-hypervisor.h|   7 ++
 src/libvirt-domai

[libvirt] [PATCH v6 6/9] libvirt: add new public API to get launch security info

2018-05-23 Thread Brijesh Singh
The API can be used outside the libvirt to get the launch security
information. When SEV is enabled, the API can be used to get the
measurement of the launch process.

Signed-off-by: Brijesh Singh 
---
 include/libvirt/libvirt-domain.h | 17 ++
 src/driver-hypervisor.h  |  7 ++
 src/libvirt-domain.c | 48 
 src/libvirt_public.syms  |  5 +
 4 files changed, 77 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index d7cbd187969d..f252d18da72f 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4764,4 +4764,21 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 unsigned int action,
 unsigned int flags);
 
+/**
+ * Launch Security API
+ */
+
+/**
+ * VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT:
+ *
+ * Macro represents the launch measurement of the SEV guest,
+ * as VIR_TYPED_PARAM_STRING.
+ */
+#define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement"
+
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags);
+
 #endif /* __VIR_LIBVIRT_DOMAIN_H__ */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index e71a72a44132..bdf13536d337 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1286,6 +1286,12 @@ typedef int
   unsigned int action,
   unsigned int flags);
 
+typedef int
+(*virDrvDomainGetLaunchSecurityInfo)(virDomainPtr domain,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);
+
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1532,6 +1538,7 @@ struct _virHypervisorDriver {
 virDrvDomainSetVcpu domainSetVcpu;
 virDrvDomainSetBlockThreshold domainSetBlockThreshold;
 virDrvDomainSetLifecycleAction domainSetLifecycleAction;
+virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
 };
 
 
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 2d86e48979d3..dd5a8712484d 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12101,3 +12101,51 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 virDispatchError(domain->conn);
 return -1;
 }
+
+/**
+ * virDomainGetLaunchSecurityInfo:
+ * @domain: a domain object
+ * @params: where to store security info
+ * @nparams: number of items in @params
+ * @flags: currently used, set to 0.
+ *
+ * Get the launch security info. In case of the SEV guest, this will
+ * return the launch measurement.
+ *
+ * Returns -1 in case of failure, 0 in case of success.
+ */
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+virConnectPtr conn = domain->conn;
+
+VIR_DOMAIN_DEBUG(domain, "params=%p, nparams=%p flags=0x%x",
+ params, nparams, flags);
+
+virResetLastError();
+
+virCheckDomainReturn(domain, -1);
+virCheckNonNullArgGoto(params, error);
+virCheckNonNullArgGoto(nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->domainGetLaunchSecurityInfo) {
+int ret;
+ret = conn->driver->domainGetLaunchSecurityInfo(domain, params,
+nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+virReportUnsupportedError();
+
+ error:
+virDispatchError(domain->conn);
+return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 95df3a0dbc7b..5ccae5da8883 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -785,4 +785,9 @@ LIBVIRT_4.1.0 {
 virStoragePoolLookupByTargetPath;
 } LIBVIRT_3.9.0;
 
+LIBVIRT_4.4.0 {
+global:
+virDomainGetLaunchSecurityInfo;
+} LIBVIRT_4.1.0;
+
 #  define new API here using predicted next version number 
-- 
2.14.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v6 5/9] qemu: add support to launch SEV guest

2018-05-23 Thread Brijesh Singh
QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted

VMs on AMD platform using SEV feature. The various inputs required to
launch SEV guest is provided through the  tag. A typical
SEV guest launch command line looks like this:

# $QEMU ...\
  -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
  -machine memory-encryption=sev0 \

Signed-off-by: Brijesh Singh 
---
 src/qemu/qemu_command.c | 41 
 src/qemu/qemu_process.c | 62 +
 tests/qemuxml2argvdata/launch-security-sev.args | 29 
 tests/qemuxml2argvdata/launch-security-sev.xml  | 37 +++
 tests/qemuxml2argvtest.c|  4 ++
 5 files changed, 173 insertions(+)
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.args
 create mode 100644 tests/qemuxml2argvdata/launch-security-sev.xml

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index cb397c75586a..63941e10ad83 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7203,6 +7203,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
 qemuAppendLoadparmMachineParm(&buf, def);
 
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) && def->sev)
+virBufferAddLit(&buf, ",memory-encryption=sev0");
+
 virCommandAddArgBuffer(cmd, &buf);
 
 ret = 0;
@@ -9566,6 +9569,41 @@ qemuBuildTPMCommandLine(virCommandPtr cmd,
 return 0;
 }
 
+static int
+qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
+virDomainSevDefPtr sev)
+{
+virBuffer obj = VIR_BUFFER_INITIALIZER;
+qemuDomainObjPrivatePtr priv = vm->privateData;
+char *path = NULL;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
+  sev->policy, sev->cbitpos, sev->reduced_phys_bits);
+
+virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
+virBufferAsprintf(&obj, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
+virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
+
+if (sev->dh_cert) {
+if (virAsprintf(&path, "%s/dh_cert.base64", priv->libDir) < 0)
+return -1;
+virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
+VIR_FREE(path);
+}
+
+if (sev->session) {
+if (virAsprintf(&path, "%s/session.base64", priv->libDir) < 0)
+return -1;
+virBufferAsprintf(&obj, ",session-file=%s", path);
+VIR_FREE(path);
+}
+
+virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), NULL);
+return 0;
+}
 
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
@@ -10097,6 +10135,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
 if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
 goto error;
 
+if (qemuBuildSevCommandLine(vm, cmd, def->sev) < 0)
+goto error;
+
 if (snapshot)
 virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ac2049b95df5..3cf818aee034 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5919,6 +5919,65 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
 }
 
 
+static int
+qemuBuildSevCreateFile(const char *configDir,
+   const char *name,
+   const char *data)
+{
+char *configFile;
+
+if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
+return -1;
+
+if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+virReportSystemError(errno, _("failed to write data to config '%s'"),
+ configFile);
+goto error;
+}
+
+VIR_FREE(configFile);
+return 0;
+
+ error:
+VIR_FREE(configFile);
+return -1;
+}
+
+
+static int
+qemuProcessPrepareSevGuestInput(virDomainObjPtr vm)
+{
+qemuDomainObjPrivatePtr priv = vm->privateData;
+virDomainDefPtr def = vm->def;
+virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+virDomainSevDefPtr sev = def->sev;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("Prepare SEV guest");
+
+if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+_("Domain %s asked for 'sev' launch but this "
+  "QEMU does not support SEV feature"), vm->def->name);
+return -1;
+}
+
+if (sev->dh_cert) {
+if (qemuBuildSevCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
+  

Re: [libvirt] [PATCH v5 05/10] qemu: add support to launch SEV guest

2018-04-05 Thread Brijesh Singh



On 04/04/2018 09:22 AM, John Ferlan wrote:


I understand - your other option is to make required. This is one of
those cases where there is a gray area with respect to libvirt picking
some default or policy that we generally prefer to avoid.



I think now I am more inclined towards making it required from libvirt 
-- this matches with SEV spec.




As noted before/elsewhere - what happens when the default changes...




Theoretically speaking, change in default policy should not cause any 
issue when creating the guest. But the policy change can limit us what a 
hypervisor can do after the boots, e.g disable or disable debug, 
migration or save/restore etc.



On side note, I will be going on 4 weeks of paternity leave starting 
next week and will submit the series after I am back from leave.




+}

Check out storageBackendCreateQemuImgSecretPath which just goes straight
to safewrite when writing to the file or qemuDomainWriteMasterKeyFile
which is a similar w/r/t a single key file for the domain.

The one thing to think about being the privileges for the file being
created and written and the expectations for QEMU's usage. I think this
is more like the storage secret code, but I could be wrong!


The data is public in this case, we do not need to protect it with
secret. Hence I am keeping all this certificate keys in unsecure place.


It wasn't so much the public keys as it was me (more or less) thinking
out loud about the protections on the file that you're "temporarily"
creating and using to pass the keys.

I noted two other areas which libvirt does something similarly - one is
the master public key file for decrypting the AES secrets for
libvirt/qemu secret manipulation.  The second is the "temporary" file we
create in the storage driver to handle the luks encryption password for
create/resize of a luks encrypted file when using qemu-img. Now that is
slightly different than using a temporary file for the emulator binary.

In any case, since you're creating in libDir it's probably OK as is, but
I know when reading files libvirt creates which qemu will use there have
been issues in the past - I always have to refresh my memory what those
issues are though.




IIRC, Daniel recommended to use libDir in previous reviews, if its not a 
big deal then we lets use libDir in initial patches and if need arises 
then we can revisit it later.


thanks for all your feedback.

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v5 09/10] virsh: implement new command for launch security

2018-04-04 Thread Brijesh Singh


On 4/3/18 9:32 AM, Erik Skultety wrote:
> On Mon, Apr 02, 2018 at 09:18:55AM -0500, Brijesh Singh wrote:
>> Add new 'launch-security' command, the command can be used to get or set
>> the launch security information when booting encrypted VMs.
>>
>> Signed-off-by: Brijesh Singh 
>> ---
>>  tools/virsh-domain.c | 84 
>> 
>>  1 file changed, 84 insertions(+)
>>
>> diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
>> index 2b775fc..4dca191 100644
>> --- a/tools/virsh-domain.c
>> +++ b/tools/virsh-domain.c
>> @@ -13877,6 +13877,84 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd)
>>  return ret >= 0;
>>  }
>>
>> +/*
>> + * "launch-security" command
>> + */
>> +static const vshCmdInfo info_launch_security[] = {
>> +{.name = "help",
>> +.data = N_("Get or set launch-security information")
>> +},
>> +{.name = "desc",
>> +.data = N_("Get or set the current launch-security information for 
>> a guest"
>> +   " domain.\n"
>> +   "To get the launch-security information use 
>> following command: \n\n"
>> +   "virsh # launch-security ")
> As John has pointed out, you might want to shorten ^these 2 lines, however, I
> think it makes sense to make it obvious that running without any
> arguments/options this behaves like a getter, otherwise it's going to behave
> like a setter, right? (it's a common practice in libvirt, so nothing against
> conceptually).
>

Yes, without any command line it should be getter otherwise settter.
Currently, we don't have anything in setter yet.

>> +},
>> +{.name = NULL}
>> +};
>> +
>> +static const vshCmdOptDef opts_launch_security[] = {
>> +VIRSH_COMMON_OPT_DOMAIN_FULL(0),
>> +{.name = "get",
>> + .type = VSH_OT_STRING,
>> + .help = N_("Show the launch-security info")
>> +},
>> +VIRSH_COMMON_OPT_DOMAIN_CONFIG,
>> +VIRSH_COMMON_OPT_DOMAIN_LIVE,
>> +VIRSH_COMMON_OPT_DOMAIN_CURRENT,
>> +{.name = NULL}
>> +};
> Sorry if I missed the obvious, but what exactly is the --get  supposed
> to do?

The command will return a measurement of encrypted image. The
measurement value can be used by guest owner to validate the image
before it launches the VM. In a typical scenario we may have something
like this:

# virsh create guest.xml --paused
# virsh launch-security --domain guest
// validate the measurement obtained through above command
if measurement is wrong then;
 destory the guest
else
 // optionally inject secret in guest using virsh launch-security set <>
 resume the guest



> Erik

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

Re: [libvirt] [PATCH v5 09/10] virsh: implement new command for launch security

2018-04-04 Thread Brijesh Singh


On 4/2/18 6:31 PM, John Ferlan wrote:
>
> On 04/02/2018 10:18 AM, Brijesh Singh wrote:
>> Add new 'launch-security' command, the command can be used to get or set
>> the launch security information when booting encrypted VMs.
>>
>> Signed-off-by: Brijesh Singh 
>> ---
>>  tools/virsh-domain.c | 84 
>> 
>>  1 file changed, 84 insertions(+)
>>
> Need to modify tools/virsh.pod too in order to supply the man page
> information.

Ah, I missed that. Will add help in next rev.

>
>> diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
>> index 2b775fc..4dca191 100644
>> --- a/tools/virsh-domain.c
>> +++ b/tools/virsh-domain.c
>> @@ -13877,6 +13877,84 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd)
>>  return ret >= 0;
>>  }
>>  
>> +/*
>> + * "launch-security" command
>> + */
>> +static const vshCmdInfo info_launch_security[] = {
>> +{.name = "help",
>> +.data = N_("Get or set launch-security information")
>> +},
>> +{.name = "desc",
>> +.data = N_("Get or set the current launch-security information for 
>> a guest"
>> +   " domain.\n"
>> +   "To get the launch-security information use 
>> following command: \n\n"
>> +   "virsh # launch-security ")
>> +},
> Rather lengthy...  don't think the last 2 lines are necessary. Is there
> another command doing the same?

Yes, I tried to follow other commands.

> Probably should fill in the ".help" entry too like other commands.

OK.
>> +{.name = NULL}
>> +};
>> +
>> +static const vshCmdOptDef opts_launch_security[] = {
>> +VIRSH_COMMON_OPT_DOMAIN_FULL(0),
>> +{.name = "get",
>> + .type = VSH_OT_STRING,
>> + .help = N_("Show the launch-security info")
>> +},
>> +VIRSH_COMMON_OPT_DOMAIN_CONFIG,
>> +VIRSH_COMMON_OPT_DOMAIN_LIVE,
>> +VIRSH_COMMON_OPT_DOMAIN_CURRENT,
>> +{.name = NULL}
>> +};
>> +
> 2 lines...
>
>> +static void
>> +virshPrintLaunchSecurityInfo(vshControl *ctl, virTypedParameterPtr params,
>> + int nparams)
>> +{
>> +size_t i;
>> +
> Should there perhaps be a header here for the columns?

For now we have only one column and I am not too sure if we need to add
a header file for it, if it grows then we can revisit.
>
>> +for (i = 0; i < nparams; i++) {
>> +if (params[i].type == VIR_TYPED_PARAM_STRING)
>> +vshPrintExtra(ctl, "%-15s: %s\n", params[i].field, 
>> params[i].value.s);
>> +}
>> +}
>> +
> 2 lines...
>
> John
>
>> +static bool
>> +cmdLaunchSecurity(vshControl *ctl, const vshCmd *cmd)
>> +{
>> +virDomainPtr dom;
>> +int nparams = 0;
>> +virTypedParameterPtr params = NULL;
>> +bool ret = false;
>> +unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
>> +bool current = vshCommandOptBool(cmd, "current");
>> +bool config = vshCommandOptBool(cmd, "config");
>> +bool live = vshCommandOptBool(cmd, "live");
>> +
>> +VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
>> +VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
>> +
>> +if (config)
>> +flags |= VIR_DOMAIN_AFFECT_CONFIG;
>> +if (live)
>> +flags |= VIR_DOMAIN_AFFECT_LIVE;
>> +
>> +if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
>> +return false;
>> +
>> +if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, flags) != 0) 
>> {
>> +vshError(ctl, "%s", _("Unable to get launch security info"));
>> +goto cleanup;
>> +}
>> +
>> +virshPrintLaunchSecurityInfo(ctl, params, nparams);
>> +
>> +ret = true;
>> + cleanup:
>> +virTypedParamsFree(params, nparams);
>> +virshDomainFree(dom);
>> +return ret;
>> +}
>> +
>> +
>>  const vshCmdDef domManagementCmds[] = {
>>  {.name = "attach-device",
>>   .handler = cmdAttachDevice,
>> @@ -14492,5 +14570,11 @@ const vshCmdDef domManagementCmds[] = {
>>   .info = info_domblkthreshold,
>>   .flags = 0
>>  },
>> +{.name = "launch-security",
>> + .handler = cmdLaunchSecurity,
>> + .opts = opts_launch_security,
>> + .info = info_launch_security,
>> + .flags = 0
>> +},
>>  {.name = NULL}
>>  };
>>

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v5 05/10] qemu: add support to launch SEV guest

2018-04-04 Thread Brijesh Singh


On 4/2/18 6:04 PM, John Ferlan wrote:
>
> On 04/02/2018 10:18 AM, Brijesh Singh wrote:
>> QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted
>> VMs on AMD platform using SEV feature. The various inputs required to
>> launch SEV guest is provided through the  tag. A typical
>> SEV guest launch command line looks like this:
>>
>> # $QEMU ...\
>>   -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
>>   -machine memory-encryption=sev0 \
>>
>> Signed-off-by: Brijesh Singh 
>> ---
>>  src/qemu/qemu_command.c | 35 +
>>  src/qemu/qemu_process.c | 58 
>> +
>>  2 files changed, 93 insertions(+)
>>
> (slight delay for next part of review - today was rocket launch day and
> then we headed out for a bit ;-))
>
>> diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
>> index 682d714..55bbfa2 100644
>> --- a/src/qemu/qemu_command.c
>> +++ b/src/qemu/qemu_command.c
>> @@ -7405,6 +7405,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
>>  virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
>>  qemuAppendLoadparmMachineParm(&buf, def);
>>  
>> +if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) && def->sev)
> Since we already checked sev-guest at prepare host storage (mostly
> unconditionally), I don't think we have to make the check here as well -
> although I could be wrong...


Yes, probably we can avoid the SEV_GUEST cap check in this case. I will
make the changes in next rev.

>> +virBufferAddLit(&buf, ",memory-encryption=sev0");
>> +
>>  virCommandAddArgBuffer(cmd, &buf);
>>  }
>>  
>> @@ -9750,6 +9753,35 @@ qemuBuildTPMCommandLine(virCommandPtr cmd,
>>  return 0;
>>  }
>>  
>> +static void
> This probably should be an int...

I think it will be unlikely that this function will fail hence I was
using void. The only time it can fail is when we fail to create a
dh-cert and session blob file (e.g disk is full). I will propagate the
error.

>> +qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
>> +virDomainSevDefPtr sev)
>> +{
>> +virBuffer obj = VIR_BUFFER_INITIALIZER;
>> +qemuDomainObjPrivatePtr priv = vm->privateData;
>> +char *path = NULL;
>> +
> if (!dev->sev)
> return 0;
>
> again, since prepare host storage checked the sev-guest capability we
> should be good to go here...

OK.

>> +VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
>> +  sev->policy, sev->cbitpos, sev->reduced_phys_bits);
>> +
>> +virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
>> +virBufferAsprintf(&obj, ",reduced-phys-bits=%d", 
>> sev->reduced_phys_bits);
>> +virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
> Here I would say:
>
> if (sev->policy > 0)
> virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
>
> and let qemu pick the default (which is 0x1 as I read that code).

OK, then I will remove the comment from html about the default value
since I was trying to not depend on QEMU default.

>> +
>> +if (sev->dh_cert) {
>> +ignore_value(virAsprintf(&path, "%s/dh_cert.base64", priv->libDir));
>> +virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
>> +VIR_FREE(path);
>> +}
>> +
>> +if (sev->session) {
>> +ignore_value(virAsprintf(&path, "%s/session.base64", priv->libDir));
>> +virBufferAsprintf(&obj, ",session-file=%s", path);
>> +VIR_FREE(path);
>> +}
> ...since I don't believe we can ignore_value on the paths - especially
> since we're using it to create a path to a file containing some sort of
> session info or DH key (base64 encrypted).

Sure, will do.

>> +
>> +virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), 
>> NULL);
>> +}
>>  
>>  static int
>>  qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
>> @@ -10195,6 +10227,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
>>  if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
>>  goto error;
>>  
>> +if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) && def->sev)
>> +qemuBuildSevCommandLine(vm, cmd, de

Re: [libvirt] [PATCH v5 03/10] conf: introduce launch-security element in domain

2018-04-02 Thread Brijesh Singh

Hi John,

Thanks for very details review feedbacks.

On 04/02/2018 01:26 PM, John Ferlan wrote:



On 04/02/2018 10:18 AM, Brijesh Singh wrote:

The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
  docs/formatdomain.html.in | 120 ++
  docs/schemas/domaincommon.rng |  39 ++
  src/conf/domain_conf.c| 110 ++
  src/conf/domain_conf.h|  26 +
  4 files changed, 295 insertions(+)



Again - I see the R-by from Daniel, but I have more comments for the
patches...

Also since this patch is where we introduce the XML, the xml2xml changes
that are in the last patch should move into here so that we keep
everything together.



Noted, I will merge the hunks from last patch in this patch.



We're probably getting beyond the point of me doing the movement, so a
v6 will be needed.



Yes, I can see us doing v6 and will roll all other review feedbacks.



diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 82e7d7c..2a6bed7 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8200,6 +8200,126 @@ qemu-kvm -net nic,model=? /dev/null
  
  Note: DEA/TDEA is synonymous with DES/TDES.
  
+Secure Encrypted Virtualization (SEV)

+
+
+   The contents of the <launch-security type='sev'> 
element
+   is used to provide the guest owners input used for creating an encrypted
+   VM using the AMD SEV feature.
+
+   SEV is an extension to the AMD-V architecture which supports running
+   encrypted virtual machine (VMs) under the control of KVM. Encrypted
+   VMs have their pages (code and data) secured such that only the guest
+   itself has access to the unencrypted version. Each encrypted VM is
+   associated with a unique encryption key; if its data is accessed to a
+   different entity using a different key the encrypted guests data will
+   be incorrectly decrypted, leading to unintelligible data.
+
+   For more information see various input parameters and its format see 
SEV API spec


s/see/see the/


+   https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";> 
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf 
+   Since 4.2.0


I'll be 4.3.0 now that 4.2.0 is released.



Noted.



+   
+
+<domain>
+  ...
+  <launch-security type='sev'>
+<policy> 0 </policy>
+<cbitpos> 47 </cbitpos>
+<reduced-phys-bits> 5 </reduced-phys-bits>
+<session> ... </session>
+<dh-cert> ... </dh>
+  </sev>
+  ...
+</domain>
+


Your example should provide some more realistic values.



Sure, I will add some realistic value.



+
+
+A least cbitpos and reduced-phys-bits must be
+nested within the launch-security element.
+


The above won't be necessary as long as you note required below, e.g.



Ah make sense. thanks


+
+  cbitpos
+  The cbitpos element provides the C-bit (aka encryption 
bit)


s/The/The required/



Noted.


+  location in guest page table entry. The value of cbitpos is
+  hypervisor dependent and can be obtained through the sev 
element
+  from domaincapabilities.


s/from domaincapabilities/from the domain capabilities/



Noted.



+  
+  reduced-phys-bits
+  The reduced-phys-bits element provides the physical


s/The/The required/


Noted.





+  address bit reducation. Similar to cbitpos the value of 



s/reducation/reduction/



Noted.



+  reduced-phys-bit is hypervisor dependent and can be obtained
+  through the sev element from domaincapabilities.


s/from domaincapabilities/from the domain capabilities/



Noted.



+  
+  policy
+  The optional policy element provides the guest policy
+  which must be maintained by the SEV firmware. This policy is enforced by
+  the firmware and restricts what configuration and operational commands
+  can be performed on this guest by the hypervisor. The guest policy
+  provided during guest launch is bound to the guest and cannot be changed
+  throughout the lifetime of the guest. The policy is also transmitted
+  d

Re: [libvirt] [PATCH v5 02/10] qemu: introduce SEV feature in hypervisor capabilities

2018-04-02 Thread Brijesh Singh



On 04/02/2018 12:33 PM, John Ferlan wrote:



On 04/02/2018 10:18 AM, Brijesh Singh wrote:

Extend hypervisor capabilities to include sev feature. When available,
hypervisor supports launching an encrypted VM on AMD platform. The
sev feature tag provides additional details like platform diffie-hellman


Diffie-Hellman

right?



Yes, I will use camel case in next patch.



key and certificate chain which can be used by the guest owner to
establish a cryptographic session with the SEV firmware to negotiate
keys used for attestation or to provide secret during launch.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
  docs/formatdomaincaps.html.in  | 40 
  docs/schemas/domaincaps.rng| 20 
  src/conf/domain_capabilities.c | 20 
  src/conf/domain_capabilities.h |  1 +
  src/qemu/qemu_capabilities.c   |  2 ++
  5 files changed, 83 insertions(+)



I see this has Daniel's R-by, but I have a few notes and questions...


diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index 6bfcaf6..f383141 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -417,6 +417,12 @@
  <value>3</value>
</enum>
  </gic>
+<sev>
+  <pdh> </pdh>
+  <cert-chain> </cert-chain>
+  <cbitpos> </cbitpos>
+  <reduced-phys-bits> </reduced-phys-bits>
+</sev>


The example output should have some sort of example output and not an
empty space.



Noted, I will fill in some random values.



</features>
  </domainCapabilities>
  
@@ -441,5 +447,39 @@
gic element.
  
  
+SEV capabilities

+
+AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under
+the sev element.
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When supported,
+guest owner can create a VM whose memory contents will be transparently
+encrypted with a key unique to that VM.


I think it would be cleaner to add a  to after VM and then a new 
on the next line



Noted.



+
+For more details on SEV feature see:
+  https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";>
+SEV API spec and http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf";>
+SEV White Paper
+
+
+
+
+  pdh
+  Platform diffie-hellman key, which can be exported to remote entities


Again, I think this should be Diffie-Hellman ?

And it's the public key right - so "A base64 encoded platform
Diffie-Hellman public key which..."



Noted.





+  which wish to establish a secure transport context with the SEV platform


"which wish" reads strange - how about "that desire"


+  in order to transmit data securely. The key is encoded in base64


Add "A base64 encoded" up front makes the last sentence duplicitous.


+  cert-chain
+   Platform certificate chain -- which includes platform endorsement 
key
+  (PEK), owners certificate authory (OCA) and chip endorsement key (CEK).
+  The certificate chain is encoded in base64.


A base64 encoded platform certificate chain that includes the platform
endorsement key (PEK), owners certificate authority (OCD), and chip
endorsement key (CEK).




Noted, makes it much cleaner. thanks



+  cbitpos
+  When memory encryption is enabled, one of the physical address bit


s/bit/bits



Noted.


+  (aka the C-bit) is utilized to mark if a memory page is protected. The
+  C-bit position is Hypervisor dependent.
+  reduced-phys-bits
+  When memory encryption is enabled, we loose certain bits in physical
+  address space. The number of bits we loose is hypervisor dependent.
+
+


s/loose/lose



Noted



  
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 3905318..53b33eb 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -173,6 +173,9 @@
  

  
+
+
+

  

@@ -184,6 +187,23 @@
  

  
+  

+
+  
+
+  
+  
+
+  
+  
+
+  
+  
+
+  
+
+  
+


I want to make sure of recent preferences which aren't documented, but
sometimes draw attention of certain reviewers...

Do we want dashes or camelCase for new names?  e.g. "cert-chain" or
"certChain"? And likewise for reduced-phys-bits or reducedPhysBits?



I have been trying keep the same naming convension as sev-guest object 
name (which uses dashes). I am flexible, if libvirt community prefers 
camelCase over the dashes then I am okay with it.







Re: [libvirt] [PATCH v5 01/10] qemu: provide support to query the SEV capability

2018-04-02 Thread Brijesh Singh



On 04/02/2018 12:31 PM, John Ferlan wrote:



On 04/02/2018 10:18 AM, Brijesh Singh wrote:

QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
  src/conf/domain_capabilities.h | 13 
  src/qemu/qemu_capabilities.c   | 38 +++
  src/qemu/qemu_capabilities.h   |  1 +
  src/qemu/qemu_capspriv.h   |  4 ++
  src/qemu/qemu_monitor.c|  9 +++
  src/qemu/qemu_monitor.h|  3 +
  src/qemu/qemu_monitor_json.c   | 73 ++
  src/qemu/qemu_monitor_json.h   |  3 +
  .../caps_2.12.0.x86_64.replies | 10 +++
  tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |  3 +-
  10 files changed, 156 insertions(+), 1 deletion(-)



Should have noted the first time - should have 2 blank lines around new
methods...



Noted, I will go through all the patches and add two new lines around 
new methods. thanks


-Brijesh


--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list

[libvirt] [PATCH v5 07/10] remote: implement the remote protocol for launch security

2018-04-02 Thread Brijesh Singh
Add remote support for launch security info.

Signed-off-by: Brijesh Singh 
---
 src/remote/remote_daemon_dispatch.c | 47 +
 src/remote/remote_driver.c  | 42 -
 src/remote/remote_protocol.x| 20 +++-
 src/remote_protocol-structs | 11 +
 4 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index 121d114..0959604 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -3088,6 +3088,53 @@ remoteDispatchNodeGetMemoryStats(virNetServerPtr server 
ATTRIBUTE_UNUSED,
 }
 
 static int
+remoteDispatchDomainGetLaunchSecurityInfo(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+  virNetMessagePtr msg 
ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  
remote_domain_get_launch_security_info_args *args,
+  
remote_domain_get_launch_security_info_ret *ret)
+{
+virDomainPtr dom = NULL;
+virTypedParameterPtr params = NULL;
+int nparams = 0;
+int rv = -1;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, args->flags) < 
0)
+goto cleanup;
+
+if (nparams > REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+goto cleanup;
+}
+
+if (virTypedParamsSerialize(params, nparams,
+(virTypedParameterRemotePtr *) 
&ret->params.params_val,
+&ret->params.params_len,
+args->flags) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0)
+virNetMessageSaveError(rerr);
+virTypedParamsFree(params, nparams);
+virObjectUnref(dom);
+return rv;
+}
+
+static int
 remoteDispatchDomainGetPerfEvents(virNetServerPtr server ATTRIBUTE_UNUSED,
   virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
   virNetMessagePtr msg ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 325ef3f..b52faa1 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1948,6 +1948,45 @@ remoteDomainGetNumaParameters(virDomainPtr domain,
 }
 
 static int
+remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags)
+{
+int rv = -1;
+remote_domain_get_launch_security_info_args args;
+remote_domain_get_launch_security_info_ret ret;
+struct private_data *priv = domain->conn->privateData;
+
+remoteDriverLock(priv);
+
+make_nonnull_domain(&args.dom, domain);
+args.flags = flags;
+
+memset(&ret, 0, sizeof(ret));
+if (call(domain->conn, priv, 0, 
REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_args, 
(char *) &args,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_ret, (char 
*) &ret) == -1)
+goto done;
+
+if (virTypedParamsDeserialize((virTypedParameterRemotePtr) 
ret.params.params_val,
+  ret.params.params_len,
+  
REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX,
+  params,
+  nparams) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+xdr_free((xdrproc_t) xdr_remote_domain_get_launch_security_info_ret,
+ (char *) &ret);
+ done:
+remoteDriverUnlock(priv);
+return rv;
+}
+
+static int
 remoteDomainGetPerfEvents(virDomainPtr domain,
   virTypedParameterPtr *params,
   int *nparams,
@@ -8430,7 +8469,8 @@ static virHypervisorDriver hypervisor_driver = {
 .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */
 .domainSetVcpu = remoteDomainSetVcpu, /* 3.1.0 */
 .domainSetBlockThreshold = remoteDomainSetBlockThreshold, /* 3.2.0 */
-.domainSetLifecycleAction = remoteDomainSetLifecycleAction /* 3.9.0 */
+.domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */
+.domainGetLaunc

[libvirt] [PATCH v5 08/10] qemu_driver: add support to launch security info

2018-04-02 Thread Brijesh Singh
This patch implement the internal driver API for launch event into
qemu driver. When SEV is enabled, execute 'query-sev-launch-measurement'
to get the measurement of memory encrypted through launch sequence.

Signed-off-by: Brijesh Singh 
---
 src/qemu/qemu_driver.c   | 66 
 src/qemu/qemu_monitor.c  |  8 ++
 src/qemu/qemu_monitor.h  |  3 ++
 src/qemu/qemu_monitor_json.c | 32 +
 src/qemu/qemu_monitor_json.h |  2 ++
 5 files changed, 111 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 072eb54..898aaf0 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21332,6 +21332,71 @@ qemuDomainSetLifecycleAction(virDomainPtr dom,
 return ret;
 }
 
+static int qemuDomainGetSevMeasurement(virQEMUDriverPtr driver,
+   virDomainObjPtr vm,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+int ret = -1;
+char *tmp;
+int maxpar = 0;
+
+virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+return -1;
+
+if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
+goto endjob;
+
+tmp = qemuMonitorGetSevMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
+if (tmp == NULL)
+goto endjob;
+
+if (qemuDomainObjExitMonitor(driver, vm) < 0)
+goto endjob;
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
+tmp) < 0)
+goto endjob;
+
+ret = 0;
+
+ endjob:
+qemuDomainObjEndJob(driver, vm);
+return ret;
+}
+
+
+static int
+qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+virQEMUDriverPtr driver = domain->conn->privateData;
+virDomainObjPtr vm;
+int ret = -1;
+
+if (!(vm = qemuDomObjFromDomain(domain)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
+goto cleanup;
+
+if (vm->def->sev) {
+if (qemuDomainGetSevMeasurement(driver, vm, params, nparams, flags) < 
0)
+goto cleanup;
+}
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
 
 static virHypervisorDriver qemuHypervisorDriver = {
 .name = QEMU_DRIVER_NAME,
@@ -21552,6 +21617,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
 .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */
 .domainSetBlockThreshold = qemuDomainSetBlockThreshold, /* 3.2.0 */
 .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
+.domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.2.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 44c2dff..877aaa56 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4417,3 +4417,11 @@ qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
 
 return qemuMonitorJSONSetWatchdogAction(mon, action);
 }
+
+char *
+qemuMonitorGetSevMeasurement(qemuMonitorPtr mon)
+{
+QEMU_CHECK_MONITOR_NULL(mon);
+
+return qemuMonitorJSONGetSevMeasurement(mon);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index efd3427..c475b73 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1188,4 +1188,7 @@ virJSONValuePtr 
qemuMonitorQueryNamedBlockNodes(qemuMonitorPtr mon);
 
 int qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
  const char *action);
+char *
+qemuMonitorGetSevMeasurement(qemuMonitorPtr mon);
+
 #endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index e67f7b7..be5731b 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -7960,3 +7960,35 @@ qemuMonitorJSONSetWatchdogAction(qemuMonitorPtr mon,
 virJSONValueFree(reply);
 return ret;
 }
+
+char *
+qemuMonitorJSONGetSevMeasurement(qemuMonitorPtr mon)
+{
+const char *tmp;
+char *measurement = NULL;
+virJSONValuePtr cmd;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr data;
+
+if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NULL)))
+ return NULL;
+
+if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+goto cleanup;
+
+if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+goto cleanup;
+
+data = virJSONValueObjectGetObject(reply, "return");
+
+if (!(tmp = virJSONValueObjectGetString(data, "data")))
+goto cleanup;
+
+if (VIR_STRDUP(measurement, tmp)

[libvirt] [PATCH v5 09/10] virsh: implement new command for launch security

2018-04-02 Thread Brijesh Singh
Add new 'launch-security' command, the command can be used to get or set
the launch security information when booting encrypted VMs.

Signed-off-by: Brijesh Singh 
---
 tools/virsh-domain.c | 84 
 1 file changed, 84 insertions(+)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 2b775fc..4dca191 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13877,6 +13877,84 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd)
 return ret >= 0;
 }
 
+/*
+ * "launch-security" command
+ */
+static const vshCmdInfo info_launch_security[] = {
+{.name = "help",
+.data = N_("Get or set launch-security information")
+},
+{.name = "desc",
+.data = N_("Get or set the current launch-security information for a 
guest"
+   " domain.\n"
+   "To get the launch-security information use following 
command: \n\n"
+   "virsh # launch-security ")
+},
+{.name = NULL}
+};
+
+static const vshCmdOptDef opts_launch_security[] = {
+VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+{.name = "get",
+ .type = VSH_OT_STRING,
+ .help = N_("Show the launch-security info")
+},
+VIRSH_COMMON_OPT_DOMAIN_CONFIG,
+VIRSH_COMMON_OPT_DOMAIN_LIVE,
+VIRSH_COMMON_OPT_DOMAIN_CURRENT,
+{.name = NULL}
+};
+
+static void
+virshPrintLaunchSecurityInfo(vshControl *ctl, virTypedParameterPtr params,
+ int nparams)
+{
+size_t i;
+
+for (i = 0; i < nparams; i++) {
+if (params[i].type == VIR_TYPED_PARAM_STRING)
+vshPrintExtra(ctl, "%-15s: %s\n", params[i].field, 
params[i].value.s);
+}
+}
+
+static bool
+cmdLaunchSecurity(vshControl *ctl, const vshCmd *cmd)
+{
+virDomainPtr dom;
+int nparams = 0;
+virTypedParameterPtr params = NULL;
+bool ret = false;
+unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+bool current = vshCommandOptBool(cmd, "current");
+bool config = vshCommandOptBool(cmd, "config");
+bool live = vshCommandOptBool(cmd, "live");
+
+VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
+VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+
+if (config)
+flags |= VIR_DOMAIN_AFFECT_CONFIG;
+if (live)
+flags |= VIR_DOMAIN_AFFECT_LIVE;
+
+if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+return false;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, flags) != 0) {
+vshError(ctl, "%s", _("Unable to get launch security info"));
+goto cleanup;
+}
+
+virshPrintLaunchSecurityInfo(ctl, params, nparams);
+
+ret = true;
+ cleanup:
+virTypedParamsFree(params, nparams);
+virshDomainFree(dom);
+return ret;
+}
+
+
 const vshCmdDef domManagementCmds[] = {
 {.name = "attach-device",
  .handler = cmdAttachDevice,
@@ -14492,5 +14570,11 @@ const vshCmdDef domManagementCmds[] = {
  .info = info_domblkthreshold,
  .flags = 0
 },
+{.name = "launch-security",
+ .handler = cmdLaunchSecurity,
+ .opts = opts_launch_security,
+ .info = info_launch_security,
+ .flags = 0
+},
 {.name = NULL}
 };
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v5 02/10] qemu: introduce SEV feature in hypervisor capabilities

2018-04-02 Thread Brijesh Singh
Extend hypervisor capabilities to include sev feature. When available,
hypervisor supports launching an encrypted VM on AMD platform. The
sev feature tag provides additional details like platform diffie-hellman
key and certificate chain which can be used by the guest owner to
establish a cryptographic session with the SEV firmware to negotiate
keys used for attestation or to provide secret during launch.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
 docs/formatdomaincaps.html.in  | 40 
 docs/schemas/domaincaps.rng| 20 
 src/conf/domain_capabilities.c | 20 
 src/conf/domain_capabilities.h |  1 +
 src/qemu/qemu_capabilities.c   |  2 ++
 5 files changed, 83 insertions(+)

diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index 6bfcaf6..f383141 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -417,6 +417,12 @@
 <value>3</value>
   </enum>
 </gic>
+<sev>
+  <pdh> </pdh>
+  <cert-chain> </cert-chain>
+  <cbitpos> </cbitpos>
+  <reduced-phys-bits> </reduced-phys-bits>
+</sev>
   </features>
 </domainCapabilities>
 
@@ -441,5 +447,39 @@
   gic element.
 
 
+SEV capabilities
+
+AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under
+the sev element.
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When supported,
+guest owner can create a VM whose memory contents will be transparently
+encrypted with a key unique to that VM.
+
+For more details on SEV feature see:
+  https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";>
+SEV API spec and http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf";>
+SEV White Paper
+
+
+
+
+  pdh
+  Platform diffie-hellman key, which can be exported to remote entities
+  which wish to establish a secure transport context with the SEV platform
+  in order to transmit data securely. The key is encoded in base64
+  cert-chain
+   Platform certificate chain -- which includes platform endorsement 
key
+  (PEK), owners certificate authory (OCA) and chip endorsement key (CEK).
+  The certificate chain is encoded in base64.
+  cbitpos
+  When memory encryption is enabled, one of the physical address bit
+  (aka the C-bit) is utilized to mark if a memory page is protected. The
+  C-bit position is Hypervisor dependent.
+  reduced-phys-bits
+  When memory encryption is enabled, we loose certain bits in physical
+  address space. The number of bits we loose is hypervisor dependent.
+
+
   
 
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 3905318..53b33eb 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -173,6 +173,9 @@
 
   
 
+
+
+
   
 
   
@@ -184,6 +187,23 @@
 
   
 
+  
+
+  
+
+  
+  
+
+  
+  
+
+  
+  
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index f7d9be5..082065f 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -549,6 +549,25 @@ virDomainCapsFeatureGICFormat(virBufferPtr buf,
 FORMAT_EPILOGUE(gic);
 }
 
+static void
+virDomainCapsFeatureSEVFormat(virBufferPtr buf,
+  virSEVCapabilityPtr const sev)
+{
+if (!sev)
+return;
+
+virBufferAddLit(buf, "\n");
+virBufferAdjustIndent(buf, 2);
+virBufferAsprintf(buf, "%d\n", sev->cbitpos);
+virBufferAsprintf(buf, "%d\n",
+  sev->reduced_phys_bits);
+virBufferAsprintf(buf, "%s\n", sev->pdh);
+virBufferAsprintf(buf, "%s\n",
+  sev->cert_chain);
+virBufferAdjustIndent(buf, -2);
+virBufferAddLit(buf, "\n");
+}
+
 
 char *
 virDomainCapsFormat(virDomainCapsPtr const caps)
@@ -587,6 +606,7 @@ virDomainCapsFormat(virDomainCapsPtr const caps)
 virBufferAdjustIndent(&buf, 2);
 
 virDomainCapsFeatureGICFormat(&buf, &caps->gic);
+virDomainCapsFeatureSEVFormat(&buf, caps->sev);
 
 virBufferAdjustIndent(&buf, -2);
 virBufferAddLit(&buf, "\n");
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 72e9daf..2e8596c 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -170,6 +170,7 @@ struct _virDomainCaps {
 /* add new domain devices her

[libvirt] [PATCH v5 03/10] conf: introduce launch-security element in domain

2018-04-02 Thread Brijesh Singh
The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
 docs/formatdomain.html.in | 120 ++
 docs/schemas/domaincommon.rng |  39 ++
 src/conf/domain_conf.c| 110 ++
 src/conf/domain_conf.h|  26 +
 4 files changed, 295 insertions(+)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 82e7d7c..2a6bed7 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8200,6 +8200,126 @@ qemu-kvm -net nic,model=? /dev/null
 
 Note: DEA/TDEA is synonymous with DES/TDES.
 
+Secure Encrypted Virtualization (SEV)
+
+
+   The contents of the <launch-security type='sev'> 
element
+   is used to provide the guest owners input used for creating an encrypted
+   VM using the AMD SEV feature.
+
+   SEV is an extension to the AMD-V architecture which supports running
+   encrypted virtual machine (VMs) under the control of KVM. Encrypted
+   VMs have their pages (code and data) secured such that only the guest
+   itself has access to the unencrypted version. Each encrypted VM is
+   associated with a unique encryption key; if its data is accessed to a
+   different entity using a different key the encrypted guests data will
+   be incorrectly decrypted, leading to unintelligible data.
+
+   For more information see various input parameters and its format see 
SEV API spec
+   https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";> 
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf 
+   Since 4.2.0
+   
+
+<domain>
+  ...
+  <launch-security type='sev'>
+<policy> 0 </policy>
+<cbitpos> 47 </cbitpos>
+<reduced-phys-bits> 5 </reduced-phys-bits>
+<session> ... </session>
+<dh-cert> ... </dh>
+  </sev>
+  ...
+</domain>
+
+
+
+A least cbitpos and reduced-phys-bits must be
+nested within the launch-security element.
+
+
+  cbitpos
+  The cbitpos element provides the C-bit (aka encryption 
bit)
+  location in guest page table entry. The value of cbitpos is
+  hypervisor dependent and can be obtained through the sev 
element
+  from domaincapabilities.
+  
+  reduced-phys-bits
+  The reduced-phys-bits element provides the physical
+  address bit reducation. Similar to cbitpos the value of 

+  reduced-phys-bit is hypervisor dependent and can be obtained
+  through the sev element from domaincapabilities.
+  
+  policy
+  The optional policy element provides the guest policy
+  which must be maintained by the SEV firmware. This policy is enforced by
+  the firmware and restricts what configuration and operational commands
+  can be performed on this guest by the hypervisor. The guest policy
+  provided during guest launch is bound to the guest and cannot be changed
+  throughout the lifetime of the guest. The policy is also transmitted
+  during snapshot and migration flows and enforced on the destination 
platform.
+
+  The guest policy is a 4-byte structure with the fields shown in Table:
+
+  
+
+   Bit(s) 
+   Description 
+
+
+   0 
+   Debugging of the guest is disallowed when set 
+
+
+   1 
+   Sharing keys with other guests is disallowed when set 
+
+
+   2 
+   SEV-ES is required when set
+
+
+   3 
+   Sending the guest to another platform is disallowed when 
set
+
+
+   4 
+   The guest must not be transmitted to another platform that is
+   not in the domain when set. 
+
+
+   5 
+   The guest must not be transmitted to another platform that is
+   not SEV capable when set. 
+
+
+   15:6 
+   reserved 
+
+
+   16:32 
+   The guest must not be transmitted to another platform with a
+   lower firmware version. 
+
+  
+  Default value is 0x1
+
+  

[libvirt] [PATCH v5 10/10] tests: extend tests to include sev specific tag parsing

2018-04-02 Thread Brijesh Singh
From: Xiaogang Chen 

Update qemuxml2xmltest, genericxml2xmltest and qemuxml2argvtest to include
sev specific tag, a typical SEV specific tag looks like


+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+47
+1
+1
+  
+
diff --git a/tests/genericxml2xmloutdata/sev.xml 
b/tests/genericxml2xmloutdata/sev.xml
new file mode 100644
index 000..70065b8
--- /dev/null
+++ b/tests/genericxml2xmloutdata/sev.xml
@@ -0,0 +1,22 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+  
+  
+47
+1
+1
+  
+
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
index d8270a6..3b75b43 100644
--- a/tests/genericxml2xmltest.c
+++ b/tests/genericxml2xmltest.c
@@ -141,6 +141,8 @@ mymain(void)
 DO_TEST_FULL("cachetune-colliding-types", false, true,
  TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
 
+DO_TEST_DIFFERENT("sev");
+
 virObjectUnref(caps);
 virObjectUnref(xmlopt);
 
diff --git a/tests/qemuxml2argvdata/sev.args b/tests/qemuxml2argvdata/sev.args
new file mode 100644
index 000..312dbcf
--- /dev/null
+++ b/tests/qemuxml2argvdata/sev.args
@@ -0,0 +1,24 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name QEMUGuest1 \
+-S \
+-machine pc-1.0,accel=kvm,memory-encryption=sev0 \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-chardev 
socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x1
diff --git a/tests/qemuxml2argvdata/sev.xml b/tests/qemuxml2argvdata/sev.xml
new file mode 100644
index 000..2476b58
--- /dev/null
+++ b/tests/qemuxml2argvdata/sev.xml
@@ -0,0 +1,35 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+  
+  
+  
+
+
+
+
+
+
+
+  
+  
+47
+1
+1
+  
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 308d71f..de0ac58 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -3023,6 +3023,8 @@ mymain(void)
 QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW,
 QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW);
 
+DO_TEST("sev", QEMU_CAPS_MACHINE_OPT, QEMU_CAPS_KVM, QEMU_CAPS_SEV_GUEST);
+
 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
 virFileDeleteTree(fakerootdir);
 
diff --git a/tests/qemuxml2xmloutdata/sev.xml b/tests/qemuxml2xmloutdata/sev.xml
new file mode 100644
index 000..80017fe
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/sev.xml
@@ -0,0 +1,39 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+  
+  
+  
+
+
+  
+
+
+  
+
+
+
+
+
+  
+  
+47
+1
+1
+  
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 0f56029..328ef66 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1265,6 +1265,8 @@ mymain(void)
 DO_TEST_STATUS("modern");
 DO_TEST_STATUS("migration-out-nbd");
 
+DO_TEST("sev", NONE);
+
 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
 virFileDeleteTree(fakerootdir);
 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v5 06/10] libvirt: add new public API to get launch security info

2018-04-02 Thread Brijesh Singh
The API can be used outside the libvirt to get the launch security
information. When SEV is enabled, the API can be used to get the
measurement of the launch process.

Signed-off-by: Brijesh Singh 
---
 include/libvirt/libvirt-domain.h | 17 ++
 src/driver-hypervisor.h  |  7 ++
 src/libvirt-domain.c | 48 
 src/libvirt_public.syms  |  5 +
 4 files changed, 77 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 12fd340..6870a1a 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4764,4 +4764,21 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 unsigned int action,
 unsigned int flags);
 
+/**
+ * Launch Security API
+ */
+
+/**
+ * VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT:
+ *
+ * Macro represents the launch measurement of the SEV guest,
+ * as VIR_TYPED_PARAM_STRING.
+ */
+#define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement"
+
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags);
+
 #endif /* __VIR_LIBVIRT_DOMAIN_H__ */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index ce0e2b2..b066413 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1283,6 +1283,12 @@ typedef int
   unsigned int action,
   unsigned int flags);
 
+typedef int
+(*virDrvDomainGetLaunchSecurityInfo)(virDomainPtr domain,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);
+
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1528,6 +1534,7 @@ struct _virHypervisorDriver {
 virDrvDomainSetVcpu domainSetVcpu;
 virDrvDomainSetBlockThreshold domainSetBlockThreshold;
 virDrvDomainSetLifecycleAction domainSetLifecycleAction;
+virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
 };
 
 
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 63d2ae2..5b63a3c 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12101,3 +12101,51 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 virDispatchError(domain->conn);
 return -1;
 }
+
+/**
+ * virDomainGetLaunchSecurityInfo:
+ * @domain: a domain object
+ * @params: where to store security info
+ * @nparams: number of items in @params
+ * @flags: currently used, set to 0.
+ *
+ * Get the launch security info. In case of the SEV guest, this will
+ * return the launch measurement.
+ *
+ * Returns -1 in case of failure, 0 in case of success.
+ */
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+virConnectPtr conn = domain->conn;
+
+VIR_DOMAIN_DEBUG(domain, "params=%p, nparams=%p flags=0x%x",
+ params, nparams, flags);
+
+virResetLastError();
+
+virCheckDomainReturn(domain, -1);
+virCheckNonNullArgGoto(params, error);
+virCheckNonNullArgGoto(nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->domainGetLaunchSecurityInfo) {
+int ret;
+ret = conn->driver->domainGetLaunchSecurityInfo(domain, params,
+nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+virReportUnsupportedError();
+
+ error:
+virDispatchError(domain->conn);
+return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 95df3a0..caba286 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -785,4 +785,9 @@ LIBVIRT_4.1.0 {
 virStoragePoolLookupByTargetPath;
 } LIBVIRT_3.9.0;
 
+LIBVIRT_4.2.0 {
+global:
+virDomainGetLaunchSecurityInfo;
+} LIBVIRT_4.1.0;
+
 #  define new API here using predicted next version number 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v5 05/10] qemu: add support to launch SEV guest

2018-04-02 Thread Brijesh Singh
QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted
VMs on AMD platform using SEV feature. The various inputs required to
launch SEV guest is provided through the  tag. A typical
SEV guest launch command line looks like this:

# $QEMU ...\
  -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
  -machine memory-encryption=sev0 \

Signed-off-by: Brijesh Singh 
---
 src/qemu/qemu_command.c | 35 +
 src/qemu/qemu_process.c | 58 +
 2 files changed, 93 insertions(+)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 682d714..55bbfa2 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7405,6 +7405,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
 qemuAppendLoadparmMachineParm(&buf, def);
 
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) && def->sev)
+virBufferAddLit(&buf, ",memory-encryption=sev0");
+
 virCommandAddArgBuffer(cmd, &buf);
 }
 
@@ -9750,6 +9753,35 @@ qemuBuildTPMCommandLine(virCommandPtr cmd,
 return 0;
 }
 
+static void
+qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
+virDomainSevDefPtr sev)
+{
+virBuffer obj = VIR_BUFFER_INITIALIZER;
+qemuDomainObjPrivatePtr priv = vm->privateData;
+char *path = NULL;
+
+VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
+  sev->policy, sev->cbitpos, sev->reduced_phys_bits);
+
+virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
+virBufferAsprintf(&obj, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
+virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
+
+if (sev->dh_cert) {
+ignore_value(virAsprintf(&path, "%s/dh_cert.base64", priv->libDir));
+virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
+VIR_FREE(path);
+}
+
+if (sev->session) {
+ignore_value(virAsprintf(&path, "%s/session.base64", priv->libDir));
+virBufferAsprintf(&obj, ",session-file=%s", path);
+VIR_FREE(path);
+}
+
+virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), NULL);
+}
 
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
@@ -10195,6 +10227,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
 if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
 goto error;
 
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) && def->sev)
+qemuBuildSevCommandLine(vm, cmd, def->sev);
+
 if (snapshot)
 virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index c0105c8..0c93f15 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5745,6 +5745,61 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
 return ret;
 }
 
+static int
+qemuBuildSevCreateFile(const char *configDir, const char *name,
+   const char *data)
+{
+char *configFile;
+
+if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
+return -1;
+
+if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+virReportSystemError(errno, _("failed to write data to config '%s'"),
+ configFile);
+goto error;
+}
+
+VIR_FREE(configFile);
+return 0;
+
+ error:
+VIR_FREE(configFile);
+return -1;
+}
+
+static int
+qemuProcessPrepareSevGuestInput(virDomainObjPtr vm)
+{
+qemuDomainObjPrivatePtr priv = vm->privateData;
+virDomainDefPtr def = vm->def;
+virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+virDomainSevDefPtr sev = def->sev;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("Prepare SEV guest");
+
+if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+_("Domain %s asked for 'sev' launch but "
+  "QEMU does not support SEV feature"), vm->def->name);
+return -1;
+}
+
+if (sev->dh_cert) {
+if (qemuBuildSevCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
+return -1;
+}
+
+if (sev->session) {
+if (qemuBuildSevCreateFile(priv->libDir, "session", sev->session) < 0)
+return -1;
+}
+
+return 0;
+}
 
 static int
 qemuProcessPrepareHostStorage(virQEMUDriverPtr driver,
@@ -5870,6 +5925,9 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver,
 if (qemuProcessPrepareHostStorage(driver, vm, flags) < 0)
 goto cleanup;
 
+if (qemuProcessPrepareSevGuestInput(vm) < 0)
+goto cleanup;
+
 ret = 0;
  cleanup:
 virObjectUnref(cfg);
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v5 04/10] qemu/cgroup: add /dev/sev in shared devices list

2018-04-02 Thread Brijesh Singh
QEMU uses /dev/sev device while creating the SEV guest, lets add /dev/sev
in the list of devices allowed to be accessed by the QEMU.

Signed-off-by: Brijesh Singh <>
---
 docs/drvqemu.html.in   | 1 +
 src/qemu/qemu.conf | 2 +-
 src/qemu/qemu_cgroup.c | 2 +-
 3 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/docs/drvqemu.html.in b/docs/drvqemu.html.in
index cbd159d..7c33a18 100644
--- a/docs/drvqemu.html.in
+++ b/docs/drvqemu.html.in
@@ -397,6 +397,7 @@ chmod o+x /path/to/directory
 /dev/random, /dev/urandom,
 /dev/ptmx, /dev/kvm, /dev/kqemu,
 /dev/rtc, /dev/hpet, /dev/net/tun
+/dev/sev
 
 
 
diff --git a/src/qemu/qemu.conf b/src/qemu/qemu.conf
index 07eab7e..d328d96 100644
--- a/src/qemu/qemu.conf
+++ b/src/qemu/qemu.conf
@@ -451,7 +451,7 @@
 #"/dev/null", "/dev/full", "/dev/zero",
 #"/dev/random", "/dev/urandom",
 #"/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-#"/dev/rtc","/dev/hpet"
+#"/dev/rtc","/dev/hpet", "/dev/sev"
 #]
 #
 # RDMA migration requires the following extra files to be added to the list:
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index b604edb..1a271df 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -46,7 +46,7 @@ const char *const defaultDeviceACL[] = {
 "/dev/null", "/dev/full", "/dev/zero",
 "/dev/random", "/dev/urandom",
 "/dev/ptmx", "/dev/kvm", "/dev/kqemu",
-"/dev/rtc", "/dev/hpet",
+"/dev/rtc", "/dev/hpet", "/dev/sev",
 NULL,
 };
 #define DEVICE_PTY_MAJOR 136
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v5 01/10] qemu: provide support to query the SEV capability

2018-04-02 Thread Brijesh Singh
QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
 src/conf/domain_capabilities.h | 13 
 src/qemu/qemu_capabilities.c   | 38 +++
 src/qemu/qemu_capabilities.h   |  1 +
 src/qemu/qemu_capspriv.h   |  4 ++
 src/qemu/qemu_monitor.c|  9 +++
 src/qemu/qemu_monitor.h|  3 +
 src/qemu/qemu_monitor_json.c   | 73 ++
 src/qemu/qemu_monitor_json.h   |  3 +
 .../caps_2.12.0.x86_64.replies | 10 +++
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |  3 +-
 10 files changed, 156 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index fa4c1e4..72e9daf 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -137,6 +137,19 @@ struct _virDomainCapsCPU {
 virDomainCapsCPUModelsPtr custom;
 };
 
+/*
+ * SEV capabilities
+ */
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+char *pdh;
+char *cert_chain;
+unsigned int cbitpos;
+unsigned int reduced_phys_bits;
+};
+
+
 struct _virDomainCaps {
 virObjectLockable parent;
 
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index e54dde6..0f6e6fb 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -466,6 +466,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
   /* 285 */
   "virtio-mouse-ccw",
   "virtio-tablet-ccw",
+  "sev-guest",
 );
 
 
@@ -532,6 +533,8 @@ struct _virQEMUCaps {
 size_t ngicCapabilities;
 virGICCapability *gicCapabilities;
 
+virSEVCapability *sevCapabilities;
+
 virQEMUCapsHostCPUData kvmCPU;
 virQEMUCapsHostCPUData tcgCPU;
 };
@@ -1705,6 +1708,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
 { "virtio-keyboard-ccw", QEMU_CAPS_DEVICE_VIRTIO_KEYBOARD_CCW },
 { "virtio-mouse-ccw", QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW },
 { "virtio-tablet-ccw", QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW },
+{ "sev-guest", QEMU_CAPS_SEV_GUEST },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = {
@@ -2784,6 +2788,21 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
 qemuCaps->ngicCapabilities = ncapabilities;
 }
 
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+  virSEVCapability *capabilities)
+{
+virSEVCapability *cap = qemuCaps->sevCapabilities;
+
+if (cap) {
+VIR_FREE(cap->pdh);
+VIR_FREE(cap->cert_chain);
+}
+
+VIR_FREE(qemuCaps->sevCapabilities);
+
+qemuCaps->sevCapabilities = capabilities;
+}
 
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
@@ -3287,6 +3306,19 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr 
qemuCaps,
 return 0;
 }
 
+static int
+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+   qemuMonitorPtr mon)
+{
+virSEVCapability *caps = NULL;
+
+if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+return -1;
+
+virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+return 0;
+}
 
 bool
 virQEMUCapsCPUFilterFeatures(const char *name,
@@ -4768,6 +4800,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
 virQEMUCapsSet(qemuCaps, QEMU_CAPS_CPU_CACHE);
 
+/* Probe for SEV capabilities */
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
+virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
+}
+
 ret = 0;
  cleanup:
 return ret;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 3f3c29f..9b51cc2 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -450,6 +450,7 @@ typedef enum {
 /* 285 */
 QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW, /* -device virtio-mouse-ccw */
 QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW, /* -device virtio-tablet-ccw */
+QEMU_CAPS_SEV_GUEST, /* -object sev-guest,... */
 
 QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
index 222f336..1fa85cc 100644
--- a/src/qemu/qemu_capspriv.h
+++ b/src/qemu/qemu_capspriv.h
@@ -86,6 +86,10 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
   virGICCapabil

[libvirt] [PATCH v5 00/10] x86: Secure Encrypted Virtualization (AMD)

2018-04-02 Thread Brijesh Singh
This patch series provides support for launching an encrypted guest using
AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV feature
allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
that includes the following


...
  
 
 
 
 


If  is provided then we indicate that hypervisor is capable of launching
SEV guest. 

2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in 
case
if guest owner wish to establish a secure connection with SEV firmware to
negotiate a key used for validating the measurement.

3. mgmt tool requests to start a guest calling virCreateXML(), passing 
VIR_DOMAIN_START_PAUSED.
The xml would include


 /* the value is same as what is obtained via 
virConnectGetDomainCapabilities()
 /* the value is same as what is 
obtained via virConnectGetDomainCapabilities()
   ..  /* guest owners diffie-hellman key */ (optional)
   .. /* guest owners session blob */ (optional)
   .. /* guest policy */ (optional)


4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
args looks like this:

# $QEMU ..
-machine memory-encryption=sev0 \
-object sev-guest,id=sev0,dh-cert-file=

5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event

6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls 
virDomainGetLaunchSecretInfo()
to retrieve the measurement of encrypted memory.

7. (optional) mgmt tool can provide the measurement value to guest owner, which 
can
validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
it resumes the guest otherwise it calls destroy() to kill the guest.

8. mgmt tool resumes the guest

TODO:
* SEV guest require to use DMA apis for the virtio devices. In order to use the 
DMA
apis the virtio devices must have this tag



It is a bit unclear to me where these changes need to go. Do we need to
modify the libvirt to automatically add these when SEV is enabled or
we ask mgmt tool to make sure that it creates XML with right tag to enable
the DMA APIs for virtio devices. I am looking for some suggestions.

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

SEV Firmware API spec is available at:
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Changes since v4:
* add /dev/sev in shared device list

Changes since v3:
* rename QEMU_CAPS_SEV -> QEMU_CAPS_SEV_GUEST
* update caps_2.12.0.x86_64.replies to include query-sev-capabilities data

Changes since v2:
* make cbitpos, policy and reduced-phys-bits as unsigned int
* update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr *params
instead of virTypedParameterPtr params.

Changes since v1:
* rename  ->  for domain
* add more information about policy and other fields in domaincaps.html
* split the domain_conf support in two patches
* add virDomainGetLaunchInfo() to retrieve the SEV measurement
* extend virsh command to show the domain's launch security information
* add test cases to validate newly added  element
* fix issues reported with 'make check' and 'make syntax-check'

The complete git tree is available at:
https://github.com/codomania/libvirt/tree/v5

Brijesh Singh (9):
  qemu: provide support to query the SEV capability
  qemu: introduce SEV feature in hypervisor capabilities
  conf: introduce launch-security element in domain
  qemu/cgroup: add /dev/sev in shared devices list
  qemu: add support to launch SEV guest
  libvirt: add new public API to get launch security info
  remote: implement the remote protocol for launch security
  qemu_driver: add support to launch security info
  virsh: implement new command for launch security

Xiaogang Chen (1):
  tests: extend tests to include sev specific tag parsing

 docs/drvqemu.html.in   |   1 +
 docs/formatdomain.html.in  | 120 +
 docs/formatdomaincaps.html.in  |  40 +++
 docs/schemas/domaincaps.rng|  20 
 docs/schemas/domaincommon.rng  |  39 +++
 include/libvirt/libvirt-domain.h   |  17 +++
 src/conf/domain_capabilities.c |  20 
 src/conf/domain_capabilities.h |  14 +++
 src/conf/domain_conf.c | 110 +++
 src/conf/domain_conf.h |  26 +
 src/driver-hypervisor.h|   7 ++
 src/libvirt-domain.c   |  48 +
 src/libvirt_public.syms|   5 +
 src/qemu/qemu.conf  

[libvirt] [PATCH v4 7/9] qemu_driver: add support to launch security info

2018-03-27 Thread Brijesh Singh
This patch implement the internal driver API for launch event into
qemu driver. When SEV is enabled, execute 'query-sev-launch-measurement'
to get the measurement of memory encrypted through launch sequence.

Signed-off-by: Brijesh Singh 
---
 src/qemu/qemu_driver.c   | 66 
 src/qemu/qemu_monitor.c  |  8 ++
 src/qemu/qemu_monitor.h  |  3 ++
 src/qemu/qemu_monitor_json.c | 32 +
 src/qemu/qemu_monitor_json.h |  2 ++
 5 files changed, 111 insertions(+)

diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 7bcc493..282d3ce 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -21332,6 +21332,71 @@ qemuDomainSetLifecycleAction(virDomainPtr dom,
 return ret;
 }
 
+static int qemuDomainGetSevMeasurement(virQEMUDriverPtr driver,
+   virDomainObjPtr vm,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+int ret = -1;
+char *tmp;
+int maxpar = 0;
+
+virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+
+if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+return -1;
+
+if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0)
+goto endjob;
+
+tmp = qemuMonitorGetSevMeasurement(QEMU_DOMAIN_PRIVATE(vm)->mon);
+if (tmp == NULL)
+goto endjob;
+
+if (qemuDomainObjExitMonitor(driver, vm) < 0)
+goto endjob;
+
+if (virTypedParamsAddString(params, nparams, &maxpar,
+VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT,
+tmp) < 0)
+goto endjob;
+
+ret = 0;
+
+ endjob:
+qemuDomainObjEndJob(driver, vm);
+return ret;
+}
+
+
+static int
+qemuDomainGetLaunchSecurityInfo(virDomainPtr domain,
+virTypedParameterPtr *params,
+int *nparams,
+unsigned int flags)
+{
+virQEMUDriverPtr driver = domain->conn->privateData;
+virDomainObjPtr vm;
+int ret = -1;
+
+if (!(vm = qemuDomObjFromDomain(domain)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfoEnsureACL(domain->conn, vm->def) < 0)
+goto cleanup;
+
+if (vm->def->sev) {
+if (qemuDomainGetSevMeasurement(driver, vm, params, nparams, flags) < 
0)
+goto cleanup;
+}
+
+ret = 0;
+
+ cleanup:
+virDomainObjEndAPI(&vm);
+return ret;
+}
 
 static virHypervisorDriver qemuHypervisorDriver = {
 .name = QEMU_DRIVER_NAME,
@@ -21552,6 +21617,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
 .domainSetVcpu = qemuDomainSetVcpu, /* 3.1.0 */
 .domainSetBlockThreshold = qemuDomainSetBlockThreshold, /* 3.2.0 */
 .domainSetLifecycleAction = qemuDomainSetLifecycleAction, /* 3.9.0 */
+.domainGetLaunchSecurityInfo = qemuDomainGetLaunchSecurityInfo, /* 4.2.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 44c2dff..877aaa56 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4417,3 +4417,11 @@ qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
 
 return qemuMonitorJSONSetWatchdogAction(mon, action);
 }
+
+char *
+qemuMonitorGetSevMeasurement(qemuMonitorPtr mon)
+{
+QEMU_CHECK_MONITOR_NULL(mon);
+
+return qemuMonitorJSONGetSevMeasurement(mon);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index efd3427..c475b73 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1188,4 +1188,7 @@ virJSONValuePtr 
qemuMonitorQueryNamedBlockNodes(qemuMonitorPtr mon);
 
 int qemuMonitorSetWatchdogAction(qemuMonitorPtr mon,
  const char *action);
+char *
+qemuMonitorGetSevMeasurement(qemuMonitorPtr mon);
+
 #endif /* QEMU_MONITOR_H */
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index e67f7b7..be5731b 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -7960,3 +7960,35 @@ qemuMonitorJSONSetWatchdogAction(qemuMonitorPtr mon,
 virJSONValueFree(reply);
 return ret;
 }
+
+char *
+qemuMonitorJSONGetSevMeasurement(qemuMonitorPtr mon)
+{
+const char *tmp;
+char *measurement = NULL;
+virJSONValuePtr cmd;
+virJSONValuePtr reply = NULL;
+virJSONValuePtr data;
+
+if (!(cmd = qemuMonitorJSONMakeCommand("query-sev-launch-measure", NULL)))
+ return NULL;
+
+if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+goto cleanup;
+
+if (qemuMonitorJSONCheckError(cmd, reply) < 0)
+goto cleanup;
+
+data = virJSONValueObjectGetObject(reply, "return");
+
+if (!(tmp = virJSONValueObjectGetString(data, "data")))
+goto cleanup;
+
+if (VIR_STRDUP(measurement, tmp)

[libvirt] [PATCH v4 9/9] tests: extend tests to include sev specific tag parsing

2018-03-27 Thread Brijesh Singh
From: Xiaogang Chen 

Update qemuxml2xmltest, genericxml2xmltest and qemuxml2argvtest to include
sev specific tag, a typical SEV specific tag looks like


+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+47
+1
+1
+  
+
diff --git a/tests/genericxml2xmloutdata/sev.xml 
b/tests/genericxml2xmloutdata/sev.xml
new file mode 100644
index 000..70065b8
--- /dev/null
+++ b/tests/genericxml2xmloutdata/sev.xml
@@ -0,0 +1,22 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+  
+  
+47
+1
+1
+  
+
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
index d8270a6..3b75b43 100644
--- a/tests/genericxml2xmltest.c
+++ b/tests/genericxml2xmltest.c
@@ -141,6 +141,8 @@ mymain(void)
 DO_TEST_FULL("cachetune-colliding-types", false, true,
  TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
 
+DO_TEST_DIFFERENT("sev");
+
 virObjectUnref(caps);
 virObjectUnref(xmlopt);
 
diff --git a/tests/qemuxml2argvdata/sev.args b/tests/qemuxml2argvdata/sev.args
new file mode 100644
index 000..312dbcf
--- /dev/null
+++ b/tests/qemuxml2argvdata/sev.args
@@ -0,0 +1,24 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name QEMUGuest1 \
+-S \
+-machine pc-1.0,accel=kvm,memory-encryption=sev0 \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-chardev 
socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x1
diff --git a/tests/qemuxml2argvdata/sev.xml b/tests/qemuxml2argvdata/sev.xml
new file mode 100644
index 000..2476b58
--- /dev/null
+++ b/tests/qemuxml2argvdata/sev.xml
@@ -0,0 +1,35 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+  
+  
+  
+
+
+
+
+
+
+
+  
+  
+47
+1
+1
+  
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 308d71f..de0ac58 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -3023,6 +3023,8 @@ mymain(void)
 QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW,
 QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW);
 
+DO_TEST("sev", QEMU_CAPS_MACHINE_OPT, QEMU_CAPS_KVM, QEMU_CAPS_SEV_GUEST);
+
 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
 virFileDeleteTree(fakerootdir);
 
diff --git a/tests/qemuxml2xmloutdata/sev.xml b/tests/qemuxml2xmloutdata/sev.xml
new file mode 100644
index 000..80017fe
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/sev.xml
@@ -0,0 +1,39 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+  
+  
+  
+
+
+  
+
+
+  
+
+
+
+
+
+  
+  
+47
+1
+1
+  
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 0f56029..328ef66 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1265,6 +1265,8 @@ mymain(void)
 DO_TEST_STATUS("modern");
 DO_TEST_STATUS("migration-out-nbd");
 
+DO_TEST("sev", NONE);
+
 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
 virFileDeleteTree(fakerootdir);
 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v4 8/9] virsh: implement new command for launch security

2018-03-27 Thread Brijesh Singh
Add new 'launch-security' command, the command can be used to get or set
the launch security information when booting encrypted VMs.

Signed-off-by: Brijesh Singh 
---
 tools/virsh-domain.c | 84 
 1 file changed, 84 insertions(+)

diff --git a/tools/virsh-domain.c b/tools/virsh-domain.c
index 2b775fc..4dca191 100644
--- a/tools/virsh-domain.c
+++ b/tools/virsh-domain.c
@@ -13877,6 +13877,84 @@ cmdDomFSInfo(vshControl *ctl, const vshCmd *cmd)
 return ret >= 0;
 }
 
+/*
+ * "launch-security" command
+ */
+static const vshCmdInfo info_launch_security[] = {
+{.name = "help",
+.data = N_("Get or set launch-security information")
+},
+{.name = "desc",
+.data = N_("Get or set the current launch-security information for a 
guest"
+   " domain.\n"
+   "To get the launch-security information use following 
command: \n\n"
+   "virsh # launch-security ")
+},
+{.name = NULL}
+};
+
+static const vshCmdOptDef opts_launch_security[] = {
+VIRSH_COMMON_OPT_DOMAIN_FULL(0),
+{.name = "get",
+ .type = VSH_OT_STRING,
+ .help = N_("Show the launch-security info")
+},
+VIRSH_COMMON_OPT_DOMAIN_CONFIG,
+VIRSH_COMMON_OPT_DOMAIN_LIVE,
+VIRSH_COMMON_OPT_DOMAIN_CURRENT,
+{.name = NULL}
+};
+
+static void
+virshPrintLaunchSecurityInfo(vshControl *ctl, virTypedParameterPtr params,
+ int nparams)
+{
+size_t i;
+
+for (i = 0; i < nparams; i++) {
+if (params[i].type == VIR_TYPED_PARAM_STRING)
+vshPrintExtra(ctl, "%-15s: %s\n", params[i].field, 
params[i].value.s);
+}
+}
+
+static bool
+cmdLaunchSecurity(vshControl *ctl, const vshCmd *cmd)
+{
+virDomainPtr dom;
+int nparams = 0;
+virTypedParameterPtr params = NULL;
+bool ret = false;
+unsigned int flags = VIR_DOMAIN_AFFECT_CURRENT;
+bool current = vshCommandOptBool(cmd, "current");
+bool config = vshCommandOptBool(cmd, "config");
+bool live = vshCommandOptBool(cmd, "live");
+
+VSH_EXCLUSIVE_OPTIONS_VAR(current, live);
+VSH_EXCLUSIVE_OPTIONS_VAR(current, config);
+
+if (config)
+flags |= VIR_DOMAIN_AFFECT_CONFIG;
+if (live)
+flags |= VIR_DOMAIN_AFFECT_LIVE;
+
+if (!(dom = virshCommandOptDomain(ctl, cmd, NULL)))
+return false;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, flags) != 0) {
+vshError(ctl, "%s", _("Unable to get launch security info"));
+goto cleanup;
+}
+
+virshPrintLaunchSecurityInfo(ctl, params, nparams);
+
+ret = true;
+ cleanup:
+virTypedParamsFree(params, nparams);
+virshDomainFree(dom);
+return ret;
+}
+
+
 const vshCmdDef domManagementCmds[] = {
 {.name = "attach-device",
  .handler = cmdAttachDevice,
@@ -14492,5 +14570,11 @@ const vshCmdDef domManagementCmds[] = {
  .info = info_domblkthreshold,
  .flags = 0
 },
+{.name = "launch-security",
+ .handler = cmdLaunchSecurity,
+ .opts = opts_launch_security,
+ .info = info_launch_security,
+ .flags = 0
+},
 {.name = NULL}
 };
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v4 6/9] remote: implement the remote protocol for launch security

2018-03-27 Thread Brijesh Singh
Add remote support for launch security info.

Signed-off-by: Brijesh Singh 
---
 src/remote/remote_daemon_dispatch.c | 47 +
 src/remote/remote_driver.c  | 42 -
 src/remote/remote_protocol.x| 20 +++-
 src/remote_protocol-structs | 11 +
 4 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index 121d114..0959604 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -3088,6 +3088,53 @@ remoteDispatchNodeGetMemoryStats(virNetServerPtr server 
ATTRIBUTE_UNUSED,
 }
 
 static int
+remoteDispatchDomainGetLaunchSecurityInfo(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+  virNetMessagePtr msg 
ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  
remote_domain_get_launch_security_info_args *args,
+  
remote_domain_get_launch_security_info_ret *ret)
+{
+virDomainPtr dom = NULL;
+virTypedParameterPtr params = NULL;
+int nparams = 0;
+int rv = -1;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, args->flags) < 
0)
+goto cleanup;
+
+if (nparams > REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+goto cleanup;
+}
+
+if (virTypedParamsSerialize(params, nparams,
+(virTypedParameterRemotePtr *) 
&ret->params.params_val,
+&ret->params.params_len,
+args->flags) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0)
+virNetMessageSaveError(rerr);
+virTypedParamsFree(params, nparams);
+virObjectUnref(dom);
+return rv;
+}
+
+static int
 remoteDispatchDomainGetPerfEvents(virNetServerPtr server ATTRIBUTE_UNUSED,
   virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
   virNetMessagePtr msg ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 34e5ced..4dc0d5a 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1950,6 +1950,45 @@ remoteDomainGetNumaParameters(virDomainPtr domain,
 }
 
 static int
+remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags)
+{
+int rv = -1;
+remote_domain_get_launch_security_info_args args;
+remote_domain_get_launch_security_info_ret ret;
+struct private_data *priv = domain->conn->privateData;
+
+remoteDriverLock(priv);
+
+make_nonnull_domain(&args.dom, domain);
+args.flags = flags;
+
+memset(&ret, 0, sizeof(ret));
+if (call(domain->conn, priv, 0, 
REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_args, 
(char *) &args,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_ret, (char 
*) &ret) == -1)
+goto done;
+
+if (virTypedParamsDeserialize((virTypedParameterRemotePtr) 
ret.params.params_val,
+  ret.params.params_len,
+  
REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX,
+  params,
+  nparams) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+xdr_free((xdrproc_t) xdr_remote_domain_get_launch_security_info_ret,
+ (char *) &ret);
+ done:
+remoteDriverUnlock(priv);
+return rv;
+}
+
+static int
 remoteDomainGetPerfEvents(virDomainPtr domain,
   virTypedParameterPtr *params,
   int *nparams,
@@ -8432,7 +8471,8 @@ static virHypervisorDriver hypervisor_driver = {
 .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */
 .domainSetVcpu = remoteDomainSetVcpu, /* 3.1.0 */
 .domainSetBlockThreshold = remoteDomainSetBlockThreshold, /* 3.2.0 */
-.domainSetLifecycleAction = remoteDomainSetLifecycleAction /* 3.9.0 */
+.domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */
+.domainGetLaunc

[libvirt] [PATCH v4 2/9] qemu: introduce SEV feature in hypervisor capabilities

2018-03-27 Thread Brijesh Singh
Extend hypervisor capabilities to include sev feature. When available,
hypervisor supports launching an encrypted VM on AMD platform. The
sev feature tag provides additional details like platform diffie-hellman
key and certificate chain which can be used by the guest owner to
establish a cryptographic session with the SEV firmware to negotiate
keys used for attestation or to provide secret during launch.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
 docs/formatdomaincaps.html.in  | 40 
 docs/schemas/domaincaps.rng| 20 
 src/conf/domain_capabilities.c | 20 
 src/conf/domain_capabilities.h |  1 +
 src/qemu/qemu_capabilities.c   |  2 ++
 5 files changed, 83 insertions(+)

diff --git a/docs/formatdomaincaps.html.in b/docs/formatdomaincaps.html.in
index 6bfcaf6..f383141 100644
--- a/docs/formatdomaincaps.html.in
+++ b/docs/formatdomaincaps.html.in
@@ -417,6 +417,12 @@
 <value>3</value>
   </enum>
 </gic>
+<sev>
+  <pdh> </pdh>
+  <cert-chain> </cert-chain>
+  <cbitpos> </cbitpos>
+  <reduced-phys-bits> </reduced-phys-bits>
+</sev>
   </features>
 </domainCapabilities>
 
@@ -441,5 +447,39 @@
   gic element.
 
 
+SEV capabilities
+
+AMD Secure Encrypted Virtualization (SEV) capabilities are exposed under
+the sev element.
+SEV is an extension to the AMD-V architecture which supports running
+virtual machines (VMs) under the control of a hypervisor. When supported,
+guest owner can create a VM whose memory contents will be transparently
+encrypted with a key unique to that VM.
+
+For more details on SEV feature see:
+  https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";>
+SEV API spec and http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf";>
+SEV White Paper
+
+
+
+
+  pdh
+  Platform diffie-hellman key, which can be exported to remote entities
+  which wish to establish a secure transport context with the SEV platform
+  in order to transmit data securely. The key is encoded in base64
+  cert-chain
+   Platform certificate chain -- which includes platform endorsement 
key
+  (PEK), owners certificate authory (OCA) and chip endorsement key (CEK).
+  The certificate chain is encoded in base64.
+  cbitpos
+  When memory encryption is enabled, one of the physical address bit
+  (aka the C-bit) is utilized to mark if a memory page is protected. The
+  C-bit position is Hypervisor dependent.
+  reduced-phys-bits
+  When memory encryption is enabled, we loose certain bits in physical
+  address space. The number of bits we loose is hypervisor dependent.
+
+
   
 
diff --git a/docs/schemas/domaincaps.rng b/docs/schemas/domaincaps.rng
index 3905318..53b33eb 100644
--- a/docs/schemas/domaincaps.rng
+++ b/docs/schemas/domaincaps.rng
@@ -173,6 +173,9 @@
 
   
 
+
+
+
   
 
   
@@ -184,6 +187,23 @@
 
   
 
+  
+
+  
+
+  
+  
+
+  
+  
+
+  
+  
+
+  
+
+  
+
   
 
   
diff --git a/src/conf/domain_capabilities.c b/src/conf/domain_capabilities.c
index f7d9be5..082065f 100644
--- a/src/conf/domain_capabilities.c
+++ b/src/conf/domain_capabilities.c
@@ -549,6 +549,25 @@ virDomainCapsFeatureGICFormat(virBufferPtr buf,
 FORMAT_EPILOGUE(gic);
 }
 
+static void
+virDomainCapsFeatureSEVFormat(virBufferPtr buf,
+  virSEVCapabilityPtr const sev)
+{
+if (!sev)
+return;
+
+virBufferAddLit(buf, "\n");
+virBufferAdjustIndent(buf, 2);
+virBufferAsprintf(buf, "%d\n", sev->cbitpos);
+virBufferAsprintf(buf, "%d\n",
+  sev->reduced_phys_bits);
+virBufferAsprintf(buf, "%s\n", sev->pdh);
+virBufferAsprintf(buf, "%s\n",
+  sev->cert_chain);
+virBufferAdjustIndent(buf, -2);
+virBufferAddLit(buf, "\n");
+}
+
 
 char *
 virDomainCapsFormat(virDomainCapsPtr const caps)
@@ -587,6 +606,7 @@ virDomainCapsFormat(virDomainCapsPtr const caps)
 virBufferAdjustIndent(&buf, 2);
 
 virDomainCapsFeatureGICFormat(&buf, &caps->gic);
+virDomainCapsFeatureSEVFormat(&buf, caps->sev);
 
 virBufferAdjustIndent(&buf, -2);
 virBufferAddLit(&buf, "\n");
diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index 72e9daf..2e8596c 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -170,6 +170,7 @@ struct _virDomainCaps {
 /* add new domain devices her

[libvirt] [PATCH v4 3/9] conf: introduce launch-security element in domain

2018-03-27 Thread Brijesh Singh
The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
 docs/formatdomain.html.in | 120 ++
 docs/schemas/domaincommon.rng |  39 ++
 src/conf/domain_conf.c| 110 ++
 src/conf/domain_conf.h|  26 +
 4 files changed, 295 insertions(+)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 08dc74b..00ed0b4 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8200,6 +8200,126 @@ qemu-kvm -net nic,model=? /dev/null
 
 Note: DEA/TDEA is synonymous with DES/TDES.
 
+Secure Encrypted Virtualization (SEV)
+
+
+   The contents of the <launch-security type='sev'> 
element
+   is used to provide the guest owners input used for creating an encrypted
+   VM using the AMD SEV feature.
+
+   SEV is an extension to the AMD-V architecture which supports running
+   encrypted virtual machine (VMs) under the control of KVM. Encrypted
+   VMs have their pages (code and data) secured such that only the guest
+   itself has access to the unencrypted version. Each encrypted VM is
+   associated with a unique encryption key; if its data is accessed to a
+   different entity using a different key the encrypted guests data will
+   be incorrectly decrypted, leading to unintelligible data.
+
+   For more information see various input parameters and its format see 
SEV API spec
+   https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";> 
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf 
+   Since 4.2.0
+   
+
+<domain>
+  ...
+  <launch-security type='sev'>
+<policy> 0 </policy>
+<cbitpos> 47 </cbitpos>
+<reduced-phys-bits> 5 </reduced-phys-bits>
+<session> ... </session>
+<dh-cert> ... </dh>
+  </sev>
+  ...
+</domain>
+
+
+
+A least cbitpos and reduced-phys-bits must be
+nested within the launch-security element.
+
+
+  cbitpos
+  The cbitpos element provides the C-bit (aka encryption 
bit)
+  location in guest page table entry. The value of cbitpos is
+  hypervisor dependent and can be obtained through the sev 
element
+  from domaincapabilities.
+  
+  reduced-phys-bits
+  The reduced-phys-bits element provides the physical
+  address bit reducation. Similar to cbitpos the value of 

+  reduced-phys-bit is hypervisor dependent and can be obtained
+  through the sev element from domaincapabilities.
+  
+  policy
+  The optional policy element provides the guest policy
+  which must be maintained by the SEV firmware. This policy is enforced by
+  the firmware and restricts what configuration and operational commands
+  can be performed on this guest by the hypervisor. The guest policy
+  provided during guest launch is bound to the guest and cannot be changed
+  throughout the lifetime of the guest. The policy is also transmitted
+  during snapshot and migration flows and enforced on the destination 
platform.
+
+  The guest policy is a 4-byte structure with the fields shown in Table:
+
+  
+
+   Bit(s) 
+   Description 
+
+
+   0 
+   Debugging of the guest is disallowed when set 
+
+
+   1 
+   Sharing keys with other guests is disallowed when set 
+
+
+   2 
+   SEV-ES is required when set
+
+
+   3 
+   Sending the guest to another platform is disallowed when 
set
+
+
+   4 
+   The guest must not be transmitted to another platform that is
+   not in the domain when set. 
+
+
+   5 
+   The guest must not be transmitted to another platform that is
+   not SEV capable when set. 
+
+
+   15:6 
+   reserved 
+
+
+   16:32 
+   The guest must not be transmitted to another platform with a
+   lower firmware version. 
+
+  
+  Default value is 0x1
+
+  

[libvirt] [PATCH v4 5/9] libvirt: add new public API to get launch security info

2018-03-27 Thread Brijesh Singh
The API can be used outside the libvirt to get the launch security
information. When SEV is enabled, the API can be used to get the
measurement of the launch process.

Signed-off-by: Brijesh Singh 
---
 include/libvirt/libvirt-domain.h | 17 ++
 src/driver-hypervisor.h  |  7 ++
 src/libvirt-domain.c | 48 
 src/libvirt_public.syms  |  5 +
 4 files changed, 77 insertions(+)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index 12fd340..6870a1a 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -4764,4 +4764,21 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 unsigned int action,
 unsigned int flags);
 
+/**
+ * Launch Security API
+ */
+
+/**
+ * VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT:
+ *
+ * Macro represents the launch measurement of the SEV guest,
+ * as VIR_TYPED_PARAM_STRING.
+ */
+#define VIR_DOMAIN_LAUNCH_SECURITY_SEV_MEASUREMENT "sev-measurement"
+
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags);
+
 #endif /* __VIR_LIBVIRT_DOMAIN_H__ */
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index ce0e2b2..b066413 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1283,6 +1283,12 @@ typedef int
   unsigned int action,
   unsigned int flags);
 
+typedef int
+(*virDrvDomainGetLaunchSecurityInfo)(virDomainPtr domain,
+ virTypedParameterPtr *params,
+ int *nparams,
+ unsigned int flags);
+
 
 typedef struct _virHypervisorDriver virHypervisorDriver;
 typedef virHypervisorDriver *virHypervisorDriverPtr;
@@ -1528,6 +1534,7 @@ struct _virHypervisorDriver {
 virDrvDomainSetVcpu domainSetVcpu;
 virDrvDomainSetBlockThreshold domainSetBlockThreshold;
 virDrvDomainSetLifecycleAction domainSetLifecycleAction;
+virDrvDomainGetLaunchSecurityInfo domainGetLaunchSecurityInfo;
 };
 
 
diff --git a/src/libvirt-domain.c b/src/libvirt-domain.c
index 63d2ae2..5b63a3c 100644
--- a/src/libvirt-domain.c
+++ b/src/libvirt-domain.c
@@ -12101,3 +12101,51 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
 virDispatchError(domain->conn);
 return -1;
 }
+
+/**
+ * virDomainGetLaunchSecurityInfo:
+ * @domain: a domain object
+ * @params: where to store security info
+ * @nparams: number of items in @params
+ * @flags: currently used, set to 0.
+ *
+ * Get the launch security info. In case of the SEV guest, this will
+ * return the launch measurement.
+ *
+ * Returns -1 in case of failure, 0 in case of success.
+ */
+int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
+   virTypedParameterPtr *params,
+   int *nparams,
+   unsigned int flags)
+{
+virConnectPtr conn = domain->conn;
+
+VIR_DOMAIN_DEBUG(domain, "params=%p, nparams=%p flags=0x%x",
+ params, nparams, flags);
+
+virResetLastError();
+
+virCheckDomainReturn(domain, -1);
+virCheckNonNullArgGoto(params, error);
+virCheckNonNullArgGoto(nparams, error);
+virCheckReadOnlyGoto(conn->flags, error);
+
+if (VIR_DRV_SUPPORTS_FEATURE(domain->conn->driver, domain->conn,
+ VIR_DRV_FEATURE_TYPED_PARAM_STRING))
+flags |= VIR_TYPED_PARAM_STRING_OKAY;
+
+if (conn->driver->domainGetLaunchSecurityInfo) {
+int ret;
+ret = conn->driver->domainGetLaunchSecurityInfo(domain, params,
+nparams, flags);
+if (ret < 0)
+goto error;
+return ret;
+}
+virReportUnsupportedError();
+
+ error:
+virDispatchError(domain->conn);
+return -1;
+}
diff --git a/src/libvirt_public.syms b/src/libvirt_public.syms
index 95df3a0..caba286 100644
--- a/src/libvirt_public.syms
+++ b/src/libvirt_public.syms
@@ -785,4 +785,9 @@ LIBVIRT_4.1.0 {
 virStoragePoolLookupByTargetPath;
 } LIBVIRT_3.9.0;
 
+LIBVIRT_4.2.0 {
+global:
+virDomainGetLaunchSecurityInfo;
+} LIBVIRT_4.1.0;
+
 #  define new API here using predicted next version number 
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v4 4/9] qemu: add support to launch SEV guest

2018-03-27 Thread Brijesh Singh
QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted
VMs on AMD platform using SEV feature. The various inputs required to
launch SEV guest is provided through the  tag. A typical
SEV guest launch command line looks like this:

# $QEMU ...\
  -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
  -machine memory-encryption=sev0 \

Signed-off-by: Brijesh Singh 
---
 src/qemu/qemu_command.c | 35 +
 src/qemu/qemu_process.c | 58 +
 2 files changed, 93 insertions(+)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 89fd08b..13d54e4 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7405,6 +7405,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
 qemuAppendLoadparmMachineParm(&buf, def);
 
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) && def->sev)
+virBufferAddLit(&buf, ",memory-encryption=sev0");
+
 virCommandAddArgBuffer(cmd, &buf);
 }
 
@@ -9750,6 +9753,35 @@ qemuBuildTPMCommandLine(virCommandPtr cmd,
 return 0;
 }
 
+static void
+qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
+virDomainSevDefPtr sev)
+{
+virBuffer obj = VIR_BUFFER_INITIALIZER;
+qemuDomainObjPrivatePtr priv = vm->privateData;
+char *path = NULL;
+
+VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
+  sev->policy, sev->cbitpos, sev->reduced_phys_bits);
+
+virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
+virBufferAsprintf(&obj, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
+virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
+
+if (sev->dh_cert) {
+ignore_value(virAsprintf(&path, "%s/dh_cert.base64", priv->libDir));
+virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
+VIR_FREE(path);
+}
+
+if (sev->session) {
+ignore_value(virAsprintf(&path, "%s/session.base64", priv->libDir));
+virBufferAsprintf(&obj, ",session-file=%s", path);
+VIR_FREE(path);
+}
+
+virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), NULL);
+}
 
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
@@ -10195,6 +10227,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
 if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
 goto error;
 
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST) && def->sev)
+qemuBuildSevCommandLine(vm, cmd, def->sev);
+
 if (snapshot)
 virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 1afb71f..f0e32fd 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5744,6 +5744,61 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
 return ret;
 }
 
+static int
+qemuBuildSevCreateFile(const char *configDir, const char *name,
+   const char *data)
+{
+char *configFile;
+
+if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
+return -1;
+
+if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+virReportSystemError(errno, _("failed to write data to config '%s'"),
+ configFile);
+goto error;
+}
+
+VIR_FREE(configFile);
+return 0;
+
+ error:
+VIR_FREE(configFile);
+return -1;
+}
+
+static int
+qemuProcessPrepareSevGuestInput(virDomainObjPtr vm)
+{
+qemuDomainObjPrivatePtr priv = vm->privateData;
+virDomainDefPtr def = vm->def;
+virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+virDomainSevDefPtr sev = def->sev;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("Prepare SEV guest");
+
+if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+_("Domain %s asked for 'sev' launch but "
+  "QEMU does not support SEV feature"), vm->def->name);
+return -1;
+}
+
+if (sev->dh_cert) {
+if (qemuBuildSevCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
+return -1;
+}
+
+if (sev->session) {
+if (qemuBuildSevCreateFile(priv->libDir, "session", sev->session) < 0)
+return -1;
+}
+
+return 0;
+}
 
 static int
 qemuProcessPrepareHostStorage(virQEMUDriverPtr driver,
@@ -5869,6 +5924,9 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver,
 if (qemuProcessPrepareHostStorage(driver, vm, flags) < 0)
 goto cleanup;
 
+if (qemuProcessPrepareSevGuestInput(vm) < 0)
+goto cleanup;
+
 ret = 0;
  cleanup:
 virObjectUnref(cfg);
-- 
2.7.4

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v4 1/9] qemu: provide support to query the SEV capability

2018-03-27 Thread Brijesh Singh
QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
 src/conf/domain_capabilities.h | 13 
 src/qemu/qemu_capabilities.c   | 38 +++
 src/qemu/qemu_capabilities.h   |  1 +
 src/qemu/qemu_capspriv.h   |  4 ++
 src/qemu/qemu_monitor.c|  9 +++
 src/qemu/qemu_monitor.h|  3 +
 src/qemu/qemu_monitor_json.c   | 73 ++
 src/qemu/qemu_monitor_json.h   |  3 +
 .../caps_2.12.0.x86_64.replies | 10 +++
 tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml  |  3 +-
 10 files changed, 156 insertions(+), 1 deletion(-)

diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index fa4c1e4..72e9daf 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -137,6 +137,19 @@ struct _virDomainCapsCPU {
 virDomainCapsCPUModelsPtr custom;
 };
 
+/*
+ * SEV capabilities
+ */
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+char *pdh;
+char *cert_chain;
+unsigned int cbitpos;
+unsigned int reduced_phys_bits;
+};
+
+
 struct _virDomainCaps {
 virObjectLockable parent;
 
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c
index e54dde6..0f6e6fb 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -466,6 +466,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
   /* 285 */
   "virtio-mouse-ccw",
   "virtio-tablet-ccw",
+  "sev-guest",
 );
 
 
@@ -532,6 +533,8 @@ struct _virQEMUCaps {
 size_t ngicCapabilities;
 virGICCapability *gicCapabilities;
 
+virSEVCapability *sevCapabilities;
+
 virQEMUCapsHostCPUData kvmCPU;
 virQEMUCapsHostCPUData tcgCPU;
 };
@@ -1705,6 +1708,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
 { "virtio-keyboard-ccw", QEMU_CAPS_DEVICE_VIRTIO_KEYBOARD_CCW },
 { "virtio-mouse-ccw", QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW },
 { "virtio-tablet-ccw", QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW },
+{ "sev-guest", QEMU_CAPS_SEV_GUEST },
 };
 
 static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = {
@@ -2784,6 +2788,21 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
 qemuCaps->ngicCapabilities = ncapabilities;
 }
 
+void
+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+  virSEVCapability *capabilities)
+{
+virSEVCapability *cap = qemuCaps->sevCapabilities;
+
+if (cap) {
+VIR_FREE(cap->pdh);
+VIR_FREE(cap->cert_chain);
+}
+
+VIR_FREE(qemuCaps->sevCapabilities);
+
+qemuCaps->sevCapabilities = capabilities;
+}
 
 static int
 virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
@@ -3287,6 +3306,19 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr 
qemuCaps,
 return 0;
 }
 
+static int
+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+   qemuMonitorPtr mon)
+{
+virSEVCapability *caps = NULL;
+
+if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+return -1;
+
+virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+return 0;
+}
 
 bool
 virQEMUCapsCPUFilterFeatures(const char *name,
@@ -4768,6 +4800,12 @@ virQEMUCapsInitQMPMonitor(virQEMUCapsPtr qemuCaps,
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_QUERY_CPU_MODEL_EXPANSION))
 virQEMUCapsSet(qemuCaps, QEMU_CAPS_CPU_CACHE);
 
+/* Probe for SEV capabilities */
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV_GUEST)) {
+if (virQEMUCapsProbeQMPSEVCapabilities(qemuCaps, mon) < 0)
+virQEMUCapsClear(qemuCaps, QEMU_CAPS_SEV_GUEST);
+}
+
 ret = 0;
  cleanup:
 return ret;
diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h
index 3f3c29f..9b51cc2 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -450,6 +450,7 @@ typedef enum {
 /* 285 */
 QEMU_CAPS_DEVICE_VIRTIO_MOUSE_CCW, /* -device virtio-mouse-ccw */
 QEMU_CAPS_DEVICE_VIRTIO_TABLET_CCW, /* -device virtio-tablet-ccw */
+QEMU_CAPS_SEV_GUEST, /* -object sev-guest,... */
 
 QEMU_CAPS_LAST /* this must always be the last item */
 } virQEMUCapsFlags;
diff --git a/src/qemu/qemu_capspriv.h b/src/qemu/qemu_capspriv.h
index 222f336..1fa85cc 100644
--- a/src/qemu/qemu_capspriv.h
+++ b/src/qemu/qemu_capspriv.h
@@ -86,6 +86,10 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
   virGICCapabil

[libvirt] [PATCH v4 0/9] x86: Secure Encrypted Virtualization (AMD)

2018-03-27 Thread Brijesh Singh
This patch series provides support for launching an encrypted guest using
AMD's new Secure Encrypted  Virtualization (SEV) feature.

SEV is an extension to the AMD-V architecture which supports running
multiple VMs under the control of a hypervisor. When enabled, SEV feature
allows the memory contents of a virtual machine (VM) to be transparently
encrypted with a key unique to the guest VM.

At very high level the flow looks this:

1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML document
that includes the following


...
  
 
 
 
 


If  is provided then we indicate that hypervisor is capable of launching
SEV guest. 

2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in 
case
if guest owner wish to establish a secure connection with SEV firmware to
negotiate a key used for validating the measurement.

3. mgmt tool requests to start a guest calling virCreateXML(), passing 
VIR_DOMAIN_START_PAUSED.
The xml would include


 /* the value is same as what is obtained via 
virConnectGetDomainCapabilities()
 /* the value is same as what is 
obtained via virConnectGetDomainCapabilities()
   ..  /* guest owners diffie-hellman key */ (optional)
   .. /* guest owners session blob */ (optional)
   .. /* guest policy */ (optional)


4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
args looks like this:

# $QEMU ..
-machine memory-encryption=sev0 \
-object sev-guest,id=sev0,dh-cert-file=

5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event

6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls 
virDomainGetLaunchSecretInfo()
to retrieve the measurement of encrypted memory.

7. (optional) mgmt tool can provide the measurement value to guest owner, which 
can
validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
it resumes the guest otherwise it calls destroy() to kill the guest.

8. mgmt tool resumes the guest

TODO:
* SEV guest require to use DMA apis for the virtio devices. In order to use the 
DMA
apis the virtio devices must have this tag



It is a bit unclear to me where these changes need to go. Do we need to
modify the libvirt to automatically add these when SEV is enabled or
we ask mgmt tool to make sure that it creates XML with right tag to enable
the DMA APIs for virtio devices. I am looking for some suggestions.

Using these patches we have succesfully booted and tested a guest both with and
without SEV enabled.

SEV Firmware API spec is available at:
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf

Changes since v3:
* rename QEMU_CAPS_SEV -> QEMU_CAPS_SEV_GUEST
* update caps_2.12.0.x86_64.replies to include query-sev-capabilities data

Changes since v2:
* make cbitpos, policy and reduced-phys-bits as unsigned int
* update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr *params
instead of virTypedParameterPtr params.

Changes since v1:
* rename  ->  for domain
* add more information about policy and other fields in domaincaps.html
* split the domain_conf support in two patches
* add virDomainGetLaunchInfo() to retrieve the SEV measurement
* extend virsh command to show the domain's launch security information
* add test cases to validate newly added  element
* fix issues reported with 'make check' and 'make syntax-check'

The complete git tree is available at:
https://github.com/codomania/libvirt/tree/v3


Brijesh Singh (8):
  qemu: provide support to query the SEV capability
  qemu: introduce SEV feature in hypervisor capabilities
  conf: introduce launch-security element in domain
  qemu: add support to launch SEV guest
  libvirt: add new public API to get launch security info
  remote: implement the remote protocol for launch security
  qemu_driver: add support to launch security info
  virsh: implement new command for launch security

Xiaogang Chen (1):
  tests: extend tests to include sev specific tag parsing

 docs/formatdomain.html.in  | 120 +
 docs/formatdomaincaps.html.in  |  40 +++
 docs/schemas/domaincaps.rng|  20 
 docs/schemas/domaincommon.rng  |  39 +++
 include/libvirt/libvirt-domain.h   |  17 +++
 src/conf/domain_capabilities.c |  20 
 src/conf/domain_capabilities.h |  14 +++
 src/conf/domain_conf.c | 110 +++
 src/conf/domain_conf.h |  26 +
 src/driver-hypervisor.h|   7 ++
 src/libvirt-domain.c   |  48 +
 src/libvirt_public.syms|   5 +
 src/qemu/qemu_capabilities.c   |  40 +++
 src/qemu/qemu_capabilities.h   |   1 +
 src/qemu/qemu_capspriv.h   

Re: [libvirt] [PATCH v3 1/9] qemu: provide support to query the SEV capability

2018-03-27 Thread Brijesh Singh



On 03/26/2018 09:32 AM, Andrea Bolognani wrote:

On Mon, 2018-03-26 at 08:52 -0500, Brijesh Singh wrote:

I tried applying just this patch, but kept getting:

29) caps_2.12.0(x86_64)
... libvirt: QEMU Driver error : internal error: query-cpu-definitions
reply data was not an array

a small bit of debugging found that qemuMonitorJSONGetCPUDefinitions was
returning NULL for @data after/when the "query-sev-capabilities".

I narrowed it down into the virQEMUCapsInitQMPMonitor when run during
qemucapabilitiestest (see [1])


I have not tried latest libvirt yet, I will try this today and debug to
see what we are missing. I did the 'make check' before submitting the
patch but at that time QEMU 2.12 was not available and we did not had
updated caps_2.12.0.x86_64.xml and caps_2.12.0.x86_64.replies.


I thought the lack of churn in tests/qemucapabilitiesdata/ was
weird, but thanks to your explanation it makes perfect sense now.

Your code adds a call to query-sev-capabilities, but the replies
file doesn't contain the corresponding return data, which makes
the parser go out of sync.

You're going to have to either fetch capabilities from your own
QEMU 2.12 binary or hack it up by adding the return data in the
right spot and call tests/qemucapsfixreplies to re-align the ids.



Right, running the tests/qemucapsprobe on my system I see that 
query-sev-capabilities command returns a valid data. In my local branch, 
I updated the caps_2.12.0.x86_64.replies with response. With those 
changes I no longer get the internal error but 
tests/qemucapabilitiestest still fails for me with below error message:


29) caps_2.12.0(x86_64)   ...
 In 
'/home/amd/workdir/upstream/libvirt/tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml':

 Offset 7143
 Expect [060]
 Actual [306]

It is basically pointing to microcode version change, do I need to 
update the cap with new version ?





I think you can get away with the latter, as we're going to want
to refresh the replies files once 2.12 is released anyway.



I am not able to follow this comment, let me explain the situation.
The QEMU_CAPS_SEV flag was set to indicate QEMU supports the 
'query-sev-capabilities' QMP command and sev-guest object. That merely 
indicates that command exist but does not means that command will always 
execute successfully. e.g If hypervisor does not support the SEV feature 
then query-sev-capabilities will return error. That means if 
tests/qemucapsprobe is used to generate the replies on non-SEV capable 
system then .replies will not contain output of query-sev-capabilities 
command. Will this be an issue ?


-Brijesh

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


Re: [libvirt] [PATCH v3 1/9] qemu: provide support to query the SEV capability

2018-03-26 Thread Brijesh Singh

Hi John,


On 03/23/2018 02:18 PM, John Ferlan wrote:



On 03/14/2018 11:44 AM, Brijesh Singh wrote:

QEMU version >= 2.12 provides support for launching an encrypted VMs on
AMD x86 platform using Secure Encrypted Virtualization (SEV) feature.
This patch adds support to query the SEV capability from the qemu.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
  src/conf/domain_capabilities.h | 13 
  src/qemu/qemu_capabilities.c   | 38 ++
  src/qemu/qemu_capabilities.h   |  1 +
  src/qemu/qemu_capspriv.h   |  4 +++
  src/qemu/qemu_monitor.c|  9 ++
  src/qemu/qemu_monitor.h|  3 ++
  src/qemu/qemu_monitor_json.c   | 73 ++
  src/qemu/qemu_monitor_json.h   |  3 ++
  8 files changed, 144 insertions(+)



Now that the 2.12 capabilities were added, I started looking through
each of the upstream patch series that would make use of it - this is
just "next" on my list.

I tried applying just this patch, but kept getting:

29) caps_2.12.0(x86_64)
... libvirt: QEMU Driver error : internal error: query-cpu-definitions
reply data was not an array

a small bit of debugging found that qemuMonitorJSONGetCPUDefinitions was
returning NULL for @data after/when the "query-sev-capabilities".

I narrowed it down into the virQEMUCapsInitQMPMonitor when run during
qemucapabilitiestest (see [1])


I have not tried latest libvirt yet, I will try this today and debug to 
see what we are missing. I did the 'make check' before submitting the 
patch but at that time QEMU 2.12 was not available and we did not had 
updated caps_2.12.0.x86_64.xml and caps_2.12.0.x86_64.replies.


I will investigate a bit more and update with my findings.

thanks




diff --git a/src/conf/domain_capabilities.h b/src/conf/domain_capabilities.h
index fa4c1e442f57..72e9daf9120f 100644
--- a/src/conf/domain_capabilities.h
+++ b/src/conf/domain_capabilities.h
@@ -137,6 +137,19 @@ struct _virDomainCapsCPU {
  virDomainCapsCPUModelsPtr custom;
  };
  
+/*

+ * SEV capabilities
+ */
+typedef struct _virSEVCapability virSEVCapability;
+typedef virSEVCapability *virSEVCapabilityPtr;
+struct _virSEVCapability {
+char *pdh;
+char *cert_chain;
+unsigned int cbitpos;
+unsigned int reduced_phys_bits;
+};
+
+
  struct _virDomainCaps {
  virObjectLockable parent;
  
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c

index 3eb5ed6d1a60..6da7cf7477c7 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -459,6 +459,7 @@ VIR_ENUM_IMPL(virQEMUCaps, QEMU_CAPS_LAST,
"pl011",
"machine.pseries.max-cpu-compat",
"dump-completed",
+  "sev",


This should also be "sev-guest" to be consistent with other
virQEMUCapsObjectTypes entries naming.

BTW: You can/should pull out this entry, the one in
virQEMUCapsObjectTypes and the qemu_capabilities.h change to add the
entry to virQEMUCapsFlags, then build and run:

   VIR_TEST_REGENERATE_OUTPUT=1 tests/qemucapabilitiestest

in order to get/see the changed
tests/qemucapabilitiesdata/caps_2.12.0.x86_64.xml file.



  );
  
  
@@ -525,6 +526,8 @@ struct _virQEMUCaps {

  size_t ngicCapabilities;
  virGICCapability *gicCapabilities;
  
+virSEVCapability *sevCapabilities;

+
  virQEMUCapsHostCPUData kvmCPU;
  virQEMUCapsHostCPUData tcgCPU;
  };
@@ -1694,6 +1697,7 @@ struct virQEMUCapsStringFlags virQEMUCapsObjectTypes[] = {
  { "sclplmconsole", QEMU_CAPS_DEVICE_SCLPLMCONSOLE },
  { "isa-serial", QEMU_CAPS_DEVICE_ISA_SERIAL },
  { "pl011", QEMU_CAPS_DEVICE_PL011 },
+{ "sev-guest", QEMU_CAPS_SEV },
  };
  
  static struct virQEMUCapsStringFlags virQEMUCapsObjectPropsVirtioBalloon[] = {

@@ -2770,6 +2774,21 @@ virQEMUCapsSetGICCapabilities(virQEMUCapsPtr qemuCaps,
  qemuCaps->ngicCapabilities = ncapabilities;
  }
  
+void

+virQEMUCapsSetSEVCapabilities(virQEMUCapsPtr qemuCaps,
+  virSEVCapability *capabilities)
+{
+virSEVCapability *cap = qemuCaps->sevCapabilities;
+
+if (cap) {
+VIR_FREE(cap->pdh);
+VIR_FREE(cap->cert_chain);
+}
+
+VIR_FREE(qemuCaps->sevCapabilities);
+
+qemuCaps->sevCapabilities = capabilities;
+}
  
  static int

  virQEMUCapsProbeQMPCommands(virQEMUCapsPtr qemuCaps,
@@ -3273,6 +3292,19 @@ virQEMUCapsProbeQMPGICCapabilities(virQEMUCapsPtr 
qemuCaps,
  return 0;
  }
  
+static int

+virQEMUCapsProbeQMPSEVCapabilities(virQEMUCapsPtr qemuCaps,
+   qemuMonitorPtr mon)
+{
+virSEVCapability *caps = NULL;
+
+if (qemuMonitorGetSEVCapabilities(mon, &caps) < 0)
+return -1;
+
+virQEMUCapsSetSEVCapabilities(qemuCaps, caps);
+
+return 0;
+}
  
  bool

Re: [libvirt] [PATCH v3 0/9] x86: Secure Encrypted Virtualization (AMD)

2018-03-23 Thread Brijesh Singh
Hi Daniel and Peter.

Any feedback on the series ?

-Brijesh

On 3/14/18 10:44 AM, Brijesh Singh wrote:
> The patch series is test with QEMU recent pull which includes SEV support:
>
> https://lists.gnu.org/archive/html/qemu-devel/2018-03/msg03826.html
>
> This patch series provides support for launching an encrypted guest using
> AMD's new Secure Encrypted  Virtualization (SEV) feature.
>
> SEV is an extension to the AMD-V architecture which supports running
> multiple VMs under the control of a hypervisor. When enabled, SEV feature
> allows the memory contents of a virtual machine (VM) to be transparently
> encrypted with a key unique to the guest VM.
>
> At very high level the flow looks this:
>
> 1. mgmt tool calls virConnectGetDomainCapabilities. This returns an XML 
> document
> that includes the following
>
> 
> ...
>   
>
>
>
>
> 
>
> If  is provided then we indicate that hypervisor is capable of launching
> SEV guest. 
>
> 2. (optional) mgmt tool can provide the PDH and Cert-chain to guest owner in 
> case
> if guest owner wish to establish a secure connection with SEV firmware to
> negotiate a key used for validating the measurement.
>
> 3. mgmt tool requests to start a guest calling virCreateXML(), passing 
> VIR_DOMAIN_START_PAUSED.
> The xml would include
>
> 
>/* the value is same as what is obtained via 
> virConnectGetDomainCapabilities()
>/* the value is same as what is 
> obtained via virConnectGetDomainCapabilities()
>  ..  /* guest owners diffie-hellman key */ (optional)
>  .. /* guest owners session blob */ (optional)
> .. /* guest policy */ (optional)
>
> 4. Libvirt generate the QEMU cli arg to enable the SEV feature, a typical
> args looks like this:
>
> # $QEMU ..
> -machine memory-encryption=sev0 \
> -object sev-guest,id=sev0,dh-cert-file=
>
> 5. Libvirt generates lifecycle VIR_DOMAIN_EVENT_SUSPENDED_PAUSED event
>
> 6. mgmt tool gets the VIR_DOMAIN_EVENT_SUSPENDED_PAUSED and calls 
> virDomainGetLaunchSecretInfo()
> to retrieve the measurement of encrypted memory.
>
> 7. (optional) mgmt tool can provide the measurement value to guest owner, 
> which can
> validate the measurement and gives GO/NO-GO answer. If mgmt tool gets GO then
> it resumes the guest otherwise it calls destroy() to kill the guest.
>
> 8. mgmt tool resumes the guest
>
> TODO:
> * SEV guest require to use DMA apis for the virtio devices. In order to use 
> the DMA
> apis the virtio devices must have this tag
>
> 
>
> It is a bit unclear to me where these changes need to go. Do we need to
> modify the libvirt to automatically add these when SEV is enabled or
> we ask mgmt tool to make sure that it creates XML with right tag to enable
> the DMA APIs for virtio devices. I am looking for some suggestions.
>
> Using these patches we have succesfully booted and tested a guest both with 
> and
> without SEV enabled.
>
> SEV Firmware API spec is available at:
> https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf
>
> Changes since v2:
>  * make cbitpos, policy and reduced-phys-bits as unsigned int
>  * update virDomainGetLaunchSecurityInfo to accept virTypedParameterPtr 
> *params
>instead of virTypedParameterPtr params.
>
> Changes since v1:
>  * rename  ->  for domain
>  * add more information about policy and other fields in domaincaps.html
>  * split the domain_conf support in two patches
>  * add virDomainGetLaunchInfo() to retrieve the SEV measurement
>  * extend virsh command to show the domain's launch security information
>  * add test cases to validate newly added  element
>  * fix issues reported with 'make check' and 'make syntax-check'
>
> The complete git tree is available at:
> https://github.com/codomania/libvirt/tree/v3
>
>
> Brijesh Singh (8):
>   qemu: provide support to query the SEV capability
>   qemu: introduce SEV feature in hypervisor capabilities
>   conf: introduce launch-security element in domain
>   qemu: add support to launch SEV guest
>   libvirt: add new public API to get launch security info
>   remote: implement the remote protocol for launch security
>   qemu_driver: add support to launch security info
>   virsh: implement new command for launch security
>
> Xiaogang Chen (1):
>   tests: extend tests to include sev specific tag parsing
>
>  docs/formatdomain.html.in   | 120 
> 
>  docs/formatdomaincaps.html.in   |  40 
>  docs/schemas/domaincaps.rng |  20 ++
>  docs/schemas/domaincommon.rng   |  39 
>  include/libvirt/libvirt-domain.h|  1

[libvirt] [PATCH v3 6/9] remote: implement the remote protocol for launch security

2018-03-15 Thread Brijesh Singh
Add remote support for launch security info.

Signed-off-by: Brijesh Singh 
---
 src/remote/remote_daemon_dispatch.c | 47 +
 src/remote/remote_driver.c  | 42 -
 src/remote/remote_protocol.x| 20 +++-
 src/remote_protocol-structs | 11 +
 4 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/src/remote/remote_daemon_dispatch.c 
b/src/remote/remote_daemon_dispatch.c
index ea67cb7bc018..b22eda6b 100644
--- a/src/remote/remote_daemon_dispatch.c
+++ b/src/remote/remote_daemon_dispatch.c
@@ -3087,6 +3087,53 @@ remoteDispatchNodeGetMemoryStats(virNetServerPtr server 
ATTRIBUTE_UNUSED,
 return rv;
 }
 
+static int
+remoteDispatchDomainGetLaunchSecurityInfo(virNetServerPtr server 
ATTRIBUTE_UNUSED,
+  virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
+  virNetMessagePtr msg 
ATTRIBUTE_UNUSED,
+  virNetMessageErrorPtr rerr,
+  
remote_domain_get_launch_security_info_args *args,
+  
remote_domain_get_launch_security_info_ret *ret)
+{
+virDomainPtr dom = NULL;
+virTypedParameterPtr params = NULL;
+int nparams = 0;
+int rv = -1;
+struct daemonClientPrivate *priv =
+virNetServerClientGetPrivateData(client);
+
+if (!priv->conn) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("connection not open"));
+goto cleanup;
+}
+
+if (!(dom = get_nonnull_domain(priv->conn, args->dom)))
+goto cleanup;
+
+if (virDomainGetLaunchSecurityInfo(dom, ¶ms, &nparams, args->flags) < 
0)
+goto cleanup;
+
+if (nparams > REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX) {
+virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("nparams too large"));
+goto cleanup;
+}
+
+if (virTypedParamsSerialize(params, nparams,
+(virTypedParameterRemotePtr *) 
&ret->params.params_val,
+&ret->params.params_len,
+args->flags) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+if (rv < 0)
+virNetMessageSaveError(rerr);
+virTypedParamsFree(params, nparams);
+virObjectUnref(dom);
+return rv;
+}
+
 static int
 remoteDispatchDomainGetPerfEvents(virNetServerPtr server ATTRIBUTE_UNUSED,
   virNetServerClientPtr client 
ATTRIBUTE_UNUSED,
diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c
index 93cba5daa3e8..ea974e77490f 100644
--- a/src/remote/remote_driver.c
+++ b/src/remote/remote_driver.c
@@ -1951,6 +1951,45 @@ remoteDomainGetNumaParameters(virDomainPtr domain,
 return rv;
 }
 
+static int
+remoteDomainGetLaunchSecurityInfo(virDomainPtr domain,
+  virTypedParameterPtr *params,
+  int *nparams,
+  unsigned int flags)
+{
+int rv = -1;
+remote_domain_get_launch_security_info_args args;
+remote_domain_get_launch_security_info_ret ret;
+struct private_data *priv = domain->conn->privateData;
+
+remoteDriverLock(priv);
+
+make_nonnull_domain(&args.dom, domain);
+args.flags = flags;
+
+memset(&ret, 0, sizeof(ret));
+if (call(domain->conn, priv, 0, 
REMOTE_PROC_DOMAIN_GET_LAUNCH_SECURITY_INFO,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_args, 
(char *) &args,
+ (xdrproc_t) xdr_remote_domain_get_launch_security_info_ret, (char 
*) &ret) == -1)
+goto done;
+
+if (virTypedParamsDeserialize((virTypedParameterRemotePtr) 
ret.params.params_val,
+  ret.params.params_len,
+  
REMOTE_DOMAIN_LAUNCH_SECURITY_INFO_PARAMS_MAX,
+  params,
+  nparams) < 0)
+goto cleanup;
+
+rv = 0;
+
+ cleanup:
+xdr_free((xdrproc_t) xdr_remote_domain_get_launch_security_info_ret,
+ (char *) &ret);
+ done:
+remoteDriverUnlock(priv);
+return rv;
+}
+
 static int
 remoteDomainGetPerfEvents(virDomainPtr domain,
   virTypedParameterPtr *params,
@@ -8497,7 +8536,8 @@ static virHypervisorDriver hypervisor_driver = {
 .domainSetGuestVcpus = remoteDomainSetGuestVcpus, /* 2.0.0 */
 .domainSetVcpu = remoteDomainSetVcpu, /* 3.1.0 */
 .domainSetBlockThreshold = remoteDomainSetBlockThreshold, /* 3.2.0 */
-.domainSetLifecycleAction = remoteDomainSetLifecycleAction /* 3.9.0 */
+.domainSetLifecycleAction = remoteDomainSetLifecycleAction, /* 3.9.0 */
+.domainGetLaunchSecurityInfo = remoteDomainGetLaunchSecurityInfo 

[libvirt] [PATCH v3 9/9] tests: extend tests to include sev specific tag parsing

2018-03-15 Thread Brijesh Singh
From: Xiaogang Chen 

Update qemuxml2xmltest, genericxml2xmltest and qemuxml2argvtest to include
sev specific tag, a typical SEV specific tag looks like


+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+47
+1
+1
+  
+
diff --git a/tests/genericxml2xmloutdata/sev.xml 
b/tests/genericxml2xmloutdata/sev.xml
new file mode 100644
index ..70065b861861
--- /dev/null
+++ b/tests/genericxml2xmloutdata/sev.xml
@@ -0,0 +1,22 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+  
+  
+47
+1
+1
+  
+
diff --git a/tests/genericxml2xmltest.c b/tests/genericxml2xmltest.c
index d8270a6cae82..3b75b43feda3 100644
--- a/tests/genericxml2xmltest.c
+++ b/tests/genericxml2xmltest.c
@@ -141,6 +141,8 @@ mymain(void)
 DO_TEST_FULL("cachetune-colliding-types", false, true,
  TEST_COMPARE_DOM_XML2XML_RESULT_FAIL_PARSE);
 
+DO_TEST_DIFFERENT("sev");
+
 virObjectUnref(caps);
 virObjectUnref(xmlopt);
 
diff --git a/tests/qemuxml2argvdata/sev.args b/tests/qemuxml2argvdata/sev.args
new file mode 100644
index ..312dbcfd3c6c
--- /dev/null
+++ b/tests/qemuxml2argvdata/sev.args
@@ -0,0 +1,24 @@
+LC_ALL=C \
+PATH=/bin \
+HOME=/home/test \
+USER=test \
+LOGNAME=test \
+QEMU_AUDIO_DRV=none \
+/usr/bin/qemu-system-x86_64 \
+-name QEMUGuest1 \
+-S \
+-machine pc-1.0,accel=kvm,memory-encryption=sev0 \
+-m 214 \
+-smp 1,sockets=1,cores=1,threads=1 \
+-uuid c7a5fdbd-edaf-9455-926a-d65c16db1809 \
+-nographic \
+-nodefaults \
+-chardev 
socket,id=charmonitor,path=/tmp/lib/domain--1-QEMUGuest1/monitor.sock,\
+server,nowait \
+-mon chardev=charmonitor,id=monitor,mode=readline \
+-no-acpi \
+-boot c \
+-usb \
+-drive file=/dev/HostVG/QEMUGuest1,format=raw,if=none,id=drive-ide0-0-0 \
+-device ide-drive,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0 \
+-object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=1,policy=0x1
diff --git a/tests/qemuxml2argvdata/sev.xml b/tests/qemuxml2argvdata/sev.xml
new file mode 100644
index ..2476b586d72e
--- /dev/null
+++ b/tests/qemuxml2argvdata/sev.xml
@@ -0,0 +1,35 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+  
+  
+  
+
+
+
+
+
+
+
+  
+  
+47
+1
+1
+  
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 731db9ed5221..5d43457730cc 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -3004,6 +3004,8 @@ mymain(void)
 DO_TEST("disk-many-format-probing", QEMU_CAPS_DRIVE_BOOT);
 driver.config->allowDiskFormatProbing = false;
 
+DO_TEST("sev", QEMU_CAPS_MACHINE_OPT, QEMU_CAPS_KVM, QEMU_CAPS_SEV);
+
 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
 virFileDeleteTree(fakerootdir);
 
diff --git a/tests/qemuxml2xmloutdata/sev.xml b/tests/qemuxml2xmloutdata/sev.xml
new file mode 100644
index ..80017fe07691
--- /dev/null
+++ b/tests/qemuxml2xmloutdata/sev.xml
@@ -0,0 +1,39 @@
+
+  QEMUGuest1
+  c7a5fdbd-edaf-9455-926a-d65c16db1809
+  219100
+  219100
+  1
+  
+hvm
+
+  
+  
+  destroy
+  restart
+  destroy
+  
+/usr/bin/qemu-system-x86_64
+
+  
+  
+  
+  
+
+
+  
+
+
+  
+
+
+
+
+
+  
+  
+47
+1
+1
+  
+
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 28ba46efb2bc..1c2dcea7cf90 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -1243,6 +1243,8 @@ mymain(void)
 DO_TEST_STATUS("modern");
 DO_TEST_STATUS("migration-out-nbd");
 
+DO_TEST("sev", NONE);
+
 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
 virFileDeleteTree(fakerootdir);
 
-- 
2.14.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 4/9] qemu: add support to launch SEV guest

2018-03-15 Thread Brijesh Singh
QEMU >= 2.12 provides 'sev-guest' object which is used to launch encrypted
VMs on AMD platform using SEV feature. The various inputs required to
launch SEV guest is provided through the  tag. A typical
SEV guest launch command line looks like this:

# $QEMU ...\
  -object sev-guest,id=sev0,cbitpos=47,reduced-phys-bits=5 ...\
  -machine memory-encryption=sev0 \

Signed-off-by: Brijesh Singh 
---
 src/qemu/qemu_command.c | 35 +
 src/qemu/qemu_process.c | 58 +
 2 files changed, 93 insertions(+)

diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index fa0aa5d5c3d4..7e0f515d0d7e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -7354,6 +7354,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
 virQEMUCapsGet(qemuCaps, QEMU_CAPS_LOADPARM))
 qemuAppendLoadparmMachineParm(&buf, def);
 
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV) && def->sev)
+virBufferAddLit(&buf, ",memory-encryption=sev0");
+
 virCommandAddArgBuffer(cmd, &buf);
 }
 
@@ -9663,6 +9666,35 @@ qemuBuildTPMCommandLine(virCommandPtr cmd,
 return 0;
 }
 
+static void
+qemuBuildSevCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
+virDomainSevDefPtr sev)
+{
+virBuffer obj = VIR_BUFFER_INITIALIZER;
+qemuDomainObjPrivatePtr priv = vm->privateData;
+char *path = NULL;
+
+VIR_DEBUG("policy=0x%x cbitpos=%d reduced_phys_bits=%d",
+  sev->policy, sev->cbitpos, sev->reduced_phys_bits);
+
+virBufferAsprintf(&obj, "sev-guest,id=sev0,cbitpos=%d", sev->cbitpos);
+virBufferAsprintf(&obj, ",reduced-phys-bits=%d", sev->reduced_phys_bits);
+virBufferAsprintf(&obj, ",policy=0x%x", sev->policy);
+
+if (sev->dh_cert) {
+ignore_value(virAsprintf(&path, "%s/dh_cert.base64", priv->libDir));
+virBufferAsprintf(&obj, ",dh-cert-file=%s", path);
+VIR_FREE(path);
+}
+
+if (sev->session) {
+ignore_value(virAsprintf(&path, "%s/session.base64", priv->libDir));
+virBufferAsprintf(&obj, ",session-file=%s", path);
+VIR_FREE(path);
+}
+
+virCommandAddArgList(cmd, "-object", virBufferContentAndReset(&obj), NULL);
+}
 
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
@@ -10108,6 +10140,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
 if (qemuBuildVMCoreInfoCommandLine(cmd, def, qemuCaps) < 0)
 goto error;
 
+if (virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV) && def->sev)
+qemuBuildSevCommandLine(vm, cmd, def->sev);
+
 if (snapshot)
 virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index 57c06c7c1550..5c102de03582 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5741,6 +5741,61 @@ qemuProcessPrepareDomain(virQEMUDriverPtr driver,
 return ret;
 }
 
+static int
+qemuBuildSevCreateFile(const char *configDir, const char *name,
+   const char *data)
+{
+char *configFile;
+
+if (!(configFile = virFileBuildPath(configDir, name, ".base64")))
+return -1;
+
+if (virFileRewriteStr(configFile, S_IRUSR | S_IWUSR, data) < 0) {
+virReportSystemError(errno, _("failed to write data to config '%s'"),
+ configFile);
+goto error;
+}
+
+VIR_FREE(configFile);
+return 0;
+
+ error:
+VIR_FREE(configFile);
+return -1;
+}
+
+static int
+qemuProcessPrepareSevGuestInput(virDomainObjPtr vm)
+{
+qemuDomainObjPrivatePtr priv = vm->privateData;
+virDomainDefPtr def = vm->def;
+virQEMUCapsPtr qemuCaps = priv->qemuCaps;
+virDomainSevDefPtr sev = def->sev;
+
+if (!sev)
+return 0;
+
+VIR_DEBUG("Prepare SEV guest");
+
+if (!virQEMUCapsGet(qemuCaps, QEMU_CAPS_SEV)) {
+virReportError(VIR_ERR_INTERNAL_ERROR,
+_("Domain %s asked for 'sev' launch but "
+  "QEMU does not support SEV feature"), vm->def->name);
+return -1;
+}
+
+if (sev->dh_cert) {
+if (qemuBuildSevCreateFile(priv->libDir, "dh_cert", sev->dh_cert) < 0)
+return -1;
+}
+
+if (sev->session) {
+if (qemuBuildSevCreateFile(priv->libDir, "session", sev->session) < 0)
+return -1;
+}
+
+return 0;
+}
 
 static int
 qemuProcessPrepareHostStorage(virQEMUDriverPtr driver,
@@ -5866,6 +5921,9 @@ qemuProcessPrepareHost(virQEMUDriverPtr driver,
 if (qemuProcessPrepareHostStorage(driver, vm, flags) < 0)
 goto cleanup;
 
+if (qemuProcessPrepareSevGuestInput(vm) < 0)
+goto cleanup;
+
 ret = 0;
  cleanup:
 virObjectUnref(cfg);
-- 
2.14.3

--
libvir-list mailing list
libvir-list@redhat.com
https://www.redhat.com/mailman/listinfo/libvir-list


[libvirt] [PATCH v3 3/9] conf: introduce launch-security element in domain

2018-03-15 Thread Brijesh Singh
The launch-security element can be used to define the security
model to use when launching a domain. Currently we support 'sev'.

When 'sev' is used, the VM will be launched with AMD SEV feature enabled.
SEV feature supports running encrypted VM under the control of KVM.
Encrypted VMs have their pages (code and data) secured such that only the
guest itself has access to the unencrypted version. Each encrypted VM is
associated with a unique encryption key; if its data is accessed to a
different entity using a different key the encrypted guests data will be
incorrectly decrypted, leading to unintelligible data.

Reviewed-by: "Daniel P. Berrangé" 
Signed-off-by: Brijesh Singh 
---
 docs/formatdomain.html.in | 120 ++
 docs/schemas/domaincommon.rng |  39 ++
 src/conf/domain_conf.c| 110 ++
 src/conf/domain_conf.h|  26 +
 4 files changed, 295 insertions(+)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 6fd2189cd2f4..830d2a3c59be 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8195,6 +8195,126 @@ qemu-kvm -net nic,model=? /dev/null
 
 Note: DEA/TDEA is synonymous with DES/TDES.
 
+Secure Encrypted Virtualization (SEV)
+
+
+   The contents of the <launch-security type='sev'> 
element
+   is used to provide the guest owners input used for creating an encrypted
+   VM using the AMD SEV feature.
+
+   SEV is an extension to the AMD-V architecture which supports running
+   encrypted virtual machine (VMs) under the control of KVM. Encrypted
+   VMs have their pages (code and data) secured such that only the guest
+   itself has access to the unencrypted version. Each encrypted VM is
+   associated with a unique encryption key; if its data is accessed to a
+   different entity using a different key the encrypted guests data will
+   be incorrectly decrypted, leading to unintelligible data.
+
+   For more information see various input parameters and its format see 
SEV API spec
+   https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf";> 
https://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf 
+   Since 4.2.0
+   
+
+<domain>
+  ...
+  <launch-security type='sev'>
+<policy> 0 </policy>
+<cbitpos> 47 </cbitpos>
+<reduced-phys-bits> 5 </reduced-phys-bits>
+<session> ... </session>
+<dh-cert> ... </dh>
+  </sev>
+  ...
+</domain>
+
+
+
+A least cbitpos and reduced-phys-bits must be
+nested within the launch-security element.
+
+
+  cbitpos
+  The cbitpos element provides the C-bit (aka encryption 
bit)
+  location in guest page table entry. The value of cbitpos is
+  hypervisor dependent and can be obtained through the sev 
element
+  from domaincapabilities.
+  
+  reduced-phys-bits
+  The reduced-phys-bits element provides the physical
+  address bit reducation. Similar to cbitpos the value of 

+  reduced-phys-bit is hypervisor dependent and can be obtained
+  through the sev element from domaincapabilities.
+  
+  policy
+  The optional policy element provides the guest policy
+  which must be maintained by the SEV firmware. This policy is enforced by
+  the firmware and restricts what configuration and operational commands
+  can be performed on this guest by the hypervisor. The guest policy
+  provided during guest launch is bound to the guest and cannot be changed
+  throughout the lifetime of the guest. The policy is also transmitted
+  during snapshot and migration flows and enforced on the destination 
platform.
+
+  The guest policy is a 4-byte structure with the fields shown in Table:
+
+  
+
+   Bit(s) 
+   Description 
+
+
+   0 
+   Debugging of the guest is disallowed when set 
+
+
+   1 
+   Sharing keys with other guests is disallowed when set 
+
+
+   2 
+   SEV-ES is required when set
+
+
+   3 
+   Sending the guest to another platform is disallowed when 
set
+
+
+   4 
+   The guest must not be transmitted to another platform that is
+   not in the domain when set. 
+
+
+   5 
+   The guest must not be transmitted to another platform that is
+   not SEV capable when set. 
+
+
+   15:6 
+   reserved 
+
+
+   16:32 
+   The guest must not be transmitted to another platform with a
+   lower firmware version. 
+
+  
+  Default value is 0

  1   2   >