Skip to content

Commit 48eecfc

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 9c3aa6a commit 48eecfc

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[4];
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
@@ -1589,20 +1597,15 @@ rb_memhash(const void *ptr, long len)
15891597
void
15901598
Init_RandomSeedCore(void)
15911599
{
1592-
/*
1593-
Don't reuse this MT for Random::DEFAULT. Random::DEFAULT::seed shouldn't
1594-
provide a hint that an attacker guess siphash's seed.
1595-
*/
1596-
struct MT mt;
1597-
uint32_t initial_seed[DEFAULT_SEED_CNT];
1600+
union sipseed seed = { {0} };
1601+
uint32_t cnt = 1;
15981602

1599-
fill_random_seed(initial_seed, DEFAULT_SEED_CNT);
1600-
init_by_array(&mt, initial_seed, DEFAULT_SEED_CNT);
1603+
fill_random_seed(seed.u32, numberof(seed.u32));
16011604

1602-
init_hashseed(&mt);
1603-
init_siphash(&mt);
1605+
init_hashseed(seed.key, &cnt);
1606+
init_siphash(seed.key, &cnt);
16041607

1605-
explicit_bzero(initial_seed, DEFAULT_SEED_LEN);
1608+
explicit_bzero(seed.key, sizeof(seed.key));
16061609
}
16071610

16081611
static VALUE

0 commit comments

Comments
 (0)