Skip to content

Commit

Permalink
Merge tag 'tpmdd-next-6.15-rc1' of git://git.kernel.org/pub/scm/linux…
Browse files Browse the repository at this point in the history
…/kernel/git/jarkko/linux-tpmdd

Pull tpm updates from Jarkko Sakkinen:
 "This contains a new driver: a TPM FF-A driver.

  FF comes from Firmware Framework, and A comes from Arm's A-profile.
  FF-A is essentially a standard mechanism to communicate with TrustZone
  apps such as TPM.

  Other than that, this includes a pile of fixes and small improvments"

* tag 'tpmdd-next-6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd:
  tpm: Make chip->{status,cancel,req_canceled} opt
  MAINTAINERS: TPM DEVICE DRIVER: add missing includes
  tpm: End any active auth session before shutdown
  Documentation: tpm: Add documentation for the CRB FF-A interface
  tpm_crb: Add support for the ARM FF-A start method
  ACPICA: Add start method for ARM FF-A
  tpm_crb: Clean-up and refactor check for idle support
  tpm_crb: ffa_tpm: Implement driver compliant to CRB over FF-A
  tpm/tpm_ftpm_tee: fix struct ftpm_tee_private documentation
  tpm, tpm_tis: Workaround failed command reception on Infineon devices
  tpm, tpm_tis: Fix timeout handling when waiting for TPM status
  tpm: Convert warn to dbg in tpm2_start_auth_session()
  tpm: Lazily flush auth session when getting random data
  tpm: ftpm_tee: remove incorrect of_match_ptr annotation
  tpm: do not start chip while suspended
  • Loading branch information
Linus Torvalds committed Mar 28, 2025
2 parents f8a4eba + 980a573 commit 15cb9a2
Show file tree
Hide file tree
Showing 18 changed files with 590 additions and 58 deletions.
1 change: 1 addition & 0 deletions Documentation/security/tpm/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ Trusted Platform Module documentation
tpm_vtpm_proxy
xen-tpmfront
tpm_ftpm_tee
tpm_ffa_crb
65 changes: 65 additions & 0 deletions Documentation/security/tpm/tpm_ffa_crb.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
.. SPDX-License-Identifier: GPL-2.0
========================
TPM CRB over FF-A Driver
========================

The TPM Command Response Buffer (CRB) interface is a standard TPM interface
defined in the TCG PC Client Platform TPM Profile (PTP) Specification [1]_.
The CRB provides a structured set of control registers a client uses when
interacting with a TPM as well as a data buffer for storing TPM commands and
responses. A CRB interface can be implemented in:

- hardware registers in a discrete TPM chip

- in memory for a TPM running in isolated environment where shared memory
allows a client to interact with the TPM

The Firmware Framework for Arm A-profile (FF-A) [2]_ is a specification
that defines interfaces and protocols for the following purposes:

- Compartmentalize firmware into software partitions that run in the Arm
Secure world environment (also know as TrustZone)

- Provide a standard interface for software components in the Non-secure
state, for example OS and Hypervisors, to communicate with this firmware.

A TPM can be implemented as an FF-A secure service. This could be a firmware
TPM or could potentially be a TPM service that acts as a proxy to a discrete
TPM chip. An FF-A based TPM abstracts hardware details (e.g. bus controller
and chip selects) away from the OS and can protect locality 4 from access
by an OS. The TCG-defined CRB interface is used by clients to interact
with the TPM service.

The Arm TPM Service Command Response Buffer Interface Over FF-A [3]_
specification defines FF-A messages that can be used by a client to signal
when updates have been made to the CRB.

How the Linux CRB driver interacts with FF-A is summarized below:

- The tpm_crb_ffa driver registers with the FF-A subsystem in the kernel
with an architected TPM service UUID defined in the CRB over FF-A spec.

- If a TPM service is discovered by FF-A, the probe() function in the
tpm_crb_ffa driver runs, and the driver initializes.

- The probing and initialization of the Linux CRB driver is triggered
by the discovery of a TPM advertised via ACPI. The CRB driver can
detect the type of TPM through the ACPI 'start' method. The start
method for Arm FF-A was defined in TCG ACPI v1.4 [4]_.

- When the CRB driver performs its normal functions such as signaling 'start'
and locality request/relinquish it invokes the tpm_crb_ffa_start() funnction
in the tpm_crb_ffa driver which handles the FF-A messaging to the TPM.

References
==========

.. [1] **TCG PC Client Platform TPM Profile (PTP) Specification**
https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
.. [2] **Arm Firmware Framework for Arm A-profile (FF-A)**
https://developer.arm.com/documentation/den0077/latest/
.. [3] **Arm TPM Service Command Response Buffer Interface Over FF-A**
https://developer.arm.com/documentation/den0138/latest/
.. [4] **TCG ACPI Specification**
https://trustedcomputinggroup.org/resource/tcg-acpi-specification/
2 changes: 2 additions & 0 deletions MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -24187,6 +24187,8 @@ Q: https://patchwork.kernel.org/project/linux-integrity/list/
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git
F: Documentation/devicetree/bindings/tpm/
F: drivers/char/tpm/
F: include/linux/tpm*.h
F: include/uapi/linux/vtpm_proxy.h
F: tools/testing/selftests/tpm2/

TPS546D24 DRIVER
Expand Down
9 changes: 9 additions & 0 deletions drivers/char/tpm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,15 @@ config TCG_CRB
from within Linux. To compile this driver as a module, choose
M here; the module will be called tpm_crb.

config TCG_ARM_CRB_FFA
tristate "TPM CRB over Arm FF-A Transport"
depends on ARM_FFA_TRANSPORT && TCG_CRB
default TCG_CRB
help
If the Arm FF-A transport is used to access the TPM say Yes.
To compile this driver as a module, choose M here; the module
will be called tpm_crb_ffa.

config TCG_VTPM_PROXY
tristate "VTPM Proxy Interface"
depends on TCG_TPM
Expand Down
1 change: 1 addition & 0 deletions drivers/char/tpm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o
obj-$(CONFIG_TCG_TIS_ST33ZP24) += st33zp24/
obj-$(CONFIG_TCG_XEN) += xen-tpmfront.o
obj-$(CONFIG_TCG_CRB) += tpm_crb.o
obj-$(CONFIG_TCG_ARM_CRB_FFA) += tpm_crb_ffa.o
obj-$(CONFIG_TCG_VTPM_PROXY) += tpm_vtpm_proxy.o
obj-$(CONFIG_TCG_FTPM_TEE) += tpm_ftpm_tee.o
6 changes: 6 additions & 0 deletions drivers/char/tpm/tpm-chip.c
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ int tpm_try_get_ops(struct tpm_chip *chip)
goto out_ops;

mutex_lock(&chip->tpm_mutex);

/* tmp_chip_start may issue IO that is denied while suspended */
if (chip->flags & TPM_CHIP_FLAG_SUSPENDED)
goto out_lock;

rc = tpm_chip_start(chip);
if (rc)
goto out_lock;
Expand Down Expand Up @@ -300,6 +305,7 @@ int tpm_class_shutdown(struct device *dev)
down_write(&chip->ops_sem);
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
if (!tpm_chip_start(chip)) {
tpm2_end_auth_session(chip);
tpm2_shutdown(chip, TPM2_SU_CLEAR);
tpm_chip_stop(chip);
}
Expand Down
37 changes: 27 additions & 10 deletions drivers/char/tpm/tpm-interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,30 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
}
EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);

static void tpm_chip_cancel(struct tpm_chip *chip)
{
if (!chip->ops->cancel)
return;

chip->ops->cancel(chip);
}

static u8 tpm_chip_status(struct tpm_chip *chip)
{
if (!chip->ops->status)
return 0;

return chip->ops->status(chip);
}

static bool tpm_chip_req_canceled(struct tpm_chip *chip, u8 status)
{
if (!chip->ops->req_canceled)
return false;

return chip->ops->req_canceled(chip, status);
}

static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz)
{
struct tpm_header *header = buf;
Expand Down Expand Up @@ -104,12 +128,12 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz)

stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
do {
u8 status = chip->ops->status(chip);
u8 status = tpm_chip_status(chip);
if ((status & chip->ops->req_complete_mask) ==
chip->ops->req_complete_val)
goto out_recv;

if (chip->ops->req_canceled(chip, status)) {
if (tpm_chip_req_canceled(chip, status)) {
dev_err(&chip->dev, "Operation Canceled\n");
return -ECANCELED;
}
Expand All @@ -118,7 +142,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip, void *buf, size_t bufsiz)
rmb();
} while (time_before(jiffies, stop));

chip->ops->cancel(chip);
tpm_chip_cancel(chip);
dev_err(&chip->dev, "Operation Timed out\n");
return -ETIME;

Expand Down Expand Up @@ -445,18 +469,11 @@ int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
if (!chip)
return -ENODEV;

/* Give back zero bytes, as TPM chip has not yet fully resumed: */
if (chip->flags & TPM_CHIP_FLAG_SUSPENDED) {
rc = 0;
goto out;
}

if (chip->flags & TPM_CHIP_FLAG_TPM2)
rc = tpm2_get_random(chip, out, max);
else
rc = tpm1_get_random(chip, out, max);

out:
tpm_put_ops(chip);
return rc;
}
Expand Down
1 change: 0 additions & 1 deletion drivers/char/tpm/tpm2-cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -359,7 +359,6 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
} while (retries-- && total < max);

tpm_buf_destroy(&buf);
tpm2_end_auth_session(chip);

return total ? total : -EIO;
out:
Expand Down
2 changes: 1 addition & 1 deletion drivers/char/tpm/tpm2-sessions.c
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,7 @@ int tpm2_start_auth_session(struct tpm_chip *chip)
int rc;

if (chip->auth) {
dev_warn_once(&chip->dev, "auth session is active\n");
dev_dbg_once(&chip->dev, "auth session is active\n");
return 0;
}

Expand Down
Loading

0 comments on commit 15cb9a2

Please sign in to comment.