/*
Copyright (c) 2010 Werner Dittmann

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

*/

#include <linux/string.h>
#include "skein_api.h"

int skein_ctx_prepare(struct skein_ctx *ctx, enum skein_size size)
{
	skein_assert_ret(ctx && size, SKEIN_FAIL);

	memset(ctx , 0, sizeof(struct skein_ctx));
	ctx->skein_size = size;

	return SKEIN_SUCCESS;
}

int skein_init(struct skein_ctx *ctx, size_t hash_bit_len)
{
	int ret = SKEIN_FAIL;
	size_t x_len = 0;
	u64 *x = NULL;
	u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL;

	skein_assert_ret(ctx, SKEIN_FAIL);
	/*
	 * The following two lines rely of the fact that the real Skein
	 * contexts are a union in out context and thus have tha maximum
	 * memory available.  The beauty of C :-) .
	 */
	x = ctx->m.s256.x;
	x_len = ctx->skein_size/8;
	/*
	 * If size is the same and hash bit length is zero then reuse
	 * the save chaining variables.
	 */
	switch (ctx->skein_size) {
	case SKEIN_256:
		ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len,
					 tree_info, NULL, 0);
		break;
	case SKEIN_512:
		ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len,
					 tree_info, NULL, 0);
		break;
	case SKEIN_1024:
		ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len,
					  tree_info, NULL, 0);
		break;
	}

	if (ret == SKEIN_SUCCESS) {
		/*
		 * Save chaining variables for this combination of size and
		 * hash_bit_len
		 */
		memcpy(ctx->x_save, x, x_len);
	}
	return ret;
}

int skein_mac_init(struct skein_ctx *ctx, const u8 *key, size_t key_len,
		   size_t hash_bit_len)
{
	int ret = SKEIN_FAIL;
	u64 *x = NULL;
	size_t x_len = 0;
	u64 tree_info = SKEIN_CFG_TREE_INFO_SEQUENTIAL;

	skein_assert_ret(ctx, SKEIN_FAIL);

	x = ctx->m.s256.x;
	x_len = ctx->skein_size/8;

	skein_assert_ret(hash_bit_len, SKEIN_BAD_HASHLEN);

	switch (ctx->skein_size) {
	case SKEIN_256:
		ret = skein_256_init_ext(&ctx->m.s256, hash_bit_len,
					 tree_info,
					 (const u8 *)key, key_len);

		break;
	case SKEIN_512:
		ret = skein_512_init_ext(&ctx->m.s512, hash_bit_len,
					 tree_info,
					 (const u8 *)key, key_len);
		break;
	case SKEIN_1024:
		ret = skein_1024_init_ext(&ctx->m.s1024, hash_bit_len,
					  tree_info,
					  (const u8 *)key, key_len);

		break;
	}
	if (ret == SKEIN_SUCCESS) {
		/*
		 * Save chaining variables for this combination of key,
		 * key_len, hash_bit_len
		 */
		memcpy(ctx->x_save, x, x_len);
	}
	return ret;
}

void skein_reset(struct skein_ctx *ctx)
{
	size_t x_len = 0;
	u64 *x = NULL;

	/*
	 * The following two lines rely of the fact that the real Skein
	 * contexts are a union in out context and thus have tha maximum
	 * memory available.  The beautiy of C :-) .
	 */
	x = ctx->m.s256.x;
	x_len = ctx->skein_size/8;
	/* Restore the chaing variable, reset byte counter */
	memcpy(x, ctx->x_save, x_len);

	/* Setup context to process the message */
	skein_start_new_type(&ctx->m, MSG);
}

int skein_update(struct skein_ctx *ctx, const u8 *msg,
		 size_t msg_byte_cnt)
{
	int ret = SKEIN_FAIL;

	skein_assert_ret(ctx, SKEIN_FAIL);

	switch (ctx->skein_size) {
	case SKEIN_256:
		ret = skein_256_update(&ctx->m.s256, (const u8 *)msg,
				       msg_byte_cnt);
		break;
	case SKEIN_512:
		ret = skein_512_update(&ctx->m.s512, (const u8 *)msg,
				       msg_byte_cnt);
		break;
	case SKEIN_1024:
		ret = skein_1024_update(&ctx->m.s1024, (const u8 *)msg,
					msg_byte_cnt);
		break;
	}
	return ret;

}

int skein_update_bits(struct skein_ctx *ctx, const u8 *msg,
		      size_t msg_bit_cnt)
{
	/*
	 * I've used the bit pad implementation from skein_test.c (see NIST CD)
	 * and modified it to use the convenience functions and added some
	 * pointer arithmetic.
	 */
	size_t length;
	u8 mask;
	u8 *up;

	/*
	 * only the final Update() call is allowed do partial bytes, else
	 * assert an error
	 */
	skein_assert_ret((ctx->m.h.T[1] & SKEIN_T1_FLAG_BIT_PAD) == 0 ||
			 msg_bit_cnt == 0, SKEIN_FAIL);

	/* if number of bits is a multiple of bytes - that's easy */
	if ((msg_bit_cnt & 0x7) == 0)
		return skein_update(ctx, msg, msg_bit_cnt >> 3);

	skein_update(ctx, msg, (msg_bit_cnt >> 3) + 1);

	/*
	 * The next line rely on the fact that the real Skein contexts
	 * are a union in our context. After the addition the pointer points to
	 * Skein's real partial block buffer.
	 * If this layout ever changes we have to adapt this as well.
	 */
	up = (u8 *)ctx->m.s256.x + ctx->skein_size / 8;

	/* set tweak flag for the skein_final call */
	skein_set_bit_pad_flag(ctx->m.h);

	/* now "pad" the final partial byte the way NIST likes */
	/* get the b_cnt value (same location for all block sizes) */
	length = ctx->m.h.b_cnt;
	/* internal sanity check: there IS a partial byte in the buffer! */
	skein_assert(length != 0);
	/* partial byte bit mask */
	mask = (u8) (1u << (7 - (msg_bit_cnt & 7)));
	/* apply bit padding on final byte (in the buffer) */
	up[length-1]  = (u8)((up[length-1] & (0-mask))|mask);

	return SKEIN_SUCCESS;
}

int skein_final(struct skein_ctx *ctx, u8 *hash)
{
	int ret = SKEIN_FAIL;

	skein_assert_ret(ctx, SKEIN_FAIL);

	switch (ctx->skein_size) {
	case SKEIN_256:
		ret = skein_256_final(&ctx->m.s256, (u8 *)hash);
		break;
	case SKEIN_512:
		ret = skein_512_final(&ctx->m.s512, (u8 *)hash);
		break;
	case SKEIN_1024:
		ret = skein_1024_final(&ctx->m.s1024, (u8 *)hash);
		break;
	}
	return ret;
}
