[PATCH 4/5] qemu: Implement the virDomainGetSevAttestationReport API

Tyler Fanelli tfanelli at redhat.com
Wed Mar 23 19:36:28 UTC 2022


Get a SEV attestation report using the query-sev-attestation-report QMP
API.

Signed-off-by: Tyler Fanelli <tfanelli at redhat.com>
---
 include/libvirt/libvirt-domain.h |  8 +++
 src/driver-hypervisor.h          |  4 +-
 src/qemu/qemu_driver.c           | 86 ++++++++++++++++++++++++++++++++
 src/qemu/qemu_monitor.c          | 11 ++++
 src/qemu/qemu_monitor.h          |  5 ++
 src/qemu/qemu_monitor_json.c     | 40 +++++++++++++++
 src/qemu/qemu_monitor_json.h     |  5 ++
 7 files changed, 157 insertions(+), 2 deletions(-)

diff --git a/include/libvirt/libvirt-domain.h b/include/libvirt/libvirt-domain.h
index af8991dbd3..3f56da99cc 100644
--- a/include/libvirt/libvirt-domain.h
+++ b/include/libvirt/libvirt-domain.h
@@ -5175,6 +5175,14 @@ int virDomainSetLifecycleAction(virDomainPtr domain,
  */
 # define VIR_DOMAIN_SEV_ATTESTATION_REPORT_MNONCE "mnonce"
 
+/**
+ * VIR_DOMAIN_SEV_ATTESTATION_REPORT_DATA:
+ *
+ * A macro used to represent the returned SEV attestation report (encoded in
+ * base64).
+ */
+# define VIR_DOMAIN_SEV_ATTESTATION_REPORT_DATA "sev-attestation-report"
+
 int virDomainGetLaunchSecurityInfo(virDomainPtr domain,
                                    virTypedParameterPtr *params,
                                    int *nparams,
diff --git a/src/driver-hypervisor.h b/src/driver-hypervisor.h
index 568d8c9a26..8912e5d7ef 100644
--- a/src/driver-hypervisor.h
+++ b/src/driver-hypervisor.h
@@ -1350,8 +1350,8 @@ typedef int
 
 typedef int
 (*virDrvDomainGetSevAttestationReport)(virDomainPtr domain,
-                                       virTypedParameterPtr params,
-                                       int nparams,
+                                       virTypedParameterPtr *params_ptr,
+                                       int *nparams,
                                        unsigned int flags);
 
 typedef virDomainCheckpointPtr
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index b7e83c769a..a96a0b9f84 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -20123,6 +20123,91 @@ qemuDomainSetLaunchSecurityState(virDomainPtr domain,
     return ret;
 }
 
+static int
+qemuDomainGetSevAttestationReport(virDomainPtr domain,
+                                  virTypedParameterPtr *params,
+                                  int *nparams,
+                                  unsigned int flags)
+{
+    virQEMUDriver *driver;
+    virDomainObj *vm;
+    int ret = -1;
+    size_t i;
+    g_autofree char *mnonce = NULL;
+    g_autofree char *report = NULL;
+    int maxpar = 2;
+    g_autoptr(virQEMUCaps) qemucaps = NULL;
+
+    driver = domain->conn->privateData;
+
+    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
+    if (virTypedParamsValidate(*params, *nparams,
+                               VIR_DOMAIN_SEV_ATTESTATION_REPORT_MNONCE,
+                               VIR_TYPED_PARAM_STRING,
+                               NULL) < 0)
+        return -1;
+
+    if (!(vm = qemuDomainObjFromDomain(domain)))
+        goto cleanup;
+
+    if (virDomainGetSevAttestationReportEnsureACL(domain->conn, vm->def) < 0)
+        goto cleanup;
+
+    /* SEV must be enabled to get an attestation report */
+    if (!vm->def->sec ||
+        vm->def->sec->sectype != VIR_DOMAIN_LAUNCH_SECURITY_SEV) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+            _("attestation report is only supported in SEV-enabled domains"));
+        goto cleanup;
+    }
+
+    if (!(qemucaps = virQEMUCapsCacheLookupDefault(driver->qemuCapsCache,
+                                                   NULL, NULL, NULL, NULL,
+                                                   NULL, NULL, NULL)))
+        goto cleanup;
+
+
+    if (!virQEMUCapsGet(qemucaps, QEMU_CAPS_SEV_GET_ATTESTATION_REPORT)) {
+        virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+                _("QEMU does not support getting a SEV attestation report"));
+        goto cleanup;
+    }
+
+    for (i = 0; i < *nparams; ++i) {
+        virTypedParameterPtr param = params[i];
+
+        if (STREQ(param->field, VIR_DOMAIN_SEV_ATTESTATION_REPORT_MNONCE))
+            mnonce = g_strdup(param->value.s);
+    }
+
+    if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
+        goto cleanup;
+
+    if (virDomainObjCheckActive(vm) < 0)
+        goto endjob;
+
+    qemuDomainObjEnterMonitor(driver, vm);
+    ret = qemuMonitorGetSevAttestationReport(QEMU_DOMAIN_PRIVATE(vm)->mon,
+                                             mnonce,
+                                             &report);
+    qemuDomainObjExitMonitor(vm);
+    if (ret < 0)
+        goto endjob;
+
+    if (virTypedParamsAddString(params, nparams, &maxpar,
+                                VIR_DOMAIN_SEV_ATTESTATION_REPORT_DATA,
+                                report) < 0)
+        goto endjob;
+
+    ret = 0;
+
+endjob:
+    qemuDomainObjEndJob(vm);
+
+cleanup:
+    virDomainObjEndAPI(&vm);
+    return ret;
+}
 
 static const unsigned int qemuDomainGetGuestInfoSupportedTypes =
     VIR_DOMAIN_GUEST_INFO_USERS |
@@ -21028,6 +21113,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
     .domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */
     .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */
     .domainSetLaunchSecurityState = qemuDomainSetLaunchSecurityState, /* 8.0.0 */
+    .domainGetSevAttestationReport = qemuDomainGetSevAttestationReport, /* 8.1.0 */
 };
 
 
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 316cff5b9b..284e4a0b01 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4330,6 +4330,17 @@ qemuMonitorSetLaunchSecurityState(qemuMonitor *mon,
 }
 
 
+int
+qemuMonitorGetSevAttestationReport(qemuMonitor *mon,
+                                   const char *mnonce,
+                                   char **report)
+{
+    QEMU_CHECK_MONITOR(mon);
+
+    return qemuMonitorJSONGetSevAttestationReport(mon, mnonce, report);
+}
+
+
 int
 qemuMonitorGetPRManagerInfo(qemuMonitor *mon,
                             GHashTable **retinfo)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 5c2a749282..2e6fb8bfe0 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1447,6 +1447,11 @@ qemuMonitorSetLaunchSecurityState(qemuMonitor *mon,
                                   unsigned long long setaddr,
                                   bool hasSetaddr);
 
+int
+qemuMonitorGetSevAttestationReport(qemuMonitor *mon,
+                                   const char *mnonce,
+                                   char **report);
+
 typedef struct _qemuMonitorPRManagerInfo qemuMonitorPRManagerInfo;
 struct _qemuMonitorPRManagerInfo {
     bool connected;
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index d5622bd6d9..45adf7a740 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -8322,6 +8322,46 @@ qemuMonitorJSONSetLaunchSecurityState(qemuMonitor *mon,
     return 0;
 }
 
+/**
+ * Get a SEV attestation report
+ *
+ * Example JSON:
+ *
+ * {"execute" : "query-sev-attestation-report",
+ *  "data" : { "mnonce": "str" } }
+ * {"return" : "data" : "mnonceNlSPUDlXPJG5966/8%YZ" } }
+ */
+int
+qemuMonitorJSONGetSevAttestationReport(qemuMonitor *mon,
+                                       const char *mnonce,
+                                       char **report)
+{
+    const char *tmp;
+    g_autoptr(virJSONValue) cmd = NULL;
+    g_autoptr(virJSONValue) reply = NULL;
+    virJSONValue *data;
+
+    cmd = qemuMonitorJSONMakeCommand("query-sev-attestation-report",
+                                     "s:mnonce", mnonce,
+                                     NULL);
+    if (cmd == NULL)
+        return -1;
+
+    if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0)
+        return -1;
+
+    if (qemuMonitorJSONCheckReply(cmd, reply, VIR_JSON_TYPE_OBJECT) < 0)
+        return -1;
+
+    data = virJSONValueObjectGetObject(reply, "return");
+
+    if (!(tmp = virJSONValueObjectGetString(data, "data")))
+        return -1;
+
+    *report = g_strdup(tmp);
+
+    return 0;
+}
 
 /*
  * Example return data
diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h
index 982fbad44e..9a8e4ffd28 100644
--- a/src/qemu/qemu_monitor_json.h
+++ b/src/qemu/qemu_monitor_json.h
@@ -484,6 +484,11 @@ int qemuMonitorJSONSetLaunchSecurityState(qemuMonitor *mon,
                                           unsigned long long setaddr,
                                           bool hasSetaddr);
 
+int
+qemuMonitorJSONGetSevAttestationReport(qemuMonitor *mon,
+                                       const char *mnonce,
+                                       char **report);
+
 int
 qemuMonitorJSONGetMachines(qemuMonitor *mon,
                            qemuMonitorMachineInfo ***machines)
-- 
2.34.1



More information about the libvir-list mailing list