From d47fa330b84df9b7e8e25ed6d467a36a33fea4ee Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Tue, 22 Mar 2011 23:15:00 +0200 Subject: [PATCH] random: Read /dev/random in the background with eloop read socket This makes it more likely to be able to fetch the 20 octet seed from /dev/random in cases where other programs may also be competing for this. --- hostapd/main.c | 5 +++ src/crypto/random.c | 77 ++++++++++++++++++++++++++++++++- src/crypto/random.h | 6 ++- wpa_supplicant/wpa_supplicant.c | 5 +++ 4 files changed, 91 insertions(+), 2 deletions(-) diff --git a/hostapd/main.c b/hostapd/main.c index 94cdbbad7..21b3cca14 100644 --- a/hostapd/main.c +++ b/hostapd/main.c @@ -19,6 +19,7 @@ #include "utils/common.h" #include "utils/eloop.h" +#include "crypto/random.h" #include "crypto/tls.h" #include "common/version.h" #include "drivers/driver.h" @@ -377,6 +378,8 @@ static int hostapd_global_init(struct hapd_interfaces *interfaces) return -1; } + random_init(); + #ifndef CONFIG_NATIVE_WINDOWS eloop_register_signal(SIGHUP, handle_reload, interfaces); eloop_register_signal(SIGUSR1, handle_dump_state, interfaces); @@ -397,6 +400,8 @@ static void hostapd_global_deinit(const char *pid_file) tncs_global_deinit(); #endif /* EAP_SERVER_TNC */ + random_deinit(); + eloop_destroy(); #ifndef CONFIG_NATIVE_WINDOWS diff --git a/src/crypto/random.c b/src/crypto/random.c index 64180a13a..a30afde11 100644 --- a/src/crypto/random.c +++ b/src/crypto/random.c @@ -1,6 +1,6 @@ /* * Random number generator - * Copyright (c) 2010, Jouni Malinen + * Copyright (c) 2010-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -34,6 +34,7 @@ #endif /* __linux__ */ #include "utils/common.h" +#include "utils/eloop.h" #include "sha1.h" #include "random.h" @@ -53,6 +54,7 @@ static unsigned int pool_pos = 0; static u8 dummy_key[20]; #ifdef __linux__ static size_t dummy_key_avail = 0; +static int random_fd = -1; #endif /* __linux__ */ static unsigned int own_pool_ready = 0; @@ -260,3 +262,76 @@ void random_mark_pool_ready(void) wpa_printf(MSG_DEBUG, "random: Mark internal entropy pool to be " "ready (count=%u/%u)", own_pool_ready, MIN_READY_MARK); } + + +#ifdef __linux__ + +static void random_close_fd(void) +{ + if (random_fd >= 0) { + eloop_unregister_read_sock(random_fd); + close(random_fd); + random_fd = -1; + } +} + + +static void random_read_fd(int sock, void *eloop_ctx, void *sock_ctx) +{ + ssize_t res; + + if (dummy_key_avail == sizeof(dummy_key)) { + random_close_fd(); + return; + } + + res = read(sock, 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)); + return; + } + + wpa_printf(MSG_DEBUG, "random: Got %u/%u bytes from /dev/random", + (unsigned) res, + (unsigned) (sizeof(dummy_key) - dummy_key_avail)); + dummy_key_avail += res; + + if (dummy_key_avail == sizeof(dummy_key)) + random_close_fd(); +} + +#endif /* __linux__ */ + + +void random_init(void) +{ +#ifdef __linux__ + if (random_fd >= 0) + return; + + random_fd = open("/dev/random", O_RDONLY | O_NONBLOCK); + if (random_fd < 0) { +#ifndef CONFIG_NO_STDOUT_DEBUG + int error = errno; + perror("open(/dev/random)"); + wpa_printf(MSG_ERROR, "random: Cannot open /dev/random: %s", + strerror(error)); +#endif /* CONFIG_NO_STDOUT_DEBUG */ + return; + } + wpa_printf(MSG_DEBUG, "random: Trying to read entropy from " + "/dev/random"); + + eloop_register_read_sock(random_fd, random_read_fd, NULL, NULL); +#endif /* __linux__ */ +} + + +void random_deinit(void) +{ +#ifdef __linux__ + random_close_fd(); +#endif /* __linux__ */ +} diff --git a/src/crypto/random.h b/src/crypto/random.h index 7b6257737..5dabd2b02 100644 --- a/src/crypto/random.h +++ b/src/crypto/random.h @@ -1,6 +1,6 @@ /* * Random number generator - * Copyright (c) 2010, Jouni Malinen + * Copyright (c) 2010-2011, Jouni Malinen * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as @@ -16,11 +16,15 @@ #define RANDOM_H #ifdef CONFIG_NO_RANDOM_POOL +#define random_init() 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_deinit(void); void random_add_randomness(const void *buf, size_t len); int random_get_bytes(void *buf, size_t len); int random_pool_ready(void); diff --git a/wpa_supplicant/wpa_supplicant.c b/wpa_supplicant/wpa_supplicant.c index b34bf0395..28b3f0b70 100644 --- a/wpa_supplicant/wpa_supplicant.c +++ b/wpa_supplicant/wpa_supplicant.c @@ -19,6 +19,7 @@ #include "includes.h" #include "common.h" +#include "crypto/random.h" #include "eapol_supp/eapol_supp_sm.h" #include "eap_peer/eap.h" #include "eap_server/eap_methods.h" @@ -2543,6 +2544,8 @@ struct wpa_global * wpa_supplicant_init(struct wpa_params *params) return NULL; } + random_init(); + global->ctrl_iface = wpa_supplicant_global_ctrl_iface_init(global); if (global->ctrl_iface == NULL) { wpa_supplicant_deinit(global); @@ -2653,6 +2656,8 @@ void wpa_supplicant_deinit(struct wpa_global *global) } os_free(global->drv_priv); + random_deinit(); + eloop_destroy(); if (global->params.pid_file) {