xref: /freebsd/crypto/openssl/test/igetest.c (revision 39beb93c3f8bdbf72a61fda42300b5ebed7390c8)
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 	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 
266 int 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