The qemu-img info command has the ability to expose format
specific metadata about volumes. Wire up this facility for
the LUKS driver to report on cipher configuration and key
slot usage.

    $ qemu-img info ~/VirtualMachines/demo.luks
    image: /home/berrange/VirtualMachines/demo.luks
    file format: luks
    virtual size: 98M (102760448 bytes)
    disk size: 100M
    encrypted: yes
    Format specific information:
        ivgen alg: plain64
        hash alg: sha1
        cipher alg: aes-128
        uuid: 6ddee74b-3a22-408c-8909-6789d4fa2594
        cipher mode: xts
        slots:
            [0]:
                active: true
                iters: 572706
                key offset: 8
                stripes: 4000
            [1]:
                active: false
                iters: 0
                key offset: 264
                stripes: 4000
            [2]:
                active: false
                iters: 0
                key offset: 520
                stripes: 4000
            [3]:
                active: false
                iters: 0
                key offset: 776
                stripes: 4000
            [4]:
                active: false
                iters: 0
                key offset: 1032
                stripes: 4000
            [5]:
                active: false
                iters: 0
                key offset: 1288
                stripes: 4000
            [6]:
                active: false
                iters: 0
                key offset: 1544
                stripes: 4000
            [7]:
                active: false
                iters: 0
                key offset: 1800
                stripes: 4000
        payload offset: 2097152
        master key iters: 142375

One somewhat undesirable artifact is that the data fields are
printed out in (apparantly) random order. This will be addressed
later by changing the way the block layer pretty-prints the
image specific data.

Signed-off-by: Daniel P. Berrange <berra...@redhat.com>
---
 block/crypto.c       | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 qapi/block-core.json | 34 +++++++++++++++++++++-
 2 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/block/crypto.c b/block/crypto.c
index 758e14e..6f12c4d 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -565,6 +565,84 @@ static int block_crypto_create_luks(const char *filename,
                                        filename, opts, errp);
 }
 
+static int block_crypto_get_info_luks(BlockDriverState *bs,
+                                      BlockDriverInfo *bdi)
+{
+    BlockDriverInfo subbdi;
+    int ret;
+
+    ret = bdrv_get_info(bs->file->bs, &subbdi);
+    if (ret != 0) {
+        return ret;
+    }
+
+    bdi->unallocated_blocks_are_zero = false;
+    bdi->can_write_zeroes_with_unmap = false;
+    bdi->cluster_size = subbdi.cluster_size;
+
+    return 0;
+}
+
+static ImageInfoSpecific *
+block_crypto_get_specific_info_luks(BlockDriverState *bs)
+{
+    BlockCrypto *crypto = bs->opaque;
+    ImageInfoSpecific *spec_info;
+    QCryptoBlockInfo *info;
+    QCryptoBlockInfoLUKSSlot *luks_slot;
+    QCryptoBlockInfoLUKSSlotList *luks_slots;
+    ImageInfoSpecificLUKSSlot *slot;
+    ImageInfoSpecificLUKSSlotList *slots, *prev = NULL;
+
+    info = qcrypto_block_get_info(crypto->block, NULL);
+    if (!info) {
+        return NULL;
+    }
+    if (info->format != Q_CRYPTO_BLOCK_FORMAT_LUKS) {
+        qapi_free_QCryptoBlockInfo(info);
+        return NULL;
+    }
+
+    spec_info = g_new(ImageInfoSpecific, 1);
+    spec_info->type =  IMAGE_INFO_SPECIFIC_KIND_LUKS;
+    spec_info->u.luks.data = g_new(ImageInfoSpecificLUKS, 1);
+    spec_info->u.luks.data->cipher_alg = info->u.luks.cipher_alg;
+    spec_info->u.luks.data->cipher_mode = info->u.luks.cipher_mode;
+    spec_info->u.luks.data->ivgen_alg = info->u.luks.ivgen_alg;
+    spec_info->u.luks.data->has_ivgen_hash_alg =
+        info->u.luks.has_ivgen_hash_alg;
+    spec_info->u.luks.data->ivgen_hash_alg = info->u.luks.ivgen_hash_alg;
+    spec_info->u.luks.data->hash_alg = info->u.luks.hash_alg;
+    spec_info->u.luks.data->payload_offset = info->u.luks.payload_offset;
+    spec_info->u.luks.data->master_key_iters = info->u.luks.master_key_iters;
+    spec_info->u.luks.data->uuid = g_strdup(info->u.luks.uuid);
+
+    luks_slots = info->u.luks.slots;
+    while (luks_slots) {
+        luks_slot = luks_slots->value;
+
+        slots = g_new0(ImageInfoSpecificLUKSSlotList, 1);
+        if (prev == NULL) {
+            spec_info->u.luks.data->slots = slots;
+        } else {
+            prev->next = slots;
+        }
+
+        slots->value = slot = g_new0(ImageInfoSpecificLUKSSlot, 1);
+        slot->active = luks_slot->active;
+        slot->iters = luks_slot->iters;
+        slot->stripes = luks_slot->stripes;
+        slot->key_offset = luks_slot->key_offset;
+
+        prev = slots;
+        luks_slots = luks_slots->next;
+    }
+
+    qapi_free_QCryptoBlockInfo(info);
+
+    return spec_info;
+}
+
 BlockDriver bdrv_crypto_luks = {
     .format_name        = "luks",
     .instance_size      = sizeof(BlockCrypto),
@@ -578,6 +656,8 @@ BlockDriver bdrv_crypto_luks = {
     .bdrv_co_readv      = block_crypto_co_readv,
     .bdrv_co_writev     = block_crypto_co_writev,
     .bdrv_getlength     = block_crypto_getlength,
+    .bdrv_get_info      = block_crypto_get_info_luks,
+    .bdrv_get_specific_info = block_crypto_get_specific_info_luks,
 };
 
 static void block_crypto_init(void)
diff --git a/qapi/block-core.json b/qapi/block-core.json
index 98a20d2..58a6093 100644
--- a/qapi/block-core.json
+++ b/qapi/block-core.json
@@ -74,6 +74,37 @@
       'extents': ['ImageInfo']
   } }
 
+
+{ 'struct': 'ImageInfoSpecificLUKSSlot',
+  'data': {'active': 'bool',
+           'iters': 'int',
+           'stripes': 'int',
+           'key-offset': 'int' } }
+
+##
+# @ImageInfoSpecificLUKS:
+#
+# @cipher-alg: the cipher algorithm for data encryption
+# @cipher-mode: the cipher mode for data encryption
+# @ivgen-alg: the initialization vector generator
+# @ivgen-hash-alg: the initialization vector generator hash
+# @hash-alg: the master key hash algorithm
+#
+# Since: 2.7
+##
+{ 'struct': 'ImageInfoSpecificLUKS',
+  'data': {
+      'cipher-alg': 'QCryptoCipherAlgorithm',
+      'cipher-mode': 'QCryptoCipherMode',
+      'ivgen-alg': 'QCryptoIVGenAlgorithm',
+      '*ivgen-hash-alg': 'QCryptoHashAlgorithm',
+      'hash-alg': 'QCryptoHashAlgorithm',
+      'payload-offset': 'int',
+      'master-key-iters': 'int',
+      'uuid': 'str',
+      'slots': [ 'ImageInfoSpecificLUKSSlot' ]
+  } }
+
 ##
 # @ImageInfoSpecific:
 #
@@ -85,7 +116,8 @@
 { 'union': 'ImageInfoSpecific',
   'data': {
       'qcow2': 'ImageInfoSpecificQCow2',
-      'vmdk': 'ImageInfoSpecificVmdk'
+      'vmdk': 'ImageInfoSpecificVmdk',
+      'luks': 'ImageInfoSpecificLUKS'
   } }
 
 ##
-- 
2.5.5


Reply via email to