All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/2] Change QEMU crypto hash implementation
@ 2016-06-01 16:52 Daniel P. Berrange
  2016-06-01 16:52 ` [Qemu-devel] [PATCH 1/2] crypto: switch hash code to use nettle/gcrypt directly Daniel P. Berrange
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Daniel P. Berrange @ 2016-06-01 16:52 UTC (permalink / raw)
  To: qemu-devel

This series changes the QEMU crypto hash implementation to
use gcrypt/nettle directly instead of using gnutls abstraction.
This then lets us support several more hash algorithms that
gnutls does not expose itself. This is useful for LUKS block
driver compatibility with dm-crypt.

Daniel P. Berrange (2):
  crypto: switch hash code to use nettle/gcrypt directly
  crypto: implement sha224, sha384, sha512 and ripemd160 hashes

 configure                |  14 -----
 crypto/Makefile.objs     |   3 +
 crypto/hash-gcrypt.c     | 110 +++++++++++++++++++++++++++++++++
 crypto/hash-nettle.c     | 155 +++++++++++++++++++++++++++++++++++++++++++++++
 crypto/hash-stub.c       |  41 +++++++++++++
 crypto/hash.c            | 109 ++-------------------------------
 qapi/crypto.json         |   6 +-
 tests/Makefile           |   2 +-
 tests/test-crypto-hash.c |  53 +++++++++++++++-
 9 files changed, 370 insertions(+), 123 deletions(-)
 create mode 100644 crypto/hash-gcrypt.c
 create mode 100644 crypto/hash-nettle.c
 create mode 100644 crypto/hash-stub.c

-- 
2.5.5

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 1/2] crypto: switch hash code to use nettle/gcrypt directly
  2016-06-01 16:52 [Qemu-devel] [PATCH 0/2] Change QEMU crypto hash implementation Daniel P. Berrange
@ 2016-06-01 16:52 ` Daniel P. Berrange
  2016-06-01 16:52 ` [Qemu-devel] [PATCH 2/2] crypto: implement sha224, sha384, sha512 and ripemd160 hashes Daniel P. Berrange
  2016-06-27  9:37 ` [Qemu-devel] [PATCH 0/2] Change QEMU crypto hash implementation Daniel P. Berrange
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel P. Berrange @ 2016-06-01 16:52 UTC (permalink / raw)
  To: qemu-devel

Currently the internal hash code is using the gnutls hash APIs.
GNUTLS in turn is wrapping either nettle or gcrypt. Not only
were the GNUTLS hash APIs not added until GNUTLS 2.9.10, but
they don't expose support for all the algorithms QEMU needs
to use with LUKS.

Address this by directly wrapping nettle/gcrypt in QEMU and
avoiding GNUTLS's extra layer of indirection. This gives us
support for hash functions on a much wider range of platforms
and opens up ability to support more hash functions. It also
avoids a GNUTLS bug which would not correctly handle hashing
of large data blocks if int != size_t.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 configure                |  14 ------
 crypto/Makefile.objs     |   3 ++
 crypto/hash-gcrypt.c     | 106 +++++++++++++++++++++++++++++++++++++++
 crypto/hash-nettle.c     | 126 +++++++++++++++++++++++++++++++++++++++++++++++
 crypto/hash-stub.c       |  41 +++++++++++++++
 crypto/hash.c            | 105 ---------------------------------------
 tests/Makefile           |   2 +-
 tests/test-crypto-hash.c |  24 ++++++++-
 8 files changed, 299 insertions(+), 122 deletions(-)
 create mode 100644 crypto/hash-gcrypt.c
 create mode 100644 crypto/hash-nettle.c
 create mode 100644 crypto/hash-stub.c

diff --git a/configure b/configure
index b5aab72..6882f21 100755
--- a/configure
+++ b/configure
@@ -306,7 +306,6 @@ gtk=""
 gtkabi=""
 gtk_gl="no"
 gnutls=""
-gnutls_hash=""
 gnutls_rnd=""
 nettle=""
 nettle_kdf="no"
@@ -2202,13 +2201,6 @@ if test "$gnutls" != "no"; then
 	QEMU_CFLAGS="$QEMU_CFLAGS $gnutls_cflags"
         gnutls="yes"
 
-	# gnutls_hash_init requires >= 2.9.10
-	if $pkg_config --exists "gnutls >= 2.9.10"; then
-            gnutls_hash="yes"
-	else
-	    gnutls_hash="no"
-	fi
-
 	# gnutls_rnd requires >= 2.11.0
 	if $pkg_config --exists "gnutls >= 2.11.0"; then
 	    gnutls_rnd="yes"
@@ -2242,11 +2234,9 @@ if test "$gnutls" != "no"; then
 	feature_not_found "gnutls" "Install gnutls devel"
     else
         gnutls="no"
-        gnutls_hash="no"
         gnutls_rnd="no"
     fi
 else
-    gnutls_hash="no"
     gnutls_rnd="no"
 fi
 
@@ -4796,7 +4786,6 @@ echo "GTK support       $gtk `echo_version $gtk $gtk_version`"
 echo "GTK GL support    $gtk_gl"
 echo "VTE support       $vte `echo_version $vte $vteversion`"
 echo "GNUTLS support    $gnutls"
-echo "GNUTLS hash       $gnutls_hash"
 echo "GNUTLS rnd        $gnutls_rnd"
 echo "libgcrypt         $gcrypt"
 echo "libgcrypt kdf     $gcrypt_kdf"
@@ -5166,9 +5155,6 @@ fi
 if test "$gnutls" = "yes" ; then
   echo "CONFIG_GNUTLS=y" >> $config_host_mak
 fi
-if test "$gnutls_hash" = "yes" ; then
-  echo "CONFIG_GNUTLS_HASH=y" >> $config_host_mak
-fi
 if test "$gnutls_rnd" = "yes" ; then
   echo "CONFIG_GNUTLS_RND=y" >> $config_host_mak
 fi
diff --git a/crypto/Makefile.objs b/crypto/Makefile.objs
index 0737f48..1f86f4f 100644
--- a/crypto/Makefile.objs
+++ b/crypto/Makefile.objs
@@ -1,5 +1,7 @@
 crypto-obj-y = init.o
 crypto-obj-y += hash.o
+crypto-obj-$(CONFIG_NETTLE) += hash-nettle.o
+crypto-obj-$(if $(CONFIG_NETTLE),n,$(CONFIG_GCRYPT)) += hash-gcrypt.o
 crypto-obj-y += aes.o
 crypto-obj-y += desrfb.o
 crypto-obj-y += cipher.o
@@ -28,3 +30,4 @@ crypto-aes-obj-y = aes.o
 
 stub-obj-y += random-stub.o
 stub-obj-y += pbkdf-stub.o
+stub-obj-y += hash-stub.o
diff --git a/crypto/hash-gcrypt.c b/crypto/hash-gcrypt.c
new file mode 100644
index 0000000..e045689
--- /dev/null
+++ b/crypto/hash-gcrypt.c
@@ -0,0 +1,106 @@
+/*
+ * QEMU Crypto hash algorithms
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/hash.h"
+#include "gcrypt.h"
+
+
+static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
+    [QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5,
+    [QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1,
+    [QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256,
+};
+
+gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
+{
+    if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
+        qcrypto_hash_alg_map[alg] != GCRY_MD_NONE) {
+        return true;
+    }
+    return false;
+}
+
+
+int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
+                        const struct iovec *iov,
+                        size_t niov,
+                        uint8_t **result,
+                        size_t *resultlen,
+                        Error **errp)
+{
+    int i, ret;
+    gcry_md_hd_t md;
+    unsigned char *digest;
+
+    if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map) ||
+        qcrypto_hash_alg_map[alg] == GCRY_MD_NONE) {
+        error_setg(errp,
+                   "Unknown hash algorithm %d",
+                   alg);
+        return -1;
+    }
+
+    ret = gcry_md_open(&md, qcrypto_hash_alg_map[alg], 0);
+
+    if (ret < 0) {
+        error_setg(errp,
+                   "Unable to initialize hash algorithm: %s",
+                   gcry_strerror(ret));
+        return -1;
+    }
+
+    for (i = 0; i < niov; i++) {
+        gcry_md_write(md, iov[i].iov_base, iov[i].iov_len);
+    }
+
+    ret = gcry_md_get_algo_dlen(qcrypto_hash_alg_map[alg]);
+    if (ret <= 0) {
+        error_setg(errp,
+                   "Unable to get hash length: %s",
+                   gcry_strerror(ret));
+        goto error;
+    }
+    if (*resultlen == 0) {
+        *resultlen = ret;
+        *result = g_new0(uint8_t, *resultlen);
+    } else if (*resultlen != ret) {
+        error_setg(errp,
+                   "Result buffer size %zu is smaller than hash %d",
+                   *resultlen, ret);
+        goto error;
+    }
+
+    digest = gcry_md_read(md, 0);
+    if (!digest) {
+        error_setg(errp,
+                   "No digest produced");
+        goto error;
+    }
+    memcpy(*result, digest, *resultlen);
+
+    gcry_md_close(md);
+    return 0;
+
+ error:
+    gcry_md_close(md);
+    return -1;
+}
diff --git a/crypto/hash-nettle.c b/crypto/hash-nettle.c
new file mode 100644
index 0000000..8ec5572
--- /dev/null
+++ b/crypto/hash-nettle.c
@@ -0,0 +1,126 @@
+/*
+ * QEMU Crypto hash algorithms
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/hash.h"
+#include <nettle/md5.h>
+#include <nettle/sha.h>
+
+typedef void (*qcrypto_nettle_init)(void *ctx);
+typedef void (*qcrypto_nettle_write)(void *ctx,
+                                     unsigned int len,
+                                     const uint8_t *buf);
+typedef void (*qcrypto_nettle_result)(void *ctx,
+                                      unsigned int len,
+                                      uint8_t *buf);
+
+union qcrypto_hash_ctx {
+    struct md5_ctx md5;
+    struct sha1_ctx sha1;
+    struct sha256_ctx sha256;
+};
+
+struct qcrypto_hash_alg {
+    qcrypto_nettle_init init;
+    qcrypto_nettle_write write;
+    qcrypto_nettle_result result;
+    size_t len;
+} qcrypto_hash_alg_map[] = {
+    [QCRYPTO_HASH_ALG_MD5] = {
+        .init = (qcrypto_nettle_init)md5_init,
+        .write = (qcrypto_nettle_write)md5_update,
+        .result = (qcrypto_nettle_result)md5_digest,
+        .len = MD5_DIGEST_SIZE,
+    },
+    [QCRYPTO_HASH_ALG_SHA1] = {
+        .init = (qcrypto_nettle_init)sha1_init,
+        .write = (qcrypto_nettle_write)sha1_update,
+        .result = (qcrypto_nettle_result)sha1_digest,
+        .len = SHA1_DIGEST_SIZE,
+    },
+    [QCRYPTO_HASH_ALG_SHA256] = {
+        .init = (qcrypto_nettle_init)sha256_init,
+        .write = (qcrypto_nettle_write)sha256_update,
+        .result = (qcrypto_nettle_result)sha256_digest,
+        .len = SHA256_DIGEST_SIZE,
+    },
+};
+
+gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
+{
+    if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map) &&
+        qcrypto_hash_alg_map[alg].init != NULL) {
+        return true;
+    }
+    return false;
+}
+
+
+int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
+                        const struct iovec *iov,
+                        size_t niov,
+                        uint8_t **result,
+                        size_t *resultlen,
+                        Error **errp)
+{
+    int i;
+    union qcrypto_hash_ctx ctx;
+
+    if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map) ||
+        qcrypto_hash_alg_map[alg].init == NULL) {
+        error_setg(errp,
+                   "Unknown hash algorithm %d",
+                   alg);
+        return -1;
+    }
+
+    qcrypto_hash_alg_map[alg].init(&ctx);
+
+    for (i = 0; i < niov; i++) {
+        /* Some versions of nettle have functions
+         * declared with 'int' instead of 'size_t'
+         * so to be safe avoid writing more than
+         * UINT_MAX bytes at a time
+         */
+        size_t len = iov[i].iov_len;
+        uint8_t *base = iov[i].iov_base;
+        while (len) {
+            size_t shortlen = MIN(len, UINT_MAX);
+            qcrypto_hash_alg_map[alg].write(&ctx, len, base);
+            len -= shortlen;
+            base += len;
+        }
+    }
+
+    if (*resultlen == 0) {
+        *resultlen = qcrypto_hash_alg_map[alg].len;
+        *result = g_new0(uint8_t, *resultlen);
+    } else if (*resultlen != qcrypto_hash_alg_map[alg].len) {
+        error_setg(errp,
+                   "Result buffer size %zu is smaller than hash %zu",
+                   *resultlen, qcrypto_hash_alg_map[alg].len);
+        return -1;
+    }
+
+    qcrypto_hash_alg_map[alg].result(&ctx, *resultlen, *result);
+
+    return 0;
+}
diff --git a/crypto/hash-stub.c b/crypto/hash-stub.c
new file mode 100644
index 0000000..8a9b8d4
--- /dev/null
+++ b/crypto/hash-stub.c
@@ -0,0 +1,41 @@
+/*
+ * QEMU Crypto hash algorithms
+ *
+ * Copyright (c) 2016 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "crypto/hash.h"
+
+gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg G_GNUC_UNUSED)
+{
+    return false;
+}
+
+int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
+                        const struct iovec *iov G_GNUC_UNUSED,
+                        size_t niov G_GNUC_UNUSED,
+                        uint8_t **result G_GNUC_UNUSED,
+                        size_t *resultlen G_GNUC_UNUSED,
+                        Error **errp)
+{
+    error_setg(errp,
+               "Hash algorithm %d not supported without GNUTLS",
+               alg);
+    return -1;
+}
diff --git a/crypto/hash.c b/crypto/hash.c
index b90af34..7e587d8 100644
--- a/crypto/hash.c
+++ b/crypto/hash.c
@@ -22,12 +22,6 @@
 #include "qapi/error.h"
 #include "crypto/hash.h"
 
-#ifdef CONFIG_GNUTLS_HASH
-#include <gnutls/gnutls.h>
-#include <gnutls/crypto.h>
-#endif
-
-
 static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
     [QCRYPTO_HASH_ALG_MD5] = 16,
     [QCRYPTO_HASH_ALG_SHA1] = 20,
@@ -43,105 +37,6 @@ size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
 }
 
 
-#ifdef CONFIG_GNUTLS_HASH
-static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
-    [QCRYPTO_HASH_ALG_MD5] = GNUTLS_DIG_MD5,
-    [QCRYPTO_HASH_ALG_SHA1] = GNUTLS_DIG_SHA1,
-    [QCRYPTO_HASH_ALG_SHA256] = GNUTLS_DIG_SHA256,
-};
-
-gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
-{
-    if (alg < G_N_ELEMENTS(qcrypto_hash_alg_map)) {
-        return true;
-    }
-    return false;
-}
-
-
-int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
-                        const struct iovec *iov,
-                        size_t niov,
-                        uint8_t **result,
-                        size_t *resultlen,
-                        Error **errp)
-{
-    int i, ret;
-    gnutls_hash_hd_t dig;
-
-    if (alg >= G_N_ELEMENTS(qcrypto_hash_alg_map)) {
-        error_setg(errp,
-                   "Unknown hash algorithm %d",
-                   alg);
-        return -1;
-    }
-
-    ret = gnutls_hash_init(&dig, qcrypto_hash_alg_map[alg]);
-
-    if (ret < 0) {
-        error_setg(errp,
-                   "Unable to initialize hash algorithm: %s",
-                   gnutls_strerror(ret));
-        return -1;
-    }
-
-    for (i = 0; i < niov; i++) {
-        ret = gnutls_hash(dig, iov[i].iov_base, iov[i].iov_len);
-        if (ret < 0) {
-            error_setg(errp,
-                       "Unable process hash data: %s",
-                       gnutls_strerror(ret));
-            goto error;
-        }
-    }
-
-    ret = gnutls_hash_get_len(qcrypto_hash_alg_map[alg]);
-    if (ret <= 0) {
-        error_setg(errp,
-                   "Unable to get hash length: %s",
-                   gnutls_strerror(ret));
-        goto error;
-    }
-    if (*resultlen == 0) {
-        *resultlen = ret;
-        *result = g_new0(uint8_t, *resultlen);
-    } else if (*resultlen != ret) {
-        error_setg(errp,
-                   "Result buffer size %zu is smaller than hash %d",
-                   *resultlen, ret);
-        goto error;
-    }
-
-    gnutls_hash_deinit(dig, *result);
-    return 0;
-
- error:
-    gnutls_hash_deinit(dig, NULL);
-    return -1;
-}
-
-#else /* ! CONFIG_GNUTLS_HASH */
-
-gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg G_GNUC_UNUSED)
-{
-    return false;
-}
-
-int qcrypto_hash_bytesv(QCryptoHashAlgorithm alg,
-                        const struct iovec *iov G_GNUC_UNUSED,
-                        size_t niov G_GNUC_UNUSED,
-                        uint8_t **result G_GNUC_UNUSED,
-                        size_t *resultlen G_GNUC_UNUSED,
-                        Error **errp)
-{
-    error_setg(errp,
-               "Hash algorithm %d not supported without GNUTLS",
-               alg);
-    return -1;
-}
-
-#endif /* ! CONFIG_GNUTLS_HASH */
-
 int qcrypto_hash_bytes(QCryptoHashAlgorithm alg,
                        const char *buf,
                        size_t len,
diff --git a/tests/Makefile b/tests/Makefile
index 4bc041c..833e890 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -80,7 +80,7 @@ check-unit-y += tests/test-qemu-opts$(EXESUF)
 gcov-files-test-qemu-opts-y = qom/test-qemu-opts.c
 check-unit-y += tests/test-write-threshold$(EXESUF)
 gcov-files-test-write-threshold-y = block/write-threshold.c
-check-unit-$(CONFIG_GNUTLS_HASH) += tests/test-crypto-hash$(EXESUF)
+check-unit-y += tests/test-crypto-hash$(EXESUF)
 check-unit-y += tests/test-crypto-cipher$(EXESUF)
 check-unit-y += tests/test-crypto-secret$(EXESUF)
 check-unit-$(CONFIG_GNUTLS) += tests/test-crypto-tlscredsx509$(EXESUF)
diff --git a/tests/test-crypto-hash.c b/tests/test-crypto-hash.c
index 735d6d7..5d563f1 100644
--- a/tests/test-crypto-hash.c
+++ b/tests/test-crypto-hash.c
@@ -69,6 +69,10 @@ static void test_hash_alloc(void)
         int ret;
         size_t j;
 
+        if (!qcrypto_hash_supports(i)) {
+            continue;
+        }
+
         ret = qcrypto_hash_bytes(i,
                                  INPUT_TEXT,
                                  strlen(INPUT_TEXT),
@@ -99,6 +103,10 @@ static void test_hash_prealloc(void)
         int ret;
         size_t j;
 
+        if (!qcrypto_hash_supports(i)) {
+            continue;
+        }
+
         resultlen = expected_lens[i];
         result = g_new0(uint8_t, resultlen);
 
@@ -138,6 +146,10 @@ static void test_hash_iov(void)
         int ret;
         size_t j;
 
+        if (!qcrypto_hash_supports(i)) {
+            continue;
+        }
+
         ret = qcrypto_hash_bytesv(i,
                                   iov, 3,
                                   &result,
@@ -166,6 +178,10 @@ static void test_hash_digest(void)
         char *digest;
         size_t digestsize;
 
+        if (!qcrypto_hash_supports(i)) {
+            continue;
+        }
+
         digestsize = qcrypto_hash_digest_len(i);
 
         g_assert_cmpint(digestsize * 2, ==, strlen(expected_outputs[i]));
@@ -176,7 +192,7 @@ static void test_hash_digest(void)
                                   &digest,
                                   NULL);
         g_assert(ret == 0);
-        g_assert(g_str_equal(digest, expected_outputs[i]));
+        g_assert_cmpstr(digest, ==, expected_outputs[i]);
         g_free(digest);
     }
 }
@@ -192,13 +208,17 @@ static void test_hash_base64(void)
         int ret;
         char *digest;
 
+        if (!qcrypto_hash_supports(i)) {
+            continue;
+        }
+
         ret = qcrypto_hash_base64(i,
                                   INPUT_TEXT,
                                   strlen(INPUT_TEXT),
                                   &digest,
                                   NULL);
         g_assert(ret == 0);
-        g_assert(g_str_equal(digest, expected_outputs_b64[i]));
+        g_assert_cmpstr(digest, ==, expected_outputs_b64[i]);
         g_free(digest);
     }
 }
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [Qemu-devel] [PATCH 2/2] crypto: implement sha224, sha384, sha512 and ripemd160 hashes
  2016-06-01 16:52 [Qemu-devel] [PATCH 0/2] Change QEMU crypto hash implementation Daniel P. Berrange
  2016-06-01 16:52 ` [Qemu-devel] [PATCH 1/2] crypto: switch hash code to use nettle/gcrypt directly Daniel P. Berrange
@ 2016-06-01 16:52 ` Daniel P. Berrange
  2016-06-27  9:37 ` [Qemu-devel] [PATCH 0/2] Change QEMU crypto hash implementation Daniel P. Berrange
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel P. Berrange @ 2016-06-01 16:52 UTC (permalink / raw)
  To: qemu-devel

Wire up the nettle and gcrypt hash backends so that they can
support the sha224, sha384, sha512 and ripemd160 hash algorithms.

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
---
 crypto/hash-gcrypt.c     |  4 ++++
 crypto/hash-nettle.c     | 29 +++++++++++++++++++++++++++++
 crypto/hash.c            |  4 ++++
 qapi/crypto.json         |  6 +++++-
 tests/test-crypto-hash.c | 29 +++++++++++++++++++++++++++++
 5 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/crypto/hash-gcrypt.c b/crypto/hash-gcrypt.c
index e045689..8ea5aff 100644
--- a/crypto/hash-gcrypt.c
+++ b/crypto/hash-gcrypt.c
@@ -27,7 +27,11 @@
 static int qcrypto_hash_alg_map[QCRYPTO_HASH_ALG__MAX] = {
     [QCRYPTO_HASH_ALG_MD5] = GCRY_MD_MD5,
     [QCRYPTO_HASH_ALG_SHA1] = GCRY_MD_SHA1,
+    [QCRYPTO_HASH_ALG_SHA224] = GCRY_MD_SHA224,
     [QCRYPTO_HASH_ALG_SHA256] = GCRY_MD_SHA256,
+    [QCRYPTO_HASH_ALG_SHA384] = GCRY_MD_SHA384,
+    [QCRYPTO_HASH_ALG_SHA512] = GCRY_MD_SHA512,
+    [QCRYPTO_HASH_ALG_RIPEMD160] = GCRY_MD_RMD160,
 };
 
 gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
diff --git a/crypto/hash-nettle.c b/crypto/hash-nettle.c
index 8ec5572..4c6f50b 100644
--- a/crypto/hash-nettle.c
+++ b/crypto/hash-nettle.c
@@ -23,6 +23,7 @@
 #include "crypto/hash.h"
 #include <nettle/md5.h>
 #include <nettle/sha.h>
+#include <nettle/ripemd160.h>
 
 typedef void (*qcrypto_nettle_init)(void *ctx);
 typedef void (*qcrypto_nettle_write)(void *ctx,
@@ -35,7 +36,11 @@ typedef void (*qcrypto_nettle_result)(void *ctx,
 union qcrypto_hash_ctx {
     struct md5_ctx md5;
     struct sha1_ctx sha1;
+    struct sha224_ctx sha224;
     struct sha256_ctx sha256;
+    struct sha384_ctx sha384;
+    struct sha512_ctx sha512;
+    struct ripemd160_ctx ripemd160;
 };
 
 struct qcrypto_hash_alg {
@@ -56,12 +61,36 @@ struct qcrypto_hash_alg {
         .result = (qcrypto_nettle_result)sha1_digest,
         .len = SHA1_DIGEST_SIZE,
     },
+    [QCRYPTO_HASH_ALG_SHA224] = {
+        .init = (qcrypto_nettle_init)sha224_init,
+        .write = (qcrypto_nettle_write)sha224_update,
+        .result = (qcrypto_nettle_result)sha224_digest,
+        .len = SHA224_DIGEST_SIZE,
+    },
     [QCRYPTO_HASH_ALG_SHA256] = {
         .init = (qcrypto_nettle_init)sha256_init,
         .write = (qcrypto_nettle_write)sha256_update,
         .result = (qcrypto_nettle_result)sha256_digest,
         .len = SHA256_DIGEST_SIZE,
     },
+    [QCRYPTO_HASH_ALG_SHA384] = {
+        .init = (qcrypto_nettle_init)sha384_init,
+        .write = (qcrypto_nettle_write)sha384_update,
+        .result = (qcrypto_nettle_result)sha384_digest,
+        .len = SHA384_DIGEST_SIZE,
+    },
+    [QCRYPTO_HASH_ALG_SHA512] = {
+        .init = (qcrypto_nettle_init)sha512_init,
+        .write = (qcrypto_nettle_write)sha512_update,
+        .result = (qcrypto_nettle_result)sha512_digest,
+        .len = SHA512_DIGEST_SIZE,
+    },
+    [QCRYPTO_HASH_ALG_RIPEMD160] = {
+        .init = (qcrypto_nettle_init)ripemd160_init,
+        .write = (qcrypto_nettle_write)ripemd160_update,
+        .result = (qcrypto_nettle_result)ripemd160_digest,
+        .len = RIPEMD160_DIGEST_SIZE,
+    },
 };
 
 gboolean qcrypto_hash_supports(QCryptoHashAlgorithm alg)
diff --git a/crypto/hash.c b/crypto/hash.c
index 7e587d8..2f7955d 100644
--- a/crypto/hash.c
+++ b/crypto/hash.c
@@ -25,7 +25,11 @@
 static size_t qcrypto_hash_alg_size[QCRYPTO_HASH_ALG__MAX] = {
     [QCRYPTO_HASH_ALG_MD5] = 16,
     [QCRYPTO_HASH_ALG_SHA1] = 20,
+    [QCRYPTO_HASH_ALG_SHA224] = 28,
     [QCRYPTO_HASH_ALG_SHA256] = 32,
+    [QCRYPTO_HASH_ALG_SHA384] = 48,
+    [QCRYPTO_HASH_ALG_SHA512] = 64,
+    [QCRYPTO_HASH_ALG_RIPEMD160] = 20,
 };
 
 size_t qcrypto_hash_digest_len(QCryptoHashAlgorithm alg)
diff --git a/qapi/crypto.json b/qapi/crypto.json
index 760d0c0..271b6de 100644
--- a/qapi/crypto.json
+++ b/qapi/crypto.json
@@ -42,12 +42,16 @@
 #
 # @md5: MD5. Should not be used in any new code, legacy compat only
 # @sha1: SHA-1. Should not be used in any new code, legacy compat only
+# @sha224: SHA-224.
 # @sha256: SHA-256. Current recommended strong hash.
+# @sha384: SHA-384.
+# @sha512: SHA-512.
+# @ripemd160: RIPEMD-160.
 # Since: 2.6
 ##
 { 'enum': 'QCryptoHashAlgorithm',
   'prefix': 'QCRYPTO_HASH_ALG',
-  'data': ['md5', 'sha1', 'sha256']}
+  'data': ['md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512', 'ripemd160']}
 
 
 ##
diff --git a/tests/test-crypto-hash.c b/tests/test-crypto-hash.c
index 5d563f1..617abba 100644
--- a/tests/test-crypto-hash.c
+++ b/tests/test-crypto-hash.c
@@ -31,27 +31,56 @@
 
 #define OUTPUT_MD5 "628d206371563035ab8ef62f492bdec9"
 #define OUTPUT_SHA1 "b2e74f26758a3a421e509cee045244b78753cc02"
+#define OUTPUT_SHA224 "e2f7415aad33ef79f6516b0986d7175f" \
+                      "9ca3389a85bf6cfed078737b"
 #define OUTPUT_SHA256 "bc757abb0436586f392b437e5dd24096" \
                       "f7f224de6b74d4d86e2abc6121b160d0"
+#define OUTPUT_SHA384 "887ce52efb4f46700376356583b7e279" \
+                      "4f612bd024e4495087ddb946c448c69d" \
+                      "56dbf7152a94a5e63a80f3ba9f0eed78"
+#define OUTPUT_SHA512 "3a90d79638235ec6c4c11bebd84d83c0" \
+                      "549bc1e84edc4b6ec7086487641256cb" \
+                      "63b54e4cb2d2032b393994aa263c0dbb" \
+                      "e00a9f2fe9ef6037352232a1eec55ee7"
+#define OUTPUT_RIPEMD160 "f3d658fad3fdfb2b52c9369cf0d441249ddfa8a0"
 
 #define OUTPUT_MD5_B64 "Yo0gY3FWMDWrjvYvSSveyQ=="
 #define OUTPUT_SHA1_B64 "sudPJnWKOkIeUJzuBFJEt4dTzAI="
+#define OUTPUT_SHA224_B64 "4vdBWq0z73n2UWsJhtcXX5yjOJqFv2z+0Hhzew=="
 #define OUTPUT_SHA256_B64 "vHV6uwQ2WG85K0N+XdJAlvfyJN5rdNTYbiq8YSGxYNA="
+#define OUTPUT_SHA384_B64 "iHzlLvtPRnADdjVlg7fieU9hK9Ak5ElQh925RsRI" \
+                          "xp1W2/cVKpSl5jqA87qfDu14"
+#define OUTPUT_SHA512_B64 "OpDXljgjXsbEwRvr2E2DwFSbwehO3Etuxwhkh2QS" \
+                          "VstjtU5MstIDKzk5lKomPA274AqfL+nvYDc1IjKh" \
+                          "7sVe5w=="
+#define OUTPUT_RIPEMD160_B64 "89ZY+tP9+ytSyTac8NRBJJ3fqKA="
 
 static const char *expected_outputs[] = {
     [QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5,
     [QCRYPTO_HASH_ALG_SHA1] = OUTPUT_SHA1,
+    [QCRYPTO_HASH_ALG_SHA224] = OUTPUT_SHA224,
     [QCRYPTO_HASH_ALG_SHA256] = OUTPUT_SHA256,
+    [QCRYPTO_HASH_ALG_SHA384] = OUTPUT_SHA384,
+    [QCRYPTO_HASH_ALG_SHA512] = OUTPUT_SHA512,
+    [QCRYPTO_HASH_ALG_RIPEMD160] = OUTPUT_RIPEMD160,
 };
 static const char *expected_outputs_b64[] = {
     [QCRYPTO_HASH_ALG_MD5] = OUTPUT_MD5_B64,
     [QCRYPTO_HASH_ALG_SHA1] = OUTPUT_SHA1_B64,
+    [QCRYPTO_HASH_ALG_SHA224] = OUTPUT_SHA224_B64,
     [QCRYPTO_HASH_ALG_SHA256] = OUTPUT_SHA256_B64,
+    [QCRYPTO_HASH_ALG_SHA384] = OUTPUT_SHA384_B64,
+    [QCRYPTO_HASH_ALG_SHA512] = OUTPUT_SHA512_B64,
+    [QCRYPTO_HASH_ALG_RIPEMD160] = OUTPUT_RIPEMD160_B64,
 };
 static const int expected_lens[] = {
     [QCRYPTO_HASH_ALG_MD5] = 16,
     [QCRYPTO_HASH_ALG_SHA1] = 20,
+    [QCRYPTO_HASH_ALG_SHA224] = 28,
     [QCRYPTO_HASH_ALG_SHA256] = 32,
+    [QCRYPTO_HASH_ALG_SHA384] = 48,
+    [QCRYPTO_HASH_ALG_SHA512] = 64,
+    [QCRYPTO_HASH_ALG_RIPEMD160] = 20,
 };
 
 static const char hex[] = "0123456789abcdef";
-- 
2.5.5

^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [Qemu-devel] [PATCH 0/2] Change QEMU crypto hash implementation
  2016-06-01 16:52 [Qemu-devel] [PATCH 0/2] Change QEMU crypto hash implementation Daniel P. Berrange
  2016-06-01 16:52 ` [Qemu-devel] [PATCH 1/2] crypto: switch hash code to use nettle/gcrypt directly Daniel P. Berrange
  2016-06-01 16:52 ` [Qemu-devel] [PATCH 2/2] crypto: implement sha224, sha384, sha512 and ripemd160 hashes Daniel P. Berrange
@ 2016-06-27  9:37 ` Daniel P. Berrange
  2 siblings, 0 replies; 4+ messages in thread
From: Daniel P. Berrange @ 2016-06-27  9:37 UTC (permalink / raw)
  To: qemu-devel

On Wed, Jun 01, 2016 at 05:52:50PM +0100, Daniel P. Berrange wrote:
> This series changes the QEMU crypto hash implementation to
> use gcrypt/nettle directly instead of using gnutls abstraction.
> This then lets us support several more hash algorithms that
> gnutls does not expose itself. This is useful for LUKS block
> driver compatibility with dm-crypt.
> 
> Daniel P. Berrange (2):
>   crypto: switch hash code to use nettle/gcrypt directly
>   crypto: implement sha224, sha384, sha512 and ripemd160 hashes

I'd love some comments if anyone wants to review this, otherwise I'll
submit a pull request for it in a day or two.

Regards,
Daniel
-- 
|: http://berrange.com      -o-    http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org              -o-             http://virt-manager.org :|
|: http://autobuild.org       -o-         http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org       -o-       http://live.gnome.org/gtk-vnc :|

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2016-06-27  9:37 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-01 16:52 [Qemu-devel] [PATCH 0/2] Change QEMU crypto hash implementation Daniel P. Berrange
2016-06-01 16:52 ` [Qemu-devel] [PATCH 1/2] crypto: switch hash code to use nettle/gcrypt directly Daniel P. Berrange
2016-06-01 16:52 ` [Qemu-devel] [PATCH 2/2] crypto: implement sha224, sha384, sha512 and ripemd160 hashes Daniel P. Berrange
2016-06-27  9:37 ` [Qemu-devel] [PATCH 0/2] Change QEMU crypto hash implementation Daniel P. Berrange

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.