MCKL
Monte Carlo Kernel Library
aes_aesni_aes128.hpp
Go to the documentation of this file.
1 //============================================================================
2 // MCKL/include/mckl/random/internal/aes_aesni_aes128.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_AES128_HPP
33 #define MCKL_RANDOM_INTERNAL_AES_AESNI_AES128_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, 4>;
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  std::get<0>(rk) = xmm1_;
69  generate<1>(rk, std::integral_constant<bool, 1 < Rp1>());
70  }
71 
72  private:
73  __m128i xmm1_;
74  __m128i xmm2_;
75  __m128i xmm3_;
76 
77  template <std::size_t, std::size_t Rp1>
78  void generate(std::array<__m128i, Rp1> &, std::false_type)
79  {
80  }
81 
82  template <std::size_t N, std::size_t Rp1>
83  void generate(std::array<__m128i, Rp1> &rk, std::true_type)
84  {
85  xmm2_ = aeskeygenassist_si128<N % 256>(xmm1_);
86  expand_key();
87  std::get<N>(rk) = xmm1_;
88  generate<N + 1>(rk, std::integral_constant<bool, N + 1 < Rp1>());
89  }
90 
91  void expand_key()
92  {
93  xmm2_ = _mm_shuffle_epi32(xmm2_, 0xFF);
94  xmm3_ = _mm_slli_si128(xmm1_, 4);
95  xmm1_ = _mm_xor_si128(xmm1_, xmm3_);
96  xmm3_ = _mm_slli_si128(xmm3_, 4);
97  xmm1_ = _mm_xor_si128(xmm1_, xmm3_);
98  xmm3_ = _mm_slli_si128(xmm3_, 4);
99  xmm1_ = _mm_xor_si128(xmm1_, xmm3_);
100  xmm1_ = _mm_xor_si128(xmm1_, xmm2_);
101  }
102 }; // class AES128KeySeqGeneratorAESNIImpl
103 
105 {
107 
108  public:
109  static void eval(const void *plain, void *cipher, const KeySeqType &ks)
110  {
111  __m128i xmm0 =
112  _mm_loadu_si128(reinterpret_cast<const __m128i *>(plain));
113 
114  xmm0 = _mm_xor_si128(xmm0, ks.get<0x0>());
115  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x1>());
116  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x2>());
117  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x3>());
118  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x4>());
119  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x5>());
120  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x6>());
121  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x7>());
122  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x8>());
123  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x9>());
124  xmm0 = _mm_aesenclast_si128(xmm0, ks.get<0xA>());
125 
126  _mm_storeu_si128(reinterpret_cast<__m128i *>(cipher), xmm0);
127  }
128 
129  template <typename ResultType>
130  static void eval(
131  std::array<std::uint64_t, 2> &ctr, ResultType *r, const KeySeqType &ks)
132  {
134 
135  __m128i xmm0 =
136  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
137  static_cast<MCKL_INT64>(std::get<0>(ctr)));
138 
139  xmm0 = _mm_xor_si128(xmm0, ks.get<0x0>());
140  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x1>());
141  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x2>());
142  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x3>());
143  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x4>());
144  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x5>());
145  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x6>());
146  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x7>());
147  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x8>());
148  xmm0 = _mm_aesenc_si128(xmm0, ks.get<0x9>());
149  xmm0 = _mm_aesenclast_si128(xmm0, ks.get<0xA>());
150 
151  _mm_storeu_si128(reinterpret_cast<__m128i *>(r), xmm0);
152  }
153 
155 
156  private:
157  template <typename ResultType>
158  static void eval_kernel(std::array<std::uint64_t, 2> &ctr, std::size_t n,
159  ResultType *r, const KeySeqType &ks)
160  {
161 #if MCKL_USE_ASM_LIBRARY
162 #if MCKL_USE_AVX2
163  mckl_aes128_aesni_avx2_kernel(ctr.data(), n, r, ks.get().data());
164 #else
165  mckl_aes128_aesni_sse2_kernel(ctr.data(), n, r, ks.get().data());
166 #endif
167 #else // MCKL_USE_ASM_LIBRARY
168  constexpr std::size_t S = 8;
169  constexpr std::size_t N = S;
170 
171  const std::array<__m128i, KeySeqType::rounds() + 1> rk(ks.get());
172 
173  __m128i xmmc =
174  _mm_set_epi64x(static_cast<MCKL_INT64>(std::get<1>(ctr)),
175  static_cast<MCKL_INT64>(std::get<0>(ctr)));
176  ctr.front() += n;
177 
178  __m128i *rptr = reinterpret_cast<__m128i *>(r);
179  while (n != 0) {
180  __m128i xmm0 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 1));
181  __m128i xmm1 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 2));
182  __m128i xmm2 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 3));
183  __m128i xmm3 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 4));
184  __m128i xmm4 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 5));
185  __m128i xmm5 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 6));
186  __m128i xmm6 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 7));
187  __m128i xmm7 = _mm_add_epi64(xmmc, _mm_set_epi64x(0, 8));
188  xmmc = xmm7;
189 
190  MCKL_RANDOM_INTERNAL_AES_AESNI_ENCFIRST(std::get<0x0>(rk))
191  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x1>(rk))
192  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x2>(rk))
193  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x3>(rk))
194  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x4>(rk))
195  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x5>(rk))
196  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x6>(rk))
197  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x7>(rk))
198  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x8>(rk))
199  MCKL_RANDOM_INTERNAL_AES_AESNI_ENC(std::get<0x9>(rk))
200  MCKL_RANDOM_INTERNAL_AES_AESNI_ENCLAST(std::get<0xA>(rk))
202  }
203 #endif // MCKL_USE_ASM_LIBRARY
204  }
205 }; // class AES128GeneratorAESNIImpl
206 
207 } // namespace internal
208 
209 } // namespace mckl
210 
212 
213 #endif // MCKL_RANDOM_INTERNAL_AES_AESNI_AES128_HPP
#define MCKL_PUSH_GCC_WARNING(warning)
Definition: compiler.h:78
#define MCKL_INLINE_CALL
Definition: intel.h:142
static void eval(std::array< std::uint64_t, 2 > &ctr, ResultType *r, const KeySeqType &ks)
void mckl_aes128_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)
#define MCKL_RANDOM_INTERNAL_AES_AESNI_EVAL
void increment(std::array< T, K > &ctr, std::integral_constant< T, NSkip >)
Increment a counter by given steps.
static void eval(const void *plain, void *cipher, const KeySeqType &ks)
void operator()(const key_type &key, std::array< __m128i, Rp1 > &rk)
Definition: mcmc.hpp:40
void mckl_aes128_aesni_sse2_kernel(uint64_t *, size_t, void *, const void *)
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