crypto: Modify the qcrypto_block_create to support creation flags

Expand the signature of qcrypto_block_create to enable the
formation of LUKS volumes with detachable headers. To accomplish
that, introduce QCryptoBlockCreateFlags to instruct the creation
process to set the payload_offset_sector to 0.

Signed-off-by: Hyman Huang <yong.huang@smartx.com>
Reviewed-by: Daniel P. Berrangé <berrange@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
Hyman Huang 2024-01-30 13:37:21 +08:00 committed by Daniel P. Berrangé
parent 433957bb7f
commit d74523a3b3
8 changed files with 42 additions and 10 deletions

View File

@ -369,6 +369,7 @@ block_crypto_co_create_generic(BlockDriverState *bs, int64_t size,
block_crypto_create_init_func, block_crypto_create_init_func,
block_crypto_create_write_func, block_crypto_create_write_func,
&data, &data,
0,
errp); errp);
if (!crypto) { if (!crypto) {

View File

@ -885,7 +885,7 @@ qcow_co_create(BlockdevCreateOptions *opts, Error **errp)
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES); header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
crypto = qcrypto_block_create(qcow_opts->encrypt, "encrypt.", crypto = qcrypto_block_create(qcow_opts->encrypt, "encrypt.",
NULL, NULL, NULL, errp); NULL, NULL, NULL, 0, errp);
if (!crypto) { if (!crypto) {
ret = -EINVAL; ret = -EINVAL;
goto exit; goto exit;

View File

@ -3216,7 +3216,7 @@ qcow2_set_up_encryption(BlockDriverState *bs,
crypto = qcrypto_block_create(cryptoopts, "encrypt.", crypto = qcrypto_block_create(cryptoopts, "encrypt.",
qcow2_crypto_hdr_init_func, qcow2_crypto_hdr_init_func,
qcow2_crypto_hdr_write_func, qcow2_crypto_hdr_write_func,
bs, errp); bs, 0, errp);
if (!crypto) { if (!crypto) {
return -EINVAL; return -EINVAL;
} }

View File

@ -1315,6 +1315,7 @@ qcrypto_block_luks_create(QCryptoBlock *block,
const char *hash_alg; const char *hash_alg;
g_autofree char *cipher_mode_spec = NULL; g_autofree char *cipher_mode_spec = NULL;
uint64_t iters; uint64_t iters;
uint64_t detached_header_size;
memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts)); memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
if (!luks_opts.has_iter_time) { if (!luks_opts.has_iter_time) {
@ -1543,19 +1544,32 @@ qcrypto_block_luks_create(QCryptoBlock *block,
slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES; slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES;
} }
/* The total size of the LUKS headers is the partition header + key if (block->detached_header) {
* slot headers, rounded up to the nearest sector, combined with /*
* the size of each master key material region, also rounded up * For a detached LUKS header image, set the payload_offset_sector
* to the nearest sector */ * to 0 to specify the starting point for read/write
luks->header.payload_offset_sector = header_sectors + */
QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors; luks->header.payload_offset_sector = 0;
} else {
/*
* The total size of the LUKS headers is the partition header + key
* slot headers, rounded up to the nearest sector, combined with
* the size of each master key material region, also rounded up
* to the nearest sector
*/
luks->header.payload_offset_sector = header_sectors +
QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS * split_key_sectors;
}
block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE; block->sector_size = QCRYPTO_BLOCK_LUKS_SECTOR_SIZE;
block->payload_offset = luks->header.payload_offset_sector * block->payload_offset = luks->header.payload_offset_sector *
block->sector_size; block->sector_size;
detached_header_size =
(header_sectors + QCRYPTO_BLOCK_LUKS_NUM_KEY_SLOTS *
split_key_sectors) * block->sector_size;
/* Reserve header space to match payload offset */ /* Reserve header space to match payload offset */
initfunc(block, block->payload_offset, opaque, &local_err); initfunc(block, detached_header_size, opaque, &local_err);
if (local_err) { if (local_err) {
error_propagate(errp, local_err); error_propagate(errp, local_err);
goto error; goto error;

View File

@ -87,6 +87,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
QCryptoBlockInitFunc initfunc, QCryptoBlockInitFunc initfunc,
QCryptoBlockWriteFunc writefunc, QCryptoBlockWriteFunc writefunc,
void *opaque, void *opaque,
unsigned int flags,
Error **errp) Error **errp)
{ {
QCryptoBlock *block = g_new0(QCryptoBlock, 1); QCryptoBlock *block = g_new0(QCryptoBlock, 1);
@ -102,6 +103,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
} }
block->driver = qcrypto_block_drivers[options->format]; block->driver = qcrypto_block_drivers[options->format];
block->detached_header = flags & QCRYPTO_BLOCK_CREATE_DETACHED;
if (block->driver->create(block, options, optprefix, initfunc, if (block->driver->create(block, options, optprefix, initfunc,
writefunc, opaque, errp) < 0) { writefunc, opaque, errp) < 0) {
@ -146,7 +148,7 @@ qcrypto_block_calculate_payload_offset(QCryptoBlockCreateOptions *create_opts,
qcrypto_block_create(create_opts, optprefix, qcrypto_block_create(create_opts, optprefix,
qcrypto_block_headerlen_hdr_init_func, qcrypto_block_headerlen_hdr_init_func,
qcrypto_block_headerlen_hdr_write_func, qcrypto_block_headerlen_hdr_write_func,
len, errp); len, 0, errp);
return crypto != NULL; return crypto != NULL;
} }

View File

@ -42,6 +42,8 @@ struct QCryptoBlock {
size_t niv; size_t niv;
uint64_t payload_offset; /* In bytes */ uint64_t payload_offset; /* In bytes */
uint64_t sector_size; /* In bytes */ uint64_t sector_size; /* In bytes */
bool detached_header; /* True if disk has a detached LUKS header */
}; };
struct QCryptoBlockDriver { struct QCryptoBlockDriver {

View File

@ -116,6 +116,10 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
size_t n_threads, size_t n_threads,
Error **errp); Error **errp);
typedef enum {
QCRYPTO_BLOCK_CREATE_DETACHED = (1 << 0),
} QCryptoBlockCreateFlags;
/** /**
* qcrypto_block_create: * qcrypto_block_create:
* @options: the encryption options * @options: the encryption options
@ -123,6 +127,7 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
* @initfunc: callback for initializing volume header * @initfunc: callback for initializing volume header
* @writefunc: callback for writing data to the volume header * @writefunc: callback for writing data to the volume header
* @opaque: data to pass to @initfunc and @writefunc * @opaque: data to pass to @initfunc and @writefunc
* @flags: bitmask of QCryptoBlockCreateFlags values
* @errp: pointer to a NULL-initialized error object * @errp: pointer to a NULL-initialized error object
* *
* Create a new block encryption object for initializing * Create a new block encryption object for initializing
@ -134,6 +139,11 @@ QCryptoBlock *qcrypto_block_open(QCryptoBlockOpenOptions *options,
* generating new master keys, etc as required. Any existing * generating new master keys, etc as required. Any existing
* data present on the volume will be irrevocably destroyed. * data present on the volume will be irrevocably destroyed.
* *
* If @flags contains QCRYPTO_BLOCK_CREATE_DETACHED then
* the open process will set the payload_offset_sector to 0
* to specify the starting point for the read/write of a
* detached LUKS header image.
*
* If any part of initializing the encryption context * If any part of initializing the encryption context
* fails an error will be returned. This could be due * fails an error will be returned. This could be due
* to the volume being in the wrong format, a cipher * to the volume being in the wrong format, a cipher
@ -147,6 +157,7 @@ QCryptoBlock *qcrypto_block_create(QCryptoBlockCreateOptions *options,
QCryptoBlockInitFunc initfunc, QCryptoBlockInitFunc initfunc,
QCryptoBlockWriteFunc writefunc, QCryptoBlockWriteFunc writefunc,
void *opaque, void *opaque,
unsigned int flags,
Error **errp); Error **errp);
/** /**

View File

@ -283,6 +283,7 @@ static void test_block(gconstpointer opaque)
test_block_init_func, test_block_init_func,
test_block_write_func, test_block_write_func,
&header, &header,
0,
&error_abort); &error_abort);
g_assert(blk); g_assert(blk);
@ -362,6 +363,7 @@ test_luks_bad_header(gconstpointer data)
test_block_init_func, test_block_init_func,
test_block_write_func, test_block_write_func,
&buf, &buf,
0,
&error_abort); &error_abort);
g_assert(blk); g_assert(blk);