aboutsummaryrefslogtreecommitdiff
path: root/target/i386/sev.c
diff options
context:
space:
mode:
authorTobin Feldman-Fitzthum <tobin@ibm.com>2020-10-27 13:03:03 -0400
committerEduardo Habkost <ehabkost@redhat.com>2020-12-10 17:33:17 -0500
commitc7f7e6970d3b74c1454cafea4918187e06c473eb (patch)
tree305f51bc016b3aec4654352ada698a427677f846 /target/i386/sev.c
parent1bf8b88f144bee747e386c88d45d772e066bbb36 (diff)
sev: add sev-inject-launch-secret
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 facilitates the injection of the launch secret, it cannot access the secret. Signed-off-by: Tobin Feldman-Fitzthum <tobin@linux.ibm.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com> Reviewed-by: Daniel P. Berrangé <berrange@redhat.com> Reviewed-by: Brijesh Singh <brijesh.singh@amd.com> Message-Id: <20201027170303.47550-1-tobin@linux.ibm.com> Signed-off-by: Eduardo Habkost <ehabkost@redhat.com>
Diffstat (limited to 'target/i386/sev.c')
-rw-r--r--target/i386/sev.c65
1 files changed, 65 insertions, 0 deletions
diff --git a/target/i386/sev.c b/target/i386/sev.c
index 93c4d60b82..1546606811 100644
--- a/target/i386/sev.c
+++ b/target/i386/sev.c
@@ -29,6 +29,8 @@
#include "trace.h"
#include "migration/blocker.h"
#include "qom/object.h"
+#include "exec/address-spaces.h"
+#include "monitor/monitor.h"
#define TYPE_SEV_GUEST "sev-guest"
OBJECT_DECLARE_SIMPLE_TYPE(SevGuestState, SEV_GUEST)
@@ -785,6 +787,69 @@ 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, Error **errp)
+{
+ struct kvm_sev_launch_secret input;
+ g_autofree guchar *data = NULL, *hdr = NULL;
+ int error, ret = 1;
+ void *hva;
+ gsize hdr_sz = 0, data_sz = 0;
+ MemoryRegion *mr = NULL;
+
+ if (!sev_guest) {
+ error_setg(errp, "SEV: SEV not enabled.");
+ return 1;
+ }
+
+ /* secret can be injected only in this state */
+ if (!sev_check_state(sev_guest, SEV_STATE_LAUNCH_SECRET)) {
+ error_setg(errp, "SEV: Not in correct state. (LSECRET) %x",
+ sev_guest->state);
+ return 1;
+ }
+
+ hdr = g_base64_decode(packet_hdr, &hdr_sz);
+ if (!hdr || !hdr_sz) {
+ error_setg(errp, "SEV: Failed to decode sequence header");
+ return 1;
+ }
+
+ data = g_base64_decode(secret, &data_sz);
+ if (!data || !data_sz) {
+ error_setg(errp, "SEV: Failed to decode data");
+ return 1;
+ }
+
+ hva = gpa2hva(&mr, gpa, data_sz, errp);
+ if (!hva) {
+ error_prepend(errp, "SEV: Failed to calculate guest address: ");
+ return 1;
+ }
+
+ input.hdr_uaddr = (uint64_t)(unsigned long)hdr;
+ input.hdr_len = hdr_sz;
+
+ input.trans_uaddr = (uint64_t)(unsigned long)data;
+ input.trans_len = data_sz;
+
+ input.guest_uaddr = (uint64_t)(unsigned long)hva;
+ input.guest_len = data_sz;
+
+ trace_kvm_sev_launch_secret(gpa, input.guest_uaddr,
+ input.trans_uaddr, input.trans_len);
+
+ ret = sev_ioctl(sev_guest->sev_fd, KVM_SEV_LAUNCH_SECRET,
+ &input, &error);
+ if (ret) {
+ error_setg(errp, "SEV: failed to inject secret ret=%d fw_error=%d '%s'",
+ ret, error, fw_error_to_str(error));
+ return ret;
+ }
+
+ return 0;
+}
+
static void
sev_register_types(void)
{