3
* Acquire randomness from system. For seeding RNG.
5
* Copyright (c) 2001 Marko Kreen
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36
/* how many bytes to ask from system random provider */
40
* Try to read from /dev/urandom or /dev/random on these OS'es.
42
* The list can be pretty liberal, as the device not existing
45
#if defined(__linux__) || defined(__FreeBSD__) || defined(__OpenBSD__) \
46
|| defined(__NetBSD__) || defined(__DragonFly__) \
47
|| defined(__darwin__) || defined(__SOLARIS__) \
48
|| defined(__hpux) || defined(__HPUX__) \
49
|| defined(__CYGWIN__) || defined(_AIX)
51
#define TRY_DEV_RANDOM
57
safe_read(int fd, void *buf, size_t count)
65
res = read(fd, p, count);
70
return PXE_DEV_READ_ERROR;
80
try_dev_random(uint8 *dst)
85
fd = open("/dev/urandom", O_RDONLY, 0);
88
fd = open("/dev/random", O_RDONLY, 0);
92
res = safe_read(fd, dst, RND_BYTES);
101
* Try to find randomness on Windows
105
#define TRY_WIN32_GENRAND
106
#define TRY_WIN32_PERFC
109
#include <wincrypt.h>
112
* this function is from libtomcrypt
114
* try to use Microsoft crypto API
117
try_win32_genrand(uint8 *dst)
122
res = CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
123
(CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET));
125
res = CryptAcquireContext(&h, NULL, MS_DEF_PROV, PROV_RSA_FULL,
126
CRYPT_VERIFYCONTEXT | CRYPT_MACHINE_KEYSET | CRYPT_NEWKEYSET);
130
res = CryptGenRandom(h, RND_BYTES, dst);
134
CryptReleaseContext(h, 0);
139
try_win32_perfc(uint8 *dst)
144
res = QueryPerformanceCounter(&time);
148
memcpy(dst, &time, sizeof(time));
149
return dst + sizeof(time);
155
* If we are not on Windows, then hopefully we are
156
* on a unix-like system. Use the usual suspects
163
#include <sys/types.h>
164
#include <sys/time.h>
169
* Everything here is predictible, only needs some patience.
171
* But there is a chance that the system-specific functions
172
* did not work. So keep faith and try to slow the attacker down.
175
try_unix_std(uint8 *dst)
185
memcpy(dst, (uint8 *) &pid, sizeof(pid));
189
gettimeofday(&tv, NULL);
190
memcpy(dst, (uint8 *) &tv, sizeof(tv));
193
/* pointless, but should not hurt */
195
memcpy(dst, (uint8 *) &x, sizeof(x));
198
/* let's be desperate */
199
res = px_find_digest("sha1", &md);
204
int alloc = 32 * 1024;
206
px_md_update(md, stack, sizeof(stack));
207
ptr = px_alloc(alloc);
208
px_md_update(md, ptr, alloc);
211
px_md_finish(md, dst);
222
* try to extract some randomness for initial seeding
224
* dst should have room for 1024 bytes.
227
px_acquire_system_randomness(uint8 *dst)
231
#ifdef TRY_DEV_RANDOM
232
p = try_dev_random(p);
234
#ifdef TRY_WIN32_GENRAND
235
p = try_win32_genrand(p);
237
#ifdef TRY_WIN32_PERFC
238
p = try_win32_perfc(p);