diff --git a/random.c b/random.c index fc2a076b002ee1..ffc704ca7b6159 100644 --- a/random.c +++ b/random.c @@ -1475,39 +1475,47 @@ random_s_rand(int argc, VALUE *argv, VALUE obj) static st_index_t hashseed[4]; typedef uint8_t sipseed_keys_t[16]; -static union { +static union sipseed { sipseed_keys_t key; uint32_t u32[type_roomof(sipseed_keys_t, uint32_t)]; } sipseed; static void -init_hashseed(struct MT *mt) +init_hashseed(sipseed_keys_t key, uint32_t* cnt) { int i; for (i=0; i < numberof(hashseed); i++) { - hashseed[i] = genrand_int32(mt); -#if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8 - hashseed[i] <<= 32; - hashseed[i] |= genrand_int32(mt); + int bits = SIZEOF_ST_INDEX_T*CHAR_BIT; + hashseed[i] = 0; + for (; bits > 0; bits -= 32) { + sip_uint64_t h = sip_hash24(key, (void*)cnt, sizeof(uint32_t)); + (*cnt)++; +#if SIZEOF_ST_INDEX_T > 32 + hashseed[i] <<= 32; #endif -#if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8 - hashseed[i] <<= 32; - hashseed[i] |= genrand_int32(mt); -#endif -#if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8 - hashseed[i] <<= 32; - hashseed[i] |= genrand_int32(mt); +#ifdef HAVE_UINT64_T + hashseed[i] ^= (st_index_t)h; +#else + hashseed[i] ^= h.u32[0] ^ h.u32[1]; #endif + } } } static void -init_siphash(struct MT *mt) +init_siphash(sipseed_keys_t key, uint32_t* cnt) { int i; - for (i = 0; i < numberof(sipseed.u32); ++i) - sipseed.u32[i] = genrand_int32(mt); + for (i = 0; i < numberof(sipseed.u32); ++i) { + sip_uint64_t h = sip_hash24(key, (void*)cnt, sizeof(uint32_t)); + (*cnt)++; +#ifdef HAVE_UINT64_T + sipseed.u32[i] = (uint32_t)h ^ (uint32_t)(h >> 32); +#else + sipseed.u32[i] = h.u32[0] ^ h.u32[1]; +#endif + } } #define MurmurMagic_1 (st_index_t)0xc6a4a793 @@ -1589,20 +1597,15 @@ rb_memhash(const void *ptr, long len) void Init_RandomSeedCore(void) { - /* - Don't reuse this MT for Random::DEFAULT. Random::DEFAULT::seed shouldn't - provide a hint that an attacker guess siphash's seed. - */ - struct MT mt; - uint32_t initial_seed[DEFAULT_SEED_CNT]; + union sipseed seed = { {0} }; + uint32_t cnt = 1; - fill_random_seed(initial_seed, DEFAULT_SEED_CNT); - init_by_array(&mt, initial_seed, DEFAULT_SEED_CNT); + fill_random_seed(seed.u32, numberof(seed.u32)); - init_hashseed(&mt); - init_siphash(&mt); + init_hashseed(seed.key, &cnt); + init_siphash(seed.key, &cnt); - explicit_bzero(initial_seed, DEFAULT_SEED_LEN); + explicit_bzero(seed.key, sizeof(seed.key)); } static VALUE