[PATCH v2 1/4] luks: extract block_crypto_calculate_payload_offset()

Stefan Hajnoczi posted 4 patches 6 years, 1 month ago
Maintainers: Max Reitz <mreitz@redhat.com>, Kevin Wolf <kwolf@redhat.com>
There is a newer version of this series
[PATCH v2 1/4] luks: extract block_crypto_calculate_payload_offset()
Posted by Stefan Hajnoczi 6 years, 1 month ago
The qcow2 .bdrv_measure() code calculates the crypto payload offset.
This logic really belongs in block/crypto.c where it can be reused by
other image formats.

The "luks" block driver will need this same logic in order to implement
.bdrv_measure(), so extract the block_crypto_calculate_payload_offset()
function now.

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
---
 block/crypto.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
 block/crypto.h |  5 ++++
 block/qcow2.c  | 59 ++++------------------------------------------
 3 files changed, 73 insertions(+), 55 deletions(-)

diff --git a/block/crypto.c b/block/crypto.c
index 24823835c1..ed32202fa2 100644
--- a/block/crypto.c
+++ b/block/crypto.c
@@ -185,6 +185,70 @@ block_crypto_create_opts_init(QDict *opts, Error **errp)
 }
 
 
+static ssize_t block_crypto_headerlen_hdr_init_func(QCryptoBlock *block,
+        size_t headerlen, void *opaque, Error **errp)
+{
+    size_t *headerlenp = opaque;
+
+    /* Stash away the payload size */
+    *headerlenp = headerlen;
+    return 0;
+}
+
+
+static ssize_t block_crypto_headerlen_hdr_write_func(QCryptoBlock *block,
+        size_t offset, const uint8_t *buf, size_t buflen,
+        void *opaque, Error **errp)
+{
+    /* Discard the bytes, we're not actually writing to an image */
+    return buflen;
+}
+
+
+/* Determine the number of bytes for the crypto header */
+bool block_crypto_calculate_payload_offset(QemuOpts *opts,
+                                           const char *optprefix,
+                                           size_t *len,
+                                           Error **errp)
+{
+    QDict *cryptoopts_qdict;
+    QCryptoBlockCreateOptions *cryptoopts;
+    QCryptoBlock *crypto;
+
+    /* Extract options into a qdict */
+    if (optprefix) {
+        QDict *opts_qdict = qemu_opts_to_qdict(opts, NULL);
+
+        qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, optprefix);
+        qobject_unref(opts_qdict);
+    } else {
+        cryptoopts_qdict = qemu_opts_to_qdict(opts, NULL);
+    }
+
+    /* Build QCryptoBlockCreateOptions object from qdict */
+    qdict_put_str(cryptoopts_qdict, "format", "luks");
+
+    cryptoopts = block_crypto_create_opts_init(cryptoopts_qdict, errp);
+    qobject_unref(cryptoopts_qdict);
+    if (!cryptoopts) {
+        return false;
+    }
+
+    /* Fake LUKS creation in order to determine the payload size */
+    crypto = qcrypto_block_create(cryptoopts, optprefix,
+                                  block_crypto_headerlen_hdr_init_func,
+                                  block_crypto_headerlen_hdr_write_func,
+                                  len, errp);
+    qapi_free_QCryptoBlockCreateOptions(cryptoopts);
+    if (!crypto) {
+        return false;
+    }
+
+    qcrypto_block_free(crypto);
+    return true;
+}
+
+
 static int block_crypto_open_generic(QCryptoBlockFormat format,
                                      QemuOptsList *opts_spec,
                                      BlockDriverState *bs,
diff --git a/block/crypto.h b/block/crypto.h
index b935695e79..5a39bee71b 100644
--- a/block/crypto.h
+++ b/block/crypto.h
@@ -94,4 +94,9 @@ block_crypto_create_opts_init(QDict *opts, Error **errp);
 QCryptoBlockOpenOptions *
 block_crypto_open_opts_init(QDict *opts, Error **errp);
 
+bool block_crypto_calculate_payload_offset(QemuOpts *opts,
+                                           const char *optprefix,
+                                           size_t *len,
+                                           Error **errp);
+
 #endif /* BLOCK_CRYPTO_H */
diff --git a/block/qcow2.c b/block/qcow2.c
index cef9d72b3a..3aaf79bbf6 100644
--- a/block/qcow2.c
+++ b/block/qcow2.c
@@ -4609,60 +4609,6 @@ static coroutine_fn int qcow2_co_flush_to_os(BlockDriverState *bs)
     return ret;
 }
 
-static ssize_t qcow2_measure_crypto_hdr_init_func(QCryptoBlock *block,
-        size_t headerlen, void *opaque, Error **errp)
-{
-    size_t *headerlenp = opaque;
-
-    /* Stash away the payload size */
-    *headerlenp = headerlen;
-    return 0;
-}
-
-static ssize_t qcow2_measure_crypto_hdr_write_func(QCryptoBlock *block,
-        size_t offset, const uint8_t *buf, size_t buflen,
-        void *opaque, Error **errp)
-{
-    /* Discard the bytes, we're not actually writing to an image */
-    return buflen;
-}
-
-/* Determine the number of bytes for the LUKS payload */
-static bool qcow2_measure_luks_headerlen(QemuOpts *opts, size_t *len,
-                                         Error **errp)
-{
-    QDict *opts_qdict;
-    QDict *cryptoopts_qdict;
-    QCryptoBlockCreateOptions *cryptoopts;
-    QCryptoBlock *crypto;
-
-    /* Extract "encrypt." options into a qdict */
-    opts_qdict = qemu_opts_to_qdict(opts, NULL);
-    qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, "encrypt.");
-    qobject_unref(opts_qdict);
-
-    /* Build QCryptoBlockCreateOptions object from qdict */
-    qdict_put_str(cryptoopts_qdict, "format", "luks");
-    cryptoopts = block_crypto_create_opts_init(cryptoopts_qdict, errp);
-    qobject_unref(cryptoopts_qdict);
-    if (!cryptoopts) {
-        return false;
-    }
-
-    /* Fake LUKS creation in order to determine the payload size */
-    crypto = qcrypto_block_create(cryptoopts, "encrypt.",
-                                  qcow2_measure_crypto_hdr_init_func,
-                                  qcow2_measure_crypto_hdr_write_func,
-                                  len, errp);
-    qapi_free_QCryptoBlockCreateOptions(cryptoopts);
-    if (!crypto) {
-        return false;
-    }
-
-    qcrypto_block_free(crypto);
-    return true;
-}
-
 static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
                                        Error **errp)
 {
@@ -4715,7 +4661,10 @@ static BlockMeasureInfo *qcow2_measure(QemuOpts *opts, BlockDriverState *in_bs,
     if (has_luks) {
         size_t headerlen;
 
-        if (!qcow2_measure_luks_headerlen(opts, &headerlen, &local_err)) {
+        if (!block_crypto_calculate_payload_offset(opts,
+                                                   "encrypt.",
+                                                   &headerlen,
+                                                   &local_err)) {
             goto err;
         }
 
-- 
2.24.1


Re: [PATCH v2 1/4] luks: extract block_crypto_calculate_payload_offset()
Posted by Max Reitz 6 years ago
On 09.01.20 12:10, Stefan Hajnoczi wrote:
> The qcow2 .bdrv_measure() code calculates the crypto payload offset.
> This logic really belongs in block/crypto.c where it can be reused by
> other image formats.
> 
> The "luks" block driver will need this same logic in order to implement
> .bdrv_measure(), so extract the block_crypto_calculate_payload_offset()
> function now.
> 
> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> ---
>  block/crypto.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
>  block/crypto.h |  5 ++++
>  block/qcow2.c  | 59 ++++------------------------------------------
>  3 files changed, 73 insertions(+), 55 deletions(-)
> 
> diff --git a/block/crypto.c b/block/crypto.c
> index 24823835c1..ed32202fa2 100644
> --- a/block/crypto.c
> +++ b/block/crypto.c
> @@ -185,6 +185,70 @@ block_crypto_create_opts_init(QDict *opts, Error **errp)

[...]

> +/* Determine the number of bytes for the crypto header */
> +bool block_crypto_calculate_payload_offset(QemuOpts *opts,
> +                                           const char *optprefix,
> +                                           size_t *len,
> +                                           Error **errp)
> +{
> +    QDict *cryptoopts_qdict;
> +    QCryptoBlockCreateOptions *cryptoopts;
> +    QCryptoBlock *crypto;
> +
> +    /* Extract options into a qdict */
> +    if (optprefix) {
> +        QDict *opts_qdict = qemu_opts_to_qdict(opts, NULL);
> +
> +        qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, optprefix);
> +        qobject_unref(opts_qdict);
> +    } else {
> +        cryptoopts_qdict = qemu_opts_to_qdict(opts, NULL);
> +    }
> +
> +    /* Build QCryptoBlockCreateOptions object from qdict */
> +    qdict_put_str(cryptoopts_qdict, "format", "luks");

Should this be a parameter?

Max

Re: [PATCH v2 1/4] luks: extract block_crypto_calculate_payload_offset()
Posted by Stefan Hajnoczi 6 years ago
On Tue, Jan 14, 2020 at 04:25:44PM +0100, Max Reitz wrote:
> On 09.01.20 12:10, Stefan Hajnoczi wrote:
> > The qcow2 .bdrv_measure() code calculates the crypto payload offset.
> > This logic really belongs in block/crypto.c where it can be reused by
> > other image formats.
> > 
> > The "luks" block driver will need this same logic in order to implement
> > .bdrv_measure(), so extract the block_crypto_calculate_payload_offset()
> > function now.
> > 
> > Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
> > ---
> >  block/crypto.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >  block/crypto.h |  5 ++++
> >  block/qcow2.c  | 59 ++++------------------------------------------
> >  3 files changed, 73 insertions(+), 55 deletions(-)
> > 
> > diff --git a/block/crypto.c b/block/crypto.c
> > index 24823835c1..ed32202fa2 100644
> > --- a/block/crypto.c
> > +++ b/block/crypto.c
> > @@ -185,6 +185,70 @@ block_crypto_create_opts_init(QDict *opts, Error **errp)
> 
> [...]
> 
> > +/* Determine the number of bytes for the crypto header */
> > +bool block_crypto_calculate_payload_offset(QemuOpts *opts,
> > +                                           const char *optprefix,
> > +                                           size_t *len,
> > +                                           Error **errp)
> > +{
> > +    QDict *cryptoopts_qdict;
> > +    QCryptoBlockCreateOptions *cryptoopts;
> > +    QCryptoBlock *crypto;
> > +
> > +    /* Extract options into a qdict */
> > +    if (optprefix) {
> > +        QDict *opts_qdict = qemu_opts_to_qdict(opts, NULL);
> > +
> > +        qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, optprefix);
> > +        qobject_unref(opts_qdict);
> > +    } else {
> > +        cryptoopts_qdict = qemu_opts_to_qdict(opts, NULL);
> > +    }
> > +
> > +    /* Build QCryptoBlockCreateOptions object from qdict */
> > +    qdict_put_str(cryptoopts_qdict, "format", "luks");
> 
> Should this be a parameter?

Maybe one day, but there are no users who need it yet.

Stefan
Re: [PATCH v2 1/4] luks: extract block_crypto_calculate_payload_offset()
Posted by Max Reitz 6 years ago
On 15.01.20 14:40, Stefan Hajnoczi wrote:
> On Tue, Jan 14, 2020 at 04:25:44PM +0100, Max Reitz wrote:
>> On 09.01.20 12:10, Stefan Hajnoczi wrote:
>>> The qcow2 .bdrv_measure() code calculates the crypto payload offset.
>>> This logic really belongs in block/crypto.c where it can be reused by
>>> other image formats.
>>>
>>> The "luks" block driver will need this same logic in order to implement
>>> .bdrv_measure(), so extract the block_crypto_calculate_payload_offset()
>>> function now.
>>>
>>> Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
>>> ---
>>>  block/crypto.c | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++
>>>  block/crypto.h |  5 ++++
>>>  block/qcow2.c  | 59 ++++------------------------------------------
>>>  3 files changed, 73 insertions(+), 55 deletions(-)
>>>
>>> diff --git a/block/crypto.c b/block/crypto.c
>>> index 24823835c1..ed32202fa2 100644
>>> --- a/block/crypto.c
>>> +++ b/block/crypto.c
>>> @@ -185,6 +185,70 @@ block_crypto_create_opts_init(QDict *opts, Error **errp)
>>
>> [...]
>>
>>> +/* Determine the number of bytes for the crypto header */
>>> +bool block_crypto_calculate_payload_offset(QemuOpts *opts,
>>> +                                           const char *optprefix,
>>> +                                           size_t *len,
>>> +                                           Error **errp)
>>> +{
>>> +    QDict *cryptoopts_qdict;
>>> +    QCryptoBlockCreateOptions *cryptoopts;
>>> +    QCryptoBlock *crypto;
>>> +
>>> +    /* Extract options into a qdict */
>>> +    if (optprefix) {
>>> +        QDict *opts_qdict = qemu_opts_to_qdict(opts, NULL);
>>> +
>>> +        qdict_extract_subqdict(opts_qdict, &cryptoopts_qdict, optprefix);
>>> +        qobject_unref(opts_qdict);
>>> +    } else {
>>> +        cryptoopts_qdict = qemu_opts_to_qdict(opts, NULL);
>>> +    }
>>> +
>>> +    /* Build QCryptoBlockCreateOptions object from qdict */
>>> +    qdict_put_str(cryptoopts_qdict, "format", "luks");
>>
>> Should this be a parameter?
> 
> Maybe one day, but there are no users who need it yet.

Sure, but would it hurt? O:-)

I’m just asking because this file doesn’t implement luks crypto, so it
seems a bit strange to reference it here.  Actually, now that I think
about it...  This file only implements the luks block driver.  Is this
even the right place for the common
block_crypto_calculate_payload_offset() function?  Would it make more
sense in crypto/block.c or crypto/block-luks.c?

Max