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