commit
						71c5c8ac4b
					
				
							
								
								
									
										186
									
								
								bn_mp_rand.c
									
									
									
									
									
								
							
							
						
						
									
										186
									
								
								bn_mp_rand.c
									
									
									
									
									
								
							@ -13,34 +13,171 @@
 | 
			
		||||
 * guarantee it works.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#if defined(MP_8BIT) || defined(MP_16BIT)
 | 
			
		||||
#define MP_GEN_RANDOM_SHIFT  DIGIT_BIT
 | 
			
		||||
#else
 | 
			
		||||
#if MP_GEN_RANDOM_MAX == 0xffffffffu
 | 
			
		||||
#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
 | 
			
		||||
/* First the OS-specific special cases
 | 
			
		||||
 * - *BSD
 | 
			
		||||
 * - 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
 | 
			
		||||
 | 
			
		||||
/* makes a pseudo-random int of a given size */
 | 
			
		||||
static mp_digit s_gen_random(void)
 | 
			
		||||
static int s_read_arc4random(mp_digit* p)
 | 
			
		||||
{
 | 
			
		||||
   mp_digit d = 0, msk = 0;
 | 
			
		||||
   do {
 | 
			
		||||
      d <<= MP_GEN_RANDOM_SHIFT;
 | 
			
		||||
      d |= ((mp_digit) MP_GEN_RANDOM());
 | 
			
		||||
      d |= ((mp_digit) arc4random());
 | 
			
		||||
      msk <<= MP_GEN_RANDOM_SHIFT;
 | 
			
		||||
      msk |= (MP_MASK & MP_GEN_RANDOM_MAX);
 | 
			
		||||
   } while ((MP_MASK & msk) != MP_MASK);
 | 
			
		||||
   d &= MP_MASK;
 | 
			
		||||
   return d;
 | 
			
		||||
   *p = 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)
 | 
			
		||||
@ -55,7 +192,9 @@ int mp_rand(mp_int *a, int digits)
 | 
			
		||||
 | 
			
		||||
   /* first place a random non-zero digit */
 | 
			
		||||
   do {
 | 
			
		||||
      d = s_gen_random();
 | 
			
		||||
      if (s_gen_random(&d) != MP_OKAY) {
 | 
			
		||||
         return MP_VAL;
 | 
			
		||||
      }
 | 
			
		||||
   } while (d == 0u);
 | 
			
		||||
 | 
			
		||||
   if ((res = mp_add_d(a, d, a)) != MP_OKAY) {
 | 
			
		||||
@ -67,7 +206,10 @@ int mp_rand(mp_int *a, int digits)
 | 
			
		||||
         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;
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								tommath.h
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								tommath.h
									
									
									
									
									
								
							@ -100,18 +100,6 @@ typedef uint_least32_t mp_min_u32;
 | 
			
		||||
typedef mp_digit mp_min_u32;
 | 
			
		||||
#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_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
 | 
			
		||||
#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 */
 | 
			
		||||
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 <--- */
 | 
			
		||||
/* c = a XOR b  */
 | 
			
		||||
int mp_xor(const mp_int *a, const mp_int *b, mp_int *c);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user