crypto: Add option to use getrandom()
According to random(4) manual, /dev/random is essentially deprecated on Linux for quite some time: "The /dev/random interface is considered a legacy interface, and /dev/urandom is preferred and sufficient in all use cases, with the exception of applications which require randomness during early boot time; for these applications, getrandom(2) must be used instead, because it will block until the entropy pool is initialized." An attempt to use it would cause unnecessary blocking on machines without a good hwrng even when it shouldn't be needed. Since Linux 3.17, a getrandom(2) call is available that will block only until the randomness pool has been seeded. It is probably not a good default yet as it requires a fairly recent kernel and glibc (3.17 and 2.25 respectively). Signed-off-by: Lubomir Rintel <lkundrak@v3.sk>
This commit is contained in:
parent
2a54979695
commit
89a7cdd690
5 changed files with 72 additions and 18 deletions
|
@ -1101,6 +1101,9 @@ endif
|
||||||
ifdef CONFIG_NO_RANDOM_POOL
|
ifdef CONFIG_NO_RANDOM_POOL
|
||||||
CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
||||||
else
|
else
|
||||||
|
ifdef CONFIG_GETRANDOM
|
||||||
|
CFLAGS += -DCONFIG_GETRANDOM
|
||||||
|
endif
|
||||||
OBJS += ../src/crypto/random.o
|
OBJS += ../src/crypto/random.o
|
||||||
HOBJS += ../src/crypto/random.o
|
HOBJS += ../src/crypto/random.o
|
||||||
HOBJS += ../src/utils/eloop.o
|
HOBJS += ../src/utils/eloop.o
|
||||||
|
|
|
@ -252,6 +252,11 @@ CONFIG_IPV6=y
|
||||||
# requirements described above.
|
# requirements described above.
|
||||||
#CONFIG_NO_RANDOM_POOL=y
|
#CONFIG_NO_RANDOM_POOL=y
|
||||||
|
|
||||||
|
# Should we attempt to use the getrandom(2) call that provides more reliable
|
||||||
|
# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
||||||
|
# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
|
||||||
|
#CONFIG_GETRANDOM=y
|
||||||
|
|
||||||
# Should we use poll instead of select? Select is used by default.
|
# Should we use poll instead of select? Select is used by default.
|
||||||
#CONFIG_ELOOP_POLL=y
|
#CONFIG_ELOOP_POLL=y
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
#include "utils/includes.h"
|
#include "utils/includes.h"
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#ifdef CONFIG_GETRANDOM
|
||||||
|
#include <sys/random.h>
|
||||||
|
#endif /* CONFIG_GETRANDOM */
|
||||||
#endif /* __linux__ */
|
#endif /* __linux__ */
|
||||||
|
|
||||||
#include "utils/common.h"
|
#include "utils/common.h"
|
||||||
|
@ -228,30 +231,52 @@ int random_pool_ready(void)
|
||||||
return 1; /* Already initialized - good to continue */
|
return 1; /* Already initialized - good to continue */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to fetch some more data from the kernel high quality
|
* Try to fetch some more data from the kernel high quality RNG.
|
||||||
* /dev/random. There may not be enough data available at this point,
|
* There may not be enough data available at this point,
|
||||||
* so use non-blocking read to avoid blocking the application
|
* so use non-blocking read to avoid blocking the application
|
||||||
* completely.
|
* completely.
|
||||||
*/
|
*/
|
||||||
fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
|
|
||||||
if (fd < 0) {
|
#ifdef CONFIG_GETRANDOM
|
||||||
wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
|
res = getrandom(dummy_key + dummy_key_avail,
|
||||||
strerror(errno));
|
sizeof(dummy_key) - dummy_key_avail, GRND_NONBLOCK);
|
||||||
return -1;
|
if (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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#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);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = read(fd, dummy_key + dummy_key_avail,
|
wpa_printf(MSG_DEBUG, "random: Got %u/%u random bytes", (unsigned) res,
|
||||||
sizeof(dummy_key) - dummy_key_avail);
|
|
||||||
if (res < 0) {
|
|
||||||
wpa_printf(MSG_ERROR, "random: Cannot read from /dev/random: "
|
|
||||||
"%s", strerror(errno));
|
|
||||||
res = 0;
|
|
||||||
}
|
|
||||||
wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from "
|
|
||||||
"/dev/random", (unsigned) res,
|
|
||||||
(unsigned) (sizeof(dummy_key) - dummy_key_avail));
|
(unsigned) (sizeof(dummy_key) - dummy_key_avail));
|
||||||
dummy_key_avail += res;
|
dummy_key_avail += res;
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if (dummy_key_avail == sizeof(dummy_key)) {
|
if (dummy_key_avail == sizeof(dummy_key)) {
|
||||||
if (own_pool_ready < MIN_READY_MARK)
|
if (own_pool_ready < MIN_READY_MARK)
|
||||||
|
@ -261,7 +286,7 @@ int random_pool_ready(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong "
|
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));
|
(unsigned) dummy_key_avail, (unsigned) sizeof(dummy_key));
|
||||||
|
|
||||||
if (own_pool_ready >= MIN_READY_MARK ||
|
if (own_pool_ready >= MIN_READY_MARK ||
|
||||||
|
@ -413,6 +438,19 @@ void random_init(const char *entropy_file)
|
||||||
if (random_fd >= 0)
|
if (random_fd >= 0)
|
||||||
return;
|
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);
|
random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK);
|
||||||
if (random_fd < 0) {
|
if (random_fd < 0) {
|
||||||
wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
|
wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s",
|
||||||
|
|
|
@ -1532,6 +1532,9 @@ endif
|
||||||
ifdef CONFIG_NO_RANDOM_POOL
|
ifdef CONFIG_NO_RANDOM_POOL
|
||||||
CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
CFLAGS += -DCONFIG_NO_RANDOM_POOL
|
||||||
else
|
else
|
||||||
|
ifdef CONFIG_GETRANDOM
|
||||||
|
CFLAGS += -DCONFIG_GETRANDOM
|
||||||
|
endif
|
||||||
OBJS += ../src/crypto/random.o
|
OBJS += ../src/crypto/random.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
|
|
@ -461,6 +461,11 @@ CONFIG_BACKEND=file
|
||||||
# that meet the requirements described above.
|
# that meet the requirements described above.
|
||||||
#CONFIG_NO_RANDOM_POOL=y
|
#CONFIG_NO_RANDOM_POOL=y
|
||||||
|
|
||||||
|
# Should we attempt to use the getrandom(2) call that provides more reliable
|
||||||
|
# yet secure randomness source than /dev/random on Linux 3.17 and newer.
|
||||||
|
# Requires glibc 2.25 to build, falls back to /dev/random if unavailable.
|
||||||
|
#CONFIG_GETRANDOM=y
|
||||||
|
|
||||||
# IEEE 802.11n (High Throughput) support (mainly for AP mode)
|
# IEEE 802.11n (High Throughput) support (mainly for AP mode)
|
||||||
#CONFIG_IEEE80211N=y
|
#CONFIG_IEEE80211N=y
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue