From c78a2b5c8f8936e2d65fd8c750dc090a01d144e6 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Fri, 21 Oct 2016 08:01:54 +0100 Subject: [PATCH] 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.) --- source/randLIB.c | 25 +++++++------------ .../unittest/randlib/test_randlib.c | 18 ++++++------- 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/source/randLIB.c b/source/randLIB.c index 0777f2719e..21c6a58c3c 100644 --- a/source/randLIB.c +++ b/source/randLIB.c @@ -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 } diff --git a/test/mbed-client-randlib/unittest/randlib/test_randlib.c b/test/mbed-client-randlib/unittest/randlib/test_randlib.c index 0fc3138a12..d918d59108 100644 --- a/test/mbed-client-randlib/unittest/randlib/test_randlib.c +++ b/test/mbed-client-randlib/unittest/randlib/test_randlib.c @@ -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)) {