Project Alice
Loading...
Searching...
No Matches
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
43typedef struct r123array1xm128i aesni1xm128i_ctr_t;
45typedef struct r123array1xm128i aesni1xm128i_ukey_t;
47typedef struct r123array4x32 aesni4x32_ukey_t;
49enum r123_enum_aesni1xm128i { aesni1xm128i_rounds = 10 };
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 __m128i rkey = uk.v[0].m;
67 __m128i tmp2;
68
69 ret[0] = rkey;
70 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x1);
71 rkey = AES_128_ASSIST(rkey, tmp2);
72 ret[1] = rkey;
73
74 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x2);
75 rkey = AES_128_ASSIST(rkey, tmp2);
76 ret[2] = rkey;
77
78 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x4);
79 rkey = AES_128_ASSIST(rkey, tmp2);
80 ret[3] = rkey;
81
82 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x8);
83 rkey = AES_128_ASSIST(rkey, tmp2);
84 ret[4] = rkey;
85
86 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x10);
87 rkey = AES_128_ASSIST(rkey, tmp2);
88 ret[5] = rkey;
89
90 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x20);
91 rkey = AES_128_ASSIST(rkey, tmp2);
92 ret[6] = rkey;
93
94 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x40);
95 rkey = AES_128_ASSIST(rkey, tmp2);
96 ret[7] = rkey;
97
98 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x80);
99 rkey = AES_128_ASSIST(rkey, tmp2);
100 ret[8] = rkey;
101
102 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x1b);
103 rkey = AES_128_ASSIST(rkey, tmp2);
104 ret[9] = rkey;
105
106 tmp2 = _mm_aeskeygenassist_si128(rkey, 0x36);
107 rkey = AES_128_ASSIST(rkey, tmp2);
108 ret[10] = rkey;
109}
112#ifdef __cplusplus
114struct aesni1xm128i_key_t {
115 __m128i k[11];
116 aesni1xm128i_key_t() {
117 aesni1xm128i_ukey_t uk;
118 uk.v[0].m = _mm_setzero_si128();
119 aesni1xm128iexpand(uk, k);
120 }
121 aesni1xm128i_key_t(aesni1xm128i_ukey_t const& uk) { aesni1xm128iexpand(uk, k); }
122 aesni1xm128i_key_t(aesni4x32_ukey_t const& uk) {
123 aesni1xm128i_ukey_t uk128;
124 uk128.v[0].m = _mm_set_epi32(uk.v[3], uk.v[2], uk.v[1], uk.v[0]);
125 aesni1xm128iexpand(uk128, k);
126 }
127 aesni1xm128i_key_t& operator=(aesni1xm128i_ukey_t const& uk) {
128 aesni1xm128iexpand(uk, k);
129 return *this;
130 }
131 aesni1xm128i_key_t& operator=(aesni4x32_ukey_t const& uk) {
132 aesni1xm128i_ukey_t uk128;
133 uk128.v[0].m = _mm_set_epi32(uk.v[3], uk.v[2], uk.v[1], uk.v[0]);
134 aesni1xm128iexpand(uk128, k);
135 return *this;
136 }
137 bool operator==(aesni1xm128i_key_t const& rhs) const {
138 for(int i = 0; i < 11; ++i) {
139 // Sigh... No r123m128i(__m128i) constructor!
140 r123m128i li;
141 li.m = k[i];
142 r123m128i ri;
143 ri.m = rhs.k[i];
144 if(li != ri)
145 return false;
146 }
147 return true;
148 }
149 bool operator!=(aesni1xm128i_key_t const& rhs) const { return !(*this == rhs); }
150 friend std::ostream& operator<<(std::ostream& os, aesni1xm128i_key_t const& v) {
151 r123m128i ki;
152 for(int i = 0; i < 10; ++i) {
153 ki.m = v.k[i];
154 os << ki << " ";
155 }
156 ki.m = v.k[10];
157 return os << ki;
158 }
159 friend std::istream& operator>>(std::istream& is, aesni1xm128i_key_t& v) {
160 r123m128i ki;
161 for(int i = 0; i < 11; ++i) {
162 is >> ki;
163 v.k[i] = ki;
164 }
165 return is;
166 }
167};
168#else
169typedef struct {
170 __m128i k[11];
171} aesni1xm128i_key_t;
172
174R123_STATIC_INLINE aesni1xm128i_key_t aesni1xm128ikeyinit(aesni1xm128i_ukey_t uk) {
175 aesni1xm128i_key_t ret;
176 aesni1xm128iexpand(uk, ret.k);
177 return ret;
178}
179#endif
180
182R123_STATIC_INLINE aesni1xm128i_ctr_t aesni1xm128i(aesni1xm128i_ctr_t in, aesni1xm128i_key_t k) {
183 __m128i x = _mm_xor_si128(k.k[0], in.v[0].m);
184 x = _mm_aesenc_si128(x, k.k[1]);
185 x = _mm_aesenc_si128(x, k.k[2]);
186 x = _mm_aesenc_si128(x, k.k[3]);
187 x = _mm_aesenc_si128(x, k.k[4]);
188 x = _mm_aesenc_si128(x, k.k[5]);
189 x = _mm_aesenc_si128(x, k.k[6]);
190 x = _mm_aesenc_si128(x, k.k[7]);
191 x = _mm_aesenc_si128(x, k.k[8]);
192 x = _mm_aesenc_si128(x, k.k[9]);
193 x = _mm_aesenclast_si128(x, k.k[10]);
194 {
195 aesni1xm128i_ctr_t ret;
196 ret.v[0].m = x;
197 return ret;
198 }
199}
200
202R123_STATIC_INLINE aesni1xm128i_ctr_t aesni1xm128i_R(unsigned R, aesni1xm128i_ctr_t in, aesni1xm128i_key_t k) {
203 R123_ASSERT(R == 10);
204 return aesni1xm128i(in, k);
205}
206
208typedef struct r123array4x32 aesni4x32_ctr_t;
210typedef aesni1xm128i_key_t aesni4x32_key_t;
212enum r123_enum_aesni4x32 { aesni4x32_rounds = 10 };
214R123_STATIC_INLINE aesni4x32_key_t aesni4x32keyinit(aesni4x32_ukey_t uk) {
215 aesni1xm128i_ukey_t uk128;
216 aesni4x32_key_t ret;
217 uk128.v[0].m = _mm_set_epi32(uk.v[3], uk.v[2], uk.v[1], uk.v[0]);
218 aesni1xm128iexpand(uk128, ret.k);
219 return ret;
220}
221
225R123_STATIC_INLINE aesni4x32_ctr_t aesni4x32_R(unsigned int Nrounds, aesni4x32_ctr_t c, aesni4x32_key_t k) {
226 aesni1xm128i_ctr_t c128;
227 c128.v[0].m = _mm_set_epi32(c.v[3], c.v[2], c.v[1], c.v[0]);
228 c128 = aesni1xm128i_R(Nrounds, c128, k);
229 _mm_storeu_si128((__m128i*)&c.v[0], c128.v[0].m);
230 return c;
231}
232
233#define aesni4x32_rounds aesni1xm128i_rounds
234
237#define aesni4x32(c, k) aesni4x32_R(aesni4x32_rounds, c, k)
238
239#ifdef __cplusplus
240namespace r123 {
273struct AESNI1xm128i {
274 typedef aesni1xm128i_ctr_t ctr_type;
275 typedef aesni1xm128i_ukey_t ukey_type;
276 typedef aesni1xm128i_key_t key_type;
277 static unsigned int const rounds = 10;
278 ctr_type operator()(ctr_type ctr, key_type key) const { return aesni1xm128i(ctr, key); }
279};
280
281/* @class AESNI4x32 */
282struct AESNI4x32 {
283 typedef aesni4x32_ctr_t ctr_type;
284 typedef aesni4x32_ukey_t ukey_type;
285 typedef aesni4x32_key_t key_type;
286 static unsigned int const rounds = 10;
287 ctr_type operator()(ctr_type ctr, key_type key) const { return aesni4x32(ctr, key); }
288};
289
295template<unsigned ROUNDS = 10> struct AESNI1xm128i_R : public AESNI1xm128i { R123_STATIC_ASSERT(ROUNDS == 10, "AESNI1xm128i_R<R> is only valid with R=10"); };
296
298template<unsigned ROUNDS = 10> struct AESNI4x32_R : public AESNI4x32 { R123_STATIC_ASSERT(ROUNDS == 10, "AESNI4x32_R<R> is only valid with R=10"); };
299} // namespace r123
300#endif /* __cplusplus */
301
302#endif /* R123_USE_AES_NI */
303
304#if R123_USE_AES_OPENSSL
305#include "string.h"
306#include <openssl/aes.h>
307typedef struct r123array16x8 aesopenssl16x8_ctr_t;
308typedef struct r123array16x8 aesopenssl16x8_ukey_t;
309#ifdef __cplusplus
310struct aesopenssl16x8_key_t {
311 AES_KEY k;
312 aesopenssl16x8_key_t() {
313 aesopenssl16x8_ukey_t ukey = {{}};
314 AES_set_encrypt_key((unsigned char const*)&ukey.v[0], 128, &k);
315 }
316 aesopenssl16x8_key_t(aesopenssl16x8_ukey_t const& ukey) { AES_set_encrypt_key((unsigned char const*)&ukey.v[0], 128, &k); }
317 aesopenssl16x8_key_t& operator=(aesopenssl16x8_ukey_t const& ukey) {
318 AES_set_encrypt_key((unsigned char const*)&ukey.v[0], 128, &k);
319 return *this;
320 }
321 bool operator==(aesopenssl16x8_key_t const& rhs) const { return (k.rounds == rhs.k.rounds) && 0 == ::memcmp(&k.rd_key[0], &rhs.k.rd_key[0], (k.rounds + 1) * 4 * sizeof(uint32_t)); }
322 bool operator!=(aesopenssl16x8_key_t const& rhs) const { return !(*this == rhs); }
323 friend std::ostream& operator<<(std::ostream& os, aesopenssl16x8_key_t const& v) {
324 os << v.k.rounds;
325 unsigned int const* p = &v.k.rd_key[0];
326 for(int i = 0; i < (v.k.rounds + 1); ++i) {
327 os << " " << p[0] << " " << p[1] << " " << p[2] << " " << p[3];
328 p += 4;
329 }
330 return os;
331 }
332 friend std::istream& operator>>(std::istream& is, aesopenssl16x8_key_t& v) {
333 is >> v.k.rounds;
334 unsigned int* p = &v.k.rd_key[0];
335 for(int i = 0; i < (v.k.rounds + 1); ++i) {
336 is >> p[0] >> p[1] >> p[2] >> p[3];
337 p += 4;
338 }
339 return is;
340 }
341};
342#else
343typedef struct aesopenssl16x8_key_t {
344 AES_KEY k;
345} aesopenssl16x8_key_t;
346R123_STATIC_INLINE struct aesopenssl16x8_key_t aesopenssl16x8keyinit(aesopenssl16x8_ukey_t uk) {
347 aesopenssl16x8_key_t ret;
348 AES_set_encrypt_key((unsigned char const*)&uk.v[0], 128, &ret.k);
349 return ret;
350}
351#endif
352
353R123_STATIC_INLINE R123_FORCE_INLINE(aesopenssl16x8_ctr_t aesopenssl16x8_R(aesopenssl16x8_ctr_t ctr, aesopenssl16x8_key_t key));
355aesopenssl16x8_ctr_t aesopenssl16x8_R(aesopenssl16x8_ctr_t ctr, aesopenssl16x8_key_t key) {
356 aesopenssl16x8_ctr_t ret;
357 AES_encrypt((unsigned char const*)&ctr.v[0], (unsigned char*)&ret.v[0], &key.k);
358 return ret;
359}
360
361#define aesopenssl16x8_rounds aesni4x32_rounds
362#define aesopenssl16x8(c, k) aesopenssl16x8_R(aesopenssl16x8_rounds)
363
364#ifdef __cplusplus
365namespace r123 {
366struct AESOpenSSL16x8 {
367 typedef aesopenssl16x8_ctr_t ctr_type;
368 typedef aesopenssl16x8_key_t key_type;
369 typedef aesopenssl16x8_ukey_t ukey_type;
370 static unsigned int const rounds = 10;
371 ctr_type operator()(ctr_type const& in, key_type const& k) {
372 ctr_type out;
373 AES_encrypt((unsigned char const*)&in[0], (unsigned char*)&out[0], &k.k);
374 return out;
375 }
376};
377} // namespace r123
378#endif /* __cplusplus */
379#endif /* R123_USE_AES_OPENSSL */
380
381#endif
#define R123_STATIC_ASSERT(expr, msg)
Definition: clangfeatures.h:57
#define R123_STATIC_INLINE
#define R123_FORCE_INLINE(decl)
#define R123_ASSERT(x)
Definition: array.h:344
mask_vector operator==(contiguous_tags_base< tag_type > a, tag_type b)
mask_vector operator!=(contiguous_tags_base< tag_type > a, tag_type b)
uint uint32_t