test_ecdsa (const struct ecc_curve *ecc,
	    /* Public key */
	    const char *xs, const char *ys,
	    /* Hash */
	    struct tstring *h,
	    /* Valid signature */
	    const char *r, const char *s)
{
  struct ecc_point pub;
  struct dsa_signature signature;
  mpz_t x, y;

  ecc_point_init (&pub, ecc);
  dsa_signature_init (&signature);

  mpz_init_set_str (x, xs, 16);
  mpz_init_set_str (y, ys, 16);

  if (!ecc_point_set (&pub, x, y))
    die ("ecc_point_set failed.\n");

  mpz_set_str (signature.r, r, 16);
  mpz_set_str (signature.s, s, 16);

  if (!ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify failed with valid signature.\n");
    fail:
      fprintf (stderr, "bit_size = %u\nx = ", ecc->p.bit_size);
      mpz_out_str (stderr, 16, x);
      fprintf (stderr, "\ny = ");
      mpz_out_str (stderr, 16, y);
      fprintf (stderr, "\ndigest ");
      print_hex (h->length, h->data);
      fprintf (stderr, "r = ");
      mpz_out_str (stderr, 16, signature.r);
      fprintf (stderr, "\ns = ");
      mpz_out_str (stderr, 16, signature.s);
      fprintf (stderr, "\n");
      abort();
    }

  mpz_combit (signature.r, ecc->p.bit_size / 3);
  if (ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify unexpectedly succeeded with invalid signature (r modified).\n");
      goto fail;
    }
  mpz_combit (signature.r, ecc->p.bit_size / 3);
  
  mpz_combit (signature.s, 4*ecc->p.bit_size / 5);
  if (ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify unexpectedly succeeded with invalid signature (s modified).\n");
      goto fail;
    }
  mpz_combit (signature.s, 4*ecc->p.bit_size / 5);

  h->data[2*h->length / 3] ^= 0x40;
  if (ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify unexpectedly succeeded with invalid signature (h modified).\n");
      goto fail;
    }
  h->data[2*h->length / 3] ^= 0x40;
  if (!ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify failed, internal testsuite error.\n");
      goto fail;
    }

  ecc_point_clear (&pub);
  dsa_signature_clear (&signature);
  mpz_clear (x);
  mpz_clear (y);  
}
test_ecdsa (const struct ecc_curve *ecc,
	     
	    const char *xs, const char *ys,
	     
	    struct tstring *h,
	     
	    const char *r, const char *s)
{
  struct ecc_point pub;
  struct dsa_signature signature;
  mpz_t x, y;

  ecc_point_init (&pub, ecc);
  dsa_signature_init (&signature);

  mpz_init_set_str (x, xs, 16);
  mpz_init_set_str (y, ys, 16);

  if (!ecc_point_set (&pub, x, y))
    die ("ecc_point_set failed.\n");

  mpz_set_str (signature.r, r, 16);
  mpz_set_str (signature.s, s, 16);

  if (!ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify failed with valid signature.\n");
    fail:
      fprintf (stderr, "bit_size = %u\nx = ", ecc->p.bit_size);
      mpz_out_str (stderr, 16, x);
      fprintf (stderr, "\ny = ");
      mpz_out_str (stderr, 16, y);
      fprintf (stderr, "\ndigest ");
      print_hex (h->length, h->data);
      fprintf (stderr, "r = ");
      mpz_out_str (stderr, 16, signature.r);
      fprintf (stderr, "\ns = ");
      mpz_out_str (stderr, 16, signature.s);
      fprintf (stderr, "\n");
      abort();
    }

  mpz_combit (signature.r, ecc->p.bit_size / 3);
  if (ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify unexpectedly succeeded with invalid signature (r modified).\n");
      goto fail;
    }
  mpz_combit (signature.r, ecc->p.bit_size / 3);
  
  mpz_combit (signature.s, 4*ecc->p.bit_size / 5);
  if (ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify unexpectedly succeeded with invalid signature (s modified).\n");
      goto fail;
    }
  mpz_combit (signature.s, 4*ecc->p.bit_size / 5);

  h->data[2*h->length / 3] ^= 0x40;
  if (ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify unexpectedly succeeded with invalid signature (h modified).\n");
      goto fail;
    }
  h->data[2*h->length / 3] ^= 0x40;
  if (!ecdsa_verify (&pub, h->length, h->data, &signature))
    {
      fprintf (stderr, "ecdsa_verify failed, internal testsuite error.\n");
      goto fail;
    }

  ecc_point_clear (&pub);
  dsa_signature_clear (&signature);
  mpz_clear (x);
  mpz_clear (y);  
}