Mix input to randLIB_add_seed calls

Don't just xor in the 64-bit number given, splitmix64 it across the entire
state. Also, make sure we don't accidentally set the state to all-zero.

RANDLIB_ASSUME_GOOD_SEED dropped - we now assume splitmix64 will be
present for the seed additions.

(Note that add_seed will be somewhat slow on platforms like MSP430 with
slow multipliers - don't call it too much.)
pull/3240/head
Kevin Bracey 2016-10-21 08:01:54 +01:00
parent 9a00890fde
commit c78a2b5c8f
2 changed files with 18 additions and 25 deletions

View File

@ -69,7 +69,6 @@ static inline uint64_t rol(uint64_t n, int bits)
return (n << bits) | (n >> (64 - bits));
}
#ifndef RANDLIB_ASSUME_GOOD_SEED
/* Lower-quality generator used only for initial seeding, if platform
* isn't returning multiple seeds itself. Multiplies are rather heavy
* for lower-end platforms, but this is initialisation only.
@ -81,7 +80,6 @@ static uint64_t splitmix64(uint64_t *seed)
z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
return z ^ (z >> 31);
}
#endif // RANDLIB_ASSUME_GOOD_SEED
#endif // RANDOM_DEVICE
void randLIB_seed_random(void)
@ -94,7 +92,8 @@ void randLIB_seed_random(void)
arm_random_module_init();
/* We exclusive-OR with the current state, in case they make this call
* multiple times. We don't want to potentially lose entropy.
* multiple times,or in case someone has called randLIB_add_seed before
* this. We don't want to potentially lose entropy.
*/
/* Spell out expressions so we get known ordering of 4 seed calls */
@ -104,30 +103,24 @@ void randLIB_seed_random(void)
s = (uint64_t) arm_random_seed_get() << 32;
state[1] ^= s | arm_random_seed_get();
#ifdef RANDLIB_ASSUME_GOOD_SEED
/* Can avoid significant code overhead of splitmix64(), but we do still
* have to check for the theoretically possible illegal case of all-zero.
*/
if (state[0] == 0 && state[1] == 0) {
state[1] = 1;
}
#else
/* This check serves to both to stir the state if the platform is returning
* constant seeding values, and to avoid the illegal all-zero state.
*/
if (state[0] == state[1]) {
uint64_t seed = state[0];
state[0] = splitmix64(&seed);
state[1] = splitmix64(&seed);
randLIB_add_seed(state[0]);
}
#endif // RANDLIB_ASSUME_GOOD_SEED
#endif // RANDOM_DEVICE
}
void randLIB_add_seed(uint64_t seed)
{
#ifndef RANDOM_DEVICE
state[1] += seed;
state[0] ^= splitmix64(&seed);
state[1] ^= splitmix64(&seed);
/* This is absolutely necessary, but I challenge you to add it to line coverage */
if (state[1] == 0 && state[0] == 0) {
state[0] = 1;
}
#endif
}

View File

@ -111,18 +111,18 @@ bool test_randLIB_get_64bit()
/* If passed all "4" seeds, seeding should detect this
* and use splitmix64 to create the actual seed
* (0x03910b0aab9b37e5, 0x0b309ab13d42b2a6),
* (0x03910b0eab9b37e1, 0x0b309ab53d42b2a2),
* and produce this output:
*/
static const uint64_t expected4444[] = {
UINT64_C(0x0ec1a5bbe8ddea8b),
UINT64_C(0x0be710b8fcf5a491),
UINT64_C(0xb21127f7159348b4),
UINT64_C(0xdf31900d21f92182),
UINT64_C(0xd5a797507d94daa9),
UINT64_C(0x66a1c5a4fb04be3d),
UINT64_C(0x259e5385f48353be),
UINT64_C(0x5d3e3286cd4eae19)
UINT64_C(0x0ec1a5c3e8ddea83),
UINT64_C(0x09e710b8faf5a491),
UINT64_C(0xd4102776f79448b4),
UINT64_C(0x5d61988b60091900),
UINT64_C(0xf6c8a72a9c72cb4b),
UINT64_C(0xb06923e0cf0f2fb1),
UINT64_C(0x24bbed475153f573),
UINT64_C(0xfff0b4bd08c5581f),
};
if (!test_output(4, false, expected4444)) {