]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Implement secp192r1 square root, based on patch by Wim Lewis.
authorNiels Möller <nisse@lysator.liu.se>
Mon, 8 Nov 2021 16:37:05 +0000 (17:37 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Mon, 8 Nov 2021 16:37:05 +0000 (17:37 +0100)
12 files changed:
ChangeLog
ecc-curve25519.c
ecc-curve448.c
ecc-gost-gc256b.c
ecc-gost-gc512a.c
ecc-internal.h
ecc-secp192r1.c
ecc-secp224r1.c
ecc-secp256r1.c
ecc-secp384r1.c
ecc-secp521r1.c
testsuite/ecc-sqrt-test.c

index 3b4115043c1c3e4d591c905dff7420ec1ac9521a..30aa255f13c1862dae63c61bfdcdfc2c9f4d0dc8 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2021-11-08  Niels Möller  <nisse@lysator.liu.se>
+
+       Square root functions, based on patch by Wim Lewis.
+       * ecc-internal.h (ecc_mod_sqrt_func): New typedef.
+       (struct ecc_modulo): Add sqrt function pointer and sqrt_itch.
+       Update all curve definitions.
+       * ecc-secp192r1.c (ECC_SECP192R1_SQRT_ITCH): New constant.
+       (ecc_secp192r1_sqrt): New function.
+
+       * testsuite/ecc-sqrt-test.c (test_sqrt): New function.
+       (test_sqrt_ratio): Renamed function (was test_modulo).
+       (test_main): Test sqrt function, for curves that define it.
+
 2021-11-07  Niels Möller  <nisse@lysator.liu.se>
 
        * ecc-internal.h (struct ecc_modulo): Renamed sqrt_itch to
index e461c1978b31c57357d4d966a0a7ac2cdda4db0c..56abcf233ce36db3df4cf3bb9b3dcf3562d3ff4f 100644 (file)
@@ -260,6 +260,7 @@ const struct ecc_curve _nettle_curve25519 =
     ECC_BMODP_SIZE,
     0,
     ECC_25519_INV_ITCH,
+    0,
     ECC_25519_SQRT_RATIO_ITCH,
 
     ecc_p,
@@ -271,6 +272,7 @@ const struct ecc_curve _nettle_curve25519 =
     ecc_curve25519_modp,
     ecc_curve25519_modp,
     ecc_curve25519_inv,
+    NULL,
     ecc_curve25519_sqrt_ratio,
   },
   {
@@ -280,6 +282,7 @@ const struct ecc_curve _nettle_curve25519 =
     0,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_q,
     ecc_Bmodq,  
@@ -291,6 +294,7 @@ const struct ecc_curve _nettle_curve25519 =
     ecc_curve25519_modq,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
 
   0, /* No redc */
index 67d197eb61ecfb98c71247dec9bdffc24183714d..1bd4e11f76cd8f005b8161086029443f0dcef189 100644 (file)
@@ -214,6 +214,7 @@ const struct ecc_curve _nettle_curve448 =
     ECC_BMODP_SIZE,
     0,
     ECC_CURVE448_INV_ITCH,
+    0,
     ECC_CURVE448_SQRT_RATIO_ITCH,
 
     ecc_p,
@@ -225,6 +226,7 @@ const struct ecc_curve _nettle_curve448 =
     ecc_curve448_modp,
     ecc_curve448_modp,
     ecc_curve448_inv,
+    NULL,
     ecc_curve448_sqrt_ratio,
   },
   {
@@ -234,6 +236,7 @@ const struct ecc_curve _nettle_curve448 =
     0,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_q,
     ecc_Bmodq,
@@ -245,6 +248,7 @@ const struct ecc_curve _nettle_curve448 =
     ecc_mod,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
 
   0, /* No redc */
index 988368e99ae962d9df3dd3fc10964ee13dd1410a..0cf753e4631bb038da291d1ac31e3524cfe83b44 100644 (file)
@@ -66,6 +66,7 @@ const struct ecc_curve _nettle_gost_gc256b =
     ECC_REDC_SIZE,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_p,
     ecc_Bmodp,
@@ -77,6 +78,7 @@ const struct ecc_curve _nettle_gost_gc256b =
     ecc_gost_gc256b_modp,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
   {
     256,
@@ -85,6 +87,7 @@ const struct ecc_curve _nettle_gost_gc256b =
     0,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_q,
     ecc_Bmodq,
@@ -96,6 +99,7 @@ const struct ecc_curve _nettle_gost_gc256b =
     ecc_gost_gc256b_modq,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
 
   USE_REDC,
index 0b9864efdc366df198fc6f6d5917fef8e100f17d..338ed00194ba87b7af1ee55fc3a68f94b8b486a9 100644 (file)
@@ -66,6 +66,7 @@ const struct ecc_curve _nettle_gost_gc512a =
     ECC_REDC_SIZE,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_p,
     ecc_Bmodp,
@@ -77,6 +78,7 @@ const struct ecc_curve _nettle_gost_gc512a =
     ecc_gost_gc512a_modp,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
   {
     512,
@@ -85,6 +87,7 @@ const struct ecc_curve _nettle_gost_gc512a =
     0,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_q,
     ecc_Bmodq,
@@ -96,6 +99,7 @@ const struct ecc_curve _nettle_gost_gc512a =
     ecc_gost_gc512a_modq,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
 
   USE_REDC,
index a3e1933154b985ff04531042e1ae16a0f1ba105d..277f5a02af6066cbaaa42545d0a8227de80990a6 100644 (file)
@@ -125,6 +125,11 @@ 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 ap mod p. No overlap between input and output. */
+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,
@@ -161,6 +166,7 @@ struct ecc_modulo
   unsigned short B_size;
   unsigned short redc_size;
   unsigned short invert_itch;
+  unsigned short sqrt_itch;
   unsigned short sqrt_ratio_itch;
 
   const mp_limb_t *m;
@@ -179,6 +185,7 @@ struct ecc_modulo
   /* For moduli where we use redc, the invert and sqrt functions work
      with inputs and outputs in redc form. */
   ecc_mod_inv_func *invert;
+  ecc_mod_sqrt_func *sqrt;
   ecc_mod_sqrt_ratio_func *sqrt_ratio;
 };
 
index abdad0c9dc30f264ea7b5ddd9fcba7cbad914362..391ba52817f409ddd38b68da343d757e3b099095 100644 (file)
@@ -2,7 +2,8 @@
 
    Compile time constant (but machine dependent) tables.
 
-   Copyright (C) 2013, 2014 Niels Möller
+   Copyright (C) 2013, 2014, 2019, 2021 Niels Möller
+   Copyright (C) 2019 Wim Lewis
 
    This file is part of GNU Nettle.
 
@@ -180,6 +181,57 @@ ecc_secp192r1_inv (const struct ecc_modulo *p,
   ecc_mod_sqr (p, rp, rp, tp);         /* a^{2^191 - 2^63 - 2} */
   ecc_mod_sqr (p, rp, rp, tp);         /* a^{2^192 - 2^64 - 4} */
   ecc_mod_mul (p, rp, rp, ap, tp);
+
+#undef a62m1
+#undef t0
+#undef tp
+}
+
+/* To guarantee that inputs to ecc_mod_zero_p are in the required range. */
+#if ECC_LIMB_SIZE * GMP_NUMB_BITS != 192
+#error Unsupported limb size
+#endif
+
+#define ECC_SECP192R1_SQRT_ITCH (3*ECC_LIMB_SIZE)
+
+static int
+ecc_secp192r1_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 need one t0 (and use clobbering rp) and scratch space for mul and sqr. */
+
+#define t0 scratch
+#define tp (scratch + ECC_LIMB_SIZE)
+
+  ecc_mod_sqr(p, rp, cp, tp);          /* c^2 */
+  ecc_mod_mul(p, rp, rp, cp, tp);      /* c^3 */
+  ecc_mod_pow_2kp1(p, t0, rp, 2, tp);  /* c^(2^4 - 1) */
+  ecc_mod_pow_2kp1(p, rp, t0, 4, tp);  /* c^(2^8 - 1) */
+  ecc_mod_pow_2kp1(p, t0, rp, 8,  tp); /* c^(2^16 - 1) */
+  ecc_mod_pow_2kp1(p, rp, t0, 16, tp); /* c^(2^32 - 1) */
+  ecc_mod_pow_2kp1(p, t0, rp, 32, tp); /* c^(2^64 - 1) */
+  ecc_mod_pow_2kp1(p, rp, t0, 64, tp); /* c^(2^128 - 1) */
+
+  ecc_mod_pow_2k    (p, rp, rp,     62, tp);   /* 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, t0, rp, tp);
+  ecc_mod_sub(p, t0, t0, cp);
+
+  return ecc_mod_zero_p (p, t0);
+
+#undef t0
+#undef tp
 }
 
 const struct ecc_curve _nettle_secp_192r1 =
@@ -190,6 +242,7 @@ const struct ecc_curve _nettle_secp_192r1 =
     ECC_BMODP_SIZE,
     ECC_REDC_SIZE,
     ECC_SECP192R1_INV_ITCH,
+    ECC_SECP192R1_SQRT_ITCH,
     0,
 
     ecc_p,
@@ -201,6 +254,7 @@ const struct ecc_curve _nettle_secp_192r1 =
     ecc_secp192r1_modp,
     ecc_secp192r1_modp,
     ecc_secp192r1_inv,
+    ecc_secp192r1_sqrt,
     NULL,
   },
   {
@@ -210,6 +264,7 @@ const struct ecc_curve _nettle_secp_192r1 =
     0,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_q,
     ecc_Bmodq,
@@ -221,6 +276,7 @@ const struct ecc_curve _nettle_secp_192r1 =
     ecc_mod,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
   
   USE_REDC,
index 91c337d4415e8b9cd7c4ba439000b3c0e392c3f7..767eccf7e87f2f746fb1f4f8ec5bc01c35fea762 100644 (file)
@@ -121,6 +121,7 @@ const struct ecc_curve _nettle_secp_224r1 =
     -ECC_REDC_SIZE,
     ECC_SECP224R1_INV_ITCH,
     0,
+    0,
 
     ecc_p,
     ecc_Bmodp,
@@ -132,6 +133,7 @@ const struct ecc_curve _nettle_secp_224r1 =
     USE_REDC ? ecc_secp224r1_redc : ecc_secp224r1_modp,
     ecc_secp224r1_inv,
     NULL,
+    NULL,
   },
   {
     224,
@@ -140,6 +142,7 @@ const struct ecc_curve _nettle_secp_224r1 =
     0,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_q,
     ecc_Bmodq,
@@ -151,6 +154,7 @@ const struct ecc_curve _nettle_secp_224r1 =
     ecc_mod,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
   
   USE_REDC,
index 625c9f7afc0fbf9774a8ec18ecfcf20508f9a18b..3bdbdc21aac14e09503b48c48f8c0824e29c7662 100644 (file)
@@ -273,6 +273,7 @@ const struct ecc_curve _nettle_secp_256r1 =
     ECC_BMODP_SIZE,
     ECC_REDC_SIZE,
     ECC_SECP256R1_INV_ITCH,
+    0, 
     0,
 
     ecc_p,
@@ -285,6 +286,7 @@ const struct ecc_curve _nettle_secp_256r1 =
     USE_REDC ? ecc_secp256r1_redc : ecc_secp256r1_modp,
     ecc_secp256r1_inv,
     NULL,
+    NULL,
   },
   {
     256,
@@ -293,6 +295,7 @@ const struct ecc_curve _nettle_secp_256r1 =
     0,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_q,
     ecc_Bmodq,
@@ -304,6 +307,7 @@ const struct ecc_curve _nettle_secp_256r1 =
     ecc_secp256r1_modq,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
 
   USE_REDC,
index 2c00523bd0c0bbf9323172caf6503adecbd223e6..ae76390f193cb5c76a3eb0a2beb0f4895580bae1 100644 (file)
@@ -213,6 +213,7 @@ const struct ecc_curve _nettle_secp_384r1 =
     ECC_REDC_SIZE,
     ECC_SECP384R1_INV_ITCH,
     0,
+    0,
 
     ecc_p,
     ecc_Bmodp,
@@ -224,6 +225,7 @@ const struct ecc_curve _nettle_secp_384r1 =
     ecc_secp384r1_modp,
     ecc_secp384r1_inv,
     NULL,
+    NULL,
   },
   {
     384,
@@ -232,6 +234,7 @@ const struct ecc_curve _nettle_secp_384r1 =
     0,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_q,
     ecc_Bmodq,
@@ -243,6 +246,7 @@ const struct ecc_curve _nettle_secp_384r1 =
     ecc_mod,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
 
   USE_REDC,
index 7eda37323012a8b23175dbf029cdfd17d351e4cb..1b09e7b1b210350c1591d1f2469f077dc166754b 100644 (file)
@@ -130,6 +130,7 @@ const struct ecc_curve _nettle_secp_521r1 =
     ECC_REDC_SIZE,
     ECC_SECP521R1_INV_ITCH,
     0,
+    0,
 
     ecc_p,
     ecc_Bmodp,
@@ -141,6 +142,7 @@ const struct ecc_curve _nettle_secp_521r1 =
     ecc_secp521r1_modp,
     ecc_secp521r1_inv,
     NULL,
+    NULL,
   },
   {
     521,
@@ -149,6 +151,7 @@ const struct ecc_curve _nettle_secp_521r1 =
     0,
     ECC_MOD_INV_ITCH (ECC_LIMB_SIZE),
     0,
+    0,
 
     ecc_q,
     ecc_Bmodq,
@@ -160,6 +163,7 @@ const struct ecc_curve _nettle_secp_521r1 =
     ecc_mod,
     ecc_mod_inv,
     NULL,
+    NULL,
   },
   
   USE_REDC,
index 026d7f7a9640bb6e712c390aa80047670efa1e46..69e08aa4198b60b9e097e321c06a468f3e6e5e15 100644 (file)
@@ -66,7 +66,92 @@ 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, int use_redc)
+{
+  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, "test_sqrt on %d-bit modulo. Non square: %d\n", m->bit_size, 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);
+
+      if (use_redc)
+       {
+         /* We get non-redc sqrt if we reduce u before calling m->sqrt */
+         mpz_limbs_copy (scratch, u, m->size);
+         mpn_zero (scratch + m->size, m->size);
+         m->reduce (m, up, scratch);
+       }
+      else
+       {
+         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);
+         ecc_mod_mul_1 (m, up, up, z);
+
+         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;
@@ -96,7 +181,7 @@ test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m)
     ;
 
   if (verbose)
-    fprintf(stderr, "Non square: %d\n", z);
+    fprintf(stderr, "test_sqrt_ratio on %d-bit modulo. Non square: %d\n", m->bit_size, z);
 
   for (i = 0; i < COUNT; i++)
     {
@@ -119,7 +204,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 +220,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 +250,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, ecc_curves[i]->use_redc);
       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);
 }