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>
---
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