// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2019-2021 Linaro Ltd.
 *
 * Author:
 * Sumit Garg <sumit.garg@linaro.org>
 */

#include <linux/err.h>
#include <linux/key-type.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/tee_drv.h>
#include <linux/uuid.h>

#include <keys/trusted_tee.h>

#define DRIVER_NAME "trusted-key-tee"

/*
 * Get random data for symmetric key
 *
 * [out]     memref[0]        Random data
 */
#define TA_CMD_GET_RANDOM	0x0

/*
 * Seal trusted key using hardware unique key
 *
 * [in]      memref[0]        Plain key
 * [out]     memref[1]        Sealed key datablob
 */
#define TA_CMD_SEAL		0x1

/*
 * Unseal trusted key using hardware unique key
 *
 * [in]      memref[0]        Sealed key datablob
 * [out]     memref[1]        Plain key
 */
#define TA_CMD_UNSEAL		0x2

/**
 * struct trusted_key_tee_private - TEE Trusted key private data
 * @dev:		TEE based Trusted key device.
 * @ctx:		TEE context handler.
 * @session_id:		Trusted key TA session identifier.
 * @shm_pool:		Memory pool shared with TEE device.
 */
struct trusted_key_tee_private {
	struct device *dev;
	struct tee_context *ctx;
	u32 session_id;
	struct tee_shm *shm_pool;
};

static struct trusted_key_tee_private pvt_data;

/*
 * Have the TEE seal(encrypt) the symmetric key
 */
static int trusted_tee_seal(struct trusted_key_payload *p, char *datablob)
{
	int ret;
	struct tee_ioctl_invoke_arg inv_arg;
	struct tee_param param[4];
	struct tee_shm *reg_shm_in = NULL, *reg_shm_out = NULL;

	memset(&inv_arg, 0, sizeof(inv_arg));
	memset(&param, 0, sizeof(param));

	reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
						 p->key_len);
	if (IS_ERR(reg_shm_in)) {
		dev_err(pvt_data.dev, "key shm register failed\n");
		return PTR_ERR(reg_shm_in);
	}

	reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob,
						  sizeof(p->blob));
	if (IS_ERR(reg_shm_out)) {
		dev_err(pvt_data.dev, "blob shm register failed\n");
		ret = PTR_ERR(reg_shm_out);
		goto out;
	}

	inv_arg.func = TA_CMD_SEAL;
	inv_arg.session = pvt_data.session_id;
	inv_arg.num_params = 4;

	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
	param[0].u.memref.shm = reg_shm_in;
	param[0].u.memref.size = p->key_len;
	param[0].u.memref.shm_offs = 0;
	param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
	param[1].u.memref.shm = reg_shm_out;
	param[1].u.memref.size = sizeof(p->blob);
	param[1].u.memref.shm_offs = 0;

	ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
	if ((ret < 0) || (inv_arg.ret != 0)) {
		dev_err(pvt_data.dev, "TA_CMD_SEAL invoke err: %x\n",
			inv_arg.ret);
		ret = -EFAULT;
	} else {
		p->blob_len = param[1].u.memref.size;
	}

out:
	if (reg_shm_out)
		tee_shm_free(reg_shm_out);
	if (reg_shm_in)
		tee_shm_free(reg_shm_in);

	return ret;
}

/*
 * Have the TEE unseal(decrypt) the symmetric key
 */
static int trusted_tee_unseal(struct trusted_key_payload *p, char *datablob)
{
	int ret;
	struct tee_ioctl_invoke_arg inv_arg;
	struct tee_param param[4];
	struct tee_shm *reg_shm_in = NULL, *reg_shm_out = NULL;

	memset(&inv_arg, 0, sizeof(inv_arg));
	memset(&param, 0, sizeof(param));

	reg_shm_in = tee_shm_register_kernel_buf(pvt_data.ctx, p->blob,
						 p->blob_len);
	if (IS_ERR(reg_shm_in)) {
		dev_err(pvt_data.dev, "blob shm register failed\n");
		return PTR_ERR(reg_shm_in);
	}

	reg_shm_out = tee_shm_register_kernel_buf(pvt_data.ctx, p->key,
						  sizeof(p->key));
	if (IS_ERR(reg_shm_out)) {
		dev_err(pvt_data.dev, "key shm register failed\n");
		ret = PTR_ERR(reg_shm_out);
		goto out;
	}

	inv_arg.func = TA_CMD_UNSEAL;
	inv_arg.session = pvt_data.session_id;
	inv_arg.num_params = 4;

	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_INPUT;
	param[0].u.memref.shm = reg_shm_in;
	param[0].u.memref.size = p->blob_len;
	param[0].u.memref.shm_offs = 0;
	param[1].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
	param[1].u.memref.shm = reg_shm_out;
	param[1].u.memref.size = sizeof(p->key);
	param[1].u.memref.shm_offs = 0;

	ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
	if ((ret < 0) || (inv_arg.ret != 0)) {
		dev_err(pvt_data.dev, "TA_CMD_UNSEAL invoke err: %x\n",
			inv_arg.ret);
		ret = -EFAULT;
	} else {
		p->key_len = param[1].u.memref.size;
	}

out:
	if (reg_shm_out)
		tee_shm_free(reg_shm_out);
	if (reg_shm_in)
		tee_shm_free(reg_shm_in);

	return ret;
}

/*
 * Have the TEE generate random symmetric key
 */
static int trusted_tee_get_random(unsigned char *key, size_t key_len)
{
	int ret;
	struct tee_ioctl_invoke_arg inv_arg;
	struct tee_param param[4];
	struct tee_shm *reg_shm = NULL;

	memset(&inv_arg, 0, sizeof(inv_arg));
	memset(&param, 0, sizeof(param));

	reg_shm = tee_shm_register_kernel_buf(pvt_data.ctx, key, key_len);
	if (IS_ERR(reg_shm)) {
		dev_err(pvt_data.dev, "key shm register failed\n");
		return PTR_ERR(reg_shm);
	}

	inv_arg.func = TA_CMD_GET_RANDOM;
	inv_arg.session = pvt_data.session_id;
	inv_arg.num_params = 4;

	param[0].attr = TEE_IOCTL_PARAM_ATTR_TYPE_MEMREF_OUTPUT;
	param[0].u.memref.shm = reg_shm;
	param[0].u.memref.size = key_len;
	param[0].u.memref.shm_offs = 0;

	ret = tee_client_invoke_func(pvt_data.ctx, &inv_arg, param);
	if ((ret < 0) || (inv_arg.ret != 0)) {
		dev_err(pvt_data.dev, "TA_CMD_GET_RANDOM invoke err: %x\n",
			inv_arg.ret);
		ret = -EFAULT;
	} else {
		ret = param[0].u.memref.size;
	}

	tee_shm_free(reg_shm);

	return ret;
}

static int optee_ctx_match(struct tee_ioctl_version_data *ver, const void *data)
{
	if (ver->impl_id == TEE_IMPL_ID_OPTEE)
		return 1;
	else
		return 0;
}

static int trusted_key_probe(struct device *dev)
{
	struct tee_client_device *rng_device = to_tee_client_device(dev);
	int ret;
	struct tee_ioctl_open_session_arg sess_arg;

	memset(&sess_arg, 0, sizeof(sess_arg));

	pvt_data.ctx = tee_client_open_context(NULL, optee_ctx_match, NULL,
					       NULL);
	if (IS_ERR(pvt_data.ctx))
		return -ENODEV;

	memcpy(sess_arg.uuid, rng_device->id.uuid.b, TEE_IOCTL_UUID_LEN);
	sess_arg.clnt_login = TEE_IOCTL_LOGIN_REE_KERNEL;
	sess_arg.num_params = 0;

	ret = tee_client_open_session(pvt_data.ctx, &sess_arg, NULL);
	if ((ret < 0) || (sess_arg.ret != 0)) {
		dev_err(dev, "tee_client_open_session failed, err: %x\n",
			sess_arg.ret);
		ret = -EINVAL;
		goto out_ctx;
	}
	pvt_data.session_id = sess_arg.session;

	ret = register_key_type(&key_type_trusted);
	if (ret < 0)
		goto out_sess;

	pvt_data.dev = dev;

	return 0;

out_sess:
	tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
out_ctx:
	tee_client_close_context(pvt_data.ctx);

	return ret;
}

static int trusted_key_remove(struct device *dev)
{
	unregister_key_type(&key_type_trusted);
	tee_client_close_session(pvt_data.ctx, pvt_data.session_id);
	tee_client_close_context(pvt_data.ctx);

	return 0;
}

static const struct tee_client_device_id trusted_key_id_table[] = {
	{UUID_INIT(0xf04a0fe7, 0x1f5d, 0x4b9b,
		   0xab, 0xf7, 0x61, 0x9b, 0x85, 0xb4, 0xce, 0x8c)},
	{}
};
MODULE_DEVICE_TABLE(tee, trusted_key_id_table);

static struct tee_client_driver trusted_key_driver = {
	.id_table	= trusted_key_id_table,
	.driver		= {
		.name		= DRIVER_NAME,
		.bus		= &tee_bus_type,
		.probe		= trusted_key_probe,
		.remove		= trusted_key_remove,
	},
};

static int trusted_tee_init(void)
{
	return driver_register(&trusted_key_driver.driver);
}

static void trusted_tee_exit(void)
{
	driver_unregister(&trusted_key_driver.driver);
}

struct trusted_key_ops trusted_key_tee_ops = {
	.migratable = 0, /* non-migratable */
	.init = trusted_tee_init,
	.seal = trusted_tee_seal,
	.unseal = trusted_tee_unseal,
	.get_random = trusted_tee_get_random,
	.exit = trusted_tee_exit,
};
