1 #include "tommath_private.h"
2 #ifdef BN_S_MP_RAND_PLATFORM_C
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4 /* SPDX-License-Identifier: Unlicense */
6 /* First the OS-specific special cases
10 #if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
11 #define BN_S_READ_ARC4RANDOM_C
12 static mp_err s_read_arc4random(void *p, size_t n)
19 #if defined(_WIN32) || defined(_WIN32_WCE)
20 #define BN_S_READ_WINCSP_C
23 #define _WIN32_WINNT 0x0400
30 #define WIN32_LEAN_AND_MEAN
34 static mp_err s_read_wincsp(void *p, size_t n)
36 static HCRYPTPROV hProv = 0;
39 if (!CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
40 (CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
41 !CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
42 CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET)) {
47 return CryptGenRandom(hProv, (DWORD)n, (BYTE *)p) == TRUE ? MP_OKAY : MP_ERR;
51 #if !defined(BN_S_READ_WINCSP_C) && defined(__linux__) && defined(__GLIBC_PREREQ)
52 #if __GLIBC_PREREQ(2, 25)
53 #define BN_S_READ_GETRANDOM_C
54 #include <sys/random.h>
57 static mp_err s_read_getrandom(void *p, size_t n)
61 ssize_t ret = getrandom(q, n, 0);
76 /* We assume all platforms besides windows provide "/dev/urandom".
77 * In case yours doesn't, define MP_NO_DEV_URANDOM at compile-time.
79 #if !defined(BN_S_READ_WINCSP_C) && !defined(MP_NO_DEV_URANDOM)
80 #define BN_S_READ_URANDOM_C
81 #ifndef MP_DEV_URANDOM
82 #define MP_DEV_URANDOM "/dev/urandom"
88 static mp_err s_read_urandom(void *p, size_t n)
94 fd = open(MP_DEV_URANDOM, O_RDONLY);
95 } while ((fd == -1) && (errno == EINTR));
96 if (fd == -1) return MP_ERR;
99 ssize_t ret = read(fd, p, n);
101 if (errno == EINTR) {
116 #if defined(MP_PRNG_ENABLE_LTM_RNG)
117 #define BN_S_READ_LTM_RNG
118 unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void));
119 void (*ltm_rng_callback)(void);
121 static mp_err s_read_ltm_rng(void *p, size_t n)
124 if (ltm_rng == NULL) return MP_ERR;
125 res = ltm_rng(p, n, ltm_rng_callback);
126 if (res != n) return MP_ERR;
131 #ifdef BN_S_READ_ARC4RANDOM_C
132 mp_err s_read_arc4random(void *p, size_t n);
134 #ifdef BN_S_READ_WINCSP_C
135 mp_err s_read_wincsp(void *p, size_t n);
137 #ifdef BN_S_READ_GETRANDOM_C
138 mp_err s_read_getrandom(void *p, size_t n);
140 #ifdef BN_S_READ_URANDOM_C
141 mp_err s_read_urandom(void *p, size_t n);
143 #ifdef BN_S_READ_LTM_RNG
144 mp_err s_read_ltm_rng(void *p, size_t n);
147 mp_err s_mp_rand_platform(void *p, size_t n)
150 #ifdef BN_S_READ_ARC4RANDOM_C
151 if ((err != MP_OKAY) && MP_HAS(S_READ_ARC4RANDOM)) err = s_read_arc4random(p, n);
153 #ifdef BN_S_READ_WINCSP_C
154 if ((err != MP_OKAY) && MP_HAS(S_READ_WINCSP)) err = s_read_wincsp(p, n);
156 #ifdef BN_S_READ_GETRANDOM_C
157 if ((err != MP_OKAY) && MP_HAS(S_READ_GETRANDOM)) err = s_read_getrandom(p, n);
159 #ifdef BN_S_READ_URANDOM_C
160 if ((err != MP_OKAY) && MP_HAS(S_READ_URANDOM)) err = s_read_urandom(p, n);
162 #ifdef BN_S_READ_LTM_RNG
163 if ((err != MP_OKAY) && MP_HAS(S_READ_LTM_RNG)) err = s_read_ltm_rng(p, n);