Get a SEV attestation report using the query-sev-attestation-report QMP
API.
Signed-off-by: Tyler Fanelli <tfanelli(a)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