MCKL
Monte Carlo Kernel Library
aes_aesni_aes256.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/aes_aesni_aes256.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_AES256_HPP
33 #define MCKL_RANDOM_INTERNAL_AES_AESNI_AES256_HPP
34 
39 
40 MCKL_PUSH_GCC_WARNING("-Wignored-attributes")
41 
42 namespace mckl {
43 
44 namespace internal {
45 
47 {
48  public:
49  using key_type = std::array<std::uint32_t, 8>;
50  using rk_type = __m128i;
51 
52  template <std::size_t Rp1>
53  static key_type key(const std::array<__m128i, Rp1> &rk)
54  {
55  key_type key;
56  std::memcpy(key.data(), rk.data(), sizeof(key_type));
57 
58  return key;
59  }
60 
61  template <std::size_t Rp1>
62  void operator()(const key_type &key, std::array<__m128i, Rp1> &rk)
63  {
64  xmm1_ = _mm_set_epi32(static_cast<int>(std::get<3>(key)),
65  static_cast<int>(std::get<2>(key)),
66  static_cast<int>(std::get<1>(key)),
67  static_cast<int>(std::get<0>(key)));
68  xmm3_ = _mm_set_epi32(static_cast<int>(std::get<7>(key)),
69  static_cast<int>(std::get<6>(key)),
70  static_cast<int>(std::get<5>(key)),
71  static_cast<int>(std::get<4>(key)));
72  std::get<0>(rk) = xmm1_;
73  std::get<1>(rk) = xmm3_;
74  generate<2>(rk, std::integral_constant<bool, 2 < Rp1>());
75  }
76 
77  private:
78  __m128i xmm1_;
79  __m128i xmm2_;
80  __m128i xmm3_;
81  __m128i xmm4_;
82 
83  template <std::size_t, std::size_t Rp1>
84  void generate(std::array<__m128i, Rp1> &, std::false_type)
85  {
86  }
87 
88  template <std::size_t N, std::size_t Rp1>
89  void generate(std::array<__m128i, Rp1> &rk, std::true_type)
90  {
91  generate_key<N>(rk, std::integral_constant<bool, N % 2 == 0>());
92  generate<N + 1>(rk, std::integral_constant<bool, N + 1 < Rp1>());
93  }
94 
95  template <std::size_t N, std::size_t Rp1>
96  void generate_key(std::array<__m128i, Rp1> &rk, std::true_type)
97  {
98  xmm2_ = aeskeygenassist_si128<(N / 2) % 256>(xmm3_);
99  expand_key(std::true_type());
100  std::get<N>(rk) = xmm1_;
101  }
102 
103  template <std::size_t N, std::size_t Rp1>
104  void generate_key(std::array<__m128i, Rp1> &rk, std::false_type)
105  {
106  xmm4_ = aeskeygenassist_si128<0>(xmm1_);
107  expand_key(std::false_type());
108  std::get<N>(rk) = xmm3_;
109  }
110 
111  void expand_key(std::true_type)
112  {
113  xmm2_ = _mm_shuffle_epi32(xmm2_, 0xFF);
114  xmm4_ = _mm_slli_si128(xmm1_, 4);
115  xmm1_ = _mm_xor_si128(xmm1_, xmm4_);
116  xmm4_ = _mm_slli_si128(xmm4_, 4);
117  xmm1_ = _mm_xor_si128(xmm1_, xmm4_);
118  xmm4_ = _mm_slli_si128(xmm4_, 4);
119  xmm1_ = _mm_xor_si128(xmm1_, xmm4_);
120  xmm1_ = _mm_xor_si128(xmm1_, xmm2_);
121  }
122 
123  void expand_key(std::false_type)
124  {
125  xmm2_ = _mm_shuffle_epi32(xmm4_, 0xAA);
126  xmm4_ = _mm_slli_si128(xmm3_, 4);
127  xmm3_ = _mm_xor_si128(xmm3_, xmm4_);
128  xmm4_ = _mm_slli_si128(xmm4_, 4);
129  xmm3_ = _mm_xor_si128(xmm3_, xmm4_);
130  xmm4_ = _mm_slli_si128(xmm4_, 4);
131  xmm3_ = _mm_xor_si128(xmm3_, xmm4_);
132  xmm3_ = _mm_xor_si128(xmm3_, xmm2_);
133  }
134 }; // class AES256KeySeqGeneratorAESNIImpl
135 
137 {
139 
140  public:
141  static void eval(const void *plain, void *cipher, const KeySeqType &ks)
142  {
143  __m128i xmm0 =
144  _mm_loadu_si128(reinterpret_cast<const __m128i *>(plain));
145 
146  xmm0 = _mm_xor_si128(xmm0, ks.get<0x0>());
147  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x1>());
148  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x2>());
149  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x3>());
150  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x4>());
151  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x5>());
152  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x6>());
153  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x7>());
154  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x8>());
155  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x9>());
156  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xA>());
157  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xB>());
158  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xC>());
159  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xD>());
160  xmm0 = _mm_aesenclast_si128(xmm0, ks.get<0xE>());
161 
162  _mm_storeu_si128(reinterpret_cast<__m128i *>(cipher), xmm0);
163  }
164 
165  template <typename ResultType>
166  static void eval(
167  std::array<std::uint64_t, 2> &ctr, ResultType *r, const KeySeqType &ks)
168  {
170 
171  __m128i xmm0 =
172  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
173  static_cast<MCKL_INT64>(std::get<0>(ctr)));
174 
175  xmm0 = _mm_xor_si128(xmm0, ks.get<0x0>());
176  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x1>());
177  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x2>());
178  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x3>());
179  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x4>());
180  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x5>());
181  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x6>());
182  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x7>());
183  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x8>());
184  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x9>());
185  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xA>());
186  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xB>());
187  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xC>());
188  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xD>());
189  xmm0 = _mm_aesenclast_si128(xmm0, ks.get<0xE>());
190 
191  _mm_storeu_si128(reinterpret_cast<__m128i *>(r), xmm0);
192  }
193 
195 
196  private:
197  template <typename ResultType>
198  static void eval_kernel(std::array<std::uint64_t, 2> &ctr, std::size_t n,
199  ResultType *r, const KeySeqType &ks)
200  {
201 #if MCKL_USE_ASM_LIBRARY
202 #if MCKL_USE_AVX2
203  mckl_aes256_aesni_avx2_kernel(ctr.data(), n, r, ks.get().data());
204 #else
205  mckl_aes256_aesni_sse2_kernel(ctr.data(), n, r, ks.get().data());
206 #endif
207 #else // MCKL_USE_ASM_LIBRARY
208  constexpr std::size_t S = 8;
209  constexpr std::size_t N = S;
210 
211  const std::array<__m128i, KeySeqType::rounds() + 1> rk(ks.get());
212 
213  __m128i xmmc =
214  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
215  static_cast<MCKL_INT64>(std::get<0>(ctr)));
216  ctr.front() += n;
217 
218  __m128i *rptr = reinterpret_cast<__m128i *>(r);
219  while (n != 0) {
220  __m128i xmm0 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 1));
221  __m128i xmm1 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 2));
222  __m128i xmm2 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 3));
223  __m128i xmm3 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 4));
224  __m128i xmm4 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 5));
225  __m128i xmm5 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 6));
226  __m128i xmm6 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 7));
227  __m128i xmm7 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 8));
228  xmmc = xmm7;
229 
230  MCKL_RANDOM_INTERNAL_AES_AESNI_ENCFIRST(std::get<0x0>(rk))
231  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x1>(rk))
232  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x2>(rk))
233  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x3>(rk))
234  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x4>(rk))
235  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x5>(rk))
236  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x6>(rk))
237  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x7>(rk))
238  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x8>(rk))
239  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x9>(rk))
240  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0xA>(rk))
241  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0xB>(rk))
242  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0xC>(rk))
243  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0xD>(rk))
244  MCKL_RANDOM_INTERNAL_AES_AESNI_ENCLAST(std::get<0xE>(rk))
246  }
247 #endif // MCKL_USE_ASM_LIBRARY
248  }
249 }; // class AES256GeneratorAESNIImpl
250 
251 } // namespace internal
252 
253 } // namespace mckl
254 
256 
257 #endif // MCKL_RANDOM_INTERNAL_AES_AESNI_AES256_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
static void eval(const void *plain, void *cipher, const KeySeqType &ks)
#define MCKL_INLINE_CALL
Definition: intel.h:142
void mckl_aes256_aesni_sse2_kernel(uint64_t *, size_t, void *, const void *)
void mckl_aes256_aesni_avx2_kernel(uint64_t *, size_t, void *, const void *)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(xmmk)
const std::array< rk_type, rounds()+1 > & get() const
Definition: aes_key_seq.hpp:60
#define MCKL_RANDOM_INTERNAL_AES_AESNI_STORE(n, N, rptr)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_ENCFIRST(xmmk)
void operator()(const key_type &key, std::array< __m128i, Rp1 > &rk)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_EVAL
static void eval(std::array< std::uint64_t, 2 > &ctr, ResultType *r, const KeySeqType &ks)
void increment(std::array< T, K > &ctr, std::integral_constant< T, NSkip >)
Increment a counter by given steps.
Definition: mcmc.hpp:40
static key_type key(const std::array< __m128i, Rp1 > &rk)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_ENCLAST(xmmk)
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79
__m128i aeskeygenassist_si128(const __m128i &)