xref: /freebsd/crypto/openssl/crypto/aes/aes_ige.c (revision 7bd6fde3)
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 	}
284