mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 12:35:17 +00:00
libvirt: Introduce protected key mgmt ops
Two new domain configuration XML elements are added to enable/disable 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@linux.vnet.ibm.com> Signed-off-by: Viktor Mihajlovski <mihajlov@linux.vnet.ibm.com> Signed-off-by: Daniel Hansel <daniel.hansel@linux.vnet.ibm.com> Reviewed-by: Boris Fiuczynski <fiuczy@linux.vnet.ibm.com> Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
This commit is contained in:
parent
99a42f3c0f
commit
73eda71028
@ -6227,6 +6227,45 @@ qemu-kvm -net nic,model=? /dev/null
|
||||
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>
|
||||
|
@ -67,6 +67,9 @@
|
||||
<optional>
|
||||
<ref name='qemucmdline'/>
|
||||
</optional>
|
||||
<optional>
|
||||
<ref name='keywrap'/>
|
||||
</optional>
|
||||
</interleave>
|
||||
</element>
|
||||
</define>
|
||||
@ -382,6 +385,24 @@
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<define name="keywrap">
|
||||
<element name="keywrap">
|
||||
<oneOrMore>
|
||||
<element name="cipher">
|
||||
<attribute name="name">
|
||||
<choice>
|
||||
<value>aes</value>
|
||||
<value>dea</value>
|
||||
</choice>
|
||||
</attribute>
|
||||
<attribute name="state">
|
||||
<ref name='virOnOff'/>
|
||||
</attribute>
|
||||
</element>
|
||||
</oneOrMore>
|
||||
</element>
|
||||
</define>
|
||||
|
||||
<!--
|
||||
The Identifiers can be:
|
||||
- an optional id attribute with a number on the domain element
|
||||
|
@ -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);
|
||||
|
||||
@ -15569,6 +15701,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);
|
||||
@ -20622,6 +20757,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)
|
||||
{
|
||||
@ -21524,6 +21677,9 @@ virDomainDefFormatInternal(virDomainDefPtr def,
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (def->keywrap)
|
||||
virDomainKeyWrapDefFormat(buf, def->keywrap);
|
||||
|
||||
virBufferAdjustIndent(buf, -2);
|
||||
virBufferAddLit(buf, "</domain>\n");
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
@ -2263,6 +2272,13 @@ unsigned long long virDomainDefGetMemoryInitial(virDomainDefPtr def);
|
||||
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 */
|
||||
@ -2954,6 +2970,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)
|
||||
|
@ -330,6 +330,8 @@ virDomainIOThreadIDDefFree;
|
||||
virDomainIOThreadIDDel;
|
||||
virDomainIOThreadIDFind;
|
||||
virDomainIOThreadSchedDelId;
|
||||
virDomainKeyWrapCipherNameTypeFromString;
|
||||
virDomainKeyWrapCipherNameTypeToString;
|
||||
virDomainLeaseDefFree;
|
||||
virDomainLeaseIndex;
|
||||
virDomainLeaseInsert;
|
||||
|
Loading…
x
Reference in New Issue
Block a user