1 #include "quiche/common/quiche_random.h"
2
3 #include <cstdint>
4 #include <cstring>
5
6 #include "openssl/rand.h"
7 #include "quiche/common/platform/api/quiche_logging.h"
8 namespace quiche {
9
10 namespace {
11
12 // Insecure randomness in DefaultRandom uses an implementation of
13 // xoshiro256++ 1.0 based on code in the public domain from
14 // <http://prng.di.unimi.it/xoshiro256plusplus.c>.
15
Xoshiro256InitializeRngStateMember()16 inline uint64_t Xoshiro256InitializeRngStateMember() {
17 uint64_t result;
18 RAND_bytes(reinterpret_cast<uint8_t*>(&result), sizeof(result));
19 return result;
20 }
21
Xoshiro256PlusPlusRotLeft(uint64_t x,int k)22 inline uint64_t Xoshiro256PlusPlusRotLeft(uint64_t x, int k) {
23 return (x << k) | (x >> (64 - k));
24 }
25
Xoshiro256PlusPlus()26 uint64_t Xoshiro256PlusPlus() {
27 static thread_local uint64_t rng_state[4] = {
28 Xoshiro256InitializeRngStateMember(),
29 Xoshiro256InitializeRngStateMember(),
30 Xoshiro256InitializeRngStateMember(),
31 Xoshiro256InitializeRngStateMember()};
32 const uint64_t result =
33 Xoshiro256PlusPlusRotLeft(rng_state[0] + rng_state[3], 23) + rng_state[0];
34 const uint64_t t = rng_state[1] << 17;
35 rng_state[2] ^= rng_state[0];
36 rng_state[3] ^= rng_state[1];
37 rng_state[1] ^= rng_state[2];
38 rng_state[0] ^= rng_state[3];
39 rng_state[2] ^= t;
40 rng_state[3] = Xoshiro256PlusPlusRotLeft(rng_state[3], 45);
41 return result;
42 }
43
44 class DefaultQuicheRandom : public QuicheRandom {
45 public:
DefaultQuicheRandom()46 DefaultQuicheRandom() {}
47 DefaultQuicheRandom(const DefaultQuicheRandom&) = delete;
48 DefaultQuicheRandom& operator=(const DefaultQuicheRandom&) = delete;
~DefaultQuicheRandom()49 ~DefaultQuicheRandom() override {}
50
51 // QuicRandom implementation
52 void RandBytes(void* data, size_t len) override;
53 uint64_t RandUint64() override;
54 void InsecureRandBytes(void* data, size_t len) override;
55 uint64_t InsecureRandUint64() override;
56 };
57
RandBytes(void * data,size_t len)58 void DefaultQuicheRandom::RandBytes(void* data, size_t len) {
59 RAND_bytes(reinterpret_cast<uint8_t*>(data), len);
60 }
61
RandUint64()62 uint64_t DefaultQuicheRandom::RandUint64() {
63 uint64_t value;
64 RandBytes(&value, sizeof(value));
65 return value;
66 }
67
InsecureRandBytes(void * data,size_t len)68 void DefaultQuicheRandom::InsecureRandBytes(void* data, size_t len) {
69 while (len >= sizeof(uint64_t)) {
70 uint64_t random_bytes64 = Xoshiro256PlusPlus();
71 memcpy(data, &random_bytes64, sizeof(uint64_t));
72 data = reinterpret_cast<char*>(data) + sizeof(uint64_t);
73 len -= sizeof(uint64_t);
74 }
75 if (len > 0) {
76 QUICHE_DCHECK_LT(len, sizeof(uint64_t));
77 uint64_t random_bytes64 = Xoshiro256PlusPlus();
78 memcpy(data, &random_bytes64, len);
79 }
80 }
81
InsecureRandUint64()82 uint64_t DefaultQuicheRandom::InsecureRandUint64() {
83 return Xoshiro256PlusPlus();
84 }
85
86 } // namespace
87
88 // static
GetInstance()89 QuicheRandom* QuicheRandom::GetInstance() {
90 static DefaultQuicheRandom* random = new DefaultQuicheRandom();
91 return random;
92 }
93 } // namespace quiche
94