+
+ virCheckFlags(0, -1);
+ if (virTypedParamsValidate(params, nparams,
+ VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_HEADER,
+ VIR_TYPED_PARAM_STRING,
+ VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET,
+ VIR_TYPED_PARAM_STRING,
+ VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_SET_ADDRESS,
+ VIR_TYPED_PARAM_LLONG,
+ NULL) < 0)
+ return -1;
+
+ if (!(vm = qemuDomainObjFromDomain(domain)))
+ goto cleanup;
+
+ if (virDomainSetLaunchSecurityStateEnsureACL(domain->conn, vm->def) < 0)
+ goto cleanup;
+
+ /* Currently only SEV is supported */
+ if (!vm->def->sec ||
+ vm->def->sec->sectype != VIR_DOMAIN_LAUNCH_SECURITY_SEV) {
+ virReportError(VIR_ERR_OPERATION_UNSUPPORTED, "%s",
+ _("setting a launch secret is only supported in SEV-enabled domains"));
+ goto cleanup;
+ }
+
+ for (i = 0; i < nparams; i++) {
+ virTypedParameterPtr param = ¶ms[i];
+
+ if (STREQ(param->field, VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_HEADER))
+ secrethdr = g_strdup(param->value.s);
+ else if (STREQ(param->field, VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET))
+ secret = g_strdup(param->value.s);
+ else if (STREQ(param->field, VIR_DOMAIN_LAUNCH_SECURITY_SEV_SECRET_SET_ADDRESS))
+ setaddr = param->value.l;
+ }
+
+ if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0)
+ goto cleanup;
+
+ if (virDomainObjCheckActive(vm) < 0)
+ goto endjob;
+
+ qemuDomainObjEnterMonitor(driver, vm);
+
+ if (qemuMonitorSetLaunchSecurityState(QEMU_DOMAIN_PRIVATE(vm)->mon,
+ secrethdr, secret, setaddr) < 0)
+ goto endjob;
+
+ if (qemuDomainObjExitMonitor(driver, vm) < 0)
+ goto endjob;
+
+ ret = 0;
+
+ endjob:
+ qemuDomainObjEndJob(driver, vm);
+
+ cleanup:
+ virDomainObjEndAPI(&vm);
+ return ret;
+}
+
+
static const unsigned int qemuDomainGetGuestInfoSupportedTypes =
VIR_DOMAIN_GUEST_INFO_USERS |
VIR_DOMAIN_GUEST_INFO_OS |
@@ -20930,6 +21007,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
.domainAuthorizedSSHKeysSet = qemuDomainAuthorizedSSHKeysSet, /* 6.10.0 */
.domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */
.domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */
+ .domainSetLaunchSecurityState = qemuDomainSetLaunchSecurityState, /* 8.0.0 */
};
diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 26b59801b8..7f31a53231 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -4372,6 +4372,18 @@ qemuMonitorGetSEVMeasurement(qemuMonitor *mon)
}
+int
+qemuMonitorSetLaunchSecurityState(qemuMonitor *mon,
+ const char *secrethdr,
+ const char *secret,
+ long long injectaddr)
+{
+ QEMU_CHECK_MONITOR(mon);
+
+ return qemuMonitorJSONSetLaunchSecurityState(mon, secrethdr, secret, injectaddr);
+}
+
+
int
qemuMonitorGetPRManagerInfo(qemuMonitor *mon,
GHashTable **retinfo)
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index 99ecebc648..c485e403fd 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -1444,6 +1444,12 @@ int qemuMonitorBlockdevMediumInsert(qemuMonitor *mon,
char *
qemuMonitorGetSEVMeasurement(qemuMonitor *mon);
+int
+qemuMonitorSetLaunchSecurityState(qemuMonitor *mon,
+ const char *secrethdr,
+ const char *secret,
+ long long injectaddr);
+
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 56f0b22b2a..35aea34b5f 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -8174,6 +8174,40 @@ qemuMonitorJSONGetSEVMeasurement(qemuMonitor *mon)
}
+/**
+ * The function is used to inject a launch secret in an SEV guest.
+ *
+ * Example JSON:
+ *
+ * { "execute" : "sev-inject-launch-secret",
+ * "data": { "packet-header": "str", "secret": "str", "gpa": "uint64" } }
+ */
+int
+qemuMonitorJSONSetLaunchSecurityState(qemuMonitor *mon,
+ const char *secrethdr,
+ const char *secret,
+ long long injectaddr)
+{
+ g_autoptr(virJSONValue) cmd = NULL;
+ g_autoptr(virJSONValue) reply = NULL;
+
+ if (!(cmd = qemuMonitorJSONMakeCommand("sev-inject-launch-secret",
+ "s:packet-header", secrethdr,
+ "s:secret", secret,
+ "U:gpa", injectaddr,
+ NULL)))