[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH 3/4] crypto: add support for gcrypt's native XTS impl
From: |
Stefano Garzarella |
Subject: |
Re: [PATCH 3/4] crypto: add support for gcrypt's native XTS impl |
Date: |
Fri, 25 Oct 2019 16:03:46 +0200 |
User-agent: |
NeoMutt/20180716 |
On Thu, Oct 17, 2019 at 03:56:53PM +0100, Daniel P. Berrangé wrote:
> Libgcrypt 1.8.0 added support for the XTS mode. Use this because long
> term we wish to delete QEMU's XTS impl to avoid carrying private crypto
> algorithm impls.
>
> As an added benefit, using this improves performance from 531 MB/sec to
> 670 MB/sec, since we are avoiding several layers of function call
> indirection.
>
> This is even more noticable with the gcrypt builds in Fedora or RHEL-8
> which have a non-upstream patch for FIPS mode which does mutex locking.
> This is catastrophic for encryption performance with small block sizes,
> meaning this patch improves encryption from 240 MB/sec to 670 MB/sec.
>
> Signed-off-by: Daniel P. Berrangé <address@hidden>
> ---
> configure | 22 ++++++++++++++++++++++
> crypto/Makefile.objs | 2 +-
> crypto/cipher-gcrypt.c | 36 +++++++++++++++++++++++++++++++++++-
> tests/Makefile.include | 2 +-
> 4 files changed, 59 insertions(+), 3 deletions(-)
>
> diff --git a/configure b/configure
> index 08ca4bcb46..98edb0ff44 100755
> --- a/configure
> +++ b/configure
> @@ -473,6 +473,8 @@ gnutls=""
> nettle=""
> gcrypt=""
> gcrypt_hmac="no"
> +gcrypt_xts="no"
> +qemu_private_xts="yes"
> auth_pam=""
> vte=""
> virglrenderer=""
> @@ -2902,6 +2904,18 @@ EOF
> if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
> gcrypt_hmac=yes
> fi
> + cat > $TMPC << EOF
> +#include <gcrypt.h>
> +int main(void) {
> + gcry_cipher_hd_t handle;
> + gcry_cipher_open(&handle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_XTS, 0);
> + return 0;
> +}
> +EOF
> + if compile_prog "$gcrypt_cflags" "$gcrypt_libs" ; then
> + gcrypt_xts=yes
> + qemu_private_xts=no
> + fi
> elif test "$gcrypt" = "yes"; then
> feature_not_found "gcrypt" "Install gcrypt devel >= 1.5.0"
> else
> @@ -6317,6 +6331,11 @@ echo "VTE support $vte $(echo_version $vte
> $vteversion)"
> echo "TLS priority $tls_priority"
> echo "GNUTLS support $gnutls"
> echo "libgcrypt $gcrypt"
> +if test "$gcrypt" = "yes"
> +then
> + echo " hmac $gcrypt_hmac"
> + echo " XTS $gcrypt_xts"
> +fi
> echo "nettle $nettle $(echo_version $nettle $nettle_version)"
> echo "libtasn1 $tasn1"
> echo "PAM $auth_pam"
> @@ -6794,6 +6813,9 @@ if test "$nettle" = "yes" ; then
> echo "CONFIG_NETTLE=y" >> $config_host_mak
> echo "CONFIG_NETTLE_VERSION_MAJOR=${nettle_version%%.*}" >>
> $config_host_mak
> fi
> +if test "$qemu_private_xts" = "yes" ; then
> + echo "CONFIG_QEMU_PRIVATE_XTS=y" >> $config_host_mak
> +fi
> if test "$tasn1" = "yes" ; then
> echo "CONFIG_TASN1=y" >> $config_host_mak
> fi
> diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
> index 7fe2fa9da2..cdb01f9de9 100644
> --- a/crypto/Makefile.objs
> +++ b/crypto/Makefile.objs
> @@ -31,7 +31,7 @@ crypto-obj-y += ivgen-essiv.o
> crypto-obj-y += ivgen-plain.o
> crypto-obj-y += ivgen-plain64.o
> crypto-obj-y += afsplit.o
> -crypto-obj-y += xts.o
> +crypto-obj-$(CONFIG_QEMU_PRIVATE_XTS) += xts.o
> crypto-obj-y += block.o
> crypto-obj-y += block-qcow.o
> crypto-obj-y += block-luks.o
> diff --git a/crypto/cipher-gcrypt.c b/crypto/cipher-gcrypt.c
> index 5cece9b244..ace719526a 100644
> --- a/crypto/cipher-gcrypt.c
> +++ b/crypto/cipher-gcrypt.c
> @@ -19,7 +19,9 @@
> */
>
> #include "qemu/osdep.h"
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> #include "crypto/xts.h"
> +#endif
> #include "cipherpriv.h"
>
> #include <gcrypt.h>
> @@ -59,10 +61,12 @@ bool qcrypto_cipher_supports(QCryptoCipherAlgorithm alg,
> typedef struct QCryptoCipherGcrypt QCryptoCipherGcrypt;
> struct QCryptoCipherGcrypt {
> gcry_cipher_hd_t handle;
> - gcry_cipher_hd_t tweakhandle;
> size_t blocksize;
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> + gcry_cipher_hd_t tweakhandle;
> /* Initialization vector or Counter */
> uint8_t *iv;
> +#endif
> };
>
> static void
> @@ -74,10 +78,12 @@ qcrypto_gcrypt_cipher_free_ctx(QCryptoCipherGcrypt *ctx,
> }
>
> gcry_cipher_close(ctx->handle);
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> if (mode == QCRYPTO_CIPHER_MODE_XTS) {
> gcry_cipher_close(ctx->tweakhandle);
> }
> g_free(ctx->iv);
> +#endif
> g_free(ctx);
> }
>
> @@ -94,8 +100,14 @@ static QCryptoCipherGcrypt
> *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
>
> switch (mode) {
> case QCRYPTO_CIPHER_MODE_ECB:
> + gcrymode = GCRY_CIPHER_MODE_ECB;
> + break;
> case QCRYPTO_CIPHER_MODE_XTS:
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> gcrymode = GCRY_CIPHER_MODE_ECB;
> +#else
> + gcrymode = GCRY_CIPHER_MODE_XTS;
> +#endif
> break;
> case QCRYPTO_CIPHER_MODE_CBC:
> gcrymode = GCRY_CIPHER_MODE_CBC;
> @@ -172,6 +184,7 @@ static QCryptoCipherGcrypt
> *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
> gcry_strerror(err));
> goto error;
> }
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> if (mode == QCRYPTO_CIPHER_MODE_XTS) {
> err = gcry_cipher_open(&ctx->tweakhandle, gcryalg, gcrymode, 0);
> if (err != 0) {
> @@ -180,6 +193,7 @@ static QCryptoCipherGcrypt
> *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
> goto error;
> }
> }
> +#endif
>
> if (alg == QCRYPTO_CIPHER_ALG_DES_RFB) {
> /* We're using standard DES cipher from gcrypt, so we need
> @@ -191,6 +205,7 @@ static QCryptoCipherGcrypt
> *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
> g_free(rfbkey);
> ctx->blocksize = 8;
> } else {
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> if (mode == QCRYPTO_CIPHER_MODE_XTS) {
> nkey /= 2;
> err = gcry_cipher_setkey(ctx->handle, key, nkey);
> @@ -201,8 +216,11 @@ static QCryptoCipherGcrypt
> *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
> }
> err = gcry_cipher_setkey(ctx->tweakhandle, key + nkey, nkey);
> } else {
> +#endif
> err = gcry_cipher_setkey(ctx->handle, key, nkey);
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> }
> +#endif
> if (err != 0) {
> error_setg(errp, "Cannot set key: %s",
> gcry_strerror(err));
> @@ -228,6 +246,7 @@ static QCryptoCipherGcrypt
> *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
> }
> }
>
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> if (mode == QCRYPTO_CIPHER_MODE_XTS) {
> if (ctx->blocksize != XTS_BLOCK_SIZE) {
> error_setg(errp,
> @@ -237,6 +256,7 @@ static QCryptoCipherGcrypt
> *qcrypto_cipher_ctx_new(QCryptoCipherAlgorithm alg,
> }
> ctx->iv = g_new0(uint8_t, ctx->blocksize);
> }
> +#endif
>
> return ctx;
>
> @@ -253,6 +273,7 @@ qcrypto_gcrypt_cipher_ctx_free(QCryptoCipher *cipher)
> }
>
>
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> static void qcrypto_gcrypt_xts_encrypt(const void *ctx,
> size_t length,
> uint8_t *dst,
> @@ -272,6 +293,7 @@ static void qcrypto_gcrypt_xts_decrypt(const void *ctx,
> err = gcry_cipher_decrypt((gcry_cipher_hd_t)ctx, dst, length, src,
> length);
> g_assert(err == 0);
> }
> +#endif
>
> static int
> qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher,
> @@ -289,12 +311,14 @@ qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher,
> return -1;
> }
>
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
> xts_encrypt(ctx->handle, ctx->tweakhandle,
> qcrypto_gcrypt_xts_encrypt,
> qcrypto_gcrypt_xts_decrypt,
> ctx->iv, len, out, in);
What about adding 'return 0' here and avoiding the next ifdef?
> } else {
> +#endif
> err = gcry_cipher_encrypt(ctx->handle,
> out, len,
> in, len);
> @@ -303,7 +327,9 @@ qcrypto_gcrypt_cipher_encrypt(QCryptoCipher *cipher,
> gcry_strerror(err));
> return -1;
> }
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> }
> +#endif
>
> return 0;
> }
> @@ -325,12 +351,14 @@ qcrypto_gcrypt_cipher_decrypt(QCryptoCipher *cipher,
> return -1;
> }
>
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> if (cipher->mode == QCRYPTO_CIPHER_MODE_XTS) {
> xts_decrypt(ctx->handle, ctx->tweakhandle,
> qcrypto_gcrypt_xts_encrypt,
> qcrypto_gcrypt_xts_decrypt,
> ctx->iv, len, out, in);
Also here...
> } else {
> +#endif
> err = gcry_cipher_decrypt(ctx->handle,
> out, len,
> in, len);
> @@ -339,7 +367,9 @@ qcrypto_gcrypt_cipher_decrypt(QCryptoCipher *cipher,
> gcry_strerror(err));
> return -1;
> }
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> }
> +#endif
>
> return 0;
> }
> @@ -358,9 +388,11 @@ qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher,
> return -1;
> }
>
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> if (ctx->iv) {
> memcpy(ctx->iv, iv, niv);
And maybe here...
> } else {
> +#endif
> if (cipher->mode == QCRYPTO_CIPHER_MODE_CTR) {
> err = gcry_cipher_setctr(ctx->handle, iv, niv);
> if (err != 0) {
> @@ -377,7 +409,9 @@ qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher,
> return -1;
> }
> }
> +#ifdef CONFIG_QEMU_PRIVATE_XTS
> }
> +#endif
>
> return 0;
> }
> diff --git a/tests/Makefile.include b/tests/Makefile.include
> index 3543451ed3..2e5b0d3604 100644
> --- a/tests/Makefile.include
> +++ b/tests/Makefile.include
> @@ -133,7 +133,7 @@ check-unit-y += tests/test-base64$(EXESUF)
> check-unit-$(call land,$(CONFIG_BLOCK),$(if
> $(CONFIG_NETTLE),y,$(CONFIG_GCRYPT))) += tests/test-crypto-pbkdf$(EXESUF)
> check-unit-$(CONFIG_BLOCK) += tests/test-crypto-ivgen$(EXESUF)
> check-unit-$(CONFIG_BLOCK) += tests/test-crypto-afsplit$(EXESUF)
> -check-unit-$(CONFIG_BLOCK) += tests/test-crypto-xts$(EXESUF)
> +check-unit-$(if $(CONFIG_BLOCK),$(CONFIG_QEMU_PRIVATE_XTS)) +=
> tests/test-crypto-xts$(EXESUF)
> check-unit-$(CONFIG_BLOCK) += tests/test-crypto-block$(EXESUF)
> check-unit-y += tests/test-logging$(EXESUF)
> check-unit-$(call land,$(CONFIG_BLOCK),$(CONFIG_REPLICATION)) +=
> tests/test-replication$(EXESUF)
Anyway the patch LGTM, but I don't know this code very well, then:
Acked-by: Stefano Garzarella <address@hidden>
- Re: [PATCH 1/4] tests: allow filtering crypto cipher benchmark tests, (continued)