Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1582883 > unrolled thread
| Started by | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
|---|---|
| First post | 2017-02-16 20:30 +0100 |
| Last post | 2017-02-24 18:10 +0100 |
| Articles | 13 on this page of 33 — 6 participants |
Back to article view | Back to linux.kernel
[PATCH v2 0/7] in-kernel resource manager Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-16 20:30 +0100
[PATCH v2 1/7] tpm: move length validation to tpm_transmit() Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-16 20:30 +0100
[PATCH v2 7/7] tpm2: add session handle context saving and restoring to the space code Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-16 20:30 +0100
Re: [PATCH v2 7/7] tpm2: add session handle context saving and restoring to the space code Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-23 10:10 +0100
[PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-16 20:30 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-23 10:10 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> James Bottomley <James.Bottomley@HansenPartnership.com> - 2017-02-24 14:10 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-24 18:40 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jason Gunthorpe <jgunthorpe@obsidianresearch.com> - 2017-02-24 19:20 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> James Bottomley <James.Bottomley@HansenPartnership.com> - 2017-02-24 21:30 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jason Gunthorpe <jgunthorpe@obsidianresearch.com> - 2017-02-24 22:00 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> James Bottomley <James.Bottomley@HansenPartnership.com> - 2017-02-25 00:10 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jason Gunthorpe <jgunthorpe@obsidianresearch.com> - 2017-02-25 00:30 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> James Bottomley <James.Bottomley@HansenPartnership.com> - 2017-02-25 00:50 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jason Gunthorpe <jgunthorpe@obsidianresearch.com> - 2017-02-25 01:30 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> James Bottomley <James.Bottomley@HansenPartnership.com> - 2017-02-25 18:10 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jason Gunthorpe <jgunthorpe@obsidianresearch.com> - 2017-02-27 18:40 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-26 12:50 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> "Dr. Greg Wettstein" <greg@enjellic.com> - 2017-02-26 19:40 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Ken Goldman <kgold@linux.vnet.ibm.com> - 2017-02-28 20:00 +0100
Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Jason Gunthorpe <jgunthorpe@obsidianresearch.com> - 2017-02-27 18:40 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Nayna <nayna@linux.vnet.ibm.com> - 2017-02-24 08:10 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> James Bottomley <James.Bottomley@HansenPartnership.com> - 2017-02-24 14:00 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> Nayna <nayna@linux.vnet.ibm.com> - 2017-02-27 12:50 +0100
Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> James Bottomley <James.Bottomley@HansenPartnership.com> - 2017-02-27 16:10 +0100
[PATCH v2 4/7] tpm: infrastructure for TPM spaces Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-16 20:30 +0100
Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces Nayna <nayna@linux.vnet.ibm.com> - 2017-02-21 19:30 +0100
Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces James Bottomley <James.Bottomley@HansenPartnership.com> - 2017-02-22 18:40 +0100
Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces Ken Goldman <kgold@linux.vnet.ibm.com> - 2017-02-22 22:00 +0100
Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-22 22:20 +0100
Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces Ken Goldman <kgold@linux.vnet.ibm.com> - 2017-02-22 22:30 +0100
Re: [PATCH v2 4/7] tpm: infrastructure for TPM spaces James Bottomley <James.Bottomley@HansenPartnership.com> - 2017-02-24 14:00 +0100
Re: [PATCH v2 4/7] tpm: infrastructure for TPM spaces Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> - 2017-02-24 18:10 +0100
Page 2 of 2 — ← Prev page 1 [2]
| From | Jason Gunthorpe <jgunthorpe@obsidianresearch.com> |
|---|---|
| Date | 2017-02-27 18:40 +0100 |
| Subject | Re: [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> |
| Message-ID | <tfxrb-n1-9@gated-at.bofh.it> |
| In reply to | #1588315 |
On Sun, Feb 26, 2017 at 01:44:40PM +0200, Jarkko Sakkinen wrote: > There's now tabrm-v3 branch. I had to tweak error handling in your > device adding patch because of b4e9d7561a70. I hope I didn't break > anything. Just looked, the flow seemed like it works to me. Just confusing that tpm_add_char_device isn't undone by tpm_del_char_device Jason
[toc] | [prev] | [next] | [standalone]
| From | Nayna <nayna@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-02-24 08:10 +0100 |
| Subject | Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> |
| Message-ID | <teiaR-58j-5@gated-at.bofh.it> |
| In reply to | #1582887 |
On 02/17/2017 12:55 AM, Jarkko Sakkinen wrote:
> From: James Bottomley <James.Bottomley@HansenPartnership.com>
>
> Currently the tpm spaces are not exposed to userspace. Make this
> exposure via a separate device, which can now be opened multiple times
> because each read/write transaction goes separately via the space.
>
> Concurrency is protected by the chip->tpm_mutex for each read/write
> transaction separately. The TPM is cleared of all transient objects
> by the time the mutex is dropped, so there should be no interference
> between the kernel and userspace.
To understand, I have two questions:
1. How would a userspace application using TPM know whether to use
/dev/tpm0 or /dev/tpms0 ?
2. How would a userspace RM know to build on top of /dev/tpm0 or
/dev/tpms0. And if it is built on top of /dev/tpms0, can there be issues
with one RM on top of other RM.
Thanks & Regards,
- Nayna
>
> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
> ---
> drivers/char/tpm/Makefile | 3 +-
> drivers/char/tpm/tpm-chip.c | 73 ++++++++++++++++++++++++++++++++++++++--
> drivers/char/tpm/tpm-interface.c | 13 +++++--
> drivers/char/tpm/tpm.h | 4 +++
> drivers/char/tpm/tpms-dev.c | 65 +++++++++++++++++++++++++++++++++++
> 5 files changed, 152 insertions(+), 6 deletions(-)
> create mode 100644 drivers/char/tpm/tpms-dev.c
>
> diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
> index 10e5827..bbe6531 100644
> --- a/drivers/char/tpm/Makefile
> +++ b/drivers/char/tpm/Makefile
> @@ -3,7 +3,8 @@
> #
> obj-$(CONFIG_TCG_TPM) += tpm.o
> tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
> - tpm-dev-common.o tpm1_eventlog.o tpm2_eventlog.o tpm2-space.o
> + tpm-dev-common.o tpms-dev.o tpm1_eventlog.o tpm2_eventlog.o \
> + tpm2-space.o
> tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
> tpm-$(CONFIG_OF) += tpm_of.o
> obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index 993b9ae..c71c353 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -33,6 +33,7 @@ DEFINE_IDR(dev_nums_idr);
> static DEFINE_MUTEX(idr_lock);
>
> struct class *tpm_class;
> +struct class *tpms_class;
> dev_t tpm_devt;
>
> /**
> @@ -132,6 +133,14 @@ static void tpm_dev_release(struct device *dev)
> kfree(chip);
> }
>
> +static void tpm_devs_release(struct device *dev)
> +{
> + struct tpm_chip *chip = container_of(dev, struct tpm_chip, devs);
> +
> + /* release the master device reference */
> + put_device(&chip->dev);
> +}
> +
> /**
> * tpm_chip_alloc() - allocate a new struct tpm_chip instance
> * @pdev: device to which the chip is associated
> @@ -168,27 +177,47 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
> chip->dev_num = rc;
>
> device_initialize(&chip->dev);
> + device_initialize(&chip->devs);
>
> chip->dev.class = tpm_class;
> chip->dev.release = tpm_dev_release;
> chip->dev.parent = pdev;
> chip->dev.groups = chip->groups;
>
> + chip->devs.parent = pdev;
> + chip->devs.class = tpms_class;
> + chip->devs.release = tpm_devs_release;
> + /* get extra reference on main device to hold on
> + * behalf of devs. This holds the chip structure
> + * while cdevs is in use. The corresponding put
> + * is in the tpm_devs_release
> + */
> + get_device(&chip->dev);
> +
> if (chip->dev_num == 0)
> chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
> else
> chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip->dev_num);
>
> + chip->devs.devt =
> + MKDEV(MAJOR(tpm_devt), chip->dev_num + TPM_NUM_DEVICES);
> +
> rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
> if (rc)
> goto out;
> + rc = dev_set_name(&chip->devs, "tpms%d", chip->dev_num);
> + if (rc)
> + goto out;
>
> if (!pdev)
> chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
>
> cdev_init(&chip->cdev, &tpm_fops);
> + cdev_init(&chip->cdevs, &tpms_fops);
> chip->cdev.owner = THIS_MODULE;
> + chip->cdevs.owner = THIS_MODULE;
> chip->cdev.kobj.parent = &chip->dev.kobj;
> + chip->cdevs.kobj.parent = &chip->devs.kobj;
>
> chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
> if (!chip->work_space.context_buf) {
> @@ -199,6 +228,7 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
> return chip;
>
> out:
> + put_device(&chip->devs);
> put_device(&chip->dev);
> return ERR_PTR(rc);
> }
> @@ -244,7 +274,7 @@ static int tpm_add_char_device(struct tpm_chip *chip)
> dev_name(&chip->dev), MAJOR(chip->dev.devt),
> MINOR(chip->dev.devt), rc);
>
> - return rc;
> + goto err_1;
> }
>
> rc = device_add(&chip->dev);
> @@ -254,16 +284,44 @@ static int tpm_add_char_device(struct tpm_chip *chip)
> dev_name(&chip->dev), MAJOR(chip->dev.devt),
> MINOR(chip->dev.devt), rc);
>
> - cdev_del(&chip->cdev);
> - return rc;
> + goto err_2;
> + }
> +
> + if (chip->flags & TPM_CHIP_FLAG_TPM2)
> + rc = cdev_add(&chip->cdevs, chip->devs.devt, 1);
> + if (rc) {
> + dev_err(&chip->dev,
> + "unable to cdev_add() %s, major %d, minor %d, err=%d\n",
> + dev_name(&chip->devs), MAJOR(chip->devs.devt),
> + MINOR(chip->devs.devt), rc);
> +
> + goto err_3;
> }
>
> + if (chip->flags & TPM_CHIP_FLAG_TPM2)
> + rc = device_add(&chip->devs);
> + if (rc) {
> + dev_err(&chip->dev,
> + "unable to device_register() %s, major %d, minor %d, err=%d\n",
> + dev_name(&chip->devs), MAJOR(chip->devs.devt),
> + MINOR(chip->devs.devt), rc);
> +
> + goto err_4;
> + }
> /* Make the chip available. */
> mutex_lock(&idr_lock);
> idr_replace(&dev_nums_idr, chip, chip->dev_num);
> mutex_unlock(&idr_lock);
>
> return rc;
> + err_4:
> + cdev_del(&chip->cdevs);
> + err_3:
> + device_del(&chip->dev);
> + err_2:
> + cdev_del(&chip->cdev);
> + err_1:
> + return rc;
> }
>
> static void tpm_del_char_device(struct tpm_chip *chip)
> @@ -271,6 +329,11 @@ static void tpm_del_char_device(struct tpm_chip *chip)
> cdev_del(&chip->cdev);
> device_del(&chip->dev);
>
> + if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> + cdev_del(&chip->cdevs);
> + device_del(&chip->devs);
> + }
> +
> /* Make the chip unavailable. */
> mutex_lock(&idr_lock);
> idr_replace(&dev_nums_idr, NULL, chip->dev_num);
> @@ -282,6 +345,10 @@ static void tpm_del_char_device(struct tpm_chip *chip)
> tpm2_shutdown(chip, TPM2_SU_CLEAR);
> chip->ops = NULL;
> up_write(&chip->ops_sem);
> + /* will release the devs reference to the chip->dev unless
> + * something has cdevs open
> + */
> + put_device(&chip->devs);
> }
>
> static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index db5ffe9..deb2021 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -1257,9 +1257,17 @@ static int __init tpm_init(void)
> return PTR_ERR(tpm_class);
> }
>
> - rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES, "tpm");
> + tpms_class = class_create(THIS_MODULE, "tpms");
> + if (IS_ERR(tpms_class)) {
> + pr_err("couldn't create tpms class\n");
> + class_destroy(tpm_class);
> + return PTR_ERR(tpms_class);
> + }
> +
> + rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES, "tpm");
> if (rc < 0) {
> pr_err("tpm: failed to allocate char dev region\n");
> + class_destroy(tpms_class);
> class_destroy(tpm_class);
> return rc;
> }
> @@ -1271,7 +1279,8 @@ static void __exit tpm_exit(void)
> {
> idr_destroy(&dev_nums_idr);
> class_destroy(tpm_class);
> - unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
> + class_destroy(tpms_class);
> + unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES);
> }
>
> subsys_initcall(tpm_init);
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 97e48a4..822ca67 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -182,7 +182,9 @@ struct tpm_chip_seqops {
>
> struct tpm_chip {
> struct device dev;
> + struct device devs;
> struct cdev cdev;
> + struct cdev cdevs;
>
> /* A driver callback under ops cannot be run unless ops_sem is held
> * (sometimes implicitly, eg for the sysfs code). ops becomes null
> @@ -510,8 +512,10 @@ static inline void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value)
> }
>
> extern struct class *tpm_class;
> +extern struct class *tpms_class;
> extern dev_t tpm_devt;
> extern const struct file_operations tpm_fops;
> +extern const struct file_operations tpms_fops;
> extern struct idr dev_nums_idr;
>
> enum tpm_transmit_flags {
> diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms-dev.c
> new file mode 100644
> index 0000000..5720885
> --- /dev/null
> +++ b/drivers/char/tpm/tpms-dev.c
> @@ -0,0 +1,65 @@
> +/*
> + * Copyright (C) 2017 James.Bottomley@HansenPartnership.com
> + *
> + * GPLv2
> + */
> +#include <linux/slab.h>
> +#include "tpm-dev.h"
> +
> +struct tpms_priv {
> + struct file_priv priv;
> + struct tpm_space space;
> +};
> +
> +static int tpms_open(struct inode *inode, struct file *file)
> +{
> + struct tpm_chip *chip;
> + struct tpms_priv *priv;
> + int rc;
> +
> + chip = container_of(inode->i_cdev, struct tpm_chip, cdevs);
> + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> + if (priv == NULL)
> + return -ENOMEM;
> +
> + rc = tpm2_init_space(&priv->space);
> + if (rc) {
> + kfree(priv);
> + return -ENOMEM;
> + }
> +
> + tpm_common_open(file, chip, &priv->priv);
> +
> + return 0;
> +}
> +
> +static int tpms_release(struct inode *inode, struct file *file)
> +{
> + struct file_priv *fpriv = file->private_data;
> + struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
> +
> + tpm_common_release(file, fpriv);
> + tpm2_del_space(&priv->space);
> + kfree(priv);
> +
> + return 0;
> +}
> +
> +ssize_t tpms_write(struct file *file, const char __user *buf,
> + size_t size, loff_t *off)
> +{
> + struct file_priv *fpriv = file->private_data;
> + struct tpms_priv *priv = container_of(fpriv, struct tpms_priv, priv);
> +
> + return tpm_common_write(file, buf, size, off, &priv->space);
> +}
> +
> +const struct file_operations tpms_fops = {
> + .owner = THIS_MODULE,
> + .llseek = no_llseek,
> + .open = tpms_open,
> + .read = tpm_common_read,
> + .write = tpms_write,
> + .release = tpms_release,
> +};
> +
>
[toc] | [prev] | [next] | [standalone]
| From | James Bottomley <James.Bottomley@HansenPartnership.com> |
|---|---|
| Date | 2017-02-24 14:00 +0100 |
| Subject | Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> |
| Message-ID | <tenDB-eO-41@gated-at.bofh.it> |
| In reply to | #1587320 |
On Fri, 2017-02-24 at 12:29 +0530, Nayna wrote:
>
> On 02/17/2017 12:55 AM, Jarkko Sakkinen wrote:
> > From: James Bottomley <James.Bottomley@HansenPartnership.com>
> >
> > Currently the tpm spaces are not exposed to userspace. Make this
> > exposure via a separate device, which can now be opened multiple
> > times because each read/write transaction goes separately via the
> > space.
> >
> > Concurrency is protected by the chip->tpm_mutex for each read/write
> > transaction separately. The TPM is cleared of all transient
> > objects by the time the mutex is dropped, so there should be no
> > interference between the kernel and userspace.
>
> To understand, I have two questions:
>
> 1. How would a userspace application using TPM know whether to use
> /dev/tpm0 or /dev/tpms0 ?
Likely they can't use /dev/tpm0 becuase it will be root only, but the
major indicator will be whether /dev/tpms0 exists or not.
> 2. How would a userspace RM know to build on top of /dev/tpm0 or
> /dev/tpms0. And if it is built on top of /dev/tpms0, can there be
> issues with one RM on top of other RM.
There's a known problem with RMs in that they're not fully stackable,
so I suspect the answer is that if tpms0 exists you won't use an RM,
but this is currently an area of active research. The other potential
problem is that if you build a RM on tpm0 in userspace, it will fight
with the kernel when the kernel uses sessions.
James
> Thanks & Regards,
> - Nayna
>
>
> >
> > Signed-off-by: James Bottomley <
> > James.Bottomley@HansenPartnership.com>
> > ---
> > drivers/char/tpm/Makefile | 3 +-
> > drivers/char/tpm/tpm-chip.c | 73
> > ++++++++++++++++++++++++++++++++++++++--
> > drivers/char/tpm/tpm-interface.c | 13 +++++--
> > drivers/char/tpm/tpm.h | 4 +++
> > drivers/char/tpm/tpms-dev.c | 65
> > +++++++++++++++++++++++++++++++++++
> > 5 files changed, 152 insertions(+), 6 deletions(-)
> > create mode 100644 drivers/char/tpm/tpms-dev.c
> >
> > diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
> > index 10e5827..bbe6531 100644
> > --- a/drivers/char/tpm/Makefile
> > +++ b/drivers/char/tpm/Makefile
> > @@ -3,7 +3,8 @@
> > #
> > obj-$(CONFIG_TCG_TPM) += tpm.o
> > tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2
> > -cmd.o \
> > - tpm-dev-common.o tpm1_eventlog.o tpm2_eventlog.o tpm2
> > -space.o
> > + tpm-dev-common.o tpms-dev.o tpm1_eventlog.o
> > tpm2_eventlog.o \
> > + tpm2-space.o
> > tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
> > tpm-$(CONFIG_OF) += tpm_of.o
> > obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
> > diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm
> > -chip.c
> > index 993b9ae..c71c353 100644
> > --- a/drivers/char/tpm/tpm-chip.c
> > +++ b/drivers/char/tpm/tpm-chip.c
> > @@ -33,6 +33,7 @@ DEFINE_IDR(dev_nums_idr);
> > static DEFINE_MUTEX(idr_lock);
> >
> > struct class *tpm_class;
> > +struct class *tpms_class;
> > dev_t tpm_devt;
> >
> > /**
> > @@ -132,6 +133,14 @@ static void tpm_dev_release(struct device
> > *dev)
> > kfree(chip);
> > }
> >
> > +static void tpm_devs_release(struct device *dev)
> > +{
> > + struct tpm_chip *chip = container_of(dev, struct tpm_chip,
> > devs);
> > +
> > + /* release the master device reference */
> > + put_device(&chip->dev);
> > +}
> > +
> > /**
> > * tpm_chip_alloc() - allocate a new struct tpm_chip instance
> > * @pdev: device to which the chip is associated
> > @@ -168,27 +177,47 @@ struct tpm_chip *tpm_chip_alloc(struct device
> > *pdev,
> > chip->dev_num = rc;
> >
> > device_initialize(&chip->dev);
> > + device_initialize(&chip->devs);
> >
> > chip->dev.class = tpm_class;
> > chip->dev.release = tpm_dev_release;
> > chip->dev.parent = pdev;
> > chip->dev.groups = chip->groups;
> >
> > + chip->devs.parent = pdev;
> > + chip->devs.class = tpms_class;
> > + chip->devs.release = tpm_devs_release;
> > + /* get extra reference on main device to hold on
> > + * behalf of devs. This holds the chip structure
> > + * while cdevs is in use. The corresponding put
> > + * is in the tpm_devs_release
> > + */
> > + get_device(&chip->dev);
> > +
> > if (chip->dev_num == 0)
> > chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
> > else
> > chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip
> > ->dev_num);
> >
> > + chip->devs.devt =
> > + MKDEV(MAJOR(tpm_devt), chip->dev_num +
> > TPM_NUM_DEVICES);
> > +
> > rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
> > if (rc)
> > goto out;
> > + rc = dev_set_name(&chip->devs, "tpms%d", chip->dev_num);
> > + if (rc)
> > + goto out;
> >
> > if (!pdev)
> > chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
> >
> > cdev_init(&chip->cdev, &tpm_fops);
> > + cdev_init(&chip->cdevs, &tpms_fops);
> > chip->cdev.owner = THIS_MODULE;
> > + chip->cdevs.owner = THIS_MODULE;
> > chip->cdev.kobj.parent = &chip->dev.kobj;
> > + chip->cdevs.kobj.parent = &chip->devs.kobj;
> >
> > chip->work_space.context_buf = kzalloc(PAGE_SIZE,
> > GFP_KERNEL);
> > if (!chip->work_space.context_buf) {
> > @@ -199,6 +228,7 @@ struct tpm_chip *tpm_chip_alloc(struct device
> > *pdev,
> > return chip;
> >
> > out:
> > + put_device(&chip->devs);
> > put_device(&chip->dev);
> > return ERR_PTR(rc);
> > }
> > @@ -244,7 +274,7 @@ static int tpm_add_char_device(struct tpm_chip
> > *chip)
> > dev_name(&chip->dev), MAJOR(chip
> > ->dev.devt),
> > MINOR(chip->dev.devt), rc);
> >
> > - return rc;
> > + goto err_1;
> > }
> >
> > rc = device_add(&chip->dev);
> > @@ -254,16 +284,44 @@ static int tpm_add_char_device(struct
> > tpm_chip *chip)
> > dev_name(&chip->dev), MAJOR(chip
> > ->dev.devt),
> > MINOR(chip->dev.devt), rc);
> >
> > - cdev_del(&chip->cdev);
> > - return rc;
> > + goto err_2;
> > + }
> > +
> > + if (chip->flags & TPM_CHIP_FLAG_TPM2)
> > + rc = cdev_add(&chip->cdevs, chip->devs.devt, 1);
> > + if (rc) {
> > + dev_err(&chip->dev,
> > + "unable to cdev_add() %s, major %d, minor
> > %d, err=%d\n",
> > + dev_name(&chip->devs), MAJOR(chip
> > ->devs.devt),
> > + MINOR(chip->devs.devt), rc);
> > +
> > + goto err_3;
> > }
> >
> > + if (chip->flags & TPM_CHIP_FLAG_TPM2)
> > + rc = device_add(&chip->devs);
> > + if (rc) {
> > + dev_err(&chip->dev,
> > + "unable to device_register() %s, major %d,
> > minor %d, err=%d\n",
> > + dev_name(&chip->devs), MAJOR(chip
> > ->devs.devt),
> > + MINOR(chip->devs.devt), rc);
> > +
> > + goto err_4;
> > + }
> > /* Make the chip available. */
> > mutex_lock(&idr_lock);
> > idr_replace(&dev_nums_idr, chip, chip->dev_num);
> > mutex_unlock(&idr_lock);
> >
> > return rc;
> > + err_4:
> > + cdev_del(&chip->cdevs);
> > + err_3:
> > + device_del(&chip->dev);
> > + err_2:
> > + cdev_del(&chip->cdev);
> > + err_1:
> > + return rc;
> > }
> >
> > static void tpm_del_char_device(struct tpm_chip *chip)
> > @@ -271,6 +329,11 @@ static void tpm_del_char_device(struct
> > tpm_chip *chip)
> > cdev_del(&chip->cdev);
> > device_del(&chip->dev);
> >
> > + if (chip->flags & TPM_CHIP_FLAG_TPM2) {
> > + cdev_del(&chip->cdevs);
> > + device_del(&chip->devs);
> > + }
> > +
> > /* Make the chip unavailable. */
> > mutex_lock(&idr_lock);
> > idr_replace(&dev_nums_idr, NULL, chip->dev_num);
> > @@ -282,6 +345,10 @@ static void tpm_del_char_device(struct
> > tpm_chip *chip)
> > tpm2_shutdown(chip, TPM2_SU_CLEAR);
> > chip->ops = NULL;
> > up_write(&chip->ops_sem);
> > + /* will release the devs reference to the chip->dev unless
> > + * something has cdevs open
> > + */
> > + put_device(&chip->devs);
> > }
> >
> > static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
> > diff --git a/drivers/char/tpm/tpm-interface.c
> > b/drivers/char/tpm/tpm-interface.c
> > index db5ffe9..deb2021 100644
> > --- a/drivers/char/tpm/tpm-interface.c
> > +++ b/drivers/char/tpm/tpm-interface.c
> > @@ -1257,9 +1257,17 @@ static int __init tpm_init(void)
> > return PTR_ERR(tpm_class);
> > }
> >
> > - rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES,
> > "tpm");
> > + tpms_class = class_create(THIS_MODULE, "tpms");
> > + if (IS_ERR(tpms_class)) {
> > + pr_err("couldn't create tpms class\n");
> > + class_destroy(tpm_class);
> > + return PTR_ERR(tpms_class);
> > + }
> > +
> > + rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES,
> > "tpm");
> > if (rc < 0) {
> > pr_err("tpm: failed to allocate char dev
> > region\n");
> > + class_destroy(tpms_class);
> > class_destroy(tpm_class);
> > return rc;
> > }
> > @@ -1271,7 +1279,8 @@ static void __exit tpm_exit(void)
> > {
> > idr_destroy(&dev_nums_idr);
> > class_destroy(tpm_class);
> > - unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
> > + class_destroy(tpms_class);
> > + unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES);
> > }
> >
> > subsys_initcall(tpm_init);
> > diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> > index 97e48a4..822ca67 100644
> > --- a/drivers/char/tpm/tpm.h
> > +++ b/drivers/char/tpm/tpm.h
> > @@ -182,7 +182,9 @@ struct tpm_chip_seqops {
> >
> > struct tpm_chip {
> > struct device dev;
> > + struct device devs;
> > struct cdev cdev;
> > + struct cdev cdevs;
> >
> > /* A driver callback under ops cannot be run unless
> > ops_sem is held
> > * (sometimes implicitly, eg for the sysfs code). ops
> > becomes null
> > @@ -510,8 +512,10 @@ static inline void tpm_buf_append_u32(struct
> > tpm_buf *buf, const u32 value)
> > }
> >
> > extern struct class *tpm_class;
> > +extern struct class *tpms_class;
> > extern dev_t tpm_devt;
> > extern const struct file_operations tpm_fops;
> > +extern const struct file_operations tpms_fops;
> > extern struct idr dev_nums_idr;
> >
> > enum tpm_transmit_flags {
> > diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms
> > -dev.c
> > new file mode 100644
> > index 0000000..5720885
> > --- /dev/null
> > +++ b/drivers/char/tpm/tpms-dev.c
> > @@ -0,0 +1,65 @@
> > +/*
> > + * Copyright (C) 2017 James.Bottomley@HansenPartnership.com
> > + *
> > + * GPLv2
> > + */
> > +#include <linux/slab.h>
> > +#include "tpm-dev.h"
> > +
> > +struct tpms_priv {
> > + struct file_priv priv;
> > + struct tpm_space space;
> > +};
> > +
> > +static int tpms_open(struct inode *inode, struct file *file)
> > +{
> > + struct tpm_chip *chip;
> > + struct tpms_priv *priv;
> > + int rc;
> > +
> > + chip = container_of(inode->i_cdev, struct tpm_chip,
> > cdevs);
> > + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
> > + if (priv == NULL)
> > + return -ENOMEM;
> > +
> > + rc = tpm2_init_space(&priv->space);
> > + if (rc) {
> > + kfree(priv);
> > + return -ENOMEM;
> > + }
> > +
> > + tpm_common_open(file, chip, &priv->priv);
> > +
> > + return 0;
> > +}
> > +
> > +static int tpms_release(struct inode *inode, struct file *file)
> > +{
> > + struct file_priv *fpriv = file->private_data;
> > + struct tpms_priv *priv = container_of(fpriv, struct
> > tpms_priv, priv);
> > +
> > + tpm_common_release(file, fpriv);
> > + tpm2_del_space(&priv->space);
> > + kfree(priv);
> > +
> > + return 0;
> > +}
> > +
> > +ssize_t tpms_write(struct file *file, const char __user *buf,
> > + size_t size, loff_t *off)
> > +{
> > + struct file_priv *fpriv = file->private_data;
> > + struct tpms_priv *priv = container_of(fpriv, struct
> > tpms_priv, priv);
> > +
> > + return tpm_common_write(file, buf, size, off, &priv
> > ->space);
> > +}
> > +
> > +const struct file_operations tpms_fops = {
> > + .owner = THIS_MODULE,
> > + .llseek = no_llseek,
> > + .open = tpms_open,
> > + .read = tpm_common_read,
> > + .write = tpms_write,
> > + .release = tpms_release,
> > +};
> > +
> >
>
[toc] | [prev] | [next] | [standalone]
| From | Nayna <nayna@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-02-27 12:50 +0100 |
| Subject | Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> |
| Message-ID | <tfrYu-4Xq-5@gated-at.bofh.it> |
| In reply to | #1587587 |
On 02/24/2017 06:23 PM, James Bottomley wrote:
> On Fri, 2017-02-24 at 12:29 +0530, Nayna wrote:
>>
>> On 02/17/2017 12:55 AM, Jarkko Sakkinen wrote:
>>> From: James Bottomley <James.Bottomley@HansenPartnership.com>
>>>
>>> Currently the tpm spaces are not exposed to userspace. Make this
>>> exposure via a separate device, which can now be opened multiple
>>> times because each read/write transaction goes separately via the
>>> space.
>>>
>>> Concurrency is protected by the chip->tpm_mutex for each read/write
>>> transaction separately. The TPM is cleared of all transient
>>> objects by the time the mutex is dropped, so there should be no
>>> interference between the kernel and userspace.
>>
>> To understand, I have two questions:
>>
>> 1. How would a userspace application using TPM know whether to use
>> /dev/tpm0 or /dev/tpms0 ?
>
> Likely they can't use /dev/tpm0 becuase it will be root only, but the
> major indicator will be whether /dev/tpms0 exists or not.
Thanks James !!
Currently, I see even /dev/tpms0 is also only root accessible. I did see
the discussion to make it 0666, and I understand adding command
filtering is part of enabling /dev/tpms0 as all-accessible.
Sorry, I didn't understand when you said, "major indicator will be
whether /dev/tpms0" exists or not ? I mean in what case it might not
exist..
>
>> 2. How would a userspace RM know to build on top of /dev/tpm0 or
>> /dev/tpms0. And if it is built on top of /dev/tpms0, can there be
>> issues with one RM on top of other RM.
>
> There's a known problem with RMs in that they're not fully stackable,
> so I suspect the answer is that if tpms0 exists you won't use an RM,
> but this is currently an area of active research. The other potential
> problem is that if you build a RM on tpm0 in userspace, it will fight
> with the kernel when the kernel uses sessions.
Does it imply that there should be restriction to disallow any RM
specific commands from userspace on /dev/tpm0 ?
Thanks & Regards,
- Nayna
>
> James
>
>> Thanks & Regards,
>> - Nayna
>>
>>
>>>
>>> Signed-off-by: James Bottomley <
>>> James.Bottomley@HansenPartnership.com>
>>> ---
>>> drivers/char/tpm/Makefile | 3 +-
>>> drivers/char/tpm/tpm-chip.c | 73
>>> ++++++++++++++++++++++++++++++++++++++--
>>> drivers/char/tpm/tpm-interface.c | 13 +++++--
>>> drivers/char/tpm/tpm.h | 4 +++
>>> drivers/char/tpm/tpms-dev.c | 65
>>> +++++++++++++++++++++++++++++++++++
>>> 5 files changed, 152 insertions(+), 6 deletions(-)
>>> create mode 100644 drivers/char/tpm/tpms-dev.c
>>>
>>> diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
>>> index 10e5827..bbe6531 100644
>>> --- a/drivers/char/tpm/Makefile
>>> +++ b/drivers/char/tpm/Makefile
>>> @@ -3,7 +3,8 @@
>>> #
>>> obj-$(CONFIG_TCG_TPM) += tpm.o
>>> tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2
>>> -cmd.o \
>>> - tpm-dev-common.o tpm1_eventlog.o tpm2_eventlog.o tpm2
>>> -space.o
>>> + tpm-dev-common.o tpms-dev.o tpm1_eventlog.o
>>> tpm2_eventlog.o \
>>> + tpm2-space.o
>>> tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
>>> tpm-$(CONFIG_OF) += tpm_of.o
>>> obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
>>> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm
>>> -chip.c
>>> index 993b9ae..c71c353 100644
>>> --- a/drivers/char/tpm/tpm-chip.c
>>> +++ b/drivers/char/tpm/tpm-chip.c
>>> @@ -33,6 +33,7 @@ DEFINE_IDR(dev_nums_idr);
>>> static DEFINE_MUTEX(idr_lock);
>>>
>>> struct class *tpm_class;
>>> +struct class *tpms_class;
>>> dev_t tpm_devt;
>>>
>>> /**
>>> @@ -132,6 +133,14 @@ static void tpm_dev_release(struct device
>>> *dev)
>>> kfree(chip);
>>> }
>>>
>>> +static void tpm_devs_release(struct device *dev)
>>> +{
>>> + struct tpm_chip *chip = container_of(dev, struct tpm_chip,
>>> devs);
>>> +
>>> + /* release the master device reference */
>>> + put_device(&chip->dev);
>>> +}
>>> +
>>> /**
>>> * tpm_chip_alloc() - allocate a new struct tpm_chip instance
>>> * @pdev: device to which the chip is associated
>>> @@ -168,27 +177,47 @@ struct tpm_chip *tpm_chip_alloc(struct device
>>> *pdev,
>>> chip->dev_num = rc;
>>>
>>> device_initialize(&chip->dev);
>>> + device_initialize(&chip->devs);
>>>
>>> chip->dev.class = tpm_class;
>>> chip->dev.release = tpm_dev_release;
>>> chip->dev.parent = pdev;
>>> chip->dev.groups = chip->groups;
>>>
>>> + chip->devs.parent = pdev;
>>> + chip->devs.class = tpms_class;
>>> + chip->devs.release = tpm_devs_release;
>>> + /* get extra reference on main device to hold on
>>> + * behalf of devs. This holds the chip structure
>>> + * while cdevs is in use. The corresponding put
>>> + * is in the tpm_devs_release
>>> + */
>>> + get_device(&chip->dev);
>>> +
>>> if (chip->dev_num == 0)
>>> chip->dev.devt = MKDEV(MISC_MAJOR, TPM_MINOR);
>>> else
>>> chip->dev.devt = MKDEV(MAJOR(tpm_devt), chip
>>> ->dev_num);
>>>
>>> + chip->devs.devt =
>>> + MKDEV(MAJOR(tpm_devt), chip->dev_num +
>>> TPM_NUM_DEVICES);
>>> +
>>> rc = dev_set_name(&chip->dev, "tpm%d", chip->dev_num);
>>> if (rc)
>>> goto out;
>>> + rc = dev_set_name(&chip->devs, "tpms%d", chip->dev_num);
>>> + if (rc)
>>> + goto out;
>>>
>>> if (!pdev)
>>> chip->flags |= TPM_CHIP_FLAG_VIRTUAL;
>>>
>>> cdev_init(&chip->cdev, &tpm_fops);
>>> + cdev_init(&chip->cdevs, &tpms_fops);
>>> chip->cdev.owner = THIS_MODULE;
>>> + chip->cdevs.owner = THIS_MODULE;
>>> chip->cdev.kobj.parent = &chip->dev.kobj;
>>> + chip->cdevs.kobj.parent = &chip->devs.kobj;
>>>
>>> chip->work_space.context_buf = kzalloc(PAGE_SIZE,
>>> GFP_KERNEL);
>>> if (!chip->work_space.context_buf) {
>>> @@ -199,6 +228,7 @@ struct tpm_chip *tpm_chip_alloc(struct device
>>> *pdev,
>>> return chip;
>>>
>>> out:
>>> + put_device(&chip->devs);
>>> put_device(&chip->dev);
>>> return ERR_PTR(rc);
>>> }
>>> @@ -244,7 +274,7 @@ static int tpm_add_char_device(struct tpm_chip
>>> *chip)
>>> dev_name(&chip->dev), MAJOR(chip
>>> ->dev.devt),
>>> MINOR(chip->dev.devt), rc);
>>>
>>> - return rc;
>>> + goto err_1;
>>> }
>>>
>>> rc = device_add(&chip->dev);
>>> @@ -254,16 +284,44 @@ static int tpm_add_char_device(struct
>>> tpm_chip *chip)
>>> dev_name(&chip->dev), MAJOR(chip
>>> ->dev.devt),
>>> MINOR(chip->dev.devt), rc);
>>>
>>> - cdev_del(&chip->cdev);
>>> - return rc;
>>> + goto err_2;
>>> + }
>>> +
>>> + if (chip->flags & TPM_CHIP_FLAG_TPM2)
>>> + rc = cdev_add(&chip->cdevs, chip->devs.devt, 1);
>>> + if (rc) {
>>> + dev_err(&chip->dev,
>>> + "unable to cdev_add() %s, major %d, minor
>>> %d, err=%d\n",
>>> + dev_name(&chip->devs), MAJOR(chip
>>> ->devs.devt),
>>> + MINOR(chip->devs.devt), rc);
>>> +
>>> + goto err_3;
>>> }
>>>
>>> + if (chip->flags & TPM_CHIP_FLAG_TPM2)
>>> + rc = device_add(&chip->devs);
>>> + if (rc) {
>>> + dev_err(&chip->dev,
>>> + "unable to device_register() %s, major %d,
>>> minor %d, err=%d\n",
>>> + dev_name(&chip->devs), MAJOR(chip
>>> ->devs.devt),
>>> + MINOR(chip->devs.devt), rc);
>>> +
>>> + goto err_4;
>>> + }
>>> /* Make the chip available. */
>>> mutex_lock(&idr_lock);
>>> idr_replace(&dev_nums_idr, chip, chip->dev_num);
>>> mutex_unlock(&idr_lock);
>>>
>>> return rc;
>>> + err_4:
>>> + cdev_del(&chip->cdevs);
>>> + err_3:
>>> + device_del(&chip->dev);
>>> + err_2:
>>> + cdev_del(&chip->cdev);
>>> + err_1:
>>> + return rc;
>>> }
>>>
>>> static void tpm_del_char_device(struct tpm_chip *chip)
>>> @@ -271,6 +329,11 @@ static void tpm_del_char_device(struct
>>> tpm_chip *chip)
>>> cdev_del(&chip->cdev);
>>> device_del(&chip->dev);
>>>
>>> + if (chip->flags & TPM_CHIP_FLAG_TPM2) {
>>> + cdev_del(&chip->cdevs);
>>> + device_del(&chip->devs);
>>> + }
>>> +
>>> /* Make the chip unavailable. */
>>> mutex_lock(&idr_lock);
>>> idr_replace(&dev_nums_idr, NULL, chip->dev_num);
>>> @@ -282,6 +345,10 @@ static void tpm_del_char_device(struct
>>> tpm_chip *chip)
>>> tpm2_shutdown(chip, TPM2_SU_CLEAR);
>>> chip->ops = NULL;
>>> up_write(&chip->ops_sem);
>>> + /* will release the devs reference to the chip->dev unless
>>> + * something has cdevs open
>>> + */
>>> + put_device(&chip->devs);
>>> }
>>>
>>> static void tpm_del_legacy_sysfs(struct tpm_chip *chip)
>>> diff --git a/drivers/char/tpm/tpm-interface.c
>>> b/drivers/char/tpm/tpm-interface.c
>>> index db5ffe9..deb2021 100644
>>> --- a/drivers/char/tpm/tpm-interface.c
>>> +++ b/drivers/char/tpm/tpm-interface.c
>>> @@ -1257,9 +1257,17 @@ static int __init tpm_init(void)
>>> return PTR_ERR(tpm_class);
>>> }
>>>
>>> - rc = alloc_chrdev_region(&tpm_devt, 0, TPM_NUM_DEVICES,
>>> "tpm");
>>> + tpms_class = class_create(THIS_MODULE, "tpms");
>>> + if (IS_ERR(tpms_class)) {
>>> + pr_err("couldn't create tpms class\n");
>>> + class_destroy(tpm_class);
>>> + return PTR_ERR(tpms_class);
>>> + }
>>> +
>>> + rc = alloc_chrdev_region(&tpm_devt, 0, 2*TPM_NUM_DEVICES,
>>> "tpm");
>>> if (rc < 0) {
>>> pr_err("tpm: failed to allocate char dev
>>> region\n");
>>> + class_destroy(tpms_class);
>>> class_destroy(tpm_class);
>>> return rc;
>>> }
>>> @@ -1271,7 +1279,8 @@ static void __exit tpm_exit(void)
>>> {
>>> idr_destroy(&dev_nums_idr);
>>> class_destroy(tpm_class);
>>> - unregister_chrdev_region(tpm_devt, TPM_NUM_DEVICES);
>>> + class_destroy(tpms_class);
>>> + unregister_chrdev_region(tpm_devt, 2*TPM_NUM_DEVICES);
>>> }
>>>
>>> subsys_initcall(tpm_init);
>>> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
>>> index 97e48a4..822ca67 100644
>>> --- a/drivers/char/tpm/tpm.h
>>> +++ b/drivers/char/tpm/tpm.h
>>> @@ -182,7 +182,9 @@ struct tpm_chip_seqops {
>>>
>>> struct tpm_chip {
>>> struct device dev;
>>> + struct device devs;
>>> struct cdev cdev;
>>> + struct cdev cdevs;
>>>
>>> /* A driver callback under ops cannot be run unless
>>> ops_sem is held
>>> * (sometimes implicitly, eg for the sysfs code). ops
>>> becomes null
>>> @@ -510,8 +512,10 @@ static inline void tpm_buf_append_u32(struct
>>> tpm_buf *buf, const u32 value)
>>> }
>>>
>>> extern struct class *tpm_class;
>>> +extern struct class *tpms_class;
>>> extern dev_t tpm_devt;
>>> extern const struct file_operations tpm_fops;
>>> +extern const struct file_operations tpms_fops;
>>> extern struct idr dev_nums_idr;
>>>
>>> enum tpm_transmit_flags {
>>> diff --git a/drivers/char/tpm/tpms-dev.c b/drivers/char/tpm/tpms
>>> -dev.c
>>> new file mode 100644
>>> index 0000000..5720885
>>> --- /dev/null
>>> +++ b/drivers/char/tpm/tpms-dev.c
>>> @@ -0,0 +1,65 @@
>>> +/*
>>> + * Copyright (C) 2017 James.Bottomley@HansenPartnership.com
>>> + *
>>> + * GPLv2
>>> + */
>>> +#include <linux/slab.h>
>>> +#include "tpm-dev.h"
>>> +
>>> +struct tpms_priv {
>>> + struct file_priv priv;
>>> + struct tpm_space space;
>>> +};
>>> +
>>> +static int tpms_open(struct inode *inode, struct file *file)
>>> +{
>>> + struct tpm_chip *chip;
>>> + struct tpms_priv *priv;
>>> + int rc;
>>> +
>>> + chip = container_of(inode->i_cdev, struct tpm_chip,
>>> cdevs);
>>> + priv = kzalloc(sizeof(*priv), GFP_KERNEL);
>>> + if (priv == NULL)
>>> + return -ENOMEM;
>>> +
>>> + rc = tpm2_init_space(&priv->space);
>>> + if (rc) {
>>> + kfree(priv);
>>> + return -ENOMEM;
>>> + }
>>> +
>>> + tpm_common_open(file, chip, &priv->priv);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +static int tpms_release(struct inode *inode, struct file *file)
>>> +{
>>> + struct file_priv *fpriv = file->private_data;
>>> + struct tpms_priv *priv = container_of(fpriv, struct
>>> tpms_priv, priv);
>>> +
>>> + tpm_common_release(file, fpriv);
>>> + tpm2_del_space(&priv->space);
>>> + kfree(priv);
>>> +
>>> + return 0;
>>> +}
>>> +
>>> +ssize_t tpms_write(struct file *file, const char __user *buf,
>>> + size_t size, loff_t *off)
>>> +{
>>> + struct file_priv *fpriv = file->private_data;
>>> + struct tpms_priv *priv = container_of(fpriv, struct
>>> tpms_priv, priv);
>>> +
>>> + return tpm_common_write(file, buf, size, off, &priv
>>> ->space);
>>> +}
>>> +
>>> +const struct file_operations tpms_fops = {
>>> + .owner = THIS_MODULE,
>>> + .llseek = no_llseek,
>>> + .open = tpms_open,
>>> + .read = tpm_common_read,
>>> + .write = tpms_write,
>>> + .release = tpms_release,
>>> +};
>>> +
>>>
>>
>
[toc] | [prev] | [next] | [standalone]
| From | James Bottomley <James.Bottomley@HansenPartnership.com> |
|---|---|
| Date | 2017-02-27 16:10 +0100 |
| Subject | Re: [tpmdd-devel] [PATCH v2 6/7] tpm: expose spaces via a device link /dev/tpms<n> |
| Message-ID | <tfv62-7iD-17@gated-at.bofh.it> |
| In reply to | #1588623 |
On Mon, 2017-02-27 at 17:16 +0530, Nayna wrote: > > On 02/24/2017 06:23 PM, James Bottomley wrote: > > On Fri, 2017-02-24 at 12:29 +0530, Nayna wrote: > > > > > > On 02/17/2017 12:55 AM, Jarkko Sakkinen wrote: > > > > From: James Bottomley <James.Bottomley@HansenPartnership.com> > > > > > > > > Currently the tpm spaces are not exposed to userspace. Make > > > > this exposure via a separate device, which can now be opened > > > > multiple times because each read/write transaction goes > > > > separately via the space. > > > > > > > > Concurrency is protected by the chip->tpm_mutex for each > > > > read/write transaction separately. The TPM is cleared of all > > > > transient objects by the time the mutex is dropped, so there > > > > should be no interference between the kernel and userspace. > > > > > > To understand, I have two questions: > > > > > > 1. How would a userspace application using TPM know whether to > > > use /dev/tpm0 or /dev/tpms0 ? > > > > Likely they can't use /dev/tpm0 becuase it will be root only, but > > the major indicator will be whether /dev/tpms0 exists or not. > > Thanks James !! > Currently, I see even /dev/tpms0 is also only root accessible. I did > see the discussion to make it 0666, and I understand adding command > filtering is part of enabling /dev/tpms0 as all-accessible. I don't think we'd ever do that from the kernel. Accessibility would be a userspace policy. This is what I have on my system to make it accessible: /etc/udev/rules.d/80-tpm-2.rules: # tpm 2 devices need to be world readable SUBSYSTEM=="tpms", ACTION=="add", MODE="0666" > Sorry, I didn't understand when you said, "major indicator will be > whether /dev/tpms0" exists or not ? I mean in what case it might not > exist.. If the kernel is too old or you have a 1.2 TPM. > > > > > 2. How would a userspace RM know to build on top of /dev/tpm0 or > > > /dev/tpms0. And if it is built on top of /dev/tpms0, can there be > > > issues with one RM on top of other RM. > > > > There's a known problem with RMs in that they're not fully > > stackable, so I suspect the answer is that if tpms0 exists you > > won't use an RM, but this is currently an area of active research. > > The other potential problem is that if you build a RM on tpm0 in > > userspace, it will fight with the kernel when the kernel uses > > sessions. > > Does it imply that there should be restriction to disallow any RM > specific commands from userspace on /dev/tpm0 ? The only such command would be session or policy context save. It's debateable whether we should interfere. James
[toc] | [prev] | [next] | [standalone]
| From | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
|---|---|
| Date | 2017-02-16 20:30 +0100 |
| Subject | [PATCH v2 4/7] tpm: infrastructure for TPM spaces |
| Message-ID | <tbzUC-2oT-29@gated-at.bofh.it> |
| In reply to | #1582883 |
Added an ability to virtualize TPM commands into an isolated context
that we call a TPM space because the word context is already heavily
used in the TPM specification. Both the handle areas and bodies (where
necessary) are virtualized.
The mechanism works by adding a new parameter struct tpm_space to the
tpm_transmit() function. This new structure contains the list of virtual
handles and a buffer of page size (currently) for backing storage.
When tpm_transmit() is called with a struct tpm_space instance it will
execute the following sequence:
1. Take locks.
2. Load transient objects from the backing storage by using ContextLoad
and map virtual handles to physical handles.
3. Perform the transaction.
4. Save transient objects to backing storage by using ContextSave and
map resulting physical handle to virtual handle if there is such.
This commit does not implement virtualization support for hmac and
policy sessions.
Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
drivers/char/tpm/Makefile | 2 +-
drivers/char/tpm/tpm-chip.c | 7 +
drivers/char/tpm/tpm-dev.c | 2 +-
drivers/char/tpm/tpm-interface.c | 68 +++---
drivers/char/tpm/tpm-sysfs.c | 2 +-
drivers/char/tpm/tpm.h | 26 ++-
drivers/char/tpm/tpm2-cmd.c | 33 +--
drivers/char/tpm/tpm2-space.c | 431 +++++++++++++++++++++++++++++++++++++++
8 files changed, 520 insertions(+), 51 deletions(-)
create mode 100644 drivers/char/tpm/tpm2-space.c
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 3d386a8..8f07fcf 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -3,7 +3,7 @@
#
obj-$(CONFIG_TCG_TPM) += tpm.o
tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
- tpm1_eventlog.o tpm2_eventlog.o
+ tpm1_eventlog.o tpm2_eventlog.o tpm2-space.o
tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
tpm-$(CONFIG_OF) += tpm_of.o
obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index c406343..993b9ae 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -128,6 +128,7 @@ static void tpm_dev_release(struct device *dev)
mutex_unlock(&idr_lock);
kfree(chip->log.bios_event_log);
+ kfree(chip->work_space.context_buf);
kfree(chip);
}
@@ -189,6 +190,12 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
chip->cdev.owner = THIS_MODULE;
chip->cdev.kobj.parent = &chip->dev.kobj;
+ chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!chip->work_space.context_buf) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
return chip;
out:
diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
index 02a8850..414553b 100644
--- a/drivers/char/tpm/tpm-dev.c
+++ b/drivers/char/tpm/tpm-dev.c
@@ -147,7 +147,7 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
mutex_unlock(&priv->buffer_mutex);
return -EPIPE;
}
- out_size = tpm_transmit(priv->chip, priv->data_buffer,
+ out_size = tpm_transmit(priv->chip, NULL, priv->data_buffer,
sizeof(priv->data_buffer), 0);
tpm_put_ops(priv->chip);
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 20b1fe3..db5ffe9 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -376,11 +376,12 @@ static bool tpm_validate_command(struct tpm_chip *chip, const u8 *cmd,
* 0 when the operation is successful.
* A negative number for system errors (errno).
*/
-ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
- unsigned int flags)
+ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
+ u8 *buf, size_t bufsiz, unsigned int flags)
{
- const struct tpm_output_header *header = (void *)buf;
- ssize_t rc;
+ struct tpm_output_header *header = (void *)buf;
+ int rc;
+ ssize_t len = 0;
u32 count, ordinal;
unsigned long stop;
@@ -406,10 +407,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
if (chip->dev.parent)
pm_runtime_get_sync(chip->dev.parent);
+ rc = tpm2_prepare_space(chip, space, ordinal, buf);
+ if (rc)
+ goto out;
+
rc = chip->ops->send(chip, (u8 *) buf, count);
if (rc < 0) {
dev_err(&chip->dev,
- "tpm_transmit: tpm_send: error %zd\n", rc);
+ "tpm_transmit: tpm_send: error %d\n", rc);
goto out;
}
@@ -442,18 +447,23 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
goto out;
out_recv:
- rc = chip->ops->recv(chip, (u8 *) buf, bufsiz);
- if (rc < 0) {
+ len = chip->ops->recv(chip, (u8 *) buf, bufsiz);
+ if (len < 0) {
dev_err(&chip->dev,
- "tpm_transmit: tpm_recv: error %zd\n", rc);
+ "tpm_transmit: tpm_recv: error %d\n", rc);
+ rc = len;
goto out;
- } else if (rc < TPM_HEADER_SIZE) {
+ } else if (len < TPM_HEADER_SIZE) {
rc = -EFAULT;
goto out;
}
- if (rc != be32_to_cpu(header->length))
+ if (len != be32_to_cpu(header->length)) {
+ rc = -EFAULT;
goto out;
+ }
+
+ rc = tpm2_commit_space(chip, space, ordinal, buf, &len);
out:
if (chip->dev.parent)
@@ -461,7 +471,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
if (!(flags & TPM_TRANSMIT_UNLOCKED))
mutex_unlock(&chip->tpm_mutex);
- return rc;
+ return rc ? rc : len;
}
/**
@@ -480,15 +490,16 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
* A negative number for system errors (errno).
* A positive number for a TPM error.
*/
-ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *buf,
- size_t bufsiz, size_t min_rsp_body_length,
- unsigned int flags, const char *desc)
+ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
+ const void *buf, size_t bufsiz,
+ size_t min_rsp_body_length, unsigned int flags,
+ const char *desc)
{
const struct tpm_output_header *header = buf;
int err;
ssize_t len;
- len = tpm_transmit(chip, (const u8 *)buf, bufsiz, flags);
+ len = tpm_transmit(chip, space, (u8 *)buf, bufsiz, flags);
if (len < 0)
return len;
@@ -541,7 +552,7 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
tpm_cmd.params.getcap_in.subcap = cpu_to_be32(subcap_id);
}
- rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
+ rc = tpm_transmit_cmd(chip, NULL, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
min_cap_length, 0, desc);
if (!rc)
*cap = tpm_cmd.params.getcap_out.cap;
@@ -565,7 +576,8 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
start_cmd.header.in = tpm_startup_header;
start_cmd.params.startup_in.startup_type = startup_type;
- return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
+ return tpm_transmit_cmd(chip, NULL, &start_cmd,
+ TPM_INTERNAL_RESULT_SIZE, 0,
0, "attempting to start the TPM");
}
@@ -722,8 +734,8 @@ static int tpm_continue_selftest(struct tpm_chip *chip)
struct tpm_cmd_t cmd;
cmd.header.in = continue_selftest_header;
- rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, 0, 0,
- "continue selftest");
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
+ 0, 0, "continue selftest");
return rc;
}
@@ -743,7 +755,7 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
cmd.header.in = pcrread_header;
cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
- rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, READ_PCR_RESULT_SIZE,
READ_PCR_RESULT_BODY_SIZE, 0,
"attempting to read a pcr value");
@@ -855,7 +867,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
cmd.header.in = pcrextend_header;
cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
- rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE,
EXTEND_PCR_RESULT_BODY_SIZE, 0,
"attempting extend a PCR value");
@@ -960,8 +972,8 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen)
if (chip == NULL)
return -ENODEV;
- rc = tpm_transmit_cmd(chip, cmd, buflen, 0, 0, "attempting tpm_cmd");
-
+ rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, 0, 0,
+ "attempting tpm_cmd");
tpm_put_ops(chip);
return rc;
}
@@ -1062,16 +1074,16 @@ int tpm_pm_suspend(struct device *dev)
cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
TPM_DIGEST_SIZE);
- rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
- EXTEND_PCR_RESULT_BODY_SIZE, 0,
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE,
+ EXTEND_PCR_RESULT_BODY_SIZE, 0,
"extending dummy pcr before suspend");
}
/* now do the actual savestate */
for (try = 0; try < TPM_RETRY; try++) {
cmd.header.in = savestate_header;
- rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, 0,
- 0, NULL);
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, SAVESTATE_RESULT_SIZE,
+ 0, 0, NULL);
/*
* If the TPM indicates that it is too busy to respond to
@@ -1154,7 +1166,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
tpm_cmd.header.in = tpm_getrandom_header;
tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
- err = tpm_transmit_cmd(chip, &tpm_cmd,
+ err = tpm_transmit_cmd(chip, NULL, &tpm_cmd,
TPM_GETRANDOM_RESULT_SIZE + num_bytes,
offsetof(struct tpm_getrandom_out,
rng_data),
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 2f596d7..55405db 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -40,7 +40,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
struct tpm_chip *chip = to_tpm_chip(dev);
tpm_cmd.header.in = tpm_readpubek_header;
- err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
+ err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
"attempting to read the PUBEK");
if (err)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 0ec1cf0..97e48a4 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -89,10 +89,13 @@ enum tpm2_structures {
};
enum tpm2_return_codes {
+ TPM2_RC_SUCCESS = 0x0000,
TPM2_RC_HASH = 0x0083, /* RC_FMT1 */
+ TPM2_RC_HANDLE = 0x008B,
TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */
TPM2_RC_DISABLED = 0x0120,
TPM2_RC_TESTING = 0x090A, /* RC_WARN */
+ TPM2_RC_REFERENCE_H0 = 0x0910,
};
enum tpm2_algorithms {
@@ -114,6 +117,7 @@ enum tpm2_command_codes {
TPM2_CC_CREATE = 0x0153,
TPM2_CC_LOAD = 0x0157,
TPM2_CC_UNSEAL = 0x015E,
+ TPM2_CC_CONTEXT_LOAD = 0x0161,
TPM2_CC_CONTEXT_SAVE = 0x0162,
TPM2_CC_FLUSH_CONTEXT = 0x0165,
TPM2_CC_GET_CAPABILITY = 0x017A,
@@ -128,6 +132,7 @@ enum tpm2_permanent_handles {
};
enum tpm2_capabilities {
+ TPM2_CAP_HANDLES = 1,
TPM2_CAP_COMMANDS = 2,
TPM2_CAP_PCRS = 5,
TPM2_CAP_TPM_PROPERTIES = 6,
@@ -153,6 +158,11 @@ enum tpm2_cc_attrs {
#define TPM_PPI_VERSION_LEN 3
+struct tpm_space {
+ u32 context_tbl[3];
+ u8 *context_buf;
+};
+
enum tpm_chip_flags {
TPM_CHIP_FLAG_TPM2 = BIT(1),
TPM_CHIP_FLAG_IRQ = BIT(2),
@@ -211,6 +221,7 @@ struct tpm_chip {
char ppi_version[TPM_PPI_VERSION_LEN + 1];
#endif /* CONFIG_ACPI */
+ struct tpm_space work_space;
u32 nr_commands;
u32 *cc_attrs_tbl;
};
@@ -507,10 +518,11 @@ enum tpm_transmit_flags {
TPM_TRANSMIT_UNLOCKED = BIT(0),
};
-ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
- unsigned int flags);
-ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *buf, size_t bufsiz,
- size_t min_rsp_body_len, unsigned int flags,
+ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
+ u8 *buf, size_t bufsiz, unsigned int flags);
+ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
+ const void *buf, size_t bufsiz,
+ size_t min_rsp_body_length, unsigned int flags,
const char *desc);
ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length);
@@ -572,4 +584,10 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm2_probe(struct tpm_chip *chip);
ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
int tpm2_find_cc(struct tpm_chip *chip, u32 cc);
+int tpm2_init_space(struct tpm_space *space);
+void tpm2_del_space(struct tpm_space *space);
+int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc,
+ u8 *cmd);
+int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
+ u32 cc, u8 *buf, size_t *bufsiz);
#endif
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 897902a..96121b3 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -266,7 +266,7 @@ int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
sizeof(cmd.params.pcrread_in.pcr_select));
cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
- rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
TPM2_PCR_READ_RESP_BODY_SIZE,
0, "attempting to read a pcr value");
if (rc == 0) {
@@ -333,7 +333,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
}
}
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, 0,
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
"attempting extend a PCR value");
tpm_buf_destroy(&buf);
@@ -382,7 +382,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
cmd.header.in = tpm2_getrandom_header;
cmd.params.getrandom_in.size = cpu_to_be16(num_bytes);
- err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+ err = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
offsetof(struct tpm2_get_random_out,
buffer),
0, "attempting get random");
@@ -441,7 +441,7 @@ void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
tpm_buf_append_u32(&buf, handle);
- (void) tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, flags,
+ (void) tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, flags,
"flushing context");
tpm_buf_destroy(&buf);
@@ -557,7 +557,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
goto out;
}
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 4, 0,
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, 0,
"sealing data");
if (rc)
goto out;
@@ -641,7 +641,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
goto out;
}
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 4, flags,
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, flags,
"loading blob");
if (!rc)
*blob_handle = be32_to_cpup(
@@ -693,7 +693,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
options->blobauth /* hmac */,
TPM_DIGEST_SIZE);
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 6, flags,
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 6, flags,
"unsealing");
if (rc > 0)
rc = -EPERM;
@@ -770,7 +770,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
- rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
TPM2_GET_TPM_PT_OUT_BODY_SIZE, 0, desc);
if (!rc)
*value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
@@ -805,7 +805,7 @@ static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
cmd.header.in = tpm2_startup_header;
cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
- return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0,
+ return tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
"attempting to start the TPM");
}
@@ -834,7 +834,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
cmd.header.in = tpm2_shutdown_header;
cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
- rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0,
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
"stopping the TPM");
/* In places where shutdown command is sent there's no much we can do
@@ -898,7 +898,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
cmd.header.in = tpm2_selftest_header;
cmd.params.selftest_in.full_test = full;
- rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0,
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0,
"continue selftest");
/* At least some prototype chips seem to give RC_TESTING error
@@ -949,7 +949,8 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
cmd.params.pcrread_in.pcr_select[1] = 0x00;
cmd.params.pcrread_in.pcr_select[2] = 0x00;
- rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0, NULL);
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
+ NULL);
if (rc < 0)
break;
@@ -982,7 +983,7 @@ int tpm2_probe(struct tpm_chip *chip)
cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
- rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0, NULL);
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, NULL);
if (rc < 0)
return rc;
@@ -1022,8 +1023,8 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
tpm_buf_append_u32(&buf, nr_commands);
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 9 + 4 * nr_commands,
- 0, NULL);
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+ 9 + 4 * nr_commands, 0, NULL);
if (rc) {
tpm_buf_destroy(&buf);
goto out;
@@ -1136,7 +1137,7 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
tpm_buf_append_u32(&buf, 0);
tpm_buf_append_u32(&buf, 1);
- rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 9, 0,
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 9, 0,
"get tpm pcr allocation");
if (rc)
goto out;
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
new file mode 100644
index 0000000..e955548
--- /dev/null
+++ b/drivers/char/tpm/tpm2-space.c
@@ -0,0 +1,431 @@
+/*
+ * Copyright (C) 2016 Intel Corporation
+ *
+ * Authors:
+ * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
+ *
+ * Maintained by: <tpmdd-devel@lists.sourceforge.net>
+ *
+ * This file contains TPM2 protocol implementations of the commands
+ * used by the kernel internally.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; version 2
+ * of the License.
+ */
+
+#include <linux/gfp.h>
+#include <asm/unaligned.h>
+#include "tpm.h"
+
+enum tpm2_handle_types {
+ TPM2_HT_HMAC_SESSION = 0x02000000,
+ TPM2_HT_POLICY_SESSION = 0x03000000,
+ TPM2_HT_TRANSIENT = 0x80000000,
+};
+
+struct tpm2_context {
+ __be64 sequence;
+ __be32 saved_handle;
+ __be32 hierarchy;
+ __be16 blob_size;
+} __packed;
+
+int tpm2_init_space(struct tpm_space *space)
+{
+ space->context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
+ if (!space->context_buf)
+ return -ENOMEM;
+
+ return 0;
+}
+
+void tpm2_del_space(struct tpm_space *space)
+{
+ kfree(space->context_buf);
+}
+
+static int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
+ unsigned int *offset, u32 *handle)
+{
+ struct tpm_buf tbuf;
+ struct tpm2_context *ctx;
+ unsigned int body_size;
+ int rc;
+
+ rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD);
+ if (rc)
+ return rc;
+
+ ctx = (struct tpm2_context *)&buf[*offset];
+ body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size);
+ tpm_buf_append(&tbuf, &buf[*offset], body_size);
+
+ rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 4,
+ TPM_TRANSMIT_UNLOCKED, NULL);
+ if (rc < 0) {
+ dev_warn(&chip->dev, "%s: failed with a system error %d\n",
+ __func__, rc);
+ tpm_buf_destroy(&tbuf);
+ return -EFAULT;
+ } else if (rc > 0) {
+ dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
+ __func__, rc);
+ tpm_buf_destroy(&tbuf);
+ return -EFAULT;
+ }
+
+ *handle = be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]);
+ *offset += body_size;
+
+ tpm_buf_destroy(&tbuf);
+ return 0;
+}
+
+static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
+ unsigned int buf_size, unsigned int *offset)
+{
+ struct tpm_buf tbuf;
+ unsigned int body_size;
+ int rc;
+
+ rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE);
+ if (rc)
+ return rc;
+
+ tpm_buf_append_u32(&tbuf, handle);
+
+ rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 0,
+ TPM_TRANSMIT_UNLOCKED, NULL);
+ if (rc < 0) {
+ dev_warn(&chip->dev, "%s: failed with a system error %d\n",
+ __func__, rc);
+ tpm_buf_destroy(&tbuf);
+ return -EFAULT;
+ } else if (tpm2_rc_value(rc) == TPM2_RC_REFERENCE_H0) {
+ tpm_buf_destroy(&tbuf);
+ return -ENOENT;
+ } else if (rc) {
+ dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
+ __func__, rc);
+ tpm_buf_destroy(&tbuf);
+ return -EFAULT;
+ }
+
+ body_size = tpm_buf_length(&tbuf) - TPM_HEADER_SIZE;
+ if ((*offset + body_size) > buf_size) {
+ dev_warn(&chip->dev, "%s: out of backing storage\n", __func__);
+ tpm_buf_destroy(&tbuf);
+ return -ENOMEM;
+ }
+
+ memcpy(&buf[*offset], &tbuf.data[TPM_HEADER_SIZE], body_size);
+ tpm2_flush_context_cmd(chip, handle, TPM_TRANSMIT_UNLOCKED);
+ *offset += body_size;
+ tpm_buf_destroy(&tbuf);
+ return 0;
+}
+
+static void tpm2_flush_space(struct tpm_chip *chip)
+{
+ struct tpm_space *space = &chip->work_space;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
+ if (space->context_tbl[i] && ~space->context_tbl[i])
+ tpm2_flush_context_cmd(chip, space->context_tbl[i],
+ TPM_TRANSMIT_UNLOCKED);
+}
+
+static int tpm2_load_space(struct tpm_chip *chip)
+{
+ struct tpm_space *space = &chip->work_space;
+ unsigned int offset;
+ int i;
+ int rc;
+
+ for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
+ if (!space->context_tbl[i])
+ continue;
+
+ /* sanity check, should never happen */
+ if (~space->context_tbl[i]) {
+ dev_err(&chip->dev, "context table is inconsistent");
+ return -EFAULT;
+ }
+
+ rc = tpm2_load_context(chip, space->context_buf, &offset,
+ &space->context_tbl[i]);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
+
+static bool tpm2_map_to_phandle(struct tpm_space *space, void *handle)
+{
+ u32 vhandle = be32_to_cpup((__be32 *)handle);
+ u32 phandle;
+ int i;
+
+ i = 0xFFFFFF - (vhandle & 0xFFFFFF);
+ if (i > ARRAY_SIZE(space->context_tbl) || !space->context_tbl[i])
+ return false;
+
+ phandle = space->context_tbl[i];
+ *((__be32 *)handle) = cpu_to_be32(phandle);
+ return true;
+}
+
+static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd)
+{
+ struct tpm_space *space = &chip->work_space;
+ unsigned int nr_handles;
+ u32 attrs;
+ u32 *handle;
+ int i;
+
+ i = tpm2_find_cc(chip, cc);
+ if (i < 0)
+ return -EINVAL;
+
+ attrs = chip->cc_attrs_tbl[i];
+ nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
+
+ handle = (u32 *)&cmd[TPM_HEADER_SIZE];
+ for (i = 0; i < nr_handles; i++, handle++) {
+ if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) {
+ if (!tpm2_map_to_phandle(space, handle))
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc,
+ u8 *cmd)
+{
+ int rc;
+
+ if (!space)
+ return 0;
+
+ memcpy(&chip->work_space.context_tbl, &space->context_tbl,
+ sizeof(space->context_tbl));
+ memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE);
+
+ rc = tpm2_load_space(chip);
+ if (rc) {
+ tpm2_flush_space(chip);
+ return rc;
+ }
+
+ rc = tpm2_map_command(chip, cc, cmd);
+ if (rc) {
+ tpm2_flush_space(chip);
+ return rc;
+ }
+
+ return 0;
+}
+
+static u32 tpm2_map_to_vhandle(struct tpm_space *space, u32 phandle, bool alloc)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
+ if (alloc) {
+ if (!space->context_tbl[i]) {
+ space->context_tbl[i] = phandle;
+ break;
+ }
+ } else if (space->context_tbl[i] == phandle)
+ break;
+ }
+
+ if (i == ARRAY_SIZE(space->context_tbl))
+ return 0;
+
+ return TPM2_HT_TRANSIENT | (0xFFFFFF - i);
+}
+
+static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp,
+ size_t len)
+{
+ struct tpm_space *space = &chip->work_space;
+ struct tpm_output_header *header = (void *)rsp;
+ u32 phandle;
+ u32 phandle_type;
+ u32 vhandle;
+ u32 attrs;
+ int i;
+
+ if (be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS)
+ return 0;
+
+ i = tpm2_find_cc(chip, cc);
+ /* sanity check, should never happen */
+ if (i < 0)
+ return -EFAULT;
+
+ attrs = chip->cc_attrs_tbl[i];
+ if (!((attrs >> TPM2_CC_ATTR_RHANDLE) & 1))
+ return 0;
+
+ phandle = be32_to_cpup((__be32 *)&rsp[TPM_HEADER_SIZE]);
+ phandle_type = phandle & 0xFF000000;
+
+ switch (phandle_type) {
+ case TPM2_HT_TRANSIENT:
+ vhandle = tpm2_map_to_vhandle(space, phandle, true);
+ if (!vhandle)
+ goto out_no_slots;
+
+ *(__be32 *)&rsp[TPM_HEADER_SIZE] = cpu_to_be32(vhandle);
+ break;
+ case TPM2_HT_HMAC_SESSION:
+ case TPM2_HT_POLICY_SESSION:
+ break;
+ default:
+ dev_err(&chip->dev, "%s: unknown handle 0x%08X\n",
+ __func__, phandle);
+ break;
+ };
+
+ return 0;
+out_no_slots:
+ tpm2_flush_context_cmd(chip, phandle, TPM_TRANSMIT_UNLOCKED);
+ dev_warn(&chip->dev, "%s: out of slots for 0x%08X\n", __func__,
+ phandle);
+ return -ENOMEM;
+}
+
+struct tpm2_cap_handles {
+ u8 more_data;
+ __be32 capability;
+ __be32 count;
+ __be32 handles[];
+} __packed;
+
+static int tpm2_map_response_body(struct tpm_chip *chip, u32 cc, u8 *rsp,
+ size_t len)
+{
+ struct tpm_space *space = &chip->work_space;
+ struct tpm_output_header *header = (void *)rsp;
+ struct tpm2_cap_handles *data;
+ u32 phandle;
+ u32 phandle_type;
+ u32 vhandle;
+ int i;
+ int j;
+
+ if (cc != TPM2_CC_GET_CAPABILITY ||
+ be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS) {
+ return 0;
+ }
+
+ if (len < TPM_HEADER_SIZE + 9)
+ return -EFAULT;
+
+ data = (void *)&rsp[TPM_HEADER_SIZE];
+ if (be32_to_cpu(data->capability) != TPM2_CAP_HANDLES)
+ return 0;
+
+ if (len != TPM_HEADER_SIZE + 9 + 4 * be32_to_cpu(data->count))
+ return -EFAULT;
+
+ for (i = 0, j = 0; i < be32_to_cpu(data->count); i++) {
+ phandle = be32_to_cpup((__be32 *)&data->handles[i]);
+ phandle_type = phandle & 0xFF000000;
+
+ switch (phandle_type) {
+ case TPM2_HT_TRANSIENT:
+ vhandle = tpm2_map_to_vhandle(space, phandle, false);
+ if (!vhandle)
+ break;
+
+ data->handles[j] = cpu_to_be32(vhandle);
+ j++;
+ break;
+ case TPM2_HT_HMAC_SESSION:
+ case TPM2_HT_POLICY_SESSION:
+ data->handles[j] = cpu_to_be32(phandle);
+ j++;
+ break;
+ default:
+ dev_err(&chip->dev, "%s: unknown handle 0x%08X\n",
+ __func__, phandle);
+ break;
+ }
+
+ }
+
+ header->length = cpu_to_be32(TPM_HEADER_SIZE + 9 + 4 * j);
+ data->count = cpu_to_be32(j);
+ return 0;
+}
+
+static int tpm2_save_space(struct tpm_chip *chip)
+{
+ struct tpm_space *space = &chip->work_space;
+ unsigned int offset;
+ int i;
+ int rc;
+
+ for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
+ if (!(space->context_tbl[i] && ~space->context_tbl[i]))
+ continue;
+
+ rc = tpm2_save_context(chip, space->context_tbl[i],
+ space->context_buf, PAGE_SIZE,
+ &offset);
+ if (rc == -ENOENT) {
+ space->context_tbl[i] = 0;
+ continue;
+ } else if (rc)
+ return rc;
+
+ space->context_tbl[i] = ~0;
+ }
+
+ return 0;
+}
+
+int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
+ u32 cc, u8 *buf, size_t *bufsiz)
+{
+ struct tpm_output_header *header = (void *)buf;
+ int rc;
+
+ if (!space)
+ return 0;
+
+ rc = tpm2_map_response_header(chip, cc, buf, *bufsiz);
+ if (rc) {
+ tpm2_flush_space(chip);
+ return rc;
+ }
+
+ rc = tpm2_map_response_body(chip, cc, buf, *bufsiz);
+ if (rc) {
+ tpm2_flush_space(chip);
+ return rc;
+ }
+
+ rc = tpm2_save_space(chip);
+ if (rc) {
+ tpm2_flush_space(chip);
+ return rc;
+ }
+
+ *bufsiz = be32_to_cpu(header->length);
+
+ memcpy(&space->context_tbl, &chip->work_space.context_tbl,
+ sizeof(space->context_tbl));
+ memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE);
+
+ return 0;
+}
--
2.9.3
[toc] | [prev] | [next] | [standalone]
| From | Nayna <nayna@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-02-21 19:30 +0100 |
| Subject | Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces |
| Message-ID | <tdnmi-6iG-29@gated-at.bofh.it> |
| In reply to | #1582888 |
On 02/17/2017 12:55 AM, Jarkko Sakkinen wrote:
> Added an ability to virtualize TPM commands into an isolated context
> that we call a TPM space because the word context is already heavily
> used in the TPM specification. Both the handle areas and bodies (where
> necessary) are virtualized.
>
> The mechanism works by adding a new parameter struct tpm_space to the
> tpm_transmit() function. This new structure contains the list of virtual
> handles and a buffer of page size (currently) for backing storage.
>
> When tpm_transmit() is called with a struct tpm_space instance it will
> execute the following sequence:
>
> 1. Take locks.
> 2. Load transient objects from the backing storage by using ContextLoad
> and map virtual handles to physical handles.
> 3. Perform the transaction.
> 4. Save transient objects to backing storage by using ContextSave and
> map resulting physical handle to virtual handle if there is such.
>
> This commit does not implement virtualization support for hmac and
> policy sessions.
>
If I have understood discussions correctly, I assume, that kernel TPM
operations will also be routed via RM. And I think that is not happening
now with these patches.
Am I missing something ?
Thanks & Regards,
- Nayna
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> ---
> drivers/char/tpm/Makefile | 2 +-
> drivers/char/tpm/tpm-chip.c | 7 +
> drivers/char/tpm/tpm-dev.c | 2 +-
> drivers/char/tpm/tpm-interface.c | 68 +++---
> drivers/char/tpm/tpm-sysfs.c | 2 +-
> drivers/char/tpm/tpm.h | 26 ++-
> drivers/char/tpm/tpm2-cmd.c | 33 +--
> drivers/char/tpm/tpm2-space.c | 431 +++++++++++++++++++++++++++++++++++++++
> 8 files changed, 520 insertions(+), 51 deletions(-)
> create mode 100644 drivers/char/tpm/tpm2-space.c
>
> diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
> index 3d386a8..8f07fcf 100644
> --- a/drivers/char/tpm/Makefile
> +++ b/drivers/char/tpm/Makefile
> @@ -3,7 +3,7 @@
> #
> obj-$(CONFIG_TCG_TPM) += tpm.o
> tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \
> - tpm1_eventlog.o tpm2_eventlog.o
> + tpm1_eventlog.o tpm2_eventlog.o tpm2-space.o
> tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
> tpm-$(CONFIG_OF) += tpm_of.o
> obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
> diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
> index c406343..993b9ae 100644
> --- a/drivers/char/tpm/tpm-chip.c
> +++ b/drivers/char/tpm/tpm-chip.c
> @@ -128,6 +128,7 @@ static void tpm_dev_release(struct device *dev)
> mutex_unlock(&idr_lock);
>
> kfree(chip->log.bios_event_log);
> + kfree(chip->work_space.context_buf);
> kfree(chip);
> }
>
> @@ -189,6 +190,12 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
> chip->cdev.owner = THIS_MODULE;
> chip->cdev.kobj.parent = &chip->dev.kobj;
>
> + chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
> + if (!chip->work_space.context_buf) {
> + rc = -ENOMEM;
> + goto out;
> + }
> +
> return chip;
>
> out:
> diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c
> index 02a8850..414553b 100644
> --- a/drivers/char/tpm/tpm-dev.c
> +++ b/drivers/char/tpm/tpm-dev.c
> @@ -147,7 +147,7 @@ static ssize_t tpm_write(struct file *file, const char __user *buf,
> mutex_unlock(&priv->buffer_mutex);
> return -EPIPE;
> }
> - out_size = tpm_transmit(priv->chip, priv->data_buffer,
> + out_size = tpm_transmit(priv->chip, NULL, priv->data_buffer,
> sizeof(priv->data_buffer), 0);
>
> tpm_put_ops(priv->chip);
> diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
> index 20b1fe3..db5ffe9 100644
> --- a/drivers/char/tpm/tpm-interface.c
> +++ b/drivers/char/tpm/tpm-interface.c
> @@ -376,11 +376,12 @@ static bool tpm_validate_command(struct tpm_chip *chip, const u8 *cmd,
> * 0 when the operation is successful.
> * A negative number for system errors (errno).
> */
> -ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
> - unsigned int flags)
> +ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
> + u8 *buf, size_t bufsiz, unsigned int flags)
> {
> - const struct tpm_output_header *header = (void *)buf;
> - ssize_t rc;
> + struct tpm_output_header *header = (void *)buf;
> + int rc;
> + ssize_t len = 0;
> u32 count, ordinal;
> unsigned long stop;
>
> @@ -406,10 +407,14 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
> if (chip->dev.parent)
> pm_runtime_get_sync(chip->dev.parent);
>
> + rc = tpm2_prepare_space(chip, space, ordinal, buf);
> + if (rc)
> + goto out;
> +
> rc = chip->ops->send(chip, (u8 *) buf, count);
> if (rc < 0) {
> dev_err(&chip->dev,
> - "tpm_transmit: tpm_send: error %zd\n", rc);
> + "tpm_transmit: tpm_send: error %d\n", rc);
> goto out;
> }
>
> @@ -442,18 +447,23 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
> goto out;
>
> out_recv:
> - rc = chip->ops->recv(chip, (u8 *) buf, bufsiz);
> - if (rc < 0) {
> + len = chip->ops->recv(chip, (u8 *) buf, bufsiz);
> + if (len < 0) {
> dev_err(&chip->dev,
> - "tpm_transmit: tpm_recv: error %zd\n", rc);
> + "tpm_transmit: tpm_recv: error %d\n", rc);
> + rc = len;
> goto out;
> - } else if (rc < TPM_HEADER_SIZE) {
> + } else if (len < TPM_HEADER_SIZE) {
> rc = -EFAULT;
> goto out;
> }
>
> - if (rc != be32_to_cpu(header->length))
> + if (len != be32_to_cpu(header->length)) {
> + rc = -EFAULT;
> goto out;
> + }
> +
> + rc = tpm2_commit_space(chip, space, ordinal, buf, &len);
>
> out:
> if (chip->dev.parent)
> @@ -461,7 +471,7 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
>
> if (!(flags & TPM_TRANSMIT_UNLOCKED))
> mutex_unlock(&chip->tpm_mutex);
> - return rc;
> + return rc ? rc : len;
> }
>
> /**
> @@ -480,15 +490,16 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
> * A negative number for system errors (errno).
> * A positive number for a TPM error.
> */
> -ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *buf,
> - size_t bufsiz, size_t min_rsp_body_length,
> - unsigned int flags, const char *desc)
> +ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
> + const void *buf, size_t bufsiz,
> + size_t min_rsp_body_length, unsigned int flags,
> + const char *desc)
> {
> const struct tpm_output_header *header = buf;
> int err;
> ssize_t len;
>
> - len = tpm_transmit(chip, (const u8 *)buf, bufsiz, flags);
> + len = tpm_transmit(chip, space, (u8 *)buf, bufsiz, flags);
> if (len < 0)
> return len;
>
> @@ -541,7 +552,7 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
> tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4);
> tpm_cmd.params.getcap_in.subcap = cpu_to_be32(subcap_id);
> }
> - rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
> + rc = tpm_transmit_cmd(chip, NULL, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
> min_cap_length, 0, desc);
> if (!rc)
> *cap = tpm_cmd.params.getcap_out.cap;
> @@ -565,7 +576,8 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
> start_cmd.header.in = tpm_startup_header;
>
> start_cmd.params.startup_in.startup_type = startup_type;
> - return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, 0,
> + return tpm_transmit_cmd(chip, NULL, &start_cmd,
> + TPM_INTERNAL_RESULT_SIZE, 0,
> 0, "attempting to start the TPM");
> }
>
> @@ -722,8 +734,8 @@ static int tpm_continue_selftest(struct tpm_chip *chip)
> struct tpm_cmd_t cmd;
>
> cmd.header.in = continue_selftest_header;
> - rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, 0, 0,
> - "continue selftest");
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
> + 0, 0, "continue selftest");
> return rc;
> }
>
> @@ -743,7 +755,7 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
>
> cmd.header.in = pcrread_header;
> cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
> - rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE,
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, READ_PCR_RESULT_SIZE,
> READ_PCR_RESULT_BODY_SIZE, 0,
> "attempting to read a pcr value");
>
> @@ -855,7 +867,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
> cmd.header.in = pcrextend_header;
> cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
> memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
> - rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE,
> EXTEND_PCR_RESULT_BODY_SIZE, 0,
> "attempting extend a PCR value");
>
> @@ -960,8 +972,8 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen)
> if (chip == NULL)
> return -ENODEV;
>
> - rc = tpm_transmit_cmd(chip, cmd, buflen, 0, 0, "attempting tpm_cmd");
> -
> + rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, 0, 0,
> + "attempting tpm_cmd");
> tpm_put_ops(chip);
> return rc;
> }
> @@ -1062,16 +1074,16 @@ int tpm_pm_suspend(struct device *dev)
> cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr);
> memcpy(cmd.params.pcrextend_in.hash, dummy_hash,
> TPM_DIGEST_SIZE);
> - rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE,
> - EXTEND_PCR_RESULT_BODY_SIZE, 0,
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, EXTEND_PCR_RESULT_SIZE,
> + EXTEND_PCR_RESULT_BODY_SIZE, 0,
> "extending dummy pcr before suspend");
> }
>
> /* now do the actual savestate */
> for (try = 0; try < TPM_RETRY; try++) {
> cmd.header.in = savestate_header;
> - rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, 0,
> - 0, NULL);
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, SAVESTATE_RESULT_SIZE,
> + 0, 0, NULL);
>
> /*
> * If the TPM indicates that it is too busy to respond to
> @@ -1154,7 +1166,7 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
> tpm_cmd.header.in = tpm_getrandom_header;
> tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
>
> - err = tpm_transmit_cmd(chip, &tpm_cmd,
> + err = tpm_transmit_cmd(chip, NULL, &tpm_cmd,
> TPM_GETRANDOM_RESULT_SIZE + num_bytes,
> offsetof(struct tpm_getrandom_out,
> rng_data),
> diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
> index 2f596d7..55405db 100644
> --- a/drivers/char/tpm/tpm-sysfs.c
> +++ b/drivers/char/tpm/tpm-sysfs.c
> @@ -40,7 +40,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr,
> struct tpm_chip *chip = to_tpm_chip(dev);
>
> tpm_cmd.header.in = tpm_readpubek_header;
> - err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
> + err = tpm_transmit_cmd(chip, NULL, &tpm_cmd, READ_PUBEK_RESULT_SIZE,
> READ_PUBEK_RESULT_MIN_BODY_SIZE, 0,
> "attempting to read the PUBEK");
> if (err)
> diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
> index 0ec1cf0..97e48a4 100644
> --- a/drivers/char/tpm/tpm.h
> +++ b/drivers/char/tpm/tpm.h
> @@ -89,10 +89,13 @@ enum tpm2_structures {
> };
>
> enum tpm2_return_codes {
> + TPM2_RC_SUCCESS = 0x0000,
> TPM2_RC_HASH = 0x0083, /* RC_FMT1 */
> + TPM2_RC_HANDLE = 0x008B,
> TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */
> TPM2_RC_DISABLED = 0x0120,
> TPM2_RC_TESTING = 0x090A, /* RC_WARN */
> + TPM2_RC_REFERENCE_H0 = 0x0910,
> };
>
> enum tpm2_algorithms {
> @@ -114,6 +117,7 @@ enum tpm2_command_codes {
> TPM2_CC_CREATE = 0x0153,
> TPM2_CC_LOAD = 0x0157,
> TPM2_CC_UNSEAL = 0x015E,
> + TPM2_CC_CONTEXT_LOAD = 0x0161,
> TPM2_CC_CONTEXT_SAVE = 0x0162,
> TPM2_CC_FLUSH_CONTEXT = 0x0165,
> TPM2_CC_GET_CAPABILITY = 0x017A,
> @@ -128,6 +132,7 @@ enum tpm2_permanent_handles {
> };
>
> enum tpm2_capabilities {
> + TPM2_CAP_HANDLES = 1,
> TPM2_CAP_COMMANDS = 2,
> TPM2_CAP_PCRS = 5,
> TPM2_CAP_TPM_PROPERTIES = 6,
> @@ -153,6 +158,11 @@ enum tpm2_cc_attrs {
>
> #define TPM_PPI_VERSION_LEN 3
>
> +struct tpm_space {
> + u32 context_tbl[3];
> + u8 *context_buf;
> +};
> +
> enum tpm_chip_flags {
> TPM_CHIP_FLAG_TPM2 = BIT(1),
> TPM_CHIP_FLAG_IRQ = BIT(2),
> @@ -211,6 +221,7 @@ struct tpm_chip {
> char ppi_version[TPM_PPI_VERSION_LEN + 1];
> #endif /* CONFIG_ACPI */
>
> + struct tpm_space work_space;
> u32 nr_commands;
> u32 *cc_attrs_tbl;
> };
> @@ -507,10 +518,11 @@ enum tpm_transmit_flags {
> TPM_TRANSMIT_UNLOCKED = BIT(0),
> };
>
> -ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz,
> - unsigned int flags);
> -ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *buf, size_t bufsiz,
> - size_t min_rsp_body_len, unsigned int flags,
> +ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
> + u8 *buf, size_t bufsiz, unsigned int flags);
> +ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
> + const void *buf, size_t bufsiz,
> + size_t min_rsp_body_length, unsigned int flags,
> const char *desc);
> ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
> const char *desc, size_t min_cap_length);
> @@ -572,4 +584,10 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
> int tpm2_probe(struct tpm_chip *chip);
> ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip);
> int tpm2_find_cc(struct tpm_chip *chip, u32 cc);
> +int tpm2_init_space(struct tpm_space *space);
> +void tpm2_del_space(struct tpm_space *space);
> +int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc,
> + u8 *cmd);
> +int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
> + u32 cc, u8 *buf, size_t *bufsiz);
> #endif
> diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
> index 897902a..96121b3 100644
> --- a/drivers/char/tpm/tpm2-cmd.c
> +++ b/drivers/char/tpm/tpm2-cmd.c
> @@ -266,7 +266,7 @@ int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
> sizeof(cmd.params.pcrread_in.pcr_select));
> cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7);
>
> - rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
> TPM2_PCR_READ_RESP_BODY_SIZE,
> 0, "attempting to read a pcr value");
> if (rc == 0) {
> @@ -333,7 +333,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
> }
> }
>
> - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, 0,
> + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
> "attempting extend a PCR value");
>
> tpm_buf_destroy(&buf);
> @@ -382,7 +382,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max)
> cmd.header.in = tpm2_getrandom_header;
> cmd.params.getrandom_in.size = cpu_to_be16(num_bytes);
>
> - err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
> + err = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
> offsetof(struct tpm2_get_random_out,
> buffer),
> 0, "attempting get random");
> @@ -441,7 +441,7 @@ void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
>
> tpm_buf_append_u32(&buf, handle);
>
> - (void) tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, flags,
> + (void) tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, flags,
> "flushing context");
>
> tpm_buf_destroy(&buf);
> @@ -557,7 +557,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip,
> goto out;
> }
>
> - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 4, 0,
> + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, 0,
> "sealing data");
> if (rc)
> goto out;
> @@ -641,7 +641,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip,
> goto out;
> }
>
> - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 4, flags,
> + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 4, flags,
> "loading blob");
> if (!rc)
> *blob_handle = be32_to_cpup(
> @@ -693,7 +693,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip,
> options->blobauth /* hmac */,
> TPM_DIGEST_SIZE);
>
> - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 6, flags,
> + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 6, flags,
> "unsealing");
> if (rc > 0)
> rc = -EPERM;
> @@ -770,7 +770,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value,
> cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id);
> cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
>
> - rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd),
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd),
> TPM2_GET_TPM_PT_OUT_BODY_SIZE, 0, desc);
> if (!rc)
> *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value);
> @@ -805,7 +805,7 @@ static int tpm2_startup(struct tpm_chip *chip, u16 startup_type)
> cmd.header.in = tpm2_startup_header;
>
> cmd.params.startup_in.startup_type = cpu_to_be16(startup_type);
> - return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0,
> + return tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
> "attempting to start the TPM");
> }
>
> @@ -834,7 +834,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
> cmd.header.in = tpm2_shutdown_header;
> cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type);
>
> - rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0,
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
> "stopping the TPM");
>
> /* In places where shutdown command is sent there's no much we can do
> @@ -898,7 +898,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full)
> cmd.header.in = tpm2_selftest_header;
> cmd.params.selftest_in.full_test = full;
>
> - rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0,
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, 0,
> "continue selftest");
>
> /* At least some prototype chips seem to give RC_TESTING error
> @@ -949,7 +949,8 @@ static int tpm2_do_selftest(struct tpm_chip *chip)
> cmd.params.pcrread_in.pcr_select[1] = 0x00;
> cmd.params.pcrread_in.pcr_select[2] = 0x00;
>
> - rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0, NULL);
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0,
> + NULL);
> if (rc < 0)
> break;
>
> @@ -982,7 +983,7 @@ int tpm2_probe(struct tpm_chip *chip)
> cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100);
> cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1);
>
> - rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, 0, NULL);
> + rc = tpm_transmit_cmd(chip, NULL, &cmd, sizeof(cmd), 0, 0, NULL);
> if (rc < 0)
> return rc;
>
> @@ -1022,8 +1023,8 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
> tpm_buf_append_u32(&buf, TPM2_CC_FIRST);
> tpm_buf_append_u32(&buf, nr_commands);
>
> - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 9 + 4 * nr_commands,
> - 0, NULL);
> + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
> + 9 + 4 * nr_commands, 0, NULL);
> if (rc) {
> tpm_buf_destroy(&buf);
> goto out;
> @@ -1136,7 +1137,7 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip)
> tpm_buf_append_u32(&buf, 0);
> tpm_buf_append_u32(&buf, 1);
>
> - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 9, 0,
> + rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 9, 0,
> "get tpm pcr allocation");
> if (rc)
> goto out;
> diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
> new file mode 100644
> index 0000000..e955548
> --- /dev/null
> +++ b/drivers/char/tpm/tpm2-space.c
> @@ -0,0 +1,431 @@
> +/*
> + * Copyright (C) 2016 Intel Corporation
> + *
> + * Authors:
> + * Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> + *
> + * Maintained by: <tpmdd-devel@lists.sourceforge.net>
> + *
> + * This file contains TPM2 protocol implementations of the commands
> + * used by the kernel internally.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * as published by the Free Software Foundation; version 2
> + * of the License.
> + */
> +
> +#include <linux/gfp.h>
> +#include <asm/unaligned.h>
> +#include "tpm.h"
> +
> +enum tpm2_handle_types {
> + TPM2_HT_HMAC_SESSION = 0x02000000,
> + TPM2_HT_POLICY_SESSION = 0x03000000,
> + TPM2_HT_TRANSIENT = 0x80000000,
> +};
> +
> +struct tpm2_context {
> + __be64 sequence;
> + __be32 saved_handle;
> + __be32 hierarchy;
> + __be16 blob_size;
> +} __packed;
> +
> +int tpm2_init_space(struct tpm_space *space)
> +{
> + space->context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
> + if (!space->context_buf)
> + return -ENOMEM;
> +
> + return 0;
> +}
> +
> +void tpm2_del_space(struct tpm_space *space)
> +{
> + kfree(space->context_buf);
> +}
> +
> +static int tpm2_load_context(struct tpm_chip *chip, u8 *buf,
> + unsigned int *offset, u32 *handle)
> +{
> + struct tpm_buf tbuf;
> + struct tpm2_context *ctx;
> + unsigned int body_size;
> + int rc;
> +
> + rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD);
> + if (rc)
> + return rc;
> +
> + ctx = (struct tpm2_context *)&buf[*offset];
> + body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size);
> + tpm_buf_append(&tbuf, &buf[*offset], body_size);
> +
> + rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 4,
> + TPM_TRANSMIT_UNLOCKED, NULL);
> + if (rc < 0) {
> + dev_warn(&chip->dev, "%s: failed with a system error %d\n",
> + __func__, rc);
> + tpm_buf_destroy(&tbuf);
> + return -EFAULT;
> + } else if (rc > 0) {
> + dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
> + __func__, rc);
> + tpm_buf_destroy(&tbuf);
> + return -EFAULT;
> + }
> +
> + *handle = be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]);
> + *offset += body_size;
> +
> + tpm_buf_destroy(&tbuf);
> + return 0;
> +}
> +
> +static int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf,
> + unsigned int buf_size, unsigned int *offset)
> +{
> + struct tpm_buf tbuf;
> + unsigned int body_size;
> + int rc;
> +
> + rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE);
> + if (rc)
> + return rc;
> +
> + tpm_buf_append_u32(&tbuf, handle);
> +
> + rc = tpm_transmit_cmd(chip, NULL, tbuf.data, PAGE_SIZE, 0,
> + TPM_TRANSMIT_UNLOCKED, NULL);
> + if (rc < 0) {
> + dev_warn(&chip->dev, "%s: failed with a system error %d\n",
> + __func__, rc);
> + tpm_buf_destroy(&tbuf);
> + return -EFAULT;
> + } else if (tpm2_rc_value(rc) == TPM2_RC_REFERENCE_H0) {
> + tpm_buf_destroy(&tbuf);
> + return -ENOENT;
> + } else if (rc) {
> + dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n",
> + __func__, rc);
> + tpm_buf_destroy(&tbuf);
> + return -EFAULT;
> + }
> +
> + body_size = tpm_buf_length(&tbuf) - TPM_HEADER_SIZE;
> + if ((*offset + body_size) > buf_size) {
> + dev_warn(&chip->dev, "%s: out of backing storage\n", __func__);
> + tpm_buf_destroy(&tbuf);
> + return -ENOMEM;
> + }
> +
> + memcpy(&buf[*offset], &tbuf.data[TPM_HEADER_SIZE], body_size);
> + tpm2_flush_context_cmd(chip, handle, TPM_TRANSMIT_UNLOCKED);
> + *offset += body_size;
> + tpm_buf_destroy(&tbuf);
> + return 0;
> +}
> +
> +static void tpm2_flush_space(struct tpm_chip *chip)
> +{
> + struct tpm_space *space = &chip->work_space;
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++)
> + if (space->context_tbl[i] && ~space->context_tbl[i])
> + tpm2_flush_context_cmd(chip, space->context_tbl[i],
> + TPM_TRANSMIT_UNLOCKED);
> +}
> +
> +static int tpm2_load_space(struct tpm_chip *chip)
> +{
> + struct tpm_space *space = &chip->work_space;
> + unsigned int offset;
> + int i;
> + int rc;
> +
> + for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
> + if (!space->context_tbl[i])
> + continue;
> +
> + /* sanity check, should never happen */
> + if (~space->context_tbl[i]) {
> + dev_err(&chip->dev, "context table is inconsistent");
> + return -EFAULT;
> + }
> +
> + rc = tpm2_load_context(chip, space->context_buf, &offset,
> + &space->context_tbl[i]);
> + if (rc)
> + return rc;
> + }
> +
> + return 0;
> +}
> +
> +static bool tpm2_map_to_phandle(struct tpm_space *space, void *handle)
> +{
> + u32 vhandle = be32_to_cpup((__be32 *)handle);
> + u32 phandle;
> + int i;
> +
> + i = 0xFFFFFF - (vhandle & 0xFFFFFF);
> + if (i > ARRAY_SIZE(space->context_tbl) || !space->context_tbl[i])
> + return false;
> +
> + phandle = space->context_tbl[i];
> + *((__be32 *)handle) = cpu_to_be32(phandle);
> + return true;
> +}
> +
> +static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd)
> +{
> + struct tpm_space *space = &chip->work_space;
> + unsigned int nr_handles;
> + u32 attrs;
> + u32 *handle;
> + int i;
> +
> + i = tpm2_find_cc(chip, cc);
> + if (i < 0)
> + return -EINVAL;
> +
> + attrs = chip->cc_attrs_tbl[i];
> + nr_handles = (attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0);
> +
> + handle = (u32 *)&cmd[TPM_HEADER_SIZE];
> + for (i = 0; i < nr_handles; i++, handle++) {
> + if ((be32_to_cpu(*handle) & 0xFF000000) == TPM2_HT_TRANSIENT) {
> + if (!tpm2_map_to_phandle(space, handle))
> + return -EINVAL;
> + }
> + }
> +
> + return 0;
> +}
> +
> +int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc,
> + u8 *cmd)
> +{
> + int rc;
> +
> + if (!space)
> + return 0;
> +
> + memcpy(&chip->work_space.context_tbl, &space->context_tbl,
> + sizeof(space->context_tbl));
> + memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE);
> +
> + rc = tpm2_load_space(chip);
> + if (rc) {
> + tpm2_flush_space(chip);
> + return rc;
> + }
> +
> + rc = tpm2_map_command(chip, cc, cmd);
> + if (rc) {
> + tpm2_flush_space(chip);
> + return rc;
> + }
> +
> + return 0;
> +}
> +
> +static u32 tpm2_map_to_vhandle(struct tpm_space *space, u32 phandle, bool alloc)
> +{
> + int i;
> +
> + for (i = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
> + if (alloc) {
> + if (!space->context_tbl[i]) {
> + space->context_tbl[i] = phandle;
> + break;
> + }
> + } else if (space->context_tbl[i] == phandle)
> + break;
> + }
> +
> + if (i == ARRAY_SIZE(space->context_tbl))
> + return 0;
> +
> + return TPM2_HT_TRANSIENT | (0xFFFFFF - i);
> +}
> +
> +static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp,
> + size_t len)
> +{
> + struct tpm_space *space = &chip->work_space;
> + struct tpm_output_header *header = (void *)rsp;
> + u32 phandle;
> + u32 phandle_type;
> + u32 vhandle;
> + u32 attrs;
> + int i;
> +
> + if (be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS)
> + return 0;
> +
> + i = tpm2_find_cc(chip, cc);
> + /* sanity check, should never happen */
> + if (i < 0)
> + return -EFAULT;
> +
> + attrs = chip->cc_attrs_tbl[i];
> + if (!((attrs >> TPM2_CC_ATTR_RHANDLE) & 1))
> + return 0;
> +
> + phandle = be32_to_cpup((__be32 *)&rsp[TPM_HEADER_SIZE]);
> + phandle_type = phandle & 0xFF000000;
> +
> + switch (phandle_type) {
> + case TPM2_HT_TRANSIENT:
> + vhandle = tpm2_map_to_vhandle(space, phandle, true);
> + if (!vhandle)
> + goto out_no_slots;
> +
> + *(__be32 *)&rsp[TPM_HEADER_SIZE] = cpu_to_be32(vhandle);
> + break;
> + case TPM2_HT_HMAC_SESSION:
> + case TPM2_HT_POLICY_SESSION:
> + break;
> + default:
> + dev_err(&chip->dev, "%s: unknown handle 0x%08X\n",
> + __func__, phandle);
> + break;
> + };
> +
> + return 0;
> +out_no_slots:
> + tpm2_flush_context_cmd(chip, phandle, TPM_TRANSMIT_UNLOCKED);
> + dev_warn(&chip->dev, "%s: out of slots for 0x%08X\n", __func__,
> + phandle);
> + return -ENOMEM;
> +}
> +
> +struct tpm2_cap_handles {
> + u8 more_data;
> + __be32 capability;
> + __be32 count;
> + __be32 handles[];
> +} __packed;
> +
> +static int tpm2_map_response_body(struct tpm_chip *chip, u32 cc, u8 *rsp,
> + size_t len)
> +{
> + struct tpm_space *space = &chip->work_space;
> + struct tpm_output_header *header = (void *)rsp;
> + struct tpm2_cap_handles *data;
> + u32 phandle;
> + u32 phandle_type;
> + u32 vhandle;
> + int i;
> + int j;
> +
> + if (cc != TPM2_CC_GET_CAPABILITY ||
> + be32_to_cpu(header->return_code) != TPM2_RC_SUCCESS) {
> + return 0;
> + }
> +
> + if (len < TPM_HEADER_SIZE + 9)
> + return -EFAULT;
> +
> + data = (void *)&rsp[TPM_HEADER_SIZE];
> + if (be32_to_cpu(data->capability) != TPM2_CAP_HANDLES)
> + return 0;
> +
> + if (len != TPM_HEADER_SIZE + 9 + 4 * be32_to_cpu(data->count))
> + return -EFAULT;
> +
> + for (i = 0, j = 0; i < be32_to_cpu(data->count); i++) {
> + phandle = be32_to_cpup((__be32 *)&data->handles[i]);
> + phandle_type = phandle & 0xFF000000;
> +
> + switch (phandle_type) {
> + case TPM2_HT_TRANSIENT:
> + vhandle = tpm2_map_to_vhandle(space, phandle, false);
> + if (!vhandle)
> + break;
> +
> + data->handles[j] = cpu_to_be32(vhandle);
> + j++;
> + break;
> + case TPM2_HT_HMAC_SESSION:
> + case TPM2_HT_POLICY_SESSION:
> + data->handles[j] = cpu_to_be32(phandle);
> + j++;
> + break;
> + default:
> + dev_err(&chip->dev, "%s: unknown handle 0x%08X\n",
> + __func__, phandle);
> + break;
> + }
> +
> + }
> +
> + header->length = cpu_to_be32(TPM_HEADER_SIZE + 9 + 4 * j);
> + data->count = cpu_to_be32(j);
> + return 0;
> +}
> +
> +static int tpm2_save_space(struct tpm_chip *chip)
> +{
> + struct tpm_space *space = &chip->work_space;
> + unsigned int offset;
> + int i;
> + int rc;
> +
> + for (i = 0, offset = 0; i < ARRAY_SIZE(space->context_tbl); i++) {
> + if (!(space->context_tbl[i] && ~space->context_tbl[i]))
> + continue;
> +
> + rc = tpm2_save_context(chip, space->context_tbl[i],
> + space->context_buf, PAGE_SIZE,
> + &offset);
> + if (rc == -ENOENT) {
> + space->context_tbl[i] = 0;
> + continue;
> + } else if (rc)
> + return rc;
> +
> + space->context_tbl[i] = ~0;
> + }
> +
> + return 0;
> +}
> +
> +int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
> + u32 cc, u8 *buf, size_t *bufsiz)
> +{
> + struct tpm_output_header *header = (void *)buf;
> + int rc;
> +
> + if (!space)
> + return 0;
> +
> + rc = tpm2_map_response_header(chip, cc, buf, *bufsiz);
> + if (rc) {
> + tpm2_flush_space(chip);
> + return rc;
> + }
> +
> + rc = tpm2_map_response_body(chip, cc, buf, *bufsiz);
> + if (rc) {
> + tpm2_flush_space(chip);
> + return rc;
> + }
> +
> + rc = tpm2_save_space(chip);
> + if (rc) {
> + tpm2_flush_space(chip);
> + return rc;
> + }
> +
> + *bufsiz = be32_to_cpu(header->length);
> +
> + memcpy(&space->context_tbl, &chip->work_space.context_tbl,
> + sizeof(space->context_tbl));
> + memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE);
> +
> + return 0;
> +}
>
[toc] | [prev] | [next] | [standalone]
| From | James Bottomley <James.Bottomley@HansenPartnership.com> |
|---|---|
| Date | 2017-02-22 18:40 +0100 |
| Subject | Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces |
| Message-ID | <tdJ3s-5dB-15@gated-at.bofh.it> |
| In reply to | #1585604 |
On Tue, 2017-02-21 at 23:54 +0530, Nayna wrote: > > On 02/17/2017 12:55 AM, Jarkko Sakkinen wrote: > > Added an ability to virtualize TPM commands into an isolated > > context that we call a TPM space because the word context is > > already heavily used in the TPM specification. Both the handle > > areas and bodies (where necessary) are virtualized. > > > > The mechanism works by adding a new parameter struct tpm_space to > > the tpm_transmit() function. This new structure contains the list > > of virtual handles and a buffer of page size (currently) for > > backing storage. > > > > When tpm_transmit() is called with a struct tpm_space instance it > > will execute the following sequence: > > > > 1. Take locks. > > 2. Load transient objects from the backing storage by using > > ContextLoad > > and map virtual handles to physical handles. > > 3. Perform the transaction. > > 4. Save transient objects to backing storage by using ContextSave > > and > > map resulting physical handle to virtual handle if there is > > such. > > > > This commit does not implement virtualization support for hmac and > > policy sessions. > > > > If I have understood discussions correctly, I assume, that kernel TPM > operations will also be routed via RM. And I think that is not > happening now with these patches. > > Am I missing something ? Right at the moment the kernel use of tpm2 looks like acquire chip->tpm_mutex load key process key unload key release chip->tpm_mutex While it does this, there's no need for it to have a RM interface because what it does between the acquisition and drop of the mutex can't be seen by or have any effect on userspace (whether it uses the RM or not). So currently, the question doesn't arise, which is the situation you see. When the kernel needs to use resources that persisted beyond it dropping the chip->tpm_mutex (say using policy or audit sessions), then it would need to become a customer of the RM. James
[toc] | [prev] | [next] | [standalone]
| From | Ken Goldman <kgold@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-02-22 22:00 +0100 |
| Subject | Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces |
| Message-ID | <tdMb0-7mE-33@gated-at.bofh.it> |
| In reply to | #1586343 |
On 2/22/2017 12:39 PM, James Bottomley wrote: > > Right at the moment the kernel use of tpm2 looks like > > acquire chip->tpm_mutex > load key > process key > unload key > release chip->tpm_mutex The advantage to context save/ context load over load / flush is that load requires the parent(s). The parent chain may be long, a parent may require authorization, or authorization may be impossible because PCRs are no longer in the correct state. In TPM 1.2, there was a performance difference because load was an asymmetric key operation, but it's symmetric in TPM 2.0. > When the kernel needs to use resources that persisted beyond it > dropping the chip->tpm_mutex (say using policy or audit sessions), > then it would need to become a customer of the RM. BTW, use of an EK private key requires a policy session.
[toc] | [prev] | [next] | [standalone]
| From | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
|---|---|
| Date | 2017-02-22 22:20 +0100 |
| Subject | Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces |
| Message-ID | <tdMum-7Lo-17@gated-at.bofh.it> |
| In reply to | #1585604 |
On Tue, Feb 21, 2017 at 11:54:50PM +0530, Nayna wrote: > > > On 02/17/2017 12:55 AM, Jarkko Sakkinen wrote: > > Added an ability to virtualize TPM commands into an isolated context > > that we call a TPM space because the word context is already heavily > > used in the TPM specification. Both the handle areas and bodies (where > > necessary) are virtualized. > > > > The mechanism works by adding a new parameter struct tpm_space to the > > tpm_transmit() function. This new structure contains the list of virtual > > handles and a buffer of page size (currently) for backing storage. > > > > When tpm_transmit() is called with a struct tpm_space instance it will > > execute the following sequence: > > > > 1. Take locks. > > 2. Load transient objects from the backing storage by using ContextLoad > > and map virtual handles to physical handles. > > 3. Perform the transaction. > > 4. Save transient objects to backing storage by using ContextSave and > > map resulting physical handle to virtual handle if there is such. > > > > This commit does not implement virtualization support for hmac and > > policy sessions. > > > > If I have understood discussions correctly, I assume, that kernel TPM > operations will also be routed via RM. And I think that is not happening now > with these patches. > > Am I missing something ? > > Thanks & Regards, > - Nayna Nope. It's not in the scope of this patch set and there are not kernel use cases at the moment that would require it. /Jarkko
[toc] | [prev] | [next] | [standalone]
| From | Ken Goldman <kgold@linux.vnet.ibm.com> |
|---|---|
| Date | 2017-02-22 22:30 +0100 |
| Subject | Re: [tpmdd-devel] [PATCH v2 4/7] tpm: infrastructure for TPM spaces |
| Message-ID | <tdME1-7PD-3@gated-at.bofh.it> |
| In reply to | #1585604 |
On 2/21/2017 1:24 PM, Nayna wrote: > > [snip] >> >> 1. Take locks. >> 2. Load transient objects from the backing storage by using ContextLoad >> and map virtual handles to physical handles. >> 3. Perform the transaction. >> 4. Save transient objects to backing storage by using ContextSave and >> map resulting physical handle to virtual handle if there is such. >> >> This commit does not implement virtualization support for hmac and >> policy sessions. >> > > If I have understood discussions correctly, I assume, that kernel TPM > operations will also be routed via RM. And I think that is not happening > now with these patches. There is one corner case that requires kernel operations to go through the RM, and that's the session context regapping. If the kernel did not go through the RM, it could not handle TPM_RC_CONTEXT_GAP. I believe that kernel operations such as PCR extend, that don't require sessions, do not have to go through the RM. Kernel operations that use objects perhaps can bypass the RM as long as there is a lock and the kernel also context saves objects and returns the TPM to the empty state before it releases the lock. Finally, I suspect that the RM should reserve 3 sessions for kernel operations, so the kernel can't block because user space applications have filled all the session slots.
[toc] | [prev] | [next] | [standalone]
| From | James Bottomley <James.Bottomley@HansenPartnership.com> |
|---|---|
| Date | 2017-02-24 14:00 +0100 |
| Subject | Re: [PATCH v2 4/7] tpm: infrastructure for TPM spaces |
| Message-ID | <tenDC-eO-63@gated-at.bofh.it> |
| In reply to | #1582888 |
On Thu, 2017-02-16 at 21:25 +0200, Jarkko Sakkinen wrote: > Added an ability to virtualize TPM commands into an isolated context > that we call a TPM space because the word context is already heavily > used in the TPM specification. Both the handle areas and bodies > (where > necessary) are virtualized. > > The mechanism works by adding a new parameter struct tpm_space to the > tpm_transmit() function. This new structure contains the list of > virtual > handles and a buffer of page size (currently) for backing storage. > > When tpm_transmit() is called with a struct tpm_space instance it > will > execute the following sequence: > > 1. Take locks. > 2. Load transient objects from the backing storage by using > ContextLoad > and map virtual handles to physical handles. > 3. Perform the transaction. > 4. Save transient objects to backing storage by using ContextSave and > map resulting physical handle to virtual handle if there is such. > > This commit does not implement virtualization support for hmac and > policy sessions. > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> For patches 1-4 you can add Reviewed-by: James Bottomley <James.Bottomley@HansenPartnership.com> Just re-running a build with the latest kernel for my laptop to add tested by. James
[toc] | [prev] | [next] | [standalone]
| From | Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
|---|---|
| Date | 2017-02-24 18:10 +0100 |
| Subject | Re: [PATCH v2 4/7] tpm: infrastructure for TPM spaces |
| Message-ID | <terxv-3hc-3@gated-at.bofh.it> |
| In reply to | #1587596 |
On Fri, Feb 24, 2017 at 07:53:22AM -0500, James Bottomley wrote: > On Thu, 2017-02-16 at 21:25 +0200, Jarkko Sakkinen wrote: > > Added an ability to virtualize TPM commands into an isolated context > > that we call a TPM space because the word context is already heavily > > used in the TPM specification. Both the handle areas and bodies > > (where > > necessary) are virtualized. > > > > The mechanism works by adding a new parameter struct tpm_space to the > > tpm_transmit() function. This new structure contains the list of > > virtual > > handles and a buffer of page size (currently) for backing storage. > > > > When tpm_transmit() is called with a struct tpm_space instance it > > will > > execute the following sequence: > > > > 1. Take locks. > > 2. Load transient objects from the backing storage by using > > ContextLoad > > and map virtual handles to physical handles. > > 3. Perform the transaction. > > 4. Save transient objects to backing storage by using ContextSave and > > map resulting physical handle to virtual handle if there is such. > > > > This commit does not implement virtualization support for hmac and > > policy sessions. > > > > Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> > > For patches 1-4 you can add > > Reviewed-by: James Bottomley <James.Bottomley@HansenPartnership.com> > > Just re-running a build with the latest kernel for my laptop to add > tested by. > > James Thank you! /Jarkko
[toc] | [prev] | [standalone]
Page 2 of 2 — ← Prev page 1 [2]
Back to top | Article view | linux.kernel
csiph-web