Re: Why does reading from /dev/urandom deplete entropy so much?

Eric Dumazet
2007-12-04T18:18:21Z

[-- Attachment #1: Type: text/plain, Size: 1084 bytes --]

Alan Cox a écrit :
>> No matter what you consider as being better, changing a 12 years old and
>> widely used userspace interface like /dev/urandom is simply not an
>> option.
>>
>
> Fixing it to be more efficient in its use of entropy and also fixing the
> fact its not actually a good random number source would be worth looking
> at however.
>
Yes, since current behavior on network irq is very pessimistic.

If you have some trafic, (ie more than HZ/2 interrupts per second),
then add_timer_randomness() feeds
some entropy but gives no credit (calling credit_entropy_store() with
nbits=0)

This is because we take into account only the jiffies difference, and
not the get_cycles() that should give
us more entropy on most plaforms.

In this patch, I suggest that we feed only one u32 word of entropy,
combination of the previous distinct
words (with some of them being constant or so), so that the nbits
estimation is less pessimistic, but also to
avoid injecting false entropy.

Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>

[-- Attachment #2: random.patch --]
[-- Type: text/plain, Size: 1808 bytes --]

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 5fee056..6eccfc9 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -550,8 +550,8 @@ static void credit_entropy_store(struct entropy_store *r, int nbits)

/* There is one of these per entropy source */
struct timer_rand_state {
- cycles_t last_time;
- long last_delta,last_delta2;
+ u32 last_word;
+ int last_delta,last_delta2;
unsigned dont_count_entropy:1;
};

@@ -570,12 +570,17 @@ static struct timer_rand_state *irq_timer_state[NR_IRQS];
*/
static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
{
- struct {
- cycles_t cycles;
- long jiffies;
- unsigned num;
+ union {
+ struct {
+ cycles_t cycles;
+ long jiffies;
+ unsigned num;
+ };
+ u32 words[1];
} sample;
- long delta, delta2, delta3;
+ u32 word;
+ unsigned int ui;
+ int delta, delta2, delta3;

preempt_disable();
/* if over the trickle threshold, use only 1 in 4096 samples */
@@ -586,7 +591,12 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
sample.jiffies = jiffies;
sample.cycles = get_cycles();
sample.num = num;
- add_entropy_words(&input_pool, (u32 *)&sample, sizeof(sample)/4);
+
+ word = sample.words[0];
+ for (ui = 1; ui < sizeof(sample)/4; ui++)
+ word += sample.words[ui];
+
+ add_entropy_words(&input_pool, &word, 1);

/*
* Calculate number of bits of randomness we probably added.
@@ -595,8 +605,8 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num)
*/

if (!state->dont_count_entropy) {
- delta = sample.jiffies - state->last_time;
- state->last_time = sample.jiffies;
+ delta = word - state->last_word;
+ state->last_word = word;

delta2 = delta - state->last_delta;
state->last_delta = delta;