|
|
6ae9ed |
From 629e64743474a040863ef1267eb48568c6e3e80c Mon Sep 17 00:00:00 2001
|
|
|
6ae9ed |
Message-Id: <629e64743474a040863ef1267eb48568c6e3e80c@dist-git>
|
|
|
6ae9ed |
From: John Ferlan <jferlan@redhat.com>
|
|
|
6ae9ed |
Date: Mon, 25 Jul 2016 12:42:49 -0400
|
|
|
6ae9ed |
Subject: [PATCH] encryption: Add <cipher> and <ivgen> to encryption
|
|
|
6ae9ed |
|
|
|
6ae9ed |
https://bugzilla.redhat.com/show_bug.cgi?id=1301021
|
|
|
6ae9ed |
|
|
|
6ae9ed |
For a luks device, allow the configuration of a specific cipher to be
|
|
|
6ae9ed |
used for encrypting the volume.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
Signed-off-by: John Ferlan <jferlan@redhat.com>
|
|
|
6ae9ed |
(cherry picked from commit 2552fec248c665f3417a5d36840555da6bbe96a4)
|
|
|
6ae9ed |
---
|
|
|
6ae9ed |
docs/formatstorageencryption.html.in | 83 ++++++++++++-
|
|
|
6ae9ed |
docs/schemas/storagecommon.rng | 44 ++++++-
|
|
|
6ae9ed |
src/conf/domain_conf.c | 11 ++
|
|
|
6ae9ed |
src/util/virstorageencryption.c | 136 +++++++++++++++++++++
|
|
|
6ae9ed |
src/util/virstorageencryption.h | 14 +++
|
|
|
6ae9ed |
.../qemuxml2argv-luks-disk-cipher.xml | 45 +++++++
|
|
|
6ae9ed |
.../qemuxml2xmlout-luks-disk-cipher.xml | 1 +
|
|
|
6ae9ed |
tests/qemuxml2xmltest.c | 1 +
|
|
|
6ae9ed |
tests/storagevolxml2xmlin/vol-luks-cipher.xml | 23 ++++
|
|
|
6ae9ed |
tests/storagevolxml2xmlout/vol-luks-cipher.xml | 23 ++++
|
|
|
6ae9ed |
tests/storagevolxml2xmltest.c | 1 +
|
|
|
6ae9ed |
11 files changed, 376 insertions(+), 6 deletions(-)
|
|
|
6ae9ed |
create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-luks-disk-cipher.xml
|
|
|
6ae9ed |
create mode 120000 tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disk-cipher.xml
|
|
|
6ae9ed |
create mode 100644 tests/storagevolxml2xmlin/vol-luks-cipher.xml
|
|
|
6ae9ed |
create mode 100644 tests/storagevolxml2xmlout/vol-luks-cipher.xml
|
|
|
6ae9ed |
|
|
|
6ae9ed |
diff --git a/docs/formatstorageencryption.html.in b/docs/formatstorageencryption.html.in
|
|
|
6ae9ed |
index 380763e..f2b0ffd 100644
|
|
|
6ae9ed |
--- a/docs/formatstorageencryption.html.in
|
|
|
6ae9ed |
+++ b/docs/formatstorageencryption.html.in
|
|
|
6ae9ed |
@@ -68,6 +68,60 @@
|
|
|
6ae9ed |
be used as the passphrase to decrypt the volume.
|
|
|
6ae9ed |
Since 2.1.0.
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ For volume creation, it is possible to specify the encryption
|
|
|
6ae9ed |
+ algorithm used to encrypt the luks volume. The following two
|
|
|
6ae9ed |
+ optional elements may be provided for that purpose. It is hypervisor
|
|
|
6ae9ed |
+ dependent as to which algorithms are supported. The default algorithm
|
|
|
6ae9ed |
+ used by the storage driver backend when using qemu-img to create
|
|
|
6ae9ed |
+ the volume is 'aes-256-cbc' using 'essiv' for initialization vector
|
|
|
6ae9ed |
+ generation and 'sha256' hash algorithm for both the cipher and the
|
|
|
6ae9ed |
+ initialization vector generation.
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ cipher
|
|
|
6ae9ed |
+ This element describes the cipher algorithm to be used to either
|
|
|
6ae9ed |
+ encrypt or decrypt the luks volume. This element has the following
|
|
|
6ae9ed |
+ attributes:
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ name
|
|
|
6ae9ed |
+ The name of the cipher algorithm used for data encryption,
|
|
|
6ae9ed |
+ such as 'aes', 'des', 'cast5', 'serpent', 'twofish', etc.
|
|
|
6ae9ed |
+ Support of the specific algorithm is storage driver
|
|
|
6ae9ed |
+ implementation dependent.
|
|
|
6ae9ed |
+ size
|
|
|
6ae9ed |
+ The size of the cipher in bits, such as '256', '192', '128',
|
|
|
6ae9ed |
+ etc. Support of the specific size for a specific cipher is
|
|
|
6ae9ed |
+ hypervisor dependent.
|
|
|
6ae9ed |
+ mode
|
|
|
6ae9ed |
+ An optional cipher algorithm mode such as 'cbc', 'xts',
|
|
|
6ae9ed |
+ 'ecb', etc. Support of the specific cipher mode is
|
|
|
6ae9ed |
+ hypervisor dependent.
|
|
|
6ae9ed |
+ hash
|
|
|
6ae9ed |
+ An optional master key hash algorithm such as 'md5', 'sha1',
|
|
|
6ae9ed |
+ 'sha256', etc. Support of the specific hash algorithm is
|
|
|
6ae9ed |
+ hypervisor dependent.
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ ivgen
|
|
|
6ae9ed |
+ This optional element describes the initialization vector
|
|
|
6ae9ed |
+ generation algorithm used in conjunction with the
|
|
|
6ae9ed |
+ cipher . If the cipher is not provided,
|
|
|
6ae9ed |
+ then an error will be generated by the parser.
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ name
|
|
|
6ae9ed |
+ The name of the algorithm, such as 'plain', 'plain64',
|
|
|
6ae9ed |
+ 'essiv', etc. Support of the specific algorithm is hypervisor
|
|
|
6ae9ed |
+ dependent.
|
|
|
6ae9ed |
+ hash
|
|
|
6ae9ed |
+ An optional hash algorithm such as 'md5', 'sha1', 'sha256',
|
|
|
6ae9ed |
+ etc. Support of the specific ivgen hash algorithm is hypervisor
|
|
|
6ae9ed |
+ dependent.
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
@@ -81,9 +135,12 @@
|
|
|
6ae9ed |
</encryption>
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
- Here is a simple example, specifying use of the luks format
|
|
|
6ae9ed |
- where it's assumed that a secret has been defined using a
|
|
|
6ae9ed |
- usage element with a id of "luks_example":
|
|
|
6ae9ed |
+ Assuming a
|
|
|
6ae9ed |
+ luks secret is already defined using a
|
|
|
6ae9ed |
+ usage element with an name of "luks_example",
|
|
|
6ae9ed |
+ a simple example specifying use of the luks format
|
|
|
6ae9ed |
+ for either volume creation without a specific cipher being defined or
|
|
|
6ae9ed |
+ as part of a domain volume definition:
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
<encryption format='luks'>
|
|
|
6ae9ed |
@@ -91,5 +148,25 @@
|
|
|
6ae9ed |
</encryption>
|
|
|
6ae9ed |
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ Here is an example, specifying use of the luks format for
|
|
|
6ae9ed |
+ a specific cipher algorihm for volume creation:
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ <volume>
|
|
|
6ae9ed |
+ <name>twofish.luks</name>
|
|
|
6ae9ed |
+ <capacity unit='G'>5</capacity>
|
|
|
6ae9ed |
+ <target>
|
|
|
6ae9ed |
+ <path>/var/lib/libvirt/images/demo.luks</path>
|
|
|
6ae9ed |
+ <format type='luks'/>
|
|
|
6ae9ed |
+ <encryption format='luks'>
|
|
|
6ae9ed |
+ <secret type='passphrase' usage='luks_example'/>
|
|
|
6ae9ed |
+ <cipher name='twofish' size='256' mode='cbc' hash='sha256'/>
|
|
|
6ae9ed |
+ <ivgen name='plain64' hash='sha256'/>
|
|
|
6ae9ed |
+ </encryption>
|
|
|
6ae9ed |
+ </target>
|
|
|
6ae9ed |
+ </volume>
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
</body>
|
|
|
6ae9ed |
</html>
|
|
|
6ae9ed |
diff --git a/docs/schemas/storagecommon.rng b/docs/schemas/storagecommon.rng
|
|
|
6ae9ed |
index 63b55b4..316fbae 100644
|
|
|
6ae9ed |
--- a/docs/schemas/storagecommon.rng
|
|
|
6ae9ed |
+++ b/docs/schemas/storagecommon.rng
|
|
|
6ae9ed |
@@ -15,9 +15,19 @@
|
|
|
6ae9ed |
<value>luks</value>
|
|
|
6ae9ed |
</choice>
|
|
|
6ae9ed |
</attribute>
|
|
|
6ae9ed |
- <zeroOrMore>
|
|
|
6ae9ed |
- <ref name='secret'/>
|
|
|
6ae9ed |
- </zeroOrMore>
|
|
|
6ae9ed |
+ <interleave>
|
|
|
6ae9ed |
+ <zeroOrMore>
|
|
|
6ae9ed |
+ <ref name='secret'/>
|
|
|
6ae9ed |
+ </zeroOrMore>
|
|
|
6ae9ed |
+ <optional>
|
|
|
6ae9ed |
+ <element name='cipher'>
|
|
|
6ae9ed |
+ <ref name='keycipher'/>
|
|
|
6ae9ed |
+ </element>
|
|
|
6ae9ed |
+ <element name='ivgen'>
|
|
|
6ae9ed |
+ <ref name='keyivgen'/>
|
|
|
6ae9ed |
+ </element>
|
|
|
6ae9ed |
+ </optional>
|
|
|
6ae9ed |
+ </interleave>
|
|
|
6ae9ed |
</element>
|
|
|
6ae9ed |
</define>
|
|
|
6ae9ed |
|
|
|
6ae9ed |
@@ -136,4 +146,32 @@
|
|
|
6ae9ed |
</optional>
|
|
|
6ae9ed |
</define>
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ <define name='keycipher'>
|
|
|
6ae9ed |
+ <attribute name='name'>
|
|
|
6ae9ed |
+ <text/>
|
|
|
6ae9ed |
+ </attribute>
|
|
|
6ae9ed |
+ <attribute name='size'>
|
|
|
6ae9ed |
+ <ref name="unsignedInt"/>
|
|
|
6ae9ed |
+ </attribute>
|
|
|
6ae9ed |
+ <optional>
|
|
|
6ae9ed |
+ <attribute name='mode'>
|
|
|
6ae9ed |
+ <text/>
|
|
|
6ae9ed |
+ </attribute>
|
|
|
6ae9ed |
+ <attribute name='hash'>
|
|
|
6ae9ed |
+ <text/>
|
|
|
6ae9ed |
+ </attribute>
|
|
|
6ae9ed |
+ </optional>
|
|
|
6ae9ed |
+ </define>
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ <define name='keyivgen'>
|
|
|
6ae9ed |
+ <attribute name='name'>
|
|
|
6ae9ed |
+ <text/>
|
|
|
6ae9ed |
+ </attribute>
|
|
|
6ae9ed |
+ <optional>
|
|
|
6ae9ed |
+ <attribute name='hash'>
|
|
|
6ae9ed |
+ <text/>
|
|
|
6ae9ed |
+ </attribute>
|
|
|
6ae9ed |
+ </optional>
|
|
|
6ae9ed |
+ </define>
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
</grammar>
|
|
|
6ae9ed |
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
|
|
|
6ae9ed |
index 8b9b623..abf889a 100644
|
|
|
6ae9ed |
--- a/src/conf/domain_conf.c
|
|
|
6ae9ed |
+++ b/src/conf/domain_conf.c
|
|
|
6ae9ed |
@@ -7869,6 +7869,17 @@ virDomainDiskDefParseXML(virDomainXMLOptionPtr xmlopt,
|
|
|
6ae9ed |
def->startupPolicy = val;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ if (encryption) {
|
|
|
6ae9ed |
+ if (encryption->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS &&
|
|
|
6ae9ed |
+ encryption->encinfo.cipher_name) {
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
|
|
6ae9ed |
+ _("supplying the <cipher> for a domain is "
|
|
|
6ae9ed |
+ "unnecessary"));
|
|
|
6ae9ed |
+ goto error;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
def->dst = target;
|
|
|
6ae9ed |
target = NULL;
|
|
|
6ae9ed |
def->src->auth = authdef;
|
|
|
6ae9ed |
diff --git a/src/util/virstorageencryption.c b/src/util/virstorageencryption.c
|
|
|
6ae9ed |
index 2b59420..116a235 100644
|
|
|
6ae9ed |
--- a/src/util/virstorageencryption.c
|
|
|
6ae9ed |
+++ b/src/util/virstorageencryption.c
|
|
|
6ae9ed |
@@ -35,6 +35,7 @@
|
|
|
6ae9ed |
#include "viruuid.h"
|
|
|
6ae9ed |
#include "virfile.h"
|
|
|
6ae9ed |
#include "virsecret.h"
|
|
|
6ae9ed |
+#include "virstring.h"
|
|
|
6ae9ed |
|
|
|
6ae9ed |
#define VIR_FROM_THIS VIR_FROM_STORAGE
|
|
|
6ae9ed |
|
|
|
6ae9ed |
@@ -46,6 +47,17 @@ VIR_ENUM_IMPL(virStorageEncryptionFormat,
|
|
|
6ae9ed |
"default", "qcow", "luks")
|
|
|
6ae9ed |
|
|
|
6ae9ed |
static void
|
|
|
6ae9ed |
+virStorageEncryptionInfoDefFree(virStorageEncryptionInfoDefPtr def)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ VIR_FREE(def->cipher_name);
|
|
|
6ae9ed |
+ VIR_FREE(def->cipher_mode);
|
|
|
6ae9ed |
+ VIR_FREE(def->cipher_hash);
|
|
|
6ae9ed |
+ VIR_FREE(def->ivgen_name);
|
|
|
6ae9ed |
+ VIR_FREE(def->ivgen_hash);
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static void
|
|
|
6ae9ed |
virStorageEncryptionSecretFree(virStorageEncryptionSecretPtr secret)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
if (!secret)
|
|
|
6ae9ed |
@@ -64,6 +76,7 @@ virStorageEncryptionFree(virStorageEncryptionPtr enc)
|
|
|
6ae9ed |
|
|
|
6ae9ed |
for (i = 0; i < enc->nsecrets; i++)
|
|
|
6ae9ed |
virStorageEncryptionSecretFree(enc->secrets[i]);
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDefFree(&enc->encinfo);
|
|
|
6ae9ed |
VIR_FREE(enc->secrets);
|
|
|
6ae9ed |
VIR_FREE(enc);
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
@@ -81,6 +94,23 @@ virStorageEncryptionSecretCopy(const virStorageEncryptionSecret *src)
|
|
|
6ae9ed |
return ret;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+virStorageEncryptionInfoDefCopy(const virStorageEncryptionInfoDef *src,
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDefPtr dst)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ dst->cipher_size = src->cipher_size;
|
|
|
6ae9ed |
+ if (VIR_STRDUP(dst->cipher_name, src->cipher_name) < 0 ||
|
|
|
6ae9ed |
+ VIR_STRDUP(dst->cipher_mode, src->cipher_mode) < 0 ||
|
|
|
6ae9ed |
+ VIR_STRDUP(dst->cipher_hash, src->cipher_hash) < 0 ||
|
|
|
6ae9ed |
+ VIR_STRDUP(dst->ivgen_name, src->ivgen_name) < 0 ||
|
|
|
6ae9ed |
+ VIR_STRDUP(dst->ivgen_hash, src->ivgen_hash) < 0)
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return 0;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
virStorageEncryptionPtr
|
|
|
6ae9ed |
virStorageEncryptionCopy(const virStorageEncryption *src)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
@@ -101,6 +131,9 @@ virStorageEncryptionCopy(const virStorageEncryption *src)
|
|
|
6ae9ed |
goto error;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ if (virStorageEncryptionInfoDefCopy(&src->encinfo, &ret->encinfo) < 0)
|
|
|
6ae9ed |
+ goto error;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
return ret;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
error:
|
|
|
6ae9ed |
@@ -154,6 +187,61 @@ virStorageEncryptionSecretParse(xmlXPathContextPtr ctxt,
|
|
|
6ae9ed |
return NULL;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+virStorageEncryptionInfoParseCipher(xmlNodePtr info_node,
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDefPtr info)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ int ret = -1;
|
|
|
6ae9ed |
+ char *size_str = NULL;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!(info->cipher_name = virXMLPropString(info_node, "name"))) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
6ae9ed |
+ _("cipher info missing 'name' attribute"));
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if ((size_str = virXMLPropString(info_node, "size")) &&
|
|
|
6ae9ed |
+ virStrToLong_uip(size_str, NULL, 10, &info->cipher_size) < 0) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_XML_ERROR,
|
|
|
6ae9ed |
+ _("cannot parse cipher size: '%s'"),
|
|
|
6ae9ed |
+ size_str);
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (!size_str) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
6ae9ed |
+ _("cipher info missing 'size' attribute"));
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ info->cipher_mode = virXMLPropString(info_node, "mode");
|
|
|
6ae9ed |
+ info->cipher_hash = virXMLPropString(info_node, "hash");
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ ret = 0;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ cleanup:
|
|
|
6ae9ed |
+ VIR_FREE(size_str);
|
|
|
6ae9ed |
+ return ret;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static int
|
|
|
6ae9ed |
+virStorageEncryptionInfoParseIvgen(xmlNodePtr info_node,
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDefPtr info)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ if (!(info->ivgen_name = virXMLPropString(info_node, "name"))) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
6ae9ed |
+ _("missing ivgen info name string"));
|
|
|
6ae9ed |
+ return -1;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ info->ivgen_hash = virXMLPropString(info_node, "hash");
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ return 0;
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
static virStorageEncryptionPtr
|
|
|
6ae9ed |
virStorageEncryptionParseXML(xmlXPathContextPtr ctxt)
|
|
|
6ae9ed |
{
|
|
|
6ae9ed |
@@ -197,6 +285,28 @@ virStorageEncryptionParseXML(xmlXPathContextPtr ctxt)
|
|
|
6ae9ed |
VIR_FREE(nodes);
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ if (ret->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS) {
|
|
|
6ae9ed |
+ xmlNodePtr tmpnode;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if ((tmpnode = virXPathNode("./cipher[1]", ctxt))) {
|
|
|
6ae9ed |
+ if (virStorageEncryptionInfoParseCipher(tmpnode, &ret->encinfo) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if ((tmpnode = virXPathNode("./ivgen[1]", ctxt))) {
|
|
|
6ae9ed |
+ /* If no cipher node, then fail */
|
|
|
6ae9ed |
+ if (!ret->encinfo.cipher_name) {
|
|
|
6ae9ed |
+ virReportError(VIR_ERR_XML_ERROR, "%s",
|
|
|
6ae9ed |
+ _("ivgen element found, but cipher is missing"));
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (virStorageEncryptionInfoParseIvgen(tmpnode, &ret->encinfo) < 0)
|
|
|
6ae9ed |
+ goto cleanup;
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
return ret;
|
|
|
6ae9ed |
|
|
|
6ae9ed |
cleanup:
|
|
|
6ae9ed |
@@ -251,6 +361,28 @@ virStorageEncryptionSecretFormat(virBufferPtr buf,
|
|
|
6ae9ed |
return 0;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+static void
|
|
|
6ae9ed |
+virStorageEncryptionInfoDefFormat(virBufferPtr buf,
|
|
|
6ae9ed |
+ const virStorageEncryptionInfoDef *enc)
|
|
|
6ae9ed |
+{
|
|
|
6ae9ed |
+ virBufferEscapeString(buf, "<cipher name='%s'", enc->cipher_name);
|
|
|
6ae9ed |
+ virBufferAsprintf(buf, " size='%u'", enc->cipher_size);
|
|
|
6ae9ed |
+ if (enc->cipher_mode)
|
|
|
6ae9ed |
+ virBufferEscapeString(buf, " mode='%s'", enc->cipher_mode);
|
|
|
6ae9ed |
+ if (enc->cipher_hash)
|
|
|
6ae9ed |
+ virBufferEscapeString(buf, " hash='%s'", enc->cipher_hash);
|
|
|
6ae9ed |
+ virBufferAddLit(buf, "/>\n");
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ if (enc->ivgen_name) {
|
|
|
6ae9ed |
+ virBufferEscapeString(buf, "<ivgen name='%s'", enc->ivgen_name);
|
|
|
6ae9ed |
+ if (enc->ivgen_hash)
|
|
|
6ae9ed |
+ virBufferEscapeString(buf, " hash='%s'", enc->ivgen_hash);
|
|
|
6ae9ed |
+ virBufferAddLit(buf, "/>\n");
|
|
|
6ae9ed |
+ }
|
|
|
6ae9ed |
+}
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
int
|
|
|
6ae9ed |
virStorageEncryptionFormat(virBufferPtr buf,
|
|
|
6ae9ed |
virStorageEncryptionPtr enc)
|
|
|
6ae9ed |
@@ -271,6 +403,10 @@ virStorageEncryptionFormat(virBufferPtr buf,
|
|
|
6ae9ed |
return -1;
|
|
|
6ae9ed |
}
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+ if (enc->format == VIR_STORAGE_ENCRYPTION_FORMAT_LUKS &&
|
|
|
6ae9ed |
+ enc->encinfo.cipher_name)
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDefFormat(buf, &enc->encinfo);
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
virBufferAdjustIndent(buf, -2);
|
|
|
6ae9ed |
virBufferAddLit(buf, "</encryption>\n");
|
|
|
6ae9ed |
|
|
|
6ae9ed |
diff --git a/src/util/virstorageencryption.h b/src/util/virstorageencryption.h
|
|
|
6ae9ed |
index 5e1be3b..fa439fb 100644
|
|
|
6ae9ed |
--- a/src/util/virstorageencryption.h
|
|
|
6ae9ed |
+++ b/src/util/virstorageencryption.h
|
|
|
6ae9ed |
@@ -44,6 +44,18 @@ struct _virStorageEncryptionSecret {
|
|
|
6ae9ed |
virSecretLookupTypeDef seclookupdef;
|
|
|
6ae9ed |
};
|
|
|
6ae9ed |
|
|
|
6ae9ed |
+/* It's possible to dictate the cipher and if necessary iv */
|
|
|
6ae9ed |
+typedef struct _virStorageEncryptionInfoDef virStorageEncryptionInfoDef;
|
|
|
6ae9ed |
+typedef virStorageEncryptionInfoDef *virStorageEncryptionInfoDefPtr;
|
|
|
6ae9ed |
+struct _virStorageEncryptionInfoDef {
|
|
|
6ae9ed |
+ unsigned int cipher_size;
|
|
|
6ae9ed |
+ char *cipher_name;
|
|
|
6ae9ed |
+ char *cipher_mode;
|
|
|
6ae9ed |
+ char *cipher_hash;
|
|
|
6ae9ed |
+ char *ivgen_name;
|
|
|
6ae9ed |
+ char *ivgen_hash;
|
|
|
6ae9ed |
+};
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
typedef enum {
|
|
|
6ae9ed |
/* "default" is only valid for volume creation */
|
|
|
6ae9ed |
VIR_STORAGE_ENCRYPTION_FORMAT_DEFAULT = 0,
|
|
|
6ae9ed |
@@ -61,6 +73,8 @@ struct _virStorageEncryption {
|
|
|
6ae9ed |
|
|
|
6ae9ed |
size_t nsecrets;
|
|
|
6ae9ed |
virStorageEncryptionSecretPtr *secrets;
|
|
|
6ae9ed |
+
|
|
|
6ae9ed |
+ virStorageEncryptionInfoDef encinfo;
|
|
|
6ae9ed |
};
|
|
|
6ae9ed |
|
|
|
6ae9ed |
virStorageEncryptionPtr virStorageEncryptionCopy(const virStorageEncryption *src)
|
|
|
6ae9ed |
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-luks-disk-cipher.xml b/tests/qemuxml2argvdata/qemuxml2argv-luks-disk-cipher.xml
|
|
|
6ae9ed |
new file mode 100644
|
|
|
6ae9ed |
index 0000000..9ce15c0
|
|
|
6ae9ed |
--- /dev/null
|
|
|
6ae9ed |
+++ b/tests/qemuxml2argvdata/qemuxml2argv-luks-disk-cipher.xml
|
|
|
6ae9ed |
@@ -0,0 +1,45 @@
|
|
|
6ae9ed |
+<domain type='qemu'>
|
|
|
6ae9ed |
+ <name>encryptdisk</name>
|
|
|
6ae9ed |
+ <uuid>496898a6-e6ff-f7c8-5dc2-3cf410945ee9</uuid>
|
|
|
6ae9ed |
+ <memory unit='KiB'>1048576</memory>
|
|
|
6ae9ed |
+ <currentMemory unit='KiB'>524288</currentMemory>
|
|
|
6ae9ed |
+ <vcpu placement='static'>1</vcpu>
|
|
|
6ae9ed |
+ <os>
|
|
|
6ae9ed |
+ <type arch='x86_64' machine='pc-i440fx-2.1'>hvm</type>
|
|
|
6ae9ed |
+ <boot dev='hd'/>
|
|
|
6ae9ed |
+ </os>
|
|
|
6ae9ed |
+ <clock offset='utc'/>
|
|
|
6ae9ed |
+ <on_poweroff>destroy</on_poweroff>
|
|
|
6ae9ed |
+ <on_reboot>restart</on_reboot>
|
|
|
6ae9ed |
+ <on_crash>destroy</on_crash>
|
|
|
6ae9ed |
+ <devices>
|
|
|
6ae9ed |
+ <emulator>/usr/bin/qemu</emulator>
|
|
|
6ae9ed |
+ <disk type='file' device='disk'>
|
|
|
6ae9ed |
+ <driver name='qemu' type='luks'/>
|
|
|
6ae9ed |
+ <source file='/storage/guest_disks/encryptdisk'/>
|
|
|
6ae9ed |
+ <target dev='vda' bus='virtio'/>
|
|
|
6ae9ed |
+ <encryption format='luks'>
|
|
|
6ae9ed |
+ <secret type='passphrase' uuid='0a81f5b2-8403-7b23-c8d6-21ccc2f80d6f'/>
|
|
|
6ae9ed |
+ </encryption>
|
|
|
6ae9ed |
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x04' function='0x0'/>
|
|
|
6ae9ed |
+ </disk>
|
|
|
6ae9ed |
+ <disk type='file' device='disk'>
|
|
|
6ae9ed |
+ <driver name='qemu' type='luks'/>
|
|
|
6ae9ed |
+ <source file='/storage/guest_disks/encryptdisk2'/>
|
|
|
6ae9ed |
+ <target dev='vdb' bus='virtio'/>
|
|
|
6ae9ed |
+ <encryption format='luks'>
|
|
|
6ae9ed |
+ <secret type='passphrase' usage='mycluster_myname'/>
|
|
|
6ae9ed |
+ </encryption>
|
|
|
6ae9ed |
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x05' function='0x0'/>
|
|
|
6ae9ed |
+ </disk>
|
|
|
6ae9ed |
+ <controller type='usb' index='0'>
|
|
|
6ae9ed |
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x2'/>
|
|
|
6ae9ed |
+ </controller>
|
|
|
6ae9ed |
+ <controller type='pci' index='0' model='pci-root'/>
|
|
|
6ae9ed |
+ <input type='mouse' bus='ps2'/>
|
|
|
6ae9ed |
+ <input type='keyboard' bus='ps2'/>
|
|
|
6ae9ed |
+ <memballoon model='virtio'>
|
|
|
6ae9ed |
+ <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
|
|
|
6ae9ed |
+ </memballoon>
|
|
|
6ae9ed |
+ </devices>
|
|
|
6ae9ed |
+</domain>
|
|
|
6ae9ed |
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disk-cipher.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disk-cipher.xml
|
|
|
6ae9ed |
new file mode 120000
|
|
|
6ae9ed |
index 0000000..fa55233
|
|
|
6ae9ed |
--- /dev/null
|
|
|
6ae9ed |
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-luks-disk-cipher.xml
|
|
|
6ae9ed |
@@ -0,0 +1 @@
|
|
|
6ae9ed |
+../qemuxml2argvdata/qemuxml2argv-luks-disk-cipher.xml
|
|
|
6ae9ed |
\ No newline at end of file
|
|
|
6ae9ed |
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
|
|
|
6ae9ed |
index a757fdb..d00d209 100644
|
|
|
6ae9ed |
--- a/tests/qemuxml2xmltest.c
|
|
|
6ae9ed |
+++ b/tests/qemuxml2xmltest.c
|
|
|
6ae9ed |
@@ -503,6 +503,7 @@ mymain(void)
|
|
|
6ae9ed |
DO_TEST("encrypted-disk");
|
|
|
6ae9ed |
DO_TEST("encrypted-disk-usage");
|
|
|
6ae9ed |
DO_TEST("luks-disks");
|
|
|
6ae9ed |
+ DO_TEST("luks-disk-cipher");
|
|
|
6ae9ed |
DO_TEST("memtune");
|
|
|
6ae9ed |
DO_TEST("memtune-unlimited");
|
|
|
6ae9ed |
DO_TEST("blkiotune");
|
|
|
6ae9ed |
diff --git a/tests/storagevolxml2xmlin/vol-luks-cipher.xml b/tests/storagevolxml2xmlin/vol-luks-cipher.xml
|
|
|
6ae9ed |
new file mode 100644
|
|
|
6ae9ed |
index 0000000..009246f
|
|
|
6ae9ed |
--- /dev/null
|
|
|
6ae9ed |
+++ b/tests/storagevolxml2xmlin/vol-luks-cipher.xml
|
|
|
6ae9ed |
@@ -0,0 +1,23 @@
|
|
|
6ae9ed |
+<volume>
|
|
|
6ae9ed |
+ <name>LuksDemo.img</name>
|
|
|
6ae9ed |
+ <key>/var/lib/libvirt/images/LuksDemo.img</key>
|
|
|
6ae9ed |
+ <source>
|
|
|
6ae9ed |
+ </source>
|
|
|
6ae9ed |
+ <capacity unit="G">5</capacity>
|
|
|
6ae9ed |
+ <allocation>294912</allocation>
|
|
|
6ae9ed |
+ <target>
|
|
|
6ae9ed |
+ <path>/var/lib/libvirt/images/LuksDemo.img</path>
|
|
|
6ae9ed |
+ <format type='luks'/>
|
|
|
6ae9ed |
+ <permissions>
|
|
|
6ae9ed |
+ <mode>0644</mode>
|
|
|
6ae9ed |
+ <owner>0</owner>
|
|
|
6ae9ed |
+ <group>0</group>
|
|
|
6ae9ed |
+ <label>unconfined_u:object_r:virt_image_t:s0</label>
|
|
|
6ae9ed |
+ </permissions>
|
|
|
6ae9ed |
+ <encryption format='luks'>
|
|
|
6ae9ed |
+ <secret type='passphrase' usage='mumblyfratz'/>
|
|
|
6ae9ed |
+ <cipher name='serpent' size='256' mode='cbc' hash='sha256'/>
|
|
|
6ae9ed |
+ <ivgen name='plain64' hash='sha256'/>
|
|
|
6ae9ed |
+ </encryption>
|
|
|
6ae9ed |
+ </target>
|
|
|
6ae9ed |
+</volume>
|
|
|
6ae9ed |
diff --git a/tests/storagevolxml2xmlout/vol-luks-cipher.xml b/tests/storagevolxml2xmlout/vol-luks-cipher.xml
|
|
|
6ae9ed |
new file mode 100644
|
|
|
6ae9ed |
index 0000000..9014849
|
|
|
6ae9ed |
--- /dev/null
|
|
|
6ae9ed |
+++ b/tests/storagevolxml2xmlout/vol-luks-cipher.xml
|
|
|
6ae9ed |
@@ -0,0 +1,23 @@
|
|
|
6ae9ed |
+<volume type='file'>
|
|
|
6ae9ed |
+ <name>LuksDemo.img</name>
|
|
|
6ae9ed |
+ <key>/var/lib/libvirt/images/LuksDemo.img</key>
|
|
|
6ae9ed |
+ <source>
|
|
|
6ae9ed |
+ </source>
|
|
|
6ae9ed |
+ <capacity unit='bytes'>5368709120</capacity>
|
|
|
6ae9ed |
+ <allocation unit='bytes'>294912</allocation>
|
|
|
6ae9ed |
+ <target>
|
|
|
6ae9ed |
+ <path>/var/lib/libvirt/images/LuksDemo.img</path>
|
|
|
6ae9ed |
+ <format type='luks'/>
|
|
|
6ae9ed |
+ <permissions>
|
|
|
6ae9ed |
+ <mode>0644</mode>
|
|
|
6ae9ed |
+ <owner>0</owner>
|
|
|
6ae9ed |
+ <group>0</group>
|
|
|
6ae9ed |
+ <label>unconfined_u:object_r:virt_image_t:s0</label>
|
|
|
6ae9ed |
+ </permissions>
|
|
|
6ae9ed |
+ <encryption format='luks'>
|
|
|
6ae9ed |
+ <secret type='passphrase' usage='mumblyfratz'/>
|
|
|
6ae9ed |
+ <cipher name='serpent' size='256' mode='cbc' hash='sha256'/>
|
|
|
6ae9ed |
+ <ivgen name='plain64' hash='sha256'/>
|
|
|
6ae9ed |
+ </encryption>
|
|
|
6ae9ed |
+ </target>
|
|
|
6ae9ed |
+</volume>
|
|
|
6ae9ed |
diff --git a/tests/storagevolxml2xmltest.c b/tests/storagevolxml2xmltest.c
|
|
|
6ae9ed |
index a36a706..db82bea 100644
|
|
|
6ae9ed |
--- a/tests/storagevolxml2xmltest.c
|
|
|
6ae9ed |
+++ b/tests/storagevolxml2xmltest.c
|
|
|
6ae9ed |
@@ -106,6 +106,7 @@ mymain(void)
|
|
|
6ae9ed |
DO_TEST("pool-dir", "vol-qcow2-0.10-lazy");
|
|
|
6ae9ed |
DO_TEST("pool-dir", "vol-qcow2-nobacking");
|
|
|
6ae9ed |
DO_TEST("pool-dir", "vol-luks");
|
|
|
6ae9ed |
+ DO_TEST("pool-dir", "vol-luks-cipher");
|
|
|
6ae9ed |
DO_TEST("pool-disk", "vol-partition");
|
|
|
6ae9ed |
DO_TEST("pool-logical", "vol-logical");
|
|
|
6ae9ed |
DO_TEST("pool-logical", "vol-logical-backing");
|
|
|
6ae9ed |
--
|
|
|
6ae9ed |
2.9.2
|
|
|
6ae9ed |
|