1
/* LibTomCrypt, modular cryptographic library -- Tom St Denis
3
* LibTomCrypt is a library that provides various cryptographic
4
* algorithms in a highly modular and flexible manner.
6
* The library is free for all purposes without any express
9
* Tom St Denis, tomstdenis@iahu.ca, http://libtomcrypt.org
11
/* portable way to get secure random bits to feed a PRNG */
15
/* on *NIX read /dev/random */
16
static unsigned long rng_nix(unsigned char *buf, unsigned long len,
17
void (*callback)(void))
24
#ifdef TRY_URANDOM_FIRST
25
f = fopen("/dev/urandom", "rb");
27
#endif /* TRY_URANDOM_FIRST */
28
f = fopen("/dev/random", "rb");
34
/* disable buffering */
35
if (setvbuf(f, NULL, _IONBF, 0) != 0) {
40
x = (unsigned long)fread(buf, 1, (size_t)len, f);
46
#endif /* DEVRANDOM */
48
/* on ANSI C platforms with 100 < CLOCKS_PER_SEC < 10000 */
49
#if defined(CLOCKS_PER_SEC)
53
static unsigned long rng_ansic(unsigned char *buf, unsigned long len,
54
void (*callback)(void))
57
int l, acc, bits, a, b;
59
if (XCLOCKS_PER_SEC < 100 || XCLOCKS_PER_SEC > 10000) {
67
if (callback != NULL) callback();
70
t1 = XCLOCK(); while (t1 == XCLOCK()) a ^= 1;
71
t1 = XCLOCK(); while (t1 == XCLOCK()) b ^= 1;
79
acc = bits = a = b = 0;
85
/* Try the Microsoft CSP */
87
#define _WIN32_WINNT 0x0400
91
static unsigned long rng_win32(unsigned char *buf, unsigned long len,
92
void (*callback)(void))
95
if (!CryptAcquireContext(&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
96
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET)) &&
97
!CryptAcquireContext (&hProv, NULL, MS_DEF_PROV, PROV_RSA_FULL,
98
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET))
101
if (CryptGenRandom(hProv, len, buf) == TRUE) {
102
CryptReleaseContext(hProv, 0);
105
CryptReleaseContext(hProv, 0);
112
unsigned long rng_get_bytes(unsigned char *buf, unsigned long len,
113
void (*callback)(void))
117
_ARGCHK(buf != NULL);
119
#if defined(DEVRANDOM)
120
x = rng_nix(buf, len, callback); if (x != 0) { return x; }
123
x = rng_win32(buf, len, callback); if (x != 0) { return x; }
126
x = rng_ansic(buf, len, callback); if (x != 0) { return x; }