Commit d3cc7996 authored by Amit Shah's avatar Amit Shah Committed by Herbert Xu

hwrng: fetch randomness only after device init

Commit d9e79726 "hwrng: add randomness to system from rng sources"
added a call to rng_get_data() from the hwrng_register() function.
However, some rng devices need initialization before data can be read
from them.

This commit makes the call to rng_get_data() depend on no init fn
pointer being registered by the device.  If an init function is
registered, this call is made after device init.

CC: Kees Cook <keescook@chromium.org>
CC: Jason Cooper <jason@lakedaemon.net>
CC: Herbert Xu <herbert@gondor.apana.org.au>
CC: <stable@vger.kernel.org> # For v3.15+
Signed-off-by: default avatarAmit Shah <amit.shah@redhat.com>
Reviewed-by: default avatarJason Cooper <jason@lakedaemon.net>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
parent 0378c9a8
...@@ -55,16 +55,35 @@ static DEFINE_MUTEX(rng_mutex); ...@@ -55,16 +55,35 @@ static DEFINE_MUTEX(rng_mutex);
static int data_avail; static int data_avail;
static u8 *rng_buffer; static u8 *rng_buffer;
static inline int rng_get_data(struct hwrng *rng, u8 *buffer, size_t size,
int wait);
static size_t rng_buffer_size(void) static size_t rng_buffer_size(void)
{ {
return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES;
} }
static void add_early_randomness(struct hwrng *rng)
{
unsigned char bytes[16];
int bytes_read;
bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1);
if (bytes_read > 0)
add_device_randomness(bytes, bytes_read);
}
static inline int hwrng_init(struct hwrng *rng) static inline int hwrng_init(struct hwrng *rng)
{ {
if (!rng->init) if (rng->init) {
int ret;
ret = rng->init(rng);
if (ret)
return ret;
}
add_early_randomness(rng);
return 0; return 0;
return rng->init(rng);
} }
static inline void hwrng_cleanup(struct hwrng *rng) static inline void hwrng_cleanup(struct hwrng *rng)
...@@ -304,8 +323,6 @@ int hwrng_register(struct hwrng *rng) ...@@ -304,8 +323,6 @@ int hwrng_register(struct hwrng *rng)
{ {
int err = -EINVAL; int err = -EINVAL;
struct hwrng *old_rng, *tmp; struct hwrng *old_rng, *tmp;
unsigned char bytes[16];
int bytes_read;
if (rng->name == NULL || if (rng->name == NULL ||
(rng->data_read == NULL && rng->read == NULL)) (rng->data_read == NULL && rng->read == NULL))
...@@ -347,9 +364,17 @@ int hwrng_register(struct hwrng *rng) ...@@ -347,9 +364,17 @@ int hwrng_register(struct hwrng *rng)
INIT_LIST_HEAD(&rng->list); INIT_LIST_HEAD(&rng->list);
list_add_tail(&rng->list, &rng_list); list_add_tail(&rng->list, &rng_list);
bytes_read = rng_get_data(rng, bytes, sizeof(bytes), 1); if (old_rng && !rng->init) {
if (bytes_read > 0) /*
add_device_randomness(bytes, bytes_read); * Use a new device's input to add some randomness to
* the system. If this rng device isn't going to be
* used right away, its init function hasn't been
* called yet; so only use the randomness from devices
* that don't need an init callback.
*/
add_early_randomness(rng);
}
out_unlock: out_unlock:
mutex_unlock(&rng_mutex); mutex_unlock(&rng_mutex);
out: out:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment