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>
diff --git a/block/crypto.c b/block/crypto.c
index e87dc84..1b3f879 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -369,6 +369,7 @@
block_crypto_create_init_func,
block_crypto_create_write_func,
&data,
+ 0,
errp);
if (!crypto) {
diff --git a/block/qcow.c b/block/qcow.c
index c6d0e15..ca8e1d5 100644
--- a/block/qcow.c
+++ b/block/qcow.c
@@ -885,7 +885,7 @@
header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
crypto = qcrypto_block_create(qcow_opts->encrypt, "encrypt.",
- NULL, NULL, NULL, errp);
+ NULL, NULL, NULL, 0, errp);
if (!crypto) {
ret = -EINVAL;
goto exit;
diff --git a/block/qcow2.c b/block/qcow2.c
index 9bee66f..204f585 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -3216,7 +3216,7 @@
crypto = qcrypto_block_create(cryptoopts, "encrypt.",
qcow2_crypto_hdr_init_func,
qcow2_crypto_hdr_write_func,
- bs, errp);
+ bs, 0, errp);
if (!crypto) {
return -EINVAL;
}
diff --git a/crypto/block-luks.c b/crypto/block-luks.c
index 7e1235c..ab52c9d 100644
--- a/crypto/block-luks.c
+++ b/crypto/block-luks.c
@@ -1315,6 +1315,7 @@
const char *hash_alg;
g_autofree char *cipher_mode_spec = NULL;
uint64_t iters;
+ uint64_t detached_header_size;
memcpy(&luks_opts, &options->u.luks, sizeof(luks_opts));
if (!luks_opts.has_iter_time) {
@@ -1543,19 +1544,32 @@
slot->stripes = QCRYPTO_BLOCK_LUKS_STRIPES;
}
- /* 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;
+ if (block->detached_header) {
+ /*
+ * For a detached LUKS header image, set the payload_offset_sector
+ * to 0 to specify the starting point for read/write
+ */
+ 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->payload_offset = luks->header.payload_offset_sector *
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 */
- initfunc(block, block->payload_offset, opaque, &local_err);
+ initfunc(block, detached_header_size, opaque, &local_err);
if (local_err) {
error_propagate(errp, local_err);
goto error;
diff --git a/crypto/block.c b/crypto/block.c
index 7bb4b74..506ea1d 100644
--- a/crypto/block.c
+++ b/crypto/block.c
@@ -87,6 +87,7 @@
QCryptoBlockInitFunc initfunc,
QCryptoBlockWriteFunc writefunc,
void *opaque,
+ unsigned int flags,
Error **errp)
{
QCryptoBlock *block = g_new0(QCryptoBlock, 1);
@@ -102,6 +103,7 @@
}
block->driver = qcrypto_block_drivers[options->format];
+ block->detached_header = flags & QCRYPTO_BLOCK_CREATE_DETACHED;
if (block->driver->create(block, options, optprefix, initfunc,
writefunc, opaque, errp) < 0) {
@@ -146,7 +148,7 @@
qcrypto_block_create(create_opts, optprefix,
qcrypto_block_headerlen_hdr_init_func,
qcrypto_block_headerlen_hdr_write_func,
- len, errp);
+ len, 0, errp);
return crypto != NULL;
}
diff --git a/crypto/blockpriv.h b/crypto/blockpriv.h
index 3c7ccea..836f3b4 100644
--- a/crypto/blockpriv.h
+++ b/crypto/blockpriv.h
@@ -42,6 +42,8 @@
size_t niv;
uint64_t payload_offset; /* In bytes */
uint64_t sector_size; /* In bytes */
+
+ bool detached_header; /* True if disk has a detached LUKS header */
};
struct QCryptoBlockDriver {
diff --git a/include/crypto/block.h b/include/crypto/block.h
index d0d97f5..92e823c 100644
--- a/include/crypto/block.h
+++ b/include/crypto/block.h
@@ -116,6 +116,10 @@
size_t n_threads,
Error **errp);
+typedef enum {
+ QCRYPTO_BLOCK_CREATE_DETACHED = (1 << 0),
+} QCryptoBlockCreateFlags;
+
/**
* qcrypto_block_create:
* @options: the encryption options
@@ -123,6 +127,7 @@
* @initfunc: callback for initializing volume header
* @writefunc: callback for writing data to the volume header
* @opaque: data to pass to @initfunc and @writefunc
+ * @flags: bitmask of QCryptoBlockCreateFlags values
* @errp: pointer to a NULL-initialized error object
*
* Create a new block encryption object for initializing
@@ -134,6 +139,11 @@
* generating new master keys, etc as required. Any existing
* 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
* fails an error will be returned. This could be due
* to the volume being in the wrong format, a cipher
@@ -147,6 +157,7 @@
QCryptoBlockInitFunc initfunc,
QCryptoBlockWriteFunc writefunc,
void *opaque,
+ unsigned int flags,
Error **errp);
/**
diff --git a/tests/unit/test-crypto-block.c b/tests/unit/test-crypto-block.c
index 347cd5f..6cfc817 100644
--- a/tests/unit/test-crypto-block.c
+++ b/tests/unit/test-crypto-block.c
@@ -283,6 +283,7 @@
test_block_init_func,
test_block_write_func,
&header,
+ 0,
&error_abort);
g_assert(blk);
@@ -362,6 +363,7 @@
test_block_init_func,
test_block_write_func,
&buf,
+ 0,
&error_abort);
g_assert(blk);