]> git.ipfire.org Git - thirdparty/nettle.git/commitdiff
Implement secp521r1 square root, based on patch by Wim Lewis.
authorNiels Möller <nisse@lysator.liu.se>
Mon, 8 Nov 2021 16:51:07 +0000 (17:51 +0100)
committerNiels Möller <nisse@lysator.liu.se>
Mon, 8 Nov 2021 16:51:07 +0000 (17:51 +0100)
ChangeLog
ecc-secp521r1.c

index de09124121bf8a42e030e0c3e34e7e92484d8fd3..b6f8f3882e6d2e74f1c16dfb63047c99cbe20c12 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -8,6 +8,7 @@
        (ecc_secp192r1_sqrt): New function.
        * ecc-secp256r1.c (ecc_secp256r1_sqrt): New function.
        * ecc-secp384r1.c (ecc_secp384r1_sqrt): New function.
+       * ecc-secp521r1.c (ecc_secp521r1_sqrt): New function.
 
        * testsuite/ecc-sqrt-test.c (test_sqrt): New function.
        (test_sqrt_ratio): Renamed function (was test_modulo).
index 1b09e7b1b210350c1591d1f2469f077dc166754b..26314e59cd71108d064ade44e6d40990cbfd076b 100644 (file)
@@ -43,6 +43,8 @@
 
 #include "ecc-secp521r1.h"
 
+#define B_SHIFT (521 % GMP_NUMB_BITS)
+
 #if HAVE_NATIVE_ecc_secp521r1_modp
 #define ecc_secp521r1_modp _nettle_ecc_secp521r1_modp
 void
@@ -50,7 +52,6 @@ ecc_secp521r1_modp (const struct ecc_modulo *m, mp_limb_t *rp, mp_limb_t *xp);
 
 #else
 
-#define B_SHIFT (521 % GMP_NUMB_BITS)
 #define BMODP_SHIFT (GMP_NUMB_BITS - B_SHIFT)
 #define BMODP ((mp_limb_t) 1 << BMODP_SHIFT)
 
@@ -121,6 +122,39 @@ ecc_secp521r1_inv (const struct ecc_modulo *p,
   ecc_mod_mul (p, rp, rp, ap, tp);     /* a^{2^519 - 3} */
 }
 
+#define ECC_SECP521R1_SQRT_ITCH (2*ECC_LIMB_SIZE)
+
+static int
+ecc_secp521r1_sqrt (const struct ecc_modulo *m,
+                   mp_limb_t *rp,
+                   const mp_limb_t *cp,
+                   mp_limb_t *scratch)
+{
+  mp_limb_t hi;
+
+  /* This computes the square root modulo p256 using the identity:
+
+     sqrt(c) = c^(2^519) (mod P-521)
+
+     which can be seen as a special case of Tonelli-Shanks with e=1.
+  */
+
+  ecc_mod_pow_2k (m, rp, cp, 519, scratch);
+
+  /* Check result. */
+  ecc_mod_sqr (m, scratch, rp, scratch);
+  ecc_mod_sub (m, scratch, scratch, cp);
+
+  /* Reduce top bits, since ecc_mod_zero_p requires input < 2p */
+  hi = scratch[ECC_LIMB_SIZE-1] >> B_SHIFT;
+  scratch[ECC_LIMB_SIZE-1] = (scratch[ECC_LIMB_SIZE-1]
+                             & (((mp_limb_t) 1 << B_SHIFT)-1))
+    + sec_add_1 (scratch, scratch, ECC_LIMB_SIZE - 1, hi);
+
+  return ecc_mod_zero_p (m, scratch);
+}
+
+
 const struct ecc_curve _nettle_secp_521r1 =
 {
   {
@@ -129,7 +163,7 @@ const struct ecc_curve _nettle_secp_521r1 =
     ECC_BMODP_SIZE,
     ECC_REDC_SIZE,
     ECC_SECP521R1_INV_ITCH,
-    0,
+    ECC_SECP521R1_SQRT_ITCH,
     0,
 
     ecc_p,
@@ -141,7 +175,7 @@ const struct ecc_curve _nettle_secp_521r1 =
     ecc_secp521r1_modp,
     ecc_secp521r1_modp,
     ecc_secp521r1_inv,
-    NULL,
+    ecc_secp521r1_sqrt,
     NULL,
   },
   {