/*
 * Copyright (c) 2019-2020 The Fuchsia Authors
 *
 * SPDX-License-Identifier:	BSD-3-Clause
 */

#include <common.h>
#include <tee.h>
#include <tee/ta_helper.h>
#include <tee/ta_vx.h>
#include <tee/ta_vx_helper.h>

#ifdef CONFIG_TA_VX
#define VX_PERM_ATTR_HASH_SIZE 32

static struct tee_optee_ta_uuid vx_uuid = TA_VX_UUID;

static int ta_vx_setup(void)
{
	uint32_t options = 0;
	static bool setup_done = false;
	static int setup_result = 0;

	if (setup_done) {
		return setup_result;
	}

#ifdef CONFIG_TA_VX_AUTO_PROVISION_RPMB
	options |= VX_OPTION_AUTO_PROVISION_RPMB;
#endif

	if (options) {
		struct tee_param params[1] = { 0 };
		params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
		params[0].u.value.a = options;
		setup_result = ta_call(&vx_uuid, TA_VX_CMD_SET_OPTIONS,
				       ARRAY_SIZE(params), params);
	}

	setup_done = true;
	return setup_result;
}

#define SETUP_OR_FAIL()                                                        \
	do {                                                                   \
		int rc = ta_vx_setup();                                        \
		if (rc) {                                                      \
			printf("ta_vx_setup() failed, rc = %d.", rc);          \
			return rc;                                             \
		}                                                              \
	} while (0)

static int ta_vx_read_lock_state(enum vx_lock_state *lock_state)
{
	int rc;

	struct tee_param param = { 0 };
	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;

	SETUP_OR_FAIL();

	rc = ta_call(&vx_uuid, TA_VX_CMD_READ_LOCK_STATE, 1, &param);
	if (!rc) {
		*lock_state = param.u.value.a;
	}

	return rc;
}

static int ta_vx_write_lock_state(enum vx_lock_state lock_state)
{
	struct tee_param param = { 0 };
	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	param.u.value.a = lock_state;

	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_WRITE_LOCK_STATE, 1, &param);
}

int ta_vx_fdr(void) {
	SETUP_OR_FAIL();
	return ta_call(&vx_uuid, TA_VX_CMD_REFRESH_LOCK_STATE_NONCE, 0, NULL);
}

int ta_vx_lock(void)
{
	return ta_vx_write_lock_state(VX_LOCKED);
}

int ta_vx_unlock(void)
{
	return ta_vx_write_lock_state(VX_UNLOCKED);
}

int ta_vx_is_unlocked(bool *unlocked)
{
	enum vx_lock_state lock_state;
	if (ta_vx_read_lock_state(&lock_state)) {
		return -EIO;
	}
	*unlocked = (lock_state == VX_UNLOCKED);
	return 0;
}

int ta_vx_read_rollback_index(uint32_t slot, uint64_t *rollback_index)
{
	int rc;
	struct tee_param params[2] = { 0 };

	SETUP_OR_FAIL();

	params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = slot;

	params[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;

	rc = ta_call(&vx_uuid, TA_VX_CMD_READ_ROLLBACK_INDEX,
		     ARRAY_SIZE(params), params);
	if (!rc) {
		*rollback_index = ((uint64_t)params[1].u.value.a) << 32 |
				  params[1].u.value.b;
	}

	return rc;
}

int ta_vx_write_rollback_index(uint32_t slot, uint64_t rollback_index)
{
	struct tee_param params[2] = { 0 };

	SETUP_OR_FAIL();

	params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = slot;

	params[1].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[1].u.value.a = rollback_index >> 32;
	params[1].u.value.b = rollback_index;

	return ta_call(&vx_uuid, TA_VX_CMD_WRITE_ROLLBACK_INDEX,
		       ARRAY_SIZE(params), params);
}

int ta_vx_read_persistent_value(const char *name, void *buf, size_t buf_len,
				size_t *bytes_read)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[2] = { 0 };

	struct tee_shm *shm_key = NULL;
	struct tee_shm *shm_buf = NULL;

	size_t key_len = strlen(name) + 1;

	SETUP_OR_FAIL();

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	/* Pass in @key via shared memory. */
	rc = tee_shm_alloc(context.tee, key_len, TEE_SHM_ALLOC, &shm_key);
	if (rc)
		goto out;

	memcpy(shm_key->addr, name, key_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_key;
	params[0].u.memref.size = key_len;

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc)
		goto out;

	params[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
	params[1].u.memref.shm = shm_buf;
	params[1].u.memref.size = buf_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_READ_PERSIST_VALUE,
		       ARRAY_SIZE(params), params);
	if (!rc) {
		memcpy(buf, (void *)(params[1].u.memref.shm->addr),
		       params[1].u.memref.size);
		if (bytes_read) {
			*bytes_read = params[1].u.memref.size;
		}
	}

out:
	tee_shm_free(shm_key);
	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_write_persistent_value(const char *name, const void *buf,
				 size_t buf_len)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[2] = { 0 };

	struct tee_shm *shm_key = NULL;
	struct tee_shm *shm_buf = NULL;

	size_t key_len = strlen(name) + 1;

	SETUP_OR_FAIL();

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	/* Pass in @key via shared memory. */
	rc = tee_shm_alloc(context.tee, key_len, TEE_SHM_ALLOC, &shm_key);
	if (rc)
		goto out;

	memcpy(shm_key->addr, name, key_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_key;
	params[0].u.memref.size = key_len;

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc)
		goto out;

	memcpy(shm_buf->addr, buf, buf_len);
	params[1].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[1].u.memref.shm = shm_buf;
	params[1].u.memref.size = buf_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_WRITE_PERSIST_VALUE,
		       ARRAY_SIZE(params), params);

out:
	tee_shm_free(shm_key);
	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_delete_persistent_value(const char *name)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };

	struct tee_shm *shm_key = NULL;
	size_t key_len = strlen(name) + 1;

	SETUP_OR_FAIL();

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	/* Pass in @key via shared memory. */
	rc = tee_shm_alloc(context.tee, key_len, TEE_SHM_ALLOC, &shm_key);
	if (rc)
		goto out;
	memcpy(shm_key->addr, name, key_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_key;
	params[0].u.memref.size = key_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_DELETE_PERSIST_VALUE,
		       ARRAY_SIZE(params), params);

out:
	tee_shm_free(shm_key);
	ta_close(&context);
	return rc;
}

int ta_vx_cprng_draw(void *buf, size_t buf_len)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };
	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	if (!(buf && buf_len))
		return -EINVAL;

	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc)
		goto out;

	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = buf_len;

	rc = ta_invoke(&context, TA_VX_CMD_CPRNG_DRAW, ARRAY_SIZE(params),
		       params);
	if (!rc) {
		memcpy(buf, (void *)(params[0].u.memref.shm->addr),
		       params[0].u.memref.size);
	}

out:
	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

void ta_vx_exit_bootloader(void)
{
	/* Exiting bootloader should panic on failure so call ta_vx_setup()
	   directly rather than using SETUP_OR_FAIL. */
	int rc = ta_vx_setup();
	if (rc) {
		printf("ta_vx_setup() failed, rc = %d.", rc);
		panic("VX setup failed!");
	}

	if (ta_call(&vx_uuid, TA_VX_CMD_EXIT_BOOTLOADER, 0, NULL)) {
		panic("VX finalization failed!");
	}

	/* Make sure we are indeed beyond the bootloader security domain. */
	struct tee_param params[1] = { 0 };
	params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_INPUT;
	params[0].u.value.a = VX_OPTION_FOR_TESTING;
	if (!ta_call(&vx_uuid, TA_VX_CMD_SET_OPTIONS, ARRAY_SIZE(params),
		     params)) {
		panic("VX finalization verification failed.");
	}

	return;
}

int ta_vx_read_perm_attr(void *buf, size_t buf_len, size_t *bytes_read)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };

	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	if (!(buf && buf_len)) {
		return -EINVAL;
	}

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc) {
		return rc;
	}

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc) {
		ta_close(&context);
		return rc;
	}

	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = buf_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_READ_PERM_ATTR, ARRAY_SIZE(params),
		       params);
	if (!rc) {
		memcpy(buf, (void *)(params[0].u.memref.shm->addr),
		       params[0].u.memref.size);
		if (bytes_read) {
			*bytes_read = params[0].u.memref.size;
		}
	}

	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_write_perm_attr(const void *buf, size_t buf_len)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };

	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	if (!(buf && buf_len))
		return -EINVAL;

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc) {
		return rc;
	}

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, buf_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc) {
		ta_close(&context);
		return rc;
	}

	memcpy(shm_buf->addr, buf, buf_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = buf_len;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_WRITE_PERM_ATTR, ARRAY_SIZE(params),
		       params);

	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_get_rpmb_status(uint32_t *out_status, uint32_t *out_write_count)
{
	int rc;
	struct tee_param params[1] = { 0 };

	SETUP_OR_FAIL();

	params[0].attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;
	rc = ta_call(&vx_uuid, TA_VX_CMD_GET_RPMB_STATUS, ARRAY_SIZE(params),
		     params);
	if (rc) {
		return rc;
	}

	if (out_status) {
		*out_status = params[0].u.value.a;
	}
	if (out_write_count) {
		*out_write_count = params[0].u.value.b;
	}

	return 0;
}

int ta_vx_provision_rpmb(void)
{
	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_PROVISION_RPMB, 0, NULL);
}

int ta_vx_delete_perm_attr(void)
{
	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_DELETE_PERM_ATTR, 0, NULL);
}

int ta_vx_read_perm_attr_hash(void *buf, size_t buf_len)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };

	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	if (!buf || (buf_len < VX_PERM_ATTR_HASH_SIZE))
		return -EINVAL;

	/* Connect to TA. */
	rc = ta_open(&vx_uuid, &context);
	if (rc) {
		return rc;
	}

	/* Pass in buf via shared memory. */
	rc = tee_shm_alloc(context.tee, VX_PERM_ATTR_HASH_SIZE, TEE_SHM_ALLOC,
			   &shm_buf);
	if (rc) {
		ta_close(&context);
		return rc;
	}

	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INOUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = VX_PERM_ATTR_HASH_SIZE;

	/* Invoke the TA. */
	rc = ta_invoke(&context, TA_VX_CMD_READ_PERM_ATTR_HASH,
		       ARRAY_SIZE(params), params);
	if (!rc) {
		memcpy(buf, (void *)(params[0].u.memref.shm->addr),
		       params[0].u.memref.size);
	}

	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}

int ta_vx_get_perm_attr_status(uint32_t *status)
{
	int rc;

	struct tee_param param = { 0 };
	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;

	SETUP_OR_FAIL();

	rc = ta_call(&vx_uuid, TA_VX_CMD_GET_PERM_ATTR_STATUS, 1, &param);
	if (!rc) {
		if (status) {
			*status = param.u.value.a;
		}
	}

	return rc;
}

int ta_vx_lock_perm_attr(void)
{
	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_LOCK_PERM_ATTR, 0, NULL);
}

int ta_vx_provision_usb_hash(void)
{
	SETUP_OR_FAIL();

	return ta_call(&vx_uuid, TA_VX_CMD_PROVISION_USBBOOT_PWD_HASH, 0, NULL);
}

int ta_vx_get_usbboot_status(uint32_t *status)
{
	int rc;

	struct tee_param param = { 0 };
	param.attr = TEE_PARAM_ATTR_TYPE_VALUE_OUTPUT;

	SETUP_OR_FAIL();

	rc = ta_call(&vx_uuid, TA_VX_CMD_GET_USBBOOT_STATUS, 1, &param);
	if (!rc) {
		if (status) {
			*status = param.u.value.a;
		}
	}

	return rc;
}

#ifdef CONFIG_TA_VX_TESTS
int ta_vx_run_tests(const char *name)
{
	int rc;
	struct ta_context context = { 0 };
	struct tee_param params[1] = { 0 };
	size_t name_len = strlen(name) + 1;
	struct tee_shm *shm_buf = NULL;

	SETUP_OR_FAIL();

	rc = ta_open(&vx_uuid, &context);
	if (rc)
		return rc;

	rc = tee_shm_alloc(context.tee, name_len, TEE_SHM_ALLOC, &shm_buf);
	if (rc)
		goto out;

	memcpy(shm_buf->addr, name, name_len);
	params[0].attr = TEE_PARAM_ATTR_TYPE_MEMREF_INPUT;
	params[0].u.memref.shm = shm_buf;
	params[0].u.memref.size = name_len;

	rc = ta_invoke(&context, TA_VX_CMD_RUN_TESTS, ARRAY_SIZE(params),
		       params);

out:
	tee_shm_free(shm_buf);

	ta_close(&context);
	return rc;
}
#endif // CONFIG_TA_VX_TESTS

#else // CONFIG_TA_VX

static int ta_vx_fail(const char *func)
{
	printf("%s: failure due to disabled VX TA\n", func);
	return -1;
}

int ta_vx_lock()
{
	return ta_vx_fail(__func__);
}

int ta_vx_unlock()
{
	return ta_vx_fail(__func__);
}

int ta_vx_is_unlocked(bool *unlocked)
{
	return ta_vx_fail(__func__);
}

int ta_vx_read_rollback_index(uint32_t slot, uint64_t *rollback_index)
{
	return ta_vx_fail(__func__);
}

int ta_vx_write_rollback_index(uint32_t slot, uint64_t rollback_index)
{
	return ta_vx_fail(__func__);
}

int ta_vx_read_persistent_value(const char *name, void *buf, size_t buf_len,
				size_t *bytes_read)
{
	return ta_vx_fail(__func__);
}

int ta_vx_write_persistent_value(const char *name, const void *val_buf,
				 size_t val_buf_len)
{
	return ta_vx_fail(__func__);
}

int ta_vx_delete_persistent_value(const char *name)
{
	return ta_vx_fail(__func__);
}

int ta_vx_cprng_draw(void *buf, size_t buf_len)
{
	return ta_vx_fail(__func__);
}

void ta_vx_exit_bootloader()
{
	/* Unlike other VX stubs, this one succeeds by default as a no-op if
	   the VX TA is disabled. */
}

int ta_vx_read_perm_attr(void *buf, size_t buf_len, size_t *bytes_read)
{
	return ta_vx_fail(__func__);
}

int ta_vx_write_perm_attr(const void *val_buf, size_t val_buf_len)
{
	return ta_vx_fail(__func__);
}

int ta_vx_read_perm_attr_hash(void *buf, size_t buf_len)
{
	return ta_vx_fail(__func__);
}

int ta_vx_delete_perm_attr(void)
{
	return ta_vx_fail(__func__);
}

int ta_vx_get_perm_attr_status(uint32_t *status)
{
	return ta_vx_fail(__func__);
}

int ta_vx_lock_perm_attr(void)
{
	return ta_vx_fail(__func__);
}

int ta_vx_get_rpmb_status(uint32_t *out_status, uint32_t *out_write_count)
{
	return ta_vx_fail(__func__);
}

int ta_vx_provision_rpmb(void)
{
	return ta_vx_fail(__func__);
}

int ta_vx_provision_usb_hash(void)
{
	return ta_vx_fail(__func__);
}

int ta_vx_get_usbboot_status(uint32_t *status)
{
	return ta_vx_fail(__func__);
}

#endif // CONFIG_TA_VX
