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