[libvirt] [PATCH 6/7] conf: introduce launchSecurity element type mktme in domain

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


The launch-security element can be used to define the security
model to use when launching a domain.

When 'mktme' is used, the VM will be launched with Intel MKTME feature enabled.
MKTME feature supports running encrypted guest.
---
 docs/formatdomain.html.in     |  64 +++++++++++++++++--
 docs/schemas/domaincommon.rng |  87 +++++++++++++++++---------
 src/conf/domain_conf.c        | 112 +++++++++++++++++++++++++++++++++-
 src/conf/domain_conf.h        |  14 +++++
 src/conf/virconftypes.h       |   3 +
 5 files changed, 242 insertions(+), 38 deletions(-)

diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index e1da878fcc..10d512ccd1 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -8924,13 +8924,16 @@ qemu-kvm -net nic,model=? /dev/null
 
     <p>Note: DEA/TDEA is synonymous with DES/TDES.</p>
 
-    <h3><a id="sev">Launch Security</a></h3>
+    <h3><a id="launchsecurity">Launch Security</a></h3>
 
     <p>
-       The contents of the <code><launchSecurity type='sev'></code> element
-       is used to provide the guest owners input used for creating an encrypted
-       VM using the AMD SEV feature (Secure Encrypted Virtualization).
-
+       The contents of the <code>launchSecurity</code> element is used
+       to provide the guest owners input used for creating an encrypted
+       VM using the AMD SEV feature (Secure Encrypted Virtualization)
+       and Intel MKTME (Multi-Key Total Memory Encryption).
+    </p>
+    <h4><a id="sev">SEV</a></h4>
+    <p>
        SEV is an extension to the AMD-V architecture which supports running
        encrypted virtual machine (VMs) under the control of KVM. Encrypted
        VMs have their pages (code and data) secured such that only the guest
@@ -8942,7 +8945,7 @@ qemu-kvm -net nic,model=? /dev/null
        For more information see various input parameters and its format see the
        <a href="https://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf">SEV API spec</a>
        <span class="since">Since 4.4.0</span>
-       </p>
+      </p>
     <pre>
 <domain>
   ...
@@ -9039,6 +9042,55 @@ qemu-kvm -net nic,model=? /dev/null
       </dd>
     </dl>
 
+    <h4><a id="mktme">MKTME</a></h4>
+    <p>
+      Total Memory Encryption (TME) – provides the capability to encrypt the
+      entirety of the physical memory of a system. MKTME builds on TME and
+      adds support for multiple encryption keys.
+
+      By default MKTME uses the TME encryption key unless explicitly specified
+      by software. In addition to supporting a CPU generated ephemeral
+      key (not accessible by software or by using external interfaces to an SOC),
+      MKTME also supports software provided keys. Software provided keys are
+      particularly useful when used with nonvolatile memory or when combined
+      with attestation mechanisms and/or used with key provisioning services.
+
+      For more information see
+       <a href="https://software.intel.com/sites/default/files/managed/a5/16/Multi-Key-Total-Memory-Encryption-Spec.pdf">MKTME spec</a>
+       <span class="since">Since 5.3.0</span>
+    </p>
+<pre>
+<domain>
+  ...
+  <launchSecurity type='mktme'>
+    <id>mktme-0</id>
+    <key_type>samplekey</key_type>
+    <type>user</type>
+    <encryption_algorithm>aes-xts-128</encryption_algorithm>
+  </launchSecurity>
+  ...
+</domain>
+</pre>
+    <dl>
+      <dt><code>id</code></dt>
+      <dd>The required <code>id</code> element provides ability to map the key handle.
+      If the id exists, system returns the existing key handle which can be used to
+      encrpyt a different guest.
+      </dd>
+      <dt><code>key_type</code></dt>
+      <dd>MKTME supports user and cpu generated keys. The required <code>key_type</code>
+      element provides the type of key used for the encryption.
+      </dd>
+      <dt><code>key</code></dt>
+      <dd>The optional <code>key</code> element provides the key used for the encryption.
+      Required only when the key type is of user.
+      </dd>
+      <dt><code>encryption_algorithm</code></dt>
+      <dd>The required <code>encyption_algorithm</code> element provides the type of
+      encryption algorithm. Currently, MKTME supports aes-xts-128 only.
+      </dd>
+    </dl>
+
     <h2><a id="examples">Example configs</a></h2>
 
     <p>
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index 111b85c36f..5e6847d64e 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -457,35 +457,64 @@
 
   <define name="launchSecurity">
     <element name="launchSecurity">
-      <attribute name="type">
-        <value>sev</value>
-      </attribute>
-      <interleave>
-        <element name="cbitpos">
-          <data type='unsignedInt'/>
-        </element>
-        <element name="reducedPhysBits">
-          <data type='unsignedInt'/>
-        </element>
-        <element name="policy">
-          <ref name='hexuint'/>
-        </element>
-        <optional>
-          <element name="handle">
-            <ref name='unsignedInt'/>
-          </element>
-        </optional>
-        <optional>
-          <element name="dhCert">
-            <data type="string"/>
-          </element>
-        </optional>
-        <optional>
-          <element name="session">
-            <data type="string"/>
-          </element>
-        </optional>
-      </interleave>
+      <choice>
+        <group>
+          <optional>
+            <attribute name="type">
+              <value>sev</value>
+            </attribute>
+          </optional>
+          <interleave>
+            <element name="cbitpos">
+              <data type='unsignedInt'/>
+            </element>
+            <element name="reducedPhysBits">
+              <data type='unsignedInt'/>
+            </element>
+            <element name="policy">
+              <ref name='hexuint'/>
+            </element>
+            <optional>
+              <element name="handle">
+                <ref name='unsignedInt'/>
+              </element>
+            </optional>
+            <optional>
+              <element name="dhCert">
+                <data type="string"/>
+              </element>
+            </optional>
+            <optional>
+              <element name="session">
+                <data type="string"/>
+              </element>
+            </optional>
+          </interleave>
+        </group>
+        <group>
+          <optional>
+            <attribute name="type">
+              <value>mktme</value>
+            </attribute>
+          </optional>
+          <interleave>
+            <element name="id">
+              <data type="string"/>
+            </element>
+            <element name="key_type">
+              <data type="string"/>
+            </element>
+            <element name="encryption_algorithm">
+              <data type="string"/>
+            </element>
+            <optional>
+              <element name="key">
+                <data type="string"/>
+              </element>
+            </optional>
+          </interleave>
+        </group>
+      </choice>
     </element>
   </define>
 
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a3a514136b..7420a3f00d 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -1233,6 +1233,7 @@ VIR_ENUM_IMPL(virDomainLaunchSecurity,
               VIR_DOMAIN_LAUNCH_SECURITY_LAST,
               "",
               "sev",
+              "mktme",
 );
 
 static virClassPtr virDomainObjClass;
@@ -3282,6 +3283,21 @@ virDomainSEVDefFree(virDomainSEVDefPtr def)
 }
 
 
+static void
+virDomainMKTMEDefFree(virDomainMKTMEDefPtr def)
+{
+    if (!def)
+        return;
+
+    VIR_FREE(def->id);
+    VIR_FREE(def->key_type);
+    VIR_FREE(def->key);
+    VIR_FREE(def->encryption_algorithm);
+
+    VIR_FREE(def);
+}
+
+
 void virDomainDefFree(virDomainDefPtr def)
 {
     size_t i;
@@ -3466,6 +3482,7 @@ void virDomainDefFree(virDomainDefPtr def)
         (def->ns.free)(def->namespaceData);
 
     virDomainSEVDefFree(def->sev);
+    virDomainMKTMEDefFree(def->mktme);
 
     xmlFreeNode(def->metadata);
 
@@ -15940,6 +15957,44 @@ virDomainMemoryTargetDefParseXML(xmlNodePtr node,
 }
 
 
+static int
+virDomainGetLaunchSecurityType(xmlNodePtr node)
+{
+    VIR_AUTOFREE(char *) type = NULL;
+
+    if (!(type = virXMLPropString(node, "type"))) {
+        virReportError(VIR_ERR_XML_ERROR, "%s",
+            _("missing launch security type"));
+        return -1;
+    }
+
+    return virDomainLaunchSecurityTypeFromString(type);
+}
+
+
+static virDomainMKTMEDefPtr
+virDomainMKTMEDefParseXML(xmlNodePtr mktmeNode,
+    xmlXPathContextPtr ctxt)
+{
+    VIR_XPATH_NODE_AUTORESTORE(ctxt);
+    virDomainMKTMEDefPtr def;
+
+    if (VIR_ALLOC(def) < 0)
+        return NULL;
+
+    ctxt->node = mktmeNode;
+
+    def->sectype = VIR_DOMAIN_LAUNCH_SECURITY_MKTME;
+
+    def->id = virXPathString("string(./id)", ctxt);
+    def->key_type = virXPathString("string(./key_type)", ctxt);
+    def->key = virXPathString("string(./key)", ctxt);
+    def->encryption_algorithm = virXPathString("string(./encryption_algorithm)", ctxt);
+
+    return def;
+}
+
+
 static virDomainSEVDefPtr
 virDomainSEVDefParseXML(xmlNodePtr sevNode,
                         xmlXPathContextPtr ctxt)
@@ -15965,6 +16020,7 @@ virDomainSEVDefParseXML(xmlNodePtr sevNode,
     case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
         break;
     case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
+    case VIR_DOMAIN_LAUNCH_SECURITY_MKTME:
     case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
     default:
         virReportError(VIR_ERR_XML_ERROR,
@@ -21127,11 +21183,33 @@ virDomainDefParseXML(xmlDocPtr xml,
     ctxt->node = node;
     VIR_FREE(nodes);
 
-    /* Check for SEV feature */
+    /* Check for launch security (MKTME/SEV) feature */
     if ((node = virXPathNode("./launchSecurity", ctxt)) != NULL) {
-        def->sev = virDomainSEVDefParseXML(node, ctxt);
-        if (!def->sev)
+        int sectype = virDomainGetLaunchSecurityType(node);
+
+        if (sectype < 0)
             goto error;
+
+        switch ((virDomainLaunchSecurity)sectype) {
+        case VIR_DOMAIN_LAUNCH_SECURITY_SEV:
+            /* Optimize virDomainSEVDefParseXML; since we are already checking for sectype*/
+            def->sev = virDomainSEVDefParseXML(node, ctxt);
+            if (!def->sev)
+                goto error;
+            break;
+        case VIR_DOMAIN_LAUNCH_SECURITY_MKTME:
+            def->mktme = virDomainMKTMEDefParseXML(node, ctxt);
+            if (!def->mktme)
+                goto error;
+            break;
+        case VIR_DOMAIN_LAUNCH_SECURITY_NONE:
+        case VIR_DOMAIN_LAUNCH_SECURITY_LAST:
+        default:
+            virReportError(VIR_ERR_XML_ERROR,
+                _("unsupported launch security type '%s'"),
+                virXMLPropString(node, "type"));
+            goto error;
+        }
     }
 
     /* analysis of memory devices */
@@ -27268,6 +27346,33 @@ virDomainSEVDefFormat(virBufferPtr buf, virDomainSEVDefPtr sev)
 }
 
 
+static void
+virDomainMKTMEDefFormat(virBufferPtr buf, virDomainMKTMEDefPtr mktme)
+{
+    if (!mktme)
+        return;
+
+    virBufferAsprintf(buf, "<launchSecurity type='%s'>\n",
+        virDomainLaunchSecurityTypeToString(mktme->sectype));
+    virBufferAdjustIndent(buf, 2);
+
+    if (mktme->id)
+        virBufferEscapeString(buf, "<id>%s</id>\n", mktme->id);
+
+    if (mktme->key_type)
+        virBufferEscapeString(buf, "<key_type>%s</key_type>\n", mktme->key_type);
+
+    if (mktme->key)
+        virBufferEscapeString(buf, "<key>%s</key>\n", mktme->key);
+
+    if (mktme->encryption_algorithm)
+        virBufferEscapeString(buf, "<encryption_algorithm>%s</encryption_algorithm>\n", mktme->encryption_algorithm);
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</launchSecurity>\n");
+}
+
+
 static void
 virDomainPerfDefFormat(virBufferPtr buf, virDomainPerfDefPtr perf)
 {
@@ -28640,6 +28745,7 @@ virDomainDefFormatInternal(virDomainDefPtr def,
         virDomainKeyWrapDefFormat(buf, def->keywrap);
 
     virDomainSEVDefFormat(buf, def->sev);
+    virDomainMKTMEDefFormat(buf, def->mktme);
 
     virBufferAdjustIndent(buf, -2);
     virBufferAddLit(buf, "</domain>\n");
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index fa0756b634..b86d02376c 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2279,6 +2279,7 @@ struct _virDomainKeyWrapDef {
 typedef enum {
     VIR_DOMAIN_LAUNCH_SECURITY_NONE,
     VIR_DOMAIN_LAUNCH_SECURITY_SEV,
+    VIR_DOMAIN_LAUNCH_SECURITY_MKTME,
 
     VIR_DOMAIN_LAUNCH_SECURITY_LAST,
 } virDomainLaunchSecurity;
@@ -2294,6 +2295,16 @@ struct _virDomainSEVDef {
 };
 
 
+struct _virDomainMKTMEDef {
+    int   sectype; /* enum virDomainLaunchSecurity */
+    char  *id;
+    char  *key_type;
+    char  *key;
+    char  *encryption_algorithm;
+    int   key_handle;
+};
+
+
 typedef enum {
     VIR_DOMAIN_IOMMU_MODEL_INTEL,
 
@@ -2491,6 +2502,9 @@ struct _virDomainDef {
     /* SEV-specific domain */
     virDomainSEVDefPtr sev;
 
+    /* MKTME- domain info*/
+    virDomainMKTMEDefPtr mktme;
+
     /* Application-specific custom metadata */
     xmlNodePtr metadata;
 
diff --git a/src/conf/virconftypes.h b/src/conf/virconftypes.h
index 6a8267c422..c432e4493f 100644
--- a/src/conf/virconftypes.h
+++ b/src/conf/virconftypes.h
@@ -277,6 +277,9 @@ typedef virDomainResourceDef *virDomainResourceDefPtr;
 typedef struct _virDomainSEVDef virDomainSEVDef;
 typedef virDomainSEVDef *virDomainSEVDefPtr;
 
+typedef struct _virDomainMKTMEDef virDomainMKTMEDef;
+typedef virDomainMKTMEDef *virDomainMKTMEDefPtr;
+
 typedef struct _virDomainShmemDef virDomainShmemDef;
 typedef virDomainShmemDef *virDomainShmemDefPtr;
 
-- 
2.21.0.windows.1




More information about the libvir-list mailing list