// SPDX-License-Identifier: BSD-2-Clause
/*
 * Copyright (c) 2017, Linaro Limited
 */

#include <assert.h>
#include <string.h>
#include <tee/fs_htree.h>
#include <tee/tee_fs_rpc.h>
#include <trace.h>
#include <types_ext.h>
#include <util.h>

#include "misc.h"

/*
 * The smallest blocks size that can hold two struct
 * tee_fs_htree_node_image or two struct tee_fs_htree_image.
 */
#define TEST_BLOCK_SIZE		144

struct test_aux {
	uint8_t *data;
	size_t data_len;
	size_t data_alloced;
	uint8_t *block;
};

static TEE_Result test_get_offs_size(enum tee_fs_htree_type type, size_t idx,
				     uint8_t vers, size_t *offs, size_t *size)
{
	const size_t node_size = sizeof(struct tee_fs_htree_node_image);
	const size_t block_nodes = TEST_BLOCK_SIZE / (node_size * 2);
	size_t pbn;
	size_t bidx;

	COMPILE_TIME_ASSERT(TEST_BLOCK_SIZE >
			    sizeof(struct tee_fs_htree_node_image) * 2);
	COMPILE_TIME_ASSERT(TEST_BLOCK_SIZE >
			    sizeof(struct tee_fs_htree_image) * 2);

	assert(vers == 0 || vers == 1);

	/*
	 * File layout
	 *
	 * phys block 0:
	 * tee_fs_htree_image vers 0 @ offs = 0
	 * tee_fs_htree_image vers 1 @ offs = sizeof(tee_fs_htree_image)
	 *
	 * phys block 1:
	 * tee_fs_htree_node_image 0  vers 0 @ offs = 0
	 * tee_fs_htree_node_image 0  vers 1 @ offs = node_size
	 *
	 * phys block 2:
	 * data block 0 vers 0
	 *
	 * phys block 3:
	 * tee_fs_htree_node_image 1  vers 0 @ offs = 0
	 * tee_fs_htree_node_image 1  vers 1 @ offs = node_size
	 *
	 * phys block 4:
	 * data block 0 vers 1
	 *
	 * ...
	 */

	switch (type) {
	case TEE_FS_HTREE_TYPE_HEAD:
		*offs = sizeof(struct tee_fs_htree_image) * vers;
		*size = sizeof(struct tee_fs_htree_image);
		return TEE_SUCCESS;
	case TEE_FS_HTREE_TYPE_NODE:
		pbn = 1 + ((idx / block_nodes) * block_nodes * 2);
		*offs = pbn * TEST_BLOCK_SIZE +
			2 * node_size * (idx % block_nodes) +
			node_size * vers;
		*size = node_size;
		return TEE_SUCCESS;
	case TEE_FS_HTREE_TYPE_BLOCK:
		bidx = 2 * idx + vers;
		pbn = 2 + bidx + bidx / (block_nodes * 2 - 1);
		*offs = pbn * TEST_BLOCK_SIZE;
		*size = TEST_BLOCK_SIZE;
		return TEE_SUCCESS;
	default:
		return TEE_ERROR_GENERIC;
	}
}

static TEE_Result test_read_init(void *aux, struct tee_fs_rpc_operation *op,
				 enum tee_fs_htree_type type, size_t idx,
				 uint8_t vers, void **data)
{
	TEE_Result res;
	struct test_aux *a = aux;
	size_t offs;
	size_t sz;

	res = test_get_offs_size(type, idx, vers, &offs, &sz);
	if (res == TEE_SUCCESS) {
		memset(op, 0, sizeof(*op));
		op->params[0].u.value.a = (vaddr_t)aux;
		op->params[0].u.value.b = offs;
		op->params[0].u.value.c = sz;
		*data = a->block;
	}

	return res;
}

static void *uint_to_ptr(uintptr_t p)
{
	return (void *)p;
}

static TEE_Result test_read_final(struct tee_fs_rpc_operation *op,
				  size_t *bytes)
{
	struct test_aux *a = uint_to_ptr(op->params[0].u.value.a);
	size_t offs = op->params[0].u.value.b;
	size_t sz = op->params[0].u.value.c;

	if (offs + sz <= a->data_len)
		*bytes = sz;
	else if (offs <= a->data_len)
		*bytes = a->data_len - offs;
	else
		*bytes = 0;

	memcpy(a->block, a->data + offs, *bytes);
	return TEE_SUCCESS;
}

static TEE_Result test_write_init(void *aux, struct tee_fs_rpc_operation *op,
				  enum tee_fs_htree_type type, size_t idx,
				  uint8_t vers, void **data)
{
	return test_read_init(aux, op, type, idx, vers, data);
}

static TEE_Result test_write_final(struct tee_fs_rpc_operation *op)
{
	struct test_aux *a = uint_to_ptr(op->params[0].u.value.a);
	size_t offs = op->params[0].u.value.b;
	size_t sz = op->params[0].u.value.c;
	size_t end = offs + sz;

	if (end > a->data_alloced) {
		EMSG("out of bounds");
		return TEE_ERROR_GENERIC;
	}

	memcpy(a->data + offs, a->block, sz);
	if (end > a->data_len)
		a->data_len = end;
	return TEE_SUCCESS;

}

static const struct tee_fs_htree_storage test_htree_ops = {
	.block_size = TEST_BLOCK_SIZE,
	.rpc_read_init = test_read_init,
	.rpc_read_final = test_read_final,
	.rpc_write_init = test_write_init,
	.rpc_write_final = test_write_final,
};

#define CHECK_RES(res, cleanup)						\
		do {							\
			TEE_Result _res = (res);			\
									\
			if (_res != TEE_SUCCESS) {			\
				EMSG("error: res = %#" PRIx32, _res);	\
				{ cleanup; }				\
			}						\
		} while (0)

static uint32_t val_from_bn_n_salt(size_t bn, size_t n, uint8_t salt)
{
	assert(bn < UINT16_MAX);
	assert(n < UINT8_MAX);
	return SHIFT_U32(n, 16) | SHIFT_U32(bn, 8) | salt;
}

static TEE_Result write_block(struct tee_fs_htree **ht, size_t bn, uint8_t salt)
{
	uint32_t b[TEST_BLOCK_SIZE / sizeof(uint32_t)];
	size_t n;

	for (n = 0; n < ARRAY_SIZE(b); n++)
		b[n] = val_from_bn_n_salt(bn, n, salt);

	return tee_fs_htree_write_block(ht, bn, b);
}

static TEE_Result read_block(struct tee_fs_htree **ht, size_t bn, uint8_t salt)
{
	TEE_Result res;
	uint32_t b[TEST_BLOCK_SIZE / sizeof(uint32_t)];
	size_t n;

	res = tee_fs_htree_read_block(ht, bn, b);
	if (res != TEE_SUCCESS)
		return res;

	for (n = 0; n < ARRAY_SIZE(b); n++) {
		if (b[n] != val_from_bn_n_salt(bn, n, salt)) {
			DMSG("Unpected b[%zu] %#" PRIx32
			     "(expected %#" PRIx32 ")",
			     n, b[n], val_from_bn_n_salt(bn, n, salt));
			return TEE_ERROR_TIME_NOT_SET;
		}
	}

	return TEE_SUCCESS;
}

static TEE_Result do_range(TEE_Result (*fn)(struct tee_fs_htree **ht,
					    size_t bn, uint8_t salt),
			   struct tee_fs_htree **ht, size_t begin,
			   size_t num_blocks, size_t salt)
{
	TEE_Result res = TEE_SUCCESS;
	size_t n;

	for (n = 0; n < num_blocks; n++) {
		res = fn(ht, n + begin, salt);
		CHECK_RES(res, goto out);
	}

out:
	return res;
}

static TEE_Result do_range_backwards(TEE_Result (*fn)(struct tee_fs_htree **ht,
						      size_t bn, uint8_t salt),
				     struct tee_fs_htree **ht, size_t begin,
				     size_t num_blocks, size_t salt)
{
	TEE_Result res = TEE_SUCCESS;
	size_t n;

	for (n = 0; n < num_blocks; n++) {
		res = fn(ht, num_blocks - 1 - n + begin, salt);
		CHECK_RES(res, goto out);
	}

out:
	return res;
}

static TEE_Result htree_test_rewrite(struct test_aux *aux, size_t num_blocks,
				     size_t w_unsync_begin, size_t w_unsync_num)
{
	TEE_Result res;
	struct tee_fs_htree *ht = NULL;
	size_t salt = 23;
	uint8_t hash[TEE_FS_HTREE_HASH_SIZE];
	const TEE_UUID *uuid;
	struct tee_ta_session *sess;

	assert((w_unsync_begin + w_unsync_num) <= num_blocks);

	res = tee_ta_get_current_session(&sess);
	if (res)
		return res;
	uuid = &sess->ctx->uuid;

	aux->data_len = 0;
	memset(aux->data, 0xce, aux->data_alloced);

	res = tee_fs_htree_open(true, hash, uuid, &test_htree_ops, aux, &ht);
	CHECK_RES(res, goto out);

	/*
	 * Intialize all blocks and verify that they read back as
	 * expected.
	 */
	res = do_range(write_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

	res = do_range(read_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

	/*
	 * Write all blocks again, but starting from the end using a new
	 * salt, then verify that that read back as expected.
	 */
	salt++;
	res = do_range_backwards(write_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

	res = do_range(read_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

	/*
	 * Use a new salt to write all blocks once more and verify that
	 * they read back as expected.
	 */
	salt++;
	res = do_range(write_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

	res = do_range(read_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

	/*
	 * Sync the changes of the nodes to memory, verify that all
	 * blocks are read back as expected.
	 */
	res = tee_fs_htree_sync_to_storage(&ht, hash);
	CHECK_RES(res, goto out);

	res = do_range(read_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

	/*
	 * Close and reopen the hash-tree
	 */
	tee_fs_htree_close(&ht);
	res = tee_fs_htree_open(false, hash, uuid, &test_htree_ops, aux, &ht);
	CHECK_RES(res, goto out);

	/*
	 * Verify that all blocks are read as expected.
	 */
	res = do_range(read_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

	/*
	 * Rewrite a few blocks and verify that all blocks are read as
	 * expected.
	 */
	res = do_range_backwards(write_block, &ht, w_unsync_begin, w_unsync_num,
				 salt + 1);
	CHECK_RES(res, goto out);

	res = do_range(read_block, &ht, 0, w_unsync_begin, salt);
	CHECK_RES(res, goto out);
	res = do_range(read_block, &ht, w_unsync_begin, w_unsync_num, salt + 1);
	CHECK_RES(res, goto out);
	res = do_range(read_block, &ht, w_unsync_begin + w_unsync_num,
			num_blocks - (w_unsync_begin + w_unsync_num), salt);
	CHECK_RES(res, goto out);

	/*
	 * Rewrite the blocks from above again with another salt and
	 * verify that they are read back as expected.
	 */
	res = do_range(write_block, &ht, w_unsync_begin, w_unsync_num,
		       salt + 2);
	CHECK_RES(res, goto out);

	res = do_range(read_block, &ht, 0, w_unsync_begin, salt);
	CHECK_RES(res, goto out);
	res = do_range(read_block, &ht, w_unsync_begin, w_unsync_num, salt + 2);
	CHECK_RES(res, goto out);
	res = do_range(read_block, &ht, w_unsync_begin + w_unsync_num,
			num_blocks - (w_unsync_begin + w_unsync_num), salt);
	CHECK_RES(res, goto out);

	/*
	 * Skip tee_fs_htree_sync_to_storage() and call
	 * tee_fs_htree_close() directly to undo the changes since last
	 * call to tee_fs_htree_sync_to_storage().  Reopen the hash-tree
	 * and verify that recent changes indeed was discarded.
	 */
	tee_fs_htree_close(&ht);
	res = tee_fs_htree_open(false, hash, uuid, &test_htree_ops, aux, &ht);
	CHECK_RES(res, goto out);

	res = do_range(read_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

	/*
	 * Close, reopen and verify that all blocks are read as expected
	 * again but this time based on the counter value in struct
	 * tee_fs_htree_image.
	 */
	tee_fs_htree_close(&ht);
	res = tee_fs_htree_open(false, NULL, uuid, &test_htree_ops, aux, &ht);
	CHECK_RES(res, goto out);

	res = do_range(read_block, &ht, 0, num_blocks, salt);
	CHECK_RES(res, goto out);

out:
	tee_fs_htree_close(&ht);
	/*
	 * read_block() returns TEE_ERROR_TIME_NOT_SET in case unexpected
	 * data is read.
	 */
	if (res == TEE_ERROR_TIME_NOT_SET)
		res = TEE_ERROR_SECURITY;
	return res;
}

static void aux_free(struct test_aux *aux)
{
	if (aux) {
		free(aux->data);
		free(aux->block);
		free(aux);
	}
}

static struct test_aux *aux_alloc(size_t num_blocks)
{
	struct test_aux *aux;
	size_t o;
	size_t sz;

	if (test_get_offs_size(TEE_FS_HTREE_TYPE_BLOCK, num_blocks, 1, &o, &sz))
		return NULL;

	aux = calloc(1, sizeof(*aux));
	if (!aux)
		return NULL;

	aux->data_alloced = o + sz;
	aux->data = malloc(aux->data_alloced);
	if (!aux->data)
		goto err;

	aux->block = malloc(TEST_BLOCK_SIZE);
	if (!aux->block)
		goto err;

	return aux;
err:
	aux_free(aux);
	return NULL;

}

static TEE_Result test_write_read(size_t num_blocks)
{
	struct test_aux *aux = aux_alloc(num_blocks);
	TEE_Result res;
	size_t n;
	size_t m;
	size_t o;

	if (!aux)
		return TEE_ERROR_OUT_OF_MEMORY;

	/*
	 * n is the number of block we're going to initialize/use.
	 * m is the offset from where we'll rewrite blocks and expect
	 * the changes to be visible until tee_fs_htree_close() is called
	 * without a call to tee_fs_htree_sync_to_storage() before.
	 * o is the number of blocks we're rewriting starting at m.
	 */
	for (n = 0; n < num_blocks; n += 3) {
		for (m = 0; m < n; m += 3) {
			for (o = 0; o < (n - m); o++) {
				res = htree_test_rewrite(aux, n, m, o);
				CHECK_RES(res, goto out);
				o += 2;
			}
		}
	}

out:
	aux_free(aux);
	return res;
}

static TEE_Result test_corrupt_type(const TEE_UUID *uuid, uint8_t *hash,
				    size_t num_blocks, struct test_aux *aux,
				    enum tee_fs_htree_type type, size_t idx)
{
	TEE_Result res;
	struct test_aux aux2 = *aux;
	struct tee_fs_htree *ht = NULL;
	size_t offs;
	size_t size;
	size_t size0;
	size_t n;

	res = test_get_offs_size(type, idx, 0, &offs, &size0);
	CHECK_RES(res, return res);

	aux2.data = malloc(aux->data_alloced);
	if (!aux2.data)
		return TEE_ERROR_OUT_OF_MEMORY;

	n = 0;
	while (true) {
		memcpy(aux2.data, aux->data, aux->data_len);

		res = test_get_offs_size(type, idx, 0, &offs, &size);
		CHECK_RES(res, goto out);
		aux2.data[offs + n]++;
		res = test_get_offs_size(type, idx, 1, &offs, &size);
		CHECK_RES(res, goto out);
		aux2.data[offs + n]++;

		/*
		 * Errors in head or node is detected by
		 * tee_fs_htree_open() errors in block is detected when
		 * actually read by do_range(read_block)
		 */
		res = tee_fs_htree_open(false, hash, uuid, &test_htree_ops,
					&aux2, &ht);
		if (!res) {
			res = do_range(read_block, &ht, 0, num_blocks, 1);
			/*
			 * do_range(read_block,) is supposed to detect the
			 * error. If TEE_ERROR_TIME_NOT_SET is returned
			 * read_block() was acutally able to get some data,
			 * but the data was incorrect.
			 *
			 * If res == TEE_SUCCESS or
			 *    res == TEE_ERROR_TIME_NOT_SET
			 * there's some problem with the htree
			 * implementation.
			 */
			if (res == TEE_ERROR_TIME_NOT_SET) {
				EMSG("error: data silently corrupted");
				res = TEE_ERROR_SECURITY;
				goto out;
			}
			if (!res)
				break;
			tee_fs_htree_close(&ht);
		}

		/* We've tested the last byte, let's get out of here */
		if (n == size0 - 1)
			break;

		/* Increase n exponentionally after 1 to skip some testing */
		if (n)
			n += n;
		else
			n = 1;

		/* Make sure we test the last byte too */
		if (n >= size0)
			n = size0 - 1;
	}

	if (res) {
		res = TEE_SUCCESS;
	} else {
		EMSG("error: data corruption undetected");
		res = TEE_ERROR_SECURITY;
	}
out:
	free(aux2.data);
	tee_fs_htree_close(&ht);
	return res;
}



static TEE_Result test_corrupt(size_t num_blocks)
{
	TEE_Result res;
	struct tee_fs_htree *ht = NULL;
	struct tee_ta_session *sess;
	uint8_t hash[TEE_FS_HTREE_HASH_SIZE];
	const TEE_UUID *uuid;
	struct test_aux *aux;
	size_t n;

	res = tee_ta_get_current_session(&sess);
	if (res)
		return res;
	uuid = &sess->ctx->uuid;

	aux = aux_alloc(num_blocks);
	if (!aux) {
		res = TEE_ERROR_OUT_OF_MEMORY;
		goto out;
	}

	aux->data_len = 0;
	memset(aux->data, 0xce, aux->data_alloced);

	/* Write the object and close it */
	res = tee_fs_htree_open(true, hash, uuid, &test_htree_ops, aux, &ht);
	CHECK_RES(res, goto out);
	res = do_range(write_block, &ht, 0, num_blocks, 1);
	CHECK_RES(res, goto out);
	res = tee_fs_htree_sync_to_storage(&ht, hash);
	CHECK_RES(res, goto out);
	tee_fs_htree_close(&ht);

	/* Verify that the object can be read correctly */
	res = tee_fs_htree_open(false, hash, uuid, &test_htree_ops, aux, &ht);
	CHECK_RES(res, goto out);
	res = do_range(read_block, &ht, 0, num_blocks, 1);
	CHECK_RES(res, goto out);
	tee_fs_htree_close(&ht);

	res = test_corrupt_type(uuid, hash, num_blocks, aux,
				TEE_FS_HTREE_TYPE_HEAD, 0);
	CHECK_RES(res, goto out);
	for (n = 0; n < num_blocks; n++) {
		res = test_corrupt_type(uuid, hash, num_blocks, aux,
					TEE_FS_HTREE_TYPE_NODE, n);
		CHECK_RES(res, goto out);
	}
	for (n = 0; n < num_blocks; n++) {
		res = test_corrupt_type(uuid, hash, num_blocks, aux,
					TEE_FS_HTREE_TYPE_BLOCK, n);
		CHECK_RES(res, goto out);
	}

out:
	tee_fs_htree_close(&ht);
	aux_free(aux);
	return res;
}

TEE_Result core_fs_htree_tests(uint32_t nParamTypes,
			       TEE_Param pParams[TEE_NUM_PARAMS] __unused)
{
	TEE_Result res;

	if (nParamTypes)
		return TEE_ERROR_BAD_PARAMETERS;

	res = test_write_read(10);
	if (res)
		return res;

	return test_corrupt(5);
}
