diff --git a/ChangeLog b/ChangeLog
index 8629842603b637bad8a07f6ca2b1286bebe0d24b..c71738f36c70e72295bf4911138e160fb52d46be 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,23 @@
+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
diff --git a/ecc-192.c b/ecc-192.c
index 4f428113674e246e22d7ad67d32d5b114983a656..d938ea03abc0666f1f0949d57ab38f67c6513521 100644
--- a/ecc-192.c
+++ b/ecc-192.c
@@ -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,
diff --git a/ecc-224.c b/ecc-224.c
index 5962e1b863bfd1e4e7bf1a723943c513a2c56b43..3d2014cd4ce5d5301b869ee8fe91d1b0171696d9 100644
--- a/ecc-224.c
+++ b/ecc-224.c
@@ -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,
diff --git a/ecc-25519.c b/ecc-25519.c
index fdf3299d60b7b1d94a1081a1fe6e75e16a9f0b68..d7b25c087c93b2d878dc164fe57aabc6995f7eab 100644
--- a/ecc-25519.c
+++ b/ecc-25519.c
@@ -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 */
diff --git a/ecc-256.c b/ecc-256.c
index 7eed2835c08a0719ce6c6f5e6ff016f8d43e3eb2..cd8fedf381ab31ddea6203a0fc0408ffee4fa10f 100644
--- a/ecc-256.c
+++ b/ecc-256.c
@@ -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,
diff --git a/ecc-384.c b/ecc-384.c
index 94b8af91354e767b7a7232d955218226f9588730..32a73883a76857adfb8b773a8702fd5f02220879 100644
--- a/ecc-384.c
+++ b/ecc-384.c
@@ -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,
diff --git a/ecc-521.c b/ecc-521.c
index 52a018dd7c9c0124c90dc1cbd389e79cd47e1c11..117d5a668d9218e2b8f633f6cf656030506f9b7a 100644
--- a/ecc-521.c
+++ b/ecc-521.c
@@ -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,
diff --git a/ecc-internal.h b/ecc-internal.h
index 247b8e7c0bcb3691bbd7929821d0c49bdfa85d39..72fc37157588db9fa11aa82f4a9874e6f12c6734 100644
--- a/ecc-internal.h
+++ b/ecc-internal.h
@@ -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;
 };
 
diff --git a/eddsa-decompress.c b/eddsa-decompress.c
index 05d60245daff22aa6c3aa47b9d9685b2be2d9ee7..710fd405164481d8a3123defc1c74244206c5191 100644
--- a/eddsa-decompress.c
+++ b/eddsa-decompress.c
@@ -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
diff --git a/testsuite/ecc-sqrt-test.c b/testsuite/ecc-sqrt-test.c
index 4c70677dfd5aab8f1a0241022342aec7df0cb688..5be2648b70a42e2032735ec2d492ddbf6d865bf5 100644
--- a/testsuite/ecc-sqrt-test.c
+++ b/testsuite/ecc-sqrt-test.c
@@ -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);
 }