/* test_ecc_utils.c - TinyCrypt common functions for ECC tests */

/*
 *  Copyright (C) 2015 by Intel Corporation, 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 Intel Corporation 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 BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS 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 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.
 *
 *  test_ecc_utils.c -- Implementation of some common functions for ECC tests.
 *
 */

#include <zephyr.h>
#include <drivers/rand32.h>

#include <tinycrypt/ecc.h>
#include <tinycrypt/ecc_dh.h>
#include <test_ecc_utils.h>
#include <test_utils.h>
#include <tinycrypt/constants.h>

#include <stdlib.h>
#include <string.h>
#include <errno.h>

int random_start(const char *fn)
{
	(void)fn;

	return 0;
}

int random_end(void)
{
	return 0;
}

int random_bytes(uint32_t *out, size_t len)
{
	size_t i;

	for (i = 0; i < len; i++) {
		out[i] = sys_rand32_get();
	}

	return i == len ? 0 : -EINVAL;
}

int hex_to_num(char hex)
{
	uint8_t dec;

	if ('0' <= hex && hex <= '9') {
		dec = hex - '0';
	} else if ('a' <= hex && hex <= 'f') {
		dec = hex - 'a' + 10;
	} else if ('A' <= hex && hex <= 'F') {
		dec = hex - 'A' + 10;
	} else {
		return -1;
	}

	return dec;
}

/*
 * Convert hex string to byte string
 * Return number of bytes written to buf, or 0 on error
 */
int hex_to_num_str(uint8_t *buf, const size_t buflen, const char *hex,
		   const size_t hexlen)
{
	int dec;

	if (buflen < hexlen / 2 + hexlen % 2) {
		return 0;
	}

	/* if hexlen is uneven, insert leading zero nibble */
	if (hexlen % 2) {
		dec = hex_to_num(hex[0]);
		if (dec == -1) {
			return 0;
		}
		buf[0] = dec;
		buf++;
		hex++;
	}

	/* regular hex conversion */
	for (size_t i = 0; i < hexlen / 2; i++) {
		dec = hex_to_num(hex[2 * i]);
		if (dec == -1) {
			return 0;
		}
		buf[i] = dec << 4;

		dec = hex_to_num(hex[2 * i + 1]);
		if (dec == -1) {
			return 0;
		}
		buf[i] += dec;
	}
	return hexlen / 2 + hexlen % 2;
}

/*
 * Convert hex string to zero-padded nanoECC scalar
 */
int str_to_scalar(uint32_t *scalar, uint32_t num_word32, char *str)
{
	uint32_t num_bytes = 4 * num_word32;
	uint8_t tmp[num_bytes];
	size_t hexlen = strlen(str);
	int padding;
	int rc;

	padding = 2 * num_bytes - strlen(str);
	if (padding < 0) {
		TC_PRINT("Error: 2*num_bytes(%d) < strlen(hex) (%zu)\n",
			 2 * num_bytes, strlen(str));
		return TC_FAIL;
	}

	memset(tmp, 0, padding / 2);

	rc = hex_to_num_str(tmp + padding / 2, num_bytes, str, hexlen);
	if (rc == 0) {
		return TC_FAIL;
	}

	ecc_bytes2native(scalar, tmp);

	return TC_PASS;
}

void vli_print(uint32_t *p_vli, unsigned int p_size)
{
	while (p_size) {
		TC_PRINT("%08X ", (unsigned)p_vli[p_size - 1]);
		--p_size;
	}
}

int check_code(const int num, const char *name, const int expected,
	       const int computed, const int verbose)
{
	if (expected != computed) {
		TC_PRINT("\nVector #%02d check %s - FAILURE:\n", num, name);
		TC_PRINT("\nExpected: %d, computed: %d\n\n", expected,
			 computed);
		return TC_FAIL;
	}

	if (verbose) {
		TC_PRINT("Vector #%02d check %s - success (%d=%d)\n", num, name,
			 expected, computed);
	}

	return TC_PASS;
}

int check_ecc_result(const int num, const char *name, const uint32_t *expected,
		     const uint32_t *computed, const uint32_t num_word32,
		     int verbose)
{
	uint32_t num_bytes = 4 * num_word32;

	if (memcmp(computed, expected, num_bytes)) {
		TC_PRINT("\n  Vector #%02d check %s - FAILURE\n", num, name);
		return TC_FAIL;
	}
	if (verbose) {
		TC_PRINT("  Vector #%02d check %s - success\n", num, name);
	}

	return TC_PASS;
}

/* Test ecc_make_keys, and also as keygen part of other tests */
int keygen_vectors(EccPoint *pub, char **d_vec, char **qx_vec, char **qy_vec,
		   int tests, int verbose)
{
	uint32_t seed[2 * NUM_ECC_DIGITS];
	uint32_t prv[NUM_ECC_DIGITS];

	/* expected outputs (converted input vectors) */
	EccPoint exp_pub;
	uint32_t exp_prv[NUM_ECC_DIGITS];

	int rc;

	for (int i = 0; i < tests; i++) {

		str_to_scalar(exp_prv, NUM_ECC_DIGITS, d_vec[i]);
		str_to_scalar(exp_pub.x, NUM_ECC_DIGITS, qx_vec[i]);
		str_to_scalar(exp_pub.y, NUM_ECC_DIGITS, qy_vec[i]);

		/*
		 * Feed prvkey vector as padded random seed into ecc_make_key.
		 * Internal mod-reduction will be zero-op and generate correct
		 * prv/pub
		 */
		memset(seed, 0, 2 * NUM_ECC_BYTES);
		str_to_scalar(seed, NUM_ECC_DIGITS, d_vec[i]);
		ecc_make_key(pub, prv, seed);

		/* validate correctness of vector conversion and make_key() */
		rc = check_ecc_result(i, "prv  ", exp_prv, prv,
				      NUM_ECC_DIGITS, verbose);
		if (rc != TC_PASS) {
			goto exit_test;
		}
		rc = check_ecc_result(i, "pub.x", exp_pub.x, pub->x,
				      NUM_ECC_DIGITS, verbose);
		if (rc != TC_PASS) {
			goto exit_test;
		}
		rc = check_ecc_result(i, "pub.y", exp_pub.y, pub->y,
				      NUM_ECC_DIGITS, verbose);
		if (rc != TC_PASS) {
			goto exit_test;
		}
	}

	rc = TC_PASS;
exit_test:
	return rc;
}
