OpenSSL  1.0.1c
 All Classes Files Functions Variables Typedefs Enumerations Enumerator Macros
aes_ige.c
Go to the documentation of this file.
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
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_SIZE);
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, (unsigned 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, (unsigned 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_SIZE);
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 *key,
215  const AES_KEY *key2, const unsigned 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_BLOCK_SIZE); */
268  /* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */
269  for(n=0 ; n < AES_BLOCK_SIZE ; ++n)
270  out[n] ^= iv2[n];
271  /* hexdump(stdout,"out", out, AES_BLOCK_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  }