diff --git a/ChangeLog b/ChangeLog
index f570a1d445c393192f2b3b119e2eecc1393d7258..637060bd7bd63eeee8bdb880c913b1dc1fe27b1d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,9 @@
 2014-10-02  Niels Möller  <nisse@lysator.liu.se>
 
+	* testsuite/ecc-sqrt-test.c: New test case.
+	* testsuite/Makefile.in (TS_HOGWEED_SOURCES): Added
+	ecc-sqrt-test.c.
+
 	* ecc-25519.c (PHIGH_BITS): Always define this constant.
 	(ecc_25519_zero_p): New function.
 	(ecc_25519_sqrt): Take a ratio u/v as input. Added scratch
diff --git a/testsuite/.test-rules.make b/testsuite/.test-rules.make
index fc87f1ebe1a62b36f220bad52e94eed65e80b85c..3399f9ef58ace2223a70ee5fb04653ea53e9ae8d 100644
--- a/testsuite/.test-rules.make
+++ b/testsuite/.test-rules.make
@@ -187,12 +187,6 @@ dsa-test$(EXEEXT): dsa-test.$(OBJEXT)
 dsa-keygen-test$(EXEEXT): dsa-keygen-test.$(OBJEXT)
 	$(LINK) dsa-keygen-test.$(OBJEXT) $(TEST_OBJS) -o dsa-keygen-test$(EXEEXT)
 
-curve25519-dup-test$(EXEEXT): curve25519-dup-test.$(OBJEXT)
-	$(LINK) curve25519-dup-test.$(OBJEXT) $(TEST_OBJS) -o curve25519-dup-test$(EXEEXT)
-
-curve25519-add-test$(EXEEXT): curve25519-add-test.$(OBJEXT)
-	$(LINK) curve25519-add-test.$(OBJEXT) $(TEST_OBJS) -o curve25519-add-test$(EXEEXT)
-
 curve25519-dh-test$(EXEEXT): curve25519-dh-test.$(OBJEXT)
 	$(LINK) curve25519-dh-test.$(OBJEXT) $(TEST_OBJS) -o curve25519-dh-test$(EXEEXT)
 
@@ -205,6 +199,9 @@ ecc-modinv-test$(EXEEXT): ecc-modinv-test.$(OBJEXT)
 ecc-redc-test$(EXEEXT): ecc-redc-test.$(OBJEXT)
 	$(LINK) ecc-redc-test.$(OBJEXT) $(TEST_OBJS) -o ecc-redc-test$(EXEEXT)
 
+ecc-sqrt-test$(EXEEXT): ecc-sqrt-test.$(OBJEXT)
+	$(LINK) ecc-sqrt-test.$(OBJEXT) $(TEST_OBJS) -o ecc-sqrt-test$(EXEEXT)
+
 ecc-dup-test$(EXEEXT): ecc-dup-test.$(OBJEXT)
 	$(LINK) ecc-dup-test.$(OBJEXT) $(TEST_OBJS) -o ecc-dup-test$(EXEEXT)
 
diff --git a/testsuite/Makefile.in b/testsuite/Makefile.in
index a5c5458c205cda6c6dd2d0703f000f98c5050d42..31bd29d5808b1fedbce405f862cce5070091b607 100644
--- a/testsuite/Makefile.in
+++ b/testsuite/Makefile.in
@@ -40,6 +40,7 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
 		     dsa-test.c dsa-keygen-test.c \
 		     curve25519-dh-test.c \
 		     ecc-mod-test.c ecc-modinv-test.c ecc-redc-test.c \
+		     ecc-sqrt-test.c \
 		     ecc-dup-test.c ecc-add-test.c \
 		     ecc-mul-g-test.c ecc-mul-a-test.c \
 		     ecdsa-sign-test.c ecdsa-verify-test.c \
diff --git a/testsuite/ecc-sqrt-test.c b/testsuite/ecc-sqrt-test.c
new file mode 100644
index 0000000000000000000000000000000000000000..08cd8f38ac505bb41e31710e2708c40dce835bd7
--- /dev/null
+++ b/testsuite/ecc-sqrt-test.c
@@ -0,0 +1,140 @@
+/* ecc-sqrt.c
+
+   Copyright (C) 2014 Niels Möller
+
+   This file is part of GNU Nettle.
+
+   GNU Nettle is free software: you can redistribute it and/or
+   modify it under the terms of either:
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at your
+       option) any later version.
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at your
+       option) any later version.
+
+   or both in parallel, as here.
+
+   GNU Nettle is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see http://www.gnu.org/licenses/.
+*/
+
+#include "testutils.h"
+
+#define COUNT 5000
+
+static void
+test_modulo (gmp_randstate_t rands, const struct ecc_modulo *m)
+{
+  mpz_t u;
+  mpz_t v;
+  mpz_t p;
+  mpz_t r;
+  mpz_t t;
+
+  unsigned z, i;
+  mp_limb_t *up;
+  mp_limb_t *vp;
+  mp_limb_t *rp;
+  mp_limb_t *scratch;
+
+  mpz_init (u);
+  mpz_init (v);
+  mpz_init (t);
+
+  mpz_roinit_n (p, m->m, m->size);
+
+  up = xalloc_limbs (m->size);
+  vp = 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);
+	  mpz_rrandomb (v, rands, m->bit_size);
+	}
+      else
+	{
+	  mpz_urandomb (u, rands, m->bit_size);
+	  mpz_urandomb (v, rands, m->bit_size);
+	}
+      mpz_limbs_copy (up, u, m->size);
+      mpz_limbs_copy (vp, v, m->size);
+      if (!m->sqrt (m, rp, up, vp, 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, vp, scratch))
+	    {
+	      fprintf (stderr, "m->sqrt returned failure, bit_size = %d\n"
+		       "u = 0x",
+		       m->bit_size);
+	      mpz_out_str (stderr, 16, u);
+	      fprintf (stderr, "\nv = 0x");
+	      mpz_out_str (stderr, 16, v);
+	      fprintf (stderr, "\n");
+	      abort ();
+	    }
+	}
+      /* Check that r^2 v = u */
+      mpz_roinit_n (r, rp, m->size);
+      mpz_mul (t, r, r);
+      mpz_mul (t, t, v);
+      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, "\nv = 0x");
+	  mpz_out_str (stderr, 16, v);
+	  fprintf (stderr, "\nr = 0x");
+	  mpz_out_str (stderr, 16, r);
+	  fprintf (stderr, "\n");
+	  abort ();
+	}
+    }
+  mpz_clear (u);
+  mpz_clear (v);
+  mpz_clear (t);
+  free (up);
+  free (vp);
+  free (rp);
+  free (scratch);
+}
+
+void
+test_main (void)
+{
+  gmp_randstate_t rands;
+  unsigned i;
+
+  gmp_randinit_default (rands);
+  for (i = 0; ecc_curves[i]; i++)
+    {
+      if (ecc_curves[i]->p.sqrt)
+	test_modulo (rands, &ecc_curves[i]->p);
+    }
+  gmp_randclear (rands);
+}