summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xconfigure22
-rw-r--r--crypto/Makefile.objs2
-rw-r--r--crypto/cipher-gcrypt.c97
-rw-r--r--tests/Makefile.include2
4 files changed, 88 insertions, 35 deletions
diff --git a/configure b/configure
index 145fcabbb3..d1e9e457ce 100755
--- a/configure
+++ b/configure
@@ -474,6 +474,8 @@ gnutls=""
 nettle=""
 gcrypt=""
 gcrypt_hmac="no"
+gcrypt_xts="no"
+qemu_private_xts="yes"
 auth_pam=""
 vte=""
 virglrenderer=""
@@ -2911,6 +2913,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
@@ -6326,6 +6340,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"
@@ -6804,6 +6823,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..2864099527 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,20 +311,23 @@ 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);
-    } else {
-        err = gcry_cipher_encrypt(ctx->handle,
-                                  out, len,
-                                  in, len);
-        if (err != 0) {
-            error_setg(errp, "Cannot encrypt data: %s",
-                       gcry_strerror(err));
-            return -1;
-        }
+        return 0;
+    }
+#endif
+
+    err = gcry_cipher_encrypt(ctx->handle,
+                              out, len,
+                              in, len);
+    if (err != 0) {
+        error_setg(errp, "Cannot encrypt data: %s",
+                   gcry_strerror(err));
+        return -1;
     }
 
     return 0;
@@ -325,20 +350,23 @@ 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);
-    } else {
-        err = gcry_cipher_decrypt(ctx->handle,
-                                  out, len,
-                                  in, len);
-        if (err != 0) {
-            error_setg(errp, "Cannot decrypt data: %s",
-                       gcry_strerror(err));
-            return -1;
-        }
+        return 0;
+    }
+#endif
+
+    err = gcry_cipher_decrypt(ctx->handle,
+                              out, len,
+                              in, len);
+    if (err != 0) {
+        error_setg(errp, "Cannot decrypt data: %s",
+                   gcry_strerror(err));
+        return -1;
     }
 
     return 0;
@@ -358,24 +386,27 @@ qcrypto_gcrypt_cipher_setiv(QCryptoCipher *cipher,
         return -1;
     }
 
+#ifdef CONFIG_QEMU_PRIVATE_XTS
     if (ctx->iv) {
         memcpy(ctx->iv, iv, niv);
-    } else {
-        if (cipher->mode == QCRYPTO_CIPHER_MODE_CTR) {
-            err = gcry_cipher_setctr(ctx->handle, iv, niv);
-            if (err != 0) {
-                error_setg(errp, "Cannot set Counter: %s",
+        return 0;
+    }
+#endif
+
+    if (cipher->mode == QCRYPTO_CIPHER_MODE_CTR) {
+        err = gcry_cipher_setctr(ctx->handle, iv, niv);
+        if (err != 0) {
+            error_setg(errp, "Cannot set Counter: %s",
                        gcry_strerror(err));
-                return -1;
-            }
-        } else {
-            gcry_cipher_reset(ctx->handle);
-            err = gcry_cipher_setiv(ctx->handle, iv, niv);
-            if (err != 0) {
-                error_setg(errp, "Cannot set IV: %s",
+            return -1;
+        }
+    } else {
+        gcry_cipher_reset(ctx->handle);
+        err = gcry_cipher_setiv(ctx->handle, iv, niv);
+        if (err != 0) {
+            error_setg(errp, "Cannot set IV: %s",
                        gcry_strerror(err));
-                return -1;
-            }
+            return -1;
         }
     }
 
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 09e5b410dc..4efdd0cd6e 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -140,7 +140,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)