MCKL
Monte Carlo Kernel Library
aes_aesni.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/aes_aesni.hpp
3 //----------------------------------------------------------------------------
4 // MCKL: Monte Carlo Kernel Library
5 //----------------------------------------------------------------------------
6 // Copyright (c) 2013-2018, Yan Zhou
7 // All rights reserved.
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions are met:
11 //
12 // Redistributions of source code must retain the above copyright notice,
13 // this list of conditions and the following disclaimer.
14 //
15 // Redistributions in binary form must reproduce the above copyright notice,
16 // this list of conditions and the following disclaimer in the documentation
17 // and/or other materials provided with the distribution.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS
20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 // POSSIBILITY OF SUCH DAMAGE.
30 //============================================================================
31 
32 #ifndef MCKL_RANDOM_INTERNAL_AES_AESNI_HPP
33 #define MCKL_RANDOM_INTERNAL_AES_AESNI_HPP
34 
43 
44 MCKL_PUSH_GCC_WARNING("-Wignored-attributes")
45 
46 namespace mckl {
47 
48 namespace internal {
49 
50 template <typename KeySeqType>
52 {
53  public:
54  static void eval(const void *plain, void *cipher, const KeySeqType &ks)
55  {
56  const std::array<__m128i, rounds_ + 1> rk(ks.get());
57 
58  __m128i s = _mm_loadu_si128(reinterpret_cast<const __m128i *>(plain));
59  s = _mm_xor_si128(s, std::get<0>(rk));
61  s = _mm_aesenclast_si128(s, std::get<rounds_>(rk));
62  _mm_storeu_si128(reinterpret_cast<__m128i *>(cipher), s);
63  }
64 
65  template <typename ResultType>
66  static void eval(
67  Counter<std::uint32_t, 4> &ctr, ResultType *r, const KeySeqType &ks)
68  {
69  const std::array<__m128i, rounds_ + 1> rk(ks.get());
70 
72  __m128i s =
73  _mm_loadu_si128(reinterpret_cast<const __m128i *>(ctr.data()));
74  s = _mm_xor_si128(s, std::get<0>(rk));
76  s = _mm_aesenclast_si128(s, std::get<rounds_>(rk));
77  _mm_storeu_si128(reinterpret_cast<__m128i *>(r), s);
78  }
79 
80  template <typename ResultType>
81  static void eval(Counter<std::uint32_t, 4> &ctr, std::size_t n,
82  ResultType *r, const KeySeqType &ks)
83  {
84  constexpr std::size_t S = 8;
85  constexpr std::size_t N = S;
86  constexpr std::size_t R = sizeof(__m128i) / sizeof(ResultType);
87 
88  const std::array<__m128i, rounds_ + 1> rk(ks.get());
89  while (n >= N) {
90  std::array<__m128i, S> s;
92  MCKL_INLINE_CALL xor_si128(s, std::get<0>(rk));
94  MCKL_INLINE_CALL aesenclast_si128(s, std::get<rounds_>(rk));
95  std::memcpy(r, s.data(), sizeof(__m128i) * N);
96  n -= N;
97  r += N * R;
98  }
99 
100  alignas(MCKL_ALIGNMENT) std::array<ResultType, N * R> t;
101  for (std::size_t i = 0; i != n; ++i) {
103  __m128i s =
104  _mm_loadu_si128(reinterpret_cast<const __m128i *>(ctr.data()));
105  s = _mm_xor_si128(s, std::get<0>(rk));
107  s = _mm_aesenclast_si128(s, std::get<rounds_>(rk));
108  _mm_store_si128(reinterpret_cast<__m128i *>(t.data() + i * R), s);
109  }
110  std::memcpy(r, t.data(), sizeof(__m128i) * n);
111  }
112 
113  private:
114  static constexpr std::size_t rounds_ = KeySeqType::rounds();
115 
116  template <std::size_t>
117  static void round(
118  __m128i &, const std::array<__m128i, rounds_ + 1> &, std::false_type)
119  {
120  }
121 
122  template <std::size_t N>
123  static void round(
124  __m128i &s, const std::array<__m128i, rounds_ + 1> &rk, std::true_type)
125  {
127  }
128 
129  template <std::size_t, std::size_t S>
130  static void round(std::array<__m128i, S> &,
131  const std::array<__m128i, rounds_ + 1> &, std::false_type)
132  {
133  }
134 
135  template <std::size_t N, std::size_t S>
136  static void round(std::array<__m128i, S> &s,
137  const std::array<__m128i, rounds_ + 1> &rk, std::true_type)
138  {
140  }
141 
142  template <std::size_t N>
143  MCKL_INLINE static void rbox(
144  __m128i &s, const std::array<__m128i, rounds_ + 1> &rk)
145  {
146  rbox<N>(s, rk, std::integral_constant<bool, (N > 0 && N < rounds_)>());
147  }
148 
149  template <std::size_t>
150  static void rbox(
151  __m128i &, const std::array<__m128i, rounds_ + 1> &, std::false_type)
152  {
153  }
154 
155  template <std::size_t N>
156  static void rbox(
157  __m128i &s, const std::array<__m128i, rounds_ + 1> &rk, std::true_type)
158  {
159  s = _mm_aesenc_si128(s, std::get<N>(rk));
160  }
161 
162  template <std::size_t N, std::size_t S>
163  MCKL_INLINE static void rbox(
164  std::array<__m128i, S> &s, const std::array<__m128i, rounds_ + 1> &rk)
165  {
166  rbox<N>(s, rk, std::integral_constant<bool, (N > 0 && N < rounds_)>());
167  }
168 
169  template <std::size_t, std::size_t S>
170  static void rbox(std::array<__m128i, S> &,
171  const std::array<__m128i, rounds_ + 1> &, std::false_type)
172  {
173  }
174 
175  template <std::size_t N, std::size_t S>
176  static void rbox(std::array<__m128i, S> &s,
177  const std::array<__m128i, rounds_ + 1> &rk, std::true_type)
178  {
179  aesenc_si128(s, std::get<N>(rk));
180  }
181 }; // class AESGeneratorAESNIImpl
182 
183 template <>
185  : public AES128GeneratorAESNIImpl
186 {
187 }; // class AESGeneratorAESNIImpl
188 
189 template <>
191  : public AES192GeneratorAESNIImpl
192 {
193 }; // class AESGeneratorAESNIImpl
194 
195 template <>
197  : public AES256GeneratorAESNIImpl
198 {
199 }; // class AESGeneratorAESNIImpl
200 
201 template <typename Constants>
204  : public ARSGeneratorAESNIImpl<Constants>
205 {
206 }; // class AESGeneratorAESNIImpl
207 
208 } // namespace internal
209 
210 } // namespace mckl
211 
213 
214 #endif // MCKL_RANDOM_INTERNAL_AES_AESNI_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
void increment_si128(std::array< T, K > &ctr, std::array< __m128i, S > &s, std::false_type)
void round(std::size_t n, const float *a, float *y)
Definition: vmf.hpp:310
#define MCKL_INLINE_CALL
Definition: intel.h:142
typename internal::CounterImpl< T, K >::type Counter
A counter type with the same width as std::array<T, K> but with possibly fewer elements.
Definition: increment.hpp:104
static void eval(const void *plain, void *cipher, const KeySeqType &ks)
Definition: aes_aesni.hpp:54
#define MCKL_RANDOM_INTERNAL_AES_UNROLL_ROUND(N, s, rk)
Definition: aes_unroll.hpp:53
void increment(std::array< T, K > &ctr, std::integral_constant< T, NSkip >)
Increment a counter by given steps.
static void eval(Counter< std::uint32_t, 4 > &ctr, ResultType *r, const KeySeqType &ks)
Definition: aes_aesni.hpp:66
Definition: mcmc.hpp:40
#define MCKL_ALIGNMENT
The default alignment for scalar type.
Definition: config.h:187
#define MCKL_INLINE
Definition: clang.h:147
#define MCKL_RANDOM_INTERNAL_AES_UNROLL(N, s, rk)
Definition: aes_unroll.hpp:35
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79
static void eval(Counter< std::uint32_t, 4 > &ctr, std::size_t n, ResultType *r, const KeySeqType &ks)
Definition: aes_aesni.hpp:81