1 /* test/igetest.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 <openssl/aes.h>
53 #include <openssl/rand.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <assert.h>
57 
58 #define TEST_SIZE	128
59 #define BIG_TEST_SIZE 10240
60 
61 static void hexdump(FILE *f,const char *title,const unsigned char *s,int l)
62     {
63     int n=0;
64 
65     fprintf(f,"%s",title);
66     for( ; n < l ; ++n)
67 		{
68 		if((n%16) == 0)
69 			fprintf(f,"\n%04x",n);
70 		fprintf(f," %02x",s[n]);
71 		}
72     fprintf(f,"\n");
73     }
74 
75 #define MAX_VECTOR_SIZE	64
76 
77 struct ige_test
78 	{
79 	const unsigned char key[16];
80 	const unsigned char iv[32];
81 	const unsigned char in[MAX_VECTOR_SIZE];
82 	const unsigned char out[MAX_VECTOR_SIZE];
83 	const size_t length;
84 	const int encrypt;
85 	};
86 
87 static struct ige_test const ige_test_vectors[] = {
88 { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
89     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* key */
90   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
91     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
92     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
93     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, /* iv */
94   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
96     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* in */
98   { 0x1a, 0x85, 0x19, 0xa6, 0x55, 0x7b, 0xe6, 0x52,
99     0xe9, 0xda, 0x8e, 0x43, 0xda, 0x4e, 0xf4, 0x45,
100     0x3c, 0xf4, 0x56, 0xb4, 0xca, 0x48, 0x8a, 0xa3,
101     0x83, 0xc7, 0x9c, 0x98, 0xb3, 0x47, 0x97, 0xcb }, /* out */
102   32, AES_ENCRYPT }, /* test vector 0 */
103 
104 { { 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20,
105     0x61, 0x6e, 0x20, 0x69, 0x6d, 0x70, 0x6c, 0x65 }, /* key */
106   { 0x6d, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f,
107     0x6e, 0x20, 0x6f, 0x66, 0x20, 0x49, 0x47, 0x45,
108     0x20, 0x6d, 0x6f, 0x64, 0x65, 0x20, 0x66, 0x6f,
109     0x72, 0x20, 0x4f, 0x70, 0x65, 0x6e, 0x53, 0x53 }, /* iv */
110   { 0x4c, 0x2e, 0x20, 0x4c, 0x65, 0x74, 0x27, 0x73,
111     0x20, 0x68, 0x6f, 0x70, 0x65, 0x20, 0x42, 0x65,
112     0x6e, 0x20, 0x67, 0x6f, 0x74, 0x20, 0x69, 0x74,
113     0x20, 0x72, 0x69, 0x67, 0x68, 0x74, 0x21, 0x0a }, /* in */
114   { 0x99, 0x70, 0x64, 0x87, 0xa1, 0xcd, 0xe6, 0x13,
115     0xbc, 0x6d, 0xe0, 0xb6, 0xf2, 0x4b, 0x1c, 0x7a,
116     0xa4, 0x48, 0xc8, 0xb9, 0xc3, 0x40, 0x3e, 0x34,
117     0x67, 0xa8, 0xca, 0xd8, 0x93, 0x40, 0xf5, 0x3b }, /* out */
118   32, AES_DECRYPT }, /* test vector 1 */
119 };
120 
121 struct bi_ige_test
122 	{
123 	const unsigned char key1[32];
124 	const unsigned char key2[32];
125 	const unsigned char iv[64];
126 	const unsigned char in[MAX_VECTOR_SIZE];
127 	const unsigned char out[MAX_VECTOR_SIZE];
128 	const size_t keysize;
129 	const size_t length;
130 	const int encrypt;
131 	};
132 
133 static struct bi_ige_test const bi_ige_test_vectors[] = {
134 { { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
135     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }, /* key1 */
136   { 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
137     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }, /* key2 */
138   { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
139     0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
140     0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
141     0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
142     0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
143     0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
144     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
145     0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f }, /* iv */
146   { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
147     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
148     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
149     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* in */
150   { 0x14, 0x40, 0x6f, 0xae, 0xa2, 0x79, 0xf2, 0x56,
151 	0x1f, 0x86, 0xeb, 0x3b, 0x7d, 0xff, 0x53, 0xdc,
152 	0x4e, 0x27, 0x0c, 0x03, 0xde, 0x7c, 0xe5, 0x16,
153 	0x6a, 0x9c, 0x20, 0x33, 0x9d, 0x33, 0xfe, 0x12 }, /* out */
154   16, 32, AES_ENCRYPT }, /* test vector 0 */
155 { { 0x58, 0x0a, 0x06, 0xe9, 0x97, 0x07, 0x59, 0x5c,
156 	0x9e, 0x19, 0xd2, 0xa7, 0xbb, 0x40, 0x2b, 0x7a,
157 	0xc7, 0xd8, 0x11, 0x9e, 0x4c, 0x51, 0x35, 0x75,
158 	0x64, 0x28, 0x0f, 0x23, 0xad, 0x74, 0xac, 0x37 }, /* key1 */
159   { 0xd1, 0x80, 0xa0, 0x31, 0x47, 0xa3, 0x11, 0x13,
160 	0x86, 0x26, 0x9e, 0x6d, 0xff, 0xaf, 0x72, 0x74,
161 	0x5b, 0xa2, 0x35, 0x81, 0xd2, 0xa6, 0x3d, 0x21,
162 	0x67, 0x7b, 0x58, 0xa8, 0x18, 0xf9, 0x72, 0xe4 }, /* key2 */
163   { 0x80, 0x3d, 0xbd, 0x4c, 0xe6, 0x7b, 0x06, 0xa9,
164 	0x53, 0x35, 0xd5, 0x7e, 0x71, 0xc1, 0x70, 0x70,
165 	0x74, 0x9a, 0x00, 0x28, 0x0c, 0xbf, 0x6c, 0x42,
166 	0x9b, 0xa4, 0xdd, 0x65, 0x11, 0x77, 0x7c, 0x67,
167 	0xfe, 0x76, 0x0a, 0xf0, 0xd5, 0xc6, 0x6e, 0x6a,
168 	0xe7, 0x5e, 0x4c, 0xf2, 0x7e, 0x9e, 0xf9, 0x20,
169 	0x0e, 0x54, 0x6f, 0x2d, 0x8a, 0x8d, 0x7e, 0xbd,
170 	0x48, 0x79, 0x37, 0x99, 0xff, 0x27, 0x93, 0xa3 }, /* iv */
171   { 0xf1, 0x54, 0x3d, 0xca, 0xfe, 0xb5, 0xef, 0x1c,
172 	0x4f, 0xa6, 0x43, 0xf6, 0xe6, 0x48, 0x57, 0xf0,
173 	0xee, 0x15, 0x7f, 0xe3, 0xe7, 0x2f, 0xd0, 0x2f,
174 	0x11, 0x95, 0x7a, 0x17, 0x00, 0xab, 0xa7, 0x0b,
175 	0xbe, 0x44, 0x09, 0x9c, 0xcd, 0xac, 0xa8, 0x52,
176 	0xa1, 0x8e, 0x7b, 0x75, 0xbc, 0xa4, 0x92, 0x5a,
177 	0xab, 0x46, 0xd3, 0x3a, 0xa0, 0xd5, 0x35, 0x1c,
178 	0x55, 0xa4, 0xb3, 0xa8, 0x40, 0x81, 0xa5, 0x0b}, /* in */
179   { 0x42, 0xe5, 0x28, 0x30, 0x31, 0xc2, 0xa0, 0x23,
180 	0x68, 0x49, 0x4e, 0xb3, 0x24, 0x59, 0x92, 0x79,
181 	0xc1, 0xa5, 0xcc, 0xe6, 0x76, 0x53, 0xb1, 0xcf,
182 	0x20, 0x86, 0x23, 0xe8, 0x72, 0x55, 0x99, 0x92,
183 	0x0d, 0x16, 0x1c, 0x5a, 0x2f, 0xce, 0xcb, 0x51,
184 	0xe2, 0x67, 0xfa, 0x10, 0xec, 0xcd, 0x3d, 0x67,
185 	0xa5, 0xe6, 0xf7, 0x31, 0x26, 0xb0, 0x0d, 0x76,
186 	0x5e, 0x28, 0xdc, 0x7f, 0x01, 0xc5, 0xa5, 0x4c}, /* out */
187   32, 64, AES_ENCRYPT }, /* test vector 1 */
188 
189 };
190 
191 static int run_test_vectors(void)
192 	{
193 	unsigned int n;
194 	int errs = 0;
195 
196 	for(n=0 ; n < sizeof(ige_test_vectors)/sizeof(ige_test_vectors[0]) ; ++n)
197 		{
198 		const struct ige_test * const v = &ige_test_vectors[n];
199 		AES_KEY key;
200 		unsigned char buf[MAX_VECTOR_SIZE];
201 		unsigned char iv[AES_BLOCK_SIZE*2];
202 
203 		assert(v->length <= MAX_VECTOR_SIZE);
204 
205 		if(v->encrypt == AES_ENCRYPT)
206 			AES_set_encrypt_key(v->key, 8*sizeof v->key, &key);
207 		else
208 			AES_set_decrypt_key(v->key, 8*sizeof v->key, &key);
209 		memcpy(iv, v->iv, sizeof iv);
210 		AES_ige_encrypt(v->in, buf, v->length, &key, iv, v->encrypt);
211 
212 		if(memcmp(v->out, buf, v->length))
213 			{
214 			printf("IGE test vector %d failed\n", n);
215 			hexdump(stdout, "key", v->key, sizeof v->key);
216 			hexdump(stdout, "iv", v->iv, sizeof v->iv);
217 			hexdump(stdout, "in", v->in, v->length);
218 			hexdump(stdout, "expected", v->out, v->length);
219 			hexdump(stdout, "got", buf, v->length);
220 
221 			++errs;
222 			}
223 
224                 /* try with in == out */
225 		memcpy(iv, v->iv, sizeof iv);
226                 memcpy(buf, v->in, v->length);
227 		AES_ige_encrypt(buf, buf, v->length, &key, iv, v->encrypt);
228 
229 		if(memcmp(v->out, buf, v->length))
230 			{
231 			printf("IGE test vector %d failed (with in == out)\n", n);
232 			hexdump(stdout, "key", v->key, sizeof v->key);
233 			hexdump(stdout, "iv", v->iv, sizeof v->iv);
234 			hexdump(stdout, "in", v->in, v->length);
235 			hexdump(stdout, "expected", v->out, v->length);
236 			hexdump(stdout, "got", buf, v->length);
237 
238 			++errs;
239 			}
240 		}
241 
242 	for(n=0 ; n < sizeof(bi_ige_test_vectors)/sizeof(bi_ige_test_vectors[0])
243 			; ++n)
244 		{
245 		const struct bi_ige_test * const v = &bi_ige_test_vectors[n];
246 		AES_KEY key1;
247 		AES_KEY key2;
248 		unsigned char buf[MAX_VECTOR_SIZE];
249 
250 		assert(v->length <= MAX_VECTOR_SIZE);
251 
252 		if(v->encrypt == AES_ENCRYPT)
253 			{
254 			AES_set_encrypt_key(v->key1, 8*v->keysize, &key1);
255 			AES_set_encrypt_key(v->key2, 8*v->keysize, &key2);
256 			}
257 		else
258 			{
259 			AES_set_decrypt_key(v->key1, 8*v->keysize, &key1);
260 			AES_set_decrypt_key(v->key2, 8*v->keysize, &key2);
261 			}
262 
263 		AES_bi_ige_encrypt(v->in, buf, v->length, &key1, &key2, v->iv,
264 						   v->encrypt);
265 
266 		if(memcmp(v->out, buf, v->length))
267 			{
268 			printf("Bidirectional IGE test vector %d failed\n", n);
269 			hexdump(stdout, "key 1", v->key1, sizeof v->key1);
270 			hexdump(stdout, "key 2", v->key2, sizeof v->key2);
271 			hexdump(stdout, "iv", v->iv, sizeof v->iv);
272 			hexdump(stdout, "in", v->in, v->length);
273 			hexdump(stdout, "expected", v->out, v->length);
274 			hexdump(stdout, "got", buf, v->length);
275 
276 			++errs;
277 			}
278 		}
279 
280 	return errs;
281 	}
282 
283 int main(int argc, char **argv)
284 	{
285 	unsigned char rkey[16];
286 	unsigned char rkey2[16];
287 	AES_KEY key;
288 	AES_KEY key2;
289 	unsigned char plaintext[BIG_TEST_SIZE];
290 	unsigned char ciphertext[BIG_TEST_SIZE];
291 	unsigned char checktext[BIG_TEST_SIZE];
292 	unsigned char iv[AES_BLOCK_SIZE*4];
293 	unsigned char saved_iv[AES_BLOCK_SIZE*4];
294 	int err = 0;
295 	unsigned int n;
296 	unsigned matches;
297 
298 	assert(BIG_TEST_SIZE >= TEST_SIZE);
299 
300 	RAND_pseudo_bytes(rkey, sizeof rkey);
301 	RAND_pseudo_bytes(plaintext, sizeof plaintext);
302 	RAND_pseudo_bytes(iv, sizeof iv);
303 	memcpy(saved_iv, iv, sizeof saved_iv);
304 
305 	/* Forward IGE only... */
306 
307 	/* Straight encrypt/decrypt */
308 	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
309 	AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE, &key, iv,
310 					AES_ENCRYPT);
311 
312 	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
313 	memcpy(iv, saved_iv, sizeof iv);
314 	AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv,
315 					AES_DECRYPT);
316 
317 	if(memcmp(checktext, plaintext, TEST_SIZE))
318 		{
319 		printf("Encrypt+decrypt doesn't match\n");
320 		hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
321 		hexdump(stdout, "Checktext", checktext, TEST_SIZE);
322 		++err;
323 		}
324 
325 	/* Now check encrypt chaining works */
326 	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
327 	memcpy(iv, saved_iv, sizeof iv);
328 	AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE/2, &key, iv,
329 					AES_ENCRYPT);
330 	AES_ige_encrypt(plaintext+TEST_SIZE/2,
331 					ciphertext+TEST_SIZE/2, TEST_SIZE/2,
332 					&key, iv, AES_ENCRYPT);
333 
334 	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
335 	memcpy(iv, saved_iv, sizeof iv);
336 	AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv,
337 					AES_DECRYPT);
338 
339 	if(memcmp(checktext, plaintext, TEST_SIZE))
340 		{
341 		printf("Chained encrypt+decrypt doesn't match\n");
342 		hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
343 		hexdump(stdout, "Checktext", checktext, TEST_SIZE);
344 		++err;
345 		}
346 
347 	/* And check decrypt chaining */
348 	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
349 	memcpy(iv, saved_iv, sizeof iv);
350 	AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE/2, &key, iv,
351 					AES_ENCRYPT);
352 	AES_ige_encrypt(plaintext+TEST_SIZE/2,
353 					ciphertext+TEST_SIZE/2, TEST_SIZE/2,
354 					&key, iv, AES_ENCRYPT);
355 
356 	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
357 	memcpy(iv, saved_iv, sizeof iv);
358 	AES_ige_encrypt(ciphertext, checktext, TEST_SIZE/2, &key, iv,
359 					AES_DECRYPT);
360 	AES_ige_encrypt(ciphertext+TEST_SIZE/2,
361 					checktext+TEST_SIZE/2, TEST_SIZE/2, &key, iv,
362 					AES_DECRYPT);
363 
364 	if(memcmp(checktext, plaintext, TEST_SIZE))
365 		{
366 		printf("Chained encrypt+chained decrypt doesn't match\n");
367 		hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
368 		hexdump(stdout, "Checktext", checktext, TEST_SIZE);
369 		++err;
370 		}
371 
372 	/* make sure garble extends forwards only */
373 	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
374 	memcpy(iv, saved_iv, sizeof iv);
375 	AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
376 					AES_ENCRYPT);
377 
378 	/* corrupt halfway through */
379 	++ciphertext[sizeof ciphertext/2];
380 	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
381 	memcpy(iv, saved_iv, sizeof iv);
382 	AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
383 					AES_DECRYPT);
384 
385 	matches=0;
386 	for(n=0 ; n < sizeof checktext ; ++n)
387 		if(checktext[n] == plaintext[n])
388 			++matches;
389 
390 	if(matches > sizeof checktext/2+sizeof checktext/100)
391 		{
392 		printf("More than 51%% matches after garbling\n");
393 		++err;
394 		}
395 
396 	if(matches < sizeof checktext/2)
397 		{
398 		printf("Garble extends backwards!\n");
399 		++err;
400 		}
401 
402 	/* Bi-directional IGE */
403 
404 	/* Note that we don't have to recover the IV, because chaining isn't */
405 	/* possible with biIGE, so the IV is not updated. */
406 
407 	RAND_pseudo_bytes(rkey2, sizeof rkey2);
408 
409 	/* Straight encrypt/decrypt */
410 	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
411 	AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2);
412 	AES_bi_ige_encrypt(plaintext, ciphertext, TEST_SIZE, &key, &key2, iv,
413 					   AES_ENCRYPT);
414 
415 	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
416 	AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2);
417 	AES_bi_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, &key2, iv,
418 					   AES_DECRYPT);
419 
420 	if(memcmp(checktext, plaintext, TEST_SIZE))
421 		{
422 		printf("Encrypt+decrypt doesn't match\n");
423 		hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
424 		hexdump(stdout, "Checktext", checktext, TEST_SIZE);
425 		++err;
426 		}
427 
428 	/* make sure garble extends both ways */
429 	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
430 	AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2);
431 	AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
432 					AES_ENCRYPT);
433 
434 	/* corrupt halfway through */
435 	++ciphertext[sizeof ciphertext/2];
436 	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
437 	AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2);
438 	AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
439 					AES_DECRYPT);
440 
441 	matches=0;
442 	for(n=0 ; n < sizeof checktext ; ++n)
443 		if(checktext[n] == plaintext[n])
444 			++matches;
445 
446 	if(matches > sizeof checktext/100)
447 		{
448 		printf("More than 1%% matches after bidirectional garbling\n");
449 		++err;
450 		}
451 
452 	/* make sure garble extends both ways (2) */
453 	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
454 	AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2);
455 	AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
456 					AES_ENCRYPT);
457 
458 	/* corrupt right at the end */
459 	++ciphertext[sizeof ciphertext-1];
460 	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
461 	AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2);
462 	AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
463 					AES_DECRYPT);
464 
465 	matches=0;
466 	for(n=0 ; n < sizeof checktext ; ++n)
467 		if(checktext[n] == plaintext[n])
468 			++matches;
469 
470 	if(matches > sizeof checktext/100)
471 		{
472 		printf("More than 1%% matches after bidirectional garbling (2)\n");
473 		++err;
474 		}
475 
476 	/* make sure garble extends both ways (3) */
477 	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
478 	AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2);
479 	AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
480 					AES_ENCRYPT);
481 
482 	/* corrupt right at the start */
483 	++ciphertext[0];
484 	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
485 	AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2);
486 	AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
487 					AES_DECRYPT);
488 
489 	matches=0;
490 	for(n=0 ; n < sizeof checktext ; ++n)
491 		if(checktext[n] == plaintext[n])
492 			++matches;
493 
494 	if(matches > sizeof checktext/100)
495 		{
496 		printf("More than 1%% matches after bidirectional garbling (3)\n");
497 		++err;
498 		}
499 
500 	err += run_test_vectors();
501 
502 	return err;
503 	}
504