32 #ifndef VSMC_RNG_AES_NI_HPP 33 #define VSMC_RNG_AES_NI_HPP 37 #include <wmmintrin.h> 39 #define VSMC_STATIC_ASSERT_RNG_AES_NI_BLOCKS(Blocks) \ 41 (Blocks > 0), "**AESNIGenerator** USED WITH ZERO BLOCKS") 43 #define VSMC_STATIC_ASSERT_RNG_AES_NI_RESULT_TYPE(ResultType) \ 44 VSMC_STATIC_ASSERT((std::is_unsigned<ResultType>::value), \ 45 "**AESNIGenerator USED WITH ResultType NOT AN UNSIGNED INTEGER") 47 #define VSMC_STATIC_ASSERT_RNG_AES_NI \ 48 VSMC_STATIC_ASSERT_RNG_AES_NI_BLOCKS(Blocks); \ 49 VSMC_STATIC_ASSERT_RNG_AES_NI_RESULT_TYPE(ResultType); 56 template <
typename ResultType,
typename KeySeqType, std::size_t Rounds,
62 using ctr_type = std::array<ResultType, M128I<ResultType>::size()>;
63 using key_type =
typename KeySeqType::key_type;
67 static constexpr std::size_t
size()
69 return Blocks * M128I<ResultType>::size();
75 std::array<
result_type, Blocks * M128I<ResultType>::size()> &buffer)
78 std::array<M128I<>, Blocks> state;
79 std::array<ctr_type, Blocks> ctr_block;
80 std::array<result_type, size()> result;
83 std::array<M128I<>, Rounds + 1> rk;
86 enc_first(buf.state, rk);
88 buf.state, rk, std::integral_constant<bool, 1 < Rounds>());
89 enc_last(buf.state, rk);
96 const std::size_t K = 8;
97 const std::size_t M = K * M128I<ResultType>::size();
98 const std::size_t m = n / M;
99 std::array<M128I<>, Rounds + 1> rk;
101 increment(ctr, m * K, reinterpret_cast<ctr_type *>(r));
102 std::array<M128I<>, K> *s =
103 reinterpret_cast<std::array<M128I<>, K
> *>(r);
104 for (std::size_t i = 0; i != m; ++i) {
106 enc_round<1>(s[i], rk, std::integral_constant<bool, 1 < Rounds>());
118 template <std::
size_t K>
119 void enc_first(std::array<M128I<>, K> &state,
120 const std::array<M128I<>, Rounds + 1> &rk)
const 122 enc_first<0>(state, rk, std::true_type());
125 template <std::
size_t, std::
size_t K>
126 void enc_first(std::array<M128I<>, K> &,
127 const std::array<M128I<>, Rounds + 1> &, std::false_type)
const 131 template <std::
size_t B, std::
size_t K>
132 void enc_first(std::array<M128I<>, K> &state,
133 const std::array<M128I<>, Rounds + 1> &rk, std::true_type)
const 135 std::get<B>(state) ^= std::get<0>(rk);
136 enc_first<B + 1>(state, rk, std::integral_constant<bool, B + 1 < K>());
139 template <std::
size_t, std::
size_t K>
140 void enc_round(std::array<M128I<>, K> &,
141 const std::array<M128I<>, Rounds + 1> &, std::false_type)
const 145 template <std::
size_t N, std::
size_t K>
146 void enc_round(std::array<M128I<>, K> &state,
147 const std::array<M128I<>, Rounds + 1> &rk, std::true_type)
const 149 enc_round_block<0, N>(state, rk, std::true_type());
151 state, rk, std::integral_constant<bool, N + 1 < Rounds>());
154 template <std::
size_t, std::
size_t, std::
size_t K>
155 void enc_round_block(std::array<M128I<>, K> &,
156 const std::array<M128I<>, Rounds + 1> &, std::false_type)
const 160 template <std::
size_t B, std::
size_t N, std::
size_t K>
161 void enc_round_block(std::array<M128I<>, K> &state,
162 const std::array<M128I<>, Rounds + 1> &rk, std::true_type)
const 164 std::get<B>(state) = _mm_aesenc_si128(
165 std::get<B>(state).value(), std::get<N>(rk).value());
166 enc_round_block<B + 1, N>(
167 state, rk, std::integral_constant<bool, B + 1 < K>());
170 template <std::
size_t K>
171 void enc_last(std::array<M128I<>, K> &state,
172 const std::array<M128I<>, Rounds + 1> &rk)
const 174 enc_last<0>(state, rk, std::true_type());
177 template <std::
size_t, std::
size_t K>
178 void enc_last(std::array<M128I<>, K> &,
179 const std::array<M128I<>, Rounds + 1> &, std::false_type)
const 183 template <std::
size_t B, std::
size_t K>
184 void enc_last(std::array<M128I<>, K> &state,
185 const std::array<M128I<>, Rounds + 1> &rk, std::true_type)
const 187 std::get<B>(state) = _mm_aesenclast_si128(
188 std::get<B>(state).value(), std::get<Rounds>(rk).value());
189 enc_last<B + 1>(state, rk, std::integral_constant<bool, B + 1 < K>());
195 template <
typename ResultType,
typename KeySeqType, std::size_t Rounds,
202 #endif // VSMC_RNG_AES_NI_HPP
void increment(std::array< T, K > &ctr)
Increment a counter by one.
Counter based RNG engine.
void operator()(ctr_type &ctr, const key_type &key, std::array< result_type, Blocks *M128I< ResultType >::size()> &buffer)
static constexpr std::size_t size()
std::array< ResultType, M128I< ResultType >::size()> ctr_type
void reset(const key_type &key)
typename KeySeqType::key_type key_type
std::size_t operator()(ctr_type &ctr, const key_type &key, std::size_t n, result_type *r) const
#define VSMC_STATIC_ASSERT_RNG_AES_NI
RNG generator using AES-NI instructions.