being on a file system that lacks security labeling.
</p>
+ <h3><a name="keywrap">Key Wrap</a></h3>
+
+ <p>The content of the optional <code>keywrap</code> element specifies
+ whether the guest will be allowed to perform the S390 cryptographic key
+ management operations. A clear key can be protected by encrypting it
+ under a unique wrapping key that is generated for each guest VM running
+ on the host. Two variations of wrapping keys are generated: one version
+ for encrypting protected keys using the DEA/TDEA algorithm, and another
+ version for keys encrypted using the AES algorithm. If a
+ <code>keywrap</code> element is not included, the guest will be granted
+ access to both AES and DEA/TDEA key wrapping by default.</p>
+
+ <pre>
+<domain>
+ ...
+ <keywrap>
+ <cipher name='aes' state='off'/>
+ </keywrap>
+ ...
+</domain>
+</pre>
+ <p>
+ At least one <code>cipher</code> element must be nested within the
+ <code>keywrap</code> element.
+ </p>
+ <dl>
+ <dt><code>cipher</code></dt>
+ <dd>The <code>name</code> attribute identifies the algorithm
+ for encrypting a protected key. The values supported for this attribute
+ are <code>aes</code> for encryption under the AES wrapping key, or
+ <code>dea</code> for encryption under the DEA/TDEA wrapping key. The
+ <code>state</code> attribute indicates whether the cryptographic key
+ management operations should be turned on for the specified encryption
+ algorithm. The value can be set to <code>on</code> or <code>off</code>.
+ </dd>
+ </dl>
+
+ <p>Note: DEA/TDEA is synonymous with DES/TDES.</p>
+
<h2><a name="examples">Example configs</a></h2>
<p>
"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",
(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:
virDomainShmemDefFree(def->shmems[i]);
VIR_FREE(def->shmems);
+ VIR_FREE(def->keywrap);
+
if (def->namespaceData && def->ns.free)
(def->ns.free)(def->namespaceData);
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);
}
}
+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)
{
goto error;
}
+ if (def->keywrap)
+ virDomainKeyWrapDefFormat(buf, def->keywrap);
+
virBufferAdjustIndent(buf, -2);
virBufferAddLit(buf, "</domain>\n");
int s4;
};
+typedef struct _virDomainKeyWrapDef virDomainKeyWrapDef;
+typedef virDomainKeyWrapDef *virDomainKeyWrapDefPtr;
+struct _virDomainKeyWrapDef {
+ int aes; /* enum virTristateSwitch */
+ int dea; /* enum virTristateSwitch */
+};
+
/*
* Guest VM main configuration
*
void *namespaceData;
virDomainXMLNamespace ns;
+ virDomainKeyWrapDefPtr keywrap;
+
/* Application-specific custom metadata */
xmlNodePtr metadata;
};
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_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)