From: Tony Krowiak <akrowiak@xxxxxxxxxxxxxxxxxx> 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@xxxxxxxxxxxxxxxxxx> Signed-off-by: Viktor Mihajlovski <mihajlov@xxxxxxxxxxxxxxxxxx> Signed-off-by: Daniel Hansel <daniel.hansel@xxxxxxxxxxxxxxxxxx> Reviewed-by: Boris Fiuczynski <fiuczy@xxxxxxxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list