sev/i386: add command to create launch memory encryption context

The KVM_SEV_LAUNCH_START command creates a new VM encryption key (VEK).
The encryption key created with the command will be used for encrypting
the bootstrap images (such as guest bios).

Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Richard Henderson <rth@twiddle.net>
Cc: Eduardo Habkost <ehabkost@redhat.com>
Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Brijesh Singh 2018-03-08 06:48:48 -06:00 committed by Paolo Bonzini
parent 2b308e4431
commit 620fd55c24
2 changed files with 88 additions and 0 deletions

View File

@ -105,6 +105,17 @@ fw_error_to_str(int code)
return sev_fw_errlist[code];
}
static void
sev_set_guest_state(SevState new_state)
{
assert(new_state < SEV_STATE__MAX);
assert(sev_state);
trace_kvm_sev_change_state(SevState_str(sev_state->state),
SevState_str(new_state));
sev_state->state = new_state;
}
static void
sev_ram_block_added(RAMBlockNotifier *n, void *host, size_t size)
{
@ -406,6 +417,75 @@ sev_get_info(void)
return info;
}
static int
sev_read_file_base64(const char *filename, guchar **data, gsize *len)
{
gsize sz;
gchar *base64;
GError *error = NULL;
if (!g_file_get_contents(filename, &base64, &sz, &error)) {
error_report("failed to read '%s' (%s)", filename, error->message);
return -1;
}
*data = g_base64_decode(base64, len);
return 0;
}
static int
sev_launch_start(SEVState *s)
{
gsize sz;
int ret = 1;
int fw_error;
QSevGuestInfo *sev = s->sev_info;
struct kvm_sev_launch_start *start;
guchar *session = NULL, *dh_cert = NULL;
start = g_new0(struct kvm_sev_launch_start, 1);
start->handle = object_property_get_int(OBJECT(sev), "handle",
&error_abort);
start->policy = object_property_get_int(OBJECT(sev), "policy",
&error_abort);
if (sev->session_file) {
if (sev_read_file_base64(sev->session_file, &session, &sz) < 0) {
return 1;
}
start->session_uaddr = (unsigned long)session;
start->session_len = sz;
}
if (sev->dh_cert_file) {
if (sev_read_file_base64(sev->dh_cert_file, &dh_cert, &sz) < 0) {
return 1;
}
start->dh_uaddr = (unsigned long)dh_cert;
start->dh_len = sz;
}
trace_kvm_sev_launch_start(start->policy, session, dh_cert);
ret = sev_ioctl(s->sev_fd, KVM_SEV_LAUNCH_START, start, &fw_error);
if (ret < 0) {
error_report("%s: LAUNCH_START ret=%d fw_error=%d '%s'",
__func__, ret, fw_error, fw_error_to_str(fw_error));
return 1;
}
object_property_set_int(OBJECT(sev), start->handle, "handle",
&error_abort);
sev_set_guest_state(SEV_STATE_LAUNCH_UPDATE);
s->handle = start->handle;
s->policy = start->policy;
g_free(start);
g_free(session);
g_free(dh_cert);
return 0;
}
void *
sev_guest_init(const char *id)
{
@ -476,6 +556,12 @@ sev_guest_init(const char *id)
goto err;
}
ret = sev_launch_start(s);
if (ret) {
error_report("%s: failed to create encryption context", __func__);
goto err;
}
ram_block_notifier_add(&sev_ram_notifier);
return s;

View File

@ -10,3 +10,5 @@ kvm_x86_update_msi_routes(int num) "Updated %d MSI routes"
kvm_sev_init(void) ""
kvm_memcrypt_register_region(void *addr, size_t len) "addr %p len 0x%zu"
kvm_memcrypt_unregister_region(void *addr, size_t len) "addr %p len 0x%zu"
kvm_sev_change_state(const char *old, const char *new) "%s -> %s"
kvm_sev_launch_start(int policy, void *session, void *pdh) "policy 0x%x session %p pdh %p"