blob: a4ff254596885261b65a67aed616cc0ba0790da5 [file] [log] [blame]
Austin Schuh36244a12019-09-21 17:52:38 -07001// 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
15#ifndef ABSL_RANDOM_INTERNAL_RANDEN_H_
16#define ABSL_RANDOM_INTERNAL_RANDEN_H_
17
18#include <cstddef>
19
20#include "absl/random/internal/platform.h"
21#include "absl/random/internal/randen_hwaes.h"
22#include "absl/random/internal/randen_slow.h"
23#include "absl/random/internal/randen_traits.h"
24
25namespace absl {
26namespace random_internal {
27
28// RANDen = RANDom generator or beetroots in Swiss German.
29// 'Strong' (well-distributed, unpredictable, backtracking-resistant) random
30// generator, faster in some benchmarks than std::mt19937_64 and pcg64_c32.
31//
32// Randen implements the basic state manipulation methods.
33class Randen {
34 public:
35 static constexpr size_t kStateBytes = RandenTraits::kStateBytes;
36 static constexpr size_t kCapacityBytes = RandenTraits::kCapacityBytes;
37 static constexpr size_t kSeedBytes = RandenTraits::kSeedBytes;
38
39 ~Randen() = default;
40
41 Randen();
42
43 // Generate updates the randen sponge. The outer portion of the sponge
44 // (kCapacityBytes .. kStateBytes) may be consumed as PRNG state.
45 template <typename T, size_t N>
46 void Generate(T (&state)[N]) const {
47 static_assert(N * sizeof(T) == kStateBytes,
48 "Randen::Generate() requires kStateBytes of state");
49#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
50 // HW AES Dispatch.
51 if (has_crypto_) {
52 RandenHwAes::Generate(keys_, state);
53 } else {
54 RandenSlow::Generate(keys_, state);
55 }
56#elif ABSL_HAVE_ACCELERATED_AES
57 // HW AES is enabled.
58 RandenHwAes::Generate(keys_, state);
59#else
60 // HW AES is disabled.
61 RandenSlow::Generate(keys_, state);
62#endif
63 }
64
65 // Absorb incorporates additional seed material into the randen sponge. After
66 // absorb returns, Generate must be called before the state may be consumed.
67 template <typename S, size_t M, typename T, size_t N>
68 void Absorb(const S (&seed)[M], T (&state)[N]) const {
69 static_assert(M * sizeof(S) == RandenTraits::kSeedBytes,
70 "Randen::Absorb() requires kSeedBytes of seed");
71
72 static_assert(N * sizeof(T) == RandenTraits::kStateBytes,
73 "Randen::Absorb() requires kStateBytes of state");
74#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
75 // HW AES Dispatch.
76 if (has_crypto_) {
77 RandenHwAes::Absorb(seed, state);
78 } else {
79 RandenSlow::Absorb(seed, state);
80 }
81#elif ABSL_HAVE_ACCELERATED_AES
82 // HW AES is enabled.
83 RandenHwAes::Absorb(seed, state);
84#else
85 // HW AES is disabled.
86 RandenSlow::Absorb(seed, state);
87#endif
88 }
89
90 private:
91 const void* keys_;
92#if ABSL_RANDOM_INTERNAL_AES_DISPATCH
93 bool has_crypto_;
94#endif
95};
96
97} // namespace random_internal
98} // namespace absl
99
100#endif // ABSL_RANDOM_INTERNAL_RANDEN_H_