提交 73eda710 编写于 作者: T Tony Krowiak 提交者: Michal Privoznik

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: NTony Krowiak <akrowiak@linux.vnet.ibm.com>
Signed-off-by: NViktor Mihajlovski <mihajlov@linux.vnet.ibm.com>
Signed-off-by: NDaniel Hansel <daniel.hansel@linux.vnet.ibm.com>
Reviewed-by: NBoris Fiuczynski <fiuczy@linux.vnet.ibm.com>
Signed-off-by: NMichal Privoznik <mprivozn@redhat.com>
上级 99a42f3c
......@@ -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>
&lt;domain&gt;
...
&lt;keywrap&gt;
&lt;cipher name='aes' state='off'/&gt;
&lt;/keywrap&gt;
...
&lt;/domain&gt;
</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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册