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 |
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 |
/* |
58 |
static void hexdump(FILE *f,const char *title,const unsigned char *s,int l) |
59 |
{ |
60 |
int n=0; |
61 |
|
62 |
fprintf(f,"%s",title); |
63 |
for( ; n < l ; ++n) |
64 |
{ |
65 |
if((n%16) == 0) |
66 |
fprintf(f,"\n%04x",n); |
67 |
fprintf(f," %02x",s[n]); |
68 |
} |
69 |
fprintf(f,"\n"); |
70 |
} |
71 |
*/ |
72 |
|
73 |
/* N.B. The IV for this mode is _twice_ the block size */ |
74 |
|
75 |
void AES_ige_encrypt(const unsigned char *in, unsigned char *out, |
76 |
const unsigned long length, const AES_KEY *key, |
77 |
unsigned char *ivec, const int enc) |
78 |
{ |
79 |
unsigned long n; |
80 |
unsigned long len = length; |
81 |
unsigned char tmp[AES_BLOCK_SIZE]; |
82 |
unsigned char tmp2[AES_BLOCK_SIZE]; |
83 |
unsigned char prev[AES_BLOCK_SIZE]; |
84 |
const unsigned char *iv = ivec; |
85 |
const unsigned char *iv2 = ivec + AES_BLOCK_SIZE; |
86 |
|
87 |
OPENSSL_assert(in && out && key && ivec); |
88 |
OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); |
89 |
OPENSSL_assert((length%AES_BLOCK_SIZE) == 0); |
90 |
|
91 |
if (AES_ENCRYPT == enc) |
92 |
{ |
93 |
/* XXX: Do a separate case for when in != out (strictly should |
94 |
check for overlap, too) */ |
95 |
while (len >= AES_BLOCK_SIZE) |
96 |
{ |
97 |
/* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ |
98 |
/* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ |
99 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
100 |
out[n] = in[n] ^ iv[n]; |
101 |
/* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ |
102 |
AES_encrypt(out, out, key); |
103 |
/* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ |
104 |
/* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ |
105 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
106 |
out[n] ^= iv2[n]; |
107 |
/* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ |
108 |
iv = out; |
109 |
memcpy(prev, in, AES_BLOCK_SIZE); |
110 |
iv2 = prev; |
111 |
len -= AES_BLOCK_SIZE; |
112 |
in += AES_BLOCK_SIZE; |
113 |
out += AES_BLOCK_SIZE; |
114 |
} |
115 |
memcpy(ivec, iv, AES_BLOCK_SIZE); |
116 |
memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); |
117 |
} |
118 |
else |
119 |
{ |
120 |
while (len >= AES_BLOCK_SIZE) |
121 |
{ |
122 |
memcpy(tmp, in, AES_BLOCK_SIZE); |
123 |
memcpy(tmp2, in, AES_BLOCK_SIZE); |
124 |
/* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ |
125 |
/* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ |
126 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
127 |
tmp[n] ^= iv2[n]; |
128 |
/* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ |
129 |
AES_decrypt(tmp, out, key); |
130 |
/* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ |
131 |
/* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ |
132 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
133 |
out[n] ^= ivec[n]; |
134 |
/* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ |
135 |
memcpy(ivec, tmp2, AES_BLOCK_SIZE); |
136 |
iv2 = out; |
137 |
len -= AES_BLOCK_SIZE; |
138 |
in += AES_BLOCK_SIZE; |
139 |
out += AES_BLOCK_SIZE; |
140 |
} |
141 |
memcpy(ivec + AES_BLOCK_SIZE, iv2, AES_BLOCK_SIZE); |
142 |
} |
143 |
} |
144 |
|
145 |
/* |
146 |
* Note that its effectively impossible to do biIGE in anything other |
147 |
* than a single pass, so no provision is made for chaining. |
148 |
*/ |
149 |
|
150 |
/* N.B. The IV for this mode is _four times_ the block size */ |
151 |
|
152 |
void AES_bi_ige_encrypt(const unsigned char *in, unsigned char *out, |
153 |
const unsigned long length, const AES_KEY *key, |
154 |
const AES_KEY *key2, const unsigned char *ivec, |
155 |
const int enc) |
156 |
{ |
157 |
unsigned long n; |
158 |
unsigned long len = length; |
159 |
unsigned char tmp[AES_BLOCK_SIZE]; |
160 |
unsigned char tmp2[AES_BLOCK_SIZE]; |
161 |
unsigned char tmp3[AES_BLOCK_SIZE]; |
162 |
unsigned char prev[AES_BLOCK_SIZE]; |
163 |
const unsigned char *iv; |
164 |
const unsigned char *iv2; |
165 |
|
166 |
OPENSSL_assert(in && out && key && ivec); |
167 |
OPENSSL_assert((AES_ENCRYPT == enc)||(AES_DECRYPT == enc)); |
168 |
OPENSSL_assert((length%AES_BLOCK_SIZE) == 0); |
169 |
|
170 |
if (AES_ENCRYPT == enc) |
171 |
{ |
172 |
/* XXX: Do a separate case for when in != out (strictly should |
173 |
check for overlap, too) */ |
174 |
|
175 |
/* First the forward pass */ |
176 |
iv = ivec; |
177 |
iv2 = ivec + AES_BLOCK_SIZE; |
178 |
while (len >= AES_BLOCK_SIZE) |
179 |
{ |
180 |
/* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ |
181 |
/* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ |
182 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
183 |
out[n] = in[n] ^ iv[n]; |
184 |
/* hexdump(stdout, "in ^ iv", out, AES_BLOCK_SIZE); */ |
185 |
AES_encrypt(out, out, key); |
186 |
/* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ |
187 |
/* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ |
188 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
189 |
out[n] ^= iv2[n]; |
190 |
/* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ |
191 |
iv = out; |
192 |
memcpy(prev, in, AES_BLOCK_SIZE); |
193 |
iv2 = prev; |
194 |
len -= AES_BLOCK_SIZE; |
195 |
in += AES_BLOCK_SIZE; |
196 |
out += AES_BLOCK_SIZE; |
197 |
} |
198 |
|
199 |
/* And now backwards */ |
200 |
iv = ivec + AES_BLOCK_SIZE*2; |
201 |
iv2 = ivec + AES_BLOCK_SIZE*3; |
202 |
len = length; |
203 |
while(len >= AES_BLOCK_SIZE) |
204 |
{ |
205 |
out -= AES_BLOCK_SIZE; |
206 |
/* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ |
207 |
/* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ |
208 |
/* XXX: reduce copies by alternating between buffers */ |
209 |
memcpy(tmp, out, AES_BLOCK_SIZE); |
210 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
211 |
out[n] ^= iv[n]; |
212 |
/* hexdump(stdout, "out ^ iv", out, AES_BLOCK_SIZE); */ |
213 |
AES_encrypt(out, out, key); |
214 |
/* hexdump(stdout,"enc", out, AES_BLOCK_SIZE); */ |
215 |
/* hexdump(stdout,"iv2", iv2, AES_BLOCK_SIZE); */ |
216 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
217 |
out[n] ^= iv2[n]; |
218 |
/* hexdump(stdout,"out", out, AES_BLOCK_SIZE); */ |
219 |
iv = out; |
220 |
memcpy(prev, tmp, AES_BLOCK_SIZE); |
221 |
iv2 = prev; |
222 |
len -= AES_BLOCK_SIZE; |
223 |
} |
224 |
} |
225 |
else |
226 |
{ |
227 |
/* First backwards */ |
228 |
iv = ivec + AES_BLOCK_SIZE*2; |
229 |
iv2 = ivec + AES_BLOCK_SIZE*3; |
230 |
in += length; |
231 |
out += length; |
232 |
while (len >= AES_BLOCK_SIZE) |
233 |
{ |
234 |
in -= AES_BLOCK_SIZE; |
235 |
out -= AES_BLOCK_SIZE; |
236 |
memcpy(tmp, in, AES_BLOCK_SIZE); |
237 |
memcpy(tmp2, in, AES_BLOCK_SIZE); |
238 |
/* hexdump(stdout, "in", in, AES_BLOCK_SIZE); */ |
239 |
/* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ |
240 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
241 |
tmp[n] ^= iv2[n]; |
242 |
/* hexdump(stdout, "in ^ iv2", tmp, AES_BLOCK_SIZE); */ |
243 |
AES_decrypt(tmp, out, key); |
244 |
/* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ |
245 |
/* hexdump(stdout, "iv", iv, AES_BLOCK_SIZE); */ |
246 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
247 |
out[n] ^= iv[n]; |
248 |
/* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ |
249 |
memcpy(tmp3, tmp2, AES_BLOCK_SIZE); |
250 |
iv = tmp3; |
251 |
iv2 = out; |
252 |
len -= AES_BLOCK_SIZE; |
253 |
} |
254 |
|
255 |
/* And now forwards */ |
256 |
iv = ivec; |
257 |
iv2 = ivec + AES_BLOCK_SIZE; |
258 |
len = length; |
259 |
while (len >= AES_BLOCK_SIZE) |
260 |
{ |
261 |
memcpy(tmp, out, AES_BLOCK_SIZE); |
262 |
memcpy(tmp2, out, AES_BLOCK_SIZE); |
263 |
/* hexdump(stdout, "intermediate", out, AES_BLOCK_SIZE); */ |
264 |
/* hexdump(stdout, "iv2", iv2, AES_BLOCK_SIZE); */ |
265 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
266 |
tmp[n] ^= iv2[n]; |
267 |
/* hexdump(stdout, "out ^ iv2", tmp, AES_BLOCK_SIZE); */ |
268 |
AES_decrypt(tmp, out, key); |
269 |
/* hexdump(stdout, "dec", out, AES_BLOCK_SIZE); */ |
270 |
/* hexdump(stdout, "iv", ivec, AES_BLOCK_SIZE); */ |
271 |
for(n=0 ; n < AES_BLOCK_SIZE ; ++n) |
272 |
out[n] ^= iv[n]; |
273 |
/* hexdump(stdout, "out", out, AES_BLOCK_SIZE); */ |
274 |
memcpy(tmp3, tmp2, AES_BLOCK_SIZE); |
275 |
iv = tmp3; |
276 |
iv2 = out; |
277 |
len -= AES_BLOCK_SIZE; |
278 |
in += AES_BLOCK_SIZE; |
279 |
out += AES_BLOCK_SIZE; |
280 |
} |
281 |
|
282 |
} |
283 |
} |