/*
 * Copyright 1995-2016 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 <stdio.h>
#include <string.h>
#include <stdlib.h>

#include <openssl/opensslconf.h> /* To see if OPENSSL_NO_CAST is defined */
#include "e_os.h"
#include "testutil.h"

#ifndef OPENSSL_NO_CAST
# include <openssl/cast.h>

static unsigned char k[16] = {
    0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
    0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
};

static unsigned char in[8] =
    { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF };

static int k_len[3] = { 16, 10, 5 };

static unsigned char c[3][8] = {
    {0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2},
    {0xEB, 0x6A, 0x71, 0x1A, 0x2C, 0x02, 0x27, 0x1B},
    {0x7A, 0xC8, 0x16, 0xD1, 0x6E, 0x9B, 0x30, 0x2E},
};

static unsigned char in_a[16] = {
    0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
    0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
};

static unsigned char in_b[16] = {
    0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78,
    0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A
};

static unsigned char c_a[16] = {
    0xEE, 0xA9, 0xD0, 0xA2, 0x49, 0xFD, 0x3B, 0xA6,
    0xB3, 0x43, 0x6F, 0xB8, 0x9D, 0x6D, 0xCA, 0x92
};

static unsigned char c_b[16] = {
    0xB2, 0xC9, 0x5E, 0xB0, 0x0C, 0x31, 0xAD, 0x71,
    0x80, 0xAC, 0x05, 0xB8, 0xE8, 0x3D, 0x69, 0x6E
};

static int cast_test_vector(int z)
{
    int testresult = 1;
    CAST_KEY key;
    unsigned char out[80];

    CAST_set_key(&key, k_len[z], k);
    CAST_ecb_encrypt(in, out, &key, CAST_ENCRYPT);
    if (!TEST_mem_eq(out, sizeof(c[z]), c[z], sizeof(c[z]))) {
        TEST_info("CAST_ENCRYPT iteration %d failed (len=%d)", z, k_len[z]);
        testresult = 0;
    }

    CAST_ecb_encrypt(out, out, &key, CAST_DECRYPT);
    if (!TEST_mem_eq(out, sizeof(in), in, sizeof(in))) {
        TEST_info("CAST_DECRYPT iteration %d failed (len=%d)", z, k_len[z]);
        testresult = 0;
    }
    return testresult;
}

static int cast_test_iterations(void)
{
    long l;
    int testresult = 1;
    CAST_KEY key, key_b;
    unsigned char out_a[16], out_b[16];

    memcpy(out_a, in_a, sizeof(in_a));
    memcpy(out_b, in_b, sizeof(in_b));

    for (l = 0; l < 1000000L; l++) {
        CAST_set_key(&key_b, 16, out_b);
        CAST_ecb_encrypt(&(out_a[0]), &(out_a[0]), &key_b, CAST_ENCRYPT);
        CAST_ecb_encrypt(&(out_a[8]), &(out_a[8]), &key_b, CAST_ENCRYPT);
        CAST_set_key(&key, 16, out_a);
        CAST_ecb_encrypt(&(out_b[0]), &(out_b[0]), &key, CAST_ENCRYPT);
        CAST_ecb_encrypt(&(out_b[8]), &(out_b[8]), &key, CAST_ENCRYPT);
    }

    if (!TEST_mem_eq(out_a, sizeof(c_a), c_a, sizeof(c_a))
            || !TEST_mem_eq(out_b, sizeof(c_b), c_b, sizeof(c_b)))
        testresult = 0;

    return testresult;
}
#endif

void register_tests(void)
{
#ifndef OPENSSL_NO_CAST
    ADD_ALL_TESTS(cast_test_vector, OSSL_NELEM(k_len));
    ADD_TEST(cast_test_iterations);
#endif
}
