Add test for CLIENT_EARLY_TRAFFIC_SECRET key logging
[openssl.git] / test / igetest.c
index 9c80c856e1ef55dea982d797328fb243977a7964..fd1089d273d8e3aa827dd88738c4abc91e3a5a3b 100644 (file)
@@ -1,52 +1,10 @@
-/* test/igetest.c -*- mode:C; c-file-style: "eay" -*- */
-/* ====================================================================
- * Copyright (c) 2006 The OpenSSL Project.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in
- *    the documentation and/or other materials provided with the
- *    distribution.
- *
- * 3. All advertising materials mentioning features or use of this
- *    software must display the following acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
- *
- * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
- *    endorse or promote products derived from this software without
- *    prior written permission. For written permission, please contact
- *    openssl-core@openssl.org.
- *
- * 5. Products derived from this software may not be called "OpenSSL"
- *    nor may "OpenSSL" appear in their names without prior written
- *    permission of the OpenSSL Project.
- *
- * 6. Redistributions of any form whatsoever must retain the following
- *    acknowledgment:
- *    "This product includes software developed by the OpenSSL Project
- *    for use in the OpenSSL Toolkit (http://www.openssl.org/)"
- *
- * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
- * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- * OF THE POSSIBILITY OF SUCH DAMAGE.
- * ====================================================================
+/*
+ * Copyright 2006-2017 The OpenSSL Project Authors. All Rights Reserved.
  *
+ * Licensed under the OpenSSL license (the "License").  You may not use
+ * this file except in compliance with the License.  You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
  */
 
 #include <openssl/crypto.h>
 #include <openssl/rand.h>
 #include <stdio.h>
 #include <string.h>
-#include <assert.h>
-#include "e_os.h"
+#include "internal/nelem.h"
+#include "testutil.h"
 
 #define TEST_SIZE       128
 #define BIG_TEST_SIZE 10240
 
-static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
-{
-    int n = 0;
+#if BIG_TEST_SIZE < TEST_SIZE
+#error BIG_TEST_SIZE is smaller than TEST_SIZE
+#endif
 
-    fprintf(f, "%s", title);
-    for (; n < l; ++n) {
-        if ((n % 16) == 0)
-            fprintf(f, "\n%04x", n);
-        fprintf(f, " %02x", s[n]);
-    }
-    fprintf(f, "\n");
-}
+static unsigned char rkey[16];
+static unsigned char rkey2[16];
+static unsigned char plaintext[BIG_TEST_SIZE];
+static unsigned char saved_iv[AES_BLOCK_SIZE * 4];
 
 #define MAX_VECTOR_SIZE 64
 
@@ -187,297 +141,314 @@ static struct bi_ige_test const bi_ige_test_vectors[] = {
 
 };
 
-static int run_test_vectors(void)
+static int test_ige_vectors(int n)
 {
-    unsigned int n;
-    int errs = 0;
-
-    for (n = 0; n < OSSL_NELEM(ige_test_vectors); ++n) {
-        const struct ige_test *const v = &ige_test_vectors[n];
-        AES_KEY key;
-        unsigned char buf[MAX_VECTOR_SIZE];
-        unsigned char iv[AES_BLOCK_SIZE * 2];
-
-        assert(v->length <= MAX_VECTOR_SIZE);
-
-        if (v->encrypt == AES_ENCRYPT)
-            AES_set_encrypt_key(v->key, 8 * sizeof v->key, &key);
-        else
-            AES_set_decrypt_key(v->key, 8 * sizeof v->key, &key);
-        memcpy(iv, v->iv, sizeof iv);
-        AES_ige_encrypt(v->in, buf, v->length, &key, iv, v->encrypt);
-
-        if (memcmp(v->out, buf, v->length)) {
-            printf("IGE test vector %d failed\n", n);
-            hexdump(stdout, "key", v->key, sizeof v->key);
-            hexdump(stdout, "iv", v->iv, sizeof v->iv);
-            hexdump(stdout, "in", v->in, v->length);
-            hexdump(stdout, "expected", v->out, v->length);
-            hexdump(stdout, "got", buf, v->length);
-
-            ++errs;
-        }
-
-        /* try with in == out */
-        memcpy(iv, v->iv, sizeof iv);
-        memcpy(buf, v->in, v->length);
-        AES_ige_encrypt(buf, buf, v->length, &key, iv, v->encrypt);
-
-        if (memcmp(v->out, buf, v->length)) {
-            printf("IGE test vector %d failed (with in == out)\n", n);
-            hexdump(stdout, "key", v->key, sizeof v->key);
-            hexdump(stdout, "iv", v->iv, sizeof v->iv);
-            hexdump(stdout, "in", v->in, v->length);
-            hexdump(stdout, "expected", v->out, v->length);
-            hexdump(stdout, "got", buf, v->length);
-
-            ++errs;
-        }
+    const struct ige_test *const v = &ige_test_vectors[n];
+    AES_KEY key;
+    unsigned char buf[MAX_VECTOR_SIZE];
+    unsigned char iv[AES_BLOCK_SIZE * 2];
+    int testresult = 1;
+
+    if (!TEST_int_le(v->length, MAX_VECTOR_SIZE))
+        return 0;
+
+    if (v->encrypt == AES_ENCRYPT)
+        AES_set_encrypt_key(v->key, 8 * sizeof(v->key), &key);
+    else
+        AES_set_decrypt_key(v->key, 8 * sizeof(v->key), &key);
+    memcpy(iv, v->iv, sizeof(iv));
+    AES_ige_encrypt(v->in, buf, v->length, &key, iv, v->encrypt);
+
+    if (!TEST_mem_eq(v->out, v->length, buf, v->length)) {
+        TEST_info("IGE test vector %d failed", n);
+        test_output_memory("key", v->key, sizeof(v->key));
+        test_output_memory("iv", v->iv, sizeof(v->iv));
+        test_output_memory("in", v->in, v->length);
+        testresult = 0;
     }
 
-    for (n = 0; n < OSSL_NELEM(bi_ige_test_vectors); ++n) {
-        const struct bi_ige_test *const v = &bi_ige_test_vectors[n];
-        AES_KEY key1;
-        AES_KEY key2;
-        unsigned char buf[MAX_VECTOR_SIZE];
-
-        assert(v->length <= MAX_VECTOR_SIZE);
-
-        if (v->encrypt == AES_ENCRYPT) {
-            AES_set_encrypt_key(v->key1, 8 * v->keysize, &key1);
-            AES_set_encrypt_key(v->key2, 8 * v->keysize, &key2);
-        } else {
-            AES_set_decrypt_key(v->key1, 8 * v->keysize, &key1);
-            AES_set_decrypt_key(v->key2, 8 * v->keysize, &key2);
-        }
-
-        AES_bi_ige_encrypt(v->in, buf, v->length, &key1, &key2, v->iv,
-                           v->encrypt);
-
-        if (memcmp(v->out, buf, v->length)) {
-            printf("Bidirectional IGE test vector %d failed\n", n);
-            hexdump(stdout, "key 1", v->key1, sizeof v->key1);
-            hexdump(stdout, "key 2", v->key2, sizeof v->key2);
-            hexdump(stdout, "iv", v->iv, sizeof v->iv);
-            hexdump(stdout, "in", v->in, v->length);
-            hexdump(stdout, "expected", v->out, v->length);
-            hexdump(stdout, "got", buf, v->length);
-
-            ++errs;
-        }
+    /* try with in == out */
+    memcpy(iv, v->iv, sizeof(iv));
+    memcpy(buf, v->in, v->length);
+    AES_ige_encrypt(buf, buf, v->length, &key, iv, v->encrypt);
+
+    if (!TEST_mem_eq(v->out, v->length, buf, v->length)) {
+        TEST_info("IGE test vector %d failed (with in == out)", n);
+        test_output_memory("key", v->key, sizeof(v->key));
+        test_output_memory("iv", v->iv, sizeof(v->iv));
+        test_output_memory("in", v->in, v->length);
+        testresult = 0;
     }
 
-    return errs;
+    return testresult;
 }
 
-int main(int argc, char **argv)
+static int test_bi_ige_vectors(int n)
 {
-    unsigned char rkey[16];
-    unsigned char rkey2[16];
-    AES_KEY key;
+    const struct bi_ige_test *const v = &bi_ige_test_vectors[n];
+    AES_KEY key1;
     AES_KEY key2;
-    unsigned char plaintext[BIG_TEST_SIZE];
-    unsigned char ciphertext[BIG_TEST_SIZE];
-    unsigned char checktext[BIG_TEST_SIZE];
-    unsigned char iv[AES_BLOCK_SIZE * 4];
-    unsigned char saved_iv[AES_BLOCK_SIZE * 4];
-    int err = 0;
-    unsigned int n;
-    unsigned matches;
+    unsigned char buf[MAX_VECTOR_SIZE];
 
-    assert(BIG_TEST_SIZE >= TEST_SIZE);
+        if (!TEST_int_le(v->length, MAX_VECTOR_SIZE))
+            return 0;
+
+    if (v->encrypt == AES_ENCRYPT) {
+        AES_set_encrypt_key(v->key1, 8 * v->keysize, &key1);
+        AES_set_encrypt_key(v->key2, 8 * v->keysize, &key2);
+    } else {
+        AES_set_decrypt_key(v->key1, 8 * v->keysize, &key1);
+        AES_set_decrypt_key(v->key2, 8 * v->keysize, &key2);
+    }
+
+    AES_bi_ige_encrypt(v->in, buf, v->length, &key1, &key2, v->iv,
+                       v->encrypt);
+
+    if (!TEST_mem_eq(v->out, v->length, buf, v->length)) {
+        test_output_memory("key 1", v->key1, sizeof(v->key1));
+        test_output_memory("key 2", v->key2, sizeof(v->key2));
+        test_output_memory("iv", v->iv, sizeof(v->iv));
+        test_output_memory("in", v->in, v->length);
+        return 0;
+    }
 
-    RAND_bytes(rkey, sizeof rkey);
-    RAND_bytes(plaintext, sizeof plaintext);
-    RAND_bytes(iv, sizeof iv);
-    memcpy(saved_iv, iv, sizeof saved_iv);
+    return 1;
+}
 
-    /* Forward IGE only... */
+static int test_ige_enc_dec(void)
+{
+    AES_KEY key;
+    unsigned char iv[AES_BLOCK_SIZE * 4];
+    unsigned char ciphertext[BIG_TEST_SIZE];
+    unsigned char checktext[BIG_TEST_SIZE];
 
-    /* Straight encrypt/decrypt */
-    AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
+    memcpy(iv, saved_iv, sizeof(iv));
+    AES_set_encrypt_key(rkey, 8 * sizeof(rkey), &key);
     AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE, &key, iv, AES_ENCRYPT);
 
-    AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
-    memcpy(iv, saved_iv, sizeof iv);
+    AES_set_decrypt_key(rkey, 8 * sizeof(rkey), &key);
+    memcpy(iv, saved_iv, sizeof(iv));
     AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv, AES_DECRYPT);
 
-    if (memcmp(checktext, plaintext, TEST_SIZE)) {
-        printf("Encrypt+decrypt doesn't match\n");
-        hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
-        hexdump(stdout, "Checktext", checktext, TEST_SIZE);
-        ++err;
-    }
+    return TEST_mem_eq(checktext, TEST_SIZE, plaintext, TEST_SIZE);
+}
 
-    /* Now check encrypt chaining works */
-    AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
-    memcpy(iv, saved_iv, sizeof iv);
+static int test_ige_enc_chaining(void)
+{
+    AES_KEY key;
+    unsigned char iv[AES_BLOCK_SIZE * 4];
+    unsigned char ciphertext[BIG_TEST_SIZE];
+    unsigned char checktext[BIG_TEST_SIZE];
+
+    AES_set_encrypt_key(rkey, 8 * sizeof(rkey), &key);
+    memcpy(iv, saved_iv, sizeof(iv));
     AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE / 2, &key, iv,
                     AES_ENCRYPT);
     AES_ige_encrypt(plaintext + TEST_SIZE / 2,
                     ciphertext + TEST_SIZE / 2, TEST_SIZE / 2,
                     &key, iv, AES_ENCRYPT);
 
-    AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
-    memcpy(iv, saved_iv, sizeof iv);
+    AES_set_decrypt_key(rkey, 8 * sizeof(rkey), &key);
+    memcpy(iv, saved_iv, sizeof(iv));
     AES_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, iv, AES_DECRYPT);
 
-    if (memcmp(checktext, plaintext, TEST_SIZE)) {
-        printf("Chained encrypt+decrypt doesn't match\n");
-        hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
-        hexdump(stdout, "Checktext", checktext, TEST_SIZE);
-        ++err;
-    }
+    return TEST_mem_eq(checktext, TEST_SIZE, plaintext, TEST_SIZE);
+}
 
-    /* And check decrypt chaining */
-    AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
-    memcpy(iv, saved_iv, sizeof iv);
+static int test_ige_dec_chaining(void)
+{
+    AES_KEY key;
+    unsigned char iv[AES_BLOCK_SIZE * 4];
+    unsigned char ciphertext[BIG_TEST_SIZE];
+    unsigned char checktext[BIG_TEST_SIZE];
+
+    AES_set_encrypt_key(rkey, 8 * sizeof(rkey), &key);
+    memcpy(iv, saved_iv, sizeof(iv));
     AES_ige_encrypt(plaintext, ciphertext, TEST_SIZE / 2, &key, iv,
                     AES_ENCRYPT);
     AES_ige_encrypt(plaintext + TEST_SIZE / 2,
                     ciphertext + TEST_SIZE / 2, TEST_SIZE / 2,
                     &key, iv, AES_ENCRYPT);
 
-    AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
-    memcpy(iv, saved_iv, sizeof iv);
+    AES_set_decrypt_key(rkey, 8 * sizeof(rkey), &key);
+    memcpy(iv, saved_iv, sizeof(iv));
     AES_ige_encrypt(ciphertext, checktext, TEST_SIZE / 2, &key, iv,
                     AES_DECRYPT);
     AES_ige_encrypt(ciphertext + TEST_SIZE / 2,
                     checktext + TEST_SIZE / 2, TEST_SIZE / 2, &key, iv,
                     AES_DECRYPT);
 
-    if (memcmp(checktext, plaintext, TEST_SIZE)) {
-        printf("Chained encrypt+chained decrypt doesn't match\n");
-        hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
-        hexdump(stdout, "Checktext", checktext, TEST_SIZE);
-        ++err;
-    }
+    return TEST_mem_eq(checktext, TEST_SIZE, plaintext, TEST_SIZE);
+}
+
+static int test_ige_garble_forwards(void)
+{
+    AES_KEY key;
+    unsigned char iv[AES_BLOCK_SIZE * 4];
+    unsigned char ciphertext[BIG_TEST_SIZE];
+    unsigned char checktext[BIG_TEST_SIZE];
+    unsigned int n;
+    int testresult = 1;
+    const size_t ctsize = sizeof(checktext);
+    size_t matches;
 
-    /* make sure garble extends forwards only */
-    AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
-    memcpy(iv, saved_iv, sizeof iv);
-    AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
+    AES_set_encrypt_key(rkey, 8 * sizeof(rkey), &key);
+    memcpy(iv, saved_iv, sizeof(iv));
+    AES_ige_encrypt(plaintext, ciphertext, sizeof(plaintext), &key, iv,
                     AES_ENCRYPT);
 
     /* corrupt halfway through */
-    ++ciphertext[sizeof ciphertext / 2];
-    AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
-    memcpy(iv, saved_iv, sizeof iv);
-    AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
+    ++ciphertext[sizeof(ciphertext) / 2];
+    AES_set_decrypt_key(rkey, 8 * sizeof(rkey), &key);
+    memcpy(iv, saved_iv, sizeof(iv));
+    AES_ige_encrypt(ciphertext, checktext, sizeof(checktext), &key, iv,
                     AES_DECRYPT);
 
     matches = 0;
-    for (n = 0; n < sizeof checktext; ++n)
+    for (n = 0; n < sizeof(checktext); ++n)
         if (checktext[n] == plaintext[n])
             ++matches;
 
-    if (matches > sizeof checktext / 2 + sizeof checktext / 100) {
-        printf("More than 51%% matches after garbling\n");
-        ++err;
-    }
-
-    if (matches < sizeof checktext / 2) {
-        printf("Garble extends backwards!\n");
-        ++err;
-    }
-
-    /* Bi-directional IGE */
+    /* Fail if there is more than 51% matching bytes */
+    if (!TEST_size_t_le(matches, ctsize / 2 + ctsize / 100))
+        testresult = 0;
 
-    /*
-     * Note that we don't have to recover the IV, because chaining isn't
-     */
-    /* possible with biIGE, so the IV is not updated. */
+    /* Fail if the garble goes backwards */
+    if (!TEST_size_t_gt(matches, ctsize / 2))
+        testresult = 0;
+    return testresult;
+}
 
-    RAND_bytes(rkey2, sizeof rkey2);
+static int test_bi_ige_enc_dec(void)
+{
+    AES_KEY key, key2;
+    unsigned char iv[AES_BLOCK_SIZE * 4];
+    unsigned char ciphertext[BIG_TEST_SIZE];
+    unsigned char checktext[BIG_TEST_SIZE];
 
-    /* Straight encrypt/decrypt */
-    AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
-    AES_set_encrypt_key(rkey2, 8 * sizeof rkey2, &key2);
+    memcpy(iv, saved_iv, sizeof(iv));
+    AES_set_encrypt_key(rkey, 8 * sizeof(rkey), &key);
+    AES_set_encrypt_key(rkey2, 8 * sizeof(rkey2), &key2);
     AES_bi_ige_encrypt(plaintext, ciphertext, TEST_SIZE, &key, &key2, iv,
                        AES_ENCRYPT);
 
-    AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
-    AES_set_decrypt_key(rkey2, 8 * sizeof rkey2, &key2);
+    AES_set_decrypt_key(rkey, 8 * sizeof(rkey), &key);
+    AES_set_decrypt_key(rkey2, 8 * sizeof(rkey2), &key2);
     AES_bi_ige_encrypt(ciphertext, checktext, TEST_SIZE, &key, &key2, iv,
                        AES_DECRYPT);
 
-    if (memcmp(checktext, plaintext, TEST_SIZE)) {
-        printf("Encrypt+decrypt doesn't match\n");
-        hexdump(stdout, "Plaintext", plaintext, TEST_SIZE);
-        hexdump(stdout, "Checktext", checktext, TEST_SIZE);
-        ++err;
-    }
+    return TEST_mem_eq(checktext, TEST_SIZE, plaintext, TEST_SIZE);
+}
 
-    /* make sure garble extends both ways */
-    AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
-    AES_set_encrypt_key(rkey2, 8 * sizeof rkey2, &key2);
-    AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
+static int test_bi_ige_garble1(void)
+{
+    AES_KEY key, key2;
+    unsigned char iv[AES_BLOCK_SIZE * 4];
+    unsigned char ciphertext[BIG_TEST_SIZE];
+    unsigned char checktext[BIG_TEST_SIZE];
+    unsigned int n;
+    size_t matches;
+
+    memcpy(iv, saved_iv, sizeof(iv));
+    AES_set_encrypt_key(rkey, 8 * sizeof(rkey), &key);
+    AES_set_encrypt_key(rkey2, 8 * sizeof(rkey2), &key2);
+    AES_ige_encrypt(plaintext, ciphertext, sizeof(plaintext), &key, iv,
                     AES_ENCRYPT);
 
     /* corrupt halfway through */
-    ++ciphertext[sizeof ciphertext / 2];
-    AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
-    AES_set_decrypt_key(rkey2, 8 * sizeof rkey2, &key2);
-    AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
+    ++ciphertext[sizeof(ciphertext) / 2];
+    AES_set_decrypt_key(rkey, 8 * sizeof(rkey), &key);
+    AES_set_decrypt_key(rkey2, 8 * sizeof(rkey2), &key2);
+    AES_ige_encrypt(ciphertext, checktext, sizeof(checktext), &key, iv,
                     AES_DECRYPT);
 
     matches = 0;
-    for (n = 0; n < sizeof checktext; ++n)
+    for (n = 0; n < sizeof(checktext); ++n)
         if (checktext[n] == plaintext[n])
             ++matches;
 
-    if (matches > sizeof checktext / 100) {
-        printf("More than 1%% matches after bidirectional garbling\n");
-        ++err;
-    }
+    /* Fail if there is more than 1% matching bytes */
+    return TEST_size_t_le(matches, sizeof(checktext) / 100);
+}
 
-    /* make sure garble extends both ways (2) */
-    AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
-    AES_set_encrypt_key(rkey2, 8 * sizeof rkey2, &key2);
-    AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
+static int test_bi_ige_garble2(void)
+{
+    AES_KEY key, key2;
+    unsigned char iv[AES_BLOCK_SIZE * 4];
+    unsigned char ciphertext[BIG_TEST_SIZE];
+    unsigned char checktext[BIG_TEST_SIZE];
+    unsigned int n;
+    size_t matches;
+
+    memcpy(iv, saved_iv, sizeof(iv));
+    AES_set_encrypt_key(rkey, 8 * sizeof(rkey), &key);
+    AES_set_encrypt_key(rkey2, 8 * sizeof(rkey2), &key2);
+    AES_ige_encrypt(plaintext, ciphertext, sizeof(plaintext), &key, iv,
                     AES_ENCRYPT);
 
     /* corrupt right at the end */
-    ++ciphertext[sizeof ciphertext - 1];
-    AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
-    AES_set_decrypt_key(rkey2, 8 * sizeof rkey2, &key2);
-    AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
+    ++ciphertext[sizeof(ciphertext) - 1];
+    AES_set_decrypt_key(rkey, 8 * sizeof(rkey), &key);
+    AES_set_decrypt_key(rkey2, 8 * sizeof(rkey2), &key2);
+    AES_ige_encrypt(ciphertext, checktext, sizeof(checktext), &key, iv,
                     AES_DECRYPT);
 
     matches = 0;
-    for (n = 0; n < sizeof checktext; ++n)
+    for (n = 0; n < sizeof(checktext); ++n)
         if (checktext[n] == plaintext[n])
             ++matches;
 
-    if (matches > sizeof checktext / 100) {
-        printf("More than 1%% matches after bidirectional garbling (2)\n");
-        ++err;
-    }
+    /* Fail if there is more than 1% matching bytes */
+    return TEST_size_t_le(matches, sizeof(checktext) / 100);
+}
 
-    /* make sure garble extends both ways (3) */
-    AES_set_encrypt_key(rkey, 8 * sizeof rkey, &key);
-    AES_set_encrypt_key(rkey2, 8 * sizeof rkey2, &key2);
-    AES_ige_encrypt(plaintext, ciphertext, sizeof plaintext, &key, iv,
+static int test_bi_ige_garble3(void)
+{
+    AES_KEY key, key2;
+    unsigned char iv[AES_BLOCK_SIZE * 4];
+    unsigned char ciphertext[BIG_TEST_SIZE];
+    unsigned char checktext[BIG_TEST_SIZE];
+    unsigned int n;
+    size_t matches;
+
+    memcpy(iv, saved_iv, sizeof(iv));
+    AES_set_encrypt_key(rkey, 8 * sizeof(rkey), &key);
+    AES_set_encrypt_key(rkey2, 8 * sizeof(rkey2), &key2);
+    AES_ige_encrypt(plaintext, ciphertext, sizeof(plaintext), &key, iv,
                     AES_ENCRYPT);
 
     /* corrupt right at the start */
     ++ciphertext[0];
-    AES_set_decrypt_key(rkey, 8 * sizeof rkey, &key);
-    AES_set_decrypt_key(rkey2, 8 * sizeof rkey2, &key2);
-    AES_ige_encrypt(ciphertext, checktext, sizeof checktext, &key, iv,
+    AES_set_decrypt_key(rkey, 8 * sizeof(rkey), &key);
+    AES_set_decrypt_key(rkey2, 8 * sizeof(rkey2), &key2);
+    AES_ige_encrypt(ciphertext, checktext, sizeof(checktext), &key, iv,
                     AES_DECRYPT);
 
     matches = 0;
-    for (n = 0; n < sizeof checktext; ++n)
+    for (n = 0; n < sizeof(checktext); ++n)
         if (checktext[n] == plaintext[n])
             ++matches;
 
-    if (matches > sizeof checktext / 100) {
-        printf("More than 1%% matches after bidirectional garbling (3)\n");
-        ++err;
-    }
-
-    err += run_test_vectors();
+    /* Fail if there is more than 1% matching bytes */
+    return TEST_size_t_le(matches, sizeof(checktext) / 100);
+}
 
-    return err;
+int setup_tests(void)
+{
+    RAND_bytes(rkey, sizeof(rkey));
+    RAND_bytes(rkey2, sizeof(rkey2));
+    RAND_bytes(plaintext, sizeof(plaintext));
+    RAND_bytes(saved_iv, sizeof(saved_iv));
+
+    ADD_TEST(test_ige_enc_dec);
+    ADD_TEST(test_ige_enc_chaining);
+    ADD_TEST(test_ige_dec_chaining);
+    ADD_TEST(test_ige_garble_forwards);
+    ADD_TEST(test_bi_ige_enc_dec);
+    ADD_TEST(test_bi_ige_garble1);
+    ADD_TEST(test_bi_ige_garble2);
+    ADD_TEST(test_bi_ige_garble3);
+    ADD_ALL_TESTS(test_ige_vectors, OSSL_NELEM(ige_test_vectors));
+    ADD_ALL_TESTS(test_bi_ige_vectors, OSSL_NELEM(bi_ige_test_vectors));
+    return 1;
 }