Inject a launch secret in domain memory using the sev-inject-launch-secret QMP API. Only supported for SEV-enabed domains. Signed-off-by: Jim Fehlig <jfehlig@xxxxxxxx> --- src/qemu/qemu_driver.c | 53 ++++++++++++++++++++++++++++++++++++ src/qemu/qemu_monitor.c | 12 ++++++++ src/qemu/qemu_monitor.h | 6 ++++ src/qemu/qemu_monitor_json.c | 34 +++++++++++++++++++++++ src/qemu/qemu_monitor_json.h | 5 ++++ 5 files changed, 110 insertions(+) diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c index d954635dde..58e3f08afe 100644 --- a/src/qemu/qemu_driver.c +++ b/src/qemu/qemu_driver.c @@ -20104,6 +20104,58 @@ qemuDomainGetLaunchSecurityInfo(virDomainPtr domain, return ret; } + +static int +qemuDomainInjectLaunchSecret(virDomainPtr domain, + const char *secrethdr, + const char *secret, + unsigned long long injectaddr, + unsigned int flags) +{ + virQEMUDriver *driver = domain->conn->privateData; + virDomainObj *vm; + int ret = -1; + + virCheckFlags(0, -1); + + if (!(vm = qemuDomainObjFromDomain(domain))) + goto cleanup; + + if (virDomainInjectLaunchSecretEnsureACL(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", + _("injecting a launch secret is only supported in SEV-enabled domains")); + goto cleanup; + } + + if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_MODIFY) < 0) + goto cleanup; + + if (qemuDomainObjEnterMonitorAsync(driver, vm, QEMU_ASYNC_JOB_NONE) < 0) + goto endjob; + + if (qemuMonitorInjectLaunchSecret(QEMU_DOMAIN_PRIVATE(vm)->mon, + secrethdr, secret, injectaddr) < 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 | @@ -20981,6 +21033,7 @@ static virHypervisorDriver qemuHypervisorDriver = { .domainAuthorizedSSHKeysSet = qemuDomainAuthorizedSSHKeysSet, /* 6.10.0 */ .domainGetMessages = qemuDomainGetMessages, /* 7.1.0 */ .domainStartDirtyRateCalc = qemuDomainStartDirtyRateCalc, /* 7.2.0 */ + .domainInjectLaunchSecret = qemuDomainInjectLaunchSecret, /* 7.10.0 */ }; diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c index 810dac209d..c64469a03b 100644 --- a/src/qemu/qemu_monitor.c +++ b/src/qemu/qemu_monitor.c @@ -4383,6 +4383,18 @@ qemuMonitorGetSEVMeasurement(qemuMonitor *mon) } +int +qemuMonitorInjectLaunchSecret(qemuMonitor *mon, + const char *secrethdr, + const char *secret, + unsigned long long injectaddr) +{ + QEMU_CHECK_MONITOR(mon); + + return qemuMonitorJSONInjectLaunchSecret(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 0dd7b1c4e2..2dec2b57bb 100644 --- a/src/qemu/qemu_monitor.h +++ b/src/qemu/qemu_monitor.h @@ -1445,6 +1445,12 @@ int qemuMonitorBlockdevMediumInsert(qemuMonitor *mon, char * qemuMonitorGetSEVMeasurement(qemuMonitor *mon); +int +qemuMonitorInjectLaunchSecret(qemuMonitor *mon, + const char *secrethdr, + const char *secret, + unsigned 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 4669b9135d..69aef078ec 100644 --- a/src/qemu/qemu_monitor_json.c +++ b/src/qemu/qemu_monitor_json.c @@ -8124,6 +8124,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 +qemuMonitorJSONInjectLaunchSecret(qemuMonitor *mon, + const char *secrethdr, + const char *secret, + unsigned 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))) + return -1; + + if (qemuMonitorJSONCommand(mon, cmd, &reply) < 0) + return -1; + + if (qemuMonitorJSONCheckError(cmd, reply) < 0) + return -1; + + return 0; +} + + /* * Example return data * diff --git a/src/qemu/qemu_monitor_json.h b/src/qemu/qemu_monitor_json.h index f7fb13f56c..95758cdc6e 100644 --- a/src/qemu/qemu_monitor_json.h +++ b/src/qemu/qemu_monitor_json.h @@ -368,6 +368,11 @@ int qemuMonitorJSONSystemWakeup(qemuMonitor *mon); char *qemuMonitorJSONGetSEVMeasurement(qemuMonitor *mon); +int qemuMonitorJSONInjectLaunchSecret(qemuMonitor *mon, + const char *secrethdr, + const char *secret, + unsigned long long injectaddr); + int qemuMonitorJSONGetVersion(qemuMonitor *mon, int *major, int *minor, -- 2.33.0