Re: [PATCH v2] block/rbd: Add support for rbd image encryption
Am 27.06.2021 um 15:46 hat Ilya Dryomov geschrieben: > On Sun, Jun 27, 2021 at 1:46 PM Or Ozeri wrote: > > > > Starting from ceph Pacific, RBD has built-in support for image-level > > encryption. > > Currently supported formats are LUKS version 1 and 2. > > > > There are 2 new relevant librbd APIs for controlling encryption, both > > expect an > > open image context: > > > > rbd_encryption_format: formats an image (i.e. writes the LUKS header) > > rbd_encryption_load: loads encryptor/decryptor to the image IO stack > > > > This commit extends the qemu rbd driver API to support the above. > > > > Signed-off-by: Or Ozeri > > --- > > v2: handle encryption info only for the case where encryption is not loaded > > --- > > block/rbd.c | 361 ++- > > qapi/block-core.json | 110 - > > 2 files changed, 465 insertions(+), 6 deletions(-) > > > > diff --git a/block/rbd.c b/block/rbd.c > > index f098a89c7b..8edd1be49e 100644 > > --- a/block/rbd.c > > +++ b/block/rbd.c > > @@ -73,6 +73,18 @@ > > #define LIBRBD_USE_IOVEC 0 > > #endif > > > > +#define RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN 8 > > + > > +static const char rbd_luks_header_verification[ > > +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = { > > +'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 1 > > +}; > > + > > +static const char rbd_luks2_header_verification[ > > +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = { > > +'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2 > > +}; > > + > > typedef enum { > > RBD_AIO_READ, > > RBD_AIO_WRITE, > > @@ -341,6 +353,203 @@ static void qemu_rbd_memset(RADOSCB *rcb, int64_t > > offs) > > } > > } > > > > +#ifdef LIBRBD_SUPPORTS_ENCRYPTION > > +static int qemu_rbd_convert_luks_options( > > +RbdEncryptionOptionsLUKSBase *luks_opts, > > +char **passphrase, > > +size_t *passphrase_len, > > +Error **errp) > > +{ > > +return qcrypto_secret_lookup(luks_opts->key_secret, (uint8_t > > **)passphrase, > > + passphrase_len, errp); > > +} > > + > > +static int qemu_rbd_convert_luks_create_options( > > +RbdEncryptionCreateOptionsLUKSBase *luks_opts, > > +rbd_encryption_algorithm_t *alg, > > +char **passphrase, > > +size_t *passphrase_len, > > +Error **errp) > > +{ > > +int r = 0; > > + > > +r = qemu_rbd_convert_luks_options( > > +qapi_RbdEncryptionCreateOptionsLUKSBase_base(luks_opts), > > +passphrase, passphrase_len, errp); > > +if (r < 0) { > > +return r; > > +} > > + > > +if (luks_opts->has_cipher_alg) { > > +switch (luks_opts->cipher_alg) { > > +case QCRYPTO_CIPHER_ALG_AES_128: { > > +*alg = RBD_ENCRYPTION_ALGORITHM_AES128; > > +break; > > +} > > +case QCRYPTO_CIPHER_ALG_AES_256: { > > +*alg = RBD_ENCRYPTION_ALGORITHM_AES256; > > +break; > > +} > > +default: { > > +r = -ENOTSUP; > > +error_setg_errno(errp, -r, "unknown encryption algorithm: > > %u", > > + luks_opts->cipher_alg); > > +return r; > > +} > > +} > > +} else { > > +/* default alg */ > > +*alg = RBD_ENCRYPTION_ALGORITHM_AES256; > > +} > > + > > +return 0; > > +} > > + > > +static int qemu_rbd_encryption_format(rbd_image_t image, > > + RbdEncryptionCreateOptions *encrypt, > > + Error **errp) > > +{ > > +int r = 0; > > +g_autofree char *passphrase = NULL; > > +size_t passphrase_len; > > +rbd_encryption_format_t format; > > +rbd_encryption_options_t opts; > > +rbd_encryption_luks1_format_options_t luks_opts; > > +rbd_encryption_luks2_format_options_t luks2_opts; > > +size_t opts_size; > > +uint64_t raw_size, effective_size; > > + > > +r = rbd_get_size(image, &raw_size); > > +if (r < 0) { > > +error_setg_errno(errp, -r, "cannot get raw image size"); > > +return r; > > +} > > + > > +switch (encrypt->format) { > > +case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS: { > > +memset(&luks_opts, 0, sizeof(luks_opts)); > > +format = RBD_ENCRYPTION_FORMAT_LUKS1; > > +opts = &luks_opts; > > +opts_size = sizeof(luks_opts); > > +r = qemu_rbd_convert_luks_create_options( > > + > > qapi_RbdEncryptionCreateOptionsLUKS_base(&encrypt->u.luks), > > +&luks_opts.alg, &passphrase, &passphrase_len, errp); > > +if (r < 0) { > > +return r; > > +} > > +luks_opts.passphrase = passphrase; > > +luks_opts.passphrase_size = passphrase_len; > > +break; > > +} > > +case RBD_IMAGE_ENCR
Re: [PATCH v2] block/rbd: Add support for rbd image encryption
On Sun, Jun 27, 2021 at 1:46 PM Or Ozeri wrote: > > Starting from ceph Pacific, RBD has built-in support for image-level > encryption. > Currently supported formats are LUKS version 1 and 2. > > There are 2 new relevant librbd APIs for controlling encryption, both expect > an > open image context: > > rbd_encryption_format: formats an image (i.e. writes the LUKS header) > rbd_encryption_load: loads encryptor/decryptor to the image IO stack > > This commit extends the qemu rbd driver API to support the above. > > Signed-off-by: Or Ozeri > --- > v2: handle encryption info only for the case where encryption is not loaded > --- > block/rbd.c | 361 ++- > qapi/block-core.json | 110 - > 2 files changed, 465 insertions(+), 6 deletions(-) > > diff --git a/block/rbd.c b/block/rbd.c > index f098a89c7b..8edd1be49e 100644 > --- a/block/rbd.c > +++ b/block/rbd.c > @@ -73,6 +73,18 @@ > #define LIBRBD_USE_IOVEC 0 > #endif > > +#define RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN 8 > + > +static const char rbd_luks_header_verification[ > +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = { > +'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 1 > +}; > + > +static const char rbd_luks2_header_verification[ > +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = { > +'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2 > +}; > + > typedef enum { > RBD_AIO_READ, > RBD_AIO_WRITE, > @@ -341,6 +353,203 @@ static void qemu_rbd_memset(RADOSCB *rcb, int64_t offs) > } > } > > +#ifdef LIBRBD_SUPPORTS_ENCRYPTION > +static int qemu_rbd_convert_luks_options( > +RbdEncryptionOptionsLUKSBase *luks_opts, > +char **passphrase, > +size_t *passphrase_len, > +Error **errp) > +{ > +return qcrypto_secret_lookup(luks_opts->key_secret, (uint8_t > **)passphrase, > + passphrase_len, errp); > +} > + > +static int qemu_rbd_convert_luks_create_options( > +RbdEncryptionCreateOptionsLUKSBase *luks_opts, > +rbd_encryption_algorithm_t *alg, > +char **passphrase, > +size_t *passphrase_len, > +Error **errp) > +{ > +int r = 0; > + > +r = qemu_rbd_convert_luks_options( > +qapi_RbdEncryptionCreateOptionsLUKSBase_base(luks_opts), > +passphrase, passphrase_len, errp); > +if (r < 0) { > +return r; > +} > + > +if (luks_opts->has_cipher_alg) { > +switch (luks_opts->cipher_alg) { > +case QCRYPTO_CIPHER_ALG_AES_128: { > +*alg = RBD_ENCRYPTION_ALGORITHM_AES128; > +break; > +} > +case QCRYPTO_CIPHER_ALG_AES_256: { > +*alg = RBD_ENCRYPTION_ALGORITHM_AES256; > +break; > +} > +default: { > +r = -ENOTSUP; > +error_setg_errno(errp, -r, "unknown encryption algorithm: > %u", > + luks_opts->cipher_alg); > +return r; > +} > +} > +} else { > +/* default alg */ > +*alg = RBD_ENCRYPTION_ALGORITHM_AES256; > +} > + > +return 0; > +} > + > +static int qemu_rbd_encryption_format(rbd_image_t image, > + RbdEncryptionCreateOptions *encrypt, > + Error **errp) > +{ > +int r = 0; > +g_autofree char *passphrase = NULL; > +size_t passphrase_len; > +rbd_encryption_format_t format; > +rbd_encryption_options_t opts; > +rbd_encryption_luks1_format_options_t luks_opts; > +rbd_encryption_luks2_format_options_t luks2_opts; > +size_t opts_size; > +uint64_t raw_size, effective_size; > + > +r = rbd_get_size(image, &raw_size); > +if (r < 0) { > +error_setg_errno(errp, -r, "cannot get raw image size"); > +return r; > +} > + > +switch (encrypt->format) { > +case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS: { > +memset(&luks_opts, 0, sizeof(luks_opts)); > +format = RBD_ENCRYPTION_FORMAT_LUKS1; > +opts = &luks_opts; > +opts_size = sizeof(luks_opts); > +r = qemu_rbd_convert_luks_create_options( > + > qapi_RbdEncryptionCreateOptionsLUKS_base(&encrypt->u.luks), > +&luks_opts.alg, &passphrase, &passphrase_len, errp); > +if (r < 0) { > +return r; > +} > +luks_opts.passphrase = passphrase; > +luks_opts.passphrase_size = passphrase_len; > +break; > +} > +case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: { > +memset(&luks2_opts, 0, sizeof(luks2_opts)); > +format = RBD_ENCRYPTION_FORMAT_LUKS2; > +opts = &luks2_opts; > +opts_size = sizeof(luks2_opts); > +r = qemu_rbd_convert_luks_create_options( > +qapi_RbdEncryptionCreateOptionsLUKS2_base( >
[PATCH v2] block/rbd: Add support for rbd image encryption
Starting from ceph Pacific, RBD has built-in support for image-level encryption. Currently supported formats are LUKS version 1 and 2. There are 2 new relevant librbd APIs for controlling encryption, both expect an open image context: rbd_encryption_format: formats an image (i.e. writes the LUKS header) rbd_encryption_load: loads encryptor/decryptor to the image IO stack This commit extends the qemu rbd driver API to support the above. Signed-off-by: Or Ozeri --- v2: handle encryption info only for the case where encryption is not loaded --- block/rbd.c | 361 ++- qapi/block-core.json | 110 - 2 files changed, 465 insertions(+), 6 deletions(-) diff --git a/block/rbd.c b/block/rbd.c index f098a89c7b..8edd1be49e 100644 --- a/block/rbd.c +++ b/block/rbd.c @@ -73,6 +73,18 @@ #define LIBRBD_USE_IOVEC 0 #endif +#define RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN 8 + +static const char rbd_luks_header_verification[ +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = { +'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 1 +}; + +static const char rbd_luks2_header_verification[ +RBD_ENCRYPTION_LUKS_HEADER_VERIFICATION_LEN] = { +'L', 'U', 'K', 'S', 0xBA, 0xBE, 0, 2 +}; + typedef enum { RBD_AIO_READ, RBD_AIO_WRITE, @@ -341,6 +353,203 @@ static void qemu_rbd_memset(RADOSCB *rcb, int64_t offs) } } +#ifdef LIBRBD_SUPPORTS_ENCRYPTION +static int qemu_rbd_convert_luks_options( +RbdEncryptionOptionsLUKSBase *luks_opts, +char **passphrase, +size_t *passphrase_len, +Error **errp) +{ +return qcrypto_secret_lookup(luks_opts->key_secret, (uint8_t **)passphrase, + passphrase_len, errp); +} + +static int qemu_rbd_convert_luks_create_options( +RbdEncryptionCreateOptionsLUKSBase *luks_opts, +rbd_encryption_algorithm_t *alg, +char **passphrase, +size_t *passphrase_len, +Error **errp) +{ +int r = 0; + +r = qemu_rbd_convert_luks_options( +qapi_RbdEncryptionCreateOptionsLUKSBase_base(luks_opts), +passphrase, passphrase_len, errp); +if (r < 0) { +return r; +} + +if (luks_opts->has_cipher_alg) { +switch (luks_opts->cipher_alg) { +case QCRYPTO_CIPHER_ALG_AES_128: { +*alg = RBD_ENCRYPTION_ALGORITHM_AES128; +break; +} +case QCRYPTO_CIPHER_ALG_AES_256: { +*alg = RBD_ENCRYPTION_ALGORITHM_AES256; +break; +} +default: { +r = -ENOTSUP; +error_setg_errno(errp, -r, "unknown encryption algorithm: %u", + luks_opts->cipher_alg); +return r; +} +} +} else { +/* default alg */ +*alg = RBD_ENCRYPTION_ALGORITHM_AES256; +} + +return 0; +} + +static int qemu_rbd_encryption_format(rbd_image_t image, + RbdEncryptionCreateOptions *encrypt, + Error **errp) +{ +int r = 0; +g_autofree char *passphrase = NULL; +size_t passphrase_len; +rbd_encryption_format_t format; +rbd_encryption_options_t opts; +rbd_encryption_luks1_format_options_t luks_opts; +rbd_encryption_luks2_format_options_t luks2_opts; +size_t opts_size; +uint64_t raw_size, effective_size; + +r = rbd_get_size(image, &raw_size); +if (r < 0) { +error_setg_errno(errp, -r, "cannot get raw image size"); +return r; +} + +switch (encrypt->format) { +case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS: { +memset(&luks_opts, 0, sizeof(luks_opts)); +format = RBD_ENCRYPTION_FORMAT_LUKS1; +opts = &luks_opts; +opts_size = sizeof(luks_opts); +r = qemu_rbd_convert_luks_create_options( +qapi_RbdEncryptionCreateOptionsLUKS_base(&encrypt->u.luks), +&luks_opts.alg, &passphrase, &passphrase_len, errp); +if (r < 0) { +return r; +} +luks_opts.passphrase = passphrase; +luks_opts.passphrase_size = passphrase_len; +break; +} +case RBD_IMAGE_ENCRYPTION_FORMAT_LUKS2: { +memset(&luks2_opts, 0, sizeof(luks2_opts)); +format = RBD_ENCRYPTION_FORMAT_LUKS2; +opts = &luks2_opts; +opts_size = sizeof(luks2_opts); +r = qemu_rbd_convert_luks_create_options( +qapi_RbdEncryptionCreateOptionsLUKS2_base( +&encrypt->u.luks2), +&luks2_opts.alg, &passphrase, &passphrase_len, errp); +if (r < 0) { +return r; +} +luks2_opts.passphrase = passphrase; +luks2_opts.passphrase_size = passphrase_len; +break; +} +de