MCKL
Monte Carlo Kernel Library
aes_aesni_aes192.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/aes_aesni_aes192.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_AES192_HPP
33 #define MCKL_RANDOM_INTERNAL_AES_AESNI_AES192_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, 6>;
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  xmm7_ = _mm_set_epi32(0, 0, static_cast<int>(std::get<5>(key)),
69  static_cast<int>(std::get<4>(key)));
70  std::get<0>(rk) = xmm1_;
71  std::get<1>(rk) = xmm7_;
72 
73  xmm3_ = _mm_setzero_si128();
74  xmm6_ = _mm_setzero_si128();
75  xmm4_ = _mm_shuffle_epi32(xmm7_, 0x4F);
76 
77  std::array<char, Rp1 * 16 + 16> rk_tmp;
78  generate<1, Rp1>(
79  rk_tmp.data(), std::integral_constant<bool, 24 < Rp1 * 16>());
80  copy_key(
81  rk, rk_tmp.data(), std::integral_constant<bool, 24 < Rp1 * 16>());
82  }
83 
84  private:
85  __m128i xmm1_;
86  __m128i xmm2_;
87  __m128i xmm3_;
88  __m128i xmm4_;
89  __m128i xmm5_;
90  __m128i xmm6_;
91  __m128i xmm7_;
92 
93  template <std::size_t, std::size_t>
94  void generate(char *, std::false_type)
95  {
96  }
97 
98  template <std::size_t N, std::size_t Rp1>
99  void generate(char *rk_ptr, std::true_type)
100  {
101  generate_key<N>(rk_ptr);
102  complete_key<N>(
103  rk_ptr, std::integral_constant<bool, N * 24 + 16 < Rp1 * 16>());
104  generate<N + 1, Rp1>(
105  rk_ptr, std::integral_constant<bool, N * 24 + 24 < Rp1 * 16>());
106  }
107 
108  template <std::size_t N>
109  void generate_key(char *rk_ptr)
110  {
111  // In entry, N * 24 < Rp1 * 16. Required Storage: N * 24 + 16.
112  xmm2_ = aeskeygenassist_si128<N % 256>(xmm4_);
113  generate_key_expansion();
114  _mm_storeu_si128(reinterpret_cast<__m128i *>(rk_ptr + N * 24), xmm1_);
115  }
116 
117  template <std::size_t>
118  void complete_key(char *, std::false_type)
119  {
120  }
121 
122  template <std::size_t N>
123  void complete_key(char *rk_ptr, std::true_type)
124  {
125  // In entry, N * 24 + 16 < Rp1 * 16. Required storage: N * 24 + 32.
126  complete_key_expansion();
127  _mm_storeu_si128(
128  reinterpret_cast<__m128i *>(rk_ptr + N * 24 + 16), xmm7_);
129  }
130 
131  void generate_key_expansion()
132  {
133  xmm2_ = _mm_shuffle_epi32(xmm2_, 0xFF);
134  xmm3_ = _mm_castps_si128(_mm_shuffle_ps(
135  _mm_castsi128_ps(xmm3_), _mm_castsi128_ps(xmm1_), 0x10));
136  xmm1_ = _mm_xor_si128(xmm1_, xmm3_);
137  xmm3_ = _mm_castps_si128(_mm_shuffle_ps(
138  _mm_castsi128_ps(xmm3_), _mm_castsi128_ps(xmm1_), 0x8C));
139  xmm1_ = _mm_xor_si128(xmm1_, xmm3_);
140  xmm1_ = _mm_xor_si128(xmm1_, xmm2_);
141  }
142 
143  void complete_key_expansion()
144  {
145  xmm5_ = xmm4_;
146  xmm5_ = _mm_slli_si128(xmm5_, 4);
147  xmm6_ = _mm_castps_si128(_mm_shuffle_ps(
148  _mm_castsi128_ps(xmm6_), _mm_castsi128_ps(xmm1_), 0xF0));
149  xmm6_ = _mm_xor_si128(xmm6_, xmm5_);
150  xmm4_ = _mm_xor_si128(xmm4_, xmm6_);
151  xmm7_ = _mm_shuffle_epi32(xmm4_, 0x0E);
152  }
153 
154  template <std::size_t Rp1>
155  void copy_key(std::array<__m128i, Rp1> &, const char *, std::false_type)
156  {
157  }
158 
159  template <std::size_t Rp1>
160  void copy_key(
161  std::array<__m128i, Rp1> &rk, const char *rk_ptr, std::true_type)
162  {
163  char *dst = reinterpret_cast<char *>(rk.data());
164  std::memcpy(dst + 24, rk_ptr + 24, Rp1 * 16 - 24);
165  }
166 }; // class AES192KeySeqGeneratorAESNIImpl
167 
169 {
171 
172  public:
173  static void eval(const void *plain, void *cipher, const KeySeqType &ks)
174  {
175  __m128i xmm0 =
176  _mm_loadu_si128(reinterpret_cast<const __m128i *>(plain));
177 
178  xmm0 = _mm_xor_si128(xmm0, ks.get<0x0>());
179  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x1>());
180  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x2>());
181  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x3>());
182  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x4>());
183  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x5>());
184  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x6>());
185  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x7>());
186  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x8>());
187  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x9>());
188  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xA>());
189  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xB>());
190  xmm0 = _mm_aesenclast_si128(xmm0, ks.get<0xC>());
191 
192  _mm_storeu_si128(reinterpret_cast<__m128i *>(cipher), xmm0);
193  }
194 
195  template <typename ResultType>
196  static void eval(
197  std::array<std::uint64_t, 2> &ctr, ResultType *r, const KeySeqType &ks)
198  {
200 
201  __m128i xmm0 =
202  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
203  static_cast<MCKL_INT64>(std::get<0>(ctr)));
204 
205  xmm0 = _mm_xor_si128(xmm0, ks.get<0x0>());
206  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x1>());
207  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x2>());
208  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x3>());
209  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x4>());
210  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x5>());
211  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x6>());
212  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x7>());
213  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x8>());
214  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x9>());
215  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xA>());
216  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0xB>());
217  xmm0 = _mm_aesenclast_si128(xmm0, ks.get<0xC>());
218 
219  _mm_storeu_si128(reinterpret_cast<__m128i *>(r), xmm0);
220  }
221 
223 
224  private:
225  template <typename ResultType>
226  static void eval_kernel(std::array<std::uint64_t, 2> &ctr, std::size_t n,
227  ResultType *r, const KeySeqType &ks)
228  {
229 #if MCKL_USE_ASM_LIBRARY
230 #if MCKL_USE_AVX2
231  mckl_aes192_aesni_avx2_kernel(ctr.data(), n, r, ks.get().data());
232 #else
233  mckl_aes192_aesni_sse2_kernel(ctr.data(), n, r, ks.get().data());
234 #endif
235 #else // MCKL_USE_ASM_LIBRARY
236  constexpr std::size_t S = 8;
237  constexpr std::size_t N = S;
238 
239  const std::array<__m128i, KeySeqType::rounds() + 1> rk(ks.get());
240 
241  __m128i xmmc =
242  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
243  static_cast<MCKL_INT64>(std::get<0>(ctr)));
244  ctr.front() += n;
245 
246  __m128i *rptr = reinterpret_cast<__m128i *>(r);
247  while (n != 0) {
248  __m128i xmm0 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 1));
249  __m128i xmm1 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 2));
250  __m128i xmm2 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 3));
251  __m128i xmm3 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 4));
252  __m128i xmm4 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 5));
253  __m128i xmm5 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 6));
254  __m128i xmm6 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 7));
255  __m128i xmm7 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 8));
256  xmmc = xmm7;
257 
258  MCKL_RANDOM_INTERNAL_AES_AESNI_ENCFIRST(std::get<0x0>(rk))
259  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x1>(rk))
260  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x2>(rk))
261  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x3>(rk))
262  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x4>(rk))
263  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x5>(rk))
264  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x6>(rk))
265  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x7>(rk))
266  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x8>(rk))
267  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x9>(rk))
268  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0xA>(rk))
269  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0xB>(rk))
270  MCKL_RANDOM_INTERNAL_AES_AESNI_ENCLAST(std::get<0xC>(rk))
272  }
273 #endif // MCKL_USE_ASM_LIBRARY
274  }
275 }; // class AES192GeneratorAESNIImpl
276 
277 } // namespace internal
278 
279 } // namespace mckl
280 
282 
283 #endif // MCKL_RANDOM_INTERNAL_AES_AESNI_AES192_HPP
static key_type key(const std::array< __m128i, Rp1 > &rk)
void mckl_aes192_aesni_sse2_kernel(uint64_t *, size_t, void *, const void *)
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
#define MCKL_INLINE_CALL
Definition: intel.h:142
#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)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_EVAL
static void eval(const void *plain, void *cipher, 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
void operator()(const key_type &key, std::array< __m128i, Rp1 > &rk)
static void eval(std::array< std::uint64_t, 2 > &ctr, ResultType *r, const KeySeqType &ks)
void mckl_aes192_aesni_avx2_kernel(uint64_t *, size_t, void *, const void *)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_ENCLAST(xmmk)
#define MCKL_POP_GCC_WARNING
Definition: compiler.h:79