gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] branch master updated: edx25519: use libsodium, tweak KDF call


From: gnunet
Subject: [gnunet] branch master updated: edx25519: use libsodium, tweak KDF call
Date: Tue, 19 Apr 2022 14:45:28 +0200

This is an automated email from the git hooks/post-receive script.

dold pushed a commit to branch master
in repository gnunet.

The following commit(s) were added to refs/heads/master by this push:
     new 0487df9a0 edx25519: use libsodium, tweak KDF call
0487df9a0 is described below

commit 0487df9a041ac7ecde00d4ea4c6a204eaab06e70
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Apr 19 14:43:30 2022 +0200

    edx25519: use libsodium, tweak KDF call
---
 src/util/crypto_edx25519.c | 198 +++++++++++++++------------------------------
 1 file changed, 64 insertions(+), 134 deletions(-)

diff --git a/src/util/crypto_edx25519.c b/src/util/crypto_edx25519.c
index 26b45407e..2a7f75030 100644
--- a/src/util/crypto_edx25519.c
+++ b/src/util/crypto_edx25519.c
@@ -210,53 +210,28 @@ GNUNET_CRYPTO_edx25519_verify_ (
  * @param pub public key for deriviation
  * @param seed seed for key the deriviation
  * @param seedsize the size of the seed
- * @param n The value for the modulus 'n'
  * @param[out] phc if not NULL, the output of H() will be written into
  * return h_mod_n (allocated by this function)
  */
-static gcry_mpi_t
-derive_h_mod_n (
+static void
+derive_h (
   const struct GNUNET_CRYPTO_Edx25519PublicKey *pub,
   const void *seed,
   size_t seedsize,
-  const gcry_mpi_t n,
   struct GNUNET_HashCode *phc)
 {
   static const char *const salt = "edx2559-derivation";
-  struct GNUNET_HashCode hc;
-  gcry_mpi_t h;
-  gcry_mpi_t h_mod_n;
-
-  if (NULL == phc)
-    phc = &hc;
 
-  GNUNET_CRYPTO_kdf (phc, sizeof(*phc),
-                     salt, strlen (salt),
+  GNUNET_CRYPTO_kdf (/* output*/
+                     phc, sizeof(*phc),
+                     /* salt */
                      pub, sizeof(*pub),
+                     /* ikm */
                      seed, seedsize,
+                     /* ctx chunks*/
+                     salt, strlen (salt),
                      NULL, 0);
 
-  /* calculate h_mod_n = h % n */
-  GNUNET_CRYPTO_mpi_scan_unsigned (&h,
-                                   (unsigned char *) phc,
-                                   sizeof(*phc));
-  h_mod_n = gcry_mpi_new (256);
-  gcry_mpi_mod (h_mod_n, h, n);
-
-#ifdef CHECK_RARE_CASES
-  /**
-   * Note that the following cases would be problematic:
-   *   1.) h == 0 mod n
-   *   2.) h == 1 mod n
-   *   3.) [h] * P == E
-   * We assume that the probalities for these cases to occur are neglegible.
-   */
-  GNUNET_assert (! gcry_mpi_cmp_ui (h_mod_n, 0));
-  GNUNET_assert (! gcry_mpi_cmp_ui (h_mod_n, 1));
-#endif
-
-  gcry_mpi_release(h);
-  return h_mod_n;
 }
 
 
@@ -270,40 +245,37 @@ GNUNET_CRYPTO_edx25519_private_key_derive (
   struct GNUNET_CRYPTO_Edx25519PublicKey pub;
   struct GNUNET_HashCode hc;
   uint8_t a[32];
-  gcry_ctx_t ctx;
-  gcry_mpi_t h_mod_n;
-  gcry_mpi_t x;
-  gcry_mpi_t n;
-  gcry_mpi_t a1;
-  gcry_mpi_t a2;
-  gcry_mpi_t ap; // a'
+  uint8_t eight[32] = { 8 };
+  uint8_t eight_inv[32];
+  uint8_t h[64] = { 0 };
 
   GNUNET_CRYPTO_edx25519_key_get_public (priv, &pub);
 
-  /**
-   * Libsodium does not offer an API with arbitrary arithmetic.
-   * Hence we have to use libgcrypt here.
-   */
-  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
-
-  /**
-   * Get our modulo
-   */
-  n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
-  GNUNET_assert (NULL != n);
+  /* Get h mod n */
+  derive_h (&pub,
+            seed,
+            seedsize,
+            &hc);
 
+  memcpy (h, &hc, 64);
+  crypto_core_ed25519_scalar_reduce (h,
+                                     h);
+#ifdef CHECK_RARE_CASES
   /**
-   * Get h mod n
+   * Note that the following cases would be problematic:
+   *   1.) h == 0 mod n
+   *   2.) h == 1 mod n
+   *   3.) [h] * P == E
+   * We assume that the probalities for these cases to occur are neglegible.
    */
-  h_mod_n = derive_h_mod_n (&pub,
-                            seed,
-                            seedsize,
-                            n,
-                            &hc);
+  {
+    char zero[32] = { 0 };
+    char one[32] = { 1 };
 
-  /* Convert priv->a scalar to big endian for libgcrypt */
-  for (size_t i = 0; i < 32; i++)
-    a[i] = priv->a[31 - i];
+    GNUNET_assert (0 != memcmp (zero, h, 32));
+    GNUNET_assert (0 != memcmp (one, h, 32));
+  }
+#endif
 
   /**
    * dc now contains the private scalar "a".
@@ -313,37 +285,29 @@ GNUNET_CRYPTO_edx25519_private_key_derive (
    * a2 := h * a1 mod n
    * a' := a2 * 8 mod n
    */
-  GNUNET_CRYPTO_mpi_scan_unsigned (&x, a, sizeof(a)); // a
-  a1 = gcry_mpi_new (256);
-  gcry_mpi_t eight = gcry_mpi_set_ui (NULL, 8);
-  gcry_mpi_div (a1, NULL, x, eight, 0); // a1 := a / 8
-  a2 = gcry_mpi_new (256);
-  gcry_mpi_mulm (a2, h_mod_n, a1, n); // a2 := h * a1 mod n
-  ap = gcry_mpi_new (256);
-  gcry_mpi_mul (ap, a2, eight); // a' := a2 * 8
+
+  GNUNET_assert (0 == crypto_core_ed25519_scalar_invert (eight_inv,
+                                                         eight));
+
+  crypto_core_ed25519_scalar_mul (a, priv->a, eight_inv);
+  crypto_core_ed25519_scalar_mul (a, a, h);
+  crypto_core_ed25519_scalar_mul (a, a, eight);
 
 #ifdef CHECK_RARE_CASES
   /* The likelihood for a' == 0 or a' == 1 is neglegible */
-  GNUNET_assert (! gcry_mpi_cmp_ui (ap, 0));
-  GNUNET_assert (! gcry_mpi_cmp_ui (ap, 1));
-#endif
+  {
+    char zero[32] = { 0 };
+    char one[32] = { 1 };
 
-  gcry_mpi_release (h_mod_n);
-  gcry_mpi_release (eight);
-  gcry_mpi_release (x);
-  gcry_mpi_release (n);
-  gcry_mpi_release (a1);
-  gcry_mpi_release (a2);
-  gcry_ctx_release (ctx);
-  GNUNET_CRYPTO_mpi_print_unsigned (a, sizeof(a), ap);
-  gcry_mpi_release (ap);
+    GNUNET_assert (0 != memcmp (zero, a, 32));
+    GNUNET_assert (0 != memcmp (one, a, 32));
+  }
+#endif
 
-  /**
-   * We hash the derived "h" parameter with the other half of the expanded
+  /* We hash the derived "h" parameter with the other half of the expanded
    * private key (that is: priv->b). This ensures that for signature
    * generation, the "R" is derived from the same derivation path as "h" and is
-   * not reused.
-   */
+   * not reused. */
   {
     crypto_hash_sha256_state hs;
     crypto_hash_sha256_init (&hs);
@@ -352,9 +316,8 @@ GNUNET_CRYPTO_edx25519_private_key_derive (
     crypto_hash_sha256_final (&hs, result->b);
   }
 
-  /* Convert to little endian for libsodium */
   for (size_t i = 0; i < 32; i++)
-    result->a[i] = a[31 - i];
+    result->a[i] = a[i];
 
   sodium_memzero (a, sizeof(a));
 }
@@ -367,52 +330,19 @@ GNUNET_CRYPTO_edx25519_public_key_derive (
   size_t seedsize,
   struct GNUNET_CRYPTO_Edx25519PublicKey *result)
 {
-  gcry_ctx_t ctx;
-  gcry_mpi_t q_y;
-  gcry_mpi_t n;
-  gcry_mpi_t h_mod_n;
-  gcry_mpi_point_t q;
-  gcry_mpi_point_t v;
-
-  GNUNET_assert (0 == gcry_mpi_ec_new (&ctx, NULL, "Ed25519"));
-
-  /* obtain point 'q' from original public key.  The provided 'q' is
-     compressed thus we first store it in the context and then get it
-     back as a (decompresssed) point.  */
-  q_y = gcry_mpi_set_opaque_copy (NULL,
-                                  pub->q_y,
-                                  8 * sizeof(pub->q_y));
-  GNUNET_assert (NULL != q_y);
-  GNUNET_assert (0 == gcry_mpi_ec_set_mpi ("q", q_y, ctx));
-  gcry_mpi_release (q_y);
-  q = gcry_mpi_ec_get_point ("q", ctx, 0);
-  GNUNET_assert (q);
-
-  /**
-   * Get h mod n
-   */
-  n = gcry_mpi_ec_get_mpi ("n", ctx, 1);
-  GNUNET_assert (NULL != n);
-  GNUNET_assert (NULL != pub);
-  h_mod_n = derive_h_mod_n (pub,
-                            seed,
-                            seedsize,
-                            n,
-                            NULL /* We don't need hc here */);
-
-  /* calculate v = h_mod_n * q */
-  v = gcry_mpi_point_new (0);
-  gcry_mpi_ec_mul (v, h_mod_n, q, ctx);
-  gcry_mpi_release (h_mod_n);
-  gcry_mpi_release (n);
-  gcry_mpi_point_release (q);
-
-  /* convert point 'v' to public key that we return */
-  GNUNET_assert (0 == gcry_mpi_ec_set_point ("q", v, ctx));
-  gcry_mpi_point_release (v);
-  q_y = gcry_mpi_ec_get_mpi ("q@eddsa", ctx, 0);
-  GNUNET_assert (q_y);
-  GNUNET_CRYPTO_mpi_print_unsigned (result->q_y, sizeof(result->q_y), q_y);
-  gcry_mpi_release (q_y);
-  gcry_ctx_release (ctx);
+  struct GNUNET_HashCode hc;
+  uint8_t h[64] = { 0 };
+
+  derive_h (pub,
+            seed,
+            seedsize,
+            &hc);
+  memcpy (h,
+          &hc,
+          64);
+  crypto_core_ed25519_scalar_reduce (h,
+                                     h);
+  GNUNET_assert (0 == crypto_scalarmult_ed25519_noclamp (result->q_y,
+                                                         h,
+                                                         pub->q_y));
 }

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]