Random123
aes.h
Go to the documentation of this file.
1 /*
2 Copyright 2010-2011, D. E. Shaw Research.
3 All rights reserved.
4 
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
8 
9 * Redistributions of source code must retain the above copyright
10  notice, this list of conditions, and the following disclaimer.
11 
12 * Redistributions in binary form must reproduce the above copyright
13  notice, this list of conditions, and the following disclaimer in the
14  documentation and/or other materials provided with the distribution.
15 
16 * Neither the name of D. E. Shaw Research nor the names of its
17  contributors may be used to endorse or promote products derived from
18  this software without specific prior written permission.
19 
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 #ifndef __Random123_aes_dot_hpp__
33 #define __Random123_aes_dot_hpp__
34 
36 #include "array.h"
37 
38 /* Implement a bona fide AES block cipher. It's minimally
39 // checked against the test vector in FIPS-197 in ut_aes.cpp. */
40 #if R123_USE_AES_NI
41 
50 
52 R123_STATIC_INLINE __m128i AES_128_ASSIST (__m128i temp1, __m128i temp2) {
53  __m128i temp3;
54  temp2 = _mm_shuffle_epi32 (temp2 ,0xff);
55  temp3 = _mm_slli_si128 (temp1, 0x4);
56  temp1 = _mm_xor_si128 (temp1, temp3);
57  temp3 = _mm_slli_si128 (temp3, 0x4);
58  temp1 = _mm_xor_si128 (temp1, temp3);
59  temp3 = _mm_slli_si128 (temp3, 0x4);
60  temp1 = _mm_xor_si128 (temp1, temp3);
61  temp1 = _mm_xor_si128 (temp1, temp2);
62  return temp1;
63 }
64 
65 R123_STATIC_INLINE void aesni1xm128iexpand(aesni1xm128i_ukey_t uk, __m128i ret[11])
66 {
67  __m128i rkey = uk.v[0].m;
68  __m128i tmp2;
69 
70  ret[0] = rkey;
71  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x1);
72  rkey = AES_128_ASSIST(rkey, tmp2);
73  ret[1] = rkey;
74 
75  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x2);
76  rkey = AES_128_ASSIST(rkey, tmp2);
77  ret[2] = rkey;
78 
79  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x4);
80  rkey = AES_128_ASSIST(rkey, tmp2);
81  ret[3] = rkey;
82 
83  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x8);
84  rkey = AES_128_ASSIST(rkey, tmp2);
85  ret[4] = rkey;
86 
87  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x10);
88  rkey = AES_128_ASSIST(rkey, tmp2);
89  ret[5] = rkey;
90 
91  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x20);
92  rkey = AES_128_ASSIST(rkey, tmp2);
93  ret[6] = rkey;
94 
95  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x40);
96  rkey = AES_128_ASSIST(rkey, tmp2);
97  ret[7] = rkey;
98 
99  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x80);
100  rkey = AES_128_ASSIST(rkey, tmp2);
101  ret[8] = rkey;
102 
103  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x1b);
104  rkey = AES_128_ASSIST(rkey, tmp2);
105  ret[9] = rkey;
106 
107  tmp2 = _mm_aeskeygenassist_si128(rkey, 0x36);
108  rkey = AES_128_ASSIST(rkey, tmp2);
109  ret[10] = rkey;
110 }
113 #ifdef __cplusplus
114 
116  __m128i k[11];
119  uk.v[0].m = _mm_setzero_si128();
120  aesni1xm128iexpand(uk, k);
121  }
123  aesni1xm128iexpand(uk, k);
124  }
126  aesni1xm128i_ukey_t uk128;
127  uk128.v[0].m = _mm_set_epi32(uk.v[3], uk.v[2], uk.v[1], uk.v[0]);
128  aesni1xm128iexpand(uk128, k);
129  }
131  aesni1xm128iexpand(uk, k);
132  return *this;
133  }
135  aesni1xm128i_ukey_t uk128;
136  uk128.v[0].m = _mm_set_epi32(uk.v[3], uk.v[2], uk.v[1], uk.v[0]);
137  aesni1xm128iexpand(uk128, k);
138  return *this;
139  }
140  bool operator==(const aesni1xm128i_key_t& rhs) const{
141  for(int i=0; i<11; ++i){
142  // Sigh... No r123m128i(__m128i) constructor!
143  r123m128i li; li.m = k[i];
144  r123m128i ri; ri.m = rhs.k[i];
145  if( li != ri ) return false;
146  }
147  return true;
148  }
149  bool operator!=(const aesni1xm128i_key_t& rhs) const{
150  return !(*this == rhs);
151  }
152  friend std::ostream& operator<<(std::ostream& os, const aesni1xm128i_key_t& v){
153  r123m128i ki;
154  for(int i=0; i<10; ++i){
155  ki.m = v.k[i];
156  os << ki << " ";
157  }
158  ki.m = v.k[10];
159  return os << ki;
160  }
161  friend std::istream& operator>>(std::istream& is, aesni1xm128i_key_t& v){
162  r123m128i ki;
163  for(int i=0; i<11; ++i){
164  is >> ki;
165  v.k[i] = ki;
166  }
167  return is;
168  }
169 };
170 #else
171 typedef struct {
172  __m128i k[11];
174 
176 R123_STATIC_INLINE aesni1xm128i_key_t aesni1xm128ikeyinit(aesni1xm128i_ukey_t uk){
177  aesni1xm128i_key_t ret;
178  aesni1xm128iexpand(uk, ret.k);
179  return ret;
180 }
181 #endif
182 
185  __m128i x = _mm_xor_si128(k.k[0], in.v[0].m);
186  x = _mm_aesenc_si128(x, k.k[1]);
187  x = _mm_aesenc_si128(x, k.k[2]);
188  x = _mm_aesenc_si128(x, k.k[3]);
189  x = _mm_aesenc_si128(x, k.k[4]);
190  x = _mm_aesenc_si128(x, k.k[5]);
191  x = _mm_aesenc_si128(x, k.k[6]);
192  x = _mm_aesenc_si128(x, k.k[7]);
193  x = _mm_aesenc_si128(x, k.k[8]);
194  x = _mm_aesenc_si128(x, k.k[9]);
195  x = _mm_aesenclast_si128(x, k.k[10]);
196  {
197  aesni1xm128i_ctr_t ret;
198  ret.v[0].m = x;
199  return ret;
200  }
201 }
202 
205  R123_ASSERT(R==10);
206  return aesni1xm128i(in, k);
207 }
208 
209 
218  aesni1xm128i_ukey_t uk128;
219  aesni4x32_key_t ret;
220  uk128.v[0].m = _mm_set_epi32(uk.v[3], uk.v[2], uk.v[1], uk.v[0]);
221  aesni1xm128iexpand(uk128, ret.k);
222  return ret;
223 }
224 
227 R123_STATIC_INLINE aesni4x32_ctr_t aesni4x32_R(unsigned int Nrounds, aesni4x32_ctr_t c, aesni4x32_key_t k){
228  aesni1xm128i_ctr_t c128;
229  c128.v[0].m = _mm_set_epi32(c.v[3], c.v[2], c.v[1], c.v[0]);
230  c128 = aesni1xm128i_R(Nrounds, c128, k);
231  _mm_storeu_si128((__m128i*)&c.v[0], c128.v[0].m);
232  return c;
233 }
234 
235 #define aesni4x32_rounds aesni1xm128i_rounds
236 
239 #define aesni4x32(c,k) aesni4x32_R(aesni4x32_rounds, c, k)
240 
241 #ifdef __cplusplus
242 namespace r123{
278  static const unsigned int rounds=10;
280  return aesni1xm128i(ctr, key);
281  }
282 };
283 
284 /* @class AESNI4x32 */
285 struct AESNI4x32{
289  static const unsigned int rounds=10;
291  return aesni4x32(ctr, key);
292  }
293 };
294 
300 template <unsigned ROUNDS=10>
301 struct AESNI1xm128i_R : public AESNI1xm128i{
302  R123_STATIC_ASSERT(ROUNDS==10, "AESNI1xm128i_R<R> is only valid with R=10");
303 };
304 
306 template <unsigned ROUNDS=10>
307 struct AESNI4x32_R : public AESNI4x32{
308  R123_STATIC_ASSERT(ROUNDS==10, "AESNI4x32_R<R> is only valid with R=10");
309 };
310 } // namespace r123
311 #endif /* __cplusplus */
312 
313 #endif /* R123_USE_AES_NI */
314 
315 #if R123_USE_AES_OPENSSL
316 #include "string.h"
317 #include <openssl/aes.h>
318 typedef struct r123array16x8 aesopenssl16x8_ctr_t;
319 typedef struct r123array16x8 aesopenssl16x8_ukey_t;
320 #ifdef __cplusplus
321 struct aesopenssl16x8_key_t{
322  AES_KEY k;
323  aesopenssl16x8_key_t(){
324  aesopenssl16x8_ukey_t ukey={{}};
325  AES_set_encrypt_key((const unsigned char *)&ukey.v[0], 128, &k);
326  }
327  aesopenssl16x8_key_t(const aesopenssl16x8_ukey_t& ukey){
328  AES_set_encrypt_key((const unsigned char *)&ukey.v[0], 128, &k);
329  }
330  aesopenssl16x8_key_t& operator=(const aesopenssl16x8_ukey_t& ukey){
331  AES_set_encrypt_key((const unsigned char *)&ukey.v[0], 128, &k);
332  return *this;
333  }
334  bool operator==(const aesopenssl16x8_key_t& rhs) const{
335  return (k.rounds == rhs.k.rounds) && 0==::memcmp(&k.rd_key[0], &rhs.k.rd_key[0], (k.rounds+1) * 4 * sizeof(uint32_t));
336  }
337  bool operator!=(const aesopenssl16x8_key_t& rhs) const{
338  return !(*this == rhs);
339  }
340  friend std::ostream& operator<<(std::ostream& os, const aesopenssl16x8_key_t& v){
341  os << v.k.rounds;
342  const unsigned int *p = &v.k.rd_key[0];
343  for(int i=0; i<(v.k.rounds+1); ++i){
344  os << " " << p[0] << " " << p[1] << " " << p[2] << " " << p[3];
345  p += 4;
346  }
347  return os;
348  }
349  friend std::istream& operator>>(std::istream& is, aesopenssl16x8_key_t& v){
350  is >> v.k.rounds;
351  unsigned int *p = &v.k.rd_key[0];
352  for(int i=0; i<(v.k.rounds+1); ++i){
353  is >> p[0] >> p[1] >> p[2] >> p[3];
354  p += 4;
355  }
356  return is;
357  }
358 };
359 #else
360 typedef struct aesopenssl16x8_key_t{
361  AES_KEY k;
362 }aesopenssl16x8_key_t;
363 R123_STATIC_INLINE struct aesopenssl16x8_key_t aesopenssl16x8keyinit(aesopenssl16x8_ukey_t uk){
364  aesopenssl16x8_key_t ret;
365  AES_set_encrypt_key((const unsigned char *)&uk.v[0], 128, &ret.k);
366  return ret;
367 }
368 #endif
369 
370 R123_STATIC_INLINE R123_FORCE_INLINE(aesopenssl16x8_ctr_t aesopenssl16x8_R(aesopenssl16x8_ctr_t ctr, aesopenssl16x8_key_t key));
371 R123_STATIC_INLINE
372 aesopenssl16x8_ctr_t aesopenssl16x8_R(aesopenssl16x8_ctr_t ctr, aesopenssl16x8_key_t key){
373  aesopenssl16x8_ctr_t ret;
374  AES_encrypt((const unsigned char*)&ctr.v[0], (unsigned char *)&ret.v[0], &key.k);
375  return ret;
376 }
377 
378 #define aesopenssl16x8_rounds aesni4x32_rounds
379 #define aesopenssl16x8(c,k) aesopenssl16x8_R(aesopenssl16x8_rounds)
380 
381 #ifdef __cplusplus
382 namespace r123{
383 struct AESOpenSSL16x8{
384  typedef aesopenssl16x8_ctr_t ctr_type;
385  typedef aesopenssl16x8_key_t key_type;
386  typedef aesopenssl16x8_ukey_t ukey_type;
387  static const unsigned int rounds=10;
388  ctr_type operator()(const ctr_type& in, const key_type& k){
389  ctr_type out;
390  AES_encrypt((const unsigned char *)&in[0], (unsigned char *)&out[0], &k.k);
391  return out;
392  }
393 };
394 } // namespace r123
395 #endif /* __cplusplus */
396 #endif /* R123_USE_AES_OPENSSL */
397 
398 #endif
aesni1xm128i_key_t
Definition: aes.h:115
operator>>
std::istream & operator>>(std::istream &is, r123array1x32 &a)
Definition: array.h:314
r123::AESNI4x32_R
Definition: aes.h:307
r123array4x32::v
uint32_t v[4]
Definition: array.h:316
aesni4x32_key_t
aesni1xm128i_key_t aesni4x32_key_t
Definition: aes.h:213
r123::AESNI1xm128i
Definition: aes.h:274
aesni1xm128i_key_t::operator=
aesni1xm128i_key_t & operator=(const aesni1xm128i_ukey_t &uk)
Definition: aes.h:130
aesni1xm128i_key_t::k
__m128i k[11]
Definition: aes.h:116
aesni1xm128i_key_t::aesni1xm128i_key_t
aesni1xm128i_key_t()
Definition: aes.h:117
aesni4x32
#define aesni4x32(c, k)
Definition: aes.h:239
r123::AESNI4x32::rounds
static const unsigned int rounds
Definition: aes.h:289
aesni1xm128i_key_t::aesni1xm128i_key_t
aesni1xm128i_key_t(const aesni1xm128i_ukey_t &uk)
Definition: aes.h:122
r123array1xm128i::v
r123m128i v[1]
Definition: array.h:331
aesni4x32_R
static aesni4x32_ctr_t aesni4x32_R(unsigned int Nrounds, aesni4x32_ctr_t c, aesni4x32_key_t k)
Definition: aes.h:227
aesni1xm128i
static aesni1xm128i_ctr_t aesni1xm128i(aesni1xm128i_ctr_t in, aesni1xm128i_key_t k)
Definition: aes.h:184
aesni1xm128i_rounds
@ aesni1xm128i_rounds
Definition: aes.h:49
aesni4x32keyinit
static aesni4x32_key_t aesni4x32keyinit(aesni4x32_ukey_t uk)
Definition: aes.h:217
r123::AESNI1xm128i::ctr_type
aesni1xm128i_ctr_t ctr_type
Definition: aes.h:275
aesni1xm128i_key_t::operator!=
bool operator!=(const aesni1xm128i_key_t &rhs) const
Definition: aes.h:149
aesni4x32_rounds
#define aesni4x32_rounds
Definition: aes.h:235
array.h
r123_enum_aesni1xm128i
r123_enum_aesni1xm128i
Definition: aes.h:49
r123m128i::m
__m128i m
Definition: sse.h:149
operator!=
static bool operator!=(const r123m128i &lhs, const r123m128i &rhs)
Definition: sse.h:235
r123::AESNI1xm128i::rounds
static const unsigned int rounds
Definition: aes.h:278
r123::AESNI4x32::operator()
ctr_type operator()(ctr_type ctr, key_type key) const
Definition: aes.h:290
r123::AESNI1xm128i::key_type
aesni1xm128i_key_t key_type
Definition: aes.h:277
operator<<
std::ostream & operator<<(std::ostream &os, const r123array1x32 &a)
Definition: array.h:314
r123::AESNI1xm128i::operator()
ctr_type operator()(ctr_type ctr, key_type key) const
Definition: aes.h:279
aesni1xm128i_key_t::operator<<
friend std::ostream & operator<<(std::ostream &os, const aesni1xm128i_key_t &v)
Definition: aes.h:152
r123array1xm128i
Definition: array.h:331
r123::AESNI4x32::key_type
aesni4x32_key_t key_type
Definition: aes.h:288
aesni1xm128i_key_t::operator>>
friend std::istream & operator>>(std::istream &is, aesni1xm128i_key_t &v)
Definition: aes.h:161
r123::AESNI1xm128i::ukey_type
aesni1xm128i_ukey_t ukey_type
Definition: aes.h:276
aesni1xm128i_key_t::aesni1xm128i_key_t
aesni1xm128i_key_t(const aesni4x32_ukey_t &uk)
Definition: aes.h:125
r123array4x32
Definition: array.h:316
r123::AESNI4x32::ctr_type
aesni4x32_ctr_t ctr_type
Definition: aes.h:286
r123::AESNI1xm128i_R
Definition: aes.h:301
r123
Definition: aes.h:242
compilerfeatures.h
r123array16x8
Definition: array.h:328
aesni1xm128i_key_t::operator=
aesni1xm128i_key_t & operator=(const aesni4x32_ukey_t &uk)
Definition: aes.h:134
r123m128i
Definition: sse.h:148
r123_enum_aesni4x32
r123_enum_aesni4x32
Definition: aes.h:215
operator==
static bool operator==(const r123m128i &lhs, const r123m128i &rhs)
Definition: sse.h:233
aesni1xm128i_R
static aesni1xm128i_ctr_t aesni1xm128i_R(unsigned R, aesni1xm128i_ctr_t in, aesni1xm128i_key_t k)
Definition: aes.h:204
r123::AESNI4x32::ukey_type
aesni4x32_ukey_t ukey_type
Definition: aes.h:287
r123::AESNI4x32
Definition: aes.h:285
aesni1xm128i_key_t::operator==
bool operator==(const aesni1xm128i_key_t &rhs) const
Definition: aes.h:140