Random123
aes.h
Go to the documentation of this file.
1/*
2Copyright 2010-2011, D. E. Shaw Research.
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
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
20THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30OF 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
52R123_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
65R123_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
116 __m128i k[11];
119 uk.v[0].m = _mm_setzero_si128();
120 aesni1xm128iexpand(uk, k);
121 }
123 aesni1xm128iexpand(uk, k);
124 }
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 }
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
171typedef struct {
172 __m128i k[11];
174
176R123_STATIC_INLINE aesni1xm128i_key_t aesni1xm128ikeyinit(aesni1xm128i_ukey_t uk){
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 {
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
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
227R123_STATIC_INLINE aesni4x32_ctr_t aesni4x32_R(unsigned int Nrounds, aesni4x32_ctr_t c, aesni4x32_key_t k){
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
242namespace r123{
278 static const unsigned int rounds=10;
280 return aesni1xm128i(ctr, key);
281 }
282};
283
284/* @class AESNI4x32 */
289 static const unsigned int rounds=10;
291 return aesni4x32(ctr, key);
292 }
293};
294
300template <unsigned ROUNDS=10>
302 R123_STATIC_ASSERT(ROUNDS==10, "AESNI1xm128i_R<R> is only valid with R=10");
303};
304
306template <unsigned ROUNDS=10>
307struct 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>
318typedef struct r123array16x8 aesopenssl16x8_ctr_t;
319typedef struct r123array16x8 aesopenssl16x8_ukey_t;
320#ifdef __cplusplus
321struct 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
360typedef struct aesopenssl16x8_key_t{
361 AES_KEY k;
362}aesopenssl16x8_key_t;
363R123_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
370R123_STATIC_INLINE R123_FORCE_INLINE(aesopenssl16x8_ctr_t aesopenssl16x8_R(aesopenssl16x8_ctr_t ctr, aesopenssl16x8_key_t key));
371R123_STATIC_INLINE
372aesopenssl16x8_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
382namespace r123{
383struct 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
#define aesni4x32_rounds
Definition: aes.h:235
std::ostream & operator<<(std::ostream &os, const r123array1x32 &a)
Definition: array.h:314
std::istream & operator>>(std::istream &is, r123array1x32 &a)
Definition: array.h:314
r123_enum_aesni4x32
Definition: aes.h:215
r123_enum_aesni1xm128i
Definition: aes.h:49
static aesni4x32_key_t aesni4x32keyinit(aesni4x32_ukey_t uk)
Definition: aes.h:217
static aesni1xm128i_ctr_t aesni1xm128i(aesni1xm128i_ctr_t in, aesni1xm128i_key_t k)
Definition: aes.h:184
aesni1xm128i_key_t aesni4x32_key_t
Definition: aes.h:213
static aesni1xm128i_ctr_t aesni1xm128i_R(unsigned R, aesni1xm128i_ctr_t in, aesni1xm128i_key_t k)
Definition: aes.h:204
static aesni4x32_ctr_t aesni4x32_R(unsigned int Nrounds, aesni4x32_ctr_t c, aesni4x32_key_t k)
Definition: aes.h:227
#define aesni4x32(c, k)
Definition: aes.h:239
@ aesni1xm128i_rounds
Definition: aes.h:49
Definition: aes.h:242
static bool operator!=(const r123m128i &lhs, const r123m128i &rhs)
Definition: sse.h:235
static bool operator==(const r123m128i &lhs, const r123m128i &rhs)
Definition: sse.h:233
Definition: aes.h:115
aesni1xm128i_key_t(const aesni1xm128i_ukey_t &uk)
Definition: aes.h:122
aesni1xm128i_key_t(const aesni4x32_ukey_t &uk)
Definition: aes.h:125
__m128i k[11]
Definition: aes.h:116
friend std::istream & operator>>(std::istream &is, aesni1xm128i_key_t &v)
Definition: aes.h:161
bool operator==(const aesni1xm128i_key_t &rhs) const
Definition: aes.h:140
bool operator!=(const aesni1xm128i_key_t &rhs) const
Definition: aes.h:149
aesni1xm128i_key_t & operator=(const aesni4x32_ukey_t &uk)
Definition: aes.h:134
aesni1xm128i_key_t & operator=(const aesni1xm128i_ukey_t &uk)
Definition: aes.h:130
friend std::ostream & operator<<(std::ostream &os, const aesni1xm128i_key_t &v)
Definition: aes.h:152
aesni1xm128i_key_t()
Definition: aes.h:117
Definition: aes.h:301
Definition: aes.h:274
static const unsigned int rounds
Definition: aes.h:278
aesni1xm128i_ukey_t ukey_type
Definition: aes.h:276
aesni1xm128i_key_t key_type
Definition: aes.h:277
ctr_type operator()(ctr_type ctr, key_type key) const
Definition: aes.h:279
aesni1xm128i_ctr_t ctr_type
Definition: aes.h:275
Definition: aes.h:307
Definition: aes.h:285
aesni4x32_key_t key_type
Definition: aes.h:288
aesni4x32_ukey_t ukey_type
Definition: aes.h:287
static const unsigned int rounds
Definition: aes.h:289
ctr_type operator()(ctr_type ctr, key_type key) const
Definition: aes.h:290
aesni4x32_ctr_t ctr_type
Definition: aes.h:286
Definition: array.h:328
Definition: array.h:331
r123m128i v[1]
Definition: array.h:331
Definition: array.h:316
uint32_t v[4]
Definition: array.h:316
Definition: sse.h:148
__m128i m
Definition: sse.h:149