From patchwork Mon Jul 17 14:44:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 107968 Delivered-To: patches@linaro.org Received: by 10.140.101.44 with SMTP id t41csp4607510qge; Mon, 17 Jul 2017 07:44:39 -0700 (PDT) X-Received: by 10.25.76.3 with SMTP id z3mr6039874lfa.27.1500302679342; Mon, 17 Jul 2017 07:44:39 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1500302679; cv=none; d=google.com; s=arc-20160816; b=H1QrU8mTqTyVaZqxp+C2INPd/PV0y9XkZWnoRU7klaBWMygYQxUijjmfOb2hnZ2aSt JKH9solE4Yx/VHm4HhblokyvNXaJB1ptorBVL32L40rADE4FgcPz2T5tf4r8bxikYAQf VDm9J47fwigtGVwAQpiajAALZQzEkuMfDxhk0icj3vqvt7ikzs2MFHAc+pcdHFRYS9sG fztYTiCQyZlYTBkdQQmYoHYK1uY2RPlCWZXKw0iwwZr0NWolhSDc6/gB3Zewj+Ub/++q tYk49AeDAqs2oXdUnhpsiDlQjzd8N1l9hyXzesU/7nxD7IMvjoQtsCilhlcfvi2F1Ar4 Z+iQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=message-id:date:subject:cc:to:from:dkim-signature :arc-authentication-results; bh=3ecR2M7k4JAmF+Btj+eB3MElXwjeWbV4qSSkCo3S6eM=; b=qPpOIPmd9LV6rOxtzydigCc3SWNyeyVIttfupKdf9aE5RI/JLa01O32gGhCiR5crQe DgjHJHdonZlQJ0XuwsYi57pPr8SJ4N2M2i0PyGB6vCbbz1ZW4qJNS4+3JJQF9YMIACmj 9oL3oaeQoPPA0+jRUBierK+KmB0n/4QTgy3ibkMpFKmddh6KOj6rPrFD70khwc2bR3I5 qWCa4L9b+hf+hKqeGdBY2Wbb3z3mQKzTdFlq+bWXyMumiboAAJzW1Q3fGVHKW7OugfAc E/CYCIM60mmoKfRDSq/8ulKLMeARje2acTD2+plXSjA6BrYzKoBZFc2ED4M2FcC/fdGu 5/+A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.b=PyD9HDpJ; spf=pass (google.com: domain of jens.wiklander@linaro.org designates 2a00:1450:4010:c07::22d as permitted sender) smtp.mailfrom=jens.wiklander@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from mail-lf0-x22d.google.com (mail-lf0-x22d.google.com. [2a00:1450:4010:c07::22d]) by mx.google.com with ESMTPS id w27si7607546ljd.347.2017.07.17.07.44.39 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Jul 2017 07:44:39 -0700 (PDT) Received-SPF: pass (google.com: domain of jens.wiklander@linaro.org designates 2a00:1450:4010:c07::22d as permitted sender) client-ip=2a00:1450:4010:c07::22d; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.b=PyD9HDpJ; spf=pass (google.com: domain of jens.wiklander@linaro.org designates 2a00:1450:4010:c07::22d as permitted sender) smtp.mailfrom=jens.wiklander@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: by mail-lf0-x22d.google.com with SMTP id t72so87057772lff.1 for ; Mon, 17 Jul 2017 07:44:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=3ecR2M7k4JAmF+Btj+eB3MElXwjeWbV4qSSkCo3S6eM=; b=PyD9HDpJBQM42E7+usk6bK62mJM2qUrKuUkf6/OQdJLi1nG5VE3uEmQiKbJKTfv+BS LymCjllrvRb8whprZz55XZ2O0Ky2hbEHFBHKQrAv0pUx9+GxYHE8eOlvwkbldLmGCiBq XwdBu+6scnk1+ugvXn4gjSTSfRgaek+iOCEvI= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=3ecR2M7k4JAmF+Btj+eB3MElXwjeWbV4qSSkCo3S6eM=; b=Al+0Kx9/6iFJ7zPatCO6Ug4wv6iFCY9gaF9Q2C5uWNdKQNXACCW/uMJuiG0YQR6APf 1pPsw0T7P6SvqjNmQZuBCN15BqPoebY3T54N1Sc6IGssxMzMG/iF2XphojOk4AOQ5VUG 1sc02Tn4XOhjCxH7QF5rk2aMhXh5ytphTnnk/Q8biiHxF5YW0r/csq3MkD5nelv5/VPQ 23l0/NC5aXEOAhC8w+6sXq4OQo8CxIHrsxDGVeEvULso6ykdfir/Z82S9jfJtPEf5LPs w22yoNW8dPkB1yU9SliKDPVfOI5JoiwEmocqoaRqv9LWOh4xcvVCODzNH0PPaB8KOCKw xwlQ== X-Gm-Message-State: AIVw113ViR+dufOG/4pQIqBhO+JAtYpIb1wi9H16K8e1yodCpWnJSV4J eIYmnICCFzWntcavPqstA6p/ X-Received: by 10.46.7.80 with SMTP id i16mr4849575ljd.1.1500302678911; Mon, 17 Jul 2017 07:44:38 -0700 (PDT) Return-Path: Received: from jax.urgonet (h-84-45.A175.priv.bahnhof.se. [79.136.84.45]) by smtp.gmail.com with ESMTPSA id e8sm3907697ljb.58.2017.07.17.07.44.37 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 17 Jul 2017 07:44:38 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, tee-dev@lists.linaro.org Cc: acarb95@cs.ubc.ca, Jens Wiklander Subject: [PATCH] tee: add kernel internal client interface Date: Mon, 17 Jul 2017 16:44:15 +0200 Message-Id: <1500302655-4909-1-git-send-email-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.7.4 Adds a kernel internal TEE client interface to be used by other drivers. Signed-off-by: Jens Wiklander --- drivers/tee/tee_core.c | 124 +++++++++++++++++++++++++++++++++++++++++++----- include/linux/tee_drv.h | 73 ++++++++++++++++++++++++++++ 2 files changed, 186 insertions(+), 11 deletions(-) -- 2.7.4 diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index 58a5009eacc3..bcc39e263bdd 100644 --- a/drivers/tee/tee_core.c +++ b/drivers/tee/tee_core.c @@ -38,15 +38,13 @@ static DEFINE_SPINLOCK(driver_lock); static struct class *tee_class; static dev_t tee_devt; -static int tee_open(struct inode *inode, struct file *filp) +static struct tee_context *teedev_open(struct tee_device *teedev) { int rc; - struct tee_device *teedev; struct tee_context *ctx; - teedev = container_of(inode->i_cdev, struct tee_device, cdev); if (!tee_device_get(teedev)) - return -EINVAL; + return ERR_PTR(-EINVAL); ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); if (!ctx) { @@ -56,22 +54,20 @@ static int tee_open(struct inode *inode, struct file *filp) ctx->teedev = teedev; INIT_LIST_HEAD(&ctx->list_shm); - filp->private_data = ctx; rc = teedev->desc->ops->open(ctx); if (rc) goto err; - return 0; + return ctx; err: kfree(ctx); tee_device_put(teedev); - return rc; + return ERR_PTR(rc); + } -static int tee_release(struct inode *inode, struct file *filp) +static void teedev_close_context(struct tee_context *ctx) { - struct tee_context *ctx = filp->private_data; - struct tee_device *teedev = ctx->teedev; struct tee_shm *shm; ctx->teedev->desc->ops->release(ctx); @@ -79,8 +75,25 @@ static int tee_release(struct inode *inode, struct file *filp) list_for_each_entry(shm, &ctx->list_shm, link) shm->ctx = NULL; mutex_unlock(&ctx->teedev->mutex); + tee_device_put(ctx->teedev); kfree(ctx); - tee_device_put(teedev); +} + +static int tee_open(struct inode *inode, struct file *filp) +{ + struct tee_context *ctx; + + ctx = teedev_open(container_of(inode->i_cdev, struct tee_device, cdev)); + if (IS_ERR(ctx)) + return PTR_ERR(ctx); + + filp->private_data = ctx; + return 0; +} + +static int tee_release(struct inode *inode, struct file *filp) +{ + teedev_close_context(filp->private_data); return 0; } @@ -862,6 +875,95 @@ void *tee_get_drvdata(struct tee_device *teedev) } EXPORT_SYMBOL_GPL(tee_get_drvdata); +struct match_dev_data { + struct tee_ioctl_version_data *vers; + const void *data; + int (*match)(struct tee_ioctl_version_data *, const void *); +}; + +static int match_dev(struct device *dev, const void *data) +{ + const struct match_dev_data *match_data = data; + struct tee_device *teedev = container_of(dev, struct tee_device, dev); + + teedev->desc->ops->get_version(teedev, match_data->vers); + return match_data->match(match_data->vers, match_data->data); +} + +struct tee_context * +tee_client_open_context(struct tee_context *start, + int (*match)(struct tee_ioctl_version_data *, + const void *), + const void *data, struct tee_ioctl_version_data *vers) +{ + struct device *dev = NULL; + struct device *put_dev = NULL; + struct tee_context *ctx = NULL; + struct tee_ioctl_version_data v; + struct match_dev_data match_data = { vers ? vers : &v, data, match }; + + if (start) + dev = &start->teedev->dev; + + do { + dev = class_find_device(tee_class, dev, &match_data, match_dev); + if (!dev) { + ctx = ERR_PTR(-ENOENT); + break; + } + + put_device(put_dev); + put_dev = dev; + + ctx = teedev_open(container_of(dev, struct tee_device, dev)); + } while (IS_ERR(ctx) && PTR_ERR(ctx) != -ENOMEM); + + put_device(put_dev); + return ctx; +} +EXPORT_SYMBOL_GPL(tee_client_open_context); + +void tee_client_close_context(struct tee_context *ctx) +{ + teedev_close_context(ctx); +} +EXPORT_SYMBOL_GPL(tee_client_close_context); + +void tee_client_get_version(struct tee_context *ctx, + struct tee_ioctl_version_data *vers) +{ + ctx->teedev->desc->ops->get_version(ctx->teedev, vers); +} +EXPORT_SYMBOL_GPL(tee_client_get_version); + +int tee_client_open_session(struct tee_context *ctx, + struct tee_ioctl_open_session_arg *arg, + struct tee_param *param) +{ + if (!ctx->teedev->desc->ops->open_session) + return -EINVAL; + return ctx->teedev->desc->ops->open_session(ctx, arg, param); +} +EXPORT_SYMBOL_GPL(tee_client_open_session); + +int tee_client_close_session(struct tee_context *ctx, u32 session) +{ + if (!ctx->teedev->desc->ops->close_session) + return -EINVAL; + return ctx->teedev->desc->ops->close_session(ctx, session); +} +EXPORT_SYMBOL_GPL(tee_client_close_session); + +int tee_client_invoke_func(struct tee_context *ctx, + struct tee_ioctl_invoke_arg *arg, + struct tee_param *param) +{ + if (!ctx->teedev->desc->ops->invoke_func) + return -EINVAL; + return ctx->teedev->desc->ops->invoke_func(ctx, arg, param); +} +EXPORT_SYMBOL_GPL(tee_client_invoke_func); + static int __init tee_init(void) { int rc; diff --git a/include/linux/tee_drv.h b/include/linux/tee_drv.h index 0f175b8f6456..39440c7c7558 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -274,4 +274,77 @@ int tee_shm_get_id(struct tee_shm *shm); */ struct tee_shm *tee_shm_get_from_id(struct tee_context *ctx, int id); +/** + * tee_client_open_context() - Open a TEE context + * @start: if not NULL, continue search after this context + * @match: function to check TEE device + * @data: data for match function + * @vers: if not NULL, version data of TEE device of the context returned + * + * This function does an operation similar to open("/dev/teeX") in user space. + * A returned context must be released with tee_client_close_context(). + * + * Returns a TEE context of the first TEE device matched by the match() + * callback or an ERR_PTR. + */ +struct tee_context * +tee_client_open_context(struct tee_context *start, + int (*match)(struct tee_ioctl_version_data *, + const void *), + const void *data, struct tee_ioctl_version_data *vers); + +/** + * tee_client_close_context() - Close a TEE context + * @ctx: TEE context to close + * + * Note that all sessions previously opened with this context will be + * closed when this function is called. + */ +void tee_client_close_context(struct tee_context *ctx); + +/** + * tee_client_get_version() - Query version of TEE + * @ctx: TEE context to TEE to query + * @vers: Pointer to version data + */ +void tee_client_get_version(struct tee_context *ctx, + struct tee_ioctl_version_data *vers); + +/** + * tee_client_open_session() - Open a session to a Trusted Application + * @ctx: TEE context + * @arg: Open session arguments, see description of + * struct tee_ioctl_open_session_arg + * @param: Parameters passed to the Trusted Application + * + * Returns < 0 on error else see @arg->ret for result. If @arg->ret + * is TEEC_SUCCESS the session identifier is available in @arg->session. + */ +int tee_client_open_session(struct tee_context *ctx, + struct tee_ioctl_open_session_arg *arg, + struct tee_param *param); + +/** + * tee_client_close_session() - Close a session to a Trusted Application + * @ctx: TEE Context + * @session: Session id + * + * Return < 0 on error else 0, regardless the session will not be + * valid after this function has returned. + */ +int tee_client_close_session(struct tee_context *ctx, u32 session); + +/** + * tee_client_invoke_func() - Invoke a function in a Trusted Application + * @ctx: TEE Context + * @arg: Invoke arguments, see description of + * struct tee_ioctl_invoke_arg + * @param: Parameters passed to the Trusted Application + * + * Returns < 0 on error else see @arg->ret for result. + */ +int tee_client_invoke_func(struct tee_context *ctx, + struct tee_ioctl_invoke_arg *arg, + struct tee_param *param); + #endif /*__TEE_DRV_H*/