Forward port of IGE mode.
[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/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         }