aboutsummaryrefslogtreecommitdiff
path: root/src/platform/posix/posix_rand.c
diff options
context:
space:
mode:
authorGarrett D'Amore <garrett@damore.org>2017-01-08 15:28:37 -0800
committerGarrett D'Amore <garrett@damore.org>2017-01-08 17:33:05 -0800
commitc5b5bd910507520f7974a156a1de9d187f23bc2f (patch)
tree9766716c795d88fe902c7196696c1389d76717ba /src/platform/posix/posix_rand.c
parent4b166dd8ae417b818a5ba214d8f2e648ac1d5be9 (diff)
downloadnng-c5b5bd910507520f7974a156a1de9d187f23bc2f.tar.gz
nng-c5b5bd910507520f7974a156a1de9d187f23bc2f.tar.bz2
nng-c5b5bd910507520f7974a156a1de9d187f23bc2f.zip
New ISAAC pRNG. This replaces other local hacks for random data.
Platforms must seed the pRNGs by offering an nni_plat_seed_prng() routine. Implementations for POSIX using various options (including the /dev/urandom device) are supplied.
Diffstat (limited to 'src/platform/posix/posix_rand.c')
-rw-r--r--src/platform/posix/posix_rand.c86
1 files changed, 86 insertions, 0 deletions
diff --git a/src/platform/posix/posix_rand.c b/src/platform/posix/posix_rand.c
new file mode 100644
index 00000000..65d1c031
--- /dev/null
+++ b/src/platform/posix/posix_rand.c
@@ -0,0 +1,86 @@
+//
+// Copyright 2017 Garrett D'Amore <garrett@damore.org>
+//
+// This software is supplied under the terms of the MIT License, a
+// copy of which should be located in the distribution where this
+// file was obtained (LICENSE.txt). A copy of the license may also be
+// found online at https://opensource.org/licenses/MIT.
+//
+
+// POSIX clock stuff.
+#include "core/nng_impl.h"
+
+#ifdef PLATFORM_POSIX_RANDOM
+
+#include <time.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <sys/utsname.h>
+#include <fcntl.h>
+
+#ifdef NNG_USE_GETRANDOM
+#include <linux/random.h>
+#endif
+
+#ifdef NNG_USE_GETENTROPY
+#include <sys/random.h>
+#endif
+
+// This structure represents the very barest minimum that we can use as
+// a source of entropy. We mix these into our initial entropy, but really
+// really really you want to have more data than this available, especially
+// for cryptographic applications.
+struct nni_plat_prng_x {
+ nni_time now;
+ pid_t pid;
+ uid_t uid;
+ struct utsname uts;
+};
+
+void
+nni_plat_seed_prng(void *buf, size_t bufsz)
+{
+ struct nni_plat_prng_x x;
+ int i;
+
+#if defined(NNG_USE_GETRANDOM)
+ // Latest Linux has a nice API here.
+ (void) getrandom(buf, bufsz, 0);
+#elif defined(NNG_USE_GETENTROPY)
+ // Modern BSD systems prefer this, but can only generate 256 bytes
+ (void) getentropy(buf, bufsz > 256 ? 256 : 0);
+#elif defined(NNG_USE_ARC4RANDOM)
+ // This uses BSD style pRNG seeded from the kernel in libc.
+ (void) arc4random_buf(buf, bufsz);
+#elif defined(NNG_USE_DEVURANDOM)
+ // The historic /dev/urandom device. This is not as a good as
+ // a system call, since file descriptor attacks are possible,
+ // and it may need special permissions. We choose /dev/urandom
+ // over /dev/random to avoid diminishing the system entropy.
+ int fd;
+
+ if ((fd = open("/dev/urandom", O_RDONLY)) >= 0) {
+ (void) read(fd, buf, buffz);
+ (void) close(fd);
+ }
+#endif
+
+ // As a speical extra guard, let's mixin the data from the
+ // following system calls. This ensures that even on the most
+ // limited of systems, we have at least *some* level of randomness.
+ // The mixing is done in a way to avoid diminishing entropy we may
+ // have already collected.
+ x.now = nni_clock();
+ x.pid = getpid();
+ x.uid = getuid();
+ uname(&x.uts);
+
+ for (i = 0; (i < bufsz) && (i < sizeof (x)); i++) {
+ ((uint8_t *) buf)[i] ^= ((uint8_t *) &x)[i];
+ }
+}
+
+
+#endif // PLATFORM_POSIX_RANDOM