diff options
Diffstat (limited to 'contrib/wpa/src/crypto/random.c')
-rw-r--r-- | contrib/wpa/src/crypto/random.c | 77 |
1 files changed, 58 insertions, 19 deletions
diff --git a/contrib/wpa/src/crypto/random.c b/contrib/wpa/src/crypto/random.c index 3a86a93a46a8..1cabf3f4b9a4 100644 --- a/contrib/wpa/src/crypto/random.c +++ b/contrib/wpa/src/crypto/random.c @@ -25,6 +25,9 @@ #include "utils/includes.h" #ifdef __linux__ #include <fcntl.h> +#ifdef CONFIG_GETRANDOM +#include <sys/random.h> +#endif /* CONFIG_GETRANDOM */ #endif /* __linux__ */ #include "utils/common.h" @@ -54,7 +57,6 @@ static int random_fd = -1; static unsigned int own_pool_ready = 0; #define RANDOM_ENTROPY_SIZE 20 static char *random_entropy_file = NULL; -static int random_entropy_file_read = 0; #define MIN_COLLECT_ENTROPY 1000 static unsigned int entropy = 0; @@ -66,6 +68,9 @@ static void random_write_entropy(void); static u32 __ROL32(u32 x, u32 y) { + if (y == 0) + return x; + return (x << (y & 31)) | (x >> (32 - (y & 31))); } @@ -226,30 +231,52 @@ int random_pool_ready(void) return 1; /* Already initialized - good to continue */ /* - * Try to fetch some more data from the kernel high quality - * /dev/random. There may not be enough data available at this point, + * Try to fetch some more data from the kernel high quality RNG. + * There may not be enough data available at this point, * so use non-blocking read to avoid blocking the application * completely. */ - fd = open("/dev/random", O_RDONLY | O_NONBLOCK); - if (fd < 0) { - wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s", - strerror(errno)); - return -1; - } - res = read(fd, dummy_key + dummy_key_avail, - sizeof(dummy_key) - dummy_key_avail); +#ifdef CONFIG_GETRANDOM + res = getrandom(dummy_key + dummy_key_avail, + sizeof(dummy_key) - dummy_key_avail, GRND_NONBLOCK); if (res < 0) { - wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: " - "%s", strerror(errno)); - res = 0; + if (errno == ENOSYS) { + wpa_printf(MSG_DEBUG, + "random: getrandom() not supported, falling back to /dev/random"); + } else { + wpa_printf(MSG_INFO, + "random: no data from getrandom(): %s", + strerror(errno)); + res = 0; + } } - wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from " - "/dev/random", (unsigned) res, +#else /* CONFIG_GETRANDOM */ + res = -1; +#endif /* CONFIG_GETRANDOM */ + if (res < 0) { + fd = open("/dev/random", O_RDONLY | O_NONBLOCK); + if (fd < 0) { + wpa_printf(MSG_ERROR, + "random: Cannot open /dev/random: %s", + strerror(errno)); + return -1; + } + + res = read(fd, dummy_key + dummy_key_avail, + sizeof(dummy_key) - dummy_key_avail); + if (res < 0) { + wpa_printf(MSG_ERROR, + "random: Cannot read from /dev/random: %s", + strerror(errno)); + res = 0; + } + close(fd); + } + + wpa_printf(MSG_DEBUG, "random: Got %u/%u random bytes", (unsigned) res, (unsigned) (sizeof(dummy_key) - dummy_key_avail)); dummy_key_avail += res; - close(fd); if (dummy_key_avail == sizeof(dummy_key)) { if (own_pool_ready < MIN_READY_MARK) @@ -259,7 +286,7 @@ int random_pool_ready(void) } wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong " - "random data available from /dev/random", + "random data available", (unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key)); if (own_pool_ready >= MIN_READY_MARK || @@ -354,7 +381,6 @@ static void random_read_entropy(void) own_pool_ready = (u8) buf[0]; random_add_randomness(buf + 1, RANDOM_ENTROPY_SIZE); - random_entropy_file_read = 1; os_free(buf); wpa_printf(MSG_DEBUG, "random: Added entropy from %s " "(own_pool_ready=%u)", @@ -412,6 +438,19 @@ void random_init(const char *entropy_file) if (random_fd >= 0) return; +#ifdef CONFIG_GETRANDOM + { + u8 dummy; + + if (getrandom(&dummy, 0, GRND_NONBLOCK) == 0 || + errno != ENOSYS) { + wpa_printf(MSG_DEBUG, + "random: getrandom() support available"); + return; + } + } +#endif /* CONFIG_GETRANDOM */ + random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK); if (random_fd < 0) { wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s", |