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
);