/*
 * 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>
#include <zircon_uboot/boot_args.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_read_lock_state(enum vx_lock_state *lock_state)
{
	int rc;

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

	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;

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

int ta_vx_lock(void)
{
	int rc = zircon_clear_stored_cmdline();
	if (rc) {
		printf("Failed to clear stored boot args\n");
		return rc;
	}

	return ta_vx_write_lock_state(VX_LOCKED);
}

int ta_vx_lock_if_ephemerally_unlocked(void)
{
	int rc;
	uint32_t vars;

	rc = ta_vx_getvar_all(&vars);
	if (rc) {
		return rc;
	}

	if (!(vars & VX_VAR_EPHEMERALLY_UNLOCKED)) {
		return 0;
	}

	printf("Locking up an ephemerally unlocked device\n");
	rc = ta_vx_lock();
	if (!rc) {
		printf("ta_vx_lock() failed\n");
		return rc;
	}

	rc = ta_vx_getvar_all(&vars);
	if (rc) {
		return rc;
	}

	if (vars & VX_VAR_EPHEMERALLY_UNLOCKED) {
		printf("SHOCKED: device is still ephemerally unlocked after "
		       "successful locking\n");
		return -EINVAL;
	}

	return 0;
}

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 };

	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 };

	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;

	/* 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;

	/* 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;

	/* 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;

	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_or_panic(void)
{
	uint32_t vars;

	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. */
	if (ta_vx_getvar_all(&vars) || !(vars & VX_VAR_OUT_OF_BOOTLOADER)) {
		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;

	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;

	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 };

	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)
{
	return ta_call(&vx_uuid, TA_VX_CMD_PROVISION_RPMB, 0, NULL);
}

int ta_vx_reroute_rpmb_till_reboot(void)
{
	return ta_call(&vx_uuid, TA_VX_CMD_REROUTE_RPMB_TILL_REBOOT, 0, NULL);
}

int ta_vx_reroute_rpmb_to_software(void)
{
	return ta_call(&vx_uuid, TA_VX_CMD_REROUTE_RPMB_TO_SOFTWARE, 0, NULL);
}

int ta_vx_reroute_rpmb_to_hardware(void)
{
	return ta_call(&vx_uuid, TA_VX_CMD_REROUTE_RPMB_TO_HARDWARE, 0, NULL);
}

int ta_vx_delete_perm_attr(void)
{
	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;

	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;

	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)
{
	return ta_call(&vx_uuid, TA_VX_CMD_LOCK_PERM_ATTR, 0, NULL);
}

int ta_vx_provision_usb_hash(void)
{
	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;

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

	return rc;
}

int ta_vx_getvar_all(uint32_t *out_vars)
{
	int rc;
	struct tee_param params[1] = { 0 };

	if (!out_vars) {
		return -EINVAL;
	}

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

	*out_vars = params[0].u.value.a;
	return 0;
}

#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;

	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_lock_if_ephemerally_unlocked()
{
	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_or_panic()
{
	/* 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_reroute_rpmb_till_reboot(void)
{
	return ta_vx_fail(__func__);
}

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

int ta_vx_reroute_rpmb_to_hardware(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__);
}

int ta_vx_getvar_all(uint32_t *out_vars)
{
	return ta_vx_fail(__func__);
}

#endif // CONFIG_TA_VX
