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	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
225	for(n=0 ; n < sizeof(bi_ige_test_vectors)/sizeof(bi_ige_test_vectors[0])
226			; ++n)
227		{
228		const struct bi_ige_test * const v = &bi_ige_test_vectors[n];
229		AES_KEY key1;
230		AES_KEY key2;
231		unsigned char buf[MAX_VECTOR_SIZE];
232
233		assert(v->length <= MAX_VECTOR_SIZE);
234
235		if(v->encrypt == AES_ENCRYPT)
236			{
237			AES_set_encrypt_key(v->key1, 8*v->keysize, &key1);
238			AES_set_encrypt_key(v->key2, 8*v->keysize, &key2);
239			}
240		else
241			{
242			AES_set_decrypt_key(v->key1, 8*v->keysize, &key1);
243			AES_set_decrypt_key(v->key2, 8*v->keysize, &key2);
244			}
245
246		AES_bi_ige_encrypt(v->in, buf, v->length, &key1, &key2, v->iv,
247						   v->encrypt);
248
249		if(memcmp(v->out, buf, v->length))
250			{
251			printf("Bidirectional IGE test vector %d failed\n", n);
252			hexdump(stdout, "key 1", v->key1, sizeof v->key1);
253			hexdump(stdout, "key 2", v->key2, sizeof v->key2);
254			hexdump(stdout, "iv", v->iv, sizeof v->iv);
255			hexdump(stdout, "in", v->in, v->length);
256			hexdump(stdout, "expected", v->out, v->length);
257			hexdump(stdout, "got", buf, v->length);
258
259			++errs;
260			}
261		}
262
263	return errs;
264	}
265
266int main(int argc, char **argv)
267	{
268	unsigned char rkey[16];
269	unsigned char rkey2[16];
270	AES_KEY key;
271	AES_KEY key2;
272	unsigned char plaintext[BIG_TEST_SIZE];
273	unsigned char ciphertext[BIG_TEST_SIZE];
274	unsigned char checktext[BIG_TEST_SIZE];
275	unsigned char iv[AES_BLOCK_SIZE*4];
276	unsigned char saved_iv[AES_BLOCK_SIZE*4];
277	int err = 0;
278	int n;
279	unsigned matches;
280
281	assert(BIG_TEST_SIZE >= TEST_SIZE);
282
283	RAND_pseudo_bytes(rkey, sizeof rkey);
284	RAND_pseudo_bytes(plaintext, sizeof plaintext);
285	RAND_pseudo_bytes(iv, sizeof iv);
286	memcpy(saved_iv, iv, sizeof saved_iv);
287
288	/* Forward IGE only... */
289
290	/* Straight encrypt/decrypt */
291	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
292	AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE, &key, iv,
293					AES_ENCRYPT);
294
295	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
296	memcpy(iv, saved_iv, sizeof iv);
297	AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv,
298					AES_DECRYPT);
299
300	if(memcmp(checktext, plaintext, TEST_SIZE))
301		{
302		printf("Encrypt+decrypt doesn't match\n");
303		hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
304		hexdump(stdout, "Checktext", checktext, TEST_SIZE);
305		++err;
306		}
307
308	/* Now check encrypt chaining works */
309	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
310	memcpy(iv, saved_iv, sizeof iv);
311	AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE/2, &key, iv,
312					AES_ENCRYPT);
313	AES_ige_encrypt(plaintext+TEST_SIZE/2,
314					ciphertext+TEST_SIZE/2, TEST_SIZE/2,
315					&key, iv, AES_ENCRYPT);
316
317	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
318	memcpy(iv, saved_iv, sizeof iv);
319	AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv,
320					AES_DECRYPT);
321
322	if(memcmp(checktext, plaintext, TEST_SIZE))
323		{
324		printf("Chained encrypt+decrypt doesn't match\n");
325		hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
326		hexdump(stdout, "Checktext", checktext, TEST_SIZE);
327		++err;
328		}
329
330	/* And check decrypt chaining */
331	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
332	memcpy(iv, saved_iv, sizeof iv);
333	AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE/2, &key, iv,
334					AES_ENCRYPT);
335	AES_ige_encrypt(plaintext+TEST_SIZE/2,
336					ciphertext+TEST_SIZE/2, TEST_SIZE/2,
337					&key, iv, AES_ENCRYPT);
338
339	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
340	memcpy(iv, saved_iv, sizeof iv);
341	AES_ige_encrypt(ciphertext, checktext, TEST_SIZE/2, &key, iv,
342					AES_DECRYPT);
343	AES_ige_encrypt(ciphertext+TEST_SIZE/2,
344					checktext+TEST_SIZE/2, TEST_SIZE/2, &key, iv,
345					AES_DECRYPT);
346
347	if(memcmp(checktext, plaintext, TEST_SIZE))
348		{
349		printf("Chained encrypt+chained decrypt doesn't match\n");
350		hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
351		hexdump(stdout, "Checktext", checktext, TEST_SIZE);
352		++err;
353		}
354
355	/* make sure garble extends forwards only */
356	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
357	memcpy(iv, saved_iv, sizeof iv);
358	AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
359					AES_ENCRYPT);
360
361	/* corrupt halfway through */
362	++ciphertext[sizeof ciphertext/2];
363	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
364	memcpy(iv, saved_iv, sizeof iv);
365	AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
366					AES_DECRYPT);
367
368	matches=0;
369	for(n=0 ; n < sizeof checktext ; ++n)
370		if(checktext[n] == plaintext[n])
371			++matches;
372
373	if(matches > sizeof checktext/2+sizeof checktext/100)
374		{
375		printf("More than 51%% matches after garbling\n");
376		++err;
377		}
378
379	if(matches < sizeof checktext/2)
380		{
381		printf("Garble extends backwards!\n");
382		++err;
383		}
384
385	/* Bi-directional IGE */
386
387	/* Note that we don't have to recover the IV, because chaining isn't */
388	/* possible with biIGE, so the IV is not updated. */
389
390	RAND_pseudo_bytes(rkey2, sizeof rkey2);
391
392	/* Straight encrypt/decrypt */
393	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
394	AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2);
395	AES_bi_ige_encrypt(plaintext, ciphertext, TEST_SIZE, &key, &key2, iv,
396					   AES_ENCRYPT);
397
398	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
399	AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2);
400	AES_bi_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, &key2, iv,
401					   AES_DECRYPT);
402
403	if(memcmp(checktext, plaintext, TEST_SIZE))
404		{
405		printf("Encrypt+decrypt doesn't match\n");
406		hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
407		hexdump(stdout, "Checktext", checktext, TEST_SIZE);
408		++err;
409		}
410
411	/* make sure garble extends both ways */
412	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
413	AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2);
414	AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
415					AES_ENCRYPT);
416
417	/* corrupt halfway through */
418	++ciphertext[sizeof ciphertext/2];
419	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
420	AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2);
421	AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
422					AES_DECRYPT);
423
424	matches=0;
425	for(n=0 ; n < sizeof checktext ; ++n)
426		if(checktext[n] == plaintext[n])
427			++matches;
428
429	if(matches > sizeof checktext/100)
430		{
431		printf("More than 1%% matches after bidirectional garbling\n");
432		++err;
433		}
434
435	/* make sure garble extends both ways (2) */
436	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
437	AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2);
438	AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
439					AES_ENCRYPT);
440
441	/* corrupt right at the end */
442	++ciphertext[sizeof ciphertext-1];
443	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
444	AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2);
445	AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
446					AES_DECRYPT);
447
448	matches=0;
449	for(n=0 ; n < sizeof checktext ; ++n)
450		if(checktext[n] == plaintext[n])
451			++matches;
452
453	if(matches > sizeof checktext/100)
454		{
455		printf("More than 1%% matches after bidirectional garbling (2)\n");
456		++err;
457		}
458
459	/* make sure garble extends both ways (3) */
460	AES_set_encrypt_key(rkey, 8*sizeof rkey, &key);
461	AES_set_encrypt_key(rkey2, 8*sizeof rkey2, &key2);
462	AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
463					AES_ENCRYPT);
464
465	/* corrupt right at the start */
466	++ciphertext[0];
467	AES_set_decrypt_key(rkey, 8*sizeof rkey, &key);
468	AES_set_decrypt_key(rkey2, 8*sizeof rkey2, &key2);
469	AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
470					AES_DECRYPT);
471
472	matches=0;
473	for(n=0 ; n < sizeof checktext ; ++n)
474		if(checktext[n] == plaintext[n])
475			++matches;
476
477	if(matches > sizeof checktext/100)
478		{
479		printf("More than 1%% matches after bidirectional garbling (3)\n");
480		++err;
481		}
482
483	err += run_test_vectors();
484
485	return err;
486	}
487