crypto: add support for querying parameters for block encryption
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 <berrange@redhat.com> Message-id: 1469192015-16487-2-git-send-email-berrange@redhat.com Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Max Reitz <mreitz@redhat.com>
This commit is contained in:
parent
54a16a63d0
commit
40c8502822
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -847,6 +856,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);
|
||||
|
||||
@ -1271,6 +1286,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);
|
||||
@ -1305,6 +1326,51 @@ 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 = &info->u.luks.slots;
|
||||
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_strndup((const char *)luks->header.uuid,
|
||||
sizeof(luks->header.uuid));
|
||||
|
||||
for (i = 0; i < QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS; i++) {
|
||||
slots = g_new0(QCryptoBlockInfoLUKSSlotList, 1);
|
||||
*prev = slots;
|
||||
|
||||
slots->value = slot = g_new0(QCryptoBlockInfoLUKSSlot, 1);
|
||||
slot->active = luks->header.key_slots[i].active ==
|
||||
QCRYPTO_BLOCK_LUKS_KEY_SLOT_ENABLED;
|
||||
slot->key_offset = luks->header.key_slots[i].key_offset
|
||||
* QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
|
||||
if (slot->active) {
|
||||
slot->has_iters = true;
|
||||
slot->iters = luks->header.key_slots[i].iterations;
|
||||
slot->has_stripes = true;
|
||||
slot->stripes = luks->header.key_slots[i].stripes;
|
||||
}
|
||||
|
||||
prev = &slots->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void qcrypto_block_luks_cleanup(QCryptoBlock *block)
|
||||
{
|
||||
g_free(block->opaque);
|
||||
@ -1342,6 +1408,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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -138,6 +138,22 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
|
||||
void *opaque,
|
||||
Error **errp);
|
||||
|
||||
|
||||
/**
|
||||
* qcrypto_block_get_info:
|
||||
* @block: 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
|
||||
|
@ -224,3 +224,90 @@
|
||||
'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
|
||||
#
|
||||
# @active: whether the key slot is currently in use
|
||||
# @key-offset: offset to the key material in bytes
|
||||
# @iters: #optional number of PBKDF2 iterations for key material
|
||||
# @stripes: #optional number of stripes for splitting key material
|
||||
#
|
||||
# Since: 2.7
|
||||
##
|
||||
{ '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: #optional the initialization vector generator hash
|
||||
# @hash-alg: the master key hash algorithm
|
||||
# @payload-offset: offset to the payload data in bytes
|
||||
# @master-key-iters: number of PBKDF2 iterations for key material
|
||||
# @uuid: unique identifier for the volume
|
||||
# @slots: information about each key slot
|
||||
#
|
||||
# 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' ] }}
|
||||
|
||||
##
|
||||
# QCryptoBlockInfoQCow:
|
||||
#
|
||||
# Information about the QCow block encryption options
|
||||
#
|
||||
# Since: 2.7
|
||||
##
|
||||
{ 'struct': 'QCryptoBlockInfoQCow',
|
||||
'data': { }}
|
||||
|
||||
|
||||
##
|
||||
# QCryptoBlockInfo:
|
||||
#
|
||||
# Information about the block encryption options
|
||||
#
|
||||
# Since: 2.7
|
||||
##
|
||||
{ 'union': 'QCryptoBlockInfo',
|
||||
'base': 'QCryptoBlockInfoBase',
|
||||
'discriminator': 'format',
|
||||
'data': { 'qcow': 'QCryptoBlockInfoQCow',
|
||||
'luks': 'QCryptoBlockInfoLUKS' } }
|
||||
|
Loading…
Reference in New Issue
Block a user