[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v1 1/6] crypto: add support for querying parameters
From: |
Daniel P. Berrange |
Subject: |
[Qemu-devel] [PATCH v1 1/6] crypto: add support for querying parameters for block encryption |
Date: |
Tue, 7 Jun 2016 11:11:10 +0100 |
When creating new block encryption volumes, we accept a list of
parameters to control the formatting process. It is useful to
be able to query what those parameters were for existing block
devices. Add a qcrypto_block_get_info() method which returns a
QCryptoBlockInfo instance to report this data.
Signed-off-by: Daniel P. Berrange <address@hidden>
---
crypto/block-luks.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++-
crypto/block.c | 17 +++++++++++++
crypto/blockpriv.h | 4 +++
include/crypto/block.h | 16 ++++++++++++
qapi/crypto.json | 65 +++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 167 insertions(+), 1 deletion(-)
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 17c4300..1c8e4d6 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -201,6 +201,15 @@ QEMU_BUILD_BUG_ON(sizeof(struct QCryptoBlockLUKSHeader) !=
592);
struct QCryptoBlockLUKS {
QCryptoBlockLUKSHeader header;
+
+ /* Cache parsed versions of what's in header fields.
+ * as we can't rely on QCryptoBlock.cipher being
+ * non-NULL */
+ QCryptoCipherAlgorithm cipher_alg;
+ QCryptoCipherMode cipher_mode;
+ QCryptoIVGenAlgorithm ivgen_alg;
+ QCryptoHashAlgorithm ivgen_hash_alg;
+ QCryptoHashAlgorithm hash_alg;
};
@@ -835,6 +844,12 @@ qcrypto_block_luks_open(QCryptoBlock *block,
block->payload_offset = luks->header.payload_offset *
QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
+ luks->cipher_alg = cipheralg;
+ luks->cipher_mode = ciphermode;
+ luks->ivgen_alg = ivalg;
+ luks->ivgen_hash_alg = ivhash;
+ luks->hash_alg = hash;
+
g_free(masterkey);
g_free(password);
@@ -947,7 +962,6 @@ qcrypto_block_luks_create(QCryptoBlock *block,
}
hash_alg = QCryptoHashAlgorithm_lookup[luks_opts.hash_alg];
-
if (strlen(cipher_alg) >= QCRYPTO_BLOCK_LUKS_CIPHER_NAME_LEN) {
error_setg(errp, "Cipher name '%s' is too long for LUKS header",
cipher_alg);
@@ -1252,6 +1266,12 @@ qcrypto_block_luks_create(QCryptoBlock *block,
goto error;
}
+ luks->cipher_alg = luks_opts.cipher_alg;
+ luks->cipher_mode = luks_opts.cipher_mode;
+ luks->ivgen_alg = luks_opts.ivgen_alg;
+ luks->ivgen_hash_alg = luks_opts.ivgen_hash_alg;
+ luks->hash_alg = luks_opts.hash_alg;
+
memset(masterkey, 0, luks->header.key_bytes);
g_free(masterkey);
memset(slotkey, 0, luks->header.key_bytes);
@@ -1286,6 +1306,49 @@ qcrypto_block_luks_create(QCryptoBlock *block,
}
+static int qcrypto_block_luks_get_info(QCryptoBlock *block,
+ QCryptoBlockInfo *info,
+ Error **errp)
+{
+ QCryptoBlockLUKS *luks = block->opaque;
+ QCryptoBlockInfoLUKSSlot *slot;
+ QCryptoBlockInfoLUKSSlotList *slots = NULL, *prev = NULL;
+ size_t i;
+
+ info->u.luks.cipher_alg = luks->cipher_alg;
+ info->u.luks.cipher_mode = luks->cipher_mode;
+ info->u.luks.ivgen_alg = luks->ivgen_alg;
+ if (info->u.luks.ivgen_alg == QCRYPTO_IVGEN_ALG_ESSIV) {
+ info->u.luks.has_ivgen_hash_alg = true;
+ info->u.luks.ivgen_hash_alg = luks->ivgen_hash_alg;
+ }
+ info->u.luks.hash_alg = luks->hash_alg;
+ info->u.luks.payload_offset = block->payload_offset;
+ info->u.luks.master_key_iters = luks->header.master_key_iterations;
+ info->u.luks.uuid = g_strdup((const char *)luks->header.uuid);
+
+ for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
+ slots = g_new0(QCryptoBlockInfoLUKSSlotList, 1);
+ if (i == 0) {
+ info->u.luks.slots = slots;
+ } else {
+ prev->next = slots;
+ }
+
+ slots->value = slot = g_new0(QCryptoBlockInfoLUKSSlot, 1);
+ slot->active = luks->header.key_slots[i].active ==
+ QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
+ slot->iters = luks->header.key_slots[i].iterations;
+ slot->stripes = luks->header.key_slots[i].stripes;
+ slot->key_offset = luks->header.key_slots[i].key_offset;
+
+ prev = slots;
+ }
+
+ return 0;
+}
+
+
static void qcrypto_block_luks_cleanup(QCryptoBlock *block)
{
g_free(block->opaque);
@@ -1323,6 +1386,7 @@ qcrypto_block_luks_encrypt(QCryptoBlock *block,
const QCryptoBlockDriver qcrypto_block_driver_luks = {
.open = qcrypto_block_luks_open,
.create = qcrypto_block_luks_create,
+ .get_info = qcrypto_block_luks_get_info,
.cleanup = qcrypto_block_luks_cleanup,
.decrypt = qcrypto_block_luks_decrypt,
.encrypt = qcrypto_block_luks_encrypt,
diff --git a/crypto/block.c b/crypto/block.c
index da60eba..be823ee 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -105,6 +105,23 @@ QCryptoBlock
*qcrypto_block_create(QCryptoBlockCreateOptions *options,
}
+QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
+ Error **errp)
+{
+ QCryptoBlockInfo *info = g_new0(QCryptoBlockInfo, 1);
+
+ info->format = block->format;
+
+ if (block->driver->get_info &&
+ block->driver->get_info(block, info, errp) < 0) {
+ g_free(info);
+ return NULL;
+ }
+
+ return info;
+}
+
+
int qcrypto_block_decrypt(QCryptoBlock *block,
uint64_t startsector,
uint8_t *buf,
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
index 6297085..35217cd 100644
--- a/crypto/blockpriv.h
+++ b/crypto/blockpriv.h
@@ -53,6 +53,10 @@ struct QCryptoBlockDriver {
void *opaque,
Error **errp);
+ int (*get_info)(QCryptoBlock *block,
+ QCryptoBlockInfo *info,
+ Error **errp);
+
void (*cleanup)(QCryptoBlock *block);
int (*encrypt)(QCryptoBlock *block,
diff --git a/include/crypto/block.h b/include/crypto/block.h
index a21e11f..5ce18d9 100644
--- a/include/crypto/block.h
+++ b/include/crypto/block.h
@@ -138,6 +138,22 @@ QCryptoBlock
*qcrypto_block_create(QCryptoBlockCreateOptions *options,
void *opaque,
Error **errp);
+
+/**
+ * qcrypto_block_get_info:
+ * block:L the block encryption object
+ * @errp: pointer to a NULL-initialized error object
+ *
+ * Get information about the configuration options for the
+ * block encryption object. This includes details such as
+ * the cipher algorithms, modes, and initialization vector
+ * generators.
+ *
+ * Returns: a block encryption info object, or NULL on error
+ */
+QCryptoBlockInfo *qcrypto_block_get_info(QCryptoBlock *block,
+ Error **errp);
+
/**
* @qcrypto_block_decrypt:
* @block: the block encryption object
diff --git a/qapi/crypto.json b/qapi/crypto.json
index 760d0c0..29bfeb2 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -220,3 +220,68 @@
'discriminator': 'format',
'data': { 'qcow': 'QCryptoBlockOptionsQCow',
'luks': 'QCryptoBlockCreateOptionsLUKS' } }
+
+
+##
+# QCryptoBlockInfoBase:
+#
+# The common information that applies to all full disk
+# encryption formats
+#
+# @format: the encryption format
+#
+# Since: 2.7
+##
+{ 'struct': 'QCryptoBlockInfoBase',
+ 'data': { 'format': 'QCryptoBlockFormat' }}
+
+
+##
+# QCryptoBlockInfoLUKSSlot:
+#
+# Information about the LUKS block encryption key
+# slot options
+#
+{ 'struct': 'QCryptoBlockInfoLUKSSlot',
+ 'data': {'active': 'bool',
+ 'iters': 'int',
+ 'stripes': 'int',
+ 'key-offset': 'int' } }
+
+
+##
+# QCryptoBlockInfoLUKS:
+#
+# Information about the LUKS block encryption options
+#
+# @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': 'QCryptoBlockInfoLUKS',
+ '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': [ 'QCryptoBlockInfoLUKSSlot' ] }}
+
+
+##
+# QCryptoBlockInfo:
+#
+# Information about the block encryption options
+#
+# Since: 2.7
+##
+{ 'union': 'QCryptoBlockInfo',
+ 'base': 'QCryptoBlockInfoBase',
+ 'discriminator': 'format',
+ 'data': { 'luks': 'QCryptoBlockInfoLUKS' } }
--
2.5.5