nonsecure_base.h 5.4 KB

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