OLD | NEW |
| (Empty) |
1 /* crypto/aes/aes_ige.c -*- mode:C; c-file-style: "eay" -*- */ | |
2 /* ==================================================================== | |
3 * Copyright (c) 2006 The OpenSSL Project. 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 | |
7 * are met: | |
8 * | |
9 * 1. Redistributions of source code must retain the above copyright | |
10 * notice, this list of conditions and the following disclaimer. | |
11 * | |
12 * 2. Redistributions in binary form must reproduce the above copyright | |
13 * notice, this list of conditions and the following disclaimer in | |
14 * the documentation and/or other materials provided with the | |
15 * distribution. | |
16 * | |
17 * 3. All advertising materials mentioning features or use of this | |
18 * software must display the following acknowledgment: | |
19 * "This product includes software developed by the OpenSSL Project | |
20 * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" | |
21 * | |
22 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to | |
23 * endorse or promote products derived from this software without | |
24 * prior written permission. For written permission, please contact | |
25 * openssl-core@openssl.org. | |
26 * | |
27 * 5. Products derived from this software may not be called "OpenSSL" | |
28 * nor may "OpenSSL" appear in their names without prior written | |
29 * permission of the OpenSSL Project. | |
30 * | |
31 * 6. Redistributions of any form whatsoever must retain the following | |
32 * acknowledgment: | |
33 * "This product includes software developed by the OpenSSL Project | |
34 * for use in the OpenSSL Toolkit (http://www.openssl.org/)" | |
35 * | |
36 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY | |
37 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
38 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
39 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR | |
40 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
41 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
42 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
43 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
45 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
46 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
47 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
48 * ==================================================================== | |
49 * | |
50 */ | |
51 | |
52 #include "cryptlib.h" | |
53 | |
54 #include <openssl/aes.h> | |
55 #include "aes_locl.h" | |
56 | |
57 #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long)) | |
58 typedef struct { | |
59 unsigned long data[N_WORDS]; | |
60 } aes_block_t; | |
61 | |
62 /* XXX: probably some better way to do this */ | |
63 #if defined(__i386__) || defined(__x86_64__) | |
64 #define UNALIGNED_MEMOPS_ARE_FAST 1 | |
65 #else | |
66 #define UNALIGNED_MEMOPS_ARE_FAST 0 | |
67 #endif | |
68 | |
69 #if UNALIGNED_MEMOPS_ARE_FAST | |
70 #define load_block(d, s) (d) = *(const aes_block_t *)(s) | |
71 #define store_block(d, s) *(aes_block_t *)(d) = (s) | |
72 #else | |
73 #define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE) | |
74 #define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE) | |
75 #endif | |
76 | |
77 /* N.B. The IV for this mode is _twice_ the block size */ | |
78 | |
79 void AES_ige_encrypt(const unsigned char *in, unsigned char *out, | |
80 size_t length, const AES_KEY *key, | |
81 unsigned char *ivec, const int enc) | |
82 { | |
83 size_t n; | |
84 size_t len = length; | |
85 | |
86 OPENSSL_assert(in && out && key && ivec); | |
87 OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); | |
88 OPENSSL_assert((length%AES_BLOCK_SIZE) == 0); | |
89 | |
90 len = length / AES_BLOCK_SIZE; | |
91 | |
92 if (AES_ENCRYPT == enc) | |
93 { | |
94 if (in != out && | |
95 (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_
t)ivec)%sizeof(long)==0)) | |
96 { | |
97 aes_block_t *ivp = (aes_block_t *)ivec; | |
98 aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZ
E); | |
99 | |
100 while (len) | |
101 { | |
102 aes_block_t *inp = (aes_block_t *)in; | |
103 aes_block_t *outp = (aes_block_t *)out; | |
104 | |
105 for(n=0 ; n < N_WORDS; ++n) | |
106 outp->data[n] = inp->data[n] ^ ivp->data
[n]; | |
107 AES_encrypt((unsigned char *)outp->data, (unsign
ed char *)outp->data, key); | |
108 for(n=0 ; n < N_WORDS; ++n) | |
109 outp->data[n] ^= iv2p->data[n]; | |
110 ivp = outp; | |
111 iv2p = inp; | |
112 --len; | |
113 in += AES_BLOCK_SIZE; | |
114 out += AES_BLOCK_SIZE; | |
115 } | |
116 memcpy(ivec, ivp->data, AES_BLOCK_SIZE); | |
117 memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE
); | |
118 } | |
119 else | |
120 { | |
121 aes_block_t tmp, tmp2; | |
122 aes_block_t iv; | |
123 aes_block_t iv2; | |
124 | |
125 load_block(iv, ivec); | |
126 load_block(iv2, ivec + AES_BLOCK_SIZE); | |
127 | |
128 while (len) | |
129 { | |
130 load_block(tmp, in); | |
131 for(n=0 ; n < N_WORDS; ++n) | |
132 tmp2.data[n] = tmp.data[n] ^ iv.data[n]; | |
133 AES_encrypt((unsigned char *)tmp2.data, (unsigne
d char *)tmp2.data, key); | |
134 for(n=0 ; n < N_WORDS; ++n) | |
135 tmp2.data[n] ^= iv2.data[n]; | |
136 store_block(out, tmp2); | |
137 iv = tmp2; | |
138 iv2 = tmp; | |
139 --len; | |
140 in += AES_BLOCK_SIZE; | |
141 out += AES_BLOCK_SIZE; | |
142 } | |
143 memcpy(ivec, iv.data, AES_BLOCK_SIZE); | |
144 memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); | |
145 } | |
146 } | |
147 else | |
148 { | |
149 if (in != out && | |
150 (UNALIGNED_MEMOPS_ARE_FAST || ((size_t)in|(size_t)out|(size_
t)ivec)%sizeof(long)==0)) | |
151 { | |
152 aes_block_t *ivp = (aes_block_t *)ivec; | |
153 aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZ
E); | |
154 | |
155 while (len) | |
156 { | |
157 aes_block_t tmp; | |
158 aes_block_t *inp = (aes_block_t *)in; | |
159 aes_block_t *outp = (aes_block_t *)out; | |
160 | |
161 for(n=0 ; n < N_WORDS; ++n) | |
162 tmp.data[n] = inp->data[n] ^ iv2p->data[
n]; | |
163 AES_decrypt((unsigned char *)tmp.data, (unsigned
char *)outp->data, key); | |
164 for(n=0 ; n < N_WORDS; ++n) | |
165 outp->data[n] ^= ivp->data[n]; | |
166 ivp = inp; | |
167 iv2p = outp; | |
168 --len; | |
169 in += AES_BLOCK_SIZE; | |
170 out += AES_BLOCK_SIZE; | |
171 } | |
172 memcpy(ivec, ivp->data, AES_BLOCK_SIZE); | |
173 memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE
); | |
174 } | |
175 else | |
176 { | |
177 aes_block_t tmp, tmp2; | |
178 aes_block_t iv; | |
179 aes_block_t iv2; | |
180 | |
181 load_block(iv, ivec); | |
182 load_block(iv2, ivec + AES_BLOCK_SIZE); | |
183 | |
184 while (len) | |
185 { | |
186 load_block(tmp, in); | |
187 tmp2 = tmp; | |
188 for(n=0 ; n < N_WORDS; ++n) | |
189 tmp.data[n] ^= iv2.data[n]; | |
190 AES_decrypt((unsigned char *)tmp.data, (unsigned
char *)tmp.data, key); | |
191 for(n=0 ; n < N_WORDS; ++n) | |
192 tmp.data[n] ^= iv.data[n]; | |
193 store_block(out, tmp); | |
194 iv = tmp2; | |
195 iv2 = tmp; | |
196 --len; | |
197 in += AES_BLOCK_SIZE; | |
198 out += AES_BLOCK_SIZE; | |
199 } | |
200 memcpy(ivec, iv.data, AES_BLOCK_SIZE); | |
201 memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); | |
202 } | |
203 } | |
204 } | |
205 | |
206 /* | |
207 * Note that its effectively impossible to do biIGE in anything other | |
208 * than a single pass, so no provision is made for chaining. | |
209 */ | |
210 | |
211 /* N.B. The IV for this mode is _four times_ the block size */ | |
212 | |
213 void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, | |
214 size_t length, const AES_KEY *ke
y, | |
215 const AES_KEY *key2, const unsig
ned char *ivec, | |
216 const int enc) | |
217 { | |
218 size_t n; | |
219 size_t len = length; | |
220 unsigned char tmp[AES_BLOCK_SIZE]; | |
221 unsigned char tmp2[AES_BLOCK_SIZE]; | |
222 unsigned char tmp3[AES_BLOCK_SIZE]; | |
223 unsigned char prev[AES_BLOCK_SIZE]; | |
224 const unsigned char *iv; | |
225 const unsigned char *iv2; | |
226 | |
227 OPENSSL_assert(in && out && key && ivec); | |
228 OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); | |
229 OPENSSL_assert((length%AES_BLOCK_SIZE) == 0); | |
230 | |
231 if (AES_ENCRYPT == enc) | |
232 { | |
233 /* XXX: Do a separate case for when in != out (strictly should | |
234 check for overlap, too) */ | |
235 | |
236 /* First the forward pass */ | |
237 iv = ivec; | |
238 iv2 = ivec + AES_BLOCK_SIZE; | |
239 while (len >= AES_BLOCK_SIZE) | |
240 { | |
241 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) | |
242 out[n] = in[n] ^ iv[n]; | |
243 AES_encrypt(out, out, key); | |
244 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) | |
245 out[n] ^= iv2[n]; | |
246 iv = out; | |
247 memcpy(prev, in, AES_BLOCK_SIZE); | |
248 iv2 = prev; | |
249 len -= AES_BLOCK_SIZE; | |
250 in += AES_BLOCK_SIZE; | |
251 out += AES_BLOCK_SIZE; | |
252 } | |
253 | |
254 /* And now backwards */ | |
255 iv = ivec + AES_BLOCK_SIZE*2; | |
256 iv2 = ivec + AES_BLOCK_SIZE*3; | |
257 len = length; | |
258 while(len >= AES_BLOCK_SIZE) | |
259 { | |
260 out -= AES_BLOCK_SIZE; | |
261 /* XXX: reduce copies by alternating between buffers */ | |
262 memcpy(tmp, out, AES_BLOCK_SIZE); | |
263 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) | |
264 out[n] ^= iv[n]; | |
265 /* hexdump(stdout, "out ^ iv", out,
AES_BLOCK_SIZE); */ | |
266 AES_encrypt(out, out, key); | |
267 /* hexdump(stdout,"enc", out, AES_B
LOCK_SIZE); */ | |
268 /* hexdump(stdout,"iv2", iv2, AES_B
LOCK_SIZE); */ | |
269 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) | |
270 out[n] ^= iv2[n]; | |
271 /* hexdump(stdout,"out", out, AES_B
LOCK_SIZE); */ | |
272 iv = out; | |
273 memcpy(prev, tmp, AES_BLOCK_SIZE); | |
274 iv2 = prev; | |
275 len -= AES_BLOCK_SIZE; | |
276 } | |
277 } | |
278 else | |
279 { | |
280 /* First backwards */ | |
281 iv = ivec + AES_BLOCK_SIZE*2; | |
282 iv2 = ivec + AES_BLOCK_SIZE*3; | |
283 in += length; | |
284 out += length; | |
285 while (len >= AES_BLOCK_SIZE) | |
286 { | |
287 in -= AES_BLOCK_SIZE; | |
288 out -= AES_BLOCK_SIZE; | |
289 memcpy(tmp, in, AES_BLOCK_SIZE); | |
290 memcpy(tmp2, in, AES_BLOCK_SIZE); | |
291 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) | |
292 tmp[n] ^= iv2[n]; | |
293 AES_decrypt(tmp, out, key); | |
294 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) | |
295 out[n] ^= iv[n]; | |
296 memcpy(tmp3, tmp2, AES_BLOCK_SIZE); | |
297 iv = tmp3; | |
298 iv2 = out; | |
299 len -= AES_BLOCK_SIZE; | |
300 } | |
301 | |
302 /* And now forwards */ | |
303 iv = ivec; | |
304 iv2 = ivec + AES_BLOCK_SIZE; | |
305 len = length; | |
306 while (len >= AES_BLOCK_SIZE) | |
307 { | |
308 memcpy(tmp, out, AES_BLOCK_SIZE); | |
309 memcpy(tmp2, out, AES_BLOCK_SIZE); | |
310 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) | |
311 tmp[n] ^= iv2[n]; | |
312 AES_decrypt(tmp, out, key); | |
313 for(n=0 ; n < AES_BLOCK_SIZE ; ++n) | |
314 out[n] ^= iv[n]; | |
315 memcpy(tmp3, tmp2, AES_BLOCK_SIZE); | |
316 iv = tmp3; | |
317 iv2 = out; | |
318 len -= AES_BLOCK_SIZE; | |
319 in += AES_BLOCK_SIZE; | |
320 out += AES_BLOCK_SIZE; | |
321 } | |
322 } | |
323 } | |
OLD | NEW |