Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 697f8d03 authored by Stephen Hemminger's avatar Stephen Hemminger Committed by David S. Miller
Browse files

random32: seeding improvement



The rationale is:
   * use u32 consistently
   * no need to do LCG on values from (better) get_random_bytes
   * use more data from get_random_bytes for secondary seeding
   * don't reduce state space on srandom32()
   * enforce state variable initialization restrictions

Note: the second paper has a version of random32() with even longer period
and a version of random64() if needed.

Signed-off-by: default avatarStephen Hemminger <shemminger@vyatta.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 4adf0af6
Loading
Loading
Loading
Loading
+27 −21
Original line number Diff line number Diff line
@@ -56,23 +56,12 @@ static u32 __random32(struct rnd_state *state)
	return (state->s1 ^ state->s2 ^ state->s3);
}

static void __set_random32(struct rnd_state *state, unsigned long s)
/*
 * Handle minimum values for seeds
 */
static inline u32 __seed(u32 x, u32 m)
{
	if (s == 0)
		s = 1;      /* default seed is 1 */

#define LCG(n) (69069 * n)
	state->s1 = LCG(s);
	state->s2 = LCG(state->s1);
	state->s3 = LCG(state->s2);

	/* "warm it up" */
	__random32(state);
	__random32(state);
	__random32(state);
	__random32(state);
	__random32(state);
	__random32(state);
	return (x < m) ? x + m : x;
}

/**
@@ -107,7 +96,7 @@ void srandom32(u32 entropy)
	 */
	for_each_possible_cpu (i) {
		struct rnd_state *state = &per_cpu(net_rand_state, i);
		__set_random32(state, state->s1 ^ entropy);
		state->s1 = __seed(state->s1 ^ entropy, 1);
	}
}
EXPORT_SYMBOL(srandom32);
@@ -122,7 +111,19 @@ static int __init random32_init(void)

	for_each_possible_cpu(i) {
		struct rnd_state *state = &per_cpu(net_rand_state,i);
		__set_random32(state, i + jiffies);

#define LCG(x)	((x) * 69069)	/* super-duper LCG */
		state->s1 = __seed(LCG(i + jiffies), 1);
		state->s2 = __seed(LCG(state->s1), 7);
		state->s3 = __seed(LCG(state->s2), 15);

		/* "warm it up" */
		__random32(state);
		__random32(state);
		__random32(state);
		__random32(state);
		__random32(state);
		__random32(state);
	}
	return 0;
}
@@ -135,13 +136,18 @@ core_initcall(random32_init);
static int __init random32_reseed(void)
{
	int i;
	unsigned long seed;

	for_each_possible_cpu(i) {
		struct rnd_state *state = &per_cpu(net_rand_state,i);
		u32 seeds[3];

		get_random_bytes(&seed, sizeof(seed));
		__set_random32(state, seed);
		get_random_bytes(&seeds, sizeof(seeds));
		state->s1 = __seed(seeds[0], 1);
		state->s2 = __seed(seeds[1], 7);
		state->s3 = __seed(seeds[2], 15);

		/* mix it in */
		__random32(state);
	}
	return 0;
}