diff options
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/posix/posix_rand.c | 88 | ||||
| -rw-r--r-- | src/platform/posix/posix_rand_arc4random.c | 24 | ||||
| -rw-r--r-- | src/platform/posix/posix_rand_getrandom.c | 40 | ||||
| -rw-r--r-- | src/platform/posix/posix_rand_urandom.c | 58 | ||||
| -rw-r--r-- | src/platform/windows/win_rand.c | 28 |
5 files changed, 137 insertions, 101 deletions
diff --git a/src/platform/posix/posix_rand.c b/src/platform/posix/posix_rand.c deleted file mode 100644 index 2b704e2f..00000000 --- a/src/platform/posix/posix_rand.c +++ /dev/null @@ -1,88 +0,0 @@ -// -// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> -// Copyright 2018 Capitar IT Group BV <info@capitar.com> -// -// 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 NNG_PLATFORM_POSIX - -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <string.h> -#include <sys/types.h> -#include <sys/utsname.h> -#include <time.h> -#include <unistd.h> - -#if defined(NNG_USE_GETRANDOM) -#include <linux/random.h> -#elif defined(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; - size_t i; - - memset(buf, 0, bufsz); - -#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, bufsz); - (void) close(fd); - } -#endif - - // As a special 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. - memset(&x, 0, sizeof(x)); // satisfy valgrind - 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 // NNG_PLATFORM_POSIX diff --git a/src/platform/posix/posix_rand_arc4random.c b/src/platform/posix/posix_rand_arc4random.c new file mode 100644 index 00000000..a3cc265b --- /dev/null +++ b/src/platform/posix/posix_rand_arc4random.c @@ -0,0 +1,24 @@ +// +// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> +// +// 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. +// + +// arc4random is the preferred source of cryptographic random numbers +// on any platform where it is found. +#include <stdlib.h> + +#include "core/nng_impl.h" + +#ifdef NNG_HAVE_ARC4RANDOM + +uint32_t +nni_random(void) +{ + return (arc4random()); +} + +#endif
\ No newline at end of file diff --git a/src/platform/posix/posix_rand_getrandom.c b/src/platform/posix/posix_rand_getrandom.c new file mode 100644 index 00000000..489b2c76 --- /dev/null +++ b/src/platform/posix/posix_rand_getrandom.c @@ -0,0 +1,40 @@ +// +// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> +// +// 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. +// + +// getrandom is not as nice as arc4random, but on platforms where it +// exists and arc4random does not, we should use it. +// +// getrandom will block only if the urandom device is not seeded yet. +// That can only happen during very early boot (earlier than we should +// normally be running. This is the only time it can fail with correct +// arguments, and then only if it is interrupted with a signal. + +#include <sys/random.h> + +#include "core/nng_impl.h" + +#ifdef NNG_HAVE_GETRANDOM + +uint32_t +nni_random(void) +{ + uint32_t val; + + // Documentation claims that as long as we are not using + // GRND_RANDOM and buflen < 256, this should never fail. + // The exception here is that we could fail if for some + // reason we got a signal while blocked at very early boot + // (i.e. /dev/urandom was not yet seeded). + if (getrandom(&val, sizeof(val), 0) != sizeof(val)) { + nni_panic("getrandom failed"); + } + return (val); +} + +#endif
\ No newline at end of file diff --git a/src/platform/posix/posix_rand_urandom.c b/src/platform/posix/posix_rand_urandom.c new file mode 100644 index 00000000..32ea6a51 --- /dev/null +++ b/src/platform/posix/posix_rand_urandom.c @@ -0,0 +1,58 @@ +// +// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> +// +// 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. +// + +#include <fcntl.h> +#include <pthread.h> +#include <stdint.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +#include "core/nng_impl.h" + +// 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. Modern advice is to always use /dev/urandom +// unless you have very particular reasons for doing otherwise. +// If you're in this code base, you're probably on either an ancient OS, +// or one of the off-beat ones that hasn't updated for support with +// arc4random or getrandom. + +// We could use ISAAC or something like that to seed it only once, +// but instead we just keep our file descriptor open. This will have +// the apparent effect of leaking these file descriptors across fork. + +static int urandom_fd = -1; +static pthread_mutex_t urandom_lock = PTHREAD_MUTEX_INITIALIZER; + +#ifndef O_CLOEXEC +#define O_CLOEXEC 0u +#endif + +uint32_t +nni_random(void) +{ + int fd; + uint32_t val; + + (void) pthread_mutex_lock(&urandom_lock); + if ((fd = urandom_fd) == -1) { + if ((fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC)) < 0) { + (void) pthread_mutex_unlock(&urandom_lock); + nni_panic("failed to open /dev/urandom"); + } + urandom_fd = fd; + } + (void) pthread_mutex_unlock(&urandom_lock); + + if (read(fd, &val, sizeof(val)) != sizeof(val)) { + nni_panic("failed reading /dev/urandom"); + } + return (val); +}
\ No newline at end of file diff --git a/src/platform/windows/win_rand.c b/src/platform/windows/win_rand.c index afe703ef..21568a81 100644 --- a/src/platform/windows/win_rand.c +++ b/src/platform/windows/win_rand.c @@ -1,5 +1,5 @@ // -// Copyright 2017 Garrett D'Amore <garrett@damore.org> +// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> // // This software is supplied under the terms of the MIT License, a // copy of which should be located in the distribution where this @@ -11,22 +11,24 @@ #ifdef NNG_PLATFORM_WINDOWS +#ifndef _CRT_RAND_S +#define _CRT_RAND_S +#endif + #include <stdlib.h> -void -nni_plat_seed_prng(void *buf, size_t bufsz) +uint32_t +nni_random(void) { unsigned val; - // The rand_s routine uses RtlGenRandom to get high quality - // pseudo random numbers (i.e. numbers that should be good enough - // for use with crypto keying.) - while (bufsz > sizeof(val)) { - rand_s(&val); - memcpy(buf, &val, sizeof(val)); - buf = (((char *) buf) + sizeof(val)); - bufsz -= sizeof(val); - } + // rand_s is claimed by Microsoft to generate cryptographically + // secure numbers. It also is claimed that this will only fail + // for EINVAL if val is NULL (not the case here). Other error + // conditions might be possible, but we have no way to tell. + // For now we just ignore that possibility. + rand_s(&val); + return ((uint32_t)val); } -#endif // NNG_PLATFORM_WINDOWS +#endif // NNG_PLATFORM_WINDOWS
\ No newline at end of file |
