]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Update eddsa internals to support ed448.
authorNiels Möller <nisse@lysator.liu.se>
Thu, 2 Jan 2020 18:36:17 +0000 (19:36 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Thu, 2 Jan 2020 18:36:17 +0000 (19:36 +0100)
ChangeLog
ed25519-sha512-sign.c
eddsa-hash.c
eddsa-internal.h
eddsa-pubkey.c
eddsa-sign.c
eddsa-verify.c
testsuite/eddsa-sign-test.c

index b5db3abbb43596878af9eaa98ffa7c59194e5647..93a91d5aa087106c497263baac134c9e37bd26ca 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -2,6 +2,21 @@
 
        * eddsa-internal.h (struct ecc_eddsa): Add magic "dom" string,
        needed for ed448.
+       * ed25519-sha512.c (_nettle_ed25519_sha512): Empty dom string.
+       * ed448-shake256.c (_nettle_ed448_shake256): New file and
+       parameter struct.
+
+       * eddsa-hash.c (_eddsa_hash): Add digest_size as input argument.
+       Handle ed448 digests with two extra bytes. Update callers.
+       * eddsa-verify.c (_eddsa_verify): Hash dom string.
+       * eddsa-sign.c (_eddsa_sign_itch): Assert that
+       _eddsa_compress_itch isn't too large.
+       (_eddsa_sign): New argument k1, with the hash prefix. Add hashing
+       of this prefix and the dom string. Update callers. Fix final
+       reduction, it's different for ed25519, with q slightly larger than
+       a power of two, and ed448, with q slightly smaller.
+       * eddsa-pubkey.c (_eddsa_public_key_itch): Assert that
+       _eddsa_compress_itch isn't too large.
 
 2020-01-01  Niels Möller  <nisse@lysator.liu.se>
 
index 0205e6f0b0996b53d6eadb2ac47b25edaadbb170..389a157e9c684df85abf3d06fe48792299568ec4 100644 (file)
@@ -52,14 +52,13 @@ ed25519_sha512_sign (const uint8_t *pub,
 #define scratch_out (scratch + ecc->q.size)
   struct sha512_ctx ctx;
   uint8_t digest[SHA512_DIGEST_SIZE];
-#define k1 (digest + ED25519_KEY_SIZE)
+
   sha512_init (&ctx);
   _eddsa_expand_key (ecc, &_nettle_ed25519_sha512, &ctx, priv, digest, k2);
 
-  sha512_update (&ctx, ED25519_KEY_SIZE, k1);
-  _eddsa_sign (ecc, &_nettle_ed25519_sha512, pub,
-              &ctx,
-              k2, length, msg, signature, scratch_out);
+  _eddsa_sign (ecc, &_nettle_ed25519_sha512, &ctx,
+              pub, digest + ED25519_KEY_SIZE, k2,
+              length, msg, signature, scratch_out);
 
   gmp_free_limbs (scratch, itch);
 #undef k1
index 46f6ca34422c82bcac60dc49c14ede51140c126a..e05f6ac1a5ed648ac48a6f6af1f8e395e2e33964 100644 (file)
@@ -1,6 +1,8 @@
 /* eddsa-hash.c
 
-   Copyright (C) 2014 Niels Möller
+   Copyright (C) 2014, 2019 Niels Möller
+   Copyright (C) 2017 Daiki Ueno
+   Copyright (C) 2017 Red Hat, Inc.
 
    This file is part of GNU Nettle.
 
 #include "ecc-internal.h"
 #include "nettle-internal.h"
 
+/* Convert hash digest to integer, and reduce modulo q, to m->size
+   limbs. Needs space for 2*m->size + 1 at rp. */
 void
 _eddsa_hash (const struct ecc_modulo *m,
-            mp_limb_t *rp, const uint8_t *digest)
+            mp_limb_t *rp, size_t digest_size, const uint8_t *digest)
 {
-  size_t nbytes = 1 + m->bit_size / 8;
-  mpn_set_base256_le (rp, 2*m->size, digest, 2*nbytes);
+  mp_size_t nlimbs = (8*digest_size + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
+
+  mpn_set_base256_le (rp, nlimbs, digest, digest_size);
+
+  if (nlimbs > 2*m->size)
+    {
+      /* Special case for Ed448: reduce rp to 2*m->size limbs.
+        After decoding rp from a hash of size 2*rn:
+
+        rp = r2 || r1 || r0
+
+        where r0 and r1 have m->size limbs.  Reduce this to:
+
+        rp = r1' || r0
+
+        where r1' has m->size limbs.  */
+      mp_limb_t hi = rp[2*m->size];
+      assert (nlimbs == 2*m->size + 1);
+
+      hi = mpn_addmul_1 (rp + m->size, m->B, m->size, hi);
+      assert (hi <= 1);
+      hi = cnd_add_n (hi, rp + m->size, m->B, m->size);
+      assert (hi == 0);
+    }
   m->mod (m, rp);
 }
index 4dd441f0c8568f3738d326cf17b18858d46c6fec..ea4c5e349516fd0ad523139568bb036b9c67f73e 100644 (file)
@@ -82,7 +82,7 @@ _eddsa_decompress (const struct ecc_curve *ecc, mp_limb_t *p,
 
 void
 _eddsa_hash (const struct ecc_modulo *m,
-            mp_limb_t *rp, const uint8_t *digest);
+            mp_limb_t *rp, size_t digest_size, const uint8_t *digest);
 
 mp_size_t
 _eddsa_sign_itch (const struct ecc_curve *ecc);
@@ -90,8 +90,9 @@ _eddsa_sign_itch (const struct ecc_curve *ecc);
 void
 _eddsa_sign (const struct ecc_curve *ecc,
             const struct ecc_eddsa *eddsa,
-            const uint8_t *pub,
             void *ctx,
+            const uint8_t *pub,
+            const uint8_t *k1,
             const mp_limb_t *k2,
             size_t length,
             const uint8_t *msg,
index c952ad17421946e282f50e4926d997ffec3a9b54..72726e567d98cfdcbc1081498ce9d8d9f66ab2a5 100644 (file)
@@ -33,6 +33,8 @@
 # include "config.h"
 #endif
 
+#include <assert.h>
+
 #include "eddsa.h"
 #include "eddsa-internal.h"
 
@@ -41,6 +43,7 @@
 mp_size_t
 _eddsa_public_key_itch (const struct ecc_curve *ecc)
 {
+  assert (_eddsa_compress_itch (ecc) <= ecc->mul_g_itch);
   return 3*ecc->p.size + ecc->mul_g_itch;
 }
 
index 5e39fe6906219825f0ccc813dc679d8743f0773e..a5970e984d84871e23882f7c454754f05cd4f890 100644 (file)
 mp_size_t
 _eddsa_sign_itch (const struct ecc_curve *ecc)
 {
+  assert (_eddsa_compress_itch (ecc) <= ecc->mul_g_itch);
   return 5*ecc->p.size + ecc->mul_g_itch;
 }
 
 void
 _eddsa_sign (const struct ecc_curve *ecc,
             const struct ecc_eddsa *eddsa,
-            const uint8_t *pub,
             void *ctx,
+            const uint8_t *pub,
+            const uint8_t *k1,
             const mp_limb_t *k2,
             size_t length,
             const uint8_t *msg,
@@ -61,6 +63,8 @@ _eddsa_sign (const struct ecc_curve *ecc,
 {
   mp_size_t size;
   size_t nbytes;
+  mp_limb_t q, cy;
+
 #define rp scratch
 #define hp (scratch + size)
 #define P (scratch + 2*size)
@@ -71,32 +75,51 @@ _eddsa_sign (const struct ecc_curve *ecc,
   size = ecc->p.size;
   nbytes = 1 + ecc->p.bit_size / 8;
 
+  eddsa->update (ctx, eddsa->dom_size, eddsa->dom);
+  eddsa->update (ctx, nbytes, k1);
   eddsa->update (ctx, length, msg);
   eddsa->digest (ctx, 2*nbytes, hash);
-  _eddsa_hash (&ecc->q, rp, hash);
+  _eddsa_hash (&ecc->q, rp, 2*nbytes, hash);
+
   ecc->mul_g (ecc, P, rp, scratch_out);
   _eddsa_compress (ecc, signature, P, scratch_out);
 
+  eddsa->update (ctx, eddsa->dom_size, eddsa->dom);
   eddsa->update (ctx, nbytes, signature);
   eddsa->update (ctx, nbytes, pub);
   eddsa->update (ctx, length, msg);
   eddsa->digest (ctx, 2*nbytes, hash);
-  _eddsa_hash (&ecc->q, hp, hash);
+  _eddsa_hash (&ecc->q, hp, 2*nbytes, hash);
 
   ecc_modq_mul (ecc, sp, hp, k2);
   ecc_modq_add (ecc, sp, sp, rp); /* FIXME: Can be plain add */
-  /* FIXME: Special code duplicated in ecc_25519_modq and ecc_eh_to_a.
-     Define a suitable method? */
-  {
-    unsigned shift;
-    mp_limb_t cy;
-    assert (ecc->p.bit_size == 255);
-    shift = ecc->q.bit_size - 1 - GMP_NUMB_BITS * (ecc->p.size - 1);
-    cy = mpn_submul_1 (sp, ecc->q.m, ecc->p.size,
-                      sp[ecc->p.size-1] >> shift);
-    assert (cy < 2);
-    cnd_add_n (cy, sp, ecc->q.m, ecc->p.size);
-  }
+  if (ecc->p.bit_size == 255)
+    {
+      /* FIXME: Special code duplicated in ecc_25519_modq
+        Define a suitable method for canonical reduction? */
+
+      /* q is slightly larger than 2^252, underflow from below
+        mpn_submul_1 is unlikely. */
+      unsigned shift = 252 - GMP_NUMB_BITS * (ecc->p.size - 1);
+      q = sp[ecc->p.size-1] >> shift;
+    }
+  else
+    {
+      unsigned shift;
+
+      assert (ecc->p.bit_size == 448);
+      /* q is slightly smaller than 2^446 */
+      shift = 446 - GMP_NUMB_BITS * (ecc->p.size - 1);
+      /* Add one, then it's possible but unlikely that below
+        mpn_submul_1 does *not* underflow. */
+      q = (sp[ecc->p.size-1] >> shift) + 1;
+    }
+
+  cy = mpn_submul_1 (sp, ecc->q.m, ecc->p.size, q);
+  assert (cy < 2);
+  cy -= cnd_add_n (cy, sp, ecc->q.m, ecc->p.size);
+  assert (cy == 0);
+
   mpn_get_base256_le (signature + nbytes, nbytes, sp, ecc->q.size);
 #undef rp
 #undef hp
index e482c9b99c0eb8d1d085cd6d1c5d754f1281e359..c4e65d69c6a71961463f830c52285b604826639c 100644 (file)
@@ -106,11 +106,12 @@ _eddsa_verify (const struct ecc_curve *ecc,
   if (mpn_cmp (sp, ecc->q.m, ecc->q.size) >= 0)
     return 0;
 
+  eddsa->update (ctx, eddsa->dom_size, eddsa->dom);
   eddsa->update (ctx, nbytes, signature);
   eddsa->update (ctx, nbytes, pub);
   eddsa->update (ctx, length, msg);
   eddsa->digest (ctx, 2*nbytes, hash);
-  _eddsa_hash (&ecc->q, hp, hash);
+  _eddsa_hash (&ecc->q, hp, 2*nbytes, hash);
 
   /* Compute h A + R - s G, which should be the neutral point */
   ecc->mul (ecc, P, hp, A, scratch_out);
index 4cfc4dbb192188738b9483e1a1bfa2a390d269a0..47ca6e76037737c31b11450914849ec481b8ed56 100644 (file)
@@ -69,9 +69,8 @@ test_eddsa_sign (const struct ecc_curve *ecc,
       fprintf (stderr, "\n");
       abort ();
     }
-  eddsa->update (ctx, nbytes, k1);
-  
-  _eddsa_sign (ecc, eddsa, public->data, ctx, k2,
+  _eddsa_sign (ecc, eddsa, ctx,
+              public->data, k1, k2,
               msg->length, msg->data, signature, scratch);
 
   if (!MEMEQ (2*nbytes, signature, ref->data))