Extract up to 32 bytes of entropy from the RNG state, mixing in new entropy from hasher. * * If this function has never been called with strong_seed = true, false is returned. */
| 407 | * If this function has never been called with strong_seed = true, false is returned. |
| 408 | */ |
| 409 | bool MixExtract(unsigned char* out, size_t num, CSHA512&& hasher, bool strong_seed) noexcept |
| 410 | { |
| 411 | assert(num <= 32); |
| 412 | unsigned char buf[64]; |
| 413 | static_assert(sizeof(buf) == CSHA512::OUTPUT_SIZE, "Buffer needs to have hasher's output size"); |
| 414 | bool ret; |
| 415 | { |
| 416 | LOCK(m_mutex); |
| 417 | ret = (m_strongly_seeded |= strong_seed); |
| 418 | // Write the current state of the RNG into the hasher |
| 419 | hasher.Write(m_state, 32); |
| 420 | // Write a new counter number into the state |
| 421 | hasher.Write((const unsigned char*)&m_counter, sizeof(m_counter)); |
| 422 | ++m_counter; |
| 423 | // Finalize the hasher |
| 424 | hasher.Finalize(buf); |
| 425 | // Store the last 32 bytes of the hash output as new RNG state. |
| 426 | memcpy(m_state, buf + 32, 32); |
| 427 | } |
| 428 | // If desired, copy (up to) the first 32 bytes of the hash output as output. |
| 429 | if (num) { |
| 430 | assert(out != nullptr); |
| 431 | memcpy(out, buf, num); |
| 432 | } |
| 433 | // Best effort cleanup of internal state |
| 434 | hasher.Reset(); |
| 435 | memory_cleanse(buf, 64); |
| 436 | return ret; |
| 437 | } |
| 438 | }; |
| 439 | |
| 440 | RNGState& GetRNGState() noexcept |
no test coverage detected