Randomzed testing of rsa-sec-compute-root
authorSimo Sorce <simo@redhat.com>
Fri, 9 Nov 2018 22:32:04 +0000 (17:32 -0500)
committerNiels Möller <nisse@lysator.liu.se>
Sun, 25 Nov 2018 16:12:43 +0000 (17:12 +0100)
Signed-off-by: Simo Sorce <simo@redhat.com>
testsuite/.gitignore
testsuite/.test-rules.make
testsuite/Makefile.in
testsuite/rsa-sec-compute-root-test.c [new file with mode: 0644]

index 53ffff961bdef7059d3a28279825334c229023b7..b140ee3476cb3e9de02402acd8dc2b51c169e80a 100644 (file)
@@ -66,6 +66,7 @@
 /random-prime-test
 /ripemd160-test
 /rsa-sec-decrypt-test
+/rsa-sec-compute-root-test
 /rsa-encrypt-test
 /rsa-keygen-test
 /rsa-pss-sign-tr-test
index cc03851efb96ab9e8a79afc2747997dcc2d6ea13..9b329b5f923ae6ade471fd2fcc5a663980b1f9fb 100644 (file)
@@ -214,6 +214,9 @@ rsa-keygen-test$(EXEEXT): rsa-keygen-test.$(OBJEXT)
 rsa-sec-decrypt-test$(EXEEXT): rsa-sec-decrypt-test.$(OBJEXT)
        $(LINK) rsa-sec-decrypt-test.$(OBJEXT) $(TEST_OBJS) -o rsa-sec-decrypt-test$(EXEEXT)
 
+rsa-sec-compute-root-test$(EXEEXT): rsa-sec-compute-root-test.$(OBJEXT)
+       $(LINK) rsa-sec-compute-root-test.$(OBJEXT) $(TEST_OBJS) -o rsa-sec-compute-root-test$(EXEEXT)
+
 dsa-test$(EXEEXT): dsa-test.$(OBJEXT)
        $(LINK) dsa-test.$(OBJEXT) $(TEST_OBJS) -o dsa-test$(EXEEXT)
 
index ecb2f69f416f15dde1b6760acf6e93bf17b0deab..5a4174e9acbf5fd17381dc02121be739285b9556 100644 (file)
@@ -41,6 +41,7 @@ TS_HOGWEED_SOURCES = sexp-test.c sexp-format-test.c \
                     pss-mgf1-test.c rsa-pss-sign-tr-test.c \
                     rsa-test.c rsa-encrypt-test.c rsa-keygen-test.c \
                     rsa-sec-decrypt-test.c \
+                    rsa-sec-compute-root-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 \
diff --git a/testsuite/rsa-sec-compute-root-test.c b/testsuite/rsa-sec-compute-root-test.c
new file mode 100644 (file)
index 0000000..baaa7ff
--- /dev/null
@@ -0,0 +1,229 @@
+#include "testutils.h"
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <sys/time.h>
+
+#include "rsa.h"
+
+#define COUNT 5000
+
+static void
+random_fn (void *ctx, size_t n, uint8_t *dst)
+{
+  gmp_randstate_t *rands = (gmp_randstate_t *)ctx;
+  mpz_t r;
+
+  mpz_init (r);
+  mpz_urandomb (r, *rands, n*8);
+  nettle_mpz_get_str_256 (n, dst, r);
+  mpz_clear (r);
+}
+
+static void
+test_one (gmp_randstate_t *rands, struct rsa_public_key *pub,
+          struct rsa_private_key *key, mpz_t plaintext)
+{
+  mpz_t ciphertext;
+  mpz_t decrypted;
+
+  mpz_init (ciphertext);
+  mpz_init (decrypted);
+
+  mpz_powm (ciphertext, plaintext, pub->e, pub->n);
+  rsa_compute_root_tr (pub, key, rands, random_fn, decrypted, ciphertext);
+  if (mpz_cmp (plaintext, decrypted)) {
+    fprintf (stderr, "rsa_sec_compute_root_tr failed\n");
+
+    fprintf(stderr, "Public key: size=%lu\n n:", pub->size);
+    mpz_out_str (stderr, 10, pub->n);
+    fprintf(stderr, "\n e:");
+    mpz_out_str (stderr, 10, pub->e);
+    fprintf(stderr, "\nPrivate key: size=%lu\n p:", key->size);
+    mpz_out_str (stderr, 10, key->p);
+    fprintf(stderr, "\n q:");
+    mpz_out_str (stderr, 10, key->q);
+    fprintf(stderr, "\n a:");
+    mpz_out_str (stderr, 10, key->a);
+    fprintf(stderr, "\n b:");
+    mpz_out_str (stderr, 10, key->b);
+    fprintf(stderr, "\n c:");
+    mpz_out_str (stderr, 10, key->c);
+    fprintf(stderr, "\n d:");
+    mpz_out_str (stderr, 10, key->d);
+    fprintf(stderr, "\n");
+
+    fprintf (stderr, "plaintext(%lu) = ", mpz_sizeinbase (plaintext, 2));
+    mpn_out_str (stderr, 16, mpz_limbs_read (plaintext), mpz_size (plaintext));
+    fprintf (stderr, "\n");
+    fprintf (stderr, "decrypted(%lu) = ", mpz_sizeinbase (decrypted, 2));
+    mpn_out_str (stderr, 16, mpz_limbs_read (decrypted), mpz_size (decrypted));
+    fprintf (stderr, "\n");
+    abort();
+  }
+}
+
+#if !NETTLE_USE_MINI_GMP
+/* we want to generate keypairs that are not "standard" but have more size
+ * variance between q and p.
+ * Function is otheriwse the same as standard rsa_generate_keypair()
+ */
+static void
+generate_keypair (gmp_randstate_t *rands,
+                  struct rsa_public_key *pub, struct rsa_private_key *key)
+{
+  unsigned long int psize = 0;
+  unsigned long int qsize = 0;
+  mpz_t p1;
+  mpz_t q1;
+  mpz_t phi;
+  mpz_t tmp;
+
+  mpz_init (p1);
+  mpz_init (q1);
+  mpz_init (phi);
+  mpz_init (tmp);
+
+  while (psize < 100)
+    {
+      mpz_set_ui(tmp, 500);
+      mpz_urandomm (tmp, *rands, tmp);
+      psize = mpz_get_ui (tmp);
+    }
+  while (qsize < 100)
+    {
+      mpz_set_ui(tmp, 500);
+      mpz_urandomm (tmp, *rands, tmp);
+      qsize = mpz_get_ui (tmp);
+    }
+
+  mpz_set_ui (pub->e, 65537);
+
+  for (;;)
+    {
+      for (;;)
+        {
+          mpz_rrandomb (key->p, *rands, psize);
+          mpz_nextprime (key->p, key->p);
+          mpz_sub_ui (p1, key->p, 1);
+          mpz_gcd (tmp, pub->e, p1);
+          if (mpz_cmp_ui (tmp, 1) == 0)
+            break;
+        }
+
+      for (;;)
+        {
+          mpz_rrandomb (key->q, *rands, psize);
+          mpz_nextprime (key->q, key->q);
+          mpz_sub_ui (q1, key->q, 1);
+          mpz_gcd (tmp, pub->e, q1);
+          if (mpz_cmp_ui (tmp, 1) == 0)
+            break;
+        }
+
+      if (mpz_invert (key->c, key->q, key->p))
+        break;
+    }
+
+  mpz_mul(phi, p1, q1);
+  assert (mpz_invert(key->d, pub->e, phi));
+
+  mpz_fdiv_r (key->a, key->d, p1);
+  mpz_fdiv_r (key->b, key->d, q1);
+
+  mpz_mul (pub->n, key->p, key->q);
+
+  pub->size = key->size = mpz_size(pub->n) * sizeof(mp_limb_t);
+
+  mpz_clear (tmp);
+  mpz_clear (phi);
+  mpz_clear (q1);
+  mpz_clear (p1);
+}
+#endif
+
+#if !NETTLE_USE_MINI_GMP
+static void
+get_random_seed(mpz_t seed)
+{
+  struct timeval tv;
+  FILE *f;
+  f = fopen ("/dev/urandom", "rb");
+  if (f)
+    {
+      uint8_t buf[8];
+      size_t res;
+
+      setbuf (f, NULL);
+      res = fread (&buf, sizeof(buf), 1, f);
+      fclose(f);
+      if (res == 1)
+       {
+         nettle_mpz_set_str_256_u (seed, sizeof(buf), buf);
+         return;
+       }
+      fprintf (stderr, "Read of /dev/urandom failed: %s\n",
+              strerror (errno));
+    }
+  gettimeofday(&tv, NULL);
+  mpz_set_ui (seed, tv.tv_sec);
+  mpz_mul_ui (seed, seed, 1000000UL);
+  mpz_add_ui (seed, seed, tv.tv_usec);
+}
+#endif /* !NETTLE_USE_MINI_GMP */
+
+void
+test_main (void)
+{
+  const char *nettle_test_seed;
+  gmp_randstate_t rands;
+  struct rsa_public_key pub;
+  struct rsa_private_key key;
+  mpz_t plaintext;
+  unsigned i;
+
+  rsa_private_key_init(&key);
+  rsa_public_key_init(&pub);
+
+  gmp_randinit_default (rands);
+
+#if !NETTLE_USE_MINI_GMP
+  nettle_test_seed = getenv ("NETTLE_TEST_SEED");
+  if (nettle_test_seed && *nettle_test_seed)
+    {
+      mpz_t seed;
+      mpz_init (seed);
+      if (mpz_set_str (seed, nettle_test_seed, 0) < 0
+         || mpz_sgn (seed) < 0)
+       die ("Invalid NETTLE_TEST_SEED: %s\n",
+            nettle_test_seed);
+      if (mpz_sgn (seed) == 0)
+       get_random_seed (seed);
+      fprintf (stderr, "Using NETTLE_TEST_SEED=");
+      mpz_out_str (stderr, 10, seed);
+      fprintf (stderr, "\n");
+
+      gmp_randseed (rands, seed);
+      mpz_clear (seed);
+    }
+
+  generate_keypair(&rands, &pub, &key);
+#else
+  rsa_generate_keypair(&pub, &key, &rands, random_fn, NULL, NULL, 512, 16);
+#endif /* !NETTLE_USE_MINI_GMP */
+
+  mpz_init (plaintext);
+  for (i = 0; i < COUNT; i++)
+    {
+      mpz_urandomb(plaintext, rands, mpz_sizeinbase(pub.n, 2) - 1);
+      test_one(&rands, &pub, &key, plaintext);
+    }
+  for (i = 0; i < COUNT; i++)
+    {
+      mpz_rrandomb(plaintext, rands, mpz_sizeinbase(pub.n, 2) - 1);
+      test_one(&rands, &pub, &key, plaintext);
+    }
+
+  gmp_randclear (rands);
+}