[U-Boot] [PATCH v4 00/32] Introduce TPMv2.0 support

Miquel Raynal
2018-05-15T09:56:56Z

Current U-Boot supports TPM v1.2 specification. The new specification
(v2.0) is not backward compatible and renames/introduces several
functions. This series introduces the support for TPMv2.x chips.

First, some cleaning is done in TPM-related code. Then, the code is
split in two categories: generic code (common for both specifications)
and specific code (only used by one specification).

Then, basic functionalities are introduced one by one for the v2.x
specification. TPMv1 vs TPMv2 commands/support distinction is done with
Kconfig options. Drivers of only one specification can be selected at a
time.

A new SPI driver following the TPM v2.x specification is introduced. It
has been tested on a ST TPM but should be usable with others v2.0
compliant chips.

Finally a full Python test suite is added, as well as a Sandbox driver.
Regular testing may be done through the test/py/ framework when using
real hardware as well as the Sandbox driver. The following test has run
more than 300 times without failing with my setup:

test/py/test.py --bd <board> -k tpm2

Available commands for v2.0 TPMs are:
* STARTUP
* SELF TEST
* CLEAR
* PCR EXTEND
* PCR READ
* GET CAPABILITY
* DICTIONARY ATTACK LOCK RESET
* DICTIONARY ATTACK CHANGE PARAMETERS
* HIERARCHY CHANGE AUTH

Two commands have been written but could not be tested (unsupported by
the TPM chosen):
* PCR CHANGE AUTH POLICY
* PCR CHANGE AUTH VALUE

With this set of function, minimal TPMv2.0 handling is possible with the
following sequence.

* First, initialize the TPM stack in U-Boot.

> tpm init

* Then send the STARTUP command to the TPM. The flag is slightly
different between the revisions.

> tpm startup TPM2_SU_CLEAR

* To enable full TPM capabilities, continue the tests (or do them all
again). It seems like self_test_full always waits for the operation to
finish, while continue_self_test returns a busy state if called to
early.

> tpm self_test full
> tpm self_test continue

* Manage passwords (force_clear also resets a lot of internal stuff).
Olderly, TAKE OWNERSHIP == CLEAR + CHANGE AUTH. LOCKOUT is an example,
ENDORSEMENT and PLATFORM hierarchies are available too:

> tpm clear TPM2_RH_LOCKOUT [<pw>]
> tpm change_auth TPM2_RH_LOCKOUT <new_pw> [<old_pw>]

* Dictionary Attack Mitigation (DAM) parameters can be changed. It is
possible to reset the failure counter and disable the lockout (values
erased after a CLEAR). It is then possible to check the parameters
have been correctly applied.

> tpm dam_reset [<pw>]
> tpm dam_parameters 0xffff 1 0 [<pw>]
> tpm get_capability 0x0006 0x020e 0x4000000 4

* PCR policy may be changed (untested).
PCR can be extended (no protection against packet replay yet).
PCR can be read (the counter with the number of "extensions" is also
given).

> tpm pcr_setauthpolicy 0 12345678901234567890123456789012 [<pw>]
> tpm pcr_read 0 0x4000000
> tpm pcr_extend 0 0x4000000

Thanks,
MiquÃ¨l

Changes since v3:
=================
* Added Simon Glass's RB tags.
* Moved all the small fixes about lines, alignments, spellings, etc out
of the big commit splitting the TPM code structure. Multiple commits
have been made for these changes. Now the split is still done in one
commit, but it is supposed to be only code moves and headers changes.
* Used map_sysmem() calls to let Sandbox run TPM commands instead of my
hack (allocating memory on the go).
* Updated the documentation to use the new way of declaring parameters:
s/@param x: y/@x: y/.
* Added two parameters in the chip private structure to store the number
of PCRs and the minimum number of bytes needed to address one in a TPM
command. This should fit all the TIS TPM2 compliant modules.
* The above change removes some (wrongly) hardcoded values.
* Changed the error path as suggested in tpm2_get_capability().
* Minor rephrasing.
* Explained in tpm2_get_capability() the offset '19'.
* Removed useless reset of rx_buf[0] in tpm_tis_spi_xfer().
* Changed the way spi_xfer return code is checked: error out on any
value != 0 instead of just negative ones.
* Removed unused functions flagged __maybe_unused as well as well as the
__maybe_unused flags themselves when not needed.
* Simplified the validity check of the GPIO as suggested.
* Updated the compatible property for the SPI modules (as well as the
bindings docuementation) to be simply "tis,tpm2-spi" which should work
with most compliant chips. Data is linked to this generic compatible
in the TPM driver, other values may be added if needed in the future
to fit other chips that would use different values than the current
ones (used by Infineon SLB 9670 and ST ST33TPHF20 modules, for
instance).

Changes since v2:
=================
* Wrote a full sandbox driver that passes _all_ the Python tests.
* Added changes in the library to support running in Sandbox.
* Did not rename the former I2C driver. Instead, will prefix new ones
by "tpm2_" to make the distinction.
* Updated the Kconfig menu to have a clear separated view of the
different drivers/specifications. CMD_TPM is now selected by a
TPM_DRIVER_SELECTED boolean that is selected automatically when one
driver at least is selected. One driver can only be selected if only
one specification was precised (1.x or 2.x).
* Removed the styling fixes in the TPMv1.x command file as another one
will be created.
* Removed the buffer length variable renaming as there is no need for
it anymore.
* Split the whole architecture: for commands and library files, one
tpm-common.c file plus one tpm-v<x>.c per specification. Same split
for the header files. Some prototypes have been moved to
lib/tpm-utils.h and cmd/tpm-user-utils.h depending on their use.
This removed the need for an initialization with the right
specification and the boilerplate coming with it.
* Commented all the TPMv2 enumerations.
* Renamed the macro U<XX>_TO_ARRAY into tpm_u<xx> as suggested.
* Dropped the buffer length name change as the files are split, there
is no more need for such a rename.
* Added RB/AB tags.
* Used the new logging mechanism.
* Added documentation (bindings) for both drivers.
* Add the reset by GPIO in the SPI TPMv2.0 driver.
* Added a delay in the tests between the pcr_extend and the read_pcr.
* Ran the test suite a saw random errors sometimes, with a "LIB_ERROR".
I wonder what produces these. Added traces to try to detect where it
comes from.
* Some checkpatch.pl warnings have been left intentionally.

Changes since v1:
=================
* Complete test suite for the TPMv2 commands in test/py/.
* s/STRINGIFY<X>/U<X>_TO_ARRAY/ (the macros had nothing to do with
actual "stringification").
* Changed/fixed some comments.

Miquel Raynal (32):
tpm: remove redundant blank line
tpm: remove extra spaces between a function and its opening bracket
tpm: substitute deprecated uint<x>_t types with their u<x> equivalent
tpm: align arguments with open parenthesis
tpm: use the BIT() macro where applicable
tpm: fix spelling
tpm: add extra blank lines between declarations and code
tpm: add Revision ID field in the chip structure
tpm: prepare introduction of TPMv2.x support in Kconfig
tpm: disociate TPMv1.x specific and generic code
tpm: add missing parameter in private data structure description
tpm: prepare support for TPMv2.x commands
tpm: add macros to enhance TPM commands readability
tpm: add possible traces to analyze buffers returned by the TPM
tpm: report driver error code to upper layer
tpm: add TPM2_Startup command support
tpm: add TPM2_SelfTest command support
tpm: add TPM2_Clear command support
tpm: add TPM2_PCR_Extend command support
tpm: add TPM2_PCR_Read command support
tpm: add TPM2_GetCapability command support
tpm: add dictionary attack mitigation commands support
tpm: add TPM2_HierarchyChangeAuth command support
tpm: add PCR authentication commands support
tpm: add support for TPMv2.x SPI modules
tpm: add the possibility to reset the chip with a gpio
doc: device-tree-bindings: add TIS TPMv2.0 SPI module info
test/py: add TPMv2.x test suite
tpm: add a Sandbox TPMv2.x driver
doc: device-tree-bindings: add Sandbox TPMv2.0 module info
sandbox: dts: add Sandbox TPMv2.x node
configs: add TPMv2.x support in Sandbox

arch/sandbox/dts/sandbox.dts | 4 +
arch/sandbox/dts/sandbox64.dts | 4 +
arch/sandbox/dts/test.dts | 4 +
cmd/Kconfig | 24 +-
cmd/Makefile | 4 +-
cmd/tpm-common.c | 289 +++++++++++
cmd/tpm-user-utils.h | 25 +
cmd/{tpm.c => tpm-v1.c} | 488 ++++--------------
cmd/tpm-v2.c | 389 ++++++++++++++
cmd/tpm_test.c | 2 +-
configs/sandbox64_defconfig | 1 +
configs/sandbox_defconfig | 1 +
configs/sandbox_flattree_defconfig | 1 +
configs/sandbox_noblk_defconfig | 1 +
configs/sandbox_spl_defconfig | 1 +
doc/device-tree-bindings/tpm2/sandbox.txt | 11 +
doc/device-tree-bindings/tpm2/tis-tpm2-spi.txt | 18 +
drivers/tpm/Kconfig | 83 ++-
drivers/tpm/Makefile | 3 +
drivers/tpm/tpm-uclass.c | 6 +-
drivers/tpm/tpm2_tis_sandbox.c | 626 +++++++++++++++++++++++
drivers/tpm/tpm2_tis_spi.c | 681 +++++++++++++++++++++++++
drivers/tpm/tpm_atmel_twi.c | 2 +-
drivers/tpm/tpm_tis.h | 1 +
drivers/tpm/tpm_tis_infineon.c | 2 +-
drivers/tpm/tpm_tis_lpc.c | 2 +-
drivers/tpm/tpm_tis_sandbox.c | 2 +-
drivers/tpm/tpm_tis_st33zp24_i2c.c | 2 +-
drivers/tpm/tpm_tis_st33zp24_spi.c | 2 +-
include/tpm-common.h | 218 ++++++++
include/{tpm.h => tpm-v1.h} | 296 ++---------
include/tpm-v2.h | 262 ++++++++++
lib/Makefile | 4 +-
lib/tpm-common.c | 198 +++++++
lib/tpm-utils.h | 102 ++++
lib/{tpm.c => tpm-v1.c} | 600 +++++++---------------
lib/tpm-v2.c | 419 +++++++++++++++
test/py/tests/test_tpm2.py | 234 +++++++++
38 files changed, 3936 insertions(+), 1076 deletions(-)
create mode 100644 cmd/tpm-common.c
create mode 100644 cmd/tpm-user-utils.h
rename cmd/{tpm.c => tpm-v1.c} (64%)
create mode 100644 cmd/tpm-v2.c
create mode 100644 doc/device-tree-bindings/tpm2/sandbox.txt
create mode 100644 doc/device-tree-bindings/tpm2/tis-tpm2-spi.txt
create mode 100644 drivers/tpm/tpm2_tis_sandbox.c
create mode 100644 drivers/tpm/tpm2_tis_spi.c
create mode 100644 include/tpm-common.h
rename include/{tpm.h => tpm-v1.h} (60%)
create mode 100644 include/tpm-v2.h
create mode 100644 lib/tpm-common.c
create mode 100644 lib/tpm-utils.h
rename lib/{tpm.c => tpm-v1.c} (59%)
create mode 100644 lib/tpm-v2.c
create mode 100644 test/py/tests/test_tpm2.py

--
2.14.1