Skip to content

Commit

Permalink
hwrng: use rng source with best quality
Browse files Browse the repository at this point in the history
This patch rewoks the hwrng to always use the
rng source with best entropy quality.

On registation and unregistration the hwrng now
tries to choose the best (= highest quality value)
rng source. The handling of the internal list
of registered rng sources is now always sorted
by quality and the top most rng chosen.

Signed-off-by: Harald Freudenberger <freude@linux.vnet.ibm.com>
Reviewed-by: PrasannaKumar Muralidharan <prasannatsmkumar@gmail.com>
Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
  • Loading branch information
Harald Freudenberger authored and Herbert Xu committed Jul 18, 2017
1 parent ad81808 commit 2bbb698
Showing 1 changed file with 19 additions and 6 deletions.
25 changes: 19 additions & 6 deletions drivers/char/hw_random/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

static struct hwrng *current_rng;
static struct task_struct *hwrng_fill;
/* list of registered rngs, sorted decending by quality */
static LIST_HEAD(rng_list);
/* Protects rng_list and current_rng */
static DEFINE_MUTEX(rng_mutex);
Expand Down Expand Up @@ -417,6 +418,7 @@ int hwrng_register(struct hwrng *rng)
{
int err = -EINVAL;
struct hwrng *old_rng, *tmp;
struct list_head *rng_list_ptr;

if (!rng->name || (!rng->data_read && !rng->read))
goto out;
Expand All @@ -432,14 +434,25 @@ int hwrng_register(struct hwrng *rng)
init_completion(&rng->cleanup_done);
complete(&rng->cleanup_done);

/* rng_list is sorted by decreasing quality */
list_for_each(rng_list_ptr, &rng_list) {
tmp = list_entry(rng_list_ptr, struct hwrng, list);
if (tmp->quality < rng->quality)
break;
}
list_add_tail(&rng->list, rng_list_ptr);

old_rng = current_rng;
err = 0;
if (!old_rng) {
if (!old_rng || (rng->quality > old_rng->quality)) {
/*
* Set new rng as current as the new rng source
* provides better entropy quality.
*/
err = set_current_rng(rng);
if (err)
goto out_unlock;
}
list_add_tail(&rng->list, &rng_list);

if (old_rng && !rng->init) {
/*
Expand All @@ -466,12 +479,12 @@ void hwrng_unregister(struct hwrng *rng)
list_del(&rng->list);
if (current_rng == rng) {
drop_current_rng();
/* rng_list is sorted by quality, use the best (=first) one */
if (!list_empty(&rng_list)) {
struct hwrng *tail;

tail = list_entry(rng_list.prev, struct hwrng, list);
struct hwrng *new_rng;

set_current_rng(tail);
new_rng = list_entry(rng_list.next, struct hwrng, list);
set_current_rng(new_rng);
}
}

Expand Down

0 comments on commit 2bbb698

Please sign in to comment.