Skip to content

Commit 95e377f

Browse files
committed
random.c: use siphash in counter mode for hash initialization.
SipHash is secure PseudoRandom Function, and could be used in a counter mode to produce strong pseudorandom stream of bytes. So use it to securely initialize both hashseed and sipseed. (so no way to recover sipseed from hashseed)
1 parent a6265d5 commit 95e377f

File tree

1 file changed

+30
-27
lines changed

1 file changed

+30
-27
lines changed

random.c

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,39 +1475,47 @@ random_s_rand(int argc, VALUE *argv, VALUE obj)
14751475

14761476
static st_index_t hashseed[3];
14771477
typedef uint8_t sipseed_keys_t[16];
1478-
static union {
1478+
static union sipseed {
14791479
sipseed_keys_t key;
14801480
uint32_t u32[type_roomof(sipseed_keys_t, uint32_t)];
14811481
} sipseed;
14821482

14831483
static void
1484-
init_hashseed(struct MT *mt)
1484+
init_hashseed(sipseed_keys_t key, uint32_t* cnt)
14851485
{
14861486
int i;
14871487
for (i=0; i < numberof(hashseed); i++) {
1488-
hashseed[i] = genrand_int32(mt);
1489-
#if SIZEOF_ST_INDEX_T*CHAR_BIT > 4*8
1490-
hashseed[i] <<= 32;
1491-
hashseed[i] |= genrand_int32(mt);
1488+
int bits = SIZEOF_ST_INDEX_T*CHAR_BIT;
1489+
hashseed[i] = 0;
1490+
for (; bits > 0; bits -= 32) {
1491+
sip_uint64_t h = sip_hash24(key, (void*)cnt, sizeof(uint32_t));
1492+
(*cnt)++;
1493+
#if SIZEOF_ST_INDEX_T > 32
1494+
hashseed[i] <<= 32;
14921495
#endif
1493-
#if SIZEOF_ST_INDEX_T*CHAR_BIT > 8*8
1494-
hashseed[i] <<= 32;
1495-
hashseed[i] |= genrand_int32(mt);
1496-
#endif
1497-
#if SIZEOF_ST_INDEX_T*CHAR_BIT > 12*8
1498-
hashseed[i] <<= 32;
1499-
hashseed[i] |= genrand_int32(mt);
1496+
#ifdef HAVE_UINT64_T
1497+
hashseed[i] ^= (st_index_t)h;
1498+
#else
1499+
hashseed[i] ^= h.u32[0] ^ h.u32[1];
15001500
#endif
1501+
}
15011502
}
15021503
}
15031504

15041505
static void
1505-
init_siphash(struct MT *mt)
1506+
init_siphash(sipseed_keys_t key, uint32_t* cnt)
15061507
{
15071508
int i;
15081509

1509-
for (i = 0; i < numberof(sipseed.u32); ++i)
1510-
sipseed.u32[i] = genrand_int32(mt);
1510+
for (i = 0; i < numberof(sipseed.u32); ++i) {
1511+
sip_uint64_t h = sip_hash24(key, (void*)cnt, sizeof(uint32_t));
1512+
(*cnt)++;
1513+
#ifdef HAVE_UINT64_T
1514+
sipseed.u32[i] = (uint32_t)h ^ (uint32_t)(h >> 32);
1515+
#else
1516+
sipseed.u32[i] = h.u32[0] ^ h.u32[1];
1517+
#endif
1518+
}
15111519
}
15121520

15131521
#define MurmurMagic_1 (st_index_t)0xc6a4a793
@@ -1580,20 +1588,15 @@ rb_memhash(const void *ptr, long len)
15801588
void
15811589
Init_RandomSeedCore(void)
15821590
{
1583-
/*
1584-
Don't reuse this MT for Random::DEFAULT. Random::DEFAULT::seed shouldn't
1585-
provide a hint that an attacker guess siphash's seed.
1586-
*/
1587-
struct MT mt;
1588-
uint32_t initial_seed[DEFAULT_SEED_CNT];
1591+
union sipseed seed = { {0} };
1592+
uint32_t cnt = 1;
15891593

1590-
fill_random_seed(initial_seed, DEFAULT_SEED_CNT);
1591-
init_by_array(&mt, initial_seed, DEFAULT_SEED_CNT);
1594+
fill_random_seed(seed.u32, numberof(seed.u32));
15921595

1593-
init_hashseed(&mt);
1594-
init_siphash(&mt);
1596+
init_hashseed(seed.key, &cnt);
1597+
init_siphash(seed.key, &cnt);
15951598

1596-
explicit_bzero(initial_seed, DEFAULT_SEED_LEN);
1599+
explicit_bzero(seed.key, sizeof(seed.key));
15971600
}
15981601

15991602
static VALUE

0 commit comments

Comments
 (0)