[libvirt] [PATCH 7/7] qemu: add support to launch MKTME guest

Larkins Carvalho larkins.l.carvalho at intel.com
Fri May 17 23:55:52 UTC 2019


QEMU provides 'mktme-guest' object which is used to launch encrypted
VMs on Intel platform using MKTME feature. The various inputs required to
launch MKTME guest is provided through the <launchSecurity> tag.

 MKTME guest launch command:

 # Qemu ...\
 -machine pc,memory-encryption=m0 -object mktme-guest,id=m0,handle=${serial}

 Using system call to generate mktme handle.

Required input to generate MKTME key which returns key handle:
 CPU Mode: type=cpu algorithm=ats-xts-128
 User Mode: type=user algorithm=ats-xts-128 key=1234567887654321 tweak=1234567887654321
---
 src/libvirt_private.syms |   3 +
 src/qemu/qemu_command.c  |  40 ++++++++++++
 src/util/Makefile.inc.am |   2 +
 src/util/virmktme.c      | 127 +++++++++++++++++++++++++++++++++++++++
 src/util/virmktme.h      |  34 +++++++++++
 5 files changed, 206 insertions(+)
 create mode 100644 src/util/virmktme.c
 create mode 100644 src/util/virmktme.h

diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 1b83e44b15..90f98097ef 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -2353,6 +2353,9 @@ virMediatedDeviceSetUsedBy;
 virMediatedDeviceTypeFree;
 virMediatedDeviceTypeReadAttrs;
 
+# util/virmktme.h
+virGetMktmeKeyHandle;
+virIsMktmeEnabled;
 
 # util/virmodule.h
 virModuleLoad;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index aae2f43044..2b35a1116e 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -59,6 +59,7 @@
 #include "virgic.h"
 #include "virmdev.h"
 #include "virdomainsnapshotobjlist.h"
+#include "virmktme.h"
 #if defined(__linux__)
 # include <linux/capability.h>
 #endif
@@ -7788,6 +7789,9 @@ qemuBuildMachineCommandLine(virCommandPtr cmd,
     if (def->sev)
         virBufferAddLit(&buf, ",memory-encryption=sev0");
 
+    if (def->mktme)
+        virBufferAddLit(&buf, ",memory-encryption=m0");
+
     virCommandAddArgBuffer(cmd, &buf);
 
     ret = 0;
@@ -10291,6 +10295,39 @@ qemuBuildSEVCommandLine(virDomainObjPtr vm, virCommandPtr cmd,
     return ret;
 }
 
+
+static int
+qemuBuildMKTMECommandLine(virCommandPtr cmd,
+                          virDomainMKTMEDefPtr mktme)
+{
+    virBuffer buf = VIR_BUFFER_INITIALIZER;
+    int ret = -1;
+
+    if (!mktme)
+        return 0;
+
+    if ((mktme->key_handle = virGetMktmeKeyHandle(mktme->id, mktme->key_type,
+        mktme->key, mktme->encryption_algorithm)) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR,
+            _("Failed to get MKTME key handle id %s"), mktme->id);
+        return -1;
+
+    }
+
+    VIR_DEBUG("id=%s key_type=%s key_handle=0x%x",
+              mktme->id, mktme->key_type, mktme->key_handle);
+
+    virBufferAsprintf(&buf, "mktme-guest,id=m0,handle=%d", mktme->key_handle);
+
+    virCommandAddArg(cmd, "-object");
+    virCommandAddArgBuffer(cmd, &buf);
+    ret = 0;
+
+    virBufferFreeAndReset(&buf);
+    return ret;
+}
+
+
 static int
 qemuBuildVMCoreInfoCommandLine(virCommandPtr cmd,
                                const virDomainDef *def,
@@ -10911,6 +10948,9 @@ qemuBuildCommandLine(virQEMUDriverPtr driver,
     if (qemuBuildSEVCommandLine(vm, cmd, def->sev) < 0)
         goto error;
 
+    if (qemuBuildMKTMECommandLine(cmd, def->mktme) < 0)
+        goto error;
+
     if (snapshot)
         virCommandAddArgList(cmd, "-loadvm", snapshot->def->name, NULL);
 
diff --git a/src/util/Makefile.inc.am b/src/util/Makefile.inc.am
index c757f5a6ae..2dc920f47c 100644
--- a/src/util/Makefile.inc.am
+++ b/src/util/Makefile.inc.am
@@ -228,6 +228,8 @@ UTIL_SOURCES = \
 	util/virmdev.h \
 	util/virfilecache.c \
 	util/virfilecache.h \
+    util/virmktme.c \
+    util/virmktme.h \
 	$(NULL)
 
 
diff --git a/src/util/virmktme.c b/src/util/virmktme.c
new file mode 100644
index 0000000000..f78d5de8d6
--- /dev/null
+++ b/src/util/virmktme.c
@@ -0,0 +1,127 @@
+/*
+ * virmktme.c: interaction with mktme key ring services
+ *
+ * Copyright (C) 2010-2015 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifdef __linux__
+#include <config.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <asm/unistd.h>
+#include <linux/keyctl.h>
+#endif
+#include "virerror.h"
+#include "virlog.h"
+#include "viraudit.h"
+#include "virfile.h"
+#include "viralloc.h"
+#include "virutil.h"
+#include "virstring.h"
+#include "virrandom.h"
+#include "virmktme.h"
+
+VIR_LOG_INIT("util.mktme");
+
+#define VIR_FROM_THIS VIR_FROM_NONE
+
+#define MKTME_AES_XTS_SIZE 16
+
+#ifdef __linux__
+#define GET_MKTME_DEST_RING() \
+        { \
+            destringid = syscall(__NR_request_key, \
+                                 "keyring", \
+                                 LIBVIRT_MKTME_KEY_RING_NAME, \
+                                 KEY_SPEC_PROCESS_KEYRING); \
+        }
+#else
+#define GET_MKTME_DEST_RING()
+#endif
+
+/**
+ * virGetMktmeKey:
+ * @id: mktme id-string
+ * @type: mktme key type
+ * @key: user key value
+ * @encyption_algorithm: encryption algorithm
+ *
+ * Request's a key handle, which is required to launch a encrypted guest
+ *
+ * Returns mktme key handle in case of success, and -1 in case of failure
+ */
+int
+virGetMktmeKeyHandle(const char *id,
+                     const char *type,
+                     const char *key,
+                     const char *algorithm)
+{
+    char *callout = NULL;
+    int destringid = -1;
+    unsigned char kern_entropy[MKTME_AES_XTS_SIZE];
+
+    int ret = -1;
+
+    if (!id || !type || !algorithm)
+        return -1;
+
+    GET_MKTME_DEST_RING();
+    if (destringid < 0)
+        return -1;
+
+    if (key) {
+        if (sizeof(key) != MKTME_AES_XTS_SIZE) {
+            virReportError(VIR_ERR_INVALID_ARG, "%s",
+                           _("Invalid MKTME key length"));
+            return -1;
+        }
+        if (virRandomBytes(kern_entropy, MKTME_AES_XTS_SIZE) < 0)
+            return -1;
+        if (virAsprintf(&callout, "type=%s algorithm=%s key=%s tweak=%s",
+                        type, algorithm, key, kern_entropy) < 0)
+            return -1;
+    } else {
+        if (virAsprintf(&callout, "type=%s algorithm=%s", type, algorithm) < 0)
+            return -1;
+    }
+
+#ifdef __linux__
+    ret = syscall(__NR_request_key, "mktme", id, callout, destringid);
+    VIR_FREE(callout);
+#endif
+    return ret;
+}
+
+/**
+ * virIsMktmeEnabled:
+ *
+ * Check if mktme key ring exists.
+ *
+ * Returns 0 in case mktme key ring exists, and -1 in case not present
+ */
+int
+virIsMktmeEnabled(void)
+{
+    int destringid = -1;
+    GET_MKTME_DEST_RING();
+    if (destringid < 0)
+        return -1;
+
+    return 0;
+}
diff --git a/src/util/virmktme.h b/src/util/virmktme.h
new file mode 100644
index 0000000000..e417e6eb67
--- /dev/null
+++ b/src/util/virmktme.h
@@ -0,0 +1,34 @@
+/*
+ * virmktme.h: MKTME kernel calls
+ *
+ * Copyright (C) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library.  If not, see
+ * <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef LIBVIRT_VIRMKTME_H
+# define LIBVIRT_VIRMKTME_H
+
+int
+virGetMktmeKeyHandle(const char *id,
+                     const char *type,
+                     const char *key,
+                     const char *algorithm);
+
+int
+virIsMktmeEnabled(void);
+
+# define LIBVIRT_MKTME_KEY_RING_NAME "mktme_key_ring_service"
+#endif /* LIBVIRT_VIRMKTME_H */
-- 
2.21.0.windows.1




More information about the libvir-list mailing list