summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog15
-rw-r--r--ed25519-sha512-sign.c9
-rw-r--r--eddsa-hash.c34
-rw-r--r--eddsa-internal.h5
-rw-r--r--eddsa-pubkey.c3
-rw-r--r--eddsa-sign.c53
-rw-r--r--eddsa-verify.c3
-rw-r--r--testsuite/eddsa-sign-test.c5
8 files changed, 97 insertions, 30 deletions
diff --git a/ChangeLog b/ChangeLog
index b5db3abb..93a91d5a 100644
--- 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>
diff --git a/ed25519-sha512-sign.c b/ed25519-sha512-sign.c
index 0205e6f0..389a157e 100644
--- a/ed25519-sha512-sign.c
+++ b/ed25519-sha512-sign.c
@@ -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
diff --git a/eddsa-hash.c b/eddsa-hash.c
index 46f6ca34..e05f6ac1 100644
--- a/eddsa-hash.c
+++ b/eddsa-hash.c
@@ -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.
@@ -42,11 +44,35 @@
#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);
}
diff --git a/eddsa-internal.h b/eddsa-internal.h
index 4dd441f0..ea4c5e34 100644
--- a/eddsa-internal.h
+++ b/eddsa-internal.h
@@ -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,
diff --git a/eddsa-pubkey.c b/eddsa-pubkey.c
index c952ad17..72726e56 100644
--- a/eddsa-pubkey.c
+++ b/eddsa-pubkey.c
@@ -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;
}
diff --git a/eddsa-sign.c b/eddsa-sign.c
index 5e39fe69..a5970e98 100644
--- a/eddsa-sign.c
+++ b/eddsa-sign.c
@@ -45,14 +45,16 @@
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
diff --git a/eddsa-verify.c b/eddsa-verify.c
index e482c9b9..c4e65d69 100644
--- a/eddsa-verify.c
+++ b/eddsa-verify.c
@@ -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);
diff --git a/testsuite/eddsa-sign-test.c b/testsuite/eddsa-sign-test.c
index 4cfc4dbb..47ca6e76 100644
--- a/testsuite/eddsa-sign-test.c
+++ b/testsuite/eddsa-sign-test.c
@@ -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))