From: Tony Krowiak <akrowiak(a)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(a)linux.vnet.ibm.com>
Signed-off-by: Viktor Mihajlovski <mihajlov(a)linux.vnet.ibm.com>
Signed-off-by: Daniel Hansel <daniel.hansel(a)linux.vnet.ibm.com>
Reviewed-by: Boris Fiuczynski <fiuczy(a)linux.vnet.ibm.com>
Signed-off-by: Michal Privoznik <mprivozn(a)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