From 957f14088f471b2cb0ff9f82e8ee99ca5586313d Mon Sep 17 00:00:00 2001 From: Simon Tatham Date: Sun, 23 Feb 2020 14:45:19 +0000 Subject: [PATCH] mpint: add mp_random_upto(). This is a third random-number generation function, with an API in between the too-specific mp_random_bits and the too-general mp_random_in_range. Now you can generate a value between 0 and n without having to either make n a power of 2, or tediously allocate a zero mp_int to be the lower limit for mp_random_in_range. Implementation is done by sawing the existing mp_random_in_range into two pieces and exposing the API between them. --- mpint.c | 21 ++++++++++++++------- mpint.h | 3 +++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/mpint.c b/mpint.c index b59d8464..9541535e 100644 --- a/mpint.c +++ b/mpint.c @@ -2423,10 +2423,8 @@ mp_int *mp_random_bits_fn(size_t bits, random_read_fn_t random_read) return toret; } -mp_int *mp_random_in_range_fn(mp_int *lo, mp_int *hi, random_read_fn_t rf) +mp_int *mp_random_upto_fn(mp_int *limit, random_read_fn_t rf) { - mp_int *n_outcomes = mp_sub(hi, lo); - /* * It would be nice to generate our random numbers in such a way * as to make every possible outcome literally equiprobable. But @@ -2436,10 +2434,19 @@ mp_int *mp_random_in_range_fn(mp_int *lo, mp_int *hi, random_read_fn_t rf) * is acceptable on the grounds that you'd have to examine so many * outputs to even detect it. */ - mp_int *unreduced = mp_random_bits_fn(mp_max_bits(n_outcomes) + 128, rf); - mp_int *reduced = mp_mod(unreduced, n_outcomes); - mp_add_into(reduced, reduced, lo); + mp_int *unreduced = mp_random_bits_fn(mp_max_bits(limit) + 128, rf); + mp_int *reduced = mp_mod(unreduced, limit); mp_free(unreduced); - mp_free(n_outcomes); return reduced; } + +mp_int *mp_random_in_range_fn(mp_int *lo, mp_int *hi, random_read_fn_t rf) +{ + mp_int *n_outcomes = mp_sub(hi, lo); + mp_int *addend = mp_random_upto_fn(n_outcomes, rf); + mp_int *result = mp_make_sized(hi->nw); + mp_add_into(result, addend, lo); + mp_free(addend); + mp_free(n_outcomes); + return result; +} diff --git a/mpint.h b/mpint.h index 0ed46b12..f0bb0fe6 100644 --- a/mpint.h +++ b/mpint.h @@ -399,13 +399,16 @@ mp_int *mp_rshift_fixed(mp_int *x, size_t shift); * then _they_ have link-time dependencies on both modules.) * * mp_random_bits[_fn] returns an integer 0 <= n < 2^bits. + * mp_random_upto[_fn](limit) returns an integer 0 <= n < limit. * mp_random_in_range[_fn](lo,hi) returns an integer lo <= n < hi. */ typedef void (*random_read_fn_t)(void *, size_t); mp_int *mp_random_bits_fn(size_t bits, random_read_fn_t randfn); +mp_int *mp_random_upto_fn(mp_int *limit, random_read_fn_t randfn); mp_int *mp_random_in_range_fn( mp_int *lo_inclusive, mp_int *hi_exclusive, random_read_fn_t randfn); #define mp_random_bits(bits) mp_random_bits_fn(bits, random_read) +#define mp_random_upto(limit) mp_random_upto_fn(limit, random_read) #define mp_random_in_range(lo, hi) mp_random_in_range_fn(lo, hi, random_read) #endif /* PUTTY_MPINT_H */