RSA key generation: ensure BN_mod_inverse and BN_mod_exp_mont both get called with...
[openssl.git] / crypto / aes / aes_ige.c
1 /* crypto/aes/aes_ige.c */
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         if (in != out &&
94             (UNALIGNED_MEMOPS_ARE_FAST
95              || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
96              0)) {
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                 aes_block_t *inp = (aes_block_t *) in;
102                 aes_block_t *outp = (aes_block_t *) out;
103
104                 for (n = 0; n < N_WORDS; ++n)
105                     outp->data[n] = inp->data[n] ^ ivp->data[n];
106                 AES_encrypt((unsigned char *)outp->data,
107                             (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         } else {
119             aes_block_t tmp, tmp2;
120             aes_block_t iv;
121             aes_block_t iv2;
122
123             load_block(iv, ivec);
124             load_block(iv2, ivec + AES_BLOCK_SIZE);
125
126             while (len) {
127                 load_block(tmp, in);
128                 for (n = 0; n < N_WORDS; ++n)
129                     tmp2.data[n] = tmp.data[n] ^ iv.data[n];
130                 AES_encrypt((unsigned char *)tmp2.data,
131                             (unsigned char *)tmp2.data, key);
132                 for (n = 0; n < N_WORDS; ++n)
133                     tmp2.data[n] ^= iv2.data[n];
134                 store_block(out, tmp2);
135                 iv = tmp2;
136                 iv2 = tmp;
137                 --len;
138                 in += AES_BLOCK_SIZE;
139                 out += AES_BLOCK_SIZE;
140             }
141             memcpy(ivec, iv.data, AES_BLOCK_SIZE);
142             memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
143         }
144     } else {
145         if (in != out &&
146             (UNALIGNED_MEMOPS_ARE_FAST
147              || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
148              0)) {
149             aes_block_t *ivp = (aes_block_t *) ivec;
150             aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
151
152             while (len) {
153                 aes_block_t tmp;
154                 aes_block_t *inp = (aes_block_t *) in;
155                 aes_block_t *outp = (aes_block_t *) out;
156
157                 for (n = 0; n < N_WORDS; ++n)
158                     tmp.data[n] = inp->data[n] ^ iv2p->data[n];
159                 AES_decrypt((unsigned char *)tmp.data,
160                             (unsigned char *)outp->data, key);
161                 for (n = 0; n < N_WORDS; ++n)
162                     outp->data[n] ^= ivp->data[n];
163                 ivp = inp;
164                 iv2p = outp;
165                 --len;
166                 in += AES_BLOCK_SIZE;
167                 out += AES_BLOCK_SIZE;
168             }
169             memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
170             memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
171         } else {
172             aes_block_t tmp, tmp2;
173             aes_block_t iv;
174             aes_block_t iv2;
175
176             load_block(iv, ivec);
177             load_block(iv2, ivec + AES_BLOCK_SIZE);
178
179             while (len) {
180                 load_block(tmp, in);
181                 tmp2 = tmp;
182                 for (n = 0; n < N_WORDS; ++n)
183                     tmp.data[n] ^= iv2.data[n];
184                 AES_decrypt((unsigned char *)tmp.data,
185                             (unsigned char *)tmp.data, key);
186                 for (n = 0; n < N_WORDS; ++n)
187                     tmp.data[n] ^= iv.data[n];
188                 store_block(out, tmp);
189                 iv = tmp2;
190                 iv2 = tmp;
191                 --len;
192                 in += AES_BLOCK_SIZE;
193                 out += AES_BLOCK_SIZE;
194             }
195             memcpy(ivec, iv.data, AES_BLOCK_SIZE);
196             memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
197         }
198     }
199 }
200
201 /*
202  * Note that its effectively impossible to do biIGE in anything other
203  * than a single pass, so no provision is made for chaining.
204  */
205
206 /* N.B. The IV for this mode is _four times_ the block size */
207
208 void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
209                         size_t length, const AES_KEY *key,
210                         const AES_KEY *key2, const unsigned char *ivec,
211                         const int enc)
212 {
213     size_t n;
214     size_t len = length;
215     unsigned char tmp[AES_BLOCK_SIZE];
216     unsigned char tmp2[AES_BLOCK_SIZE];
217     unsigned char tmp3[AES_BLOCK_SIZE];
218     unsigned char prev[AES_BLOCK_SIZE];
219     const unsigned char *iv;
220     const unsigned char *iv2;
221
222     OPENSSL_assert(in && out && key && ivec);
223     OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
224     OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
225
226     if (AES_ENCRYPT == enc) {
227         /*
228          * XXX: Do a separate case for when in != out (strictly should check
229          * for overlap, too)
230          */
231
232         /* First the forward pass */
233         iv = ivec;
234         iv2 = ivec + AES_BLOCK_SIZE;
235         while (len >= AES_BLOCK_SIZE) {
236             for (n = 0; n < AES_BLOCK_SIZE; ++n)
237                 out[n] = in[n] ^ iv[n];
238             AES_encrypt(out, out, key);
239             for (n = 0; n < AES_BLOCK_SIZE; ++n)
240                 out[n] ^= iv2[n];
241             iv = out;
242             memcpy(prev, in, AES_BLOCK_SIZE);
243             iv2 = prev;
244             len -= AES_BLOCK_SIZE;
245             in += AES_BLOCK_SIZE;
246             out += AES_BLOCK_SIZE;
247         }
248
249         /* And now backwards */
250         iv = ivec + AES_BLOCK_SIZE * 2;
251         iv2 = ivec + AES_BLOCK_SIZE * 3;
252         len = length;
253         while (len >= AES_BLOCK_SIZE) {
254             out -= AES_BLOCK_SIZE;
255             /*
256              * XXX: reduce copies by alternating between buffers
257              */
258             memcpy(tmp, out, AES_BLOCK_SIZE);
259             for (n = 0; n < AES_BLOCK_SIZE; ++n)
260                 out[n] ^= iv[n];
261             /*
262              * hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE);
263              */
264             AES_encrypt(out, out, key);
265             /*
266              * hexdump(stdout,"enc", out, AES_BLOCK_SIZE);
267              */
268             /*
269              * hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE);
270              */
271             for (n = 0; n < AES_BLOCK_SIZE; ++n)
272                 out[n] ^= iv2[n];
273             /*
274              * hexdump(stdout,"out", out, AES_BLOCK_SIZE);
275              */
276             iv = out;
277             memcpy(prev, tmp, AES_BLOCK_SIZE);
278             iv2 = prev;
279             len -= AES_BLOCK_SIZE;
280         }
281     } else {
282         /* First backwards */
283         iv = ivec + AES_BLOCK_SIZE * 2;
284         iv2 = ivec + AES_BLOCK_SIZE * 3;
285         in += length;
286         out += length;
287         while (len >= AES_BLOCK_SIZE) {
288             in -= AES_BLOCK_SIZE;
289             out -= AES_BLOCK_SIZE;
290             memcpy(tmp, in, AES_BLOCK_SIZE);
291             memcpy(tmp2, in, AES_BLOCK_SIZE);
292             for (n = 0; n < AES_BLOCK_SIZE; ++n)
293                 tmp[n] ^= iv2[n];
294             AES_decrypt(tmp, out, key);
295             for (n = 0; n < AES_BLOCK_SIZE; ++n)
296                 out[n] ^= iv[n];
297             memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
298             iv = tmp3;
299             iv2 = out;
300             len -= AES_BLOCK_SIZE;
301         }
302
303         /* And now forwards */
304         iv = ivec;
305         iv2 = ivec + AES_BLOCK_SIZE;
306         len = length;
307         while (len >= AES_BLOCK_SIZE) {
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 }