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()16uint64_t RandUint64() { 17 uint64_t number; 18 RandBytes(&number, sizeof(number)); 19 return number; 20 } 21 RandGenerator(uint64_t range)22uint64_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()39InsecureRandomGenerator::InsecureRandomGenerator() { 40 a_ = base::RandUint64(); 41 b_ = base::RandUint64(); 42 } 43 ReseedForTesting(uint64_t seed)44void InsecureRandomGenerator::ReseedForTesting(uint64_t seed) { 45 a_ = seed; 46 b_ = seed; 47 } 48 RandUint64()49uint64_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()64uint32_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