mirror of https://github.com/ARMmbed/mbed-os.git
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
parent
9a00890fde
commit
c78a2b5c8f
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)) {
|
||||||
|
|
Loading…
Reference in New Issue