| #include "quiche/common/quiche_random.h" | 
 |  | 
 | #include <cstdint> | 
 | #include <cstring> | 
 |  | 
 | #include "openssl/rand.h" | 
 | #include "quiche/common/platform/api/quiche_logging.h" | 
 | namespace quiche { | 
 |  | 
 | namespace { | 
 |  | 
 | // Insecure randomness in DefaultRandom uses an implementation of | 
 | // xoshiro256++ 1.0 based on code in the public domain from | 
 | // <http://prng.di.unimi.it/xoshiro256plusplus.c>. | 
 |  | 
 | inline uint64_t Xoshiro256InitializeRngStateMember() { | 
 |   uint64_t result; | 
 |   RAND_bytes(reinterpret_cast<uint8_t*>(&result), sizeof(result)); | 
 |   return result; | 
 | } | 
 |  | 
 | inline uint64_t Xoshiro256PlusPlusRotLeft(uint64_t x, int k) { | 
 |   return (x << k) | (x >> (64 - k)); | 
 | } | 
 |  | 
 | uint64_t Xoshiro256PlusPlus() { | 
 |   static thread_local uint64_t rng_state[4] = { | 
 |       Xoshiro256InitializeRngStateMember(), | 
 |       Xoshiro256InitializeRngStateMember(), | 
 |       Xoshiro256InitializeRngStateMember(), | 
 |       Xoshiro256InitializeRngStateMember()}; | 
 |   const uint64_t result = | 
 |       Xoshiro256PlusPlusRotLeft(rng_state[0] + rng_state[3], 23) + rng_state[0]; | 
 |   const uint64_t t = rng_state[1] << 17; | 
 |   rng_state[2] ^= rng_state[0]; | 
 |   rng_state[3] ^= rng_state[1]; | 
 |   rng_state[1] ^= rng_state[2]; | 
 |   rng_state[0] ^= rng_state[3]; | 
 |   rng_state[2] ^= t; | 
 |   rng_state[3] = Xoshiro256PlusPlusRotLeft(rng_state[3], 45); | 
 |   return result; | 
 | } | 
 |  | 
 | class DefaultQuicheRandom : public QuicheRandom { | 
 |  public: | 
 |   DefaultQuicheRandom() {} | 
 |   DefaultQuicheRandom(const DefaultQuicheRandom&) = delete; | 
 |   DefaultQuicheRandom& operator=(const DefaultQuicheRandom&) = delete; | 
 |   ~DefaultQuicheRandom() override {} | 
 |  | 
 |   // QuicRandom implementation | 
 |   void RandBytes(void* data, size_t len) override; | 
 |   uint64_t RandUint64() override; | 
 |   void InsecureRandBytes(void* data, size_t len) override; | 
 |   uint64_t InsecureRandUint64() override; | 
 | }; | 
 |  | 
 | void DefaultQuicheRandom::RandBytes(void* data, size_t len) { | 
 |   RAND_bytes(reinterpret_cast<uint8_t*>(data), len); | 
 | } | 
 |  | 
 | uint64_t DefaultQuicheRandom::RandUint64() { | 
 |   uint64_t value; | 
 |   RandBytes(&value, sizeof(value)); | 
 |   return value; | 
 | } | 
 |  | 
 | void DefaultQuicheRandom::InsecureRandBytes(void* data, size_t len) { | 
 |   while (len >= sizeof(uint64_t)) { | 
 |     uint64_t random_bytes64 = Xoshiro256PlusPlus(); | 
 |     memcpy(data, &random_bytes64, sizeof(uint64_t)); | 
 |     data = reinterpret_cast<char*>(data) + sizeof(uint64_t); | 
 |     len -= sizeof(uint64_t); | 
 |   } | 
 |   if (len > 0) { | 
 |     QUICHE_DCHECK_LT(len, sizeof(uint64_t)); | 
 |     uint64_t random_bytes64 = Xoshiro256PlusPlus(); | 
 |     memcpy(data, &random_bytes64, len); | 
 |   } | 
 | } | 
 |  | 
 | uint64_t DefaultQuicheRandom::InsecureRandUint64() { | 
 |   return Xoshiro256PlusPlus(); | 
 | } | 
 |  | 
 | }  // namespace | 
 |  | 
 | // static | 
 | QuicheRandom* QuicheRandom::GetInstance() { | 
 |   static DefaultQuicheRandom* random = new DefaultQuicheRandom(); | 
 |   return random; | 
 | } | 
 | }  // namespace quiche |