Commit 60833975 authored by Niels Möller's avatar Niels Möller

Add modular square root for ecc-192.

* testsuite/ecc-sqrt-test.c (test_sqrt): New function.
(test_sqrt_ratio): Renamed, from...
(test_modulo): ... old name.
(test_main): Call test_sqrt and test_sqrt_ratio, for those curves
that support these operations.

* ecc-192.c (ecc_192_zero_p): New function.
(ecc_192_sqrt): New square root function, based on patch by Wim
Lewis.

* ecc-25519.c (ecc_25519_sqrt_ratio): Renamed, from...
(ecc_25519_sqrt): ... old name.
(_nettle_curve25519): Update curve definition.

* ecc-internal.h (ecc_mod_sqrt_func): New typedef.
(struct ecc_modulo): Add sqrt_ratio_itch and sqrt function
pointer. Update all curve definitionns.
parent d0ab52a3
2019-10-15 Niels Möller <nisse@lysator.liu.se>
* ecc-internal.h (ecc_mod_sqrt_func): New typedef.
(struct ecc_modulo): Add sqrt_ratio_itch and sqrt function
pointer. Update all curve definitionns.
* ecc-25519.c (ecc_25519_sqrt_ratio): Renamed, from...
(ecc_25519_sqrt): ... old name.
(_nettle_curve25519): Update curve definition.
* ecc-192.c (ecc_192_zero_p): New function.
(ecc_192_sqrt): New square root function, based on patch by Wim
Lewis.
* testsuite/ecc-sqrt-test.c (test_sqrt): New function.
(test_sqrt_ratio): Renamed, from...
(test_modulo): ... old name.
(test_main): Call test_sqrt and test_sqrt_ratio, for those curves
that support these operations.
2019-09-26 Niels Möller <nisse@lysator.liu.se>
* ecc-mod-pow.c (ecc_mod_pow_2k, ecc_mod_pow_2k_mul): New file, new
......
......@@ -2,7 +2,8 @@
Compile time constant (but machine dependent) tables.
Copyright (C) 2013, 2014 Niels Möller
Copyright (C) 2013, 2014, 2019 Niels Möller
Copyright (C) 2019 Wim Lewis
This file is part of GNU Nettle.
......@@ -110,6 +111,73 @@ ecc_192_modp (const struct ecc_modulo *m UNUSED, mp_limb_t *rp)
#define ecc_192_modp ecc_mod
#endif
/* If there are extra bits, ecc_192_zero_p would need an initial
reduction. */
#if ECC_LIMB_SIZE * GMP_NUMB_BITS != 192
#error Unsupported limb size
#endif
static int
ecc_192_zero_p (const struct ecc_modulo *p, const volatile mp_limb_t *rp)
{
volatile mp_limb_t is_non_zero, is_not_p;
mp_size_t i;
for (i = 0, is_non_zero = is_not_p = 0; i < ECC_LIMB_SIZE; i++)
{
is_non_zero |= rp[i];
is_not_p |= (rp[i] ^ p->m[i]);
}
return (is_non_zero == 0) | (is_not_p == 0);
}
#define ECC_192_SQRT_ITCH (6*ECC_LIMB_SIZE)
static int
ecc_192_sqrt (const struct ecc_modulo *p,
mp_limb_t *rp,
const mp_limb_t *cp,
mp_limb_t *scratch)
{
/* This computes the square root modulo p192 using the identity:
sqrt(c) = c^(2^190 - 2^62) (mod P-192)
which can be seen as a special case of Tonelli-Shanks with e=1.
*/
/* We use our scratch space for three temporaries (TA, TB, TC) all of
which are 2*size long to allow for multiplication/squaring */
#define TA scratch
#define TB (scratch + 2*ECC_LIMB_SIZE)
#define TC (scratch + 4*ECC_LIMB_SIZE)
ecc_mod_pow_2k_mul(p, TA, cp, 1, cp, TB); /* [1] TA <-- c^3 */
ecc_mod_pow_2k_mul(p, TB, TA, 2, TA, TC); /* [2] TB <-- c^(2^4 - 1) */
ecc_mod_pow_2k_mul(p, TA, TB, 4, TB, TC); /* [3] TA <-- c^(2^8 - 1) */
ecc_mod_pow_2k_mul(p, TB, TA, 8, TA, TC); /* [4] TB <-- c^(2^16 - 1) */
ecc_mod_pow_2k_mul(p, TA, TB, 16, TB, TC); /* [5] TA <-- c^(2^32 - 1) */
ecc_mod_pow_2k_mul(p, TB, TA, 32, TA, TC); /* [6] TB <-- c^(2^64 - 1) */
ecc_mod_pow_2k_mul(p, TC, TB, 64, TB, TA); /* [7] TC <-- c^(2^128 - 1) */
ecc_mod_pow_2k (p, rp, TC, 62, TA); /* [8] r <-- c^(2^190 - 2^62) */
/* Check that input was a square, R^2 = C, for non-squares we'd get
R^2 = -C. */
ecc_mod_sqr(p, TA, rp);
ecc_mod_sub(p, TA, TA, cp);
return ecc_192_zero_p (p, TA);
#undef TA
#undef TB
#undef TC
}
const struct ecc_curve _nettle_secp_192r1 =
{
{
......@@ -118,6 +186,7 @@ const struct ecc_curve _nettle_secp_192r1 =
ECC_BMODP_SIZE,
ECC_REDC_SIZE,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
ECC_192_SQRT_ITCH,
0,
ecc_p,
......@@ -129,6 +198,7 @@ const struct ecc_curve _nettle_secp_192r1 =
ecc_192_modp,
ecc_192_modp,
ecc_mod_inv,
ecc_192_sqrt,
NULL,
},
{
......@@ -138,6 +208,7 @@ const struct ecc_curve _nettle_secp_192r1 =
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_q,
ecc_Bmodq,
......@@ -149,6 +220,7 @@ const struct ecc_curve _nettle_secp_192r1 =
ecc_mod,
ecc_mod_inv,
NULL,
NULL
},
USE_REDC,
......
......@@ -71,6 +71,7 @@ const struct ecc_curve _nettle_secp_224r1 =
-ECC_REDC_SIZE,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_p,
ecc_Bmodp,
......@@ -82,6 +83,7 @@ const struct ecc_curve _nettle_secp_224r1 =
USE_REDC ? ecc_224_redc : ecc_224_modp,
ecc_mod_inv,
NULL,
NULL,
},
{
224,
......@@ -90,6 +92,7 @@ const struct ecc_curve _nettle_secp_224r1 =
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_q,
ecc_Bmodq,
......@@ -101,6 +104,7 @@ const struct ecc_curve _nettle_secp_224r1 =
ecc_mod,
ecc_mod_inv,
NULL,
NULL,
},
USE_REDC,
......
......@@ -209,12 +209,12 @@ ecc_25519_zero_p (const struct ecc_modulo *p, mp_limb_t *xp)
#endif
/* Needs 4*n space + scratch for ecc_mod_pow_252m3. */
#define ECC_25519_SQRT_ITCH (9*ECC_LIMB_SIZE)
#define ECC_25519_SQRT_RATIO_ITCH (9*ECC_LIMB_SIZE)
static int
ecc_25519_sqrt(const struct ecc_modulo *p, mp_limb_t *rp,
const mp_limb_t *up, const mp_limb_t *vp,
mp_limb_t *scratch)
ecc_25519_sqrt_ratio(const struct ecc_modulo *p, mp_limb_t *rp,
const mp_limb_t *up, const mp_limb_t *vp,
mp_limb_t *scratch)
{
int pos, neg;
......@@ -271,7 +271,8 @@ const struct ecc_curve _nettle_curve25519 =
ECC_BMODP_SIZE,
0,
ECC_25519_INV_ITCH,
ECC_25519_SQRT_ITCH,
0,
ECC_25519_SQRT_RATIO_ITCH,
ecc_p,
ecc_Bmodp,
......@@ -282,7 +283,8 @@ const struct ecc_curve _nettle_curve25519 =
ecc_25519_modp,
ecc_25519_modp,
ecc_25519_inv,
ecc_25519_sqrt,
NULL,
ecc_25519_sqrt_ratio,
},
{
253,
......@@ -291,6 +293,7 @@ const struct ecc_curve _nettle_curve25519 =
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_q,
ecc_Bmodq,
......@@ -302,6 +305,7 @@ const struct ecc_curve _nettle_curve25519 =
ecc_25519_modq,
ecc_mod_inv,
NULL,
NULL,
},
0, /* No redc */
......
......@@ -248,6 +248,7 @@ const struct ecc_curve _nettle_secp_256r1 =
ECC_REDC_SIZE,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_p,
ecc_Bmodp,
......@@ -259,6 +260,7 @@ const struct ecc_curve _nettle_secp_256r1 =
USE_REDC ? ecc_256_redc : ecc_256_modp,
ecc_mod_inv,
NULL,
NULL,
},
{
256,
......@@ -267,6 +269,7 @@ const struct ecc_curve _nettle_secp_256r1 =
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_q,
ecc_Bmodq,
......@@ -278,6 +281,7 @@ const struct ecc_curve _nettle_secp_256r1 =
ecc_256_modq,
ecc_mod_inv,
NULL,
NULL,
},
USE_REDC,
......
......@@ -156,6 +156,7 @@ const struct ecc_curve _nettle_secp_384r1 =
ECC_REDC_SIZE,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_p,
ecc_Bmodp,
......@@ -167,6 +168,7 @@ const struct ecc_curve _nettle_secp_384r1 =
ecc_384_modp,
ecc_mod_inv,
NULL,
NULL,
},
{
384,
......@@ -175,7 +177,7 @@ const struct ecc_curve _nettle_secp_384r1 =
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_q,
ecc_Bmodq,
ecc_Bmodq_shifted,
......@@ -186,6 +188,7 @@ const struct ecc_curve _nettle_secp_384r1 =
ecc_mod,
ecc_mod_inv,
NULL,
NULL,
},
USE_REDC,
......
......@@ -84,6 +84,7 @@ const struct ecc_curve _nettle_secp_521r1 =
ECC_REDC_SIZE,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_p,
ecc_Bmodp,
......@@ -95,6 +96,7 @@ const struct ecc_curve _nettle_secp_521r1 =
ecc_521_modp,
ecc_mod_inv,
NULL,
NULL,
},
{
521,
......@@ -103,6 +105,7 @@ const struct ecc_curve _nettle_secp_521r1 =
0,
ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
0,
0,
ecc_q,
ecc_Bmodq,
......@@ -114,6 +117,7 @@ const struct ecc_curve _nettle_secp_521r1 =
ecc_mod,
ecc_mod_inv,
NULL,
NULL,
},
USE_REDC,
......
......@@ -109,7 +109,12 @@ typedef void ecc_mod_inv_func (const struct ecc_modulo *m,
mp_limb_t *vp, const mp_limb_t *ap,
mp_limb_t *scratch);
/* Computes the square root of (u/v) (mod p) */
/* The sqrt and sqrt_ratio functions need 2*m->size limbs at rp */
typedef int ecc_mod_sqrt_func (const struct ecc_modulo *m,
mp_limb_t *vp, const mp_limb_t *ap,
mp_limb_t *scratch);
/* Computes the square root of (u/v) (mod p). */
typedef int ecc_mod_sqrt_ratio_func (const struct ecc_modulo *m,
mp_limb_t *rp,
const mp_limb_t *up, const mp_limb_t *vp,
......@@ -141,6 +146,7 @@ struct ecc_modulo
unsigned short redc_size;
unsigned short invert_itch;
unsigned short sqrt_itch;
unsigned short sqrt_ratio_itch;
const mp_limb_t *m;
/* B^size mod m. Expected to have at least 32 leading zeros
......@@ -156,6 +162,7 @@ struct ecc_modulo
ecc_mod_func *mod;
ecc_mod_func *reduce;
ecc_mod_inv_func *invert;
ecc_mod_sqrt_func *sqrt;
ecc_mod_sqrt_ratio_func *sqrt_ratio;
};
......
......@@ -42,7 +42,7 @@
mp_size_t
_eddsa_decompress_itch (const struct ecc_curve *ecc)
{
return 4*ecc->p.size + ecc->p.sqrt_itch;
return 4*ecc->p.size + ecc->p.sqrt_ratio_itch;
}
int
......
......@@ -66,7 +66,81 @@ mpz_ui_kronecker (mp_limb_t ul, const mpz_t p)
#endif /* NETTLE_USE_MINI_GMP */
static void
test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m)
test_sqrt (gmp_randstate_t rands, const struct ecc_modulo *m)
{
mpz_t u;
mpz_t p;
mpz_t r;
mpz_t t;
unsigned z, i;
mp_limb_t *up;
mp_limb_t *rp;
mp_limb_t *scratch;
mpz_init (u);
mpz_init (t);
mpz_roinit_n (p, m->m, m->size);
up = xalloc_limbs (m->size);
rp = xalloc_limbs (2*m->size);
scratch = xalloc_limbs (m->sqrt_itch);
/* Find a non-square */
for (z = 2; mpz_ui_kronecker (z, p) != -1; z++)
;
if (verbose)
fprintf(stderr, "Non square: %d\n", z);
for (i = 0; i < COUNT; i++)
{
if (i & 1)
mpz_rrandomb (u, rands, m->bit_size);
else
mpz_urandomb (u, rands, m->bit_size);
mpz_limbs_copy (up, u, m->size);
if (!m->sqrt (m, rp, up, scratch))
{
mpz_mul_ui (u, u, z);
mpz_mod (u, u, p);
mpz_limbs_copy (up, u, m->size);
if (!m->sqrt (m, rp, up, scratch))
{
fprintf (stderr, "m->sqrt returned failure, bit_size = %d\n"
"u = 0x",
m->bit_size);
mpz_out_str (stderr, 16, u);
fprintf (stderr, "\n");
abort ();
}
}
/* Check that r^2 = u */
mpz_roinit_n (r, rp, m->size);
mpz_mul (t, r, r);
if (!mpz_congruent_p (t, u, p))
{
fprintf (stderr, "m->sqrt gave incorrect result, bit_size = %d\n"
"u = 0x",
m->bit_size);
mpz_out_str (stderr, 16, u);
fprintf (stderr, "\nr = 0x");
mpz_out_str (stderr, 16, r);
fprintf (stderr, "\n");
abort ();
}
}
mpz_clear (u);
mpz_clear (t);
free (up);
free (rp);
free (scratch);
}
static void
test_sqrt_ratio (gmp_randstate_t rands, const struct ecc_modulo *m)
{
mpz_t u;
mpz_t v;
......@@ -89,7 +163,7 @@ test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m)
up = xalloc_limbs (m->size);
vp = xalloc_limbs (m->size);
rp = xalloc_limbs (2*m->size);
scratch = xalloc_limbs (m->sqrt_itch);
scratch = xalloc_limbs (m->sqrt_ratio_itch);
/* Find a non-square */
for (z = 2; mpz_ui_kronecker (z, p) != -1; z++)
......@@ -119,7 +193,7 @@ test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m)
mpz_limbs_copy (up, u, m->size);
if (!m->sqrt_ratio (m, rp, up, vp, scratch))
{
fprintf (stderr, "m->sqrt returned failure, bit_size = %d\n"
fprintf (stderr, "m->sqrt_ratio returned failure, bit_size = %d\n"
"u = 0x",
m->bit_size);
mpz_out_str (stderr, 16, u);
......@@ -135,7 +209,7 @@ test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m)
mpz_mul (t, t, v);
if (!mpz_congruent_p (t, u, p))
{
fprintf (stderr, "m->sqrt gave incorrect result, bit_size = %d\n"
fprintf (stderr, "m->sqrt_ratio gave incorrect result, bit_size = %d\n"
"u = 0x",
m->bit_size);
mpz_out_str (stderr, 16, u);
......@@ -165,8 +239,10 @@ test_main (void)
gmp_randinit_default (rands);
for (i = 0; ecc_curves[i]; i++)
{
if (ecc_curves[i]->p.sqrt)
test_sqrt (rands, &ecc_curves[i]->p);
if (ecc_curves[i]->p.sqrt_ratio)
test_modulo (rands, &ecc_curves[i]->p);
test_sqrt_ratio (rands, &ecc_curves[i]->p);
}
gmp_randclear (rands);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment