Commit eb4c86c4 authored by Simo Sorce's avatar Simo Sorce Committed by Niels Möller

Randomzed testing of rsa-sec-compute-root

Signed-off-by: default avatarSimo Sorce <>
parent a287f1a9
......@@ -66,6 +66,7 @@
......@@ -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)
......@@ -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 \
#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");
/* 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)
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)
if (mpz_invert (key->c, key->q, key->p))
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);
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);
if (res == 1)
nettle_mpz_set_str_256_u (seed, sizeof(buf), buf);
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 */
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;
gmp_randinit_default (rands);
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",
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);
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);
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment