vici: With start_action=start, terminate IKE_SA without children on unload
[strongswan.git] / src / libstrongswan / plugins / aesni / aesni_key.c
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 }