tolerate additional IPv4 address now available for gnunet.org
[oweals/gnunet.git] / src / util / crypto_ecc.c
index c4e101369f4f346672bca4e063829d05324a1b67..339180dffbf91a12cf5dc4ed455a203aa9b18edf 100644 (file)
@@ -1,21 +1,21 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2012, 2013, 2015 Christian Grothoff (and other contributing authors)
+     Copyright (C) 2012, 2013, 2015 GNUnet e.V.
 
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
+     GNUnet is free software: you can redistribute it and/or modify it
+     under the terms of the GNU Affero General Public License as published
+     by the Free Software Foundation, either version 3 of the License,
+     or (at your option) any later version.
 
      GNUnet 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
-     General Public License for more details.
+     Affero General Public License for more details.
 
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-     Boston, MA 02110-1301, USA.
+     You should have received a copy of the GNU Affero General Public License
+     along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+     SPDX-License-Identifier: AGPL3.0-or-later
 */
 
 /**
@@ -27,6 +27,7 @@
 #include <gcrypt.h>
 #include "gnunet_crypto_lib.h"
 #include "gnunet_strings_lib.h"
+#include "benchmark.h"
 
 #define EXTRA_CHECKS 0
 
  */
 #define CURVE "Ed25519"
 
-#define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
+#define LOG(kind,...) GNUNET_log_from (kind, "util-crypto-ecc", __VA_ARGS__)
 
-#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
+#define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util-crypto-ecc", syscall)
 
-#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
+#define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util-crypto-ecc", syscall, filename)
 
 /**
  * Log an error message at log-level 'level' that indicates
@@ -227,6 +228,8 @@ GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *
   gcry_ctx_t ctx;
   gcry_mpi_t q;
 
+  BENCHMARK_START (ecdsa_key_get_public);
+
   sexp = decode_private_ecdsa_key (priv);
   GNUNET_assert (NULL != sexp);
   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
@@ -236,6 +239,8 @@ GNUNET_CRYPTO_ecdsa_key_get_public (const struct GNUNET_CRYPTO_EcdsaPrivateKey *
   GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
   gcry_mpi_release (q);
   gcry_ctx_release (ctx);
+
+  BENCHMARK_END (ecdsa_key_get_public);
 }
 
 
@@ -253,6 +258,8 @@ GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *
   gcry_ctx_t ctx;
   gcry_mpi_t q;
 
+  BENCHMARK_START (eddsa_key_get_public);
+
   sexp = decode_private_eddsa_key (priv);
   GNUNET_assert (NULL != sexp);
   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
@@ -262,6 +269,8 @@ GNUNET_CRYPTO_eddsa_key_get_public (const struct GNUNET_CRYPTO_EddsaPrivateKey *
   GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
   gcry_mpi_release (q);
   gcry_ctx_release (ctx);
+
+  BENCHMARK_END (eddsa_key_get_public);
 }
 
 
@@ -279,6 +288,8 @@ GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *
   gcry_ctx_t ctx;
   gcry_mpi_t q;
 
+  BENCHMARK_START (ecdhe_key_get_public);
+
   sexp = decode_private_ecdhe_key (priv);
   GNUNET_assert (NULL != sexp);
   GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, sexp, NULL));
@@ -288,6 +299,8 @@ GNUNET_CRYPTO_ecdhe_key_get_public (const struct GNUNET_CRYPTO_EcdhePrivateKey *
   GNUNET_CRYPTO_mpi_print_unsigned (pub->q_y, sizeof (pub->q_y), q);
   gcry_mpi_release (q);
   gcry_ctx_release (ctx);
+
+  BENCHMARK_END (ecdhe_key_get_public);
 }
 
 
@@ -353,6 +366,37 @@ GNUNET_CRYPTO_eddsa_public_key_to_string (const struct GNUNET_CRYPTO_EddsaPublic
 }
 
 
+/**
+ * Convert a private key to a string.
+ *
+ * @param priv key to convert
+ * @return string representing @a pub
+ */
+char *
+GNUNET_CRYPTO_eddsa_private_key_to_string (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
+{
+  char *privkeybuf;
+  size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
+  char *end;
+
+  if (keylen % 5 > 0)
+    keylen += 5 - keylen % 5;
+  keylen /= 5;
+  privkeybuf = GNUNET_malloc (keylen + 1);
+  end = GNUNET_STRINGS_data_to_string ((unsigned char *) priv,
+                                      sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey),
+                                      privkeybuf,
+                                      keylen);
+  if (NULL == end)
+  {
+    GNUNET_free (privkeybuf);
+    return NULL;
+  }
+  *end = '\0';
+  return privkeybuf;
+}
+
+
 /**
  * Convert a string representing a public key to a public key.
  *
@@ -374,9 +418,10 @@ GNUNET_CRYPTO_ecdsa_public_key_from_string (const char *enc,
   if (enclen != keylen)
     return GNUNET_SYSERR;
 
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
-                                                 pub,
-                                                 sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (enc, enclen,
+                                    pub,
+                                    sizeof (struct GNUNET_CRYPTO_EcdsaPublicKey)))
     return GNUNET_SYSERR;
   return GNUNET_OK;
 }
@@ -403,9 +448,10 @@ GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
   if (enclen != keylen)
     return GNUNET_SYSERR;
 
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
-                                                 pub,
-                                                 sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (enc, enclen,
+                                    pub,
+                                    sizeof (struct GNUNET_CRYPTO_EddsaPublicKey)))
     return GNUNET_SYSERR;
   return GNUNET_OK;
 }
@@ -422,7 +468,7 @@ GNUNET_CRYPTO_eddsa_public_key_from_string (const char *enc,
 int
 GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
                                              size_t enclen,
-                                             struct GNUNET_CRYPTO_EddsaPrivateKey *pub)
+                                             struct GNUNET_CRYPTO_EddsaPrivateKey *priv)
 {
   size_t keylen = (sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)) * 8;
 
@@ -432,10 +478,19 @@ GNUNET_CRYPTO_eddsa_private_key_from_string (const char *enc,
   if (enclen != keylen)
     return GNUNET_SYSERR;
 
-  if (GNUNET_OK != GNUNET_STRINGS_string_to_data (enc, enclen,
-                                                 pub,
-                                                 sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
+  if (GNUNET_OK !=
+      GNUNET_STRINGS_string_to_data (enc, enclen,
+                                     priv,
+                                     sizeof (struct GNUNET_CRYPTO_EddsaPrivateKey)))
     return GNUNET_SYSERR;
+#if CRYPTO_BUG
+  if (GNUNET_OK !=
+      check_eddsa_key (priv))
+  {
+    GNUNET_break (0);
+    return GNUNET_OK;
+  }
+#endif
   return GNUNET_OK;
 }
 
@@ -488,11 +543,35 @@ struct GNUNET_CRYPTO_EcdhePrivateKey *
 GNUNET_CRYPTO_ecdhe_key_create ()
 {
   struct GNUNET_CRYPTO_EcdhePrivateKey *priv;
+
+  priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_ecdhe_key_create2 (priv))
+  {
+    GNUNET_free (priv);
+    return NULL;
+  }
+  return priv;
+}
+
+
+/**
+ * @ingroup crypto
+ * Create a new private key.  Clear with #GNUNET_CRYPTO_ecdhe_key_clear().
+ *
+ * @param[out] pk set to fresh private key;
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
+ */
+int
+GNUNET_CRYPTO_ecdhe_key_create2 (struct GNUNET_CRYPTO_EcdhePrivateKey *pk)
+{
   gcry_sexp_t priv_sexp;
   gcry_sexp_t s_keyparam;
   gcry_mpi_t d;
   int rc;
 
+  BENCHMARK_START (ecdhe_key_create);
+
   /* NOTE: For libgcrypt >= 1.7, we do not need the 'eddsa' flag here,
      but should also be harmless. For libgcrypt < 1.7, using 'eddsa'
      disables an expensive key testing routine. We do not want to run
@@ -503,13 +582,13 @@ GNUNET_CRYPTO_ecdhe_key_create ()
                                   "(flags eddsa no-keytest)))")))
   {
     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
-    return NULL;
+    return GNUNET_SYSERR;
   }
   if (0 != (rc = gcry_pk_genkey (&priv_sexp, s_keyparam)))
   {
     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_genkey", rc);
     gcry_sexp_release (s_keyparam);
-    return NULL;
+    return GNUNET_SYSERR;
   }
   gcry_sexp_release (s_keyparam);
 #if EXTRA_CHECKS
@@ -517,20 +596,22 @@ GNUNET_CRYPTO_ecdhe_key_create ()
   {
     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_pk_testkey", rc);
     gcry_sexp_release (priv_sexp);
-    return NULL;
+    return GNUNET_SYSERR;
   }
 #endif
   if (0 != (rc = key_from_sexp (&d, priv_sexp, "private-key", "d")))
   {
     LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "key_from_sexp", rc);
     gcry_sexp_release (priv_sexp);
-    return NULL;
+    return GNUNET_SYSERR;
   }
   gcry_sexp_release (priv_sexp);
-  priv = GNUNET_new (struct GNUNET_CRYPTO_EcdhePrivateKey);
-  GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
+  GNUNET_CRYPTO_mpi_print_unsigned (pk->d, sizeof (pk->d), d);
   gcry_mpi_release (d);
-  return priv;
+
+  BENCHMARK_END (ecdhe_key_create);
+
+  return GNUNET_OK;
 }
 
 
@@ -548,6 +629,8 @@ GNUNET_CRYPTO_ecdsa_key_create ()
   gcry_mpi_t d;
   int rc;
 
+  BENCHMARK_START (ecdsa_key_create);
+
   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
                                   "(genkey(ecc(curve \"" CURVE "\")"
                                   "(flags)))")))
@@ -580,6 +663,9 @@ GNUNET_CRYPTO_ecdsa_key_create ()
   priv = GNUNET_new (struct GNUNET_CRYPTO_EcdsaPrivateKey);
   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
   gcry_mpi_release (d);
+
+  BENCHMARK_END (ecdsa_key_create);
+
   return priv;
 }
 
@@ -597,6 +683,11 @@ GNUNET_CRYPTO_eddsa_key_create ()
   gcry_mpi_t d;
   int rc;
 
+  BENCHMARK_START (eddsa_key_create);
+
+#if CRYPTO_BUG
+ again:
+#endif
   if (0 != (rc = gcry_sexp_build (&s_keyparam, NULL,
                                   "(genkey(ecc(curve \"" CURVE "\")"
                                   "(flags eddsa)))")))
@@ -629,6 +720,19 @@ GNUNET_CRYPTO_eddsa_key_create ()
   priv = GNUNET_new (struct GNUNET_CRYPTO_EddsaPrivateKey);
   GNUNET_CRYPTO_mpi_print_unsigned (priv->d, sizeof (priv->d), d);
   gcry_mpi_release (d);
+
+#if CRYPTO_BUG
+  if (GNUNET_OK !=
+      check_eddsa_key (priv))
+  {
+    GNUNET_break (0);
+    GNUNET_free (priv);
+    goto again;
+  }
+#endif
+
+  BENCHMARK_END (eddsa_key_create);
+
   return priv;
 }
 
@@ -658,23 +762,6 @@ GNUNET_CRYPTO_ecdsa_key_get_anonymous ()
 }
 
 
-/**
- * Compare two Peer Identities.
- *
- * @param first first peer identity
- * @param second second peer identity
- * @return bigger than 0 if first > second,
- *         0 if they are the same
- *         smaller than 0 if second > first
- */
-int
-GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
-                                 const struct GNUNET_PeerIdentity *second)
-{
-  return memcmp (first, second, sizeof (struct GNUNET_PeerIdentity));
-}
-
-
 /**
  * Convert the data specified in the given purpose argument to an
  * S-expression suitable for signature operations.
@@ -685,19 +772,41 @@ GNUNET_CRYPTO_cmp_peer_identity (const struct GNUNET_PeerIdentity *first,
 static gcry_sexp_t
 data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
 {
-  struct GNUNET_HashCode hc;
   gcry_sexp_t data;
   int rc;
 
+/* SEE #5398 */
+#if 1
+  struct GNUNET_HashCode hc;
+
+  GNUNET_CRYPTO_hash (purpose,
+                     ntohl (purpose->size),
+                     &hc);
+  if (0 != (rc = gcry_sexp_build (&data, NULL,
+                                 "(data(flags eddsa)(hash-algo %s)(value %b))",
+                                 "sha512",
+                                 (int)sizeof (hc),
+                                 &hc)))
+  {
+    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
+             "gcry_sexp_build",
+             rc);
+    return NULL;
+  }
+#else
   GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
   if (0 != (rc = gcry_sexp_build (&data, NULL,
                                  "(data(flags eddsa)(hash-algo %s)(value %b))",
                                  "sha512",
-                                 (int)sizeof (hc), &hc)))
+                                 ntohl (purpose->size),
+                                 purpose)))
   {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
+    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
+             "gcry_sexp_build",
+             rc);
     return NULL;
   }
+#endif
   return data;
 }
 
@@ -712,19 +821,39 @@ data_to_eddsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
 static gcry_sexp_t
 data_to_ecdsa_value (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose)
 {
-  struct GNUNET_HashCode hc;
   gcry_sexp_t data;
   int rc;
 
-  GNUNET_CRYPTO_hash (purpose, ntohl (purpose->size), &hc);
+/* See #5398 */
+#if 1
+  struct GNUNET_HashCode hc;
+
+  GNUNET_CRYPTO_hash (purpose,
+                     ntohl (purpose->size),
+                     &hc);
   if (0 != (rc = gcry_sexp_build (&data, NULL,
                                  "(data(flags rfc6979)(hash %s %b))",
                                  "sha512",
                                  (int)sizeof (hc), &hc)))
   {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "gcry_sexp_build", rc);
+    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
+             "gcry_sexp_build",
+             rc);
+    return NULL;
+  }
+#else
+  if (0 != (rc = gcry_sexp_build (&data, NULL,
+                                 "(data(flags rfc6979)(hash %s %b))",
+                                 "sha512",
+                                 ntohl (purpose->size),
+                                 purpose)))
+  {
+    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR,
+             "gcry_sexp_build",
+             rc);
     return NULL;
   }
+#endif
   return data;
 }
 
@@ -748,6 +877,8 @@ GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
   int rc;
   gcry_mpi_t rs[2];
 
+  BENCHMARK_START (ecdsa_sign);
+
   priv_sexp = decode_private_ecdsa_key (priv);
   data = data_to_ecdsa_value (purpose);
   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
@@ -771,10 +902,17 @@ GNUNET_CRYPTO_ecdsa_sign (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
     return GNUNET_SYSERR;
   }
   gcry_sexp_release (sig_sexp);
-  GNUNET_CRYPTO_mpi_print_unsigned (sig->r, sizeof (sig->r), rs[0]);
-  GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
+  GNUNET_CRYPTO_mpi_print_unsigned (sig->r,
+                                   sizeof (sig->r),
+                                   rs[0]);
+  GNUNET_CRYPTO_mpi_print_unsigned (sig->s,
+                                   sizeof (sig->s),
+                                   rs[1]);
   gcry_mpi_release (rs[0]);
   gcry_mpi_release (rs[1]);
+
+  BENCHMARK_END (ecdsa_sign);
+
   return GNUNET_OK;
 }
 
@@ -798,6 +936,8 @@ GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
   int rc;
   gcry_mpi_t rs[2];
 
+  BENCHMARK_START (eddsa_sign);
+
   priv_sexp = decode_private_eddsa_key (priv);
   data = data_to_eddsa_value (purpose);
   if (0 != (rc = gcry_pk_sign (&sig_sexp, data, priv_sexp)))
@@ -825,6 +965,9 @@ GNUNET_CRYPTO_eddsa_sign (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
   GNUNET_CRYPTO_mpi_print_unsigned (sig->s, sizeof (sig->s), rs[1]);
   gcry_mpi_release (rs[0]);
   gcry_mpi_release (rs[1]);
+
+  BENCHMARK_END (eddsa_sign);
+
   return GNUNET_OK;
 }
 
@@ -849,6 +992,8 @@ GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
   gcry_sexp_t pub_sexpr;
   int rc;
 
+  BENCHMARK_START (ecdsa_verify);
+
   if (purpose != ntohl (validate->purpose))
     return GNUNET_SYSERR;       /* purpose mismatch */
 
@@ -879,8 +1024,10 @@ GNUNET_CRYPTO_ecdsa_verify (uint32_t purpose,
     LOG (GNUNET_ERROR_TYPE_INFO,
          _("ECDSA signature verification failed at %s:%d: %s\n"), __FILE__,
          __LINE__, gcry_strerror (rc));
+    BENCHMARK_END (ecdsa_verify);
     return GNUNET_SYSERR;
   }
+  BENCHMARK_END (ecdsa_verify);
   return GNUNET_OK;
 }
 
@@ -906,6 +1053,8 @@ GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
   gcry_sexp_t pub_sexpr;
   int rc;
 
+  BENCHMARK_START (eddsa_verify);
+
   if (purpose != ntohl (validate->purpose))
     return GNUNET_SYSERR;       /* purpose mismatch */
 
@@ -936,8 +1085,10 @@ GNUNET_CRYPTO_eddsa_verify (uint32_t purpose,
     LOG (GNUNET_ERROR_TYPE_INFO,
          _("EdDSA signature verification failed at %s:%d: %s\n"), __FILE__,
          __LINE__, gcry_strerror (rc));
+    BENCHMARK_END (eddsa_verify);
     return GNUNET_SYSERR;
   }
+  BENCHMARK_END (eddsa_verify);
   return GNUNET_OK;
 }
 
@@ -964,6 +1115,8 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
   unsigned char xbuf[256 / 8];
   size_t rsize;
 
+  BENCHMARK_START (ecc_ecdh);
+
   /* first, extract the q = dP value from the public key */
   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
                             "(public-key(ecc(curve " CURVE ")(q %b)))",
@@ -1007,6 +1160,7 @@ GNUNET_CRYPTO_ecc_ecdh (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
                       rsize,
                       key_material);
   gcry_mpi_release (result_x);
+  BENCHMARK_END (ecc_ecdh);
   return GNUNET_OK;
 }
 
@@ -1028,9 +1182,10 @@ derive_h (const struct GNUNET_CRYPTO_EcdsaPublicKey *pub,
 {
   gcry_mpi_t h;
   struct GNUNET_HashCode hc;
+  static const char *const salt = "key-derivation";
 
   GNUNET_CRYPTO_kdf (&hc, sizeof (hc),
-                    "key-derivation", strlen ("key-derivation"),
+                    salt, strlen (salt),
                     pub, sizeof (*pub),
                     label, strlen (label),
                     context, strlen (context),
@@ -1187,13 +1342,14 @@ eddsa_d_to_a (gcry_mpi_t d)
   size_t rawmpilen;
   unsigned char digest[64]; /* 512-bit hash value */
   gcry_buffer_t hvec[2];
-  int b;
+  unsigned int b;
   gcry_mpi_t a;
 
   b = 256 / 8; /* number of bytes in `d` */
 
   /* Note that we clear DIGEST so we can use it as input to left pad
      the key with zeroes for hashing.  */
+  memset (digest, 0, sizeof digest);
   memset (hvec, 0, sizeof hvec);
   rawmpilen = sizeof (rawmpi);
   GNUNET_assert (0 ==
@@ -1202,7 +1358,7 @@ eddsa_d_to_a (gcry_mpi_t d)
                                  d));
   hvec[0].data = digest;
   hvec[0].off = 0;
-  hvec[0].len = b > rawmpilen? b - rawmpilen : 0;
+  hvec[0].len = b > rawmpilen ? (b - rawmpilen) : 0;
   hvec[1].data = rawmpi;
   hvec[1].off = 0;
   hvec[1].len = rawmpilen;
@@ -1223,6 +1379,48 @@ eddsa_d_to_a (gcry_mpi_t d)
 }
 
 
+/**
+ * Take point from ECDH and convert it to key material.
+ *
+ * @param result point from ECDH
+ * @param ctx ECC context
+ * @param key_material[out] set to derived key material
+ * @return #GNUNET_OK on success
+ */
+static int
+point_to_hash (gcry_mpi_point_t result,
+               gcry_ctx_t ctx,
+               struct GNUNET_HashCode *key_material)
+{
+  gcry_mpi_t result_x;
+  unsigned char xbuf[256 / 8];
+  size_t rsize;
+
+  /* finally, convert point to string for hashing */
+  result_x = gcry_mpi_new (256);
+  if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
+  {
+    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
+    return GNUNET_SYSERR;
+  }
+
+  rsize = sizeof (xbuf);
+  GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
+  /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
+     as that does not include the sign bit; x should be a 255-bit
+     value, so with the sign it should fit snugly into the 256-bit
+     xbuf */
+  GNUNET_assert (0 ==
+                 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
+                                 result_x));
+  GNUNET_CRYPTO_hash (xbuf,
+                      rsize,
+                      key_material);
+  gcry_mpi_release (result_x);
+  return GNUNET_OK;
+}
+
+
 /**
  * @ingroup crypto
  * Derive key material from a ECDH public key and a private EdDSA key.
@@ -1244,9 +1442,9 @@ GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
   gcry_mpi_t a;
   gcry_ctx_t ctx;
   gcry_sexp_t pub_sexpr;
-  gcry_mpi_t result_x;
-  unsigned char xbuf[256 / 8];
-  size_t rsize;
+  int ret;
+
+  BENCHMARK_START (eddsa_ecdh);
 
   /* first, extract the q = dP value from the public key */
   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
@@ -1270,34 +1468,16 @@ GNUNET_CRYPTO_eddsa_ecdh (const struct GNUNET_CRYPTO_EddsaPrivateKey *priv,
   gcry_mpi_point_release (q);
   gcry_mpi_release (a);
 
-  /* finally, convert point to string for hashing */
-  result_x = gcry_mpi_new (256);
-  if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
-  {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
-    gcry_mpi_point_release (result);
-    gcry_ctx_release (ctx);
-    return GNUNET_SYSERR;
-  }
+  ret = point_to_hash (result,
+                       ctx,
+                       key_material);
   gcry_mpi_point_release (result);
   gcry_ctx_release (ctx);
-
-  rsize = sizeof (xbuf);
-  GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
-  /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
-     as that does not include the sign bit; x should be a 255-bit
-     value, so with the sign it should fit snugly into the 256-bit
-     xbuf */
-  GNUNET_assert (0 ==
-                 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
-                                 result_x));
-  GNUNET_CRYPTO_hash (xbuf,
-                      rsize,
-                      key_material);
-  gcry_mpi_release (result_x);
-  return GNUNET_OK;
+  BENCHMARK_END (eddsa_ecdh);
+  return ret;
 }
 
+
 /**
  * @ingroup crypto
  * Derive key material from a ECDH public key and a private ECDSA key.
@@ -1318,9 +1498,9 @@ GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
   gcry_mpi_t d;
   gcry_ctx_t ctx;
   gcry_sexp_t pub_sexpr;
-  gcry_mpi_t result_x;
-  unsigned char xbuf[256 / 8];
-  size_t rsize;
+  int ret;
+
+  BENCHMARK_START (ecdsa_ecdh);
 
   /* first, extract the q = dP value from the public key */
   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
@@ -1341,31 +1521,13 @@ GNUNET_CRYPTO_ecdsa_ecdh (const struct GNUNET_CRYPTO_EcdsaPrivateKey *priv,
   gcry_mpi_release (d);
 
   /* finally, convert point to string for hashing */
-  result_x = gcry_mpi_new (256);
-  if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
-  {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
-    gcry_mpi_point_release (result);
-    gcry_ctx_release (ctx);
-    return GNUNET_SYSERR;
-  }
+  ret = point_to_hash (result,
+                       ctx,
+                       key_material);
   gcry_mpi_point_release (result);
   gcry_ctx_release (ctx);
-
-  rsize = sizeof (xbuf);
-  GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
-  /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
-     as that does not include the sign bit; x should be a 255-bit
-     value, so with the sign it should fit snugly into the 256-bit
-     xbuf */
-  GNUNET_assert (0 ==
-                 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
-                                 result_x));
-  GNUNET_CRYPTO_hash (xbuf,
-                      rsize,
-                      key_material);
-  gcry_mpi_release (result_x);
-  return GNUNET_OK;
+  BENCHMARK_END (ecdsa_ecdh);
+  return ret;
 }
 
 
@@ -1390,9 +1552,9 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
   gcry_mpi_t d;
   gcry_ctx_t ctx;
   gcry_sexp_t pub_sexpr;
-  gcry_mpi_t result_x;
-  unsigned char xbuf[256 / 8];
-  size_t rsize;
+  int ret;
+
+  BENCHMARK_START (ecdh_eddsa);
 
   /* first, extract the q = dP value from the public key */
   if (0 != gcry_sexp_build (&pub_sexpr, NULL,
@@ -1413,31 +1575,13 @@ GNUNET_CRYPTO_ecdh_eddsa (const struct GNUNET_CRYPTO_EcdhePrivateKey *priv,
   gcry_mpi_release (d);
 
   /* finally, convert point to string for hashing */
-  result_x = gcry_mpi_new (256);
-  if (gcry_mpi_ec_get_affine (result_x, NULL, result, ctx))
-  {
-    LOG_GCRY (GNUNET_ERROR_TYPE_ERROR, "get_affine failed", 0);
-    gcry_mpi_point_release (result);
-    gcry_ctx_release (ctx);
-    return GNUNET_SYSERR;
-  }
+  ret = point_to_hash (result,
+                       ctx,
+                       key_material);
   gcry_mpi_point_release (result);
   gcry_ctx_release (ctx);
-
-  rsize = sizeof (xbuf);
-  GNUNET_assert (! gcry_mpi_get_flag (result_x, GCRYMPI_FLAG_OPAQUE));
-  /* result_x can be negative here, so we do not use 'GNUNET_CRYPTO_mpi_print_unsigned'
-     as that does not include the sign bit; x should be a 255-bit
-     value, so with the sign it should fit snugly into the 256-bit
-     xbuf */
-  GNUNET_assert (0 ==
-                 gcry_mpi_print (GCRYMPI_FMT_STD, xbuf, rsize, &rsize,
-                                 result_x));
-  GNUNET_CRYPTO_hash (xbuf,
-                      rsize,
-                      key_material);
-  gcry_mpi_release (result_x);
-  return GNUNET_OK;
+  BENCHMARK_END (ecdh_eddsa);
+  return ret;
 }
 
 /**