support custom random data source via mp_rand_source
* deprecate MP_PRNG_ENABLE_LTM_RNG * custom mp_rand_source is used always if set, which should be more aligned with user expectations * use custom source in tune.c * don't call random number generator once per digit, which is slow
This commit is contained in:
parent
f0f75186cd
commit
9ddf1e5838
141
bn_mp_rand.c
141
bn_mp_rand.c
@ -8,22 +8,7 @@
|
||||
* - Windows
|
||||
*/
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||
#define MP_ARC4RANDOM
|
||||
#define MP_GEN_RANDOM_MAX 0xffffffffu
|
||||
#define MP_GEN_RANDOM_SHIFT 32
|
||||
|
||||
static int s_read_arc4random(mp_digit *p)
|
||||
{
|
||||
mp_digit d = 0, msk = 0;
|
||||
do {
|
||||
d <<= MP_GEN_RANDOM_SHIFT;
|
||||
d |= ((mp_digit) arc4random());
|
||||
msk <<= MP_GEN_RANDOM_SHIFT;
|
||||
msk |= (MP_MASK & MP_GEN_RANDOM_MAX);
|
||||
} while ((MP_MASK & msk) != MP_MASK);
|
||||
*p = d;
|
||||
return MP_OKAY;
|
||||
}
|
||||
# define MP_ARC4RANDOM
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN32_WCE)
|
||||
@ -49,23 +34,19 @@ static void s_cleanup_win_csp(void)
|
||||
hProv = 0;
|
||||
}
|
||||
|
||||
static int s_read_win_csp(mp_digit *p)
|
||||
static int s_read_win_csp(void *p, size_t n)
|
||||
{
|
||||
int ret = -1;
|
||||
if (hProv == 0) {
|
||||
if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
|
||||
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
|
||||
!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
|
||||
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) {
|
||||
hProv = 0;
|
||||
return ret;
|
||||
return MP_ERR;
|
||||
}
|
||||
atexit(s_cleanup_win_csp);
|
||||
}
|
||||
if (CryptGenRandom(hProv, sizeof(*p), (void *)p) == TRUE) {
|
||||
ret = MP_OKAY;
|
||||
}
|
||||
return ret;
|
||||
return CryptGenRandom(hProv, (DWORD)n, (BYTE *)p) == TRUE ? MP_OKAY : MP_ERR;
|
||||
}
|
||||
#endif /* WIN32 */
|
||||
|
||||
@ -75,14 +56,21 @@ static int s_read_win_csp(mp_digit *p)
|
||||
#include <sys/random.h>
|
||||
#include <errno.h>
|
||||
|
||||
static int s_read_getrandom(mp_digit *p)
|
||||
static int s_read_getrandom(void *p, size_t n)
|
||||
{
|
||||
ssize_t ret;
|
||||
do {
|
||||
ret = getrandom(p, sizeof(*p), 0);
|
||||
} while ((ret == -1) && (errno == EINTR));
|
||||
if (ret == sizeof(*p)) return MP_OKAY;
|
||||
return -1;
|
||||
char *q = (char *)p;
|
||||
while (n > 0) {
|
||||
ssize_t ret = getrandom(q, n, 0);
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
return MP_ERR;
|
||||
}
|
||||
q += ret;
|
||||
n -= (size_t)ret;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -98,19 +86,30 @@ static int s_read_getrandom(mp_digit *p)
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int s_read_dev_urandom(mp_digit *p)
|
||||
static int s_read_dev_urandom(void *p, size_t n)
|
||||
{
|
||||
ssize_t r;
|
||||
int fd;
|
||||
char *q = (char *)p;
|
||||
|
||||
do {
|
||||
fd = open(MP_DEV_URANDOM, O_RDONLY);
|
||||
} while ((fd == -1) && (errno == EINTR));
|
||||
if (fd == -1) return -1;
|
||||
do {
|
||||
r = read(fd, p, sizeof(*p));
|
||||
} while ((r == -1) && (errno == EINTR));
|
||||
if (fd == -1) return MP_ERR;
|
||||
|
||||
while (n > 0) {
|
||||
ssize_t ret = read(fd, p, n);
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
close(fd);
|
||||
return MP_ERR;
|
||||
}
|
||||
q += ret;
|
||||
n -= (size_t)ret;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
if (r != sizeof(*p)) return -1;
|
||||
return MP_OKAY;
|
||||
}
|
||||
#endif
|
||||
@ -119,91 +118,95 @@ static int s_read_dev_urandom(mp_digit *p)
|
||||
unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void));
|
||||
void (*ltm_rng_callback)(void);
|
||||
|
||||
static int s_read_ltm_rng(mp_digit *p)
|
||||
static int s_read_ltm_rng(void *p, size_t n)
|
||||
{
|
||||
unsigned long ret;
|
||||
if (ltm_rng == NULL) return -1;
|
||||
ret = ltm_rng((void *)p, sizeof(*p), ltm_rng_callback);
|
||||
if (ret != sizeof(*p)) return -1;
|
||||
if (ltm_rng == NULL) return MP_ERR;
|
||||
ret = ltm_rng(p, n, ltm_rng_callback);
|
||||
if (ret != n) return MP_ERR;
|
||||
return MP_OKAY;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int s_rand_digit(mp_digit *p)
|
||||
static int s_mp_rand_source_platform(void *p, size_t n)
|
||||
{
|
||||
int ret = -1;
|
||||
int ret = MP_ERR;
|
||||
|
||||
#if defined(MP_ARC4RANDOM)
|
||||
ret = s_read_arc4random(p);
|
||||
if (ret == MP_OKAY) return ret;
|
||||
arc4random_buf(p, n);
|
||||
return MP_OKAY;
|
||||
#endif
|
||||
|
||||
#if defined(MP_WIN_CSP)
|
||||
ret = s_read_win_csp(p);
|
||||
ret = s_read_win_csp(p, n);
|
||||
if (ret == MP_OKAY) return ret;
|
||||
#else
|
||||
|
||||
#if defined(MP_GETRANDOM)
|
||||
ret = s_read_getrandom(p);
|
||||
ret = s_read_getrandom(p, n);
|
||||
if (ret == MP_OKAY) return ret;
|
||||
#endif
|
||||
#if defined(MP_DEV_URANDOM)
|
||||
ret = s_read_dev_urandom(p);
|
||||
ret = s_read_dev_urandom(p, n);
|
||||
if (ret == MP_OKAY) return ret;
|
||||
#endif
|
||||
|
||||
#endif /* MP_WIN_CSP */
|
||||
|
||||
#if defined(MP_PRNG_ENABLE_LTM_RNG)
|
||||
ret = s_read_ltm_rng(p);
|
||||
ret = s_read_ltm_rng(p, n);
|
||||
if (ret == MP_OKAY) return ret;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int (*s_rand_source)(void *, size_t) = s_mp_rand_source_platform;
|
||||
|
||||
void mp_rand_source(int (*get)(void *out, size_t size))
|
||||
{
|
||||
s_rand_source = get;
|
||||
}
|
||||
|
||||
/* makes a pseudo-random int of a given size */
|
||||
int mp_rand_digit(mp_digit *r)
|
||||
{
|
||||
int ret = s_rand_digit(r);
|
||||
int ret = s_rand_source(r, sizeof(mp_digit));
|
||||
*r &= MP_MASK;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mp_rand(mp_int *a, int digits)
|
||||
{
|
||||
int res;
|
||||
mp_digit d;
|
||||
int ret, i;
|
||||
|
||||
mp_zero(a);
|
||||
|
||||
if (digits <= 0) {
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
/* first place a random non-zero digit */
|
||||
do {
|
||||
if (mp_rand_digit(&d) != MP_OKAY) {
|
||||
return MP_VAL;
|
||||
}
|
||||
} while (d == 0u);
|
||||
|
||||
if ((res = mp_add_d(a, d, a)) != MP_OKAY) {
|
||||
return res;
|
||||
if ((ret = mp_grow(a, digits)) != MP_OKAY) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
while (--digits > 0) {
|
||||
if ((res = mp_lshd(a, 1)) != MP_OKAY) {
|
||||
return res;
|
||||
if ((ret = s_rand_source(a->dp, (size_t)digits * sizeof(mp_digit))) != MP_OKAY) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (mp_rand_digit(&d) != MP_OKAY) {
|
||||
return MP_VAL;
|
||||
}
|
||||
if ((res = mp_add_d(a, d, a)) != MP_OKAY) {
|
||||
return res;
|
||||
/* TODO: We ensure that the highest digit is nonzero. Should this be removed? */
|
||||
while ((a->dp[digits - 1] & MP_MASK) == 0) {
|
||||
if ((ret = s_rand_source(a->dp + digits - 1, sizeof(mp_digit))) != MP_OKAY) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
a->used = digits;
|
||||
for (i = 0; i < digits; ++i) {
|
||||
a->dp[i] &= MP_MASK;
|
||||
}
|
||||
|
||||
mp_clamp(a);
|
||||
return MP_OKAY;
|
||||
}
|
||||
#endif
|
||||
|
@ -7377,13 +7377,8 @@ BN_MP_PRIME_IS_PRIME_C
|
||||
+--->BN_MP_COUNT_BITS_C
|
||||
+--->BN_MP_RAND_C
|
||||
| +--->BN_MP_ZERO_C
|
||||
| +--->BN_MP_ADD_D_C
|
||||
| | +--->BN_MP_GROW_C
|
||||
| | +--->BN_MP_SUB_D_C
|
||||
| | | +--->BN_MP_CLAMP_C
|
||||
| | +--->BN_MP_CLAMP_C
|
||||
| +--->BN_MP_LSHD_C
|
||||
| | +--->BN_MP_GROW_C
|
||||
| +--->BN_MP_GROW_C
|
||||
| +--->BN_MP_CLAMP_C
|
||||
+--->BN_MP_DIV_2D_C
|
||||
| +--->BN_MP_COPY_C
|
||||
| | +--->BN_MP_GROW_C
|
||||
@ -9971,8 +9966,8 @@ BN_MP_PRIME_NEXT_PRIME_C
|
||||
| +--->BN_MP_COUNT_BITS_C
|
||||
| +--->BN_MP_RAND_C
|
||||
| | +--->BN_MP_ZERO_C
|
||||
| | +--->BN_MP_LSHD_C
|
||||
| | | +--->BN_MP_GROW_C
|
||||
| | +--->BN_MP_GROW_C
|
||||
| | +--->BN_MP_CLAMP_C
|
||||
| +--->BN_MP_DIV_2D_C
|
||||
| | +--->BN_MP_COPY_C
|
||||
| | | +--->BN_MP_GROW_C
|
||||
@ -11768,13 +11763,8 @@ BN_MP_PRIME_RANDOM_EX_C
|
||||
| +--->BN_MP_COUNT_BITS_C
|
||||
| +--->BN_MP_RAND_C
|
||||
| | +--->BN_MP_ZERO_C
|
||||
| | +--->BN_MP_ADD_D_C
|
||||
| | | +--->BN_MP_GROW_C
|
||||
| | | +--->BN_MP_SUB_D_C
|
||||
| | | | +--->BN_MP_CLAMP_C
|
||||
| | | +--->BN_MP_CLAMP_C
|
||||
| | +--->BN_MP_LSHD_C
|
||||
| | | +--->BN_MP_GROW_C
|
||||
| | +--->BN_MP_GROW_C
|
||||
| | +--->BN_MP_CLAMP_C
|
||||
| +--->BN_MP_DIV_2D_C
|
||||
| | +--->BN_MP_COPY_C
|
||||
| | | +--->BN_MP_GROW_C
|
||||
@ -12169,13 +12159,8 @@ BN_MP_RADIX_SMAP_C
|
||||
|
||||
BN_MP_RAND_C
|
||||
+--->BN_MP_ZERO_C
|
||||
+--->BN_MP_ADD_D_C
|
||||
| +--->BN_MP_GROW_C
|
||||
| +--->BN_MP_SUB_D_C
|
||||
| | +--->BN_MP_CLAMP_C
|
||||
| +--->BN_MP_CLAMP_C
|
||||
+--->BN_MP_LSHD_C
|
||||
| +--->BN_MP_GROW_C
|
||||
+--->BN_MP_GROW_C
|
||||
+--->BN_MP_CLAMP_C
|
||||
|
||||
|
||||
BN_MP_READ_RADIX_C
|
||||
|
30
etc/tune.c
30
etc/tune.c
@ -12,7 +12,6 @@
|
||||
|
||||
static uint64_t s_ranval(void);
|
||||
static void s_raninit(uint64_t seed);
|
||||
static int s_mp_random(mp_int *a, int limbs);
|
||||
static uint64_t s_timer_function(void);
|
||||
static void s_timer_start(void);
|
||||
static uint64_t s_timer_stop(void);
|
||||
@ -64,19 +63,18 @@ static void s_raninit(uint64_t seed)
|
||||
source of the OS for its purpose. That is too expensive, too slow and
|
||||
most important for a benchmark: it is not repeatable.
|
||||
*/
|
||||
static int s_mp_random(mp_int *a, int limbs)
|
||||
static int s_ranbuf(void *p, size_t n)
|
||||
{
|
||||
int e = MP_OKAY;
|
||||
if ((e = mp_grow(a, limbs + 1)) != MP_OKAY) {
|
||||
goto LTM_ERR;
|
||||
char *q = (char *)p;
|
||||
while (n > 0) {
|
||||
int i;
|
||||
uint64_t x = s_ranval();
|
||||
for (i = 0; i < 8 && n > 0; ++i, --n) {
|
||||
*q++ = (char)(x & 0xFF);
|
||||
x >>= 8;
|
||||
}
|
||||
a->used = limbs--;
|
||||
do {
|
||||
a->dp[limbs] = (mp_digit)(s_ranval() & MP_MASK);
|
||||
} while (limbs--);
|
||||
mp_clamp(a);
|
||||
LTM_ERR:
|
||||
return e;
|
||||
}
|
||||
return MP_OKAY;
|
||||
}
|
||||
|
||||
static uint64_t s_timer_function(void)
|
||||
@ -127,11 +125,11 @@ static uint64_t s_time_mul(int size)
|
||||
goto LTM_ERR;
|
||||
}
|
||||
|
||||
if ((e = s_mp_random(&a, size * s_offset)) != MP_OKAY) {
|
||||
if ((e = mp_rand(&a, size * s_offset)) != MP_OKAY) {
|
||||
t1 = UINT64_MAX;
|
||||
goto LTM_ERR;
|
||||
}
|
||||
if ((e = s_mp_random(&b, size)) != MP_OKAY) {
|
||||
if ((e = mp_rand(&b, size)) != MP_OKAY) {
|
||||
t1 = UINT64_MAX;
|
||||
goto LTM_ERR;
|
||||
}
|
||||
@ -172,7 +170,7 @@ static uint64_t s_time_sqr(int size)
|
||||
goto LTM_ERR;
|
||||
}
|
||||
|
||||
if ((e = s_mp_random(&a, size)) != MP_OKAY) {
|
||||
if ((e = mp_rand(&a, size)) != MP_OKAY) {
|
||||
t1 = UINT64_MAX;
|
||||
goto LTM_ERR;
|
||||
}
|
||||
@ -265,6 +263,8 @@ int main(int argc, char **argv)
|
||||
s_number_of_test_loops = 64;
|
||||
s_stabilization_extra = 3;
|
||||
|
||||
mp_rand_source(s_ranbuf);
|
||||
|
||||
/* Very simple option parser, please treat it nicely. */
|
||||
if (argc != 1) {
|
||||
for (opt = 1; (opt < argc) && (argv[opt][0] == '-'); opt++) {
|
||||
|
@ -106,6 +106,7 @@ typedef uint64_t mp_word;
|
||||
#define MP_NEG 1 /* negative */
|
||||
|
||||
#define MP_OKAY 0 /* ok result */
|
||||
#define MP_ERR -1 /* unknown error */
|
||||
#define MP_MEM -2 /* out of mem */
|
||||
#define MP_VAL -3 /* invalid input */
|
||||
#define MP_RANGE MP_VAL
|
||||
@ -304,8 +305,11 @@ int mp_cnt_lsb(const mp_int *a);
|
||||
int mp_rand(mp_int *a, int digits);
|
||||
/* makes a pseudo-random small int of a given size */
|
||||
int mp_rand_digit(mp_digit *r);
|
||||
/* use custom random data source instead of source provided the platform */
|
||||
void mp_rand_source(int source(void *, size_t));
|
||||
|
||||
#ifdef MP_PRNG_ENABLE_LTM_RNG
|
||||
# warning MP_PRNG_ENABLE_LTM_RNG has been deprecated, use mp_rand_source instead.
|
||||
/* A last resort to provide random data on systems without any of the other
|
||||
* implemented ways to gather entropy.
|
||||
* It is compatible with `rng_get_bytes()` from libtomcrypt so you could
|
||||
|
@ -759,10 +759,12 @@
|
||||
#endif
|
||||
|
||||
#if defined(BN_MP_RAND_C)
|
||||
# define BN_S_MP_RAND_SOURCE_PLATFORM_C
|
||||
# define BN_MP_RAND_SOURCE_C
|
||||
# define BN_MP_RAND_DIGIT_C
|
||||
# define BN_MP_ZERO_C
|
||||
# define BN_MP_ADD_D_C
|
||||
# define BN_MP_LSHD_C
|
||||
# define BN_MP_GROW_C
|
||||
# define BN_MP_CLAMP_C
|
||||
#endif
|
||||
|
||||
#if defined(BN_MP_READ_RADIX_C)
|
||||
|
Loading…
Reference in New Issue
Block a user