This converts the qcow2 driver to make use of the QCryptoBlock
APIs for encrypting image content. As well as continued support
for the legacy QCow2 encryption format, the appealing benefit
is that it enables support for the LUKS format inside qcow2.

With the LUKS format it is neccessary to store the LUKS
partition header and key material in the QCow2 file. This
data can be many MB in size, so cannot go into the QCow2
header region directly. Thus the spec is defines a FDE
(Full Disk Encryption) header extension that specifies
the offset of a set of clusters to hold the FDE headers,
as well as the length of that region. The LUKS header is
thus stored in these extra allocated clusters before the
main image payload.

With this change it is now required to use the QCryptoSecret
object for providing passwords, instead of the current block
password APIs / interactive prompting.

  $QEMU \
    -object secret,id=sec0,filename=/home/berrange/encrypted.pw \
    -drive file=/home/berrange/encrypted.qcow2,key-secret=sec0

The new LUKS format is set as the new default format when
creating encrypted images. ie

  # qemu-img create --object secret,data=123456,id=sec0 \
       -f qcow2 -o encryption,key-secret=sec0 \
       test.qcow2 10G

Results in creation of an image using the LUKS format.

For compatibility the old qcow2 AES format can still be used
via the 'encryption-format' parameter which accepts the
values 'luks' or 'qcowaes'.

  # qemu-img create --object secret,data=123456,id=sec0 \
       -f qcow2 -o encryption,key-secret=sec0,encryption-format=qcowaes \
       test.qcow2 10G

Signed-off-by: Daniel P. Berrange <berra...@redhat.com>
---
 block/qcow2-cluster.c      |  46 +----
 block/qcow2-refcount.c     |  10 +
 block/qcow2.c              | 502 ++++++++++++++++++++++++++++++++++++++-------
 block/qcow2.h              |  21 +-
 crypto/block-luks.c        |   1 -
 docs/specs/qcow2.txt       |  74 +++++++
 qapi/block-core.json       |   6 +-
 tests/qemu-iotests/049     |   2 +-
 tests/qemu-iotests/049.out |   7 +-
 tests/qemu-iotests/082.out | 189 +++++++++++++++++
 tests/qemu-iotests/087     |  28 ++-
 tests/qemu-iotests/087.out |  12 +-
 tests/qemu-iotests/134     |  18 +-
 tests/qemu-iotests/134.out |  21 +-
 tests/qemu-iotests/common  |   1 +
 15 files changed, 775 insertions(+), 163 deletions(-)

diff --git a/block/qcow2-cluster.c b/block/qcow2-cluster.c
index f5bc4f2..0512256 100644
--- a/block/qcow2-cluster.c
+++ b/block/qcow2-cluster.c
@@ -341,45 +341,6 @@ static int count_contiguous_clusters_by_type(int 
nb_clusters,
     return i;
 }
 
-int qcow2_encrypt_sectors(BDRVQcow2State *s, int64_t sector_num,
-                          uint8_t *buf, int nb_sectors, bool enc,
-                          Error **errp)
-{
-    union {
-        uint64_t ll[2];
-        uint8_t b[16];
-    } ivec;
-    int i;
-    int ret;
-
-    for(i = 0; i < nb_sectors; i++) {
-        ivec.ll[0] = cpu_to_le64(sector_num);
-        ivec.ll[1] = 0;
-        if (qcrypto_cipher_setiv(s->cipher,
-                                 ivec.b, G_N_ELEMENTS(ivec.b),
-                                 errp) < 0) {
-            return -1;
-        }
-        if (enc) {
-            ret = qcrypto_cipher_encrypt(s->cipher,
-                                         buf, buf,
-                                         512,
-                                         errp);
-        } else {
-            ret = qcrypto_cipher_decrypt(s->cipher,
-                                         buf, buf,
-                                         512,
-                                         errp);
-        }
-        if (ret < 0) {
-            return -1;
-        }
-        sector_num++;
-        buf += 512;
-    }
-    return 0;
-}
-
 static int coroutine_fn copy_sectors(BlockDriverState *bs,
                                      uint64_t start_sect,
                                      uint64_t cluster_offset,
@@ -421,10 +382,9 @@ static int coroutine_fn copy_sectors(BlockDriverState *bs,
 
     if (bs->encrypted) {
         Error *err = NULL;
-        assert(s->cipher);
-        if (qcow2_encrypt_sectors(s, start_sect + n_start,
-                                  iov.iov_base, n,
-                                  true, &err) < 0) {
+        assert(s->crypto);
+        if (qcrypto_block_encrypt(s->crypto, start_sect + n_start,
+                                  iov.iov_base, n, &err) < 0) {
             ret = -EIO;
             error_free(err);
             goto out;
diff --git a/block/qcow2-refcount.c b/block/qcow2-refcount.c
index af493f8..d34d59b 100644
--- a/block/qcow2-refcount.c
+++ b/block/qcow2-refcount.c
@@ -1847,6 +1847,16 @@ static int calculate_refcounts(BlockDriverState *bs, 
BdrvCheckResult *res,
         return ret;
     }
 
+    /* encryption */
+    if (s->crypto_header.length) {
+        ret = inc_refcounts(bs, res, refcount_table, nb_clusters,
+                            s->crypto_header.offset,
+                            s->crypto_header.length);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
     return check_refblocks(bs, res, fix, rebuild, refcount_table, nb_clusters);
 }
 
diff --git a/block/qcow2.c b/block/qcow2.c
index 2fae692..5249ca2 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -34,6 +34,8 @@
 #include "qapi-event.h"
 #include "trace.h"
 #include "qemu/option_int.h"
+#include "qapi/opts-visitor.h"
+#include "qapi-visit.h"
 
 /*
   Differences with QCOW:
@@ -60,6 +62,7 @@ typedef struct {
 #define  QCOW2_EXT_MAGIC_END 0
 #define  QCOW2_EXT_MAGIC_BACKING_FORMAT 0xE2792ACA
 #define  QCOW2_EXT_MAGIC_FEATURE_TABLE 0x6803f857
+#define  QCOW2_EXT_MAGIC_CRYPTO_HEADER 0x4c554b53
 
 static int qcow2_probe(const uint8_t *buf, int buf_size, const char *filename)
 {
@@ -74,6 +77,75 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, 
const char *filename)
 }
 
 
+static ssize_t qcow2_crypto_hdr_read_func(QCryptoBlock *block, size_t offset,
+                                          uint8_t *buf, size_t buflen,
+                                          Error **errp, void *opaque)
+{
+    BlockDriverState *bs = opaque;
+    BDRVQcow2State *s = bs->opaque;
+    ssize_t ret;
+
+    if ((offset + buflen) > s->crypto_header.length) {
+        error_setg(errp, "Request for data outside of extension header");
+        return -1;
+    }
+
+    ret = bdrv_pread(bs->file->bs,
+                     s->crypto_header.offset + offset, buf, buflen);
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "Could not read encryption header");
+        return -1;
+    }
+    return ret;
+}
+
+
+static ssize_t qcow2_crypto_hdr_init_func(QCryptoBlock *block, size_t 
headerlen,
+                                          Error **errp, void *opaque)
+{
+    BlockDriverState *bs = opaque;
+    BDRVQcow2State *s = bs->opaque;
+    int64_t ret;
+
+    s->crypto_header.length = headerlen + (headerlen % s->cluster_size);
+
+    ret = qcow2_alloc_clusters(bs, s->crypto_header.length);
+    if (ret < 0) {
+        s->crypto_header.length = 0;
+        error_setg_errno(errp, -ret,
+                         "Cannot allocate cluster for LUKS header size %zu",
+                         headerlen);
+        return -1;
+    }
+
+    s->crypto_header.offset = ret;
+    return ret;
+}
+
+
+static ssize_t qcow2_crypto_hdr_write_func(QCryptoBlock *block, size_t offset,
+                                           const uint8_t *buf, size_t buflen,
+                                           Error **errp, void *opaque)
+{
+    BlockDriverState *bs = opaque;
+    BDRVQcow2State *s = bs->opaque;
+    ssize_t ret;
+
+    if ((offset + buflen) > s->crypto_header.length) {
+        error_setg(errp, "Request for data outside of extension header");
+        return -1;
+    }
+
+    ret = bdrv_pwrite(bs->file->bs,
+                      s->crypto_header.offset + offset, buf, buflen);
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "Could not read encryption header");
+        return -1;
+    }
+    return ret;
+}
+
+
 /* 
  * read qcow2 extension and fill bs
  * start reading from start_offset
@@ -83,6 +155,7 @@ static int qcow2_probe(const uint8_t *buf, int buf_size, 
const char *filename)
  */
 static int qcow2_read_extensions(BlockDriverState *bs, uint64_t start_offset,
                                  uint64_t end_offset, void **p_feature_table,
+                                 int flags,
                                  Error **errp)
 {
     BDRVQcow2State *s = bs->opaque;
@@ -159,6 +232,39 @@ static int qcow2_read_extensions(BlockDriverState *bs, 
uint64_t start_offset,
             }
             break;
 
+        case QCOW2_EXT_MAGIC_CRYPTO_HEADER: {
+            unsigned int cflags = 0;
+            if (s->crypt_method_header != QCOW_CRYPT_LUKS) {
+                error_setg(errp, "CRYPTO header extension only "
+                           "expected with LUKS encryption method");
+                return -EINVAL;
+            }
+            if (ext.len != sizeof(Qcow2CryptoHeaderExtension)) {
+                error_setg(errp, "CRYPTO header extension size %u, "
+                           "but expected size %zu", ext.len,
+                           sizeof(Qcow2CryptoHeaderExtension));
+                return -EINVAL;
+            }
+
+            ret = bdrv_pread(bs->file->bs, offset, &s->crypto_header, ext.len);
+            if (ret < 0) {
+                error_setg_errno(errp, -ret,
+                                 "Unable to read CRYPTO header extension");
+                return ret;
+            }
+            be64_to_cpu(s->crypto_header.offset);
+            be64_to_cpu(s->crypto_header.length);
+
+            if (flags & BDRV_O_NO_IO) {
+                cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
+            }
+            s->crypto = qcrypto_block_open(s->crypto_opts,
+                                           qcow2_crypto_hdr_read_func,
+                                           bs, cflags, errp);
+            if (!s->crypto) {
+                return -EINVAL;
+            }
+        }   break;
         default:
             /* unknown magic - save it in case we need to rewrite the header */
             {
@@ -472,6 +578,11 @@ static QemuOptsList qcow2_runtime_opts = {
             .type = QEMU_OPT_NUMBER,
             .help = "Clean unused cache entries after this time (in seconds)",
         },
+        {
+            .name = QCOW2_OPT_KEY_SECRET,
+            .type = QEMU_OPT_STRING,
+            .help = "ID of the secret that provides the encryption key",
+        },
         { /* end of list */ }
     },
 };
@@ -589,6 +700,111 @@ static void read_cache_sizes(BlockDriverState *bs, 
QemuOpts *opts,
     }
 }
 
+
+static QCryptoBlockOpenOptions *
+qcow2_crypto_open_opts_init(QCryptoBlockFormat format, QemuOpts *opts,
+                            Error **errp)
+{
+    OptsVisitor *ov;
+    QCryptoBlockOpenOptions *ret;
+    Error *local_err = NULL;
+
+    ret = g_new0(QCryptoBlockOpenOptions, 1);
+    ret->format = format;
+
+    ov = opts_visitor_new(opts);
+
+    switch (format) {
+    case Q_CRYPTO_BLOCK_FORMAT_QCOW:
+        ret->u.qcow = g_new0(QCryptoBlockOptionsQCow, 1);
+        visit_type_QCryptoBlockOptionsQCow(opts_get_visitor(ov),
+                                           &ret->u.qcow,
+                                           "qcow", &local_err);
+        break;
+
+    case Q_CRYPTO_BLOCK_FORMAT_LUKS:
+        ret->u.luks = g_new0(QCryptoBlockOptionsLUKS, 1);
+        visit_type_QCryptoBlockOptionsLUKS(opts_get_visitor(ov),
+                                           &ret->u.luks,
+                                           "luks", &local_err);
+        break;
+
+    default:
+        error_setg(&local_err, "Unsupported block format %d", format);
+        break;
+    }
+
+    if (local_err) {
+        error_propagate(errp, local_err);
+        opts_visitor_cleanup(ov);
+        qapi_free_QCryptoBlockOpenOptions(ret);
+        return NULL;
+    }
+
+    opts_visitor_cleanup(ov);
+    return ret;
+}
+
+
+static QCryptoBlockCreateOptions *
+qcow2_crypto_create_opts_init(QCryptoBlockFormat format, QemuOpts *opts,
+                              Error **errp)
+{
+    OptsVisitor *ov;
+    QCryptoBlockCreateOptions *ret;
+    Error *local_err = NULL, *end_err = NULL;
+    Visitor *v;
+
+    ret = g_new0(QCryptoBlockCreateOptions, 1);
+    ret->format = format;
+
+    ov = opts_visitor_new(opts);
+    v = opts_get_visitor(ov);
+    visit_start_struct(v, NULL, NULL, NULL, 0, &local_err);
+    if (local_err) {
+        goto cleanup;
+    }
+
+    switch (format) {
+    case Q_CRYPTO_BLOCK_FORMAT_QCOW:
+        ret->u.qcow = g_new0(QCryptoBlockOptionsQCow, 1);
+        visit_type_QCryptoBlockOptionsQCow(v, &ret->u.qcow,
+                                           "qcow", &local_err);
+        break;
+
+    case Q_CRYPTO_BLOCK_FORMAT_LUKS:
+        ret->u.luks = g_new0(QCryptoBlockCreateOptionsLUKS, 1);
+        visit_type_QCryptoBlockCreateOptionsLUKS(v, &ret->u.luks,
+                                                 "luks", &local_err);
+        break;
+
+    default:
+        error_setg(&local_err, "Unsupported block format %d", format);
+        break;
+    }
+
+    visit_end_struct(v, &end_err);
+    if (end_err) {
+        if (!local_err) {
+            error_propagate(&local_err, end_err);
+        } else {
+            error_free(end_err);
+        }
+    }
+
+ cleanup:
+    if (local_err) {
+        error_propagate(errp, local_err);
+        qapi_free_QCryptoBlockCreateOptions(ret);
+        ret = NULL;
+        return NULL;
+    }
+
+    opts_visitor_cleanup(ov);
+    return ret;
+}
+
+
 typedef struct Qcow2ReopenState {
     Qcow2Cache *l2_table_cache;
     Qcow2Cache *refcount_block_cache;
@@ -596,6 +812,7 @@ typedef struct Qcow2ReopenState {
     int overlap_check;
     bool discard_passthrough[QCOW2_DISCARD_MAX];
     uint64_t cache_clean_interval;
+    QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
 } Qcow2ReopenState;
 
 static int qcow2_update_options_prepare(BlockDriverState *bs,
@@ -754,6 +971,28 @@ static int qcow2_update_options_prepare(BlockDriverState 
*bs,
     r->discard_passthrough[QCOW2_DISCARD_OTHER] =
         qemu_opt_get_bool(opts, QCOW2_OPT_DISCARD_OTHER, false);
 
+    switch (s->crypt_method_header) {
+    case QCOW_CRYPT_NONE:
+        break;
+
+    case QCOW_CRYPT_AES:
+        r->crypto_opts = qcow2_crypto_open_opts_init(
+            Q_CRYPTO_BLOCK_FORMAT_QCOW, opts, errp);
+        break;
+
+    case QCOW_CRYPT_LUKS:
+        r->crypto_opts = qcow2_crypto_open_opts_init(
+            Q_CRYPTO_BLOCK_FORMAT_LUKS, opts, errp);
+        break;
+
+    default:
+        g_assert_not_reached();
+    }
+    if (s->crypt_method_header && !r->crypto_opts) {
+        ret = -EINVAL;
+        goto fail;
+    }
+
     ret = 0;
 fail:
     qemu_opts_del(opts);
@@ -788,6 +1027,9 @@ static void qcow2_update_options_commit(BlockDriverState 
*bs,
         s->cache_clean_interval = r->cache_clean_interval;
         cache_clean_timer_init(bs, bdrv_get_aio_context(bs));
     }
+
+    qapi_free_QCryptoBlockOpenOptions(s->crypto_opts);
+    s->crypto_opts = r->crypto_opts;
 }
 
 static void qcow2_update_options_abort(BlockDriverState *bs,
@@ -799,6 +1041,7 @@ static void qcow2_update_options_abort(BlockDriverState 
*bs,
     if (r->refcount_block_cache) {
         qcow2_cache_destroy(bs, r->refcount_block_cache);
     }
+    qapi_free_QCryptoBlockOpenOptions(r->crypto_opts);
 }
 
 static int qcow2_update_options(BlockDriverState *bs, QDict *options,
@@ -932,7 +1175,7 @@ static int qcow2_open(BlockDriverState *bs, QDict 
*options, int flags,
     if (s->incompatible_features & ~QCOW2_INCOMPAT_MASK) {
         void *feature_table = NULL;
         qcow2_read_extensions(bs, header.header_length, ext_end,
-                              &feature_table, NULL);
+                              &feature_table, flags, NULL);
         report_unsupported_feature(bs, errp, feature_table,
                                    s->incompatible_features &
                                    ~QCOW2_INCOMPAT_MASK);
@@ -964,20 +1207,10 @@ static int qcow2_open(BlockDriverState *bs, QDict 
*options, int flags,
     s->refcount_max = UINT64_C(1) << (s->refcount_bits - 1);
     s->refcount_max += s->refcount_max - 1;
 
-    if (header.crypt_method > QCOW_CRYPT_AES) {
-        error_setg(errp, "Unsupported encryption method: %" PRIu32,
-                   header.crypt_method);
-        ret = -EINVAL;
-        goto fail;
-    }
-    if (!qcrypto_cipher_supports(QCRYPTO_CIPHER_ALG_AES_128)) {
-        error_setg(errp, "AES cipher not available");
-        ret = -EINVAL;
-        goto fail;
-    }
     s->crypt_method_header = header.crypt_method;
     if (s->crypt_method_header) {
         bs->encrypted = 1;
+        bs->valid_key = 1;
     }
 
     s->l2_bits = s->cluster_bits - 3; /* L2 is always one cluster */
@@ -1104,12 +1337,37 @@ static int qcow2_open(BlockDriverState *bs, QDict 
*options, int flags,
 
     /* read qcow2 extensions */
     if (qcow2_read_extensions(bs, header.header_length, ext_end, NULL,
-        &local_err)) {
+                              flags, &local_err)) {
         error_propagate(errp, local_err);
         ret = -EINVAL;
         goto fail;
     }
 
+    /* qcow2_read_extension may have setup the crypto context
+     * if the crypt method needs a header region, some methods
+     * don't need header extensions, so must check here
+     */
+    if (s->crypt_method_header && !s->crypto) {
+        if (s->crypt_method_header == QCOW_CRYPT_AES) {
+            unsigned int cflags = 0;
+            if (flags & BDRV_O_NO_IO) {
+                cflags |= QCRYPTO_BLOCK_OPEN_NO_IO;
+            }
+            s->crypto = qcrypto_block_open(s->crypto_opts, NULL, NULL,
+                                           cflags, errp);
+            if (!s->crypto) {
+                error_setg(errp, "Could not setup encryption layer");
+                ret = -EINVAL;
+                goto fail;
+            }
+        } else if (!(flags & BDRV_O_NO_IO)) {
+            error_setg(errp, "Missing CRYPTO header for crypt method %d",
+                       s->crypt_method_header);
+            ret = -EINVAL;
+            goto fail;
+        }
+    }
+
     /* read the backing file name */
     if (header.backing_file_offset != 0) {
         len = header.backing_file_size;
@@ -1199,41 +1457,6 @@ static void qcow2_refresh_limits(BlockDriverState *bs, 
Error **errp)
     bs->bl.write_zeroes_alignment = s->cluster_sectors;
 }
 
-static int qcow2_set_key(BlockDriverState *bs, const char *key)
-{
-    BDRVQcow2State *s = bs->opaque;
-    uint8_t keybuf[16];
-    int len, i;
-    Error *err = NULL;
-
-    memset(keybuf, 0, 16);
-    len = strlen(key);
-    if (len > 16)
-        len = 16;
-    /* XXX: we could compress the chars to 7 bits to increase
-       entropy */
-    for(i = 0;i < len;i++) {
-        keybuf[i] = key[i];
-    }
-    assert(bs->encrypted);
-
-    qcrypto_cipher_free(s->cipher);
-    s->cipher = qcrypto_cipher_new(
-        QCRYPTO_CIPHER_ALG_AES_128,
-        QCRYPTO_CIPHER_MODE_CBC,
-        keybuf, G_N_ELEMENTS(keybuf),
-        &err);
-
-    if (!s->cipher) {
-        /* XXX would be nice if errors in this method could
-         * be properly propagate to the caller. Would need
-         * the bdrv_set_key() API signature to be fixed. */
-        error_free(err);
-        return -1;
-    }
-    return 0;
-}
-
 static int qcow2_reopen_prepare(BDRVReopenState *state,
                                 BlockReopenQueue *queue, Error **errp)
 {
@@ -1345,7 +1568,7 @@ static int64_t coroutine_fn 
qcow2_co_get_block_status(BlockDriverState *bs,
     }
 
     if (cluster_offset != 0 && ret != QCOW2_CLUSTER_COMPRESSED &&
-        !s->cipher) {
+        !s->crypto) {
         index_in_cluster = sector_num & (s->cluster_sectors - 1);
         cluster_offset |= (index_in_cluster << BDRV_SECTOR_BITS);
         status |= BDRV_BLOCK_OFFSET_VALID | cluster_offset;
@@ -1395,7 +1618,7 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState 
*bs, int64_t sector_num,
 
         /* prepare next request */
         cur_nr_sectors = remaining_sectors;
-        if (s->cipher) {
+        if (s->crypto) {
             cur_nr_sectors = MIN(cur_nr_sectors,
                 QCOW_MAX_CRYPT_CLUSTERS * s->cluster_sectors);
         }
@@ -1467,7 +1690,7 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState 
*bs, int64_t sector_num,
             }
 
             if (bs->encrypted) {
-                assert(s->cipher);
+                assert(s->crypto);
 
                 /*
                  * For encrypted images, read everything into a temporary
@@ -1501,11 +1724,10 @@ static coroutine_fn int qcow2_co_readv(BlockDriverState 
*bs, int64_t sector_num,
                 goto fail;
             }
             if (bs->encrypted) {
-                assert(s->cipher);
+                assert(s->crypto);
                 Error *err = NULL;
-                if (qcow2_encrypt_sectors(s, sector_num,  cluster_data,
-                                          cur_nr_sectors, false,
-                                          &err) < 0) {
+                if (qcrypto_block_decrypt(s->crypto, sector_num, cluster_data,
+                                          cur_nr_sectors, &err) < 0) {
                     error_free(err);
                     ret = -EIO;
                     goto fail;
@@ -1588,7 +1810,7 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState 
*bs,
 
         if (bs->encrypted) {
             Error *err = NULL;
-            assert(s->cipher);
+            assert(s->crypto);
             if (!cluster_data) {
                 cluster_data = qemu_try_blockalign(bs->file->bs,
                                                    QCOW_MAX_CRYPT_CLUSTERS
@@ -1603,8 +1825,8 @@ static coroutine_fn int qcow2_co_writev(BlockDriverState 
*bs,
                    QCOW_MAX_CRYPT_CLUSTERS * s->cluster_size);
             qemu_iovec_to_buf(&hd_qiov, 0, cluster_data, hd_qiov.size);
 
-            if (qcow2_encrypt_sectors(s, sector_num, cluster_data,
-                                      cur_nr_sectors, true, &err) < 0) {
+            if (qcrypto_block_encrypt(s->crypto, sector_num, cluster_data,
+                                      cur_nr_sectors, &err) < 0) {
                 error_free(err);
                 ret = -EIO;
                 goto fail;
@@ -1715,8 +1937,8 @@ static void qcow2_close(BlockDriverState *bs)
     qcow2_cache_destroy(bs, s->l2_table_cache);
     qcow2_cache_destroy(bs, s->refcount_block_cache);
 
-    qcrypto_cipher_free(s->cipher);
-    s->cipher = NULL;
+    qcrypto_block_free(s->crypto);
+    s->crypto = NULL;
 
     g_free(s->unknown_header_fields);
     cleanup_unknown_header_ext(bs);
@@ -1734,7 +1956,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, 
Error **errp)
 {
     BDRVQcow2State *s = bs->opaque;
     int flags = s->flags;
-    QCryptoCipher *cipher = NULL;
+    QCryptoBlock *crypto = NULL;
     QDict *options;
     Error *local_err = NULL;
     int ret;
@@ -1744,8 +1966,8 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, 
Error **errp)
      * that means we don't have to worry about reopening them here.
      */
 
-    cipher = s->cipher;
-    s->cipher = NULL;
+    crypto = s->crypto;
+    s->crypto = NULL;
 
     qcow2_close(bs);
 
@@ -1769,7 +1991,7 @@ static void qcow2_invalidate_cache(BlockDriverState *bs, 
Error **errp)
         return;
     }
 
-    s->cipher = cipher;
+    s->crypto = crypto;
 }
 
 static size_t header_ext_add(char *buf, uint32_t magic, const void *s,
@@ -1892,6 +2114,22 @@ int qcow2_update_header(BlockDriverState *bs)
         buflen -= ret;
     }
 
+    /* Full disk encryption header pointer extension */
+    if (s->crypto_header.offset != 0) {
+        cpu_to_be64(s->crypto_header.offset);
+        cpu_to_be64(s->crypto_header.length);
+        ret = header_ext_add(buf, QCOW2_EXT_MAGIC_CRYPTO_HEADER,
+                             &s->crypto_header, sizeof(s->crypto_header),
+                             buflen);
+        be64_to_cpu(s->crypto_header.offset);
+        be64_to_cpu(s->crypto_header.length);
+        if (ret < 0) {
+            goto fail;
+        }
+        buf += ret;
+        buflen -= ret;
+    }
+
     /* Feature table */
     Qcow2Feature features[] = {
         {
@@ -1984,6 +2222,77 @@ static int qcow2_change_backing_file(BlockDriverState 
*bs,
     return qcow2_update_header(bs);
 }
 
+
+static int qcow2_change_encryption(BlockDriverState *bs, QemuOpts *opts,
+                                   Error **errp)
+{
+    BDRVQcow2State *s = bs->opaque;
+    const char *cryptostr;
+    QCryptoBlockCreateOptions *cryptoopts = NULL;
+    QCryptoBlock *crypto = NULL;
+    size_t i;
+    int ret = -EINVAL;
+
+    /* Default to LUKS if crypto-format is not set */
+    cryptostr = qemu_opt_get_del(opts, QCOW2_OPT_CRYPTO_FORMAT);
+    if (cryptostr) {
+        for (i = 0; i < Q_CRYPTO_BLOCK_FORMAT__MAX; i++) {
+            if (g_str_equal(QCryptoBlockFormat_lookup[i], cryptostr)) {
+                cryptoopts = qcow2_crypto_create_opts_init(i, opts, errp);
+                if (!cryptoopts) {
+                    ret = -EINVAL;
+                    goto out;
+                }
+                break;
+            }
+        }
+        if (!cryptoopts) {
+            error_setg(errp, "Unknown crypto format %s", cryptostr);
+            ret = -EINVAL;
+            goto out;
+        }
+    } else {
+        cryptoopts = qcow2_crypto_create_opts_init(
+            Q_CRYPTO_BLOCK_FORMAT_LUKS, opts, errp);
+        if (!cryptoopts) {
+            ret = -EINVAL;
+            goto out;
+        }
+    }
+    switch (cryptoopts->format) {
+    case Q_CRYPTO_BLOCK_FORMAT_QCOW:
+        s->crypt_method_header = QCOW_CRYPT_AES;
+        break;
+    case Q_CRYPTO_BLOCK_FORMAT_LUKS:
+        s->crypt_method_header = QCOW_CRYPT_LUKS;
+        break;
+    default:
+        error_setg(errp, "Unsupported crypto format %s", cryptostr);
+        ret = -EINVAL;
+        goto out;
+    }
+
+    crypto = qcrypto_block_create(cryptoopts,
+                                  qcow2_crypto_hdr_init_func,
+                                  qcow2_crypto_hdr_write_func,
+                                  bs, errp);
+    if (!crypto) {
+        ret = -EINVAL;
+        goto out;
+    }
+
+    ret = qcow2_update_header(bs);
+    if (ret < 0) {
+        error_setg_errno(errp, -ret, "Could not write encryption header");
+        goto out;
+    }
+
+ out:
+    qapi_free_QCryptoBlockCreateOptions(cryptoopts);
+    return ret;
+}
+
+
 static int preallocate(BlockDriverState *bs)
 {
     uint64_t nb_sectors;
@@ -2177,11 +2486,8 @@ static int qcow2_create2(const char *filename, int64_t 
total_size,
         .header_length              = cpu_to_be32(sizeof(*header)),
     };
 
-    if (flags & BLOCK_FLAG_ENCRYPT) {
-        header->crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
-    } else {
-        header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
-    }
+    /* We'll update this to correct value later */
+    header->crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
 
     if (flags & BLOCK_FLAG_LAZY_REFCOUNTS) {
         header->compatible_features |=
@@ -2252,6 +2558,14 @@ static int qcow2_create2(const char *filename, int64_t 
total_size,
         }
     }
 
+    /* Want encryption? There you go. */
+    if (flags & BLOCK_FLAG_ENCRYPT) {
+        ret = qcow2_change_encryption(bs, opts, errp);
+        if (ret < 0) {
+            goto out;
+        }
+    }
+
     /* And if we're supposed to preallocate metadata, do that now */
     if (prealloc != PREALLOC_MODE_OFF) {
         BDRVQcow2State *s = bs->opaque;
@@ -2267,11 +2581,17 @@ static int qcow2_create2(const char *filename, int64_t 
total_size,
     bdrv_unref(bs);
     bs = NULL;
 
-    /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning */
+    /* Reopen the image without BDRV_O_NO_FLUSH to flush it before returning
+     * Using BDRV_O_NO_IO, since encryption is now setup we don't want to
+     * have to setup decryption context. We're not doing any I/O on the top
+     * level BlockDriverState, only lower layers, where BDRV_O_NO_IO does
+     * not have effect.
+     */
     options = qdict_new();
     qdict_put(options, "driver", qstring_from_str("qcow2"));
     ret = bdrv_open(&bs, filename, NULL, options,
-                    BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING,
+                    BDRV_O_RDWR | BDRV_O_CACHE_WB | BDRV_O_NO_BACKING |
+                    BDRV_O_NO_IO, /* Don't want to activate encryption */
                     &local_err);
     if (local_err) {
         error_propagate(errp, local_err);
@@ -3046,9 +3366,9 @@ static int qcow2_amend_options(BlockDriverState *bs, 
QemuOpts *opts,
             backing_format = qemu_opt_get(opts, BLOCK_OPT_BACKING_FMT);
         } else if (!strcmp(desc->name, BLOCK_OPT_ENCRYPT)) {
             encrypt = qemu_opt_get_bool(opts, BLOCK_OPT_ENCRYPT,
-                                        !!s->cipher);
+                                        !!s->crypto);
 
-            if (encrypt != !!s->cipher) {
+            if (encrypt != !!s->crypto) {
                 error_report("Changing the encryption flag is not supported");
                 return -ENOTSUP;
             }
@@ -3284,6 +3604,41 @@ static QemuOptsList qcow2_create_opts = {
             .help = "Width of a reference count entry in bits",
             .def_value_str = "16"
         },
+        {
+            .name = QCOW2_OPT_CRYPTO_FORMAT,
+            .type = QEMU_OPT_STRING,
+            .help = "Encryption format, 'luks' (default), 'qcow' (deprecated)",
+        },
+        {
+            .name = QCOW2_OPT_KEY_SECRET,
+            .type = QEMU_OPT_STRING,
+            .help = "ID of the secret that provides the encryption key",
+        },
+        {
+            .name = QCOW2_OPT_CIPHER_ALG,
+            .type = QEMU_OPT_STRING,
+            .help = "Name of encryption cipher algorithm",
+        },
+        {
+            .name = QCOW2_OPT_CIPHER_MODE,
+            .type = QEMU_OPT_STRING,
+            .help = "Name of encryption cipher mode",
+        },
+        {
+            .name = QCOW2_OPT_IVGEN_ALG,
+            .type = QEMU_OPT_STRING,
+            .help = "Name of IV generator algorithm",
+        },
+        {
+            .name = QCOW2_OPT_IVGEN_HASH_ALG,
+            .type = QEMU_OPT_STRING,
+            .help = "Name of IV generator hash algorithm",
+        },
+        {
+            .name = QCOW2_OPT_HASH_ALG,
+            .type = QEMU_OPT_STRING,
+            .help = "Name of encryption hash algorithm",
+        },
         { /* end of list */ }
     }
 };
@@ -3301,7 +3656,6 @@ BlockDriver bdrv_qcow2 = {
     .bdrv_create        = qcow2_create,
     .bdrv_has_zero_init = bdrv_has_zero_init_1,
     .bdrv_co_get_block_status = qcow2_co_get_block_status,
-    .bdrv_set_key       = qcow2_set_key,
 
     .bdrv_co_readv          = qcow2_co_readv,
     .bdrv_co_writev         = qcow2_co_writev,
diff --git a/block/qcow2.h b/block/qcow2.h
index ae04285..e1f0b5b 100644
--- a/block/qcow2.h
+++ b/block/qcow2.h
@@ -25,7 +25,7 @@
 #ifndef BLOCK_QCOW2_H
 #define BLOCK_QCOW2_H
 
-#include "crypto/cipher.h"
+#include "crypto/block.h"
 #include "qemu/coroutine.h"
 
 //#define DEBUG_ALLOC
@@ -36,6 +36,7 @@
 
 #define QCOW_CRYPT_NONE 0
 #define QCOW_CRYPT_AES  1
+#define QCOW_CRYPT_LUKS 2
 
 #define QCOW_MAX_CRYPT_CLUSTERS 32
 #define QCOW_MAX_SNAPSHOTS 65536
@@ -98,6 +99,15 @@
 #define QCOW2_OPT_REFCOUNT_CACHE_SIZE "refcount-cache-size"
 #define QCOW2_OPT_CACHE_CLEAN_INTERVAL "cache-clean-interval"
 
+#define QCOW2_OPT_CRYPTO_FORMAT "encryption-format"
+#define QCOW2_OPT_KEY_SECRET "key-secret"
+#define QCOW2_OPT_CIPHER_ALG "cipher-alg"
+#define QCOW2_OPT_CIPHER_MODE "cipher-mode"
+#define QCOW2_OPT_IVGEN_ALG "ivgen-alg"
+#define QCOW2_OPT_IVGEN_HASH_ALG "ivgen-hash-alg"
+#define QCOW2_OPT_HASH_ALG "hash-alg"
+
+
 typedef struct QCowHeader {
     uint32_t magic;
     uint32_t version;
@@ -163,6 +173,11 @@ typedef struct QCowSnapshot {
 struct Qcow2Cache;
 typedef struct Qcow2Cache Qcow2Cache;
 
+typedef struct Qcow2CryptoHeaderExtension {
+    uint64_t offset;
+    uint64_t length;
+} QEMU_PACKED Qcow2CryptoHeaderExtension;
+
 typedef struct Qcow2UnknownHeaderExtension {
     uint32_t magic;
     uint32_t len;
@@ -256,7 +271,9 @@ typedef struct BDRVQcow2State {
 
     CoMutex lock;
 
-    QCryptoCipher *cipher; /* current cipher, NULL if no key yet */
+    Qcow2CryptoHeaderExtension crypto_header; /* QCow2 header extension */
+    QCryptoBlockOpenOptions *crypto_opts; /* Disk encryption runtime options */
+    QCryptoBlock *crypto; /* Disk encryption format driver */
     uint32_t crypt_method_header;
     uint64_t snapshots_offset;
     int snapshots_size;
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 47630ee..2f4b983 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -990,7 +990,6 @@ qcrypto_block_luks_create(QCryptoBlock *block,
         cpu_to_be32s(&luks->header.key_slots[i].stripes);
     }
 
-
     /* Write out the partition header and key slot headers */
     writefunc(block, 0,
               (const uint8_t *)&luks->header,
diff --git a/docs/specs/qcow2.txt b/docs/specs/qcow2.txt
index f236d8c..4d141a6 100644
--- a/docs/specs/qcow2.txt
+++ b/docs/specs/qcow2.txt
@@ -45,6 +45,7 @@ The first cluster of a qcow2 image contains the file header:
          32 - 35:   crypt_method
                     0 for no encryption
                     1 for AES encryption
+                    2 for LUKS encryption
 
          36 - 39:   l1_size
                     Number of entries in the active L1 table
@@ -123,6 +124,7 @@ be stored. Each extension has a structure like the 
following:
                         0x00000000 - End of the header extension area
                         0xE2792ACA - Backing file format name
                         0x6803f857 - Feature name table
+                        0x4c554b53 - Full disk encryption header pointer
                         other      - Unknown header extension, can be safely
                                      ignored
 
@@ -166,6 +168,78 @@ the header extension data. Each entry look like this:
                     terminated if it has full length)
 
 
+== Full disk encryption header pointer ==
+
+The full disk encryption header must be present if, and only if, the
+'crypt_method' header requires metadata. Currently this is only true
+of the 'LUKS' crypt method. The header extension must be absent for
+other methods.
+
+This header provides the offset at which the crypt method can store
+its additional data, as well as the length of such data.
+
+    Byte  0 -  7:   Offset into the image file at which the encryption
+                    header starts. Must be aligned to a cluster boundary.
+    Byte  8 - 16:   Length of the encryption header. Must be a multiple
+                    of the cluster size.
+
+While the header extension allocates the length as a multiple of the
+cluster size, the encryption header may not consume the full permitted
+allocation.
+
+For the LUKS crypt method, the encryption header works as follows.
+
+The first 592 bytes of the header clusters will contain the LUKS
+partition header. This is then followed by the key material data areas.
+The size of the key material data areas is determined by the number of
+stripes in the key slot and key size. Refer to the LUKS format
+specification ('docs/on-disk-format.pdf' in the cryptsetup source
+package) for details of the LUKS partition header format.
+
+In the LUKS partition header, the "payload-offset" field does not refer
+to the offset of the QCow2 payload. Instead it simply refers to the
+total required length of the LUKS header plus key material regions.
+
+In the LUKS key slots header, the "key-material-offset" is relative
+to the start of the LUKS header clusters in the qcow2 container,
+not the start of the qcow2 file.
+
+Logically the layout looks like
+
+  +-----------------------------+
+  | QCow2 header                |
+  +-----------------------------+
+  | QCow2 header extension X    |
+  +-----------------------------+
+  | QCow2 header extension FDE  |
+  +-----------------------------+
+  | QCow2 header extension ...  |
+  +-----------------------------+
+  | QCow2 header extension Z    |
+  +-----------------------------+
+  | ....other QCow2 tables....  |
+  .                             .
+  .                             .
+  +-----------------------------+
+  | +-------------------------+ |
+  | | LUKS partition header   | |
+  | +-------------------------+ |
+  | | LUKS key material 1     | |
+  | +-------------------------+ |
+  | | LUKS key material 2     | |
+  | +-------------------------+ |
+  | | LUKS key material ...   | |
+  | +-------------------------+ |
+  | | LUKS key material 8     | |
+  | +-------------------------+ |
+  +-----------------------------+
+  | QCow2 cluster payload       |
+  .                             .
+  .                             .
+  .                             .
+  |                             |
+  +-----------------------------+
+
 == Host cluster management ==
 
 qcow2 manages the allocation of host clusters by maintaining a reference count
diff --git a/qapi/block-core.json b/qapi/block-core.json
index a194658..b704dd7 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -1789,6 +1789,8 @@
 # @cache-clean-interval:  #optional clean unused entries in the L2 and refcount
 #                         caches. The interval is in seconds. The default value
 #                         is 0 and it disables this feature (since 2.5)
+# @key-secret:            #optional the ID of a QCryptoSecret object providing
+#                         the decryption key (since 2.6)
 #
 # Since: 1.7
 ##
@@ -1802,8 +1804,8 @@
             '*cache-size': 'int',
             '*l2-cache-size': 'int',
             '*refcount-cache-size': 'int',
-            '*cache-clean-interval': 'int' } }
-
+            '*cache-clean-interval': 'int',
+            '*key-secret': 'str' } }
 
 ##
 # @BlockdevOptionsArchipelago
diff --git a/tests/qemu-iotests/049 b/tests/qemu-iotests/049
index 93aa0ea..765b950 100755
--- a/tests/qemu-iotests/049
+++ b/tests/qemu-iotests/049
@@ -107,7 +107,7 @@ test_qemu_img create -f $IMGFMT -o preallocation=1234 
"$TEST_IMG" 64M
 echo "== Check encryption option =="
 echo
 test_qemu_img create -f $IMGFMT -o encryption=off "$TEST_IMG" 64M
-test_qemu_img create -f $IMGFMT -o encryption=on "$TEST_IMG" 64M
+test_qemu_img create -f $IMGFMT --object secret,id=sec0,data=123456 -o 
encryption=on,key-secret=sec0 "$TEST_IMG" 64M
 
 echo "== Check lazy_refcounts option (only with v3) =="
 echo
diff --git a/tests/qemu-iotests/049.out b/tests/qemu-iotests/049.out
index a2b6703..c9f0bc5 100644
--- a/tests/qemu-iotests/049.out
+++ b/tests/qemu-iotests/049.out
@@ -186,14 +186,11 @@ Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 
encryption=off cluster_si
 qemu-img create -f qcow2 -o encryption=off TEST_DIR/t.qcow2 64M
 Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=off 
cluster_size=65536 lazy_refcounts=off refcount_bits=16
 
-qemu-img create -f qcow2 -o encryption=on TEST_DIR/t.qcow2 64M
+qemu-img create -f qcow2 --object secret,id=sec0,data=123456 -o 
encryption=on,key-secret=sec0 TEST_DIR/t.qcow2 64M
 qemu-img: Encrypted images are deprecated
 Support for them will be removed in a future release.
 You can use 'qemu-img convert' to convert your image to an unencrypted one.
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
-Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on 
cluster_size=65536 lazy_refcounts=off refcount_bits=16
+Formatting 'TEST_DIR/t.qcow2', fmt=qcow2 size=67108864 encryption=on 
cluster_size=65536 lazy_refcounts=off refcount_bits=16 key-secret=sec0
 
 == Check lazy_refcounts option (only with v3) ==
 
diff --git a/tests/qemu-iotests/082.out b/tests/qemu-iotests/082.out
index a952330..b0572d4 100644
--- a/tests/qemu-iotests/082.out
+++ b/tests/qemu-iotests/082.out
@@ -53,6 +53,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o ? TEST_DIR/t.qcow2 128M
@@ -66,6 +73,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 128M
@@ -79,6 +93,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 128M
@@ -92,6 +113,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 128M
@@ -105,6 +133,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 128M
@@ -118,6 +153,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 128M
@@ -131,6 +173,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 128M
@@ -144,6 +193,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: create -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help 
TEST_DIR/t.qcow2 128M
@@ -172,6 +228,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 
 Testing: create -o help
 Supported options:
@@ -234,6 +297,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o ? TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
@@ -247,6 +317,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2 
TEST_DIR/t.qcow2.base
@@ -260,6 +337,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2 
TEST_DIR/t.qcow2.base
@@ -273,6 +357,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2 
TEST_DIR/t.qcow2.base
@@ -286,6 +377,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2 
TEST_DIR/t.qcow2.base
@@ -299,6 +397,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2 
TEST_DIR/t.qcow2.base
@@ -312,6 +417,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2 
TEST_DIR/t.qcow2.base
@@ -325,6 +437,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: convert -O qcow2 -o backing_file=TEST_DIR/t.qcow2,,help 
TEST_DIR/t.qcow2 TEST_DIR/t.qcow2.base
@@ -353,6 +472,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 
 Testing: convert -o help
 Supported options:
@@ -412,6 +538,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o ? TEST_DIR/t.qcow2
@@ -425,6 +558,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o cluster_size=4k,help TEST_DIR/t.qcow2
@@ -438,6 +578,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o cluster_size=4k,? TEST_DIR/t.qcow2
@@ -451,6 +598,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o help,cluster_size=4k TEST_DIR/t.qcow2
@@ -464,6 +618,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o ?,cluster_size=4k TEST_DIR/t.qcow2
@@ -477,6 +638,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o cluster_size=4k -o help TEST_DIR/t.qcow2
@@ -490,6 +658,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o cluster_size=4k -o ? TEST_DIR/t.qcow2
@@ -503,6 +678,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 nocow            Turn off copy-on-write (valid only on btrfs)
 
 Testing: amend -f qcow2 -o backing_file=TEST_DIR/t.qcow2,,help TEST_DIR/t.qcow2
@@ -533,6 +715,13 @@ cluster_size     qcow2 cluster size
 preallocation    Preallocation mode (allowed values: off, metadata, falloc, 
full)
 lazy_refcounts   Postpone refcount updates
 refcount_bits    Width of a reference count entry in bits
+encryption-format Encryption format, 'luks' (default), 'qcow' (deprecated)
+key-secret       ID of the secret that provides the encryption key
+cipher-alg       Name of encryption cipher algorithm
+cipher-mode      Name of encryption cipher mode
+ivgen-alg        Name of IV generator algorithm
+ivgen-hash-alg   Name of IV generator hash algorithm
+hash-alg         Name of encryption hash algorithm
 
 Testing: convert -o help
 Supported options:
diff --git a/tests/qemu-iotests/087 b/tests/qemu-iotests/087
index af44299..3386668 100755
--- a/tests/qemu-iotests/087
+++ b/tests/qemu-iotests/087
@@ -184,9 +184,18 @@ echo
 echo === Encrypted image ===
 echo
 
-_make_test_img -o encryption=on $size
+_make_test_img --object secret,id=sec0,data=123456 -o 
encryption=on,key-secret=sec0 $size
 run_qemu -S <<EOF
 { "execute": "qmp_capabilities" }
+{ "execute": "object-add",
+  "arguments": {
+      "qom-type": "secret",
+      "id": "sec0",
+      "props": {
+          "data": "123456"
+      }
+  }
+}
 { "execute": "blockdev-add",
   "arguments": {
       "options": {
@@ -195,7 +204,8 @@ run_qemu -S <<EOF
         "file": {
             "driver": "file",
             "filename": "$TEST_IMG"
-        }
+        },
+        "key-secret": "sec0"
       }
     }
   }
@@ -204,6 +214,15 @@ EOF
 
 run_qemu <<EOF
 { "execute": "qmp_capabilities" }
+{ "execute": "object-add",
+  "arguments": {
+      "qom-type": "secret",
+      "id": "sec0",
+      "props": {
+          "data": "123456"
+      }
+  }
+}
 { "execute": "blockdev-add",
   "arguments": {
       "options": {
@@ -212,7 +231,8 @@ run_qemu <<EOF
         "file": {
             "driver": "file",
             "filename": "$TEST_IMG"
-        }
+        },
+        "key-secret": "sec0"
       }
     }
   }
@@ -223,7 +243,7 @@ echo
 echo === Missing driver ===
 echo
 
-_make_test_img -o encryption=on $size
+_make_test_img --object secret,id=sec0,data=123456 -o 
encryption=on,key-secret=sec0 $size
 run_qemu -S <<EOF
 { "execute": "qmp_capabilities" }
 { "execute": "blockdev-add",
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index 7d62cd5..5fc4823 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -41,13 +41,11 @@ QMP_VERSION
 qemu-img: Encrypted images are deprecated
 Support for them will be removed in a future release.
 You can use 'qemu-img convert' to convert your image to an unencrypted one.
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on 
key-secret=sec0
 Testing: -S
 QMP_VERSION
 {"return": {}}
+{"return": {}}
 Encrypted images are deprecated
 Support for them will be removed in a future release.
 You can use 'qemu-img convert' to convert your image to an unencrypted one.
@@ -58,6 +56,7 @@ You can use 'qemu-img convert' to convert your image to an 
unencrypted one.
 Testing:
 QMP_VERSION
 {"return": {}}
+{"return": {}}
 Encrypted images are deprecated
 Support for them will be removed in a future release.
 You can use 'qemu-img convert' to convert your image to an unencrypted one.
@@ -71,10 +70,7 @@ You can use 'qemu-img convert' to convert your image to an 
unencrypted one.
 qemu-img: Encrypted images are deprecated
 Support for them will be removed in a future release.
 You can use 'qemu-img convert' to convert your image to an unencrypted one.
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on 
key-secret=sec0
 Testing: -S
 QMP_VERSION
 {"return": {}}
diff --git a/tests/qemu-iotests/134 b/tests/qemu-iotests/134
index 1c3820b..e0d634e 100755
--- a/tests/qemu-iotests/134
+++ b/tests/qemu-iotests/134
@@ -44,23 +44,31 @@ _supported_os Linux
 
 
 size=128M
-IMGOPTS="encryption=on" _make_test_img $size
+
+SECRET="secret,id=sec0,data=astrochicken"
+SECRETALT="secret,id=sec0,data=platypus"
+
+_make_test_img --object $SECRET -o "encryption=on,key-secret=sec0" $size
+
+IMGSPEC="driver=$IMGFMT,file=$TEST_IMG,key-secret=sec0"
+
+QEMU_IO_OPTIONS=$QEMU_IO_OPTIONS_NO_FMT
 
 echo
 echo "== reading whole image =="
-echo "astrochicken" | $QEMU_IO -c "read 0 $size" "$TEST_IMG" | _filter_qemu_io 
| _filter_testdir
+$QEMU_IO --object $SECRET --image-opts -c "read 0 $size" $IMGSPEC | 
_filter_qemu_io | _filter_testdir
 
 echo
 echo "== rewriting whole image =="
-echo "astrochicken" | $QEMU_IO -c "write -P 0xa 0 $size" "$TEST_IMG" | 
_filter_qemu_io | _filter_testdir
+$QEMU_IO --object $SECRET --image-opts -c "write -P 0xa 0 $size" $IMGSPEC | 
_filter_qemu_io | _filter_testdir
 
 echo
 echo "== verify pattern =="
-echo "astrochicken" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | 
_filter_qemu_io | _filter_testdir
+$QEMU_IO --object $SECRET --image-opts -c "read -P 0xa 0 $size" $IMGSPEC | 
_filter_qemu_io | _filter_testdir
 
 echo
 echo "== verify pattern failure with wrong password =="
-echo "platypus" | $QEMU_IO -c "read -P 0xa 0 $size" "$TEST_IMG" | 
_filter_qemu_io | _filter_testdir
+$QEMU_IO --object $SECRETALT --image-opts -c "read -P 0xa 0 $size" $IMGSPEC | 
_filter_qemu_io | _filter_testdir
 
 
 # success, all done
diff --git a/tests/qemu-iotests/134.out b/tests/qemu-iotests/134.out
index a16acb8..e9bf302 100644
--- a/tests/qemu-iotests/134.out
+++ b/tests/qemu-iotests/134.out
@@ -2,17 +2,12 @@ QA output created by 134
 qemu-img: Encrypted images are deprecated
 Support for them will be removed in a future release.
 You can use 'qemu-img convert' to convert your image to an unencrypted one.
-qemu-img: Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
-Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on
+Formatting 'TEST_DIR/t.IMGFMT', fmt=IMGFMT size=134217728 encryption=on 
key-secret=sec0
 
 == reading whole image ==
 Encrypted images are deprecated
 Support for them will be removed in a future release.
 You can use 'qemu-img convert' to convert your image to an unencrypted one.
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
-password:
 read 134217728/134217728 bytes at offset 0
 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
@@ -20,8 +15,6 @@ read 134217728/134217728 bytes at offset 0
 Encrypted images are deprecated
 Support for them will be removed in a future release.
 You can use 'qemu-img convert' to convert your image to an unencrypted one.
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
-password:
 wrote 134217728/134217728 bytes at offset 0
 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
@@ -29,18 +22,10 @@ wrote 134217728/134217728 bytes at offset 0
 Encrypted images are deprecated
 Support for them will be removed in a future release.
 You can use 'qemu-img convert' to convert your image to an unencrypted one.
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
-password:
 read 134217728/134217728 bytes at offset 0
 128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 
 == verify pattern failure with wrong password ==
-Encrypted images are deprecated
-Support for them will be removed in a future release.
-You can use 'qemu-img convert' to convert your image to an unencrypted one.
-Disk image 'TEST_DIR/t.qcow2' is encrypted.
-password:
-Pattern verification failed at offset 0, 134217728 bytes
-read 134217728/134217728 bytes at offset 0
-128 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
+can't open device 
/home/berrange/src/virt/qemu/tests/qemu-iotests/scratch/t.qcow2: Invalid 
password, cannot unlock any keyslot
+no file open, try 'help open'
 *** done
diff --git a/tests/qemu-iotests/common b/tests/qemu-iotests/common
index ff84f4b..f65d04c 100644
--- a/tests/qemu-iotests/common
+++ b/tests/qemu-iotests/common
@@ -398,6 +398,7 @@ BEGIN        { for (t='$start'; t<='$end'; t++) printf 
"%03d\n",t }' \
 done
 
 # Set qemu-io cache mode with $CACHEMODE we have
+QEMU_IO_OPTIONS_NO_FMT="$QEMU_IO_OPTIONS --cache $CACHEMODE"
 QEMU_IO_OPTIONS="$QEMU_IO_OPTIONS -f $IMGFMT --cache $CACHEMODE"
 
 # Set default options for qemu-img create -o if they were not specified
-- 
2.5.0


Reply via email to