Ensure CRYPTO_mem_leaks is the last thing we do
[oweals/openssl.git] / test / igetest.c
1 /* ====================================================================
2  * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in
13  *    the documentation and/or other materials provided with the
14  *    distribution.
15  *
16  * 3. All advertising materials mentioning features or use of this
17  *    software must display the following acknowledgment:
18  *    "This product includes software developed by the OpenSSL Project
19  *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
20  *
21  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
22  *    endorse or promote products derived from this software without
23  *    prior written permission. For written permission, please contact
24  *    openssl-core@openssl.org.
25  *
26  * 5. Products derived from this software may not be called "OpenSSL"
27  *    nor may "OpenSSL" appear in their names without prior written
28  *    permission of the OpenSSL Project.
29  *
30  * 6. Redistributions of any form whatsoever must retain the following
31  *    acknowledgment:
32  *    "This product includes software developed by the OpenSSL Project
33  *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
36  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
37  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
38  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
39  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
41  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
43  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
44  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
45  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
46  * OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  */
50
51 #include <openssl/crypto.h>
52 #include <openssl/aes.h>
53 #include <openssl/rand.h>
54 #include <stdio.h>
55 #include <string.h>
56 #include <assert.h>
57 #include "e_os.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 < OSSL_NELEM(ige_test_vectors); ++n) {
195         const struct ige_test *const v = &ige_test_vectors[n];
196         AES_KEY key;
197         unsigned char buf[MAX_VECTOR_SIZE];
198         unsigned char iv[AES_BLOCK_SIZE * 2];
199
200         assert(v->length <= MAX_VECTOR_SIZE);
201
202         if (v->encrypt == AES_ENCRYPT)
203             AES_set_encrypt_key(v->key, 8 * sizeof v->key, &key);
204         else
205             AES_set_decrypt_key(v->key, 8 * sizeof v->key, &key);
206         memcpy(iv, v->iv, sizeof iv);
207         AES_ige_encrypt(v->in, buf, v->length, &key, iv, v->encrypt);
208
209         if (memcmp(v->out, buf, v->length)) {
210             printf("IGE test vector %d failed\n", n);
211             hexdump(stdout, "key", v->key, sizeof v->key);
212             hexdump(stdout, "iv", v->iv, sizeof v->iv);
213             hexdump(stdout, "in", v->in, v->length);
214             hexdump(stdout, "expected", v->out, v->length);
215             hexdump(stdout, "got", buf, v->length);
216
217             ++errs;
218         }
219
220         /* try with in == out */
221         memcpy(iv, v->iv, sizeof iv);
222         memcpy(buf, v->in, v->length);
223         AES_ige_encrypt(buf, buf, v->length, &key, iv, v->encrypt);
224
225         if (memcmp(v->out, buf, v->length)) {
226             printf("IGE test vector %d failed (with in == out)\n", n);
227             hexdump(stdout, "key", v->key, sizeof v->key);
228             hexdump(stdout, "iv", v->iv, sizeof v->iv);
229             hexdump(stdout, "in", v->in, v->length);
230             hexdump(stdout, "expected", v->out, v->length);
231             hexdump(stdout, "got", buf, v->length);
232
233             ++errs;
234         }
235     }
236
237     for (n = 0; n < OSSL_NELEM(bi_ige_test_vectors); ++n) {
238         const struct bi_ige_test *const v = &bi_ige_test_vectors[n];
239         AES_KEY key1;
240         AES_KEY key2;
241         unsigned char buf[MAX_VECTOR_SIZE];
242
243         assert(v->length <= MAX_VECTOR_SIZE);
244
245         if (v->encrypt == AES_ENCRYPT) {
246             AES_set_encrypt_key(v->key1, 8 * v->keysize, &key1);
247             AES_set_encrypt_key(v->key2, 8 * v->keysize, &key2);
248         } else {
249             AES_set_decrypt_key(v->key1, 8 * v->keysize, &key1);
250             AES_set_decrypt_key(v->key2, 8 * v->keysize, &key2);
251         }
252
253         AES_bi_ige_encrypt(v->in, buf, v->length, &key1, &key2, v->iv,
254                            v->encrypt);
255
256         if (memcmp(v->out, buf, v->length)) {
257             printf("Bidirectional IGE test vector %d failed\n", n);
258             hexdump(stdout, "key 1", v->key1, sizeof v->key1);
259             hexdump(stdout, "key 2", v->key2, sizeof v->key2);
260             hexdump(stdout, "iv", v->iv, sizeof v->iv);
261             hexdump(stdout, "in", v->in, v->length);
262             hexdump(stdout, "expected", v->out, v->length);
263             hexdump(stdout, "got", buf, v->length);
264
265             ++errs;
266         }
267     }
268
269     return errs;
270 }
271
272 int main(int argc, char **argv)
273 {
274     unsigned char rkey[16];
275     unsigned char rkey2[16];
276     AES_KEY key;
277     AES_KEY key2;
278     unsigned char plaintext[BIG_TEST_SIZE];
279     unsigned char ciphertext[BIG_TEST_SIZE];
280     unsigned char checktext[BIG_TEST_SIZE];
281     unsigned char iv[AES_BLOCK_SIZE * 4];
282     unsigned char saved_iv[AES_BLOCK_SIZE * 4];
283     int err = 0;
284     unsigned int n;
285     unsigned matches;
286
287     assert(BIG_TEST_SIZE >= TEST_SIZE);
288
289     RAND_bytes(rkey, sizeof rkey);
290     RAND_bytes(plaintext, sizeof plaintext);
291     RAND_bytes(iv, sizeof iv);
292     memcpy(saved_iv, iv, sizeof saved_iv);
293
294     /* Forward IGE only... */
295
296     /* Straight encrypt/decrypt */
297     AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
298     AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE, &key, iv, AES_ENCRYPT);
299
300     AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
301     memcpy(iv, saved_iv, sizeof iv);
302     AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv, AES_DECRYPT);
303
304     if (memcmp(checktext, plaintext, TEST_SIZE)) {
305         printf("Encrypt+decrypt doesn't match\n");
306         hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
307         hexdump(stdout, "Checktext", checktext, TEST_SIZE);
308         ++err;
309     }
310
311     /* Now check encrypt chaining works */
312     AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
313     memcpy(iv, saved_iv, sizeof iv);
314     AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE / 2, &key, iv,
315                     AES_ENCRYPT);
316     AES_ige_encrypt(plaintext + TEST_SIZE / 2,
317                     ciphertext + TEST_SIZE / 2, TEST_SIZE / 2,
318                     &key, iv, AES_ENCRYPT);
319
320     AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
321     memcpy(iv, saved_iv, sizeof iv);
322     AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv, AES_DECRYPT);
323
324     if (memcmp(checktext, plaintext, TEST_SIZE)) {
325         printf("Chained encrypt+decrypt doesn't match\n");
326         hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
327         hexdump(stdout, "Checktext", checktext, TEST_SIZE);
328         ++err;
329     }
330
331     /* And check decrypt chaining */
332     AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
333     memcpy(iv, saved_iv, sizeof iv);
334     AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE / 2, &key, iv,
335                     AES_ENCRYPT);
336     AES_ige_encrypt(plaintext + TEST_SIZE / 2,
337                     ciphertext + TEST_SIZE / 2, TEST_SIZE / 2,
338                     &key, iv, AES_ENCRYPT);
339
340     AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
341     memcpy(iv, saved_iv, sizeof iv);
342     AES_ige_encrypt(ciphertext, checktext, TEST_SIZE / 2, &key, iv,
343                     AES_DECRYPT);
344     AES_ige_encrypt(ciphertext + TEST_SIZE / 2,
345                     checktext + TEST_SIZE / 2, TEST_SIZE / 2, &key, iv,
346                     AES_DECRYPT);
347
348     if (memcmp(checktext, plaintext, TEST_SIZE)) {
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         printf("More than 51%% matches after garbling\n");
375         ++err;
376     }
377
378     if (matches < sizeof checktext / 2) {
379         printf("Garble extends backwards!\n");
380         ++err;
381     }
382
383     /* Bi-directional IGE */
384
385     /*
386      * Note that we don't have to recover the IV, because chaining isn't
387      */
388     /* possible with biIGE, so the IV is not updated. */
389
390     RAND_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         printf("Encrypt+decrypt doesn't match\n");
405         hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
406         hexdump(stdout, "Checktext", checktext, TEST_SIZE);
407         ++err;
408     }
409
410     /* make sure garble extends both ways */
411     AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
412     AES_set_encrypt_key(rkey2, 8 * sizeof rkey2, &key2);
413     AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
414                     AES_ENCRYPT);
415
416     /* corrupt halfway through */
417     ++ciphertext[sizeof ciphertext / 2];
418     AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
419     AES_set_decrypt_key(rkey2, 8 * sizeof rkey2, &key2);
420     AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
421                     AES_DECRYPT);
422
423     matches = 0;
424     for (n = 0; n < sizeof checktext; ++n)
425         if (checktext[n] == plaintext[n])
426             ++matches;
427
428     if (matches > sizeof checktext / 100) {
429         printf("More than 1%% matches after bidirectional garbling\n");
430         ++err;
431     }
432
433     /* make sure garble extends both ways (2) */
434     AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
435     AES_set_encrypt_key(rkey2, 8 * sizeof rkey2, &key2);
436     AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
437                     AES_ENCRYPT);
438
439     /* corrupt right at the end */
440     ++ciphertext[sizeof ciphertext - 1];
441     AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
442     AES_set_decrypt_key(rkey2, 8 * sizeof rkey2, &key2);
443     AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
444                     AES_DECRYPT);
445
446     matches = 0;
447     for (n = 0; n < sizeof checktext; ++n)
448         if (checktext[n] == plaintext[n])
449             ++matches;
450
451     if (matches > sizeof checktext / 100) {
452         printf("More than 1%% matches after bidirectional garbling (2)\n");
453         ++err;
454     }
455
456     /* make sure garble extends both ways (3) */
457     AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
458     AES_set_encrypt_key(rkey2, 8 * sizeof rkey2, &key2);
459     AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
460                     AES_ENCRYPT);
461
462     /* corrupt right at the start */
463     ++ciphertext[0];
464     AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
465     AES_set_decrypt_key(rkey2, 8 * sizeof rkey2, &key2);
466     AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
467                     AES_DECRYPT);
468
469     matches = 0;
470     for (n = 0; n < sizeof checktext; ++n)
471         if (checktext[n] == plaintext[n])
472             ++matches;
473
474     if (matches > sizeof checktext / 100) {
475         printf("More than 1%% matches after bidirectional garbling (3)\n");
476         ++err;
477     }
478
479     err += run_test_vectors();
480
481     return err;
482 }