-/* $OpenBSD: getentropy_osx.c,v 1.2 2014/07/09 13:23:15 bcook Exp $ */
+/* $OpenBSD: getentropy_osx.c,v 1.3 2014/07/12 14:48:00 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
else \
HD(b); \
} while (0)
+
#define HR(x, l) (SHA512_Update(&ctx, (char *)(x), (l)))
#define HD(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (x)))
/* (portability) some compilers cannot take sizeof a function pointer */
#define HF(x) (SHA512_Update(&ctx, (char *)&(x), sizeof (void*)))
+
int getentropy(void *buf, size_t len);
/* cannot reference main, or log_info for unbound, it
* Entropy collection via /dev/urandom and sysctl have failed.
*
* No other API exists for collecting entropy, and we have
- * no failsafe way to get it on OSX that is not sensitive
- * to resource exhaustion.
+ * no failsafe way to get it on OSX that is not sensitive
+ * to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
-#undef FAIL_WHEN_SYSTEM_ENTROPY_FAILS
-#ifdef FAIL_WHEN_SYSTEM_ENTROPY_FAILS
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
start:
- flags = O_RDONLY;
+ flags = O_RDONLY;
#ifdef O_NOFOLLOW
- flags |= O_NOFOLLOW;
+ flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
- flags |= O_CLOEXEC;
+ flags |= O_CLOEXEC;
#endif
fd = open("/dev/urandom", flags, 0);
if (fd == -1) {
return -1;
}
+static int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
+static int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
+static int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
+static int kmib[] = { CTL_KERN, KERN_USRSTACK };
+static int hwmib[] = { CTL_HW, HW_USERMEM };
+
static int
getentropy_fallback(void *buf, size_t len)
{
- int tcpmib[] = { CTL_NET, AF_INET, IPPROTO_TCP, TCPCTL_STATS };
- int udpmib[] = { CTL_NET, AF_INET, IPPROTO_UDP, UDPCTL_STATS };
- int ipmib[] = { CTL_NET, AF_INET, IPPROTO_IP, IPCTL_STATS };
- int kmib[] = { CTL_KERN, KERN_USRSTACK };
- int hwmib[] = { CTL_HW, HW_USERMEM };
- int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
uint8_t results[SHA512_DIGEST_LENGTH];
- struct tcpstat tcpstat;
- struct udpstat udpstat;
- struct ipstat ipstat;
- u_int64_t mach_time;
- unsigned int idata;
+ int save_errno = errno, e, pgs = getpagesize(), faster = 0, repeat;
+ static int cnt;
struct timespec ts;
struct timeval tv;
struct rusage ru;
sigset_t sigset;
struct stat st;
- static int cnt;
SHA512_CTX ctx;
static pid_t lastpid;
- void * addr;
pid_t pid;
- size_t i, m;
+ size_t i, ii, m;
char *p;
+ struct tcpstat tcpstat;
+ struct udpstat udpstat;
+ struct ipstat ipstat;
+ u_int64_t mach_time;
+ unsigned int idata;
+ void * addr;
pid = getpid();
if (lastpid == pid) {
int j;
SHA512_Init(&ctx);
for (j = 0; j < repeat; j++) {
- size_t len;
HX((e = gettimeofday(&tv, NULL)) == -1, tv);
if (e != -1) {
cnt += (int)tv.tv_sec;
cnt += (int)tv.tv_usec;
}
- mach_time = mach_absolute_time();
- HD(mach_time);
+ mach_time = mach_absolute_time();
+ HD(mach_time);
- len = sizeof(addr);
+ ii = sizeof(addr);
HX(sysctl(kmib, sizeof(kmib) / sizeof(kmib[0]),
- &addr, &len, NULL, 0) == -1, addr);
+ &addr, &ii, NULL, 0) == -1, addr);
- len = sizeof(idata);
+ ii = sizeof(idata);
HX(sysctl(hwmib, sizeof(hwmib) / sizeof(hwmib[0]),
- &idata, &len, NULL, 0) == -1, idata);
+ &idata, &ii, NULL, 0) == -1, idata);
- len = sizeof(tcpstat);
+ ii = sizeof(tcpstat);
HX(sysctl(tcpmib, sizeof(tcpmib) / sizeof(tcpmib[0]),
- &tcpstat, &len, NULL, 0) == -1, tcpstat);
+ &tcpstat, &ii, NULL, 0) == -1, tcpstat);
- len = sizeof(udpstat);
+ ii = sizeof(udpstat);
HX(sysctl(udpmib, sizeof(udpmib) / sizeof(udpmib[0]),
- &udpstat, &len, NULL, 0) == -1, udpstat);
+ &udpstat, &ii, NULL, 0) == -1, udpstat);
- len = sizeof(ipstat);
+ ii = sizeof(ipstat);
HX(sysctl(ipmib, sizeof(ipmib) / sizeof(ipmib[0]),
- &ipstat, &len, NULL, 0) == -1, ipstat);
+ &ipstat, &ii, NULL, 0) == -1, ipstat);
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
}
/* Check cnts and times... */
- mach_time = mach_absolute_time();
- HD(mach_time);
- cnt += (int)mach_time;
+ mach_time = mach_absolute_time();
+ HD(mach_time);
+ cnt += (int)mach_time;
HX((e = getrusage(RUSAGE_SELF,
&ru)) == -1, ru);
HD(cnt);
}
-
SHA512_Final(results, &ctx);
memcpy(buf + i, results, min(sizeof(results), len - i));
i += min(sizeof(results), len - i);
-/* $OpenBSD: getentropy_solaris.c,v 1.1 2014/07/08 10:45:35 beck Exp $ */
+/* $OpenBSD: getentropy_solaris.c,v 1.3 2014/07/12 14:46:31 deraadt Exp $ */
/*
* Copyright (c) 2014 Theo de Raadt <deraadt@openbsd.org>
#define SHA512_Update SHA512Update
#define SHA512_Final SHA512Final
-
#include <sys/vfs.h>
#include <sys/statfs.h>
#include <sys/loadavg.h>
have different link semantics (but it also fails on other platforms) */
/* extern int main(int, char *argv[]); */
static int gotdata(char *buf, size_t len);
-static int getentropy_urandom(void *buf, size_t len);
+static int getentropy_urandom(void *buf, size_t len, const char *path,
+ int devfscheck);
static int getentropy_fallback(void *buf, size_t len);
int
/*
* Try to get entropy with /dev/urandom
*
+ * Solaris provides /dev/urandom as a symbolic link to
+ * /devices/pseudo/random@0:urandom which is provided by
+ * a devfs filesystem. Best practice is to use O_NOFOLLOW,
+ * so we must try the unpublished name directly.
+ *
+ * This can fail if the process is inside a chroot which lacks
+ * the devfs mount, or if file descriptors are exhausted.
+ */
+ ret = getentropy_urandom(buf, len,
+ "/devices/pseudo/random@0:urandom", 1);
+ if (ret != -1)
+ return (ret);
+
+ /*
+ * Unfortunately, chroot spaces on Solaris are sometimes setup
+ * with direct device node of the well-known /dev/urandom name
+ * (perhaps to avoid dragging all of devfs into the space).
+ *
* This can fail if the process is inside a chroot or if file
* descriptors are exhausted.
*/
- ret = getentropy_urandom(buf, len);
+ ret = getentropy_urandom(buf, len, "/dev/urandom", 0);
if (ret != -1)
return (ret);
+
/*
- * Entropy collection via /dev/urandom and sysctl have failed.
+ * Entropy collection via /dev/urandom has failed.
*
* No other API exists for collecting entropy, and we have
- * no failsafe way to get it on Solaris that is not sensitive
- * to resource exhaustion.
+ * no failsafe way to get it on Solaris that is not sensitive
+ * to resource exhaustion.
*
* We have very few options:
* - Even syslog_r is unsafe to call at this low level, so
* providing a new failsafe API which works in a chroot or
* when file descriptors are exhausted.
*/
-#undef FAIL_WHEN_SYSTEM_ENTROPY_FAILS
-#ifdef FAIL_WHEN_SYSTEM_ENTROPY_FAILS
+#undef FAIL_INSTEAD_OF_TRYING_FALLBACK
+#ifdef FAIL_INSTEAD_OF_TRYING_FALLBACK
raise(SIGKILL);
#endif
ret = getentropy_fallback(buf, len);
}
static int
-getentropy_urandom(void *buf, size_t len)
+getentropy_urandom(void *buf, size_t len, const char *path, int devfscheck)
{
struct stat st;
size_t i;
start:
- flags = O_RDONLY;
+ flags = O_RDONLY;
#ifdef O_NOFOLLOW
- flags |= O_NOFOLLOW;
+ flags |= O_NOFOLLOW;
#endif
#ifdef O_CLOEXEC
- flags |= O_CLOEXEC;
+ flags |= O_CLOEXEC;
#endif
- /*
- * Solaris provides /dev/urandom as a symbolic link.
- * /devices/pseudo/random@0:urandom should be the
- * real device path, and we do want O_NOFOLLOW.
- */
- fd = open("/devices/pseudo/random@0:urandom", flags, 0);
+ fd = open(path, flags, 0);
if (fd == -1) {
if (errno == EINTR)
goto start;
#endif
/* Lightly verify that the device node looks sane */
- if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode)) {
+ if (fstat(fd, &st) == -1 || !S_ISCHR(st.st_mode) ||
+ (devfscheck && (strcmp(st.st_fstype, "devfs") != 0))) {
close(fd);
goto nodevrandom;
}
return -1;
}
-static int cl[] = {
+static const int cl[] = {
CLOCK_REALTIME,
#ifdef CLOCK_MONOTONIC
CLOCK_MONOTONIC,
for (ii = 0; ii < sizeof(cl)/sizeof(cl[0]); ii++)
HX(clock_gettime(cl[ii], &ts) == -1, ts);
+
HX((pid = getpid()) == -1, pid);
HX((pid = getsid(pid)) == -1, pid);
HX((pid = getppid()) == -1, pid);