From mboxrd@z Thu Jan 1 00:00:00 1970 From: Brijesh Singh Subject: [PATCH v5 14/23] sev: add command to create launch memory encryption context Date: Wed, 6 Dec 2017 14:03:37 -0600 Message-ID: <20171206200346.116537-15-brijesh.singh@amd.com> References: <20171206200346.116537-1-brijesh.singh@amd.com> Mime-Version: 1.0 Content-Type: text/plain Cc: Alistair Francis , Christian Borntraeger , Cornelia Huck , "Daniel P . Berrange" , "Dr. David Alan Gilbert" , "Edgar E . Iglesias " , Eduardo Habkost , Eric Blake , kvm@vger.kernel.org, Marcel Apfelbaum , Markus Armbruster , "Michael S. Tsirkin" , Paolo Bonzini , Peter Crosthwaite , Peter Maydell , Richard Henderson , Richard Henderson , Stefan Hajnoczi , Thomas Lendacky < To: qemu-devel@nongnu.org Return-path: Received: from mail-sn1nam01on0058.outbound.protection.outlook.com ([104.47.32.58]:2394 "EHLO NAM01-SN1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752552AbdLFUEy (ORCPT ); Wed, 6 Dec 2017 15:04:54 -0500 In-Reply-To: <20171206200346.116537-1-brijesh.singh@amd.com> Sender: kvm-owner@vger.kernel.org List-ID: 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 Cc: kvm@vger.kernel.org Signed-off-by: Brijesh Singh --- accel/kvm/sev.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sysemu/sev.h | 11 +++++++ 2 files changed, 97 insertions(+) diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c index 7b5318993969..74eb67526bd0 100644 --- a/accel/kvm/sev.c +++ b/accel/kvm/sev.c @@ -22,6 +22,15 @@ #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */ #define DEFAULT_SEV_DEVICE "/dev/sev" +#define DEBUG_SEV +#ifdef DEBUG_SEV +#define DPRINTF(fmt, ...) \ + do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ + do { } while (0) +#endif + static int sev_fd; #define SEV_FW_MAX_ERROR 0x17 @@ -288,6 +297,77 @@ lookup_sev_guest_info(const char *id) 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_malloc0(sizeof(*start)); + if (!start) { + return 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; + } + + ret = sev_ioctl(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; + } + + DPRINTF("SEV: LAUNCH_START\n"); + + object_property_set_int(OBJECT(sev), start->handle, "handle", + &error_abort); + s->cur_state = SEV_STATE_LUPDATE; + + g_free(start); + g_free(session); + g_free(dh_cert); + + return 0; +} + void * sev_guest_init(const char *id) { @@ -323,6 +403,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; diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h index f85517c0b5b5..45b464cc96f5 100644 --- a/include/sysemu/sev.h +++ b/include/sysemu/sev.h @@ -51,8 +51,19 @@ struct QSevGuestInfoClass { ObjectClass parent_class; }; +enum { + SEV_STATE_INVALID = 0, + SEV_STATE_LUPDATE, + SEV_STATE_SECRET, + SEV_STATE_RUNNING, + SEV_STATE_SENDING, + SEV_STATE_RECEIVING, + SEV_STATE_MAX +}; + struct SEVState { QSevGuestInfo *sev_info; + int cur_state; }; typedef struct SEVState SEVState; -- 2.9.5 From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:49921) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1eMfw0-0006HF-81 for qemu-devel@nongnu.org; Wed, 06 Dec 2017 15:04:49 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1eMfvx-0002gu-1f for qemu-devel@nongnu.org; Wed, 06 Dec 2017 15:04:48 -0500 Received: from mail-sn1nam01on0081.outbound.protection.outlook.com ([104.47.32.81]:20510 helo=NAM01-SN1-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1eMfvw-0002gI-Qr for qemu-devel@nongnu.org; Wed, 06 Dec 2017 15:04:44 -0500 From: Brijesh Singh Date: Wed, 6 Dec 2017 14:03:37 -0600 Message-Id: <20171206200346.116537-15-brijesh.singh@amd.com> In-Reply-To: <20171206200346.116537-1-brijesh.singh@amd.com> References: <20171206200346.116537-1-brijesh.singh@amd.com> MIME-Version: 1.0 Content-Type: text/plain Subject: [Qemu-devel] [PATCH v5 14/23] sev: add command to create launch memory encryption context List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Alistair Francis , Christian Borntraeger , Cornelia Huck , "Daniel P . Berrange" , "Dr. David Alan Gilbert" , "Edgar E . Iglesias " , Eduardo Habkost , Eric Blake , kvm@vger.kernel.org, Marcel Apfelbaum , Markus Armbruster , "Michael S. Tsirkin" , Paolo Bonzini , Peter Crosthwaite , Peter Maydell , Richard Henderson , Richard Henderson , Stefan Hajnoczi , Thomas Lendacky , Borislav Petkov , Brijesh Singh 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 Cc: kvm@vger.kernel.org Signed-off-by: Brijesh Singh --- accel/kvm/sev.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++ include/sysemu/sev.h | 11 +++++++ 2 files changed, 97 insertions(+) diff --git a/accel/kvm/sev.c b/accel/kvm/sev.c index 7b5318993969..74eb67526bd0 100644 --- a/accel/kvm/sev.c +++ b/accel/kvm/sev.c @@ -22,6 +22,15 @@ #define DEFAULT_GUEST_POLICY 0x1 /* disable debug */ #define DEFAULT_SEV_DEVICE "/dev/sev" +#define DEBUG_SEV +#ifdef DEBUG_SEV +#define DPRINTF(fmt, ...) \ + do { fprintf(stderr, fmt, ## __VA_ARGS__); } while (0) +#else +#define DPRINTF(fmt, ...) \ + do { } while (0) +#endif + static int sev_fd; #define SEV_FW_MAX_ERROR 0x17 @@ -288,6 +297,77 @@ lookup_sev_guest_info(const char *id) 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_malloc0(sizeof(*start)); + if (!start) { + return 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; + } + + ret = sev_ioctl(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; + } + + DPRINTF("SEV: LAUNCH_START\n"); + + object_property_set_int(OBJECT(sev), start->handle, "handle", + &error_abort); + s->cur_state = SEV_STATE_LUPDATE; + + g_free(start); + g_free(session); + g_free(dh_cert); + + return 0; +} + void * sev_guest_init(const char *id) { @@ -323,6 +403,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; diff --git a/include/sysemu/sev.h b/include/sysemu/sev.h index f85517c0b5b5..45b464cc96f5 100644 --- a/include/sysemu/sev.h +++ b/include/sysemu/sev.h @@ -51,8 +51,19 @@ struct QSevGuestInfoClass { ObjectClass parent_class; }; +enum { + SEV_STATE_INVALID = 0, + SEV_STATE_LUPDATE, + SEV_STATE_SECRET, + SEV_STATE_RUNNING, + SEV_STATE_SENDING, + SEV_STATE_RECEIVING, + SEV_STATE_MAX +}; + struct SEVState { QSevGuestInfo *sev_info; + int cur_state; }; typedef struct SEVState SEVState; -- 2.9.5