#include "config.h"
+#include <errno.h>
#include <setjmp.h>
#include <signal.h>
#include <stdio.h>
# include <grp.h>
#endif
+#if defined(HAVE_LINUX_RANDOM_H)
+# include <linux/random.h>
+# include <sys/syscall.h>
+#endif
+
#include <mLib/bits.h>
#include <mLib/mdup.h>
#include <mLib/sel.h>
static int bitcount(unsigned long x)
{
- char ctab[] = { 0, 1, 1, 2, 1, 2, 2, 3,
- 1, 2, 2, 3, 2, 3, 3, 4 };
+ static const char ctab[] = { 0, 1, 1, 2, 1, 2, 2, 3,
+ 1, 2, 2, 3, 2, 3, 3, 4 };
int count = 0;
while (x) {
count += ctab[x & 0xfu];
int noise_devrandom(rand_pool *r)
{
- int fd;
+ int fd = -1;
octet buf[RAND_POOLSZ];
ssize_t len;
size_t n = 0;
int ret = 0;
+#ifdef __linux__
+ fd_set infd;
+ struct timeval tv = { 0, 0 };
+#endif
+#ifdef HAVE_GETENTROPY
+ size_t nn;
+#endif
+
+#if defined(HAVE_LINUX_RANDOM_H) && \
+ defined(GRND_NONBLOCK) && \
+ defined(SYS_getrandom)
+ /* --- Use the new shinies if available --- */
+
+ while (n < sizeof(buf)) {
+ if ((len = syscall(SYS_getrandom, buf + n, sizeof(buf) - n,
+ GRND_NONBLOCK)) <= 0) {
+ if (errno == ENOSYS) break;
+ else goto done;
+ }
+ n += len;
+ }
+ if (n == sizeof(buf)) goto win;
+#endif
+
+#ifdef HAVE_GETENTROPY
+ /* --- OpenBSD-flavoured shinies --- */
+
+ while (n < sizeof(buf)) {
+ nn = sizeof(buf) - nn;
+ if (nn > 256) nn = 256;
+ if (getentropy(buf + n, nn)) break;
+ n += nn;
+ }
+ if (n == sizeof(buf)) goto win;
+#endif
+
+#ifdef __linux__
+ /* --- Don't take from `/dev/urandom' if `/dev/random' would block --- */
+
+ if ((fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) < 0) goto done;
+ FD_ZERO(&infd);
+ FD_SET(fd, &infd);
+ if (select(fd + 1, &infd, 0, 0, &tv) < 0 || !FD_ISSET(fd, &infd))
+ goto done;
+ close(fd); fd = -1;
+#endif
/* --- Be nice to other clients of the random device --- *
*
* needs to get some more entropy from somewhere.
*/
- if ((fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) >= 0 ||
+ if (fd >= 0 ||
+ (fd = open("/dev/urandom", O_RDONLY | O_NONBLOCK)) >= 0 ||
(fd = open("/dev/arandom", O_RDONLY | O_NONBLOCK)) >= 0 ||
(fd = open("/dev/random", O_RDONLY | O_NONBLOCK)) >= 0) {
while (n < sizeof(buf)) {
if ((len = read(fd, buf + n, sizeof(buf) - n)) <= 0) break;
n += len;
}
- rand_add(r, buf, n, n * 8);
- BURN(buf);
- if (n == sizeof(buf)) ret = 1;
- close(fd);
+ if (n == sizeof(buf)) goto win;
}
+ goto done;
+
+win:
+ ret = 1;
+done:
+ if (fd >= 0) close(fd);
+ rand_add(r, buf, n, 8*n);
+ BURN(buf);
noise_timer(r);
return (ret);
}
#ifdef USE_FREEWHEEL
-static jmp_buf fwjmp;
+static sigjmp_buf fwjmp;
static void fwalarm(int sig)
{