@@ -304,6 +304,34 @@ struct RNGState {
304
304
{
305
305
InitHardwareRand ();
306
306
}
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
+ }
307
335
};
308
336
309
337
RNGState& GetRNGState ()
@@ -315,38 +343,29 @@ RNGState& GetRNGState()
315
343
}
316
344
}
317
345
318
- static void AddDataToRng (void * data, size_t len);
346
+ static void AddDataToRng (void * data, size_t len, RNGState& rng );
319
347
320
348
void RandAddSeedSleep ()
321
349
{
350
+ RNGState& rng = GetRNGState ();
351
+
322
352
int64_t nPerfCounter1 = GetPerformanceCounter ();
323
353
std::this_thread::sleep_for (std::chrono::milliseconds (1 ));
324
354
int64_t nPerfCounter2 = GetPerformanceCounter ();
325
355
326
356
// 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 );
329
359
330
360
memory_cleanse (&nPerfCounter1, sizeof (nPerfCounter1));
331
361
memory_cleanse (&nPerfCounter2, sizeof (nPerfCounter2));
332
362
}
333
363
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) {
337
365
CSHA512 hasher;
338
366
hasher.Write ((const unsigned char *)&len, sizeof (len));
339
367
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));
350
369
}
351
370
352
371
void GetStrongRandBytes (unsigned char * out, int num)
@@ -372,14 +391,7 @@ void GetStrongRandBytes(unsigned char* out, int num)
372
391
}
373
392
374
393
// 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));
383
395
384
396
// Produce output
385
397
memcpy (out, buf, num);
0 commit comments