[libvirt] [PATCH v2 2/4] libvirt: conf: parse XML for protected key management ops

Michal Privoznik mprivozn at redhat.com
Fri May 15 14:43:28 UTC 2015


From: Tony Krowiak <akrowiak at linux.vnet.ibm.com>

Parse the domain configuration XML elements that enable/disable access to
the protected key management operations for a guest:

    <domain>
      ...
      <keywrap>
        <cipher name='aes|dea' state='on|off'/>
      </keywrap>
      ...
    </domain>

Signed-off-by: Tony Krowiak <akrowiak at linux.vnet.ibm.com>
Signed-off-by: Viktor Mihajlovski <mihajlov at linux.vnet.ibm.com>
Signed-off-by: Daniel Hansel <daniel.hansel at linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy at linux.vnet.ibm.com>
Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/conf/domain_conf.c   | 156 +++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h   |  17 ++++++
 src/libvirt_private.syms |   2 +
 3 files changed, 175 insertions(+)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index f3b706e..ee8b474 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -477,6 +477,11 @@ VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST,
               "ich9",
               "usb")
 
+VIR_ENUM_IMPL(virDomainKeyWrapCipherName,
+              VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST,
+              "aes",
+              "dea")
+
 VIR_ENUM_IMPL(virDomainMemballoonModel, VIR_DOMAIN_MEMBALLOON_MODEL_LAST,
               "virtio",
               "xen",
@@ -834,6 +839,131 @@ virDomainXMLOptionClassDispose(void *obj)
         (xmlopt->config.privFree)(xmlopt->config.priv);
 }
 
+/**
+ * virDomainKeyWrapCipherDefParseXML:
+ *
+ * @def  Domain definition
+ * @node An XML cipher node
+ * @ctxt The XML context
+ *
+ * Parse the attributes from the cipher node and store the state
+ * attribute in @def.
+ *
+ * A cipher node has the form of
+ *
+ *   <cipher name='aes|dea' state='on|off'/>
+ *
+ * Returns: 0 if the parse succeeded
+ *         -1 otherwise
+ */
+static int
+virDomainKeyWrapCipherDefParseXML(virDomainKeyWrapDefPtr keywrap,
+                                  xmlNodePtr node,
+                                  xmlXPathContextPtr ctxt)
+{
+
+    char *name = NULL;
+    char *state = NULL;
+    int state_type;
+    int name_type;
+    int ret = -1;
+    xmlNodePtr oldnode = ctxt->node;
+
+    ctxt->node = node;
+    if (!(name = virXPathString("string(./@name)", ctxt))) {
+        virReportError(VIR_ERR_CONF_SYNTAX, "%s",
+                       _("missing name for cipher"));
+        goto cleanup;
+    }
+
+    if ((name_type = virDomainKeyWrapCipherNameTypeFromString(name)) < 0) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("%s is not a supported cipher name"), name);
+        goto cleanup;
+    }
+
+    if (!(state = virXPathString("string(./@state)", ctxt))) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("missing state for cipher named %s"), name);
+        goto cleanup;
+    }
+
+    if ((state_type = virTristateSwitchTypeFromString(state)) < 0) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("%s is not a supported cipher state"), state);
+        goto cleanup;
+    }
+
+    switch ((virDomainKeyWrapCipherName) name_type) {
+    case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_AES:
+        if (keywrap->aes != VIR_TRISTATE_SWITCH_ABSENT) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("A domain definition can have no more than "
+                             "one cipher node with name %s"),
+                           virDomainKeyWrapCipherNameTypeToString(name_type));
+
+            goto cleanup;
+        }
+        keywrap->aes = state_type;
+        break;
+
+    case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_DEA:
+        if (keywrap->dea != VIR_TRISTATE_SWITCH_ABSENT) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           _("A domain definition can have no more than "
+                             "one cipher node with name %s"),
+                           virDomainKeyWrapCipherNameTypeToString(name_type));
+
+            goto cleanup;
+        }
+        keywrap->dea = state_type;
+        break;
+
+    case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST:
+        break;
+    }
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(name);
+    VIR_FREE(state);
+    ctxt->node = oldnode;
+    return ret;
+}
+
+static int
+virDomainKeyWrapDefParseXML(virDomainDefPtr def, xmlXPathContextPtr ctxt)
+{
+    size_t i;
+    int ret = -1;
+    xmlNodePtr *nodes = NULL;
+    int n;
+
+    if (!(n = virXPathNodeSet("./keywrap/cipher", ctxt, &nodes)))
+        return 0;
+
+    if (VIR_ALLOC(def->keywrap) < 0)
+        goto cleanup;
+
+    for (i = 0; i < n; i++) {
+        if (virDomainKeyWrapCipherDefParseXML(def->keywrap, nodes[i], ctxt) < 0)
+            goto cleanup;
+    }
+
+    if (!def->keywrap->aes &&
+        !def->keywrap->dea)
+        VIR_FREE(def->keywrap);
+
+    ret = 0;
+
+ cleanup:
+    if (ret < 0)
+        VIR_FREE(def->keywrap);
+    VIR_FREE(nodes);
+    return ret;
+}
+
 
 /**
  * virDomainXMLOptionNew:
@@ -2361,6 +2491,8 @@ void virDomainDefFree(virDomainDefPtr def)
         virDomainShmemDefFree(def->shmems[i]);
     VIR_FREE(def->shmems);
 
+    VIR_FREE(def->keywrap);
+
     if (def->namespaceData && def->ns.free)
         (def->ns.free)(def->namespaceData);
 
@@ -15535,6 +15667,9 @@ virDomainDefParseXML(xmlDocPtr xml,
         VIR_FREE(tmp);
     }
 
+    if (virDomainKeyWrapDefParseXML(def, ctxt) < 0)
+        goto error;
+
     /* Extract custom metadata */
     if ((node = virXPathNode("./metadata[1]", ctxt)) != NULL)
         def->metadata = xmlCopyNode(node, 1);
@@ -20588,6 +20723,24 @@ virDomainLoaderDefFormat(virBufferPtr buf,
     }
 }
 
+static void
+virDomainKeyWrapDefFormat(virBufferPtr buf, virDomainKeyWrapDefPtr keywrap)
+{
+    virBufferAddLit(buf, "<keywrap>\n");
+    virBufferAdjustIndent(buf, 2);
+
+    if (keywrap->aes)
+        virBufferAsprintf(buf, "<cipher name='aes' state='%s'/>\n",
+                          virTristateSwitchTypeToString(keywrap->aes));
+
+    if (keywrap->dea)
+        virBufferAsprintf(buf, "<cipher name='dea' state='%s'/>\n",
+                          virTristateSwitchTypeToString(keywrap->dea));
+
+    virBufferAdjustIndent(buf, -2);
+    virBufferAddLit(buf, "</keywrap>\n");
+}
+
 static bool
 virDomainDefHasCapabilitiesFeatures(virDomainDefPtr def)
 {
@@ -21490,6 +21643,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
             goto error;
     }
 
+    if (def->keywrap)
+        virDomainKeyWrapDefFormat(buf, def->keywrap);
+
     virBufferAdjustIndent(buf, -2);
     virBufferAddLit(buf, "</domain>\n");
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 8312c20..7b29008 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2119,6 +2119,13 @@ struct _virDomainPowerManagement {
     int s4;
 };
 
+typedef struct _virDomainKeyWrapDef virDomainKeyWrapDef;
+typedef virDomainKeyWrapDef *virDomainKeyWrapDefPtr;
+struct _virDomainKeyWrapDef {
+    int aes; /* enum virTristateSwitch */
+    int dea; /* enum virTristateSwitch */
+};
+
 /*
  * Guest VM main configuration
  *
@@ -2255,6 +2262,8 @@ struct _virDomainDef {
     void *namespaceData;
     virDomainXMLNamespace ns;
 
+    virDomainKeyWrapDefPtr keywrap;
+
     /* Application-specific custom metadata */
     xmlNodePtr metadata;
 };
@@ -2264,6 +2273,13 @@ void virDomainDefSetMemoryInitial(virDomainDefPtr def, unsigned long long size);
 unsigned long long virDomainDefGetMemoryActual(virDomainDefPtr def);
 
 typedef enum {
+    VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_AES,
+    VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_DEA,
+
+    VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_LAST
+} virDomainKeyWrapCipherName;
+
+typedef enum {
     VIR_DOMAIN_TAINT_CUSTOM_ARGV,      /* Custom ARGV passthrough from XML */
     VIR_DOMAIN_TAINT_CUSTOM_MONITOR,   /* Custom monitor commands issued */
     VIR_DOMAIN_TAINT_HIGH_PRIVILEGES,  /* Running with undesirably high privileges */
@@ -2951,6 +2967,7 @@ VIR_ENUM_DECL(virDomainChrTcpProtocol)
 VIR_ENUM_DECL(virDomainChrSpicevmc)
 VIR_ENUM_DECL(virDomainSoundCodec)
 VIR_ENUM_DECL(virDomainSoundModel)
+VIR_ENUM_DECL(virDomainKeyWrapCipherName)
 VIR_ENUM_DECL(virDomainMemballoonModel)
 VIR_ENUM_DECL(virDomainSmbiosMode)
 VIR_ENUM_DECL(virDomainWatchdogModel)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index f80fc70..afd0cb6 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -329,6 +329,8 @@ virDomainIOThreadIDDefFree;
 virDomainIOThreadIDDel;
 virDomainIOThreadIDFind;
 virDomainIOThreadSchedDelId;
+virDomainKeyWrapCipherNameTypeFromString;
+virDomainKeyWrapCipherNameTypeToString;
 virDomainLeaseDefFree;
 virDomainLeaseIndex;
 virDomainLeaseInsert;
-- 
2.3.6




More information about the libvir-list mailing list