Re: [PATCH v3] block/rbd: Add support for layered encryption

2022-11-17 Thread Daniel P . Berrangé
On Thu, Nov 17, 2022 at 12:42:04PM +, Or Ozeri wrote:
> 
> 
> > -Original Message-
> > From: Daniel P. Berrangé 
> > Sent: 16 November 2022 13:15
> > To: Or Ozeri ; qemu-de...@nongnu.org; qemu-
> > bl...@nongnu.org; Danny Harnik ;
> > idryo...@gmail.com
> > Subject: [EXTERNAL] Re: [PATCH v3] block/rbd: Add support for layered
> > encryption
> > 
> > On Wed, Nov 16, 2022 at 10:23:52AM +, Daniel P. Berrangé wrote:
> > 
> > So with that precedent I guess it is ok to add 'luks-any'.
> > 
> 
> So is it OK to leave the "luks-any" changes to this commit?
> If not, is it ok to split this to 2 commits, in the same "patch-series"?

It is conceptually separate from the layered encryption so
should be a separate commit, in a series.

> BTW is there a possibility this will actually make it to 7.2?

QEMU is in freeze now, which means we only take bug fixes, not
new features, until 8.0 opens up after release. It is fine to
send patches, as the maintainer can queue them until the tree
opens.

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




RE: [PATCH v3] block/rbd: Add support for layered encryption

2022-11-17 Thread Or Ozeri


> -Original Message-
> From: Daniel P. Berrangé 
> Sent: 16 November 2022 13:15
> To: Or Ozeri ; qemu-de...@nongnu.org; qemu-
> bl...@nongnu.org; Danny Harnik ;
> idryo...@gmail.com
> Subject: [EXTERNAL] Re: [PATCH v3] block/rbd: Add support for layered
> encryption
> 
> On Wed, Nov 16, 2022 at 10:23:52AM +, Daniel P. Berrangé wrote:
> 
> So with that precedent I guess it is ok to add 'luks-any'.
> 

So is it OK to leave the "luks-any" changes to this commit?
If not, is it ok to split this to 2 commits, in the same "patch-series"?

BTW is there a possibility this will actually make it to 7.2?
For me personally, the highest priority for me is just getting it merged (not 
necessarily to the 7.2 release),
so that I can submit a follow-up patch to libvirt.


Re: [PATCH v3] block/rbd: Add support for layered encryption

2022-11-16 Thread Ilya Dryomov
On Wed, Nov 16, 2022 at 12:15 PM Daniel P. Berrangé  wrote:
>
> On Wed, Nov 16, 2022 at 10:23:52AM +, Daniel P. Berrangé wrote:
> > On Wed, Nov 16, 2022 at 09:03:31AM +, Or Ozeri wrote:
> > > > -Original Message-
> > > > From: Daniel P. Berrangé 
> > > > Sent: 15 November 2022 19:47
> > > > To: Or Ozeri 
> > > > Cc: qemu-de...@nongnu.org; qemu-block@nongnu.org; Danny Harnik
> > > > ; idryo...@gmail.com
> > > > Subject: [EXTERNAL] Re: [PATCH v3] block/rbd: Add support for layered
> > > > encryption
> > > >
> > > > AFAICT, supporting layered encryption shouldn't require anything other 
> > > > than
> > > > the 'parent' addition.
> > > >
> > >
> > > Since the layered encryption API is new in librbd, we don't have to
> > > support "luks" and "luks2" at all.
> > > In librbd we are actually deprecating the use of "luks" and "luks2",
> > > and instead ask users to use "luks-any".
> >
> > Deprecating that is a bad idea. The security characteristics and
> > feature set of LUKSv1 and LUKSv2 can be quite different. If a mgmt
> > app is expecting the volume to be protected with LUKSv2, it should
> > be stating that explicitly and not permit a silent downgrade if
> > the volume was unexpectedly using LUKSv1.
> >
> > > If we don't add "luks-any" here, we will need to implement
> > > explicit cases for "luks" and "luks2" in the qemu_rbd_encryption_load2.
> > > This looks like a kind of wasteful coding that won't be actually used
> > > by users of the rbd driver in qemu.
> >
> > It isn't wasteful - supporting the formats explicitly is desirable
> > to prevent format downgrades.
> >
> > > Anyhow, we need the "luks-any" option for our use-case, so if you
> > > insist, I will first submit a patch to add "luks-any", before this
> > > patch.
> >
> > I'm pretty wary of any kind of automatic encryption format detection
> > in QEMU. The automatic block driver format probing has been a long
> > standing source of CVEs in QEMU and every single mgmt app above QEMU.
>
> Having said that, normal linux LUKS tools like cryptsetup or systemd
> LUKS integration will auto-detect  luks1 vs luks2. All cryptsetup
> commands also have an option to explicitly specify the format version.
>
> So with that precedent I guess it is ok to add 'luks-any'.

Yeah, I think we may need to reconsider the intent to deprecate
LUKS1 and LUKS2 options for loading encryption in librbd in favor
of a generic LUKS(-ANY) option.  But, just on its own, LUKS(-ANY)
is definitely a thing and having it exposed in QEMU seems natural.

Thanks,

Ilya



Re: [PATCH v3] block/rbd: Add support for layered encryption

2022-11-16 Thread Daniel P . Berrangé
On Wed, Nov 16, 2022 at 10:23:52AM +, Daniel P. Berrangé wrote:
> On Wed, Nov 16, 2022 at 09:03:31AM +, Or Ozeri wrote:
> > > -Original Message-
> > > From: Daniel P. Berrangé 
> > > Sent: 15 November 2022 19:47
> > > To: Or Ozeri 
> > > Cc: qemu-de...@nongnu.org; qemu-block@nongnu.org; Danny Harnik
> > > ; idryo...@gmail.com
> > > Subject: [EXTERNAL] Re: [PATCH v3] block/rbd: Add support for layered
> > > encryption
> > > 
> > > AFAICT, supporting layered encryption shouldn't require anything other 
> > > than
> > > the 'parent' addition.
> > > 
> > 
> > Since the layered encryption API is new in librbd, we don't have to
> > support "luks" and "luks2" at all.
> > In librbd we are actually deprecating the use of "luks" and "luks2",
> > and instead ask users to use "luks-any".
> 
> Deprecating that is a bad idea. The security characteristics and
> feature set of LUKSv1 and LUKSv2 can be quite different. If a mgmt
> app is expecting the volume to be protected with LUKSv2, it should
> be stating that explicitly and not permit a silent downgrade if
> the volume was unexpectedly using LUKSv1.
> 
> > If we don't add "luks-any" here, we will need to implement
> > explicit cases for "luks" and "luks2" in the qemu_rbd_encryption_load2.
> > This looks like a kind of wasteful coding that won't be actually used
> > by users of the rbd driver in qemu.
> 
> It isn't wasteful - supporting the formats explicitly is desirable
> to prevent format downgrades.
> 
> > Anyhow, we need the "luks-any" option for our use-case, so if you
> > insist, I will first submit a patch to add "luks-any", before this
> > patch.
> 
> I'm pretty wary of any kind of automatic encryption format detection
> in QEMU. The automatic block driver format probing has been a long
> standing source of CVEs in QEMU and every single mgmt app above QEMU.

Having said that, normal linux LUKS tools like cryptsetup or systemd
LUKS integration will auto-detect  luks1 vs luks2. All cryptsetup
commands also have an option to explicitly specify the format version.

So with that precedent I guess it is ok to add 'luks-any'.

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




Re: [PATCH v3] block/rbd: Add support for layered encryption

2022-11-16 Thread Daniel P . Berrangé
On Wed, Nov 16, 2022 at 09:03:31AM +, Or Ozeri wrote:
> > -Original Message-
> > From: Daniel P. Berrangé 
> > Sent: 15 November 2022 19:47
> > To: Or Ozeri 
> > Cc: qemu-de...@nongnu.org; qemu-block@nongnu.org; Danny Harnik
> > ; idryo...@gmail.com
> > Subject: [EXTERNAL] Re: [PATCH v3] block/rbd: Add support for layered
> > encryption
> > 
> > AFAICT, supporting layered encryption shouldn't require anything other than
> > the 'parent' addition.
> > 
> 
> Since the layered encryption API is new in librbd, we don't have to
> support "luks" and "luks2" at all.
> In librbd we are actually deprecating the use of "luks" and "luks2",
> and instead ask users to use "luks-any".

Deprecating that is a bad idea. The security characteristics and
feature set of LUKSv1 and LUKSv2 can be quite different. If a mgmt
app is expecting the volume to be protected with LUKSv2, it should
be stating that explicitly and not permit a silent downgrade if
the volume was unexpectedly using LUKSv1.

> If we don't add "luks-any" here, we will need to implement
> explicit cases for "luks" and "luks2" in the qemu_rbd_encryption_load2.
> This looks like a kind of wasteful coding that won't be actually used
> by users of the rbd driver in qemu.

It isn't wasteful - supporting the formats explicitly is desirable
to prevent format downgrades.

> Anyhow, we need the "luks-any" option for our use-case, so if you
> insist, I will first submit a patch to add "luks-any", before this
> patch.

I'm pretty wary of any kind of automatic encryption format detection
in QEMU. The automatic block driver format probing has been a long
standing source of CVEs in QEMU and every single mgmt app above QEMU.

What is the problem with specifying the desired LUKS format explicitly.
The mgmt app should know what formats it wants to be using. It should
be possible to query format for existing volumes too.

With regards,
Daniel
-- 
|: https://berrange.com  -o-https://www.flickr.com/photos/dberrange :|
|: https://libvirt.org -o-https://fstop138.berrange.com :|
|: https://entangle-photo.org-o-https://www.instagram.com/dberrange :|




RE: [PATCH v3] block/rbd: Add support for layered encryption

2022-11-16 Thread Or Ozeri
> -Original Message-
> From: Daniel P. Berrangé 
> Sent: 15 November 2022 19:47
> To: Or Ozeri 
> Cc: qemu-de...@nongnu.org; qemu-block@nongnu.org; Danny Harnik
> ; idryo...@gmail.com
> Subject: [EXTERNAL] Re: [PATCH v3] block/rbd: Add support for layered
> encryption
> 
> AFAICT, supporting layered encryption shouldn't require anything other than
> the 'parent' addition.
> 

Since the layered encryption API is new in librbd, we don't have to support 
"luks" and "luks2" at all.
In librbd we are actually deprecating the use of "luks" and "luks2", and 
instead ask users to use "luks-any".
If we don't add "luks-any" here, we will need to implement explicit cases for 
"luks" and "luks2" in the qemu_rbd_encryption_load2. This looks like a kind of 
wasteful coding that won't be actually used by users of the rbd driver in qemu.
Anyhow, we need the "luks-any" option for our use-case, so if you insist, I 
will first submit a patch to add "luks-any", before this patch.


Re: [PATCH v3] block/rbd: Add support for layered encryption

2022-11-15 Thread Daniel P . Berrangé
On Tue, Nov 15, 2022 at 06:25:27AM -0600, Or Ozeri wrote:
> Starting from ceph Reef, RBD has built-in support for layered encryption,
> where each ancestor image (in a cloned image setting) can be possibly
> encrypted using a unique passphrase.
> 
> A new function, rbd_encryption_load2, was added to librbd API.
> This new function supports an array of passphrases (via "spec" structs).
> 
> This commit extends the qemu rbd driver API to use this new librbd API,
> in order to support this new layered encryption feature.
> 
> Signed-off-by: Or Ozeri 
> ---
> v3: further nit fixes suggested by @idryomov
> v2: nit fixes suggested by @idryomov
> ---
>  block/rbd.c  | 119 ++-
>  qapi/block-core.json |  35 +++--
>  2 files changed, 150 insertions(+), 4 deletions(-)
> 
> diff --git a/block/rbd.c b/block/rbd.c
> index f826410f40..ce017c29b5 100644
> --- a/block/rbd.c
> +++ b/block/rbd.c
> @@ -71,6 +71,16 @@ static const char rbd_luks2_header_verification[
>  'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2
>  };
>  
> +static const char rbd_layered_luks_header_verification[
> +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
> +'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 1
> +};
> +
> +static const char rbd_layered_luks2_header_verification[
> +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
> +'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 2
> +};
> +
>  typedef enum {
>  RBD_AIO_READ,
>  RBD_AIO_WRITE,
> @@ -470,6 +480,9 @@ static int qemu_rbd_encryption_load(rbd_image_t image,
>  size_t passphrase_len;
>  rbd_encryption_luks1_format_options_t luks_opts;
>  rbd_encryption_luks2_format_options_t luks2_opts;
> +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
> +rbd_encryption_luks_format_options_t luks_any_opts;
> +#endif
>  rbd_encryption_format_t format;
>  rbd_encryption_options_t opts;
>  size_t opts_size;
> @@ -505,6 +518,23 @@ static int qemu_rbd_encryption_load(rbd_image_t image,
>  luks2_opts.passphrase_size = passphrase_len;
>  break;
>  }
> +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
> +case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: {
> +memset(&luks_any_opts, 0, sizeof(luks_any_opts));
> +format = RBD_ENCRYPTION_FORMAT_LUKS;
> +opts = &luks_any_opts;
> +opts_size = sizeof(luks_any_opts);
> +r = qemu_rbd_convert_luks_options(
> +
> qapi_RbdEncryptionOptionsLUKSAny_base(&encrypt->u.luks_any),
> +&passphrase, &passphrase_len, errp);
> +if (r < 0) {
> +return r;
> +}
> +luks_any_opts.passphrase = passphrase;
> +luks_any_opts.passphrase_size = passphrase_len;
> +break;
> +}
> +#endif

This looks unrelated to support of multiple layers, unless I'm missing
something.

>  default: {
>  r = -ENOTSUP;
>  error_setg_errno(
> @@ -522,6 +552,74 @@ static int qemu_rbd_encryption_load(rbd_image_t image,
>  
>  return 0;
>  }
> +
> +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
> +static int qemu_rbd_encryption_load2(rbd_image_t image,
> + RbdEncryptionOptions *encrypt,
> + Error **errp)
> +{
> +int r = 0;
> +int encrypt_count = 1;
> +int i;
> +RbdEncryptionOptions *curr_encrypt;
> +rbd_encryption_spec_t *specs;
> +rbd_encryption_luks_format_options_t* luks_any_opts;
> +
> +/* count encryption options */
> +for (curr_encrypt = encrypt; curr_encrypt->has_parent;
> + curr_encrypt = curr_encrypt->parent) {
> +++encrypt_count;
> +}
> +
> +specs = g_new0(rbd_encryption_spec_t, encrypt_count);
> +
> +curr_encrypt = encrypt;
> +for (i = 0; i < encrypt_count; ++i) {
> +if (curr_encrypt->format != RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY) {
> +r = -ENOTSUP;
> +error_setg_errno(
> +errp, -r, "unknown image encryption format: %u",
> +curr_encrypt->format);
> +goto exit;
> +}
> +
> +specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS;
> +specs[i].opts_size = sizeof(rbd_encryption_luks_format_options_t);
> +
> +luks_any_opts = g_new0(rbd_encryption_luks_format_options_t, 1);
> +specs[i].opts = luks_any_opts;
> +
> +r = qemu_rbd_convert_luks_options(
> +qapi_RbdEncryptionOptionsLUKSAny_base(
> +&curr_encrypt->u.luks_any),
> +(char**)&luks_any_opts->passphrase,
> +&luks_any_opts->passphrase_size,
> +errp);
> +if (r < 0) {
> +goto exit;
> +}
> +
> +curr_encrypt = curr_encrypt->parent;
> +}
> +
> +r = rbd_encryption_load2(image, specs, encrypt_count);
> +if (r < 0) {
> +error_setg_errno(errp, -r, "layered encryption load fa

Re: [PATCH v3] block/rbd: Add support for layered encryption

2022-11-15 Thread Ilya Dryomov
On Tue, Nov 15, 2022 at 1:25 PM Or Ozeri  wrote:
>
> Starting from ceph Reef, RBD has built-in support for layered encryption,
> where each ancestor image (in a cloned image setting) can be possibly
> encrypted using a unique passphrase.
>
> A new function, rbd_encryption_load2, was added to librbd API.
> This new function supports an array of passphrases (via "spec" structs).
>
> This commit extends the qemu rbd driver API to use this new librbd API,
> in order to support this new layered encryption feature.
>
> Signed-off-by: Or Ozeri 
> ---
> v3: further nit fixes suggested by @idryomov
> v2: nit fixes suggested by @idryomov
> ---
>  block/rbd.c  | 119 ++-
>  qapi/block-core.json |  35 +++--
>  2 files changed, 150 insertions(+), 4 deletions(-)
>
> diff --git a/block/rbd.c b/block/rbd.c
> index f826410f40..ce017c29b5 100644
> --- a/block/rbd.c
> +++ b/block/rbd.c
> @@ -71,6 +71,16 @@ static const char rbd_luks2_header_verification[
>  'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2
>  };
>
> +static const char rbd_layered_luks_header_verification[
> +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
> +'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 1
> +};
> +
> +static const char rbd_layered_luks2_header_verification[
> +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = {
> +'R', 'B', 'D', 'L', 0xBA, 0xBE, 0, 2
> +};
> +
>  typedef enum {
>  RBD_AIO_READ,
>  RBD_AIO_WRITE,
> @@ -470,6 +480,9 @@ static int qemu_rbd_encryption_load(rbd_image_t image,
>  size_t passphrase_len;
>  rbd_encryption_luks1_format_options_t luks_opts;
>  rbd_encryption_luks2_format_options_t luks2_opts;
> +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
> +rbd_encryption_luks_format_options_t luks_any_opts;
> +#endif
>  rbd_encryption_format_t format;
>  rbd_encryption_options_t opts;
>  size_t opts_size;
> @@ -505,6 +518,23 @@ static int qemu_rbd_encryption_load(rbd_image_t image,
>  luks2_opts.passphrase_size = passphrase_len;
>  break;
>  }
> +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
> +case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY: {
> +memset(&luks_any_opts, 0, sizeof(luks_any_opts));
> +format = RBD_ENCRYPTION_FORMAT_LUKS;
> +opts = &luks_any_opts;
> +opts_size = sizeof(luks_any_opts);
> +r = qemu_rbd_convert_luks_options(
> +
> qapi_RbdEncryptionOptionsLUKSAny_base(&encrypt->u.luks_any),
> +&passphrase, &passphrase_len, errp);
> +if (r < 0) {
> +return r;
> +}
> +luks_any_opts.passphrase = passphrase;
> +luks_any_opts.passphrase_size = passphrase_len;
> +break;
> +}
> +#endif
>  default: {
>  r = -ENOTSUP;
>  error_setg_errno(
> @@ -522,6 +552,74 @@ static int qemu_rbd_encryption_load(rbd_image_t image,
>
>  return 0;
>  }
> +
> +#ifdef LIBRBD_SUPPORTS_ENCRYPTION_LOAD2
> +static int qemu_rbd_encryption_load2(rbd_image_t image,
> + RbdEncryptionOptions *encrypt,
> + Error **errp)
> +{
> +int r = 0;
> +int encrypt_count = 1;
> +int i;
> +RbdEncryptionOptions *curr_encrypt;
> +rbd_encryption_spec_t *specs;
> +rbd_encryption_luks_format_options_t* luks_any_opts;
> +
> +/* count encryption options */
> +for (curr_encrypt = encrypt; curr_encrypt->has_parent;
> + curr_encrypt = curr_encrypt->parent) {
> +++encrypt_count;
> +}
> +
> +specs = g_new0(rbd_encryption_spec_t, encrypt_count);
> +
> +curr_encrypt = encrypt;
> +for (i = 0; i < encrypt_count; ++i) {
> +if (curr_encrypt->format != RBD_IMAGE_ENCRYPTION_FORMAT_LUKS_ANY) {
> +r = -ENOTSUP;
> +error_setg_errno(
> +errp, -r, "unknown image encryption format: %u",
> +curr_encrypt->format);
> +goto exit;
> +}
> +
> +specs[i].format = RBD_ENCRYPTION_FORMAT_LUKS;
> +specs[i].opts_size = sizeof(rbd_encryption_luks_format_options_t);
> +
> +luks_any_opts = g_new0(rbd_encryption_luks_format_options_t, 1);
> +specs[i].opts = luks_any_opts;
> +
> +r = qemu_rbd_convert_luks_options(
> +qapi_RbdEncryptionOptionsLUKSAny_base(
> +&curr_encrypt->u.luks_any),
> +(char**)&luks_any_opts->passphrase,

Nit: I would change qemu_rbd_convert_luks_options() to take
const char **passphrase and eliminate this cast.  It's a trivial
fixup so it can be folded into this patch with no explanation.

> +&luks_any_opts->passphrase_size,
> +errp);
> +if (r < 0) {
> +goto exit;
> +}
> +
> +curr_encrypt = curr_encrypt->parent;
> +}
> +
> +r = rbd_encryption_load2(image, specs, encrypt_co