aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJouni Malinen <jouni.malinen@atheros.com>2011-05-31 17:07:11 (GMT)
committerJouni Malinen <j@w1.fi>2011-05-31 17:07:11 (GMT)
commit38e24575c18b02a2f8bf7ea38b937ad010682872 (patch)
tree46df39222d7603aa5d9c14fea6fe05d8a9c6487a
parentceb34f250af7a7082f18c1e0451dc7fbc0f000f3 (diff)
downloadhostap-38e24575c18b02a2f8bf7ea38b937ad010682872.zip
hostap-38e24575c18b02a2f8bf7ea38b937ad010682872.tar.gz
hostap-38e24575c18b02a2f8bf7ea38b937ad010682872.tar.bz2
random: Add support for maintaining internal entropy store over restarts
This can be used to avoid rejection of first two 4-way handshakes every time hostapd (or wpa_supplicant in AP/IBSS mode) is restarted. A new command line parameter, -e, can now be used to specify an entropy file that will be used to maintain the needed state.
-rw-r--r--hostapd/defconfig10
-rw-r--r--hostapd/main.c16
-rw-r--r--src/crypto/random.c91
-rw-r--r--src/crypto/random.h4
-rw-r--r--wpa_supplicant/defconfig10
-rw-r--r--wpa_supplicant/main.c11
-rw-r--r--wpa_supplicant/wpa_supplicant.c2
-rw-r--r--wpa_supplicant/wpa_supplicant_i.h8
8 files changed, 134 insertions, 18 deletions
diff --git a/hostapd/defconfig b/hostapd/defconfig
index 38d3284..26be2a8 100644
--- a/hostapd/defconfig
+++ b/hostapd/defconfig
@@ -193,9 +193,15 @@ CONFIG_IPV6=y
# it may help in cases where the system pool is not initialized properly.
# However, it is very strongly recommended that the system pool is initialized
# with enough entropy either by using hardware assisted random number
-# generatior or by storing state over device reboots.
+# generator or by storing state over device reboots.
#
-# If the os_get_random() is known to provide strong ramdom data (e.g., on
+# hostapd can be configured to maintain its own entropy store over restarts to
+# enhance random number generation. This is not perfect, but it is much more
+# secure than using the same sequence of random numbers after every reboot.
+# This can be enabled with -e<entropy file> command line option. The specified
+# file needs to be readable and writable by hostapd.
+#
+# If the os_get_random() is known to provide strong random data (e.g., on
# Linux/BSD, the board in question is known to have reliable source of random
# data from /dev/urandom), the internal hostapd random pool can be disabled.
# This will save some in binary size and CPU use. However, this should only be
diff --git a/hostapd/main.c b/hostapd/main.c
index 7a4cfb0..01ad826 100644
--- a/hostapd/main.c
+++ b/hostapd/main.c
@@ -369,7 +369,8 @@ static void handle_dump_state(int sig, void *signal_ctx)
#endif /* CONFIG_NATIVE_WINDOWS */
-static int hostapd_global_init(struct hapd_interfaces *interfaces)
+static int hostapd_global_init(struct hapd_interfaces *interfaces,
+ const char *entropy_file)
{
hostapd_logger_register_cb(hostapd_logger_cb);
@@ -383,7 +384,7 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces)
return -1;
}
- random_init();
+ random_init(entropy_file);
#ifndef CONFIG_NATIVE_WINDOWS
eloop_register_signal(SIGHUP, handle_reload, interfaces);
@@ -468,13 +469,14 @@ static void usage(void)
show_version();
fprintf(stderr,
"\n"
- "usage: hostapd [-hdBKtv] [-P <PID file>] "
+ "usage: hostapd [-hdBKtv] [-P <PID file>] [-e <entropy file>] "
"<configuration file(s)>\n"
"\n"
"options:\n"
" -h show this usage\n"
" -d show more debug messages (-dd for even more)\n"
" -B run daemon in the background\n"
+ " -e entropy file\n"
" -P PID file\n"
" -K include key data in debug messages\n"
#ifdef CONFIG_DEBUG_FILE
@@ -504,12 +506,13 @@ int main(int argc, char *argv[])
int c, debug = 0, daemonize = 0;
char *pid_file = NULL;
const char *log_file = NULL;
+ const char *entropy_file = NULL;
if (os_program_init())
return -1;
for (;;) {
- c = getopt(argc, argv, "Bdf:hKP:tv");
+ c = getopt(argc, argv, "Bde:f:hKP:tv");
if (c < 0)
break;
switch (c) {
@@ -524,6 +527,9 @@ int main(int argc, char *argv[])
case 'B':
daemonize++;
break;
+ case 'e':
+ entropy_file = optarg;
+ break;
case 'f':
log_file = optarg;
break;
@@ -564,7 +570,7 @@ int main(int argc, char *argv[])
return -1;
}
- if (hostapd_global_init(&interfaces))
+ if (hostapd_global_init(&interfaces, entropy_file))
return -1;
/* Initialize interfaces */
diff --git a/src/crypto/random.c b/src/crypto/random.c
index a30afde..f545917 100644
--- a/src/crypto/random.c
+++ b/src/crypto/random.c
@@ -57,12 +57,18 @@ static size_t dummy_key_avail = 0;
static int random_fd = -1;
#endif /* __linux__ */
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;
static unsigned int total_collected = 0;
+static void random_write_entropy(void);
+
+
static u32 __ROL32(u32 x, u32 y)
{
return (x << (y & 31)) | (x >> (32 - (y & 31)));
@@ -232,8 +238,12 @@ int random_pool_ready(void)
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)
+ own_pool_ready = MIN_READY_MARK;
+ random_write_entropy();
return 1;
+ }
wpa_printf(MSG_INFO, "random: Only %u/%u bytes of strong "
"random data available from /dev/random",
@@ -261,6 +271,7 @@ void random_mark_pool_ready(void)
own_pool_ready++;
wpa_printf(MSG_DEBUG, "random: Mark internal entropy pool to be "
"ready (count=%u/%u)", own_pool_ready, MIN_READY_MARK);
+ random_write_entropy();
}
@@ -298,15 +309,84 @@ static void random_read_fd(int sock, void *eloop_ctx, void *sock_ctx)
(unsigned) (sizeof(dummy_key) - dummy_key_avail));
dummy_key_avail += res;
- if (dummy_key_avail == sizeof(dummy_key))
+ if (dummy_key_avail == sizeof(dummy_key)) {
random_close_fd();
+ if (own_pool_ready < MIN_READY_MARK)
+ own_pool_ready = MIN_READY_MARK;
+ random_write_entropy();
+ }
}
#endif /* __linux__ */
-void random_init(void)
+static void random_read_entropy(void)
+{
+ char *buf;
+ size_t len;
+
+ if (!random_entropy_file)
+ return;
+
+ buf = os_readfile(random_entropy_file, &len);
+ if (buf == NULL)
+ return; /* entropy file not yet available */
+
+ if (len != 1 + RANDOM_ENTROPY_SIZE) {
+ wpa_printf(MSG_DEBUG, "random: Invalid entropy file %s",
+ random_entropy_file);
+ os_free(buf);
+ return;
+ }
+
+ 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)",
+ random_entropy_file, own_pool_ready);
+}
+
+
+static void random_write_entropy(void)
{
+ char buf[RANDOM_ENTROPY_SIZE];
+ FILE *f;
+ u8 opr;
+
+ if (!random_entropy_file)
+ return;
+
+ random_get_bytes(buf, RANDOM_ENTROPY_SIZE);
+
+ f = fopen(random_entropy_file, "wb");
+ if (f == NULL) {
+ wpa_printf(MSG_ERROR, "random: Could not write %s",
+ random_entropy_file);
+ return;
+ }
+
+ opr = own_pool_ready > 0xff ? 0xff : own_pool_ready;
+ fwrite(&opr, 1, 1, f);
+ fwrite(buf, RANDOM_ENTROPY_SIZE, 1, f);
+ fclose(f);
+
+ wpa_printf(MSG_DEBUG, "random: Updated entropy file %s "
+ "(own_pool_ready=%u)",
+ random_entropy_file, own_pool_ready);
+}
+
+
+void random_init(const char *entropy_file)
+{
+ os_free(random_entropy_file);
+ if (entropy_file)
+ random_entropy_file = os_strdup(entropy_file);
+ else
+ random_entropy_file = NULL;
+ random_read_entropy();
+
#ifdef __linux__
if (random_fd >= 0)
return;
@@ -326,6 +406,8 @@ void random_init(void)
eloop_register_read_sock(random_fd, random_read_fd, NULL, NULL);
#endif /* __linux__ */
+
+ random_write_entropy();
}
@@ -334,4 +416,7 @@ void random_deinit(void)
#ifdef __linux__
random_close_fd();
#endif /* __linux__ */
+ random_write_entropy();
+ os_free(random_entropy_file);
+ random_entropy_file = NULL;
}
diff --git a/src/crypto/random.h b/src/crypto/random.h
index 5dabd2b..1048bb4 100644
--- a/src/crypto/random.h
+++ b/src/crypto/random.h
@@ -16,14 +16,14 @@
#define RANDOM_H
#ifdef CONFIG_NO_RANDOM_POOL
-#define random_init() do { } while (0)
+#define random_init(e) do { } while (0)
#define random_deinit() do { } while (0)
#define random_add_randomness(b, l) do { } while (0)
#define random_get_bytes(b, l) os_get_random((b), (l))
#define random_pool_ready() 1
#define random_mark_pool_ready() do { } while (0)
#else /* CONFIG_NO_RANDOM_POOL */
-void random_init(void);
+void random_init(const char *entropy_file);
void random_deinit(void);
void random_add_randomness(const void *buf, size_t len);
int random_get_bytes(void *buf, size_t len);
diff --git a/wpa_supplicant/defconfig b/wpa_supplicant/defconfig
index 0c8e5f2..ea925c4 100644
--- a/wpa_supplicant/defconfig
+++ b/wpa_supplicant/defconfig
@@ -437,10 +437,16 @@ CONFIG_PEERKEY=y
# from the OS. This by itself is not considered to be very strong, but it may
# help in cases where the system pool is not initialized properly. However, it
# is very strongly recommended that the system pool is initialized with enough
-# entropy either by using hardware assisted random number generatior or by
+# entropy either by using hardware assisted random number generator or by
# storing state over device reboots.
#
-# If the os_get_random() is known to provide strong ramdom data (e.g., on
+# wpa_supplicant can be configured to maintain its own entropy store over
+# restarts to enhance random number generation. This is not perfect, but it is
+# much more secure than using the same sequence of random numbers after every
+# reboot. This can be enabled with -e<entropy file> command line option. The
+# specified file needs to be readable and writable by wpa_supplicant.
+#
+# If the os_get_random() is known to provide strong random data (e.g., on
# Linux/BSD, the board in question is known to have reliable source of random
# data from /dev/urandom), the internal wpa_supplicant random pool can be
# disabled. This will save some in binary size and CPU use. However, this
diff --git a/wpa_supplicant/main.c b/wpa_supplicant/main.c
index c0aa59c..e196f3c 100644
--- a/wpa_supplicant/main.c
+++ b/wpa_supplicant/main.c
@@ -33,7 +33,8 @@ static void usage(void)
"[-g<global ctrl>] \\\n"
" -i<ifname> -c<config file> [-C<ctrl>] [-D<driver>] "
"[-p<driver_param>] \\\n"
- " [-b<br_ifname>] [-f<debug file>] \\\n"
+ " [-b<br_ifname>] [-f<debug file>] [-e<entropy file>] "
+ "\\\n"
" [-o<override driver>] [-O<override ctrl>] \\\n"
" [-N -i<ifname> -c<conf> [-C<ctrl>] "
"[-D<driver>] \\\n"
@@ -56,7 +57,8 @@ static void usage(void)
" -C = ctrl_interface parameter (only used if -c is not)\n"
" -i = interface name\n"
" -d = increase debugging verbosity (-dd even more)\n"
- " -D = driver name (can be multiple drivers: nl80211,wext)\n");
+ " -D = driver name (can be multiple drivers: nl80211,wext)\n"
+ " -e = entropy file\n");
#ifdef CONFIG_DEBUG_FILE
printf(" -f = log output to debug file instead of stdout\n");
#endif /* CONFIG_DEBUG_FILE */
@@ -143,7 +145,7 @@ int main(int argc, char *argv[])
wpa_supplicant_fd_workaround();
for (;;) {
- c = getopt(argc, argv, "b:Bc:C:D:df:g:hi:KLNo:O:p:P:qstuvW");
+ c = getopt(argc, argv, "b:Bc:C:D:de:f:g:hi:KLNo:O:p:P:qstuvW");
if (c < 0)
break;
switch (c) {
@@ -172,6 +174,9 @@ int main(int argc, char *argv[])
params.wpa_debug_level--;
break;
#endif /* CONFIG_NO_STDOUT_DEBUG */
+ case 'e':
+ params.entropy_file = optarg;
+ break;
#ifdef CONFIG_DEBUG_FILE
case 'f':
params.wpa_debug_file_path = optarg;
diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c
index 9295651..0352c13 100644
--- a/wpa_supplicant/wpa_supplicant.c
+++ b/wpa_supplicant/wpa_supplicant.c
@@ -2544,7 +2544,7 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params)
return NULL;
}
- random_init();
+ random_init(params->entropy_file);
global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global);
if (global->ctrl_iface == NULL) {
diff --git a/wpa_supplicant/wpa_supplicant_i.h b/wpa_supplicant/wpa_supplicant_i.h
index 8498666..b18d6d9 100644
--- a/wpa_supplicant/wpa_supplicant_i.h
+++ b/wpa_supplicant/wpa_supplicant_i.h
@@ -181,6 +181,14 @@ struct wpa_params {
* created.
*/
char *override_ctrl_interface;
+
+ /**
+ * entropy_file - Optional entropy file
+ *
+ * This parameter can be used to configure wpa_supplicant to maintain
+ * its internal entropy store over restarts.
+ */
+ char *entropy_file;
};
struct p2p_srv_bonjour {