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)); return (n << bits) | (n >> (64 - bits));
} }
#ifndef RANDLIB_ASSUME_GOOD_SEED
/* Lower-quality generator used only for initial seeding, if platform /* Lower-quality generator used only for initial seeding, if platform
* isn't returning multiple seeds itself. Multiplies are rather heavy * isn't returning multiple seeds itself. Multiplies are rather heavy
* for lower-end platforms, but this is initialisation only. * 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); z = (z ^ (z >> 27)) * UINT64_C(0x94D049BB133111EB);
return z ^ (z >> 31); return z ^ (z >> 31);
} }
#endif // RANDLIB_ASSUME_GOOD_SEED
#endif // RANDOM_DEVICE #endif // RANDOM_DEVICE
void randLIB_seed_random(void) void randLIB_seed_random(void)
@ -94,7 +92,8 @@ void randLIB_seed_random(void)
arm_random_module_init(); arm_random_module_init();
/* We exclusive-OR with the current state, in case they make this call /* 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 */ /* 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; s = (uint64_t) arm_random_seed_get() << 32;
state[1] ^= s | arm_random_seed_get(); 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 /* 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. * constant seeding values, and to avoid the illegal all-zero state.
*/ */
if (state[0] == state[1]) { if (state[0] == state[1]) {
uint64_t seed = state[0]; randLIB_add_seed(state[0]);
state[0] = splitmix64(&seed);
state[1] = splitmix64(&seed);
} }
#endif // RANDLIB_ASSUME_GOOD_SEED
#endif // RANDOM_DEVICE #endif // RANDOM_DEVICE
} }
void randLIB_add_seed(uint64_t seed) void randLIB_add_seed(uint64_t seed)
{ {
#ifndef RANDOM_DEVICE #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 #endif
} }

View File

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