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
61static 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
77struct 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
87static 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
121struct 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
133static 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
191static 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
283int 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