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