From patchwork Mon Jul 9 06:15:49 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jens Wiklander X-Patchwork-Id: 141368 Delivered-To: patches@linaro.org Received: by 2002:a2e:9754:0:0:0:0:0 with SMTP id f20-v6csp2280470ljj; Sun, 8 Jul 2018 23:15:59 -0700 (PDT) X-Received: by 2002:a19:e119:: with SMTP id y25-v6mr13907565lfg.3.1531116959180; Sun, 08 Jul 2018 23:15:59 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1531116959; cv=none; d=google.com; s=arc-20160816; b=heZu1HMBUu71PvLoE2Eebzn9Dj1k0qv7OOXs2/Y8/hi4iT7kwFMpRkIVirB2IDSO1E 8AdWcEC98Bj1kCEtWruyQBOZCth2UkIATNcvVu5dEPsi6vUaLx0Vqo4bxcgLNIFyOzQc t8pM6ZdCjvGNMoEKl//yVMGGVJYZRdU3qs8AiRrcncz+Dc0TN2l7xUKB/6XS3gAdE5Y0 QJLHTx7Op430GOkqSlhA7acZSwK9Am3+IiAQ1Ja1J2JOqp3tNCosbCjYa21j1QwtKAyA VbG+iizI3yDGeLh3hT2sjJEsUmK3++aPHCPHzSJEu6Gfdtv1Vg8BSkh1hLaqL6JBtbLN zk/Q== 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=VUswySRldL/9ULe/QmdY25JftCKNFqT6wOZCs5KsqEg=; b=SQ6RMow2m70houKRGKAxPxbzTo+D1MnZKLQTbf7CjeDAh1XqMcQuqBstXaLMq+/lqv e1FW4mTo3YHktxucKAJU6uACMl/o255pJ/xc5IZ1IYFiCd0A+nEStuCAIs9Sh/SpVmug fLN+whZXfH2VdMHFoDX8iHmwInR2shFD8LMQW9vu+tXkAv4SXdWSyRfIvFU6O6Hq2wfs Jt4UTwDOKDVJ7bPAgwlbGB/5+fse0UWQeBVbq+IxjY6iU0OggSo3c3zr1KHtDlK9k5Ik zNahOVHrexKtDA+VRXwzKlLUAUl8Zwxb7zZetrYxT0ax07MExLAd6U8P8blGjP26UFWo c9PA== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=f7476Sm+; spf=pass (google.com: domain of jens.wiklander@linaro.org designates 209.85.220.65 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-sor-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id n7-v6sor3211310lfh.10.2018.07.08.23.15.59 for (Google Transport Security); Sun, 08 Jul 2018 23:15:59 -0700 (PDT) Received-SPF: pass (google.com: domain of jens.wiklander@linaro.org designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=f7476Sm+; spf=pass (google.com: domain of jens.wiklander@linaro.org designates 209.85.220.65 as permitted sender) smtp.mailfrom=jens.wiklander@linaro.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id; bh=VUswySRldL/9ULe/QmdY25JftCKNFqT6wOZCs5KsqEg=; b=f7476Sm+oIkIiNX1tPSyoYHsRcaSUDxbnI1VQ9pFcUOW7wcI4Wu2s5MvbGT4e2fZau YMFmtw76brrDB0TKpK3IAQj6YhV8hKjdycX2JZsocO98Cc4NVMD0j//SlSUVZbqHnoQk HWqiELfJar1BmivUnMeuUUk0qIjst/ZaV+AUo= 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=VUswySRldL/9ULe/QmdY25JftCKNFqT6wOZCs5KsqEg=; b=qakAst94oArc85hmG3AAq+RcjI5kyd+EcVKBnDtI6R75QxKLFT1hAtoK+q2xu5Y+O8 D1Tcz3iLw8YQKVFwTTn/TEozHDE3CcZ5MBcqMn1+054K5LB+iQJbYd6d9pLFR9gMcEcL 3cEYpiexY0HkCnvRkYInvCCCbOjsjhQQQ9D0Cf02RDXfBCDJORA6pcxz+ql/CXXqqRts 9jcrV3jyH9qKg7xVD8vULQbKoqGg6gg1I85um6VYykc2fT5mit2tD/JUrxrNmDWyEjxv Wr73QBKP3y304nyp5jldlfZYVQPQIOvvrytaS7q/XFOoEgBDrICWB6HGLHUan/7ozqfx aR7Q== X-Gm-Message-State: APt69E2zzEb11bKqkibC0X8rlgIzYriu0MtKfFD1/WTRQXjklRqsHCGa /ikzCWoUWhVQTX5QL2V25xQQT5cHzQeNtQ== X-Google-Smtp-Source: AAOMgpdlC56fSqZ9np/0+4vEB54HfEGh5UGqIh7OmUlIK1EZE6ZLT3x6fplV3NHNbIfVsw8rt4L7WQ== X-Received: by 2002:a19:6b03:: with SMTP id d3-v6mr12790273lfa.81.1531116958814; Sun, 08 Jul 2018 23:15:58 -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 x129-v6sm1610521lff.19.2018.07.08.23.15.57 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 08 Jul 2018 23:15:58 -0700 (PDT) From: Jens Wiklander To: linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, tee-dev@lists.linaro.org Cc: Zeng Tao , Victor Chong , Jerome Forissier , Jens Wiklander Subject: [RESEND PATCH] tee: add kernel internal client interface Date: Mon, 9 Jul 2018 08:15:49 +0200 Message-Id: <20180709061549.24382-1-jens.wiklander@linaro.org> X-Mailer: git-send-email 2.17.1 Adds a kernel internal TEE client interface to be used by other drivers. Signed-off-by: Jens Wiklander --- drivers/tee/tee_core.c | 113 +++++++++++++++++++++++++++++++++++++--- include/linux/tee_drv.h | 73 ++++++++++++++++++++++++++ 2 files changed, 179 insertions(+), 7 deletions(-) -- 2.17.1 Reviewed-by: Sumit Garg Tested-by: Sumit Garg Tested-by: Zeng Tao diff --git a/drivers/tee/tee_core.c b/drivers/tee/tee_core.c index dd46b758852a..7b2bb4c50058 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) { @@ -57,16 +55,16 @@ static int tee_open(struct inode *inode, struct file *filp) kref_init(&ctx->refcount); 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); + } void teedev_ctx_get(struct tee_context *ctx) @@ -100,6 +98,18 @@ static void teedev_close_context(struct tee_context *ctx) teedev_ctx_put(ctx); } +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); @@ -928,6 +938,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 a2b3dfcee0b5..6cfe05893a76 100644 --- a/include/linux/tee_drv.h +++ b/include/linux/tee_drv.h @@ -453,6 +453,79 @@ static inline 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); + static inline bool tee_param_is_memref(struct tee_param *param) { switch (param->attr & TEE_IOCTL_PARAM_ATTR_TYPE_MASK) {