commit
71c5c8ac4b
184
bn_mp_rand.c
184
bn_mp_rand.c
@ -13,34 +13,171 @@
|
|||||||
* guarantee it works.
|
* guarantee it works.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#if defined(MP_8BIT) || defined(MP_16BIT)
|
/* First the OS-specific special cases
|
||||||
#define MP_GEN_RANDOM_SHIFT DIGIT_BIT
|
* - *BSD
|
||||||
#else
|
* - Windows
|
||||||
#if MP_GEN_RANDOM_MAX == 0xffffffffu
|
*/
|
||||||
|
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
||||||
|
#define MP_ARC4RANDOM
|
||||||
|
#define MP_GEN_RANDOM_MAX 0xffffffffu
|
||||||
#define MP_GEN_RANDOM_SHIFT 32
|
#define MP_GEN_RANDOM_SHIFT 32
|
||||||
#elif MP_GEN_RANDOM_MAX == 32767
|
|
||||||
/* SHRT_MAX */
|
|
||||||
#define MP_GEN_RANDOM_SHIFT 15
|
|
||||||
#elif MP_GEN_RANDOM_MAX == 2147483647
|
|
||||||
/* INT_MAX */
|
|
||||||
#define MP_GEN_RANDOM_SHIFT 31
|
|
||||||
#elif !defined(MP_GEN_RANDOM_SHIFT)
|
|
||||||
#error Thou shalt define their own valid MP_GEN_RANDOM_SHIFT
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* makes a pseudo-random int of a given size */
|
static int s_read_arc4random(mp_digit* p)
|
||||||
static mp_digit s_gen_random(void)
|
|
||||||
{
|
{
|
||||||
mp_digit d = 0, msk = 0;
|
mp_digit d = 0, msk = 0;
|
||||||
do {
|
do {
|
||||||
d <<= MP_GEN_RANDOM_SHIFT;
|
d <<= MP_GEN_RANDOM_SHIFT;
|
||||||
d |= ((mp_digit) MP_GEN_RANDOM());
|
d |= ((mp_digit) arc4random());
|
||||||
msk <<= MP_GEN_RANDOM_SHIFT;
|
msk <<= MP_GEN_RANDOM_SHIFT;
|
||||||
msk |= (MP_MASK & MP_GEN_RANDOM_MAX);
|
msk |= (MP_MASK & MP_GEN_RANDOM_MAX);
|
||||||
} while ((MP_MASK & msk) != MP_MASK);
|
} while ((MP_MASK & msk) != MP_MASK);
|
||||||
d &= MP_MASK;
|
*p = d;
|
||||||
return d;
|
return MP_OKAY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32) || defined(_WIN32_WCE)
|
||||||
|
#define MP_WIN_CSP
|
||||||
|
|
||||||
|
#ifndef _WIN32_WINNT
|
||||||
|
#define _WIN32_WINNT 0x0400
|
||||||
|
#endif
|
||||||
|
#ifdef _WIN32_WCE
|
||||||
|
#define UNDER_CE
|
||||||
|
#define ARM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WIN32_LEAN_AND_MEAN
|
||||||
|
#include <windows.h>
|
||||||
|
#include <wincrypt.h>
|
||||||
|
|
||||||
|
static HCRYPTPROV hProv = 0;
|
||||||
|
|
||||||
|
static void s_cleanup_win_csp(void)
|
||||||
|
{
|
||||||
|
CryptReleaseContext(hProv, 0);
|
||||||
|
hProv = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int s_read_win_csp(mp_digit* p)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
atexit(s_cleanup_win_csp);
|
||||||
|
}
|
||||||
|
if (CryptGenRandom(hProv, sizeof(*p), (void*)p) == TRUE) {
|
||||||
|
ret = MP_OKAY;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* WIN32 */
|
||||||
|
|
||||||
|
#if !defined(MP_WIN_CSP) && defined(__linux__) && defined(__GLIBC_PREREQ)
|
||||||
|
#if __GLIBC_PREREQ(2, 25)
|
||||||
|
#define MP_GETRANDOM
|
||||||
|
#include <sys/random.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
static int s_read_getrandom(mp_digit* p)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
do {
|
||||||
|
ret = getrandom(p, sizeof(*p), 0);
|
||||||
|
} while((ret == -1) && (errno == EINTR));
|
||||||
|
if (ret == sizeof(*p)) return MP_OKAY;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* We assume all platforms besides windows provide "/dev/urandom".
|
||||||
|
* In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time.
|
||||||
|
*/
|
||||||
|
#if !defined(MP_WIN_CSP) && !defined(MP_NO_DEV_URANDOM)
|
||||||
|
#ifndef MP_DEV_URANDOM
|
||||||
|
#define MP_DEV_URANDOM "/dev/urandom"
|
||||||
|
#endif
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
static int s_read_dev_urandom(mp_digit* p)
|
||||||
|
{
|
||||||
|
ssize_t r;
|
||||||
|
int fd;
|
||||||
|
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));
|
||||||
|
close(fd);
|
||||||
|
if (r != sizeof(*p)) return -1;
|
||||||
|
return MP_OKAY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MP_PRNG_ENABLE_LTM_RNG)
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
return MP_OKAY;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int s_rand_digit(mp_digit* p)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
#if defined(MP_ARC4RANDOM)
|
||||||
|
ret = s_read_arc4random(p);
|
||||||
|
if (ret == MP_OKAY) return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(MP_WIN_CSP)
|
||||||
|
ret = s_read_win_csp(p);
|
||||||
|
if (ret == MP_OKAY) return ret;
|
||||||
|
#else
|
||||||
|
|
||||||
|
#if defined(MP_GETRANDOM)
|
||||||
|
ret = s_read_getrandom(p);
|
||||||
|
if (ret == MP_OKAY) return ret;
|
||||||
|
#endif
|
||||||
|
#if defined(MP_DEV_URANDOM)
|
||||||
|
ret = s_read_dev_urandom(p);
|
||||||
|
if (ret == MP_OKAY) return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* MP_WIN_CSP */
|
||||||
|
|
||||||
|
#if defined(MP_PRNG_ENABLE_LTM_RNG)
|
||||||
|
ret = s_read_ltm_rng(p);
|
||||||
|
if (ret == MP_OKAY) return ret;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* makes a pseudo-random int of a given size */
|
||||||
|
static int s_gen_random(mp_digit *r)
|
||||||
|
{
|
||||||
|
int ret = s_rand_digit(r);
|
||||||
|
*r &= MP_MASK;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int mp_rand(mp_int *a, int digits)
|
int mp_rand(mp_int *a, int digits)
|
||||||
@ -55,7 +192,9 @@ int mp_rand(mp_int *a, int digits)
|
|||||||
|
|
||||||
/* first place a random non-zero digit */
|
/* first place a random non-zero digit */
|
||||||
do {
|
do {
|
||||||
d = s_gen_random();
|
if (s_gen_random(&d) != MP_OKAY) {
|
||||||
|
return MP_VAL;
|
||||||
|
}
|
||||||
} while (d == 0u);
|
} while (d == 0u);
|
||||||
|
|
||||||
if ((res = mp_add_d(a, d, a)) != MP_OKAY) {
|
if ((res = mp_add_d(a, d, a)) != MP_OKAY) {
|
||||||
@ -67,7 +206,10 @@ int mp_rand(mp_int *a, int digits)
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((res = mp_add_d(a, s_gen_random(), a)) != MP_OKAY) {
|
if (s_gen_random(&d) != MP_OKAY) {
|
||||||
|
return MP_VAL;
|
||||||
|
}
|
||||||
|
if ((res = mp_add_d(a, d, a)) != MP_OKAY) {
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
20
tommath.h
20
tommath.h
@ -100,18 +100,6 @@ typedef uint_least32_t mp_min_u32;
|
|||||||
typedef mp_digit mp_min_u32;
|
typedef mp_digit mp_min_u32;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* use arc4random on platforms that support it */
|
|
||||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
|
|
||||||
# define MP_GEN_RANDOM() arc4random()
|
|
||||||
# define MP_GEN_RANDOM_MAX 0xffffffffu
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* use rand() as fall-back if there's no better rand function */
|
|
||||||
#ifndef MP_GEN_RANDOM
|
|
||||||
# define MP_GEN_RANDOM() rand()
|
|
||||||
# define MP_GEN_RANDOM_MAX RAND_MAX
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MP_DIGIT_BIT DIGIT_BIT
|
#define MP_DIGIT_BIT DIGIT_BIT
|
||||||
#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
|
#define MP_MASK ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
|
||||||
#define MP_DIGIT_MAX MP_MASK
|
#define MP_DIGIT_MAX MP_MASK
|
||||||
@ -287,6 +275,14 @@ int mp_cnt_lsb(const mp_int *a);
|
|||||||
/* makes a pseudo-random int of a given size */
|
/* makes a pseudo-random int of a given size */
|
||||||
int mp_rand(mp_int *a, int digits);
|
int mp_rand(mp_int *a, int digits);
|
||||||
|
|
||||||
|
#ifdef MP_PRNG_ENABLE_LTM_RNG
|
||||||
|
/* as last resort we will fall back to libtomcrypt's rng_get_bytes()
|
||||||
|
* in case you don't use libtomcrypt or use it w/o rng_get_bytes()
|
||||||
|
* you have to implement it somewhere else, as it's required */
|
||||||
|
extern unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void));
|
||||||
|
extern void (*ltm_rng_callback)(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* ---> binary operations <--- */
|
/* ---> binary operations <--- */
|
||||||
/* c = a XOR b */
|
/* c = a XOR b */
|
||||||
int mp_xor(const mp_int *a, const mp_int *b, mp_int *c);
|
int mp_xor(const mp_int *a, const mp_int *b, mp_int *c);
|
||||||
|
Loading…
Reference in New Issue
Block a user