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

akrowiak at linux.vnet.ibm.com akrowiak at linux.vnet.ibm.com
Thu May 7 15:52:56 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>
---
 src/conf/domain_conf.c   |  189 ++++++++++++++++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h   |   20 +++++
 src/libvirt_private.syms |    2 +
 3 files changed, 211 insertions(+), 0 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 0b18720..4c8d934 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -476,6 +476,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",
@@ -835,6 +840,124 @@ virDomainXMLOptionClassDispose(void *obj)
 
 
 /**
+ * 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, otherwise; returns -1
+ */
+static int
+virDomainKeyWrapCipherDefParseXML(virDomainDefPtr def, xmlNodePtr node,
+                                  xmlXPathContextPtr ctxt)
+{
+
+    char *name = NULL;
+    char *state = NULL;
+    int state_type;
+    int name_type;
+    int rc = -1;
+    xmlNodePtr oldnode = ctxt->node;
+    ctxt->node = node;
+    name = virXPathString("string(./@name)", ctxt);
+
+    if (name == NULL) {
+        virReportError(VIR_ERR_CONF_SYNTAX, "%s",
+                       _("missing name for cipher"));
+        goto error;
+    }
+
+    if ((name_type = virDomainKeyWrapCipherNameTypeFromString(name)) < 0) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("%s is not a supported cipher name"), name);
+        goto error;
+    }
+
+    state = virXPathString("string(./@state)", ctxt);
+
+    if (state == NULL) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("missing state for cipher named %s"), name);
+        goto error;
+    }
+
+    if ((state_type = virTristateSwitchTypeFromString(state)) < 0) {
+        virReportError(VIR_ERR_CONF_SYNTAX,
+                       _("%s is not a supported cipher state"), state);
+        goto error;
+    }
+
+    switch (name_type) {
+        case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_AES:
+            if (def->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 error;
+            }
+            def->keywrap.aes = state_type;
+            break;
+        case VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_DEA:
+            if (def->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 error;
+            }
+            def->keywrap.dea = state_type;
+            break;
+        default:
+            virReportError(VIR_ERR_CONF_SYNTAX,
+                           _("%s is not a supported cipher name"), name);
+            goto error;
+    }
+
+    ctxt->node = oldnode;
+    rc = 0;
+
+ error:
+    VIR_FREE(name);
+    VIR_FREE(state);
+    return rc;
+}
+
+static int
+virDomainKeyWrapDefParseXML(virDomainDefPtr def, xmlXPathContextPtr ctxt)
+{
+    size_t i;
+    int rc = -1;
+    xmlNodePtr *nodes = NULL;
+    int n = virXPathNodeSet("./keywrap/cipher", ctxt, &nodes);
+    def->keywrap.aes = VIR_TRISTATE_SWITCH_ABSENT;
+    def->keywrap.dea = VIR_TRISTATE_SWITCH_ABSENT;
+
+    for (i = 0; i < n; i++) {
+        if (virDomainKeyWrapCipherDefParseXML(def, nodes[i], ctxt) < 0)
+            goto error;
+    }
+
+    rc = 0;
+
+ error:
+    VIR_FREE(nodes);
+
+    return rc;
+}
+
+
+/**
  * virDomainXMLOptionNew:
  *
  * Allocate a new domain XML configuration
@@ -15558,6 +15681,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);
@@ -20598,6 +20724,66 @@ virDomainLoaderDefFormat(virBufferPtr buf,
     }
 }
 
+static int
+virDomainKeyGetWrapCipherValue(int cdef, char **cstate, const char *cname)
+{
+    const char *state;
+
+    if (cdef != VIR_TRISTATE_SWITCH_ABSENT) {
+        state = virTristateSwitchTypeToString(cdef);
+
+       if (state == NULL) {
+           virReportError(VIR_ERR_INTERNAL_ERROR,
+                          _("unexpected %s key wrap state %d"), cname, cdef);
+            return -1;
+        }
+
+        if (VIR_STRDUP(*cstate, state) < 0)
+            return -1;
+    }
+
+    return 0;
+}
+
+static int
+virDomainKeyWrapDefFormat(virBufferPtr buf, virDomainDefPtr def)
+{
+    char *aes_state = NULL;
+    char *dea_state = NULL;
+    const char *aes_name =
+            virDomainKeyWrapCipherNameTypeToString(
+                    VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_AES);
+    const char *dea_name =
+            virDomainKeyWrapCipherNameTypeToString(
+                    VIR_DOMAIN_KEY_WRAP_CIPHER_NAME_DEA);
+
+    if ((virDomainKeyGetWrapCipherValue(def->keywrap.aes, &aes_state,
+                                        aes_name) < 0) ||
+        (virDomainKeyGetWrapCipherValue(def->keywrap.dea, &dea_state,
+                                        dea_name) < 0))
+        return -1;
+
+    if (aes_state || dea_state) {
+        virBufferAddLit(buf, "<keywrap>\n");
+        virBufferAdjustIndent(buf, 2);
+
+        if (aes_state)
+            virBufferAsprintf(buf, "<cipher name='%s' state='%s'/>\n",
+                              aes_name, aes_state);
+
+        if (dea_state)
+            virBufferAsprintf(buf, "<cipher name='%s' state='%s'/>\n",
+                              dea_name, dea_state);
+
+        virBufferAdjustIndent(buf, -2);
+        virBufferAddLit(buf, "</keywrap>\n");
+        VIR_FREE(aes_state);
+        VIR_FREE(dea_state);
+    }
+
+    return 0;
+}
+
 static bool
 virDomainDefHasCapabilitiesFeatures(virDomainDefPtr def)
 {
@@ -21489,6 +21675,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
             goto error;
     }
 
+    if (virDomainKeyWrapDefFormat(buf, def) < 0)
+        goto error;
+
     virBufferAdjustIndent(buf, -2);
     virBufferAddLit(buf, "</domain>\n");
 
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 0761eee..bc467f9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2126,6 +2126,13 @@ struct _virDomainPowerManagement {
     int s4;
 };
 
+typedef struct _virDomainKeyWrapDef virDomainKeyWrapDef;
+typedef virDomainKeyWrapDef *virDomainKeyWrapPtr;
+struct _virDomainKeyWrapDef {
+    int aes; /* enum virTristateSwitch */
+    int dea;
+};
+
 /*
  * Guest VM main configuration
  *
@@ -2263,12 +2270,24 @@ struct _virDomainDef {
 
     /* Application-specific custom metadata */
     xmlNodePtr metadata;
+
+    virDomainKeyWrapDef keywrap;
 };
 
 unsigned long long virDomainDefGetMemoryInitial(virDomainDefPtr def);
 void virDomainDefSetMemoryInitial(virDomainDefPtr def, unsigned long long size);
 unsigned long long virDomainDefGetMemoryActual(virDomainDefPtr def);
 
+# define VIR_DOMAIN_AES_KEY_WRAP_DEFAULT VIR_TRISTATE_SWITCH_ON
+# define VIR_DOMAIN_DEA_KEY_WRAP_DEFAULT VIR_TRISTATE_SWITCH_ON
+
+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 */
@@ -2958,6 +2977,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 3a99813..7aa178f 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -330,6 +330,8 @@ virDomainIOThreadIDDefFree;
 virDomainIOThreadIDDel;
 virDomainIOThreadIDFind;
 virDomainIOThreadSchedDelId;
+virDomainKeyWrapCipherNameTypeFromString;
+virDomainKeyWrapCipherNameTypeToString;
 virDomainLeaseDefFree;
 virDomainLeaseIndex;
 virDomainLeaseInsert;
-- 
1.7.1




More information about the libvir-list mailing list