@@ -304,6 +304,34 @@ struct RNGState {
304304 {
305305 InitHardwareRand ();
306306 }
307+
308+ /* * Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher. */
309+ void MixExtract (unsigned char * out, size_t num, CSHA512&& hasher)
310+ {
311+ assert (num <= 32 );
312+ unsigned char buf[64 ];
313+ static_assert (sizeof (buf) == CSHA512::OUTPUT_SIZE, " Buffer needs to have hasher's output size" );
314+ {
315+ LOCK (m_mutex);
316+ // Write the current state of the RNG into the hasher
317+ hasher.Write (m_state, 32 );
318+ // Write a new counter number into the state
319+ hasher.Write ((const unsigned char *)&m_counter, sizeof (m_counter));
320+ ++m_counter;
321+ // Finalize the hasher
322+ hasher.Finalize (buf);
323+ // Store the last 32 bytes of the hash output as new RNG state.
324+ memcpy (m_state, buf + 32 , 32 );
325+ }
326+ // If desired, copy (up to) the first 32 bytes of the hash output as output.
327+ if (num) {
328+ assert (out != nullptr );
329+ memcpy (out, buf, num);
330+ }
331+ // Best effort cleanup of internal state
332+ hasher.Reset ();
333+ memory_cleanse (buf, 64 );
334+ }
307335};
308336
309337RNGState& GetRNGState ()
@@ -315,38 +343,29 @@ RNGState& GetRNGState()
315343}
316344}
317345
318- static void AddDataToRng (void * data, size_t len);
346+ static void AddDataToRng (void * data, size_t len, RNGState& rng );
319347
320348void RandAddSeedSleep ()
321349{
350+ RNGState& rng = GetRNGState ();
351+
322352 int64_t nPerfCounter1 = GetPerformanceCounter ();
323353 std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
324354 int64_t nPerfCounter2 = GetPerformanceCounter ();
325355
326356 // Combine with and update state
327- AddDataToRng (&nPerfCounter1, sizeof (nPerfCounter1));
328- AddDataToRng (&nPerfCounter2, sizeof (nPerfCounter2));
357+ AddDataToRng (&nPerfCounter1, sizeof (nPerfCounter1), rng );
358+ AddDataToRng (&nPerfCounter2, sizeof (nPerfCounter2), rng );
329359
330360 memory_cleanse (&nPerfCounter1, sizeof (nPerfCounter1));
331361 memory_cleanse (&nPerfCounter2, sizeof (nPerfCounter2));
332362}
333363
334- static void AddDataToRng (void * data, size_t len) {
335- RNGState& rng = GetRNGState ();
336-
364+ static void AddDataToRng (void * data, size_t len, RNGState& rng) {
337365 CSHA512 hasher;
338366 hasher.Write ((const unsigned char *)&len, sizeof (len));
339367 hasher.Write ((const unsigned char *)data, len);
340- unsigned char buf[64 ];
341- {
342- WAIT_LOCK (rng.m_mutex , lock);
343- hasher.Write (rng.m_state , sizeof (rng.m_state ));
344- hasher.Write ((const unsigned char *)&rng.m_counter , sizeof (rng.m_counter ));
345- ++rng.m_counter ;
346- hasher.Finalize (buf);
347- memcpy (rng.m_state , buf + 32 , 32 );
348- }
349- memory_cleanse (buf, 64 );
368+ rng.MixExtract (nullptr , 0 , std::move (hasher));
350369}
351370
352371void GetStrongRandBytes (unsigned char * out, int num)
@@ -372,14 +391,7 @@ void GetStrongRandBytes(unsigned char* out, int num)
372391 }
373392
374393 // Combine with and update state
375- {
376- WAIT_LOCK (rng.m_mutex , lock);
377- hasher.Write (rng.m_state , sizeof (rng.m_state ));
378- hasher.Write ((const unsigned char *)&rng.m_counter , sizeof (rng.m_counter ));
379- ++rng.m_counter ;
380- hasher.Finalize (buf);
381- memcpy (rng.m_state , buf + 32 , 32 );
382- }
394+ rng.MixExtract (out, num, std::move (hasher));
383395
384396 // Produce output
385397 memcpy (out, buf, num);
0 commit comments