render / rpms / libvirt

Forked from rpms/libvirt 10 months ago
Clone
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
     

Examples

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