1 // Copyright 2011 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "partition_alloc/partition_alloc_base/rand_util.h"
6 
7 #include <climits>
8 #include <cmath>
9 #include <cstdint>
10 #include <limits>
11 
12 #include "partition_alloc/partition_alloc_base/check.h"
13 
14 namespace partition_alloc::internal::base {
15 
RandUint64()16 uint64_t RandUint64() {
17   uint64_t number;
18   RandBytes(&number, sizeof(number));
19   return number;
20 }
21 
RandGenerator(uint64_t range)22 uint64_t RandGenerator(uint64_t range) {
23   PA_BASE_DCHECK(range > 0u);
24   // We must discard random results above this number, as they would
25   // make the random generator non-uniform (consider e.g. if
26   // MAX_UINT64 was 7 and |range| was 5, then a result of 1 would be twice
27   // as likely as a result of 3 or 4).
28   uint64_t max_acceptable_value =
29       (std::numeric_limits<uint64_t>::max() / range) * range - 1;
30 
31   uint64_t value;
32   do {
33     value = base::RandUint64();
34   } while (value > max_acceptable_value);
35 
36   return value % range;
37 }
38 
InsecureRandomGenerator()39 InsecureRandomGenerator::InsecureRandomGenerator() {
40   a_ = base::RandUint64();
41   b_ = base::RandUint64();
42 }
43 
ReseedForTesting(uint64_t seed)44 void InsecureRandomGenerator::ReseedForTesting(uint64_t seed) {
45   a_ = seed;
46   b_ = seed;
47 }
48 
RandUint64()49 uint64_t InsecureRandomGenerator::RandUint64() {
50   // Using XorShift128+, which is simple and widely used. See
51   // https://en.wikipedia.org/wiki/Xorshift#xorshift+ for details.
52   uint64_t t = a_;
53   const uint64_t s = b_;
54 
55   a_ = s;
56   t ^= t << 23;
57   t ^= t >> 17;
58   t ^= s ^ (s >> 26);
59   b_ = t;
60 
61   return t + s;
62 }
63 
RandUint32()64 uint32_t InsecureRandomGenerator::RandUint32() {
65   // The generator usually returns an uint64_t, truncate it.
66   //
67   // It is noted in this paper (https://arxiv.org/abs/1810.05313) that the
68   // lowest 32 bits fail some statistical tests from the Big Crush
69   // suite. Use the higher ones instead.
70   return this->RandUint64() >> 32;
71 }
72 
73 }  // namespace partition_alloc::internal::base
74