1*9356374aSAndroid Build Coastguard Worker // Copyright 2017 The Abseil Authors. 2*9356374aSAndroid Build Coastguard Worker // 3*9356374aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); 4*9356374aSAndroid Build Coastguard Worker // you may not use this file except in compliance with the License. 5*9356374aSAndroid Build Coastguard Worker // You may obtain a copy of the License at 6*9356374aSAndroid Build Coastguard Worker // 7*9356374aSAndroid Build Coastguard Worker // https://www.apache.org/licenses/LICENSE-2.0 8*9356374aSAndroid Build Coastguard Worker // 9*9356374aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software 10*9356374aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, 11*9356374aSAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12*9356374aSAndroid Build Coastguard Worker // See the License for the specific language governing permissions and 13*9356374aSAndroid Build Coastguard Worker // limitations under the License. 14*9356374aSAndroid Build Coastguard Worker 15*9356374aSAndroid Build Coastguard Worker #ifndef ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_ 16*9356374aSAndroid Build Coastguard Worker #define ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_ 17*9356374aSAndroid Build Coastguard Worker 18*9356374aSAndroid Build Coastguard Worker #include <algorithm> 19*9356374aSAndroid Build Coastguard Worker #include <cstdint> 20*9356374aSAndroid Build Coastguard Worker #include <iterator> 21*9356374aSAndroid Build Coastguard Worker #include <type_traits> 22*9356374aSAndroid Build Coastguard Worker #include <utility> 23*9356374aSAndroid Build Coastguard Worker #include <vector> 24*9356374aSAndroid Build Coastguard Worker 25*9356374aSAndroid Build Coastguard Worker #include "absl/base/macros.h" 26*9356374aSAndroid Build Coastguard Worker #include "absl/container/inlined_vector.h" 27*9356374aSAndroid Build Coastguard Worker #include "absl/meta/type_traits.h" 28*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/pool_urbg.h" 29*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/salted_seed_seq.h" 30*9356374aSAndroid Build Coastguard Worker #include "absl/random/internal/seed_material.h" 31*9356374aSAndroid Build Coastguard Worker #include "absl/types/span.h" 32*9356374aSAndroid Build Coastguard Worker 33*9356374aSAndroid Build Coastguard Worker namespace absl { 34*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_BEGIN 35*9356374aSAndroid Build Coastguard Worker namespace random_internal { 36*9356374aSAndroid Build Coastguard Worker 37*9356374aSAndroid Build Coastguard Worker // RandenPoolSeedSeq is a custom seed sequence type where generate() fills the 38*9356374aSAndroid Build Coastguard Worker // provided buffer via the RandenPool entropy source. 39*9356374aSAndroid Build Coastguard Worker class RandenPoolSeedSeq { 40*9356374aSAndroid Build Coastguard Worker private: 41*9356374aSAndroid Build Coastguard Worker struct ContiguousTag {}; 42*9356374aSAndroid Build Coastguard Worker struct BufferTag {}; 43*9356374aSAndroid Build Coastguard Worker 44*9356374aSAndroid Build Coastguard Worker // Generate random unsigned values directly into the buffer. 45*9356374aSAndroid Build Coastguard Worker template <typename Contiguous> generate_impl(ContiguousTag,Contiguous begin,Contiguous end)46*9356374aSAndroid Build Coastguard Worker void generate_impl(ContiguousTag, Contiguous begin, Contiguous end) { 47*9356374aSAndroid Build Coastguard Worker const size_t n = static_cast<size_t>(std::distance(begin, end)); 48*9356374aSAndroid Build Coastguard Worker auto* a = &(*begin); 49*9356374aSAndroid Build Coastguard Worker RandenPool<uint8_t>::Fill( 50*9356374aSAndroid Build Coastguard Worker absl::MakeSpan(reinterpret_cast<uint8_t*>(a), sizeof(*a) * n)); 51*9356374aSAndroid Build Coastguard Worker } 52*9356374aSAndroid Build Coastguard Worker 53*9356374aSAndroid Build Coastguard Worker // Construct a buffer of size n and fill it with values, then copy 54*9356374aSAndroid Build Coastguard Worker // those values into the seed iterators. 55*9356374aSAndroid Build Coastguard Worker template <typename RandomAccessIterator> generate_impl(BufferTag,RandomAccessIterator begin,RandomAccessIterator end)56*9356374aSAndroid Build Coastguard Worker void generate_impl(BufferTag, RandomAccessIterator begin, 57*9356374aSAndroid Build Coastguard Worker RandomAccessIterator end) { 58*9356374aSAndroid Build Coastguard Worker const size_t n = std::distance(begin, end); 59*9356374aSAndroid Build Coastguard Worker absl::InlinedVector<uint32_t, 8> data(n, 0); 60*9356374aSAndroid Build Coastguard Worker RandenPool<uint32_t>::Fill(absl::MakeSpan(data.begin(), data.end())); 61*9356374aSAndroid Build Coastguard Worker std::copy(std::begin(data), std::end(data), begin); 62*9356374aSAndroid Build Coastguard Worker } 63*9356374aSAndroid Build Coastguard Worker 64*9356374aSAndroid Build Coastguard Worker public: 65*9356374aSAndroid Build Coastguard Worker using result_type = uint32_t; 66*9356374aSAndroid Build Coastguard Worker size()67*9356374aSAndroid Build Coastguard Worker size_t size() { return 0; } 68*9356374aSAndroid Build Coastguard Worker 69*9356374aSAndroid Build Coastguard Worker template <typename OutIterator> param(OutIterator)70*9356374aSAndroid Build Coastguard Worker void param(OutIterator) const {} 71*9356374aSAndroid Build Coastguard Worker 72*9356374aSAndroid Build Coastguard Worker template <typename RandomAccessIterator> generate(RandomAccessIterator begin,RandomAccessIterator end)73*9356374aSAndroid Build Coastguard Worker void generate(RandomAccessIterator begin, RandomAccessIterator end) { 74*9356374aSAndroid Build Coastguard Worker // RandomAccessIterator must be assignable from uint32_t 75*9356374aSAndroid Build Coastguard Worker if (begin != end) { 76*9356374aSAndroid Build Coastguard Worker using U = typename std::iterator_traits<RandomAccessIterator>::value_type; 77*9356374aSAndroid Build Coastguard Worker // ContiguousTag indicates the common case of a known contiguous buffer, 78*9356374aSAndroid Build Coastguard Worker // which allows directly filling the buffer. In C++20, 79*9356374aSAndroid Build Coastguard Worker // std::contiguous_iterator_tag provides a mechanism for testing this 80*9356374aSAndroid Build Coastguard Worker // capability, however until Abseil's support requirements allow us to 81*9356374aSAndroid Build Coastguard Worker // assume C++20, limit checks to a few common cases. 82*9356374aSAndroid Build Coastguard Worker using TagType = absl::conditional_t< 83*9356374aSAndroid Build Coastguard Worker (std::is_pointer<RandomAccessIterator>::value || 84*9356374aSAndroid Build Coastguard Worker std::is_same<RandomAccessIterator, 85*9356374aSAndroid Build Coastguard Worker typename std::vector<U>::iterator>::value), 86*9356374aSAndroid Build Coastguard Worker ContiguousTag, BufferTag>; 87*9356374aSAndroid Build Coastguard Worker 88*9356374aSAndroid Build Coastguard Worker generate_impl(TagType{}, begin, end); 89*9356374aSAndroid Build Coastguard Worker } 90*9356374aSAndroid Build Coastguard Worker } 91*9356374aSAndroid Build Coastguard Worker }; 92*9356374aSAndroid Build Coastguard Worker 93*9356374aSAndroid Build Coastguard Worker // Each instance of NonsecureURBGBase<URBG> will be seeded by variates produced 94*9356374aSAndroid Build Coastguard Worker // by a thread-unique URBG-instance. 95*9356374aSAndroid Build Coastguard Worker template <typename URBG, typename Seeder = RandenPoolSeedSeq> 96*9356374aSAndroid Build Coastguard Worker class NonsecureURBGBase { 97*9356374aSAndroid Build Coastguard Worker public: 98*9356374aSAndroid Build Coastguard Worker using result_type = typename URBG::result_type; 99*9356374aSAndroid Build Coastguard Worker 100*9356374aSAndroid Build Coastguard Worker // Default constructor NonsecureURBGBase()101*9356374aSAndroid Build Coastguard Worker NonsecureURBGBase() : urbg_(ConstructURBG()) {} 102*9356374aSAndroid Build Coastguard Worker 103*9356374aSAndroid Build Coastguard Worker // Copy disallowed, move allowed. 104*9356374aSAndroid Build Coastguard Worker NonsecureURBGBase(const NonsecureURBGBase&) = delete; 105*9356374aSAndroid Build Coastguard Worker NonsecureURBGBase& operator=(const NonsecureURBGBase&) = delete; 106*9356374aSAndroid Build Coastguard Worker NonsecureURBGBase(NonsecureURBGBase&&) = default; 107*9356374aSAndroid Build Coastguard Worker NonsecureURBGBase& operator=(NonsecureURBGBase&&) = default; 108*9356374aSAndroid Build Coastguard Worker 109*9356374aSAndroid Build Coastguard Worker // Constructor using a seed 110*9356374aSAndroid Build Coastguard Worker template <class SSeq, typename = typename absl::enable_if_t< 111*9356374aSAndroid Build Coastguard Worker !std::is_same<SSeq, NonsecureURBGBase>::value>> NonsecureURBGBase(SSeq && seq)112*9356374aSAndroid Build Coastguard Worker explicit NonsecureURBGBase(SSeq&& seq) 113*9356374aSAndroid Build Coastguard Worker : urbg_(ConstructURBG(std::forward<SSeq>(seq))) {} 114*9356374aSAndroid Build Coastguard Worker 115*9356374aSAndroid Build Coastguard Worker // Note: on MSVC, min() or max() can be interpreted as MIN() or MAX(), so we 116*9356374aSAndroid Build Coastguard Worker // enclose min() or max() in parens as (min)() and (max)(). 117*9356374aSAndroid Build Coastguard Worker // Additionally, clang-format requires no space before this construction. 118*9356374aSAndroid Build Coastguard Worker 119*9356374aSAndroid Build Coastguard Worker // NonsecureURBGBase::min() result_type(min)120*9356374aSAndroid Build Coastguard Worker static constexpr result_type(min)() { return (URBG::min)(); } 121*9356374aSAndroid Build Coastguard Worker 122*9356374aSAndroid Build Coastguard Worker // NonsecureURBGBase::max() result_type(max)123*9356374aSAndroid Build Coastguard Worker static constexpr result_type(max)() { return (URBG::max)(); } 124*9356374aSAndroid Build Coastguard Worker 125*9356374aSAndroid Build Coastguard Worker // NonsecureURBGBase::operator()() operator()126*9356374aSAndroid Build Coastguard Worker result_type operator()() { return urbg_(); } 127*9356374aSAndroid Build Coastguard Worker 128*9356374aSAndroid Build Coastguard Worker // NonsecureURBGBase::discard() discard(unsigned long long values)129*9356374aSAndroid Build Coastguard Worker void discard(unsigned long long values) { // NOLINT(runtime/int) 130*9356374aSAndroid Build Coastguard Worker urbg_.discard(values); 131*9356374aSAndroid Build Coastguard Worker } 132*9356374aSAndroid Build Coastguard Worker 133*9356374aSAndroid Build Coastguard Worker bool operator==(const NonsecureURBGBase& other) const { 134*9356374aSAndroid Build Coastguard Worker return urbg_ == other.urbg_; 135*9356374aSAndroid Build Coastguard Worker } 136*9356374aSAndroid Build Coastguard Worker 137*9356374aSAndroid Build Coastguard Worker bool operator!=(const NonsecureURBGBase& other) const { 138*9356374aSAndroid Build Coastguard Worker return !(urbg_ == other.urbg_); 139*9356374aSAndroid Build Coastguard Worker } 140*9356374aSAndroid Build Coastguard Worker 141*9356374aSAndroid Build Coastguard Worker private: ConstructURBG()142*9356374aSAndroid Build Coastguard Worker static URBG ConstructURBG() { 143*9356374aSAndroid Build Coastguard Worker Seeder seeder; 144*9356374aSAndroid Build Coastguard Worker return URBG(seeder); 145*9356374aSAndroid Build Coastguard Worker } 146*9356374aSAndroid Build Coastguard Worker 147*9356374aSAndroid Build Coastguard Worker template <typename SSeq> ConstructURBG(SSeq && seq)148*9356374aSAndroid Build Coastguard Worker static URBG ConstructURBG(SSeq&& seq) { // NOLINT(runtime/references) 149*9356374aSAndroid Build Coastguard Worker auto salted_seq = 150*9356374aSAndroid Build Coastguard Worker random_internal::MakeSaltedSeedSeq(std::forward<SSeq>(seq)); 151*9356374aSAndroid Build Coastguard Worker return URBG(salted_seq); 152*9356374aSAndroid Build Coastguard Worker } 153*9356374aSAndroid Build Coastguard Worker 154*9356374aSAndroid Build Coastguard Worker URBG urbg_; 155*9356374aSAndroid Build Coastguard Worker }; 156*9356374aSAndroid Build Coastguard Worker 157*9356374aSAndroid Build Coastguard Worker } // namespace random_internal 158*9356374aSAndroid Build Coastguard Worker ABSL_NAMESPACE_END 159*9356374aSAndroid Build Coastguard Worker } // namespace absl 160*9356374aSAndroid Build Coastguard Worker 161*9356374aSAndroid Build Coastguard Worker #endif // ABSL_RANDOM_INTERNAL_NONSECURE_BASE_H_ 162