1*38a52bd3SEd Maste /* 2*38a52bd3SEd Maste * Copyright (c) 1996, David Mazieres <dm@uun.org> 3*38a52bd3SEd Maste * Copyright (c) 2008, Damien Miller <djm@openbsd.org> 4*38a52bd3SEd Maste * Copyright (c) 2013, Markus Friedl <markus@openbsd.org> 5*38a52bd3SEd Maste * 6*38a52bd3SEd Maste * Permission to use, copy, modify, and distribute this software for any 7*38a52bd3SEd Maste * purpose with or without fee is hereby granted, provided that the above 8*38a52bd3SEd Maste * copyright notice and this permission notice appear in all copies. 9*38a52bd3SEd Maste * 10*38a52bd3SEd Maste * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11*38a52bd3SEd Maste * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12*38a52bd3SEd Maste * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13*38a52bd3SEd Maste * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14*38a52bd3SEd Maste * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15*38a52bd3SEd Maste * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16*38a52bd3SEd Maste * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17*38a52bd3SEd Maste */ 18*38a52bd3SEd Maste 19*38a52bd3SEd Maste #include "includes.h" 20*38a52bd3SEd Maste 21*38a52bd3SEd Maste #ifndef HAVE_GETENTROPY 22*38a52bd3SEd Maste 23*38a52bd3SEd Maste #ifndef SSH_RANDOM_DEV 24*38a52bd3SEd Maste # define SSH_RANDOM_DEV "/dev/urandom" 25*38a52bd3SEd Maste #endif /* SSH_RANDOM_DEV */ 26*38a52bd3SEd Maste 27*38a52bd3SEd Maste #include <sys/types.h> 28*38a52bd3SEd Maste #ifdef HAVE_SYS_RANDOM_H 29*38a52bd3SEd Maste # include <sys/random.h> 30*38a52bd3SEd Maste #endif 31*38a52bd3SEd Maste 32*38a52bd3SEd Maste #include <fcntl.h> 33*38a52bd3SEd Maste #include <stdlib.h> 34*38a52bd3SEd Maste #include <string.h> 35*38a52bd3SEd Maste #include <unistd.h> 36*38a52bd3SEd Maste #ifdef WITH_OPENSSL 37*38a52bd3SEd Maste #include <openssl/rand.h> 38*38a52bd3SEd Maste #include <openssl/err.h> 39*38a52bd3SEd Maste #endif 40*38a52bd3SEd Maste 41*38a52bd3SEd Maste #include "log.h" 42*38a52bd3SEd Maste 43*38a52bd3SEd Maste int 44*38a52bd3SEd Maste _ssh_compat_getentropy(void *s, size_t len) 45*38a52bd3SEd Maste { 46*38a52bd3SEd Maste #ifdef WITH_OPENSSL 47*38a52bd3SEd Maste if (RAND_bytes(s, len) <= 0) 48*38a52bd3SEd Maste fatal("Couldn't obtain random bytes (error 0x%lx)", 49*38a52bd3SEd Maste (unsigned long)ERR_get_error()); 50*38a52bd3SEd Maste #else 51*38a52bd3SEd Maste int fd, save_errno; 52*38a52bd3SEd Maste ssize_t r; 53*38a52bd3SEd Maste size_t o = 0; 54*38a52bd3SEd Maste 55*38a52bd3SEd Maste #ifdef HAVE_GETRANDOM 56*38a52bd3SEd Maste if ((r = getrandom(s, len, 0)) > 0 && (size_t)r == len) 57*38a52bd3SEd Maste return 0; 58*38a52bd3SEd Maste #endif /* HAVE_GETRANDOM */ 59*38a52bd3SEd Maste 60*38a52bd3SEd Maste if ((fd = open(SSH_RANDOM_DEV, O_RDONLY)) == -1) { 61*38a52bd3SEd Maste save_errno = errno; 62*38a52bd3SEd Maste /* Try egd/prngd before giving up. */ 63*38a52bd3SEd Maste if (seed_from_prngd(s, len) == 0) 64*38a52bd3SEd Maste return 0; 65*38a52bd3SEd Maste fatal("Couldn't open %s: %s", SSH_RANDOM_DEV, 66*38a52bd3SEd Maste strerror(save_errno)); 67*38a52bd3SEd Maste } 68*38a52bd3SEd Maste while (o < len) { 69*38a52bd3SEd Maste r = read(fd, (u_char *)s + o, len - o); 70*38a52bd3SEd Maste if (r < 0) { 71*38a52bd3SEd Maste if (errno == EAGAIN || errno == EINTR || 72*38a52bd3SEd Maste errno == EWOULDBLOCK) 73*38a52bd3SEd Maste continue; 74*38a52bd3SEd Maste fatal("read %s: %s", SSH_RANDOM_DEV, strerror(errno)); 75*38a52bd3SEd Maste } 76*38a52bd3SEd Maste o += r; 77*38a52bd3SEd Maste } 78*38a52bd3SEd Maste close(fd); 79*38a52bd3SEd Maste #endif /* WITH_OPENSSL */ 80*38a52bd3SEd Maste return 0; 81*38a52bd3SEd Maste } 82*38a52bd3SEd Maste #endif /* WITH_GETENTROPY */ 83