summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog38
-rw-r--r--ecc-192.c5
-rw-r--r--ecc-224.c5
-rw-r--r--ecc-25519.c7
-rw-r--r--ecc-256.c5
-rw-r--r--ecc-384.c5
-rw-r--r--ecc-521.c5
-rw-r--r--ecc-eh-to-a.c9
-rw-r--r--ecc-internal.h21
-rw-r--r--ecc-mul-a-eh.c12
-rw-r--r--ecc-mul-g-eh.c4
-rw-r--r--eccdata.c301
-rw-r--r--eddsa-sign.c2
-rw-r--r--testsuite/ecc-add-test.c71
-rw-r--r--testsuite/ecc-dup-test.c29
15 files changed, 285 insertions, 234 deletions
diff --git a/ChangeLog b/ChangeLog
index f2a85d01..a63ca94e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,41 @@
+2019-11-21 Niels Möller <nisse@lysator.liu.se>
+
+ * Merge curve448 preparations, from September 2017.
+
+2017-09-23 Niels Möller <nisse@lysator.liu.se>
+
+ * eccdata.c: Reorganize curve25519 precomputation to work directly
+ with the twisted Edwards curve, with new point addition based on a
+ patch from Daiki Ueno.
+ * ecc-25519.c (_nettle_curve25519): Update for removed Montgomery
+ curve constant.
+
+ * ecc-internal.h (struct ecc_curve): Delete unused pointer
+ edwards_root. Update all instances.
+ * eccdata.c (output_curve): Don't output it.
+
+ * testsuite/ecc-add-test.c (test_main): Reduce test duplication.
+ Use ecc->add_hhh_itch.
+ * testsuite/ecc-dup-test.c (test_main): Reduce test duplication.
+ Use ecc->dup_itch.
+
+2017-09-23 Daiki Ueno <dueno@redhat.com>
+
+ * ecc-eh-to-a.c (ecc_eh_to_a): Use ecc->q.bit_size, instead of
+ hard-coded value for curve25519.
+ * eddsa-sign.c (_eddsa_sign): Likewise.
+
+ * ecc-internal.h (ecc_dup_func): New typedef.
+ (struct ecc_curve): New constants add_hh_itch and dup_itch, new
+ function pointers add_hh and dup.
+ * ecc-192.c, ecc-224.c, ecc-256.c, ecc-384.c, ecc-521.c,
+ ecc-25519.c: Update accordingly.
+ * ecc-mul-g-eh.c (ecc_mul_g_eh): Use new function pointers.
+ * ecc-mul-a-eh.c (ecc_mul_a_eh, table_init, ecc_mul_a_eh):
+ Likewise.
+ * testsuite/ecc-dup-test.c (test_main): Likewise.
+ * testsuite/ecc-add-test.c (test_main): Likewise.
+
2019-10-01 Niels Möller <nisse@lysator.liu.se>
* testsuite/testutils.c (test_cipher_cfb8): Reset destination area
diff --git a/ecc-192.c b/ecc-192.c
index 4f428113..4b756ffd 100644
--- a/ecc-192.c
+++ b/ecc-192.c
@@ -155,19 +155,22 @@ const struct ecc_curve _nettle_secp_192r1 =
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
+ ECC_ADD_JJA_ITCH (ECC_LIMB_SIZE),
ECC_ADD_JJJ_ITCH (ECC_LIMB_SIZE),
+ ECC_DUP_JJ_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_ITCH (ECC_LIMB_SIZE),
ECC_J_TO_A_ITCH (ECC_LIMB_SIZE),
+ ecc_add_jja,
ecc_add_jjj,
+ ecc_dup_jj,
ecc_mul_a,
ecc_mul_g,
ecc_j_to_a,
ecc_b,
ecc_g,
- NULL,
ecc_unit,
ecc_table
};
diff --git a/ecc-224.c b/ecc-224.c
index 5962e1b8..bf90f848 100644
--- a/ecc-224.c
+++ b/ecc-224.c
@@ -107,19 +107,22 @@ const struct ecc_curve _nettle_secp_224r1 =
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
+ ECC_ADD_JJA_ITCH (ECC_LIMB_SIZE),
ECC_ADD_JJJ_ITCH (ECC_LIMB_SIZE),
+ ECC_DUP_JJ_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_ITCH (ECC_LIMB_SIZE),
ECC_J_TO_A_ITCH (ECC_LIMB_SIZE),
+ ecc_add_jja,
ecc_add_jjj,
+ ecc_dup_jj,
ecc_mul_a,
ecc_mul_g,
ecc_j_to_a,
ecc_b,
ecc_g,
- NULL,
ecc_unit,
ecc_table
};
diff --git a/ecc-25519.c b/ecc-25519.c
index bb71a36b..105ce0f4 100644
--- a/ecc-25519.c
+++ b/ecc-25519.c
@@ -335,19 +335,22 @@ const struct ecc_curve _nettle_curve25519 =
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
+ ECC_ADD_EH_ITCH (ECC_LIMB_SIZE),
ECC_ADD_EHH_ITCH (ECC_LIMB_SIZE),
+ ECC_DUP_EH_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_EH_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_EH_ITCH (ECC_LIMB_SIZE),
ECC_EH_TO_A_ITCH (ECC_LIMB_SIZE, ECC_25519_INV_ITCH),
+ ecc_add_eh,
ecc_add_ehh,
+ ecc_dup_eh,
ecc_mul_a_eh,
ecc_mul_g_eh,
ecc_eh_to_a,
- ecc_d, /* Use the Edwards curve constant. */
+ ecc_b, /* Edwards curve constant. */
ecc_g,
- ecc_edwards,
ecc_unit,
ecc_table
};
diff --git a/ecc-256.c b/ecc-256.c
index 7eed2835..3e6ae4e2 100644
--- a/ecc-256.c
+++ b/ecc-256.c
@@ -284,19 +284,22 @@ const struct ecc_curve _nettle_secp_256r1 =
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
+ ECC_ADD_JJA_ITCH (ECC_LIMB_SIZE),
ECC_ADD_JJJ_ITCH (ECC_LIMB_SIZE),
+ ECC_DUP_JJ_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_ITCH (ECC_LIMB_SIZE),
ECC_J_TO_A_ITCH (ECC_LIMB_SIZE),
+ ecc_add_jja,
ecc_add_jjj,
+ ecc_dup_jj,
ecc_mul_a,
ecc_mul_g,
ecc_j_to_a,
ecc_b,
ecc_g,
- NULL,
ecc_unit,
ecc_table
};
diff --git a/ecc-384.c b/ecc-384.c
index 94b8af91..5bb2a247 100644
--- a/ecc-384.c
+++ b/ecc-384.c
@@ -192,19 +192,22 @@ const struct ecc_curve _nettle_secp_384r1 =
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
+ ECC_ADD_JJA_ITCH (ECC_LIMB_SIZE),
ECC_ADD_JJJ_ITCH (ECC_LIMB_SIZE),
+ ECC_DUP_JJ_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_ITCH (ECC_LIMB_SIZE),
ECC_J_TO_A_ITCH (ECC_LIMB_SIZE),
+ ecc_add_jja,
ecc_add_jjj,
+ ecc_dup_jj,
ecc_mul_a,
ecc_mul_g,
ecc_j_to_a,
ecc_b,
ecc_g,
- NULL,
ecc_unit,
ecc_table
};
diff --git a/ecc-521.c b/ecc-521.c
index 52a018dd..8ca0e6d2 100644
--- a/ecc-521.c
+++ b/ecc-521.c
@@ -120,19 +120,22 @@ const struct ecc_curve _nettle_secp_521r1 =
ECC_PIPPENGER_K,
ECC_PIPPENGER_C,
+ ECC_ADD_JJA_ITCH (ECC_LIMB_SIZE),
ECC_ADD_JJJ_ITCH (ECC_LIMB_SIZE),
+ ECC_DUP_JJ_ITCH (ECC_LIMB_SIZE),
ECC_MUL_A_ITCH (ECC_LIMB_SIZE),
ECC_MUL_G_ITCH (ECC_LIMB_SIZE),
ECC_J_TO_A_ITCH (ECC_LIMB_SIZE),
+ ecc_add_jja,
ecc_add_jjj,
+ ecc_dup_jj,
ecc_mul_a,
ecc_mul_g,
ecc_j_to_a,
ecc_b,
ecc_g,
- NULL,
ecc_unit,
ecc_table
};
diff --git a/ecc-eh-to-a.c b/ecc-eh-to-a.c
index 2acaacb1..8173b887 100644
--- a/ecc-eh-to-a.c
+++ b/ecc-eh-to-a.c
@@ -68,12 +68,13 @@ ecc_eh_to_a (const struct ecc_curve *ecc,
/* Skip y coordinate */
if (op > 1)
{
- /* Reduce modulo q. FIXME: Hardcoded for curve25519,
- duplicates end of ecc_25519_modq. FIXME: Is this needed
- at all? Full reduction mod p is maybe sufficient. */
+ /* Reduce modulo q. Hardcoded for curve25519, duplicates end
+ of ecc_25519_modq. FIXME: Is this needed at all? op > 0
+ is only used by ecdsa code, and ecdsa on Edwards curves
+ makes little sense and is is only used by tests. */
unsigned shift;
assert (ecc->p.bit_size == 255);
- shift = 252 - GMP_NUMB_BITS * (ecc->p.size - 1);
+ shift = ecc->q.bit_size - 1 - GMP_NUMB_BITS * (ecc->p.size - 1);
cy = mpn_submul_1 (r, ecc->q.m, ecc->p.size,
r[ecc->p.size-1] >> shift);
assert (cy < 2);
diff --git a/ecc-internal.h b/ecc-internal.h
index 7d961f11..18c1bf7d 100644
--- a/ecc-internal.h
+++ b/ecc-internal.h
@@ -118,6 +118,10 @@ typedef void ecc_add_func (const struct ecc_curve *ecc,
const mp_limb_t *p, const mp_limb_t *q,
mp_limb_t *scratch);
+typedef void ecc_dup_func (const struct ecc_curve *ecc,
+ mp_limb_t *r, const mp_limb_t *p,
+ mp_limb_t *scratch);
+
typedef void ecc_mul_g_func (const struct ecc_curve *ecc, mp_limb_t *r,
const mp_limb_t *np, mp_limb_t *scratch);
@@ -174,12 +178,16 @@ struct ecc_curve
unsigned short pippenger_k;
unsigned short pippenger_c;
+ unsigned short add_hh_itch;
unsigned short add_hhh_itch;
+ unsigned short dup_itch;
unsigned short mul_itch;
unsigned short mul_g_itch;
unsigned short h_to_a_itch;
+ ecc_add_func *add_hh;
ecc_add_func *add_hhh;
+ ecc_dup_func *dup;
ecc_mul_func *mul;
ecc_mul_g_func *mul_g;
ecc_h_to_a_func *h_to_a;
@@ -189,9 +197,6 @@ struct ecc_curve
/* Generator, x coordinate followed by y (affine coordinates).
Currently used only by the test suite. */
const mp_limb_t *g;
- /* If non-NULL, the constant needed for transformation to the
- equivalent Edwards curve. */
- const mp_limb_t *edwards_root;
/* For redc, same as B mod p, otherwise 1. */
const mp_limb_t *unit;
@@ -281,18 +286,16 @@ ecc_a_to_j (const struct ecc_curve *ecc,
/* Converts a point P in jacobian coordinates into a point R in affine
coordinates. If op == 1, produce x coordinate only. If op == 2,
- produce the x coordinate only, and also reduce it modulo q. FIXME:
- For the public interface, have separate functions for the three
- cases, and use this flag argument only for the internal ecc->h_to_a
- function. */
+ produce the x coordinate only, and also reduce it modulo q. */
void
ecc_j_to_a (const struct ecc_curve *ecc,
int op,
mp_limb_t *r, const mp_limb_t *p,
mp_limb_t *scratch);
-/* Converts a point P on an Edwards curve to affine coordinates on
- the corresponding Montgomery curve. */
+/* Converts a point P in homogeneous coordinates on an Edwards curve
+ to affine coordinates. Meaning of op is the same as for
+ ecc_j_to_a. */
void
ecc_eh_to_a (const struct ecc_curve *ecc,
int op,
diff --git a/ecc-mul-a-eh.c b/ecc-mul-a-eh.c
index cf743236..e9b22cd4 100644
--- a/ecc-mul-a-eh.c
+++ b/ecc-mul-a-eh.c
@@ -75,8 +75,8 @@ ecc_mul_a_eh (const struct ecc_curve *ecc,
{
int digit;
- ecc_dup_eh (ecc, r, r, scratch_out);
- ecc_add_ehh (ecc, tp, r, pe, scratch_out);
+ ecc->dup (ecc, r, r, scratch_out);
+ ecc->add_hhh (ecc, tp, r, pe, scratch_out);
digit = (w & bit) > 0;
/* If we had a one-bit, use the sum. */
@@ -107,8 +107,8 @@ table_init (const struct ecc_curve *ecc,
for (j = 2; j < size; j += 2)
{
- ecc_dup_eh (ecc, TABLE(j), TABLE(j/2), scratch);
- ecc_add_ehh (ecc, TABLE(j+1), TABLE(j), TABLE(1), scratch);
+ ecc->dup (ecc, TABLE(j), TABLE(j/2), scratch);
+ ecc->add_hhh (ecc, TABLE(j+1), TABLE(j), TABLE(1), scratch);
}
}
@@ -163,11 +163,11 @@ ecc_mul_a_eh (const struct ecc_curve *ecc,
bits |= w >> shift;
}
for (j = 0; j < ECC_MUL_A_EH_WBITS; j++)
- ecc_dup_eh (ecc, r, r, scratch_out);
+ ecc->dup (ecc, r, r, scratch_out);
bits &= TABLE_MASK;
sec_tabselect (tp, 3*ecc->p.size, table, TABLE_SIZE, bits);
- ecc_add_ehh (ecc, r, tp, r, scratch_out);
+ ecc->add_hhh (ecc, r, tp, r, scratch_out);
}
#undef table
#undef tp
diff --git a/ecc-mul-g-eh.c b/ecc-mul-g-eh.c
index a945494d..971bc6c5 100644
--- a/ecc-mul-g-eh.c
+++ b/ecc-mul-g-eh.c
@@ -64,7 +64,7 @@ ecc_mul_g_eh (const struct ecc_curve *ecc, mp_limb_t *r,
for (i = k; i-- > 0; )
{
- ecc_dup_eh (ecc, r, r, scratch);
+ ecc->dup (ecc, r, r, scratch);
for (j = 0; j * c < bit_rows; j++)
{
unsigned bits;
@@ -93,7 +93,7 @@ ecc_mul_g_eh (const struct ecc_curve *ecc, mp_limb_t *r,
+ (2*ecc->p.size * (mp_size_t) j << c)),
1<<c, bits);
- ecc_add_eh (ecc, r, r, tp, scratch_out);
+ ecc->add_hh (ecc, r, r, tp, scratch_out);
}
}
#undef tp
diff --git a/eccdata.c b/eccdata.c
index fa7a11c5..58ae156b 100644
--- a/eccdata.c
+++ b/eccdata.c
@@ -2,7 +2,9 @@
Generate compile time constant (but machine dependent) tables.
- Copyright (C) 2013, 2014 Niels Möller
+ Copyright (C) 2013, 2014, 2017 Niels Möller
+ Copyright (C) 2017 Daiki Ueno
+ Copyright (C) 2017 Red Hat, Inc.
This file is part of GNU Nettle.
@@ -53,8 +55,12 @@ enum ecc_type
{
/* y^2 = x^3 - 3x + b (mod p) */
ECC_TYPE_WEIERSTRASS,
- /* y^2 = x^3 + b x^2 + x */
- ECC_TYPE_MONTGOMERY
+#if 0
+ /* x^2 + y^2 = 1 - d x^2 y^2 */
+ ECC_TYPE_EDWARDS,
+#endif
+ /* -x^2 + y^2 = 1 - d x^2 y^2 */
+ ECC_TYPE_TWISTED_EDWARDS,
};
struct ecc_curve
@@ -73,16 +79,6 @@ struct ecc_curve
mpz_t q;
struct ecc_point g;
- /* Non-zero if we want elements represented as point s(u, v) on an
- equivalent Edwards curve, using
-
- u = t x / y
- v = (x-1) / (x+1)
- */
- int use_edwards;
- mpz_t d;
- mpz_t t;
-
/* Table for pippenger's algorithm.
Element
@@ -127,9 +123,11 @@ ecc_equal_p (const struct ecc_point *p, const struct ecc_point *q)
}
static void
-ecc_set_zero (struct ecc_point *r)
+ecc_set_zero (const struct ecc_curve *ecc, struct ecc_point *r)
{
r->is_zero = 1;
+ mpz_set_ui (r->x, 0);
+ mpz_set_ui (r->y, ecc->type != ECC_TYPE_WEIERSTRASS);
}
static void
@@ -140,13 +138,22 @@ ecc_set (struct ecc_point *r, const struct ecc_point *p)
mpz_set (r->y, p->y);
}
+static void
+ecc_add (const struct ecc_curve *ecc, struct ecc_point *r,
+ const struct ecc_point *p, const struct ecc_point *q);
+
/* Needs to support in-place operation. */
static void
ecc_dup (const struct ecc_curve *ecc,
struct ecc_point *r, const struct ecc_point *p)
{
+ if (ecc->type != ECC_TYPE_WEIERSTRASS)
+ {
+ ecc_add (ecc, r, p, p);
+ return;
+ }
if (ecc_zero_p (p))
- ecc_set_zero (r);
+ ecc_set_zero (ecc, r);
else
{
@@ -161,32 +168,18 @@ ecc_dup (const struct ecc_curve *ecc,
mpz_mul_ui (m, p->y, 2);
mpz_invert (m, m, ecc->p);
- switch (ecc->type)
- {
- case ECC_TYPE_WEIERSTRASS:
- /* t = 3 (x^2 - 1) * m */
- mpz_mul (t, p->x, p->x);
- mpz_mod (t, t, ecc->p);
- mpz_sub_ui (t, t, 1);
- mpz_mul_ui (t, t, 3);
- break;
- case ECC_TYPE_MONTGOMERY:
- /* t = (3 x^2 + 2 b x + 1) m = [x(3x+2b)+1] m */
- mpz_mul_ui (t, ecc->b, 2);
- mpz_addmul_ui (t, p->x, 3);
- mpz_mul (t, t, p->x);
- mpz_mod (t, t, ecc->p);
- mpz_add_ui (t, t, 1);
- break;
- }
+ /* t = 3 (x^2 - 1) * m */
+ mpz_mul (t, p->x, p->x);
+ mpz_mod (t, t, ecc->p);
+ mpz_sub_ui (t, t, 1);
+ mpz_mul_ui (t, t, 3);
+
mpz_mul (t, t, m);
mpz_mod (t, t, ecc->p);
/* x' = t^2 - 2 x */
mpz_mul (x, t, t);
mpz_submul_ui (x, p->x, 2);
- if (ecc->type == ECC_TYPE_MONTGOMERY)
- mpz_sub (x, x, ecc->b);
mpz_mod (x, x, ecc->p);
@@ -208,55 +201,114 @@ ecc_dup (const struct ecc_curve *ecc,
}
static void
-ecc_add (const struct ecc_curve *ecc,
- struct ecc_point *r, const struct ecc_point *p, const struct ecc_point *q)
+ecc_add (const struct ecc_curve *ecc, struct ecc_point *r,
+ const struct ecc_point *p, const struct ecc_point *q)
{
- if (ecc_zero_p (p))
- ecc_set (r, q);
+ if (ecc->type == ECC_TYPE_WEIERSTRASS)
+ {
+ if (ecc_zero_p (p))
+ ecc_set (r, q);
- else if (ecc_zero_p (q))
- ecc_set (r, p);
+ else if (ecc_zero_p (q))
+ ecc_set (r, p);
- else if (mpz_cmp (p->x, q->x) == 0)
- {
- if (mpz_cmp (p->y, q->y) == 0)
- ecc_dup (ecc, r, p);
+ else if (mpz_cmp (p->x, q->x) == 0)
+ {
+ if (mpz_cmp (p->y, q->y) == 0)
+ ecc_dup (ecc, r, p);
+ else
+ ecc_set_zero (ecc, r);
+ }
else
- ecc_set_zero (r);
+ {
+ mpz_t s, t, x, y;
+ mpz_init (s);
+ mpz_init (t);
+ mpz_init (x);
+ mpz_init (y);
+
+ /* t = (q_y - p_y) / (q_x - p_x) */
+ mpz_sub (t, q->x, p->x);
+ mpz_invert (t, t, ecc->p);
+ mpz_sub (s, q->y, p->y);
+ mpz_mul (t, t, s);
+ mpz_mod (t, t, ecc->p);
+
+ /* x' = t^2 - p_x - q_x */
+ mpz_mul (x, t, t);
+ mpz_sub (x, x, p->x);
+ mpz_sub (x, x, q->x);
+ mpz_mod (x, x, ecc->p);
+
+ /* y' = (x - x') * t - y */
+ mpz_sub (y, p->x, x);
+ mpz_mul (y, y, t);
+ mpz_sub (y, y, p->y);
+ mpz_mod (y, y, ecc->p);
+
+ r->is_zero = 0;
+ mpz_swap (x, r->x);
+ mpz_swap (y, r->y);
+
+ mpz_clear (s);
+ mpz_clear (t);
+ mpz_clear (x);
+ mpz_clear (y);
+ }
}
else
{
+ /* Untwisted:
+ x = (p_x q_y + p_y q_x) / (1 - d p_x p_y q_x q_y)
+ y = (p_y q_y - p_x q_x) / (1 + d p_x p_y q_x q_y)
+
+ Twisted:
+ x = (p_x q_y + p_y q_x) / (1 - d p_x p_y q_x q_y)
+ y = (p_y q_y + p_x q_x) / (1 + d p_x p_y q_x q_y)
+
+ So they differ only by a sign in the expression for the new y
+ coordinate.
+ */
+
mpz_t s, t, x, y;
mpz_init (s);
mpz_init (t);
mpz_init (x);
mpz_init (y);
- /* t = (q_y - p_y) / (q_x - p_x) */
- mpz_sub (t, q->x, p->x);
- mpz_invert (t, t, ecc->p);
- mpz_sub (s, q->y, p->y);
- mpz_mul (t, t, s);
+ /* t = d p_x p_y q_x q_y */
+ mpz_mul (t, ecc->b, p->x);
+ mpz_mod (t, t, ecc->p);
+ mpz_mul (t, t, p->y);
+ mpz_mod (t, t, ecc->p);
+ mpz_mul (t, t, q->x);
+ mpz_mod (t, t, ecc->p);
+ mpz_mul (t, t, q->y);
mpz_mod (t, t, ecc->p);
- /* x' = t^2 - p_x - q_x */
- mpz_mul (x, t, t);
- mpz_sub (x, x, p->x);
- mpz_sub (x, x, q->x);
- /* This appears to be the only difference between formulas. */
- if (ecc->type == ECC_TYPE_MONTGOMERY)
- mpz_sub (x, x, ecc->b);
+ /* x' = (p_x q_y + q_x p_y) / (1 - t) */
+ mpz_mul (x, p->x, q->y);
+ mpz_mod (x, x, ecc->p);
+ mpz_addmul (x, q->x, p->y);
+ mpz_mod (x, x, ecc->p);
+ mpz_ui_sub (s, 1, t);
+ mpz_invert (s, s, ecc->p);
+ mpz_mul (x, x, s);
mpz_mod (x, x, ecc->p);
- /* y' = (x - x') * t - y */
- mpz_sub (y, p->x, x);
- mpz_mul (y, y, t);
- mpz_sub (y, y, p->y);
+ /* y' = (p_y q_y - p_x q_x) / (1 + t) */
+ mpz_mul (y, p->y, q->y);
+ mpz_mod (y, y, ecc->p);
+ mpz_addmul (y, p->x, q->x);
+ mpz_mod (y, y, ecc->p);
+ mpz_add_ui (s, t, 1);
+ mpz_invert (s, s, ecc->p);
+ mpz_mul (y, y, s);
mpz_mod (y, y, ecc->p);
- r->is_zero = 0;
mpz_swap (x, r->x);
mpz_swap (y, r->y);
+ r->is_zero = (mpz_cmp_ui (r->x, 0) == 0 && mpz_cmp_ui (r->y, 1) == 0);
mpz_clear (s);
mpz_clear (t);
@@ -332,16 +384,6 @@ ecc_curve_init_str (struct ecc_curve *ecc, enum ecc_type type,
ecc->table = NULL;
ecc->ref = NULL;
-
- mpz_init (ecc->d);
- mpz_init (ecc->t);
-
- ecc->use_edwards = (t != NULL);
- if (ecc->use_edwards)
- {
- mpz_set_str (ecc->t, t, 16);
- mpz_set_str (ecc->d, d, 16);
- }
}
static void
@@ -533,43 +575,37 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size)
break;
case 255:
- /* curve25519, y^2 = x^3 + 486662 x^2 + x (mod p), with p = 2^{255} - 19.
-
- According to http://cr.yp.to/papers.html#newelliptic, this
- is birationally equivalent to the Edwards curve
-
- x^2 + y^2 = 1 + (121665/121666) x^2 y^2 (mod p).
+ /* Edwards curve used for eddsa25519 and curve25519,
- And since the constant is not a square, the Edwards formulas
- should be "complete", with no special cases needed for
- doubling, neutral element, negatives, etc.
+ -x^2 + y^2 = 1 - (121665/121666) x^2 y^2, with p = 2^{255} - 19.
- Generator is x = 9, with y coordinate
- 14781619447589544791020593568409986887264606134616475288964881837755586237401,
- according to
+ The generator is
+ x = 0x216936d3cd6e53fec0a4e231fdd6dc5c692cc7609525a7b2c9562d608f25d51a
+ y = 0x6666666666666666666666666666666666666666666666666666666666666658
- x = Mod(9, 2^255-19); sqrt(x^3 + 486662*x^2 + x)
+ Also birationally equivalent to the curve25519 Montgomery curve,
- in PARI/GP. Also, in PARI notation,
-
- curve25519 = Mod([0, 486662, 0, 1, 0], 2^255-19)
- */
- ecc_curve_init_str (ecc, ECC_TYPE_MONTGOMERY,
+ y^2 = x^3 + 486662 x^2 + x (mod p)
+ */
+ ecc_curve_init_str (ecc, ECC_TYPE_TWISTED_EDWARDS,
"7fffffffffffffffffffffffffffffff"
"ffffffffffffffffffffffffffffffed",
- "76d06",
+ /* (121665/121666) mod p, from PARI/GP
+ c = Mod(121665, p); c / (c+1)
+ */
+ "2dfc9311d490018c7338bf8688861767"
+ "ff8ff5b2bebe27548a14b235eca6874a",
/* Order of the subgroup is 2^252 + q_0, where
q_0 = 27742317777372353535851937790883648493,
125 bits.
*/
"10000000000000000000000000000000"
"14def9dea2f79cd65812631a5cf5d3ed",
- "9",
- /* y coordinate from PARI/GP
- x = Mod(9, 2^255-19); sqrt(x^3 + 486662*x^2 + x)
- */
- "20ae19a1b8a086b4e01edd2c7748d14c"
- "923d4d7e6d7c61b229e9c5a27eced3d9",
+ /* Generator */
+ "216936d3cd6e53fec0a4e231fdd6dc5c"
+ "692cc7609525a7b2c9562d608f25d51a",
+ "66666666666666666666666666666666"
+ "66666666666666666666666666666658",
/* (121665/121666) mod p, from PARI/GP
c = Mod(121665, p); c / (c+1)
*/
@@ -586,22 +622,21 @@ ecc_curve_init (struct ecc_curve *ecc, unsigned bit_size)
);
ecc->ref = ecc_alloc (3);
ecc_set_str (&ecc->ref[0], /* 2 g */
- "20d342d51873f1b7d9750c687d157114"
- "8f3f5ced1e350b5c5cae469cdd684efb",
- "13b57e011700e8ae050a00945d2ba2f3"
- "77659eb28d8d391ebcd70465c72df563");
+ "36ab384c9f5a046c3d043b7d1833e7ac"
+ "080d8e4515d7a45f83c5a14e2843ce0e",
+ "2260cdf3092329c21da25ee8c9a21f56"
+ "97390f51643851560e5f46ae6af8a3c9");
ecc_set_str (&ecc->ref[1], /* 3 g */
- "1c12bc1a6d57abe645534d91c21bba64"
- "f8824e67621c0859c00a03affb713c12",
- "2986855cbe387eaeaceea446532c338c"
- "536af570f71ef7cf75c665019c41222b");
+ "67ae9c4a22928f491ff4ae743edac83a"
+ "6343981981624886ac62485fd3f8e25c",
+ "1267b1d177ee69aba126a18e60269ef7"
+ "9f16ec176724030402c3684878f5b4d4");
ecc_set_str (&ecc->ref[2], /* 4 g */
- "79ce98b7e0689d7de7d1d074a15b315f"
- "fe1805dfcd5d2a230fee85e4550013ef",
- "75af5bf4ebdc75c8fe26873427d275d7"
- "3c0fb13da361077a565539f46de1c30");
-
+ "203da8db56cff1468325d4b87a3520f9"
+ "1a739ec193ce1547493aa657c4c9f870",
+ "47d0e827cb1595e1470eb88580d5716c"
+ "4cf22832ea2f0ff0df38ab61ca32112f");
break;
default:
@@ -618,8 +653,6 @@ ecc_curve_clear (struct ecc_curve *ecc)
mpz_clear (ecc->b);
mpz_clear (ecc->q);
ecc_clear (&ecc->g);
- mpz_clear (ecc->d);
- mpz_clear (ecc->t);
if (ecc->table)
{
size_t i;
@@ -668,7 +701,7 @@ ecc_pippenger_precompute (struct ecc_curve *ecc, unsigned k, unsigned c)
ecc->table = ecc_alloc (ecc->table_size);
/* Compute the first 2^c entries */
- ecc_set_zero (&ecc->table[0]);
+ ecc_set_zero (ecc, &ecc->table[0]);
ecc_set (&ecc->table[1], &ecc->g);
for (j = 2; j < (1U<<c); j <<= 1)
@@ -706,7 +739,7 @@ ecc_mul_pippenger (const struct ecc_curve *ecc,
mpz_init (n);
mpz_mod (n, n_input, ecc->q);
- ecc_set_zero (r);
+ ecc_set_zero (ecc, r);
k = ecc->pippenger_k;
c = ecc->pippenger_c;
@@ -904,38 +937,9 @@ output_point (const char *name, const struct ecc_curve *ecc,
if (name)
printf("static const mp_limb_t %s[%u] = {", name, 2*size);
- if (ecc->use_edwards)
- {
- if (ecc_zero_p (p))
- {
- mpz_set_si (x, 0);
- mpz_set_si (y, 1);
- }
- else if (!mpz_sgn (p->y))
- {
- assert (!mpz_sgn (p->x));
- mpz_set_si (x, 0);
- mpz_set_si (y, -1);
- }
- else
- {
- mpz_invert (x, p->y, ecc->p);
- mpz_mul (x, x, p->x);
- mpz_mul (x, x, ecc->t);
- mpz_mod (x, x, ecc->p);
+ mpz_set (x, p->x);
+ mpz_set (y, p->y);
- mpz_sub_ui (y, p->x, 1);
- mpz_add_ui (t, p->x, 1);
- mpz_invert (t, t, ecc->p);
- mpz_mul (y, y, t);
- mpz_mod (y, y, ecc->p);
- }
- }
- else
- {
- mpz_set (x, p->x);
- mpz_set (y, p->y);
- }
if (use_redc)
{
mpz_mul_2exp (x, x, size * bits_per_limb);
@@ -993,8 +997,6 @@ output_curve (const struct ecc_curve *ecc, unsigned bits_per_limb)
output_bignum ("ecc_p", ecc->p, limb_size, bits_per_limb);
output_bignum ("ecc_b", ecc->b, limb_size, bits_per_limb);
- if (ecc->use_edwards)
- output_bignum ("ecc_d", ecc->d, limb_size, bits_per_limb);
output_bignum ("ecc_q", ecc->q, limb_size, bits_per_limb);
output_point ("ecc_g", ecc, &ecc->g, 0, limb_size, bits_per_limb);
@@ -1084,9 +1086,6 @@ output_curve (const struct ecc_curve *ecc, unsigned bits_per_limb)
mpz_fdiv_q_2exp (t, t, 1);
output_bignum ("ecc_qp1h", t, limb_size, bits_per_limb);
- if (ecc->use_edwards)
- output_bignum ("ecc_edwards", ecc->t, limb_size, bits_per_limb);
-
/* Trailing zeros in p+1 correspond to trailing ones in p. */
redc_limbs = mpz_scan0 (ecc->p, 0) / bits_per_limb;
if (redc_limbs > 0)
diff --git a/eddsa-sign.c b/eddsa-sign.c
index 5832c23a..13ae4799 100644
--- a/eddsa-sign.c
+++ b/eddsa-sign.c
@@ -93,7 +93,7 @@ _eddsa_sign (const struct ecc_curve *ecc,
unsigned shift;
mp_limb_t cy;
assert (ecc->p.bit_size == 255);
- shift = 252 - GMP_NUMB_BITS * (ecc->p.size - 1);
+ 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);
diff --git a/testsuite/ecc-add-test.c b/testsuite/ecc-add-test.c
index 54fae31f..ad2bd292 100644
--- a/testsuite/ecc-add-test.c
+++ b/testsuite/ecc-add-test.c
@@ -1,4 +1,5 @@
#include "testutils.h"
+#include <assert.h>
void
test_main (void)
@@ -12,74 +13,68 @@ test_main (void)
mp_limb_t *g2 = xalloc_limbs (ecc_size_j (ecc));
mp_limb_t *g3 = xalloc_limbs (ecc_size_j (ecc));
mp_limb_t *p = xalloc_limbs (ecc_size_j (ecc));
- mp_limb_t *scratch = xalloc_limbs (ECC_ADD_JJJ_ITCH(ecc->p.size));
+ mp_limb_t *scratch = xalloc_limbs (ecc->add_hhh_itch);
+
+ ASSERT (ecc->dup_itch <= ecc->add_hhh_itch);
+
+ ecc_a_to_j (ecc, g, ecc->g);
if (ecc->p.bit_size == 255)
{
mp_limb_t *z = xalloc_limbs (ecc_size_j (ecc));
+
+ ASSERT (ecc->add_hh == ecc_add_eh);
+ ASSERT (ecc->add_hhh == ecc_add_ehh);
+ ASSERT (ecc->add_hh_itch <= ecc->add_hhh_itch);
+
/* Zero point has x = 0, y = 1, z = 1 */
mpn_zero (z, 3*ecc->p.size);
z[ecc->p.size] = z[2*ecc->p.size] = 1;
-
- ecc_a_to_j (ecc, g, ecc->g);
- ecc_add_ehh (ecc, p, z, z, scratch);
+ ecc->add_hhh (ecc, p, z, z, scratch);
test_ecc_mul_h (i, 0, p);
- ecc_add_eh (ecc, p, z, z, scratch);
+ ecc->add_hh (ecc, p, z, z, scratch);
test_ecc_mul_h (i, 0, p);
- ecc_add_ehh (ecc, p, g, p, scratch);
+ ecc->add_hhh (ecc, p, g, p, scratch);
test_ecc_mul_h (i, 1, p);
- ecc_add_eh (ecc, p, z, g, scratch);
+ ecc->add_hh (ecc, p, z, g, scratch);
test_ecc_mul_h (i, 1, p);
- ecc_add_ehh (ecc, g2, g, p, scratch);
+ ecc->add_hhh (ecc, g2, g, p, scratch);
test_ecc_mul_h (i, 2, g2);
- ecc_add_eh (ecc, g2, g, g, scratch);
+ ecc->add_hh (ecc, g2, g, g, scratch);
test_ecc_mul_h (i, 2, g2);
- ecc_add_ehh (ecc, g3, g, g2, scratch);
- test_ecc_mul_h (i, 3, g3);
-
- ecc_add_eh (ecc, g3, g2, g, scratch);
- test_ecc_mul_h (i, 3, g3);
-
- ecc_add_ehh (ecc, p, g, g3, scratch);
- test_ecc_mul_h (i, 4, p);
-
- ecc_add_eh (ecc, p, g3, g, scratch);
- test_ecc_mul_h (i, 4, p);
-
- ecc_add_ehh (ecc, p, g2, g2, scratch);
- test_ecc_mul_h (i, 4, p);
-
free (z);
}
else
{
- ecc_a_to_j (ecc, g, ecc->g);
+ ASSERT (ecc->add_hhh == ecc_add_jjj);
+ ASSERT (ecc->dup == ecc_dup_jj);
+ }
- ecc_dup_jj (ecc, g2, g, scratch);
- test_ecc_mul_h (i, 2, g2);
+ ecc->dup (ecc, g2, g, scratch);
+ test_ecc_mul_h (i, 2, g2);
- ecc_add_jjj (ecc, g3, g, g2, scratch);
- test_ecc_mul_h (i, 3, g3);
+ ecc->add_hhh (ecc, g3, g, g2, scratch);
+ test_ecc_mul_h (i, 3, g3);
- ecc_add_jjj (ecc, g3, g2, g, scratch);
- test_ecc_mul_h (i, 3, g3);
+ ecc->add_hhh (ecc, g3, g2, g, scratch);
+ test_ecc_mul_h (i, 3, g3);
- ecc_add_jjj (ecc, p, g, g3, scratch);
- test_ecc_mul_h (i, 4, p);
+ ecc->add_hhh (ecc, p, g, g3, scratch);
+ test_ecc_mul_h (i, 4, p);
- ecc_add_jjj (ecc, p, g3, g, scratch);
- test_ecc_mul_h (i, 4, p);
+ ecc->add_hhh (ecc, p, g3, g, scratch);
+ test_ecc_mul_h (i, 4, p);
+
+ ecc->dup (ecc, p, g2, scratch);
+ test_ecc_mul_h (i, 4, p);
- ecc_dup_jj (ecc, p, g2, scratch);
- test_ecc_mul_h (i, 4, p);
- }
free (g);
free (g2);
free (g3);
diff --git a/testsuite/ecc-dup-test.c b/testsuite/ecc-dup-test.c
index b92352c1..0ae4444a 100644
--- a/testsuite/ecc-dup-test.c
+++ b/testsuite/ecc-dup-test.c
@@ -10,37 +10,34 @@ test_main (void)
const struct ecc_curve *ecc = ecc_curves[i];
mp_limb_t *g = xalloc_limbs (ecc_size_j (ecc));
mp_limb_t *p = xalloc_limbs (ecc_size_j (ecc));
- mp_limb_t *scratch = xalloc_limbs (ECC_DUP_EH_ITCH(ecc->p.size));;
+ mp_limb_t *scratch = xalloc_limbs (ecc->dup_itch);
+
+ ecc_a_to_j (ecc, g, ecc->g);
if (ecc->p.bit_size == 255)
{
mp_limb_t *z = xalloc_limbs (ecc_size_j (ecc));
+
+ ASSERT (ecc->dup == ecc_dup_eh);
+
/* Zero point has x = 0, y = 1, z = 1 */
mpn_zero (z, 3*ecc->p.size);
z[ecc->p.size] = z[2*ecc->p.size] = 1;
- ecc_a_to_j (ecc, g, ecc->g);
-
- ecc_dup_eh (ecc, p, z, scratch);
+ ecc->dup (ecc, p, z, scratch);
test_ecc_mul_h (i, 0, p);
- ecc_dup_eh (ecc, p, g, scratch);
- test_ecc_mul_h (i, 2, p);
-
- ecc_dup_eh (ecc, p, p, scratch);
- test_ecc_mul_h (i, 4, p);
free (z);
}
else
- {
- ecc_a_to_j (ecc, g, ecc->g);
+ ASSERT (ecc->dup == ecc_dup_jj);
- ecc_dup_jj (ecc, p, g, scratch);
- test_ecc_mul_h (i, 2, p);
+ ecc->dup (ecc, p, g, scratch);
+ test_ecc_mul_h (i, 2, p);
+
+ ecc->dup (ecc, p, p, scratch);
+ test_ecc_mul_h (i, 4, p);
- ecc_dup_jj (ecc, p, p, scratch);
- test_ecc_mul_h (i, 4, p);
- }
free (p);
free (g);
free (scratch);