diff options
Diffstat (limited to 'crypto/openssh/openbsd-compat/arc4random.c')
-rw-r--r-- | crypto/openssh/openbsd-compat/arc4random.c | 36 |
1 files changed, 35 insertions, 1 deletions
diff --git a/crypto/openssh/openbsd-compat/arc4random.c b/crypto/openssh/openbsd-compat/arc4random.c index 09dbfda..046f57e 100644 --- a/crypto/openssh/openbsd-compat/arc4random.c +++ b/crypto/openssh/openbsd-compat/arc4random.c @@ -26,15 +26,19 @@ #include "includes.h" +#include <sys/types.h> + +#include <fcntl.h> #include <stdlib.h> #include <string.h> #include <unistd.h> -#include <sys/types.h> #ifndef HAVE_ARC4RANDOM +#ifdef WITH_OPENSSL #include <openssl/rand.h> #include <openssl/err.h> +#endif #include "log.h" @@ -73,14 +77,44 @@ _rs_init(u_char *buf, size_t n) chacha_ivsetup(&rs, buf + KEYSZ); } +#ifndef WITH_OPENSSL +#define SSH_RANDOM_DEV "/dev/urandom" +/* XXX use getrandom() if supported on Linux */ +static void +getrnd(u_char *s, size_t len) +{ + int fd; + ssize_t r; + size_t o = 0; + + if ((fd = open(SSH_RANDOM_DEV, O_RDONLY)) == -1) + fatal("Couldn't open %s: %s", SSH_RANDOM_DEV, strerror(errno)); + while (o < len) { + r = read(fd, s + o, len - o); + if (r < 0) { + if (errno == EAGAIN || errno == EINTR || + errno == EWOULDBLOCK) + continue; + fatal("read %s: %s", SSH_RANDOM_DEV, strerror(errno)); + } + o += r; + } + close(fd); +} +#endif + static void _rs_stir(void) { u_char rnd[KEYSZ + IVSZ]; +#ifdef WITH_OPENSSL if (RAND_bytes(rnd, sizeof(rnd)) <= 0) fatal("Couldn't obtain random bytes (error %ld)", ERR_get_error()); +#else + getrnd(rnd, sizeof(rnd)); +#endif if (!rs_initialized) { rs_initialized = 1; |