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