Annotation of embedaddon/strongswan/src/libstrongswan/plugins/aesni/aesni_key.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2015 Martin Willi
3: * Copyright (C) 2015 revosec AG
4: *
5: * This program is free software; you can redistribute it and/or modify it
6: * under the terms of the GNU General Public License as published by the
7: * Free Software Foundation; either version 2 of the License, or (at your
8: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9: *
10: * This program is distributed in the hope that it will be useful, but
11: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13: * for more details.
14: */
15:
16: #include "aesni_key.h"
17:
18: /**
19: * Rounds used for each AES key size
20: */
21: #define AES128_ROUNDS 10
22: #define AES192_ROUNDS 12
23: #define AES256_ROUNDS 14
24:
25: typedef struct private_aesni_key_t private_aesni_key_t;
26:
27: /**
28: * Private data of an aesni_key_t object.
29: */
30: struct private_aesni_key_t {
31:
32: /**
33: * Public aesni_key_t interface.
34: */
35: aesni_key_t public;
36: };
37:
38: /**
39: * Invert round encryption keys to get a decryption key schedule
40: */
41: static void reverse_key(aesni_key_t *this)
42: {
43: __m128i t[this->rounds + 1];
44: int i;
45:
46: for (i = 0; i <= this->rounds; i++)
47: {
48: t[i] = this->schedule[i];
49: }
50: this->schedule[this->rounds] = t[0];
51: for (i = 1; i < this->rounds; i++)
52: {
53: this->schedule[this->rounds - i] = _mm_aesimc_si128(t[i]);
54: }
55: this->schedule[0] = t[this->rounds];
56:
57: memwipe(t, sizeof(t));
58: }
59:
60: /**
61: * Assist in creating a 128-bit round key
62: */
63: static __m128i assist128(__m128i a, __m128i b)
64: {
65: __m128i c;
66:
67: b = _mm_shuffle_epi32(b ,0xff);
68: c = _mm_slli_si128(a, 0x04);
69: a = _mm_xor_si128(a, c);
70: c = _mm_slli_si128(c, 0x04);
71: a = _mm_xor_si128(a, c);
72: c = _mm_slli_si128(c, 0x04);
73: a = _mm_xor_si128(a, c);
74: a = _mm_xor_si128(a, b);
75:
76: return a;
77: }
78:
79: /**
80: * Expand a 128-bit key to encryption round keys
81: */
82: static void expand128(__m128i *key, __m128i *schedule)
83: {
84: __m128i t;
85:
86: schedule[0] = t = _mm_loadu_si128(key);
87: schedule[1] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x01));
88: schedule[2] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x02));
89: schedule[3] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x04));
90: schedule[4] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x08));
91: schedule[5] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x10));
92: schedule[6] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x20));
93: schedule[7] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x40));
94: schedule[8] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x80));
95: schedule[9] = t = assist128(t, _mm_aeskeygenassist_si128(t, 0x1b));
96: schedule[10] = assist128(t, _mm_aeskeygenassist_si128(t, 0x36));
97: }
98:
99: /**
100: * Assist in creating a 192-bit round key
101: */
102: static __m128i assist192(__m128i b, __m128i c, __m128i *a)
103: {
104: __m128i t;
105:
106: b = _mm_shuffle_epi32(b, 0x55);
107: t = _mm_slli_si128(*a, 0x04);
108: *a = _mm_xor_si128(*a, t);
109: t = _mm_slli_si128(t, 0x04);
110: *a = _mm_xor_si128(*a, t);
111: t = _mm_slli_si128(t, 0x04);
112: *a = _mm_xor_si128(*a, t);
113: *a = _mm_xor_si128(*a, b);
114: b = _mm_shuffle_epi32(*a, 0xff);
115: t = _mm_slli_si128(c, 0x04);
116: t = _mm_xor_si128(c, t);
117: t = _mm_xor_si128(t, b);
118:
119: return t;
120: }
121:
122: /**
123: * return a[63:0] | b[63:0] << 64
124: */
125: static __m128i _mm_shuffle_i00(__m128i a, __m128i b)
126: {
127: return (__m128i)_mm_shuffle_pd((__m128d)a, (__m128d)b, 0);
128: }
129:
130: /**
131: * return a[127:64] >> 64 | b[63:0] << 64
132: */
133: static __m128i _mm_shuffle_i01(__m128i a, __m128i b)
134: {
135: return (__m128i)_mm_shuffle_pd((__m128d)a, (__m128d)b, 1);
136: }
137:
138: /**
139: * Expand a 192-bit encryption key to round keys
140: */
141: static void expand192(__m128i *key, __m128i *schedule)
142: {
143: __m128i t1, t2, t3;
144:
145: schedule[0] = t1 = _mm_loadu_si128(key);
146: t2 = t3 = _mm_loadu_si128(key + 1);
147:
148: t2 = assist192(_mm_aeskeygenassist_si128(t2, 0x1), t2, &t1);
149: schedule[1] = _mm_shuffle_i00(t3, t1);
150: schedule[2] = _mm_shuffle_i01(t1, t2);
151: t2 = t3 = assist192(_mm_aeskeygenassist_si128(t2, 0x2), t2, &t1);
152: schedule[3] = t1;
153:
154: t2 = assist192(_mm_aeskeygenassist_si128(t2, 0x4), t2, &t1);
155: schedule[4] = _mm_shuffle_i00(t3, t1);
156: schedule[5] = _mm_shuffle_i01(t1, t2);
157: t2 = t3 = assist192(_mm_aeskeygenassist_si128(t2, 0x8), t2, &t1);
158: schedule[6] = t1;
159:
160: t2 = assist192(_mm_aeskeygenassist_si128 (t2,0x10), t2, &t1);
161: schedule[7] = _mm_shuffle_i00(t3, t1);
162: schedule[8] = _mm_shuffle_i01(t1, t2);
163: t2 = t3 = assist192(_mm_aeskeygenassist_si128 (t2,0x20), t2, &t1);
164: schedule[9] = t1;
165:
166: t2 = assist192(_mm_aeskeygenassist_si128(t2, 0x40), t2, &t1);
167: schedule[10] = _mm_shuffle_i00(t3, t1);
168: schedule[11] = _mm_shuffle_i01(t1, t2);
169: assist192(_mm_aeskeygenassist_si128(t2, 0x80), t2, &t1);
170: schedule[12] = t1;
171: }
172:
173: /**
174: * Assist in creating a 256-bit round key
175: */
176: static __m128i assist256_1(__m128i a, __m128i b)
177: {
178: __m128i x, y;
179:
180: b = _mm_shuffle_epi32(b, 0xff);
181: y = _mm_slli_si128(a, 0x04);
182: x = _mm_xor_si128(a, y);
183: y = _mm_slli_si128(y, 0x04);
184: x = _mm_xor_si128 (x, y);
185: y = _mm_slli_si128(y, 0x04);
186: x = _mm_xor_si128(x, y);
187: x = _mm_xor_si128(x, b);
188:
189: return x;
190: }
191:
192: /**
193: * Assist in creating a 256-bit round key
194: */
195: static __m128i assist256_2(__m128i a, __m128i b)
196: {
197: __m128i x, y, z;
198:
199: y = _mm_aeskeygenassist_si128(a, 0x00);
200: z = _mm_shuffle_epi32(y, 0xaa);
201: y = _mm_slli_si128(b, 0x04);
202: x = _mm_xor_si128(b, y);
203: y = _mm_slli_si128(y, 0x04);
204: x = _mm_xor_si128(x, y);
205: y = _mm_slli_si128(y, 0x04);
206: x = _mm_xor_si128(x, y);
207: x = _mm_xor_si128(x, z);
208:
209: return x;
210: }
211:
212: /**
213: * Expand a 256-bit encryption key to round keys
214: */
215: static void expand256(__m128i *key, __m128i *schedule)
216: {
217: __m128i t1, t2;
218:
219: schedule[0] = t1 = _mm_loadu_si128(key);
220: schedule[1] = t2 = _mm_loadu_si128(key + 1);
221:
222: schedule[2] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x01));
223: schedule[3] = t2 = assist256_2(t1, t2);
224:
225: schedule[4] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x02));
226: schedule[5] = t2 = assist256_2(t1, t2);
227:
228: schedule[6] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x04));
229: schedule[7] = t2 = assist256_2(t1, t2);
230:
231: schedule[8] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x08));
232: schedule[9] = t2 = assist256_2(t1, t2);
233:
234: schedule[10] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x10));
235: schedule[11] = t2 = assist256_2(t1, t2);
236:
237: schedule[12] = t1 = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x20));
238: schedule[13] = t2 = assist256_2(t1, t2);
239:
240: schedule[14] = assist256_1(t1, _mm_aeskeygenassist_si128(t2, 0x40));
241: }
242:
243: METHOD(aesni_key_t, destroy, void,
244: private_aesni_key_t *this)
245: {
246: memwipe(this, sizeof(*this) + (this->public.rounds + 1) * AES_BLOCK_SIZE);
247: free_align(this);
248: }
249:
250: /**
251: * See header
252: */
253: aesni_key_t *aesni_key_create(bool encrypt, chunk_t key)
254: {
255: private_aesni_key_t *this;
256: int rounds;
257:
258: switch (key.len)
259: {
260: case 16:
261: rounds = AES128_ROUNDS;
262: break;
263: case 24:
264: rounds = AES192_ROUNDS;
265: break;
266: case 32:
267: rounds = AES256_ROUNDS;
268: break;
269: default:
270: return NULL;
271: }
272:
273: INIT_EXTRA_ALIGN(this, (rounds + 1) * AES_BLOCK_SIZE, sizeof(__m128i),
274: .public = {
275: .destroy = _destroy,
276: .rounds = rounds,
277: },
278: );
279:
280: switch (key.len)
281: {
282: case 16:
283: expand128((__m128i*)key.ptr, this->public.schedule);
284: break;
285: case 24:
286: expand192((__m128i*)key.ptr, this->public.schedule);
287: break;
288: case 32:
289: expand256((__m128i*)key.ptr, this->public.schedule);
290: break;
291: default:
292: break;
293: }
294:
295: if (!encrypt)
296: {
297: reverse_key(&this->public);
298: }
299:
300: return &this->public;
301: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>