Handle find-doc-nits script rename
[openssl.git] / crypto / aes / aes_ige.c
1 /*
2  * Copyright 2006-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include "internal/cryptlib.h"
11
12 #include <openssl/aes.h>
13 #include "aes_locl.h"
14
15 #define N_WORDS (AES_BLOCK_SIZE / sizeof(unsigned long))
16 typedef struct {
17     unsigned long data[N_WORDS];
18 } aes_block_t;
19
20 /* XXX: probably some better way to do this */
21 #if defined(__i386__) || defined(__x86_64__)
22 # define UNALIGNED_MEMOPS_ARE_FAST 1
23 #else
24 # define UNALIGNED_MEMOPS_ARE_FAST 0
25 #endif
26
27 #if UNALIGNED_MEMOPS_ARE_FAST
28 # define load_block(d, s)        (d) = *(const aes_block_t *)(s)
29 # define store_block(d, s)       *(aes_block_t *)(d) = (s)
30 #else
31 # define load_block(d, s)        memcpy((d).data, (s), AES_BLOCK_SIZE)
32 # define store_block(d, s)       memcpy((d), (s).data, AES_BLOCK_SIZE)
33 #endif
34
35 /* N.B. The IV for this mode is _twice_ the block size */
36
37 void AES_ige_encrypt(const unsigned char *in, unsigned char *out,
38                      size_t length, const AES_KEY *key,
39                      unsigned char *ivec, const int enc)
40 {
41     size_t n;
42     size_t len = length;
43
44     if (length == 0)
45         return;
46
47     OPENSSL_assert(in && out && key && ivec);
48     OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
49     OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
50
51     len = length / AES_BLOCK_SIZE;
52
53     if (AES_ENCRYPT == enc) {
54         if (in != out &&
55             (UNALIGNED_MEMOPS_ARE_FAST
56              || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
57              0)) {
58             aes_block_t *ivp = (aes_block_t *) ivec;
59             aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
60
61             while (len) {
62                 aes_block_t *inp = (aes_block_t *) in;
63                 aes_block_t *outp = (aes_block_t *) out;
64
65                 for (n = 0; n < N_WORDS; ++n)
66                     outp->data[n] = inp->data[n] ^ ivp->data[n];
67                 AES_encrypt((unsigned char *)outp->data,
68                             (unsigned char *)outp->data, key);
69                 for (n = 0; n < N_WORDS; ++n)
70                     outp->data[n] ^= iv2p->data[n];
71                 ivp = outp;
72                 iv2p = inp;
73                 --len;
74                 in += AES_BLOCK_SIZE;
75                 out += AES_BLOCK_SIZE;
76             }
77             memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
78             memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
79         } else {
80             aes_block_t tmp, tmp2;
81             aes_block_t iv;
82             aes_block_t iv2;
83
84             load_block(iv, ivec);
85             load_block(iv2, ivec + AES_BLOCK_SIZE);
86
87             while (len) {
88                 load_block(tmp, in);
89                 for (n = 0; n < N_WORDS; ++n)
90                     tmp2.data[n] = tmp.data[n] ^ iv.data[n];
91                 AES_encrypt((unsigned char *)tmp2.data,
92                             (unsigned char *)tmp2.data, key);
93                 for (n = 0; n < N_WORDS; ++n)
94                     tmp2.data[n] ^= iv2.data[n];
95                 store_block(out, tmp2);
96                 iv = tmp2;
97                 iv2 = tmp;
98                 --len;
99                 in += AES_BLOCK_SIZE;
100                 out += AES_BLOCK_SIZE;
101             }
102             memcpy(ivec, iv.data, AES_BLOCK_SIZE);
103             memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
104         }
105     } else {
106         if (in != out &&
107             (UNALIGNED_MEMOPS_ARE_FAST
108              || ((size_t)in | (size_t)out | (size_t)ivec) % sizeof(long) ==
109              0)) {
110             aes_block_t *ivp = (aes_block_t *) ivec;
111             aes_block_t *iv2p = (aes_block_t *) (ivec + AES_BLOCK_SIZE);
112
113             while (len) {
114                 aes_block_t tmp;
115                 aes_block_t *inp = (aes_block_t *) in;
116                 aes_block_t *outp = (aes_block_t *) out;
117
118                 for (n = 0; n < N_WORDS; ++n)
119                     tmp.data[n] = inp->data[n] ^ iv2p->data[n];
120                 AES_decrypt((unsigned char *)tmp.data,
121                             (unsigned char *)outp->data, key);
122                 for (n = 0; n < N_WORDS; ++n)
123                     outp->data[n] ^= ivp->data[n];
124                 ivp = inp;
125                 iv2p = outp;
126                 --len;
127                 in += AES_BLOCK_SIZE;
128                 out += AES_BLOCK_SIZE;
129             }
130             memcpy(ivec, ivp->data, AES_BLOCK_SIZE);
131             memcpy(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE);
132         } else {
133             aes_block_t tmp, tmp2;
134             aes_block_t iv;
135             aes_block_t iv2;
136
137             load_block(iv, ivec);
138             load_block(iv2, ivec + AES_BLOCK_SIZE);
139
140             while (len) {
141                 load_block(tmp, in);
142                 tmp2 = tmp;
143                 for (n = 0; n < N_WORDS; ++n)
144                     tmp.data[n] ^= iv2.data[n];
145                 AES_decrypt((unsigned char *)tmp.data,
146                             (unsigned char *)tmp.data, key);
147                 for (n = 0; n < N_WORDS; ++n)
148                     tmp.data[n] ^= iv.data[n];
149                 store_block(out, tmp);
150                 iv = tmp2;
151                 iv2 = tmp;
152                 --len;
153                 in += AES_BLOCK_SIZE;
154                 out += AES_BLOCK_SIZE;
155             }
156             memcpy(ivec, iv.data, AES_BLOCK_SIZE);
157             memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE);
158         }
159     }
160 }
161
162 /*
163  * Note that its effectively impossible to do biIGE in anything other
164  * than a single pass, so no provision is made for chaining.
165  */
166
167 /* N.B. The IV for this mode is _four times_ the block size */
168
169 void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out,
170                         size_t length, const AES_KEY *key,
171                         const AES_KEY *key2, const unsigned char *ivec,
172                         const int enc)
173 {
174     size_t n;
175     size_t len = length;
176     unsigned char tmp[AES_BLOCK_SIZE];
177     unsigned char tmp2[AES_BLOCK_SIZE];
178     unsigned char tmp3[AES_BLOCK_SIZE];
179     unsigned char prev[AES_BLOCK_SIZE];
180     const unsigned char *iv;
181     const unsigned char *iv2;
182
183     OPENSSL_assert(in && out && key && ivec);
184     OPENSSL_assert((AES_ENCRYPT == enc) || (AES_DECRYPT == enc));
185     OPENSSL_assert((length % AES_BLOCK_SIZE) == 0);
186
187     if (AES_ENCRYPT == enc) {
188         /*
189          * XXX: Do a separate case for when in != out (strictly should check
190          * for overlap, too)
191          */
192
193         /* First the forward pass */
194         iv = ivec;
195         iv2 = ivec + AES_BLOCK_SIZE;
196         while (len >= AES_BLOCK_SIZE) {
197             for (n = 0; n < AES_BLOCK_SIZE; ++n)
198                 out[n] = in[n] ^ iv[n];
199             AES_encrypt(out, out, key);
200             for (n = 0; n < AES_BLOCK_SIZE; ++n)
201                 out[n] ^= iv2[n];
202             iv = out;
203             memcpy(prev, in, AES_BLOCK_SIZE);
204             iv2 = prev;
205             len -= AES_BLOCK_SIZE;
206             in += AES_BLOCK_SIZE;
207             out += AES_BLOCK_SIZE;
208         }
209
210         /* And now backwards */
211         iv = ivec + AES_BLOCK_SIZE * 2;
212         iv2 = ivec + AES_BLOCK_SIZE * 3;
213         len = length;
214         while (len >= AES_BLOCK_SIZE) {
215             out -= AES_BLOCK_SIZE;
216             /*
217              * XXX: reduce copies by alternating between buffers
218              */
219             memcpy(tmp, out, AES_BLOCK_SIZE);
220             for (n = 0; n < AES_BLOCK_SIZE; ++n)
221                 out[n] ^= iv[n];
222             /*
223              * hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE);
224              */
225             AES_encrypt(out, out, key);
226             /*
227              * hexdump(stdout,"enc", out, AES_BLOCK_SIZE);
228              */
229             /*
230              * hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE);
231              */
232             for (n = 0; n < AES_BLOCK_SIZE; ++n)
233                 out[n] ^= iv2[n];
234             /*
235              * hexdump(stdout,"out", out, AES_BLOCK_SIZE);
236              */
237             iv = out;
238             memcpy(prev, tmp, AES_BLOCK_SIZE);
239             iv2 = prev;
240             len -= AES_BLOCK_SIZE;
241         }
242     } else {
243         /* First backwards */
244         iv = ivec + AES_BLOCK_SIZE * 2;
245         iv2 = ivec + AES_BLOCK_SIZE * 3;
246         in += length;
247         out += length;
248         while (len >= AES_BLOCK_SIZE) {
249             in -= AES_BLOCK_SIZE;
250             out -= AES_BLOCK_SIZE;
251             memcpy(tmp, in, AES_BLOCK_SIZE);
252             memcpy(tmp2, in, AES_BLOCK_SIZE);
253             for (n = 0; n < AES_BLOCK_SIZE; ++n)
254                 tmp[n] ^= iv2[n];
255             AES_decrypt(tmp, out, key);
256             for (n = 0; n < AES_BLOCK_SIZE; ++n)
257                 out[n] ^= iv[n];
258             memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
259             iv = tmp3;
260             iv2 = out;
261             len -= AES_BLOCK_SIZE;
262         }
263
264         /* And now forwards */
265         iv = ivec;
266         iv2 = ivec + AES_BLOCK_SIZE;
267         len = length;
268         while (len >= AES_BLOCK_SIZE) {
269             memcpy(tmp, out, AES_BLOCK_SIZE);
270             memcpy(tmp2, out, AES_BLOCK_SIZE);
271             for (n = 0; n < AES_BLOCK_SIZE; ++n)
272                 tmp[n] ^= iv2[n];
273             AES_decrypt(tmp, out, key);
274             for (n = 0; n < AES_BLOCK_SIZE; ++n)
275                 out[n] ^= iv[n];
276             memcpy(tmp3, tmp2, AES_BLOCK_SIZE);
277             iv = tmp3;
278             iv2 = out;
279             len -= AES_BLOCK_SIZE;
280             in += AES_BLOCK_SIZE;
281             out += AES_BLOCK_SIZE;
282         }
283     }
284 }