/*
 * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of the
 * License, or any later version.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301, USA.
 *
 * You can also choose to distribute this program under the terms of
 * the Unmodified Binary Distribution Licence (as given in the file
 * COPYING.UBDL), provided that you have satisfied its requirements.
 */

FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );

/** @file
 *
 * Cipher self-tests
 *
 */

/* Forcibly enable assertions */
#undef NDEBUG

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <ipxe/crypto.h>
#include <ipxe/profile.h>
#include <ipxe/test.h>
#include "cipher_test.h"

/** Number of sample iterations for profiling */
#define PROFILE_COUNT 16

/**
 * Report a cipher encryption test result
 *
 * @v test		Cipher test
 * @v file		Test code file
 * @v line		Test code line
 */
void cipher_encrypt_okx ( struct cipher_test *test, const char *file,
			  unsigned int line ) {
	struct cipher_algorithm *cipher = test->cipher;
	size_t len = test->len;
	uint8_t ctx[cipher->ctxsize];
	uint8_t ciphertext[len];
	uint8_t auth[cipher->authsize];

	/* Initialise cipher */
	okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0,
	      file, line );
	okx ( cipher_setiv ( cipher, ctx, test->iv, test->iv_len ) == 0,
	      file, line );

	/* Process additional data, if applicable */
	if ( test->additional_len ) {
		okx ( is_auth_cipher ( cipher ), file, line );
		cipher_encrypt ( cipher, ctx, test->additional, NULL,
				 test->additional_len );
	}

	/* Perform encryption */
	cipher_encrypt ( cipher, ctx, test->plaintext, ciphertext, len );

	/* Compare against expected ciphertext */
	okx ( memcmp ( ciphertext, test->ciphertext, len ) == 0, file, line );

	/* Check authentication tag */
	okx ( cipher->authsize == test->auth_len, file, line );
	cipher_auth ( cipher, ctx, auth );
	okx ( memcmp ( auth, test->auth, test->auth_len ) == 0, file, line );

	/* Reset initialisation vector */
	okx ( cipher_setiv ( cipher, ctx, test->iv, test->iv_len ) == 0,
	      file, line );

	/* Process additional data, if applicable */
	if ( test->additional_len ) {
		cipher_encrypt ( cipher, ctx, test->additional, NULL,
				 test->additional_len );
	}

	/* Perform in-place encryption */
	memcpy ( ciphertext, test->plaintext, len );
	cipher_encrypt ( cipher, ctx, ciphertext, ciphertext, len );

	/* Compare against expected ciphertext */
	okx ( memcmp ( ciphertext, test->ciphertext, len ) == 0, file, line );

	/* Check authentication tag */
	cipher_auth ( cipher, ctx, auth );
	okx ( memcmp ( auth, test->auth, test->auth_len ) == 0, file, line );
}

/**
 * Report a cipher decryption test result
 *
 * @v test		Cipher test
 * @v file		Test code file
 * @v line		Test code line
 */
void cipher_decrypt_okx ( struct cipher_test *test, const char *file,
			  unsigned int line ) {
	struct cipher_algorithm *cipher = test->cipher;
	size_t len = test->len;
	uint8_t ctx[cipher->ctxsize];
	uint8_t plaintext[len];
	uint8_t auth[cipher->authsize];

	/* Initialise cipher */
	okx ( cipher_setkey ( cipher, ctx, test->key, test->key_len ) == 0,
	      file, line );
	okx ( cipher_setiv ( cipher, ctx, test->iv, test->iv_len ) == 0,
	      file, line );

	/* Process additional data, if applicable */
	if ( test->additional_len ) {
		okx ( is_auth_cipher ( cipher ), file, line );
		cipher_decrypt ( cipher, ctx, test->additional, NULL,
				 test->additional_len );
	}

	/* Perform decryption */
	cipher_decrypt ( cipher, ctx, test->ciphertext, plaintext, len );

	/* Compare against expected plaintext */
	okx ( memcmp ( plaintext, test->plaintext, len ) == 0, file, line );

	/* Check authentication tag */
	okx ( cipher->authsize == test->auth_len, file, line );
	cipher_auth ( cipher, ctx, auth );
	okx ( memcmp ( auth, test->auth, test->auth_len ) == 0, file, line );

	/* Reset initialisation vector */
	okx ( cipher_setiv ( cipher, ctx, test->iv, test->iv_len ) == 0,
	      file, line );

	/* Process additional data, if applicable */
	if ( test->additional_len ) {
		cipher_decrypt ( cipher, ctx, test->additional, NULL,
				 test->additional_len );
	}

	/* Perform in-place decryption */
	memcpy ( plaintext, test->ciphertext, len );
	cipher_decrypt ( cipher, ctx, plaintext, plaintext, len );

	/* Compare against expected plaintext */
	okx ( memcmp ( plaintext, test->plaintext, len ) == 0, file, line );

	/* Check authentication tag */
	cipher_auth ( cipher, ctx, auth );
	okx ( memcmp ( auth, test->auth, test->auth_len ) == 0, file, line );
}

/**
 * Report a cipher encryption and decryption test result
 *
 * @v test		Cipher test
 * @v file		Test code file
 * @v line		Test code line
 */
void cipher_okx ( struct cipher_test *test, const char *file,
		  unsigned int line ) {
	struct cipher_algorithm *cipher = test->cipher;
	size_t len = test->len;

	/* Sanity checks */
	okx ( cipher->blocksize != 0, file, line );
	okx ( ( len % cipher->blocksize ) == 0, file, line );
	okx ( ( cipher->alignsize % cipher->blocksize ) == 0, file, line );

	/* Report encryption test result */
	cipher_encrypt_okx ( test, file, line );

	/* Report decryption test result */
	cipher_decrypt_okx ( test, file, line );
}

/**
 * Calculate cipher encryption or decryption cost
 *
 * @v cipher			Cipher algorithm
 * @v key_len			Length of key
 * @v op			Encryption or decryption operation
 * @ret cost			Cost (in cycles per byte)
 */
static unsigned long
cipher_cost ( struct cipher_algorithm *cipher, size_t key_len,
	      void ( * op ) ( struct cipher_algorithm *cipher, void *ctx,
			      const void *src, void *dst, size_t len ) ) {
	static uint8_t random[8192]; /* Too large for stack */
	uint8_t key[key_len];
	uint8_t iv[cipher->blocksize];
	uint8_t ctx[cipher->ctxsize];
	struct profiler profiler;
	unsigned long cost;
	unsigned int i;
	int rc;

	/* Fill buffer with pseudo-random data */
	srand ( 0x1234568 );
	for ( i = 0 ; i < sizeof ( random ) ; i++ )
		random[i] = rand();
	for ( i = 0 ; i < sizeof ( key ) ; i++ )
		key[i] = rand();
	for ( i = 0 ; i < sizeof ( iv ) ; i++ )
		iv[i] = rand();

	/* Initialise cipher */
	rc = cipher_setkey ( cipher, ctx, key, key_len );
	assert ( rc == 0 );
	rc = cipher_setiv ( cipher, ctx, iv, sizeof ( iv ) );
	assert ( rc == 0 );

	/* Profile cipher operation */
	memset ( &profiler, 0, sizeof ( profiler ) );
	for ( i = 0 ; i < PROFILE_COUNT ; i++ ) {
		profile_start ( &profiler );
		op ( cipher, ctx, random, random, sizeof ( random ) );
		profile_stop ( &profiler );
	}

	/* Round to nearest whole number of cycles per byte */
	cost = ( ( profile_mean ( &profiler ) + ( sizeof ( random ) / 2 ) ) /
		 sizeof ( random ) );

	return cost;
}

/**
 * Calculate cipher encryption cost
 *
 * @v cipher			Cipher algorithm
 * @v key_len			Length of key
 * @ret cost			Cost (in cycles per byte)
 */
unsigned long cipher_cost_encrypt ( struct cipher_algorithm *cipher,
				    size_t key_len ) {
	return cipher_cost ( cipher, key_len, cipher_encrypt );
}

/**
 * Calculate cipher decryption cost
 *
 * @v cipher			Cipher algorithm
 * @v key_len			Length of key
 * @ret cost			Cost (in cycles per byte)
 */
unsigned long cipher_cost_decrypt ( struct cipher_algorithm *cipher,
				    size_t key_len ) {
	return cipher_cost ( cipher, key_len, cipher_decrypt );
}
