/* Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.

 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * 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.
 *   * Neither the name of The Linux Foundation nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR 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.
 */

#include <string.h>
#include <debug.h>
#include <sys/types.h>
#include "crypto_hash.h"

static crypto_SHA256_ctx g_sha256_ctx;
static crypto_SHA1_ctx g_sha1_ctx;
static bool crypto_init_done;

extern void ce_clock_init(void);

/*
 * Top level function which calculates SHAx digest with given data and size.
 * Digest varies based on the authentication algorithm.
 * It works on contiguous data and does single pass calculation.
 */

void
hash_find(unsigned char *addr, unsigned int size, unsigned char *digest,
	  unsigned char auth_alg)
{
	crypto_result_type ret_val = CRYPTO_SHA_ERR_NONE;
	crypto_engine_type platform_ce_type = board_ce_type();

	if (auth_alg == CRYPTO_AUTH_ALG_SHA1) {
		if(platform_ce_type == CRYPTO_ENGINE_TYPE_SW)
			/* Hardware CE is not present , use software hashing */
			digest = SHA1(addr, size, digest);
		else if (platform_ce_type == CRYPTO_ENGINE_TYPE_HW)
			ret_val = crypto_sha1(addr, size, digest);
		else
			ret_val = CRYPTO_SHA_ERR_FAIL;
	} else if (auth_alg == CRYPTO_AUTH_ALG_SHA256) {
		if(platform_ce_type == CRYPTO_ENGINE_TYPE_SW)
			/* Hardware CE is not present , use software hashing */
			digest = SHA256(addr, size, digest);
		else if (platform_ce_type == CRYPTO_ENGINE_TYPE_HW)
			ret_val = crypto_sha256(addr, size, digest);
		else
		ret_val = CRYPTO_SHA_ERR_FAIL;
	}
	else
		ret_val = CRYPTO_SHA_ERR_FAIL;

	if (ret_val != CRYPTO_SHA_ERR_NONE) {
		dprintf(CRITICAL, "crypto_sha256 returns error %d\n", ret_val);
	}
}

/*
 * Function to reset and init crypto engine. It resets the engine for the
 * first time. Used for multiple SHA operations.
 */

static void crypto_init(void)
{
	if (crypto_init_done != TRUE) {
		ce_clock_init();
		crypto_eng_reset();
		crypto_init_done = TRUE;
	}
	crypto_eng_init();
}

/*
 * Function to return if crypto is initialized
 */

bool crypto_initialized()
{
	return crypto_init_done;
}

/*
 * Function to initialize SHA256 context
 */

static crypto_result_type crypto_sha256_init(crypto_SHA256_ctx * ctx_ptr)
{
	unsigned int i;
	/* Standard initialization vector for SHA256 */
	unsigned int sha256_init_vector[] = { 0x6A09E667, 0xBB67AE85,
		0x3C6EF372, 0xA54FF53A,
		0x510E527F, 0x9B05688C,
		0x1F83D9AB, 0x5BE0CD19
	};

	if (ctx_ptr == NULL) {
		return CRYPTO_SHA_ERR_INVALID_PARAM;
	}

	ctx_ptr->auth_bytecnt[0] = 0;
	ctx_ptr->auth_bytecnt[1] = 0;

	memset(ctx_ptr->saved_buff, 0, CRYPTO_SHA_BLOCK_SIZE);

	for (i = 0; i < SHA256_INIT_VECTOR_SIZE; i++) {
		ctx_ptr->auth_iv[i] = sha256_init_vector[i];
	}

	ctx_ptr->saved_buff_indx = 0;

	return CRYPTO_SHA_ERR_NONE;
}

/*
 * Function to initialize SHA1 context
 */

static crypto_result_type crypto_sha1_init(crypto_SHA1_ctx * ctx_ptr)
{
	unsigned int i;
	/* Standard initialization vector for SHA1 */
	unsigned int sha1_init_vector[] = { 0x67452301, 0xEFCDAB89,
		0x98BADCFE, 0x10325476,
		0xC3D2E1F0
	};

	if (ctx_ptr == NULL) {
		return CRYPTO_SHA_ERR_INVALID_PARAM;
	}

	ctx_ptr->auth_bytecnt[0] = 0;
	ctx_ptr->auth_bytecnt[1] = 0;

	memset(ctx_ptr->saved_buff, 0, CRYPTO_SHA_BLOCK_SIZE);

	for (i = 0; i < SHA1_INIT_VECTOR_SIZE; i++) {
		ctx_ptr->auth_iv[i] = sha1_init_vector[i];
	}

	ctx_ptr->saved_buff_indx = 0;

	return CRYPTO_SHA_ERR_NONE;
}

/*
 * Function to calculate SHA256 digest of given data buffer.
 * It works on contiguous data and gives digest in single pass.
 */

static crypto_result_type
crypto_sha256(unsigned char *buff_ptr,
	      unsigned int buff_size, unsigned char *digest_ptr)
{
	crypto_result_type ret_val = CRYPTO_SHA_ERR_NONE;

	if ((!buff_size) || (buff_ptr == NULL) || (digest_ptr == NULL)) {
		return CRYPTO_SHA_ERR_INVALID_PARAM;
	}

	/* Initialize crypto engine hardware for a new SHA256 operation */
	crypto_init();

	/* Now do SHA256 hashing */
	ret_val =
	    do_sha(buff_ptr, buff_size, digest_ptr, CRYPTO_AUTH_ALG_SHA256);

	if (ret_val != CRYPTO_SHA_ERR_NONE) {
		dprintf(CRITICAL, "crypto_sha256 returns error %d\n", ret_val);
	}

	return ret_val;
}

/*
 * Function to calculate SHA1 digest of given data buffer.
 * It works on contiguous data and gives digest in single pass.
 */

static crypto_result_type
crypto_sha1(unsigned char *buff_ptr,
	    unsigned int buff_size, unsigned char *digest_ptr)
{
	crypto_result_type ret_val = CRYPTO_SHA_ERR_NONE;

	if ((!buff_size) || (buff_ptr == NULL) || (digest_ptr == NULL)) {
		return CRYPTO_SHA_ERR_INVALID_PARAM;
	}

	/* Initialize crypto engine hardware for a new SHA1 operation */
	crypto_init();

	/* Now do SHA1 hashing */
	ret_val = do_sha(buff_ptr, buff_size, digest_ptr, CRYPTO_AUTH_ALG_SHA1);

	if (ret_val != CRYPTO_SHA_ERR_NONE) {
		dprintf(CRITICAL, "crypto_sha256 returns error %d\n", ret_val);
	}

	return ret_val;
}

/*
 * Common function to calculate SHA1 and SHA256 digest based on auth algorithm.
 */

static crypto_result_type
do_sha(unsigned char *buff_ptr,
       unsigned int buff_size,
       unsigned char *digest_ptr, crypto_auth_alg_type auth_alg)
{
	void *ctx_ptr = NULL;
	crypto_result_type ret_val = CRYPTO_SHA_ERR_NONE;

	/* Initialize SHA context based on algorithm */
	if (auth_alg == CRYPTO_AUTH_ALG_SHA1) {
		crypto_sha1_init(&g_sha1_ctx);
		ctx_ptr = (void *)&g_sha1_ctx;
	} else if (auth_alg == CRYPTO_AUTH_ALG_SHA256) {
		crypto_sha256_init(&g_sha256_ctx);
		ctx_ptr = (void *)&g_sha256_ctx;
	}

	ret_val =
	    do_sha_update(ctx_ptr, buff_ptr, buff_size, auth_alg, TRUE, TRUE);

	if (ret_val != CRYPTO_SHA_ERR_NONE) {
		dprintf(CRITICAL, "do_sha_update returns error %d\n", ret_val);
		return ret_val;
	}

	/* Copy the digest value from context pointer to digest pointer */
	if (auth_alg == CRYPTO_AUTH_ALG_SHA1) {
		memcpy(digest_ptr,
		       (unsigned char *)(((crypto_SHA1_ctx *) ctx_ptr)->
					 auth_iv), 20);
	} else if (auth_alg == CRYPTO_AUTH_ALG_SHA256) {
		memcpy(digest_ptr,
		       (unsigned char *)(((crypto_SHA256_ctx *) ctx_ptr)->
					 auth_iv), 32);
	}

	return CRYPTO_SHA_ERR_NONE;
}

/*
 * Common function to calculate SHA1 and SHA256 digest based on auth algorithm.
 * Calls crypto engine APIs to setup SHAx registers, send the data and gets
 * the digest.
 */

static crypto_result_type
do_sha_update(void *ctx_ptr,
	      unsigned char *buff_ptr,
	      unsigned int buff_size,
	      crypto_auth_alg_type auth_alg, bool first, bool last)
{
	unsigned int ret_val = CRYPTO_ERR_NONE;
	unsigned int bytes_to_write = 0;
	unsigned int bytes_remaining = 0;
	unsigned int tmp_bytes = 0;
	unsigned int bytes_written = 0;
	unsigned int tmp_buff_size = 0;
	unsigned char *tmp_buff_ptr = NULL;
	unsigned char tmp_saved_buff_indx = 0;
	bool tmp_first;
	bool tmp_last;

	/* Type casting to SHA1 context as offset is similar for SHA256 context */
	crypto_SHA1_ctx *sha1_ctx = (crypto_SHA1_ctx *) ctx_ptr;

	bytes_to_write = calc_num_bytes_to_send(ctx_ptr, buff_size, last);
	bytes_remaining =
	    buff_size + sha1_ctx->saved_buff_indx - bytes_to_write;

	tmp_first = first;
	tmp_saved_buff_indx = sha1_ctx->saved_buff_indx;

	do {
		if ((bytes_to_write - bytes_written) >
		    crypto_get_max_auth_blk_size()) {
			/* Write CRYPTO_MAX_AUTH_BLOCK_SIZE bytes at a time to the CE */
			tmp_bytes = crypto_get_max_auth_blk_size();
			tmp_last = FALSE;

			if (sha1_ctx->saved_buff_indx != 0) {
				tmp_buff_ptr = buff_ptr;
				tmp_buff_size =
				    tmp_bytes - sha1_ctx->saved_buff_indx;
			} else {
				tmp_buff_ptr =
				    buff_ptr + bytes_written -
				    tmp_saved_buff_indx;
				tmp_buff_size = tmp_bytes;
			}
		} else {
			/* Since bytes_to_write are less than CRYPTO_MAX_AUTH_BLOCK_SIZE
			   write all remaining bytes now */
			if (sha1_ctx->saved_buff_indx != 0) {
				tmp_buff_ptr = buff_ptr;
				tmp_buff_size =
				    bytes_to_write - bytes_written -
				    sha1_ctx->saved_buff_indx;
			} else {
				tmp_buff_ptr =
				    buff_ptr + bytes_written -
				    tmp_saved_buff_indx;
				tmp_buff_size =
				    bytes_to_write - bytes_written -
				    tmp_saved_buff_indx;
			}

			tmp_bytes = (bytes_to_write - bytes_written);
			tmp_last = last;
		}

		/* Set SHAx context in the crypto engine */
		crypto_set_sha_ctx(ctx_ptr, tmp_bytes, auth_alg, tmp_first,
				   tmp_last);

		/* Send data to the crypto engine */
		crypto_send_data(ctx_ptr, tmp_buff_ptr, tmp_buff_size,
				 tmp_bytes, &ret_val);

		if (ret_val != CRYPTO_ERR_NONE) {
			dprintf(CRITICAL,
				"do_sha_update returns error from crypto_send_data\n");
			return CRYPTO_SHA_ERR_FAIL;
		}

		/* Get the SHAx digest from the crypto engine */
		crypto_get_digest((unsigned char *)(sha1_ctx->auth_iv),
				  &ret_val, auth_alg, tmp_last);

		if (ret_val != CRYPTO_ERR_NONE) {
			dprintf(CRITICAL,
				"do_sha_update returns error from crypto_get_digest\n");
			return CRYPTO_SHA_ERR_FAIL;
		}

		if (!tmp_last) {
			crypto_get_ctx(ctx_ptr);
		}

		bytes_written += tmp_bytes;
		sha1_ctx->saved_buff_indx = 0;

		if (bytes_written != bytes_to_write) {
			tmp_first = FALSE;
		}

	}
	while ((bytes_to_write - bytes_written) != 0);

	/* If there are bytes remaining, copy it to saved_buff */

	if (bytes_remaining) {
		memcpy(sha1_ctx->saved_buff,
		       (buff_ptr + buff_size - bytes_remaining),
		       bytes_remaining);
		sha1_ctx->saved_buff_indx = bytes_remaining;
	} else {
		sha1_ctx->saved_buff_indx = 0;
	}

	return CRYPTO_SHA_ERR_NONE;
}

/*
 * Function to calculate the number of bytes to be sent to crypto engine.
 */

static unsigned int
calc_num_bytes_to_send(void *ctx_ptr, unsigned int buff_size, bool last)
{
	unsigned int bytes_to_write = 0;
	crypto_SHA1_ctx *sha1_ctx = (crypto_SHA1_ctx *) ctx_ptr;

	if (last) {
		bytes_to_write = buff_size + sha1_ctx->saved_buff_indx;
	} else {
		bytes_to_write = ((buff_size + sha1_ctx->saved_buff_indx) /
				  CRYPTO_SHA_BLOCK_SIZE) *
		    CRYPTO_SHA_BLOCK_SIZE;
	}
	return bytes_to_write;
}
