xref: /aosp_15_r20/external/cronet/net/third_party/quiche/src/quiche/common/quiche_random.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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