|  | // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|  | // Use of this source code is governed by a BSD-style license that can be | 
|  | // found in the LICENSE file. | 
|  |  | 
|  | #include "quic/core/crypto/quic_random.h" | 
|  | #include <cstdint> | 
|  | #include <cstring> | 
|  |  | 
|  | #include "third_party/boringssl/src/include/openssl/rand.h" | 
|  | #include "quic/platform/api/quic_bug_tracker.h" | 
|  | #include "quic/platform/api/quic_logging.h" | 
|  | #include "common/platform/api/quiche_logging.h" | 
|  |  | 
|  | namespace quic { | 
|  |  | 
|  | 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 DefaultRandom : public QuicRandom { | 
|  | public: | 
|  | DefaultRandom() {} | 
|  | DefaultRandom(const DefaultRandom&) = delete; | 
|  | DefaultRandom& operator=(const DefaultRandom&) = delete; | 
|  | ~DefaultRandom() 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 DefaultRandom::RandBytes(void* data, size_t len) { | 
|  | RAND_bytes(reinterpret_cast<uint8_t*>(data), len); | 
|  | } | 
|  |  | 
|  | uint64_t DefaultRandom::RandUint64() { | 
|  | uint64_t value; | 
|  | RandBytes(&value, sizeof(value)); | 
|  | return value; | 
|  | } | 
|  |  | 
|  | void DefaultRandom::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 DefaultRandom::InsecureRandUint64() { | 
|  | return Xoshiro256PlusPlus(); | 
|  | } | 
|  |  | 
|  | }  // namespace | 
|  |  | 
|  | // static | 
|  | QuicRandom* QuicRandom::GetInstance() { | 
|  | static DefaultRandom* random = new DefaultRandom(); | 
|  | return random; | 
|  | } | 
|  |  | 
|  | }  // namespace quic |