Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-10-13 Thread tobin

On 2020-10-12 12:49, Daniel P. Berrangé wrote:

On Mon, Oct 12, 2020 at 05:21:15PM +0100, Dr. David Alan Gilbert wrote:

* Tobin Feldman-Fitzthum (to...@linux.vnet.ibm.com) wrote:
> AMD SEV allows a guest owner to inject a secret blob
> into the memory of a virtual machine. The secret is
> encrypted with the SEV Transport Encryption Key and
> integrity is guaranteed with the Transport Integrity
> Key. Although QEMU faciliates the injection of the


Trivial typo  s/faciliates/facilitates/


> launch secret, it cannot access the secret.
>
> Signed-off-by: Tobin Feldman-Fitzthum 
> ---
>  include/monitor/monitor.h |  3 ++
>  include/sysemu/sev.h  |  2 ++
>  monitor/misc.c|  8 ++---
>  qapi/misc-target.json | 18 +++
>  target/i386/monitor.c |  9 ++
>  target/i386/sev-stub.c|  5 +++
>  target/i386/sev.c | 66 +++
>  target/i386/trace-events  |  1 +
>  8 files changed, 108 insertions(+), 4 deletions(-)




> diff --git a/qapi/misc-target.json b/qapi/misc-target.json
> index dee3b45930..d145f916b3 100644
> --- a/qapi/misc-target.json
> +++ b/qapi/misc-target.json
> @@ -200,6 +200,24 @@
>  { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
>'if': 'defined(TARGET_I386)' }
>
> +##
> +# @sev-inject-launch-secret:
> +#
> +# This command injects a secret blob into memory of SEV guest.
> +#
> +# @packet-header: the launch secret packet header encoded in base64
> +#
> +# @secret: the launch secret data to be injected encoded in base64


Just to double check, this "secret" is /not/ in clear text, so there's
no way either QEMU nor the QMP client can access sensitive info, right 
?



You are correct. QEMU would only be able to read the secret in the case
of serious user error.

Thank you for your feedback. I have rebased made the changes. Will send
new version in the morning.

-Tobin


If 'secret' was clear text, then we would need to pass the data across
QMP in a different way.


> +#
> +# @gpa: the guest physical address where secret will be injected.
> +#
> +# Since: 5.1


s/5.1/5.2/


> +#
> +##
> +{ 'command': 'sev-inject-launch-secret',
> +  'data': { 'packet-header': 'str', 'secret': 'str', 'gpa': 'uint64' },
> +  'if': 'defined(TARGET_I386)' }
> +
>  ##
>  # @dump-skeys:
>  #
> diff --git a/target/i386/monitor.c b/target/i386/monitor.c
> index 27ebfa3ad2..42bcfe6dc0 100644
> --- a/target/i386/monitor.c
> +++ b/target/i386/monitor.c
> @@ -736,3 +736,12 @@ SevCapability *qmp_query_sev_capabilities(Error **errp)
>
>  return data;
>  }
> +
> +void qmp_sev_inject_launch_secret(const char *packet_hdr,
> +  const char *secret, uint64_t gpa,
> +  Error **errp)
> +{
> +if (sev_inject_launch_secret(packet_hdr, secret, gpa) != 0) {
> +error_setg(errp, "SEV inject secret failed");


This generic error message is useless - sev_inject_launch_secret() 
needs

to take the 'errp' parameter and report what actually failed.


> +}
> +}
> diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
> index e5ee13309c..fed4588185 100644
> --- a/target/i386/sev-stub.c
> +++ b/target/i386/sev-stub.c
> @@ -48,3 +48,8 @@ SevCapability *sev_get_capabilities(void)
>  {
>  return NULL;
>  }
> +int sev_inject_launch_secret(const char *hdr, const char *secret,
> + uint64_t gpa)
> +{
> +return 1;
> +}
> diff --git a/target/i386/sev.c b/target/i386/sev.c
> index d273174ad3..cbeb8f2e02 100644
> --- a/target/i386/sev.c
> +++ b/target/i386/sev.c
> @@ -28,6 +28,8 @@
>  #include "sysemu/runstate.h"
>  #include "trace.h"
>  #include "migration/blocker.h"
> +#include "exec/address-spaces.h"
> +#include "monitor/monitor.h"
>
>  #define TYPE_SEV_GUEST "sev-guest"
>  #define SEV_GUEST(obj)  \
> @@ -769,6 +771,70 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t 
len)
>  return 0;
>  }
>
> +int sev_inject_launch_secret(const char *packet_hdr,
> + const char *secret, uint64_t gpa)
> +{
> +struct kvm_sev_launch_secret input;
> +guchar *data = NULL, *hdr = NULL;


If you declare with  'g_autofree' you don't need the manual 'g_free'
calls later. This in turn means you can get rid of the "goto err"
jumps and instead directly return.


> +int error, ret = 1;
> +void *hva;
> +gsize hdr_sz = 0, data_sz = 0;
> +Error *local_err = NULL;


Declare with

   g_autoptr(Error) local_err = NULL

to fix the leak David mentions



> +MemoryRegion *mr = NULL;
> +
> +/* secret can be inject only in this state */
> +if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
> +error_report("SEV: Not in correct state. (LSECRET) %x",
> + sev_guest->state);
> +return 1;
> +}
> +
> +hdr = g_base64_decode(packet_hdr, _sz);
> +if (!hdr || !hdr_sz) {
> +error_report("SEV: Failed to decode 

Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-10-12 Thread Daniel P . Berrangé
On Mon, Oct 12, 2020 at 05:21:15PM +0100, Dr. David Alan Gilbert wrote:
> * Tobin Feldman-Fitzthum (to...@linux.vnet.ibm.com) wrote:
> > AMD SEV allows a guest owner to inject a secret blob
> > into the memory of a virtual machine. The secret is
> > encrypted with the SEV Transport Encryption Key and
> > integrity is guaranteed with the Transport Integrity
> > Key. Although QEMU faciliates the injection of the

Trivial typo  s/faciliates/facilitates/

> > launch secret, it cannot access the secret.
> > 
> > Signed-off-by: Tobin Feldman-Fitzthum 
> > ---
> >  include/monitor/monitor.h |  3 ++
> >  include/sysemu/sev.h  |  2 ++
> >  monitor/misc.c|  8 ++---
> >  qapi/misc-target.json | 18 +++
> >  target/i386/monitor.c |  9 ++
> >  target/i386/sev-stub.c|  5 +++
> >  target/i386/sev.c | 66 +++
> >  target/i386/trace-events  |  1 +
> >  8 files changed, 108 insertions(+), 4 deletions(-)


> > diff --git a/qapi/misc-target.json b/qapi/misc-target.json
> > index dee3b45930..d145f916b3 100644
> > --- a/qapi/misc-target.json
> > +++ b/qapi/misc-target.json
> > @@ -200,6 +200,24 @@
> >  { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
> >'if': 'defined(TARGET_I386)' }
> >  
> > +##
> > +# @sev-inject-launch-secret:
> > +#
> > +# This command injects a secret blob into memory of SEV guest.
> > +#
> > +# @packet-header: the launch secret packet header encoded in base64
> > +#
> > +# @secret: the launch secret data to be injected encoded in base64

Just to double check, this "secret" is /not/ in clear text, so there's
no way either QEMU nor the QMP client can access sensitive info, right ?

If 'secret' was clear text, then we would need to pass the data across
QMP in a different way.

> > +#
> > +# @gpa: the guest physical address where secret will be injected.
> > +#
> > +# Since: 5.1

s/5.1/5.2/

> > +#
> > +##
> > +{ 'command': 'sev-inject-launch-secret',
> > +  'data': { 'packet-header': 'str', 'secret': 'str', 'gpa': 'uint64' },
> > +  'if': 'defined(TARGET_I386)' }
> > +
> >  ##
> >  # @dump-skeys:
> >  #
> > diff --git a/target/i386/monitor.c b/target/i386/monitor.c
> > index 27ebfa3ad2..42bcfe6dc0 100644
> > --- a/target/i386/monitor.c
> > +++ b/target/i386/monitor.c
> > @@ -736,3 +736,12 @@ SevCapability *qmp_query_sev_capabilities(Error **errp)
> >  
> >  return data;
> >  }
> > +
> > +void qmp_sev_inject_launch_secret(const char *packet_hdr,
> > +  const char *secret, uint64_t gpa,
> > +  Error **errp)
> > +{
> > +if (sev_inject_launch_secret(packet_hdr, secret, gpa) != 0) {
> > +error_setg(errp, "SEV inject secret failed");

This generic error message is useless - sev_inject_launch_secret() needs
to take the 'errp' parameter and report what actually failed.

> > +}
> > +}
> > diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
> > index e5ee13309c..fed4588185 100644
> > --- a/target/i386/sev-stub.c
> > +++ b/target/i386/sev-stub.c
> > @@ -48,3 +48,8 @@ SevCapability *sev_get_capabilities(void)
> >  {
> >  return NULL;
> >  }
> > +int sev_inject_launch_secret(const char *hdr, const char *secret,
> > + uint64_t gpa)
> > +{
> > +return 1;
> > +}
> > diff --git a/target/i386/sev.c b/target/i386/sev.c
> > index d273174ad3..cbeb8f2e02 100644
> > --- a/target/i386/sev.c
> > +++ b/target/i386/sev.c
> > @@ -28,6 +28,8 @@
> >  #include "sysemu/runstate.h"
> >  #include "trace.h"
> >  #include "migration/blocker.h"
> > +#include "exec/address-spaces.h"
> > +#include "monitor/monitor.h"
> >  
> >  #define TYPE_SEV_GUEST "sev-guest"
> >  #define SEV_GUEST(obj)  \
> > @@ -769,6 +771,70 @@ sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t 
> > len)
> >  return 0;
> >  }
> >  
> > +int sev_inject_launch_secret(const char *packet_hdr,
> > + const char *secret, uint64_t gpa)
> > +{
> > +struct kvm_sev_launch_secret input;
> > +guchar *data = NULL, *hdr = NULL;

If you declare with  'g_autofree' you don't need the manual 'g_free'
calls later. This in turn means you can get rid of the "goto err"
jumps and instead directly return.

> > +int error, ret = 1;
> > +void *hva;
> > +gsize hdr_sz = 0, data_sz = 0;
> > +Error *local_err = NULL;

Declare with

   g_autoptr(Error) local_err = NULL

to fix the leak David mentions


> > +MemoryRegion *mr = NULL;
> > +
> > +/* secret can be inject only in this state */
> > +if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
> > +error_report("SEV: Not in correct state. (LSECRET) %x",
> > + sev_guest->state);
> > +return 1;
> > +}
> > +
> > +hdr = g_base64_decode(packet_hdr, _sz);
> > +if (!hdr || !hdr_sz) {
> > +error_report("SEV: Failed to decode sequence header");
> > +

Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-10-12 Thread Dr. David Alan Gilbert
* James Bottomley (j...@linux.ibm.com) wrote:
> On Mon, 2020-10-12 at 16:57 +0100, Dr. David Alan Gilbert wrote:
> > * Tobin Feldman-Fitzthum (to...@linux.ibm.com) wrote:
> > > On 2020-09-21 15:16, Dr. David Alan Gilbert wrote:
> > > > * Tobin Feldman-Fitzthum (to...@linux.vnet.ibm.com) wrote:
> > > > > AMD SEV allows a guest owner to inject a secret blob
> > > > > into the memory of a virtual machine. The secret is
> > > > > encrypted with the SEV Transport Encryption Key and
> > > > > integrity is guaranteed with the Transport Integrity
> > > > > Key. Although QEMU faciliates the injection of the
> > > > > launch secret, it cannot access the secret.
> > > > > 
> > > > > Signed-off-by: Tobin Feldman-Fitzthum  > > > > >
> > > > 
> > > > Hi Tobin,
> > > >   Did the ovmf stuff for agreeing the GUID for automating this
> > > > ever happen?
> > > > 
> > > OVMF patches have not been upstreamed yet. I think we are planning
> > > to do that relatively soon.
> > 
> > So as we're getting to the end of another qemu dev cycle; do we aim
> > to get this one in by itself, or to wait for the GUID?
> 
> Since they're independent of each other, I'd say get this one in now if
> it's acceptable.  The GUID will come as a discoverable way of setting
> the GPA, but this patch at least gives people a way to play with SEV
> secret injection.  I'm also reworking the OVMF GUID patch to tack on to
> the reset vector GUID that just went upstream, so it will be a few more
> weeks yet before we have it all integrated with the -ES patch set.

OK, so I've just replied with a minor error leak that needs fixing, but
other than that it looks OK to me.
I've not quite figured out who would pull it, Paolo?

Dave

> James
> 
> 
-- 
Dr. David Alan Gilbert / dgilb...@redhat.com / Manchester, UK




Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-10-12 Thread Dr. David Alan Gilbert
* Tobin Feldman-Fitzthum (to...@linux.vnet.ibm.com) wrote:
> AMD SEV allows a guest owner to inject a secret blob
> into the memory of a virtual machine. The secret is
> encrypted with the SEV Transport Encryption Key and
> integrity is guaranteed with the Transport Integrity
> Key. Although QEMU faciliates the injection of the
> launch secret, it cannot access the secret.
> 
> Signed-off-by: Tobin Feldman-Fitzthum 
> ---
>  include/monitor/monitor.h |  3 ++
>  include/sysemu/sev.h  |  2 ++
>  monitor/misc.c|  8 ++---
>  qapi/misc-target.json | 18 +++
>  target/i386/monitor.c |  9 ++
>  target/i386/sev-stub.c|  5 +++
>  target/i386/sev.c | 66 +++
>  target/i386/trace-events  |  1 +
>  8 files changed, 108 insertions(+), 4 deletions(-)
> 
> diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
> index 1018d754a6..bf049c5b00 100644
> --- a/include/monitor/monitor.h
> +++ b/include/monitor/monitor.h
> @@ -4,6 +4,7 @@
>  #include "block/block.h"
>  #include "qapi/qapi-types-misc.h"
>  #include "qemu/readline.h"
> +#include "include/exec/hwaddr.h"
>  
>  extern __thread Monitor *cur_mon;
>  typedef struct MonitorHMP MonitorHMP;
> @@ -36,6 +37,8 @@ void monitor_flush(Monitor *mon);
>  int monitor_set_cpu(int cpu_index);
>  int monitor_get_cpu_index(void);
>  
> +void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp);
> +
>  void monitor_read_command(MonitorHMP *mon, int show_prompt);
>  int monitor_read_password(MonitorHMP *mon, ReadLineFunc *readline_func,
>void *opaque);
> diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
> index 98c1ec8d38..b279b293e8 100644
> --- a/include/sysemu/sev.h
> +++ b/include/sysemu/sev.h
> @@ -18,4 +18,6 @@
>  
>  void *sev_guest_init(const char *id);
>  int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
> +int sev_inject_launch_secret(const char *hdr, const char *secret,
> + uint64_t gpa);
>  #endif
> diff --git a/monitor/misc.c b/monitor/misc.c
> index 89bb970b00..b9ec8ba410 100644
> --- a/monitor/misc.c
> +++ b/monitor/misc.c
> @@ -674,10 +674,10 @@ static void hmp_physical_memory_dump(Monitor *mon, 
> const QDict *qdict)
>  memory_dump(mon, count, format, size, addr, 1);
>  }
>  
> -static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
> +void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp)
>  {
>  MemoryRegionSection mrs = memory_region_find(get_system_memory(),
> - addr, 1);
> + addr, size);
>  
>  if (!mrs.mr) {
>  error_setg(errp, "No memory is mapped at address 0x%" HWADDR_PRIx, 
> addr);
> @@ -701,7 +701,7 @@ static void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
>  MemoryRegion *mr = NULL;
>  void *ptr;
>  
> -ptr = gpa2hva(, addr, _err);
> +ptr = gpa2hva(, addr, 1, _err);
>  if (local_err) {
>  error_report_err(local_err);
>  return;
> @@ -777,7 +777,7 @@ static void hmp_gpa2hpa(Monitor *mon, const QDict *qdict)
>  void *ptr;
>  uint64_t physaddr;
>  
> -ptr = gpa2hva(, addr, _err);
> +ptr = gpa2hva(, addr, 1, _err);
>  if (local_err) {
>  error_report_err(local_err);
>  return;
> diff --git a/qapi/misc-target.json b/qapi/misc-target.json
> index dee3b45930..d145f916b3 100644
> --- a/qapi/misc-target.json
> +++ b/qapi/misc-target.json
> @@ -200,6 +200,24 @@
>  { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
>'if': 'defined(TARGET_I386)' }
>  
> +##
> +# @sev-inject-launch-secret:
> +#
> +# This command injects a secret blob into memory of SEV guest.
> +#
> +# @packet-header: the launch secret packet header encoded in base64
> +#
> +# @secret: the launch secret data to be injected encoded in base64
> +#
> +# @gpa: the guest physical address where secret will be injected.
> +#
> +# Since: 5.1
> +#
> +##
> +{ 'command': 'sev-inject-launch-secret',
> +  'data': { 'packet-header': 'str', 'secret': 'str', 'gpa': 'uint64' },
> +  'if': 'defined(TARGET_I386)' }
> +
>  ##
>  # @dump-skeys:
>  #
> diff --git a/target/i386/monitor.c b/target/i386/monitor.c
> index 27ebfa3ad2..42bcfe6dc0 100644
> --- a/target/i386/monitor.c
> +++ b/target/i386/monitor.c
> @@ -736,3 +736,12 @@ SevCapability *qmp_query_sev_capabilities(Error **errp)
>  
>  return data;
>  }
> +
> +void qmp_sev_inject_launch_secret(const char *packet_hdr,
> +  const char *secret, uint64_t gpa,
> +  Error **errp)
> +{
> +if (sev_inject_launch_secret(packet_hdr, secret, gpa) != 0) {
> +error_setg(errp, "SEV inject secret failed");
> +}
> +}
> diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
> index e5ee13309c..fed4588185 100644
> --- a/target/i386/sev-stub.c
> +++ 

Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-10-12 Thread Dr. David Alan Gilbert
* Tobin Feldman-Fitzthum (to...@linux.ibm.com) wrote:
> On 2020-09-21 15:16, Dr. David Alan Gilbert wrote:
> > * Tobin Feldman-Fitzthum (to...@linux.vnet.ibm.com) wrote:
> > > AMD SEV allows a guest owner to inject a secret blob
> > > into the memory of a virtual machine. The secret is
> > > encrypted with the SEV Transport Encryption Key and
> > > integrity is guaranteed with the Transport Integrity
> > > Key. Although QEMU faciliates the injection of the
> > > launch secret, it cannot access the secret.
> > > 
> > > Signed-off-by: Tobin Feldman-Fitzthum 
> > 
> > Hi Tobin,
> >   Did the ovmf stuff for agreeing the GUID for automating this ever
> > happen?
> > 
> OVMF patches have not been upstreamed yet. I think we are planning
> to do that relatively soon.

So as we're getting to the end of another qemu dev cycle; do we aim
to get this one in by itself, or to wait for the GUID?

Dave

> -Tobin
> > Dave
> > 
> > > ---
> > >  include/monitor/monitor.h |  3 ++
> > >  include/sysemu/sev.h  |  2 ++
> > >  monitor/misc.c|  8 ++---
> > >  qapi/misc-target.json | 18 +++
> > >  target/i386/monitor.c |  9 ++
> > >  target/i386/sev-stub.c|  5 +++
> > >  target/i386/sev.c | 66
> > > +++
> > >  target/i386/trace-events  |  1 +
> > >  8 files changed, 108 insertions(+), 4 deletions(-)
> > > 
> > > diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
> > > index 1018d754a6..bf049c5b00 100644
> > > --- a/include/monitor/monitor.h
> > > +++ b/include/monitor/monitor.h
> > > @@ -4,6 +4,7 @@
> > >  #include "block/block.h"
> > >  #include "qapi/qapi-types-misc.h"
> > >  #include "qemu/readline.h"
> > > +#include "include/exec/hwaddr.h"
> > > 
> > >  extern __thread Monitor *cur_mon;
> > >  typedef struct MonitorHMP MonitorHMP;
> > > @@ -36,6 +37,8 @@ void monitor_flush(Monitor *mon);
> > >  int monitor_set_cpu(int cpu_index);
> > >  int monitor_get_cpu_index(void);
> > > 
> > > +void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size,
> > > Error **errp);
> > > +
> > >  void monitor_read_command(MonitorHMP *mon, int show_prompt);
> > >  int monitor_read_password(MonitorHMP *mon, ReadLineFunc
> > > *readline_func,
> > >void *opaque);
> > > diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
> > > index 98c1ec8d38..b279b293e8 100644
> > > --- a/include/sysemu/sev.h
> > > +++ b/include/sysemu/sev.h
> > > @@ -18,4 +18,6 @@
> > > 
> > >  void *sev_guest_init(const char *id);
> > >  int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
> > > +int sev_inject_launch_secret(const char *hdr, const char *secret,
> > > + uint64_t gpa);
> > >  #endif
> > > diff --git a/monitor/misc.c b/monitor/misc.c
> > > index 89bb970b00..b9ec8ba410 100644
> > > --- a/monitor/misc.c
> > > +++ b/monitor/misc.c
> > > @@ -674,10 +674,10 @@ static void hmp_physical_memory_dump(Monitor
> > > *mon, const QDict *qdict)
> > >  memory_dump(mon, count, format, size, addr, 1);
> > >  }
> > > 
> > > -static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
> > > +void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size,
> > > Error **errp)
> > >  {
> > >  MemoryRegionSection mrs = memory_region_find(get_system_memory(),
> > > - addr, 1);
> > > + addr, size);
> > > 
> > >  if (!mrs.mr) {
> > >  error_setg(errp, "No memory is mapped at address 0x%"
> > > HWADDR_PRIx, addr);
> > > @@ -701,7 +701,7 @@ static void hmp_gpa2hva(Monitor *mon, const
> > > QDict *qdict)
> > >  MemoryRegion *mr = NULL;
> > >  void *ptr;
> > > 
> > > -ptr = gpa2hva(, addr, _err);
> > > +ptr = gpa2hva(, addr, 1, _err);
> > >  if (local_err) {
> > >  error_report_err(local_err);
> > >  return;
> > > @@ -777,7 +777,7 @@ static void hmp_gpa2hpa(Monitor *mon, const
> > > QDict *qdict)
> > >  void *ptr;
> > >  uint64_t physaddr;
> > > 
> > > -ptr = gpa2hva(, addr, _err);
> > > +ptr = gpa2hva(, addr, 1, _err);
> > >  if (local_err) {
> > >  error_report_err(local_err);
> > >  return;
> > > diff --git a/qapi/misc-target.json b/qapi/misc-target.json
> > > index dee3b45930..d145f916b3 100644
> > > --- a/qapi/misc-target.json
> > > +++ b/qapi/misc-target.json
> > > @@ -200,6 +200,24 @@
> > >  { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
> > >'if': 'defined(TARGET_I386)' }
> > > 
> > > +##
> > > +# @sev-inject-launch-secret:
> > > +#
> > > +# This command injects a secret blob into memory of SEV guest.
> > > +#
> > > +# @packet-header: the launch secret packet header encoded in base64
> > > +#
> > > +# @secret: the launch secret data to be injected encoded in base64
> > > +#
> > > +# @gpa: the guest physical address where secret will be injected.
> > > +#
> > > +# Since: 5.1
> > > +#
> > > +##
> > > +{ 

Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-10-12 Thread James Bottomley
On Mon, 2020-10-12 at 16:57 +0100, Dr. David Alan Gilbert wrote:
> * Tobin Feldman-Fitzthum (to...@linux.ibm.com) wrote:
> > On 2020-09-21 15:16, Dr. David Alan Gilbert wrote:
> > > * Tobin Feldman-Fitzthum (to...@linux.vnet.ibm.com) wrote:
> > > > AMD SEV allows a guest owner to inject a secret blob
> > > > into the memory of a virtual machine. The secret is
> > > > encrypted with the SEV Transport Encryption Key and
> > > > integrity is guaranteed with the Transport Integrity
> > > > Key. Although QEMU faciliates the injection of the
> > > > launch secret, it cannot access the secret.
> > > > 
> > > > Signed-off-by: Tobin Feldman-Fitzthum  > > > >
> > > 
> > > Hi Tobin,
> > >   Did the ovmf stuff for agreeing the GUID for automating this
> > > ever happen?
> > > 
> > OVMF patches have not been upstreamed yet. I think we are planning
> > to do that relatively soon.
> 
> So as we're getting to the end of another qemu dev cycle; do we aim
> to get this one in by itself, or to wait for the GUID?

Since they're independent of each other, I'd say get this one in now if
it's acceptable.  The GUID will come as a discoverable way of setting
the GPA, but this patch at least gives people a way to play with SEV
secret injection.  I'm also reworking the OVMF GUID patch to tack on to
the reset vector GUID that just went upstream, so it will be a few more
weeks yet before we have it all integrated with the -ES patch set.

James





Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-09-21 Thread Tom Lendacky
On 9/21/20 3:33 PM, Tobin Feldman-Fitzthum wrote:
> On 2020-09-21 15:16, Dr. David Alan Gilbert wrote:
>> * Tobin Feldman-Fitzthum (to...@linux.vnet.ibm.com) wrote:
>>> AMD SEV allows a guest owner to inject a secret blob
>>> into the memory of a virtual machine. The secret is
>>> encrypted with the SEV Transport Encryption Key and
>>> integrity is guaranteed with the Transport Integrity
>>> Key. Although QEMU faciliates the injection of the
>>> launch secret, it cannot access the secret.
>>>
>>> Signed-off-by: Tobin Feldman-Fitzthum 
>>
>> Hi Tobin,
>>   Did the ovmf stuff for agreeing the GUID for automating this ever
>> happen?
>>
> OVMF patches have not been upstreamed yet. I think we are planning
> to do that relatively soon.

The SEV-ES code was recently accepted and uses a GUID for locating SEV
related information. You can probably build upon that GUID or stack
another GUID above that. The GUID block has a size indicator that can help
determine what information is available or for tracking stacked GUIDs.

https://github.com/tianocore/edk2/commit/30937f2f98c42496f2f143fe8374ae7f7e684847

Thanks,
Tom

> 
> -Tobin
>> Dave
>>
>>> ---
>>>  include/monitor/monitor.h |  3 ++
>>>  include/sysemu/sev.h  |  2 ++
>>>  monitor/misc.c    |  8 ++---
>>>  qapi/misc-target.json | 18 +++
>>>  target/i386/monitor.c |  9 ++
>>>  target/i386/sev-stub.c    |  5 +++
>>>  target/i386/sev.c | 66 +++
>>>  target/i386/trace-events  |  1 +
>>>  8 files changed, 108 insertions(+), 4 deletions(-)
>>>
>>> diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
>>> index 1018d754a6..bf049c5b00 100644
>>> --- a/include/monitor/monitor.h
>>> +++ b/include/monitor/monitor.h
>>> @@ -4,6 +4,7 @@
>>>  #include "block/block.h"
>>>  #include "qapi/qapi-types-misc.h"
>>>  #include "qemu/readline.h"
>>> +#include "include/exec/hwaddr.h"
>>>
>>>  extern __thread Monitor *cur_mon;
>>>  typedef struct MonitorHMP MonitorHMP;
>>> @@ -36,6 +37,8 @@ void monitor_flush(Monitor *mon);
>>>  int monitor_set_cpu(int cpu_index);
>>>  int monitor_get_cpu_index(void);
>>>
>>> +void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error
>>> **errp);
>>> +
>>>  void monitor_read_command(MonitorHMP *mon, int show_prompt);
>>>  int monitor_read_password(MonitorHMP *mon, ReadLineFunc *readline_func,
>>>    void *opaque);
>>> diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
>>> index 98c1ec8d38..b279b293e8 100644
>>> --- a/include/sysemu/sev.h
>>> +++ b/include/sysemu/sev.h
>>> @@ -18,4 +18,6 @@
>>>
>>>  void *sev_guest_init(const char *id);
>>>  int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
>>> +int sev_inject_launch_secret(const char *hdr, const char *secret,
>>> + uint64_t gpa);
>>>  #endif
>>> diff --git a/monitor/misc.c b/monitor/misc.c
>>> index 89bb970b00..b9ec8ba410 100644
>>> --- a/monitor/misc.c
>>> +++ b/monitor/misc.c
>>> @@ -674,10 +674,10 @@ static void hmp_physical_memory_dump(Monitor
>>> *mon, const QDict *qdict)
>>>  memory_dump(mon, count, format, size, addr, 1);
>>>  }
>>>
>>> -static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
>>> +void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error
>>> **errp)
>>>  {
>>>  MemoryRegionSection mrs = memory_region_find(get_system_memory(),
>>> - addr, 1);
>>> + addr, size);
>>>
>>>  if (!mrs.mr) {
>>>  error_setg(errp, "No memory is mapped at address 0x%"
>>> HWADDR_PRIx, addr);
>>> @@ -701,7 +701,7 @@ static void hmp_gpa2hva(Monitor *mon, const QDict
>>> *qdict)
>>>  MemoryRegion *mr = NULL;
>>>  void *ptr;
>>>
>>> -    ptr = gpa2hva(, addr, _err);
>>> +    ptr = gpa2hva(, addr, 1, _err);
>>>  if (local_err) {
>>>  error_report_err(local_err);
>>>  return;
>>> @@ -777,7 +777,7 @@ static void hmp_gpa2hpa(Monitor *mon, const QDict
>>> *qdict)
>>>  void *ptr;
>>>  uint64_t physaddr;
>>>
>>> -    ptr = gpa2hva(, addr, _err);
>>> +    ptr = gpa2hva(, addr, 1, _err);
>>>  if (local_err) {
>>>  error_report_err(local_err);
>>>  return;
>>> diff --git a/qapi/misc-target.json b/qapi/misc-target.json
>>> index dee3b45930..d145f916b3 100644
>>> --- a/qapi/misc-target.json
>>> +++ b/qapi/misc-target.json
>>> @@ -200,6 +200,24 @@
>>>  { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
>>>    'if': 'defined(TARGET_I386)' }
>>>
>>> +##
>>> +# @sev-inject-launch-secret:
>>> +#
>>> +# This command injects a secret blob into memory of SEV guest.
>>> +#
>>> +# @packet-header: the launch secret packet header encoded in base64
>>> +#
>>> +# @secret: the launch secret data to be injected encoded in base64
>>> +#
>>> +# @gpa: the guest physical address where secret will be injected.
>>> +#
>>> +# Since: 5.1
>>> +#
>>> +##
>>> +{ 'command': 

Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-09-21 Thread Tobin Feldman-Fitzthum

On 2020-09-21 15:16, Dr. David Alan Gilbert wrote:

* Tobin Feldman-Fitzthum (to...@linux.vnet.ibm.com) wrote:

AMD SEV allows a guest owner to inject a secret blob
into the memory of a virtual machine. The secret is
encrypted with the SEV Transport Encryption Key and
integrity is guaranteed with the Transport Integrity
Key. Although QEMU faciliates the injection of the
launch secret, it cannot access the secret.

Signed-off-by: Tobin Feldman-Fitzthum 


Hi Tobin,
  Did the ovmf stuff for agreeing the GUID for automating this ever
happen?


OVMF patches have not been upstreamed yet. I think we are planning
to do that relatively soon.

-Tobin

Dave


---
 include/monitor/monitor.h |  3 ++
 include/sysemu/sev.h  |  2 ++
 monitor/misc.c|  8 ++---
 qapi/misc-target.json | 18 +++
 target/i386/monitor.c |  9 ++
 target/i386/sev-stub.c|  5 +++
 target/i386/sev.c | 66 
+++

 target/i386/trace-events  |  1 +
 8 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 1018d754a6..bf049c5b00 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -4,6 +4,7 @@
 #include "block/block.h"
 #include "qapi/qapi-types-misc.h"
 #include "qemu/readline.h"
+#include "include/exec/hwaddr.h"

 extern __thread Monitor *cur_mon;
 typedef struct MonitorHMP MonitorHMP;
@@ -36,6 +37,8 @@ void monitor_flush(Monitor *mon);
 int monitor_set_cpu(int cpu_index);
 int monitor_get_cpu_index(void);

+void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error 
**errp);

+
 void monitor_read_command(MonitorHMP *mon, int show_prompt);
 int monitor_read_password(MonitorHMP *mon, ReadLineFunc 
*readline_func,

   void *opaque);
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 98c1ec8d38..b279b293e8 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -18,4 +18,6 @@

 void *sev_guest_init(const char *id);
 int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
+int sev_inject_launch_secret(const char *hdr, const char *secret,
+ uint64_t gpa);
 #endif
diff --git a/monitor/misc.c b/monitor/misc.c
index 89bb970b00..b9ec8ba410 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -674,10 +674,10 @@ static void hmp_physical_memory_dump(Monitor 
*mon, const QDict *qdict)

 memory_dump(mon, count, format, size, addr, 1);
 }

-static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
+void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error 
**errp)

 {
 MemoryRegionSection mrs = memory_region_find(get_system_memory(),
- addr, 1);
+ addr, size);

 if (!mrs.mr) {
 error_setg(errp, "No memory is mapped at address 0x%" 
HWADDR_PRIx, addr);
@@ -701,7 +701,7 @@ static void hmp_gpa2hva(Monitor *mon, const QDict 
*qdict)

 MemoryRegion *mr = NULL;
 void *ptr;

-ptr = gpa2hva(, addr, _err);
+ptr = gpa2hva(, addr, 1, _err);
 if (local_err) {
 error_report_err(local_err);
 return;
@@ -777,7 +777,7 @@ static void hmp_gpa2hpa(Monitor *mon, const QDict 
*qdict)

 void *ptr;
 uint64_t physaddr;

-ptr = gpa2hva(, addr, _err);
+ptr = gpa2hva(, addr, 1, _err);
 if (local_err) {
 error_report_err(local_err);
 return;
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index dee3b45930..d145f916b3 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -200,6 +200,24 @@
 { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
   'if': 'defined(TARGET_I386)' }

+##
+# @sev-inject-launch-secret:
+#
+# This command injects a secret blob into memory of SEV guest.
+#
+# @packet-header: the launch secret packet header encoded in base64
+#
+# @secret: the launch secret data to be injected encoded in base64
+#
+# @gpa: the guest physical address where secret will be injected.
+#
+# Since: 5.1
+#
+##
+{ 'command': 'sev-inject-launch-secret',
+  'data': { 'packet-header': 'str', 'secret': 'str', 'gpa': 'uint64' 
},

+  'if': 'defined(TARGET_I386)' }
+
 ##
 # @dump-skeys:
 #
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 27ebfa3ad2..42bcfe6dc0 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -736,3 +736,12 @@ SevCapability *qmp_query_sev_capabilities(Error 
**errp)


 return data;
 }
+
+void qmp_sev_inject_launch_secret(const char *packet_hdr,
+  const char *secret, uint64_t gpa,
+  Error **errp)
+{
+if (sev_inject_launch_secret(packet_hdr, secret, gpa) != 0) {
+error_setg(errp, "SEV inject secret failed");
+}
+}
diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
index e5ee13309c..fed4588185 100644
--- a/target/i386/sev-stub.c
+++ b/target/i386/sev-stub.c
@@ -48,3 

Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-09-21 Thread Dr. David Alan Gilbert
* Tobin Feldman-Fitzthum (to...@linux.vnet.ibm.com) wrote:
> AMD SEV allows a guest owner to inject a secret blob
> into the memory of a virtual machine. The secret is
> encrypted with the SEV Transport Encryption Key and
> integrity is guaranteed with the Transport Integrity
> Key. Although QEMU faciliates the injection of the
> launch secret, it cannot access the secret.
> 
> Signed-off-by: Tobin Feldman-Fitzthum 

Hi Tobin,
  Did the ovmf stuff for agreeing the GUID for automating this ever
happen?

Dave

> ---
>  include/monitor/monitor.h |  3 ++
>  include/sysemu/sev.h  |  2 ++
>  monitor/misc.c|  8 ++---
>  qapi/misc-target.json | 18 +++
>  target/i386/monitor.c |  9 ++
>  target/i386/sev-stub.c|  5 +++
>  target/i386/sev.c | 66 +++
>  target/i386/trace-events  |  1 +
>  8 files changed, 108 insertions(+), 4 deletions(-)
> 
> diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
> index 1018d754a6..bf049c5b00 100644
> --- a/include/monitor/monitor.h
> +++ b/include/monitor/monitor.h
> @@ -4,6 +4,7 @@
>  #include "block/block.h"
>  #include "qapi/qapi-types-misc.h"
>  #include "qemu/readline.h"
> +#include "include/exec/hwaddr.h"
>  
>  extern __thread Monitor *cur_mon;
>  typedef struct MonitorHMP MonitorHMP;
> @@ -36,6 +37,8 @@ void monitor_flush(Monitor *mon);
>  int monitor_set_cpu(int cpu_index);
>  int monitor_get_cpu_index(void);
>  
> +void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp);
> +
>  void monitor_read_command(MonitorHMP *mon, int show_prompt);
>  int monitor_read_password(MonitorHMP *mon, ReadLineFunc *readline_func,
>void *opaque);
> diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
> index 98c1ec8d38..b279b293e8 100644
> --- a/include/sysemu/sev.h
> +++ b/include/sysemu/sev.h
> @@ -18,4 +18,6 @@
>  
>  void *sev_guest_init(const char *id);
>  int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
> +int sev_inject_launch_secret(const char *hdr, const char *secret,
> + uint64_t gpa);
>  #endif
> diff --git a/monitor/misc.c b/monitor/misc.c
> index 89bb970b00..b9ec8ba410 100644
> --- a/monitor/misc.c
> +++ b/monitor/misc.c
> @@ -674,10 +674,10 @@ static void hmp_physical_memory_dump(Monitor *mon, 
> const QDict *qdict)
>  memory_dump(mon, count, format, size, addr, 1);
>  }
>  
> -static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
> +void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error **errp)
>  {
>  MemoryRegionSection mrs = memory_region_find(get_system_memory(),
> - addr, 1);
> + addr, size);
>  
>  if (!mrs.mr) {
>  error_setg(errp, "No memory is mapped at address 0x%" HWADDR_PRIx, 
> addr);
> @@ -701,7 +701,7 @@ static void hmp_gpa2hva(Monitor *mon, const QDict *qdict)
>  MemoryRegion *mr = NULL;
>  void *ptr;
>  
> -ptr = gpa2hva(, addr, _err);
> +ptr = gpa2hva(, addr, 1, _err);
>  if (local_err) {
>  error_report_err(local_err);
>  return;
> @@ -777,7 +777,7 @@ static void hmp_gpa2hpa(Monitor *mon, const QDict *qdict)
>  void *ptr;
>  uint64_t physaddr;
>  
> -ptr = gpa2hva(, addr, _err);
> +ptr = gpa2hva(, addr, 1, _err);
>  if (local_err) {
>  error_report_err(local_err);
>  return;
> diff --git a/qapi/misc-target.json b/qapi/misc-target.json
> index dee3b45930..d145f916b3 100644
> --- a/qapi/misc-target.json
> +++ b/qapi/misc-target.json
> @@ -200,6 +200,24 @@
>  { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
>'if': 'defined(TARGET_I386)' }
>  
> +##
> +# @sev-inject-launch-secret:
> +#
> +# This command injects a secret blob into memory of SEV guest.
> +#
> +# @packet-header: the launch secret packet header encoded in base64
> +#
> +# @secret: the launch secret data to be injected encoded in base64
> +#
> +# @gpa: the guest physical address where secret will be injected.
> +#
> +# Since: 5.1
> +#
> +##
> +{ 'command': 'sev-inject-launch-secret',
> +  'data': { 'packet-header': 'str', 'secret': 'str', 'gpa': 'uint64' },
> +  'if': 'defined(TARGET_I386)' }
> +
>  ##
>  # @dump-skeys:
>  #
> diff --git a/target/i386/monitor.c b/target/i386/monitor.c
> index 27ebfa3ad2..42bcfe6dc0 100644
> --- a/target/i386/monitor.c
> +++ b/target/i386/monitor.c
> @@ -736,3 +736,12 @@ SevCapability *qmp_query_sev_capabilities(Error **errp)
>  
>  return data;
>  }
> +
> +void qmp_sev_inject_launch_secret(const char *packet_hdr,
> +  const char *secret, uint64_t gpa,
> +  Error **errp)
> +{
> +if (sev_inject_launch_secret(packet_hdr, secret, gpa) != 0) {
> +error_setg(errp, "SEV inject secret failed");
> +}
> +}
> diff --git a/target/i386/sev-stub.c b/target/i386/sev-stub.c
> 

Re: [PATCH v3] SEV: QMP support for Inject-Launch-Secret

2020-07-06 Thread tobin

On 2020-07-06 17:54, Tobin Feldman-Fitzthum wrote:

Not sure if v3 is necessary, but here it is.
Fixed the 32-bit issues and removed the checks
on header and secret length. I agree with Brijesh
that those are best left to the PSP, which
returns somewhat helpful errors if either are incorrect.

Having a check in QEMU might be a handy hint for
developers who are trying to formulate a valid
secret, but it is easy enough to find the requirements
in the spec. This way we do not need to worry about
the secret format changing in future versions.



AMD SEV allows a guest owner to inject a secret blob
into the memory of a virtual machine. The secret is
encrypted with the SEV Transport Encryption Key and
integrity is guaranteed with the Transport Integrity
Key. Although QEMU faciliates the injection of the
launch secret, it cannot access the secret.

Signed-off-by: Tobin Feldman-Fitzthum 
---
 include/monitor/monitor.h |  3 ++
 include/sysemu/sev.h  |  2 ++
 monitor/misc.c|  8 ++---
 qapi/misc-target.json | 18 +++
 target/i386/monitor.c |  9 ++
 target/i386/sev-stub.c|  5 +++
 target/i386/sev.c | 66 +++
 target/i386/trace-events  |  1 +
 8 files changed, 108 insertions(+), 4 deletions(-)

diff --git a/include/monitor/monitor.h b/include/monitor/monitor.h
index 1018d754a6..bf049c5b00 100644
--- a/include/monitor/monitor.h
+++ b/include/monitor/monitor.h
@@ -4,6 +4,7 @@
 #include "block/block.h"
 #include "qapi/qapi-types-misc.h"
 #include "qemu/readline.h"
+#include "include/exec/hwaddr.h"

 extern __thread Monitor *cur_mon;
 typedef struct MonitorHMP MonitorHMP;
@@ -36,6 +37,8 @@ void monitor_flush(Monitor *mon);
 int monitor_set_cpu(int cpu_index);
 int monitor_get_cpu_index(void);

+void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error 
**errp);

+
 void monitor_read_command(MonitorHMP *mon, int show_prompt);
 int monitor_read_password(MonitorHMP *mon, ReadLineFunc 
*readline_func,

   void *opaque);
diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h
index 98c1ec8d38..b279b293e8 100644
--- a/include/sysemu/sev.h
+++ b/include/sysemu/sev.h
@@ -18,4 +18,6 @@

 void *sev_guest_init(const char *id);
 int sev_encrypt_data(void *handle, uint8_t *ptr, uint64_t len);
+int sev_inject_launch_secret(const char *hdr, const char *secret,
+ uint64_t gpa);
 #endif
diff --git a/monitor/misc.c b/monitor/misc.c
index 89bb970b00..b9ec8ba410 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -674,10 +674,10 @@ static void hmp_physical_memory_dump(Monitor
*mon, const QDict *qdict)
 memory_dump(mon, count, format, size, addr, 1);
 }

-static void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, Error **errp)
+void *gpa2hva(MemoryRegion **p_mr, hwaddr addr, uint64_t size, Error 
**errp)

 {
 MemoryRegionSection mrs = memory_region_find(get_system_memory(),
- addr, 1);
+ addr, size);

 if (!mrs.mr) {
 error_setg(errp, "No memory is mapped at address 0x%"
HWADDR_PRIx, addr);
@@ -701,7 +701,7 @@ static void hmp_gpa2hva(Monitor *mon, const QDict 
*qdict)

 MemoryRegion *mr = NULL;
 void *ptr;

-ptr = gpa2hva(, addr, _err);
+ptr = gpa2hva(, addr, 1, _err);
 if (local_err) {
 error_report_err(local_err);
 return;
@@ -777,7 +777,7 @@ static void hmp_gpa2hpa(Monitor *mon, const QDict 
*qdict)

 void *ptr;
 uint64_t physaddr;

-ptr = gpa2hva(, addr, _err);
+ptr = gpa2hva(, addr, 1, _err);
 if (local_err) {
 error_report_err(local_err);
 return;
diff --git a/qapi/misc-target.json b/qapi/misc-target.json
index dee3b45930..d145f916b3 100644
--- a/qapi/misc-target.json
+++ b/qapi/misc-target.json
@@ -200,6 +200,24 @@
 { 'command': 'query-sev-capabilities', 'returns': 'SevCapability',
   'if': 'defined(TARGET_I386)' }

+##
+# @sev-inject-launch-secret:
+#
+# This command injects a secret blob into memory of SEV guest.
+#
+# @packet-header: the launch secret packet header encoded in base64
+#
+# @secret: the launch secret data to be injected encoded in base64
+#
+# @gpa: the guest physical address where secret will be injected.
+#
+# Since: 5.1
+#
+##
+{ 'command': 'sev-inject-launch-secret',
+  'data': { 'packet-header': 'str', 'secret': 'str', 'gpa': 'uint64' 
},

+  'if': 'defined(TARGET_I386)' }
+
 ##
 # @dump-skeys:
 #
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 27ebfa3ad2..42bcfe6dc0 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -736,3 +736,12 @@ SevCapability *qmp_query_sev_capabilities(Error 
**errp)


 return data;
 }
+
+void qmp_sev_inject_launch_secret(const char *packet_hdr,
+  const char *secret, uint64_t gpa,
+  Error **errp)
+{
+if (sev_inject_launch_secret(packet_hdr, secret, gpa) != 0) {