2018-10-17 06:50:52

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 00/21] tpm: separate tpm 1.x and tpm 2.x commands

This patch series provides initial separation of tpm 1.x and tpm 2.x
commands, in foresight that the tpm 1.x chips will eventually phase out
and can be compiled out for modern systems.
A new file is added tpm1-cmd.c that contains tpm 1.x specific commands.
In addition, tpm 1.x commands are now implemented using tpm_buf
structure and instead of tpm_cmd_t construct. The latter is now removed.

Note: my tpm 1.x HW availability is limited hence some more testing is needed.

This series also contains two trivial cleanups and addition of new
commands by TCG spec 1.36, now supported on new Intet's platforms.

V6: 1. Dropping tpm: move pcr extend code to tpm2-cmd.c and rebasing code over that change
2. Trivial fixes in kdoc and header

Tomas Winkler (21):
tpm2: add new tpm2 commands according to TCG 1.36
tpm: sort objects in the Makefile
tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c
tpm: add tpm_calc_ordinal_duration() wrapper
tpm: factor out tpm_get_timeouts()
tpm: move tpm1_pcr_extend to tpm1-cmd.c
tpm: move tpm_getcap to tpm1-cmd.c
tpm: factor out tpm1_get_random into tpm1-cmd.c
tpm: move tpm 1.x selftest code from tpm-interface.c tpm1-cmd.c
tpm: factor out tpm 1.x pm suspend flow into tpm1-cmd.c
tpm: factor out tpm_startup function
tpm: add tpm_auto_startup() into tpm-interface.c
tpm: tpm-interface.c drop unused macros
tpm: tpm-space.c remove unneeded semicolon
tpm: tpm1: rewrite tpm1_get_random() using tpm_buf structure
tpm1: implement tpm1_pcr_read_dev() using tpm_buf structure
tmp1: rename tpm1_pcr_read_dev to tpm1_pcr_read()
tpm1: reimplement SAVESTATE using tpm_buf
tpm1: reimplement tpm1_continue_selftest() using tpm_buf
tpm: use u32 instead of int for PCR index

drivers/char/tpm/Makefile | 16 +-
drivers/char/tpm/st33zp24/st33zp24.c | 2 +-
drivers/char/tpm/tpm-chip.c | 11 +-
drivers/char/tpm/tpm-interface.c | 817 +++--------------------------------
drivers/char/tpm/tpm-sysfs.c | 52 +--
drivers/char/tpm/tpm.h | 97 ++---
drivers/char/tpm/tpm1-cmd.c | 781 +++++++++++++++++++++++++++++++++
drivers/char/tpm/tpm2-cmd.c | 301 +++++++------
drivers/char/tpm/tpm2-space.c | 2 +-
drivers/char/tpm/tpm_i2c_nuvoton.c | 10 +-
drivers/char/tpm/tpm_tis_core.c | 10 +-
include/linux/tpm.h | 11 +-
security/integrity/ima/ima_crypto.c | 5 +-
13 files changed, 1081 insertions(+), 1034 deletions(-)
create mode 100644 drivers/char/tpm/tpm1-cmd.c

--
2.14.4



2018-10-17 06:51:06

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 03/20] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

Factor out TPM 1.x commands calculation into tpm1-cmd.c file.
and change the prefix from tpm_ to tpm1_.
No functional change is done here.

Signed-off-by: Tomas Winkler <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---
V2-V3: Rebase
V4: 1. Remove the licence statement it's already covered by SPDX.
2. Add kdoc to tpm1_calc_ordinal_duration().
V5: Adjust the kdoc to the new standard.
V6: Resend
drivers/char/tpm/Makefile | 1 +
drivers/char/tpm/st33zp24/st33zp24.c | 2 +-
drivers/char/tpm/tpm-interface.c | 284 +-------------------------------
drivers/char/tpm/tpm.h | 2 +-
drivers/char/tpm/tpm1-cmd.c | 310 +++++++++++++++++++++++++++++++++++
drivers/char/tpm/tpm_i2c_nuvoton.c | 10 +-
drivers/char/tpm/tpm_tis_core.c | 2 +-
drivers/char/tpm/xen-tpmfront.c | 2 +-
8 files changed, 322 insertions(+), 291 deletions(-)
create mode 100644 drivers/char/tpm/tpm1-cmd.c

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index efc785053627..a01c4cab902a 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -7,6 +7,7 @@ tpm-y := tpm-chip.o
tpm-y += tpm-dev-common.o
tpm-y += tpm-dev.o
tpm-y += tpm-interface.o
+tpm-y += tpm1-cmd.o
tpm-y += tpm2-cmd.o
tpm-y += tpmrm-dev.o
tpm-y += tpm2-space.o
diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
index abd675bec88c..16be974955ea 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -430,7 +430,7 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));

ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- tpm_calc_ordinal_duration(chip, ordinal),
+ tpm1_calc_ordinal_duration(chip, ordinal),
&tpm_dev->read_queue, false);
if (ret < 0)
goto out_err;
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 95db630dd722..21c6ed2a6bc1 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -33,7 +33,6 @@

#include "tpm.h"

-#define TPM_MAX_ORDINAL 243
#define TSC_MAX_ORDINAL 12
#define TPM_PROTECTED_COMMAND 0x00
#define TPM_CONNECTION_COMMAND 0x40
@@ -48,285 +47,6 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
MODULE_PARM_DESC(suspend_pcr,
"PCR to use for dummy writes to facilitate flush on suspend.");

-/*
- * Array with one entry per ordinal defining the maximum amount
- * of time the chip could take to return the result. The ordinal
- * designation of short, medium or long is defined in a table in
- * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
- * values of the SHORT, MEDIUM, and LONG durations are retrieved
- * from the chip during initialization with a call to tpm_get_timeouts.
- */
-static const u8 tpm_ordinal_duration[TPM_MAX_ORDINAL] = {
- TPM_UNDEFINED, /* 0 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 5 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 10 */
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_LONG,
- TPM_LONG,
- TPM_MEDIUM, /* 15 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_LONG,
- TPM_SHORT, /* 20 */
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_SHORT, /* 25 */
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_MEDIUM, /* 30 */
- TPM_LONG,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT, /* 35 */
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_MEDIUM, /* 40 */
- TPM_LONG,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT, /* 45 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_LONG,
- TPM_MEDIUM, /* 50 */
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 55 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_MEDIUM, /* 60 */
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_MEDIUM, /* 65 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 70 */
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 75 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_LONG, /* 80 */
- TPM_UNDEFINED,
- TPM_MEDIUM,
- TPM_LONG,
- TPM_SHORT,
- TPM_UNDEFINED, /* 85 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 90 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED, /* 95 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_MEDIUM, /* 100 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 105 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 110 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT, /* 115 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_LONG, /* 120 */
- TPM_LONG,
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_SHORT,
- TPM_SHORT, /* 125 */
- TPM_SHORT,
- TPM_LONG,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT, /* 130 */
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_UNDEFINED, /* 135 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 140 */
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 145 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 150 */
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED, /* 155 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 160 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 165 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_LONG, /* 170 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 175 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_MEDIUM, /* 180 */
- TPM_SHORT,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_MEDIUM, /* 185 */
- TPM_SHORT,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 190 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 195 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 200 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT,
- TPM_SHORT, /* 205 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_MEDIUM, /* 210 */
- TPM_UNDEFINED,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_MEDIUM,
- TPM_UNDEFINED, /* 215 */
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT,
- TPM_SHORT, /* 220 */
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_SHORT,
- TPM_UNDEFINED, /* 225 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 230 */
- TPM_LONG,
- TPM_MEDIUM,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED, /* 235 */
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_UNDEFINED,
- TPM_SHORT, /* 240 */
- TPM_UNDEFINED,
- TPM_MEDIUM,
-};
-
-/*
- * Returns max number of jiffies to wait
- */
-unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
- u32 ordinal)
-{
- int duration_idx = TPM_UNDEFINED;
- int duration = 0;
-
- /*
- * We only have a duration table for protected commands, where the upper
- * 16 bits are 0. For the few other ordinals the fallback will be used.
- */
- if (ordinal < TPM_MAX_ORDINAL)
- duration_idx = tpm_ordinal_duration[ordinal];
-
- if (duration_idx != TPM_UNDEFINED)
- duration = chip->duration[duration_idx];
- if (duration <= 0)
- return 2 * 60 * HZ;
- else
- return duration;
-}
-EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
-
static int tpm_validate_command(struct tpm_chip *chip,
struct tpm_space *space,
const u8 *cmd,
@@ -505,7 +225,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip,
if (chip->flags & TPM_CHIP_FLAG_TPM2)
stop = jiffies + tpm2_calc_ordinal_duration(chip, ordinal);
else
- stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
+ stop = jiffies + tpm1_calc_ordinal_duration(chip, ordinal);
do {
u8 status = chip->ops->status(chip);
if ((status & chip->ops->req_complete_mask) ==
@@ -1087,7 +807,7 @@ int tpm_do_selftest(struct tpm_chip *chip)
unsigned long duration;
u8 dummy[TPM_DIGEST_SIZE];

- duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST);
+ duration = tpm1_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST);

loops = jiffies_to_msecs(duration) / delay_msec;

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 0f08518b525d..c59d2c20c339 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -546,7 +546,7 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
int tpm_get_timeouts(struct tpm_chip *);
int tpm1_auto_startup(struct tpm_chip *chip);
int tpm_do_selftest(struct tpm_chip *chip);
-unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
+unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm_pm_suspend(struct device *dev);
int tpm_pm_resume(struct device *dev);

diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
new file mode 100644
index 000000000000..991260134659
--- /dev/null
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -0,0 +1,310 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2004 IBM Corporation
+ * Copyright (C) 2014 Intel Corporation
+ *
+ * Authors:
+ * Leendert van Doorn <[email protected]>
+ * Dave Safford <[email protected]>
+ * Reiner Sailer <[email protected]>
+ * Kylene Hall <[email protected]>
+ *
+ * Device driver for TCG/TCPA TPM (trusted platform module).
+ * Specifications at http://www.trustedcomputinggroup.org
+ */
+
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/freezer.h>
+#include <linux/tpm_eventlog.h>
+
+#include "tpm.h"
+
+#define TPM_MAX_ORDINAL 243
+
+/*
+ * Array with one entry per ordinal defining the maximum amount
+ * of time the chip could take to return the result. The ordinal
+ * designation of short, medium or long is defined in a table in
+ * TCG Specification TPM Main Part 2 TPM Structures Section 17. The
+ * values of the SHORT, MEDIUM, and LONG durations are retrieved
+ * from the chip during initialization with a call to tpm_get_timeouts.
+ */
+static const u8 tpm1_ordinal_duration[TPM_MAX_ORDINAL] = {
+ TPM_UNDEFINED, /* 0 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 5 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 10 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_LONG,
+ TPM_MEDIUM, /* 15 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT, /* 20 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT, /* 25 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 30 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 35 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 40 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 45 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_MEDIUM, /* 50 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 55 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 60 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 65 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 70 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 75 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 80 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 85 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 90 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 95 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 100 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 105 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 110 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 115 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 120 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 125 */
+ TPM_SHORT,
+ TPM_LONG,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT, /* 130 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 135 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 140 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 145 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 150 */
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 155 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 160 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 165 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_LONG, /* 170 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 175 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_MEDIUM, /* 180 */
+ TPM_SHORT,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM, /* 185 */
+ TPM_SHORT,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 190 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 195 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 200 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 205 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_MEDIUM, /* 210 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_MEDIUM,
+ TPM_UNDEFINED, /* 215 */
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT,
+ TPM_SHORT, /* 220 */
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_SHORT,
+ TPM_UNDEFINED, /* 225 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 230 */
+ TPM_LONG,
+ TPM_MEDIUM,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED, /* 235 */
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_UNDEFINED,
+ TPM_SHORT, /* 240 */
+ TPM_UNDEFINED,
+ TPM_MEDIUM,
+};
+
+/**
+ * tpm1_calc_ordinal_duration() - calculate the maximum command duration
+ * @chip: TPM chip to use.
+ * @ordinal: TPM command ordinal.
+ *
+ * The function returns the maximum amount of time the chip could take
+ * to return the result for a particular ordinal in jiffies.
+ *
+ * Return: A maximal duration time for an ordinal in jiffies.
+ */
+unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
+{
+ int duration_idx = TPM_UNDEFINED;
+ int duration = 0;
+
+ /*
+ * We only have a duration table for protected commands, where the upper
+ * 16 bits are 0. For the few other ordinals the fallback will be used.
+ */
+ if (ordinal < TPM_MAX_ORDINAL)
+ duration_idx = tpm1_ordinal_duration[ordinal];
+
+ if (duration_idx != TPM_UNDEFINED)
+ duration = chip->duration[duration_idx];
+ if (duration <= 0)
+ return 2 * 60 * HZ;
+ else
+ return duration;
+}
+EXPORT_SYMBOL_GPL(tpm1_calc_ordinal_duration);
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c
index caa86b19c76d..5d20e98b844f 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -370,6 +370,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
struct i2c_client *client = to_i2c_client(dev);
u32 ordinal;
size_t count = 0;
+ unsigned long duration;
int burst_count, bytes2write, retries, rc = -EIO;

for (retries = 0; retries < TPM_RETRY; retries++) {
@@ -455,12 +456,11 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
return rc;
}
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
- rc = i2c_nuvoton_wait_for_data_avail(chip,
- tpm_calc_ordinal_duration(chip,
- ordinal),
- &priv->read_queue);
+ duration = tpm1_calc_ordinal_duration(chip, ordinal);
+ rc = i2c_nuvoton_wait_for_data_avail(chip, duration, &priv->read_queue);
if (rc) {
- dev_err(dev, "%s() timeout command duration\n", __func__);
+ dev_err(dev, "%s() timeout command duration %ld\n",
+ __func__, duration);
i2c_nuvoton_ready(chip);
return rc;
}
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index d2345d9fd7b5..14c332104de4 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -476,7 +476,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
if (chip->flags & TPM_CHIP_FLAG_TPM2)
dur = tpm2_calc_ordinal_duration(chip, ordinal);
else
- dur = tpm_calc_ordinal_duration(chip, ordinal);
+ dur = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index b150f87f38f5..77097229bf49 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -164,7 +164,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
notify_remote_via_evtchn(priv->evtchn);

ordinal = be32_to_cpu(((struct tpm_input_header*)buf)->ordinal);
- duration = tpm_calc_ordinal_duration(chip, ordinal);
+ duration = tpm1_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration,
&priv->read_queue, true) < 0) {
--
2.14.4


2018-10-17 06:51:11

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 04/20] tpm: add tpm_calc_ordinal_duration() wrapper

Add convenient wrapper for ordinal duration computation
to remove boiler plate if else statement over TPM2.

if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_calc_ordinal_duration(chip, ordinal);
else
tpm1_calc_ordinal_duration(chip, ordinal);

V2-V3: Rebase.
V4: Add Kdoc.
V5: Adjust the kdoc to the new standard.

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---
drivers/char/tpm/st33zp24/st33zp24.c | 2 +-
drivers/char/tpm/tpm-interface.c | 24 ++++++++++++++++++++----
drivers/char/tpm/tpm.h | 1 +
drivers/char/tpm/tpm1-cmd.c | 1 -
drivers/char/tpm/tpm2-cmd.c | 1 -
drivers/char/tpm/tpm_i2c_nuvoton.c | 2 +-
drivers/char/tpm/tpm_tis_core.c | 6 +-----
drivers/char/tpm/xen-tpmfront.c | 2 +-
8 files changed, 25 insertions(+), 14 deletions(-)

diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
index 16be974955ea..abd675bec88c 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -430,7 +430,7 @@ static int st33zp24_send(struct tpm_chip *chip, unsigned char *buf,
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));

ret = wait_for_stat(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- tpm1_calc_ordinal_duration(chip, ordinal),
+ tpm_calc_ordinal_duration(chip, ordinal),
&tpm_dev->read_queue, false);
if (ret < 0)
goto out_err;
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 21c6ed2a6bc1..ca09f84bfb27 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -47,6 +47,25 @@ module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
MODULE_PARM_DESC(suspend_pcr,
"PCR to use for dummy writes to facilitate flush on suspend.");

+/**
+ * tpm_calc_ordinal_duration() - calculate the maximum command duration
+ * @chip: TPM chip to use.
+ * @ordinal: TPM command ordinal.
+ *
+ * The function returns the maximum amount of time the chip could take
+ * to return the result for a particular ordinal in jiffies.
+ *
+ * Return: A maximal duration time for an ordinal in jiffies.
+ */
+unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
+{
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
+ return tpm2_calc_ordinal_duration(chip, ordinal);
+ else
+ return tpm1_calc_ordinal_duration(chip, ordinal);
+}
+EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
+
static int tpm_validate_command(struct tpm_chip *chip,
struct tpm_space *space,
const u8 *cmd,
@@ -222,10 +241,7 @@ static ssize_t tpm_try_transmit(struct tpm_chip *chip,
if (chip->flags & TPM_CHIP_FLAG_IRQ)
goto out_recv;

- if (chip->flags & TPM_CHIP_FLAG_TPM2)
- stop = jiffies + tpm2_calc_ordinal_duration(chip, ordinal);
- else
- stop = jiffies + tpm1_calc_ordinal_duration(chip, ordinal);
+ stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
do {
u8 status = chip->ops->status(chip);
if ((status & chip->ops->req_complete_mask) ==
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index c59d2c20c339..73511cd89bef 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -547,6 +547,7 @@ int tpm_get_timeouts(struct tpm_chip *);
int tpm1_auto_startup(struct tpm_chip *chip);
int tpm_do_selftest(struct tpm_chip *chip);
unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
+unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm_pm_suspend(struct device *dev);
int tpm_pm_resume(struct device *dev);

diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 991260134659..dfbe9c60cbcf 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -307,4 +307,3 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
else
return duration;
}
-EXPORT_SYMBOL_GPL(tpm1_calc_ordinal_duration);
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index d26b439976bc..3eef5565286d 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -132,7 +132,6 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
else
return msecs_to_jiffies(TPM2_DURATION_DEFAULT);
}
-EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration);


struct tpm2_pcr_read_out {
diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c
index 5d20e98b844f..4146f822fba9 100644
--- a/drivers/char/tpm/tpm_i2c_nuvoton.c
+++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
@@ -456,7 +456,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
return rc;
}
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
- duration = tpm1_calc_ordinal_duration(chip, ordinal);
+ duration = tpm_calc_ordinal_duration(chip, ordinal);
rc = i2c_nuvoton_wait_for_data_avail(chip, duration, &priv->read_queue);
if (rc) {
dev_err(dev, "%s() timeout command duration %ld\n",
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index 14c332104de4..f9e73d0f9386 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -473,11 +473,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));

- if (chip->flags & TPM_CHIP_FLAG_TPM2)
- dur = tpm2_calc_ordinal_duration(chip, ordinal);
- else
- dur = tpm1_calc_ordinal_duration(chip, ordinal);
-
+ dur = tpm_calc_ordinal_duration(chip, ordinal);
if (wait_for_tpm_stat
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
&priv->read_queue, false) < 0) {
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
index 77097229bf49..b150f87f38f5 100644
--- a/drivers/char/tpm/xen-tpmfront.c
+++ b/drivers/char/tpm/xen-tpmfront.c
@@ -164,7 +164,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
notify_remote_via_evtchn(priv->evtchn);

ordinal = be32_to_cpu(((struct tpm_input_header*)buf)->ordinal);
- duration = tpm1_calc_ordinal_duration(chip, ordinal);
+ duration = tpm_calc_ordinal_duration(chip, ordinal);

if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration,
&priv->read_queue, true) < 0) {
--
2.14.4


2018-10-17 06:51:14

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 06/20] tpm: move tpm1_pcr_extend to tpm1-cmd.c

Move tpm1_pcr_extend to tpm1-cmd.c and remove
unused pcrextend_header structure and
EXTEND_PCR_RESULT_SIZE and EXTEND_PCR_RESULT_BODY_SIZE
defines.

Fixes warning:
drivers/char/tpm/tpm-interface.c:609:38: warning: ‘pcrextend_header’ defined but not used [-Wunused-const-variable=]
static const struct tpm_input_header pcrextend_header = {
^~~~~~~~~~~~~~~~
Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
Reviewed-by: Nayna Jain <[email protected]>
Tested-by: Nayna Jain <[email protected]>
---
V2-V3: Rebase
V4: Remove defines.
V5: Resend
V6: Add Tested-by:

drivers/char/tpm/tpm-interface.c | 28 ----------------------------
drivers/char/tpm/tpm.h | 2 ++
drivers/char/tpm/tpm1-cmd.c | 21 +++++++++++++++++++++
3 files changed, 23 insertions(+), 28 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 20f5c15584e4..177795b408ff 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -615,34 +615,6 @@ int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
}
EXPORT_SYMBOL_GPL(tpm_pcr_read);

-#define TPM_ORD_PCR_EXTEND 20
-#define EXTEND_PCR_RESULT_SIZE 34
-#define EXTEND_PCR_RESULT_BODY_SIZE 20
-static const struct tpm_input_header pcrextend_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(34),
- .ordinal = cpu_to_be32(TPM_ORD_PCR_EXTEND)
-};
-
-static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
- char *log_msg)
-{
- struct tpm_buf buf;
- int rc;
-
- rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND);
- if (rc)
- return rc;
-
- tpm_buf_append_u32(&buf, pcr_idx);
- tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE);
-
- rc = tpm_transmit_cmd(chip, NULL, buf.data, EXTEND_PCR_RESULT_SIZE,
- EXTEND_PCR_RESULT_BODY_SIZE, 0, log_msg);
- tpm_buf_destroy(&buf);
- return rc;
-}
-
/**
* tpm_pcr_extend - extend a PCR value in SHA1 bank.
* @chip: a &struct tpm_chip instance, %NULL for the default chip
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 4ea51bbdbfae..221b6dcd15a1 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -549,6 +549,8 @@ int tpm_do_selftest(struct tpm_chip *chip);

int tpm1_get_timeouts(struct tpm_chip *chip);
unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
+int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
+ const char *log_msg);
unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm_pm_suspend(struct device *dev);
int tpm_pm_resume(struct device *dev);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 978946748ea3..ec242397e6dc 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -413,3 +413,24 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
return 0;
}
+
+#define TPM_ORD_PCR_EXTEND 20
+int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
+ const char *log_msg)
+{
+ struct tpm_buf buf;
+ int rc;
+
+ rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND);
+ if (rc)
+ return rc;
+
+ tpm_buf_append_u32(&buf, pcr_idx);
+ tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE);
+
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+ TPM_DIGEST_SIZE, 0, log_msg);
+
+ tpm_buf_destroy(&buf);
+ return rc;
+}
--
2.14.4


2018-10-17 06:51:24

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 08/20] tpm: factor out tpm1_get_random into tpm1-cmd.c

Factor out get random implementation from tpm-interface.c
into tpm1_get_random function in tpm1-cmd.c.
No functional changes.

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkine <[email protected]>
---

V2-V3: Rebase
V4-V8: Resend

drivers/char/tpm/tpm-interface.c | 58 +++++-----------------------------------
drivers/char/tpm/tpm.h | 1 +
drivers/char/tpm/tpm1-cmd.c | 55 +++++++++++++++++++++++++++++++++++++
3 files changed, 63 insertions(+), 51 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 486e211b03a0..a72bf6ea8f05 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -812,14 +812,6 @@ int tpm_pm_resume(struct device *dev)
}
EXPORT_SYMBOL_GPL(tpm_pm_resume);

-#define TPM_ORD_GET_RANDOM 70
-#define TPM_GETRANDOM_RESULT_SIZE 18
-static const struct tpm_input_header tpm_getrandom_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(14),
- .ordinal = cpu_to_be32(TPM_ORD_GET_RANDOM)
-};
-
/**
* tpm_get_random() - get random bytes from the TPM's RNG
* @chip: a &struct tpm_chip instance, %NULL for the default chip
@@ -830,58 +822,22 @@ static const struct tpm_input_header tpm_getrandom_header = {
*/
int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
{
- struct tpm_cmd_t tpm_cmd;
- u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA), rlength;
- int err, total = 0, retries = 5;
- u8 *dest = out;
+ int rc;

- if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
+ if (!out || max > TPM_MAX_RNG_DATA)
return -EINVAL;

chip = tpm_find_get_ops(chip);
if (!chip)
return -ENODEV;

- if (chip->flags & TPM_CHIP_FLAG_TPM2) {
- err = tpm2_get_random(chip, out, max);
- tpm_put_ops(chip);
- return err;
- }
-
- do {
- tpm_cmd.header.in = tpm_getrandom_header;
- tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
-
- err = tpm_transmit_cmd(chip, NULL, &tpm_cmd,
- TPM_GETRANDOM_RESULT_SIZE + num_bytes,
- offsetof(struct tpm_getrandom_out,
- rng_data),
- 0, "attempting get random");
- if (err)
- break;
-
- recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
- if (recd > num_bytes) {
- total = -EFAULT;
- break;
- }
-
- rlength = be32_to_cpu(tpm_cmd.header.out.length);
- if (rlength < TPM_HEADER_SIZE +
- offsetof(struct tpm_getrandom_out, rng_data) +
- recd) {
- total = -EFAULT;
- break;
- }
- memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
-
- dest += recd;
- total += recd;
- num_bytes -= recd;
- } while (retries-- && total < max);
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
+ rc = tpm2_get_random(chip, out, max);
+ else
+ rc = tpm1_get_random(chip, out, max);

tpm_put_ops(chip);
- return total ? total : -EIO;
+ return rc;
}
EXPORT_SYMBOL_GPL(tpm_get_random);

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 05c386b3ab12..22f89f41ad52 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -551,6 +551,7 @@ int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
const char *log_msg);
ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length);
+int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);
unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm_pm_suspend(struct device *dev);
int tpm_pm_resume(struct device *dev);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 3bd079587ef5..e02f0c1c822f 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -469,3 +469,58 @@ ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
return rc;
}
EXPORT_SYMBOL_GPL(tpm1_getcap);
+
+#define TPM_ORD_GET_RANDOM 70
+#define TPM_GETRANDOM_RESULT_SIZE 18
+static const struct tpm_input_header tpm_getrandom_header = {
+ .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+ .length = cpu_to_be32(14),
+ .ordinal = cpu_to_be32(TPM_ORD_GET_RANDOM)
+};
+
+int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max)
+{
+ struct tpm_cmd_t tpm_cmd;
+ u32 recd;
+ u32 num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
+ u32 rlength;
+ int err, total = 0, retries = 5;
+ u8 *dest = out;
+
+ if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
+ return -EINVAL;
+
+ do {
+ tpm_cmd.header.in = tpm_getrandom_header;
+ tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
+
+ err = tpm_transmit_cmd(chip, NULL, &tpm_cmd,
+ TPM_GETRANDOM_RESULT_SIZE + num_bytes,
+ offsetof(struct tpm_getrandom_out,
+ rng_data),
+ 0, "attempting get random");
+ if (err)
+ break;
+
+ recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
+ if (recd > num_bytes) {
+ total = -EFAULT;
+ break;
+ }
+
+ rlength = be32_to_cpu(tpm_cmd.header.out.length);
+ if (rlength < TPM_HEADER_SIZE +
+ offsetof(struct tpm_getrandom_out, rng_data) +
+ recd) {
+ total = -EFAULT;
+ break;
+ }
+ memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
+
+ dest += recd;
+ total += recd;
+ num_bytes -= recd;
+ } while (retries-- && (size_t)total < max);
+
+ return total ? total : -EIO;
+}
--
2.14.4


2018-10-17 06:51:45

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 13/20] tpm: tpm-interface.c drop unused macros

The commit:
"tpm_tis: further simplify calculation of ordinal duration"
left unused macros, we can drop them now.

Fixes compilation warnings:
tpm-interface.c:37:0: warning: macro "TPM_PROTECTED_COMMAND" is not used [-Wunused-macros]
tpm-interface.c:36:0: warning: macro "TSC_MAX_ORDINAL" is not used [-Wunused-macros]
tpm-interface.c:38:0: warning: macro "TPM_CONNECTION_COMMAND" is not used [-Wunused-macros]


Fixes: f72864300139 ("tpm_tis: further simplify calculation of ordinal duration")
Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---
V3: New in the series.
V4: Fix the commit message.
V5-V6: Rebase

drivers/char/tpm/tpm-interface.c | 4 ----
1 file changed, 4 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 69e007a198ce..ba50554e34d3 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -33,10 +33,6 @@

#include "tpm.h"

-#define TSC_MAX_ORDINAL 12
-#define TPM_PROTECTED_COMMAND 0x00
-#define TPM_CONNECTION_COMMAND 0x40
-
/*
* Bug workaround - some TPM's don't flush the most
* recently changed pcr on suspend, so force the flush
--
2.14.4


2018-10-17 06:51:47

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 14/20] tpm: tpm-space.c remove unneeded semicolon

Remove unneeded semicolon in tpm2_map_response_header()

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---
V3: New in the series.
V4-V6: Resend.

drivers/char/tpm/tpm2-space.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c
index d2e101b32482..dcdfde3c253e 100644
--- a/drivers/char/tpm/tpm2-space.c
+++ b/drivers/char/tpm/tpm2-space.c
@@ -373,7 +373,7 @@ static int tpm2_map_response_header(struct tpm_chip *chip, u32 cc, u8 *rsp,
dev_err(&chip->dev, "%s: unknown handle 0x%08X\n",
__func__, phandle);
break;
- };
+ }

return 0;
out_no_slots:
--
2.14.4


2018-10-17 06:51:50

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 15/20] tpm: tpm1: rewrite tpm1_get_random() using tpm_buf structure

1. Use tpm_buf in tpm1_get_random()
2. Fix comment in tpm_get_random() so it is clear that
the function is expected to return number of random bytes.

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---

V3: New in the series.
V4: Resend.
V5: A small adjustment in the kdoc.
V6: Rebase.

drivers/char/tpm/tpm-interface.c | 2 +-
drivers/char/tpm/tpm.h | 11 ------
drivers/char/tpm/tpm1-cmd.c | 84 +++++++++++++++++++++++-----------------
3 files changed, 49 insertions(+), 48 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index ba50554e34d3..8e1d2bc2df82 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -601,7 +601,7 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
* @out: destination buffer for the random bytes
* @max: the max number of bytes to write to @out
*
- * Return: same as with tpm_transmit_cmd()
+ * Return: number of random bytes read or a negative error value.
*/
int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
{
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index daca1d0190b1..6895f183396b 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -396,20 +396,9 @@ struct tpm_pcrread_in {
* compiler warnings about stack frame size. */
#define TPM_MAX_RNG_DATA 128

-struct tpm_getrandom_out {
- __be32 rng_data_len;
- u8 rng_data[TPM_MAX_RNG_DATA];
-} __packed;
-
-struct tpm_getrandom_in {
- __be32 num_bytes;
-} __packed;
-
typedef union {
struct tpm_pcrread_in pcrread_in;
struct tpm_pcrread_out pcrread_out;
- struct tpm_getrandom_in getrandom_in;
- struct tpm_getrandom_out getrandom_out;
} tpm_cmd_params;

struct tpm_cmd_t {
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 8a84db315676..b5c4fa158c30 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -505,58 +505,70 @@ ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
EXPORT_SYMBOL_GPL(tpm1_getcap);

#define TPM_ORD_GET_RANDOM 70
-#define TPM_GETRANDOM_RESULT_SIZE 18
-static const struct tpm_input_header tpm_getrandom_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(14),
- .ordinal = cpu_to_be32(TPM_ORD_GET_RANDOM)
-};
+struct tpm1_get_random_out {
+ __be32 rng_data_len;
+ u8 rng_data[TPM_MAX_RNG_DATA];
+} __packed;

-int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max)
+/**
+ * tpm1_get_random() - get random bytes from the TPM's RNG
+ * @chip: a &struct tpm_chip instance
+ * @dest: destination buffer for the random bytes
+ * @max: the maximum number of bytes to write to @dest
+ *
+ * Return:
+ * * number of bytes read
+ * * -errno or a TPM return code otherwise
+ */
+int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
{
- struct tpm_cmd_t tpm_cmd;
+ struct tpm1_get_random_out *out;
+ u32 num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
+ struct tpm_buf buf;
+ u32 total = 0;
+ int retries = 5;
u32 recd;
- u32 num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA);
- u32 rlength;
- int err, total = 0, retries = 5;
- u8 *dest = out;
+ int rc;

- if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
- return -EINVAL;
+ rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM);
+ if (rc)
+ return rc;

do {
- tpm_cmd.header.in = tpm_getrandom_header;
- tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
-
- err = tpm_transmit_cmd(chip, NULL, &tpm_cmd,
- TPM_GETRANDOM_RESULT_SIZE + num_bytes,
- offsetof(struct tpm_getrandom_out,
- rng_data),
- 0, "attempting get random");
- if (err)
- break;
+ tpm_buf_append_u32(&buf, num_bytes);
+
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+ sizeof(out->rng_data_len), 0,
+ "attempting get random");
+ if (rc)
+ goto out;

- recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len);
+ out = (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE];
+
+ recd = be32_to_cpu(out->rng_data_len);
if (recd > num_bytes) {
- total = -EFAULT;
- break;
+ rc = -EFAULT;
+ goto out;
}

- rlength = be32_to_cpu(tpm_cmd.header.out.length);
- if (rlength < TPM_HEADER_SIZE +
- offsetof(struct tpm_getrandom_out, rng_data) +
- recd) {
- total = -EFAULT;
- break;
+ if (tpm_buf_length(&buf) < TPM_HEADER_SIZE +
+ sizeof(out->rng_data_len) + recd) {
+ rc = -EFAULT;
+ goto out;
}
- memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd);
+ memcpy(dest, out->rng_data, recd);

dest += recd;
total += recd;
num_bytes -= recd;
- } while (retries-- && (size_t)total < max);

- return total ? total : -EIO;
+ tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM);
+ } while (retries-- && total < max);
+
+ rc = total ? (int)total : -EIO;
+out:
+ tpm_buf_destroy(&buf);
+ return rc;
}

#define TPM_ORDINAL_PCRREAD 21
--
2.14.4


2018-10-17 06:51:57

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 16/20] tpm1: implement tpm1_pcr_read_dev() using tpm_buf structure

Implement tpm1_pcr_read_dev() using tpm_buf and remove
now unneeded structures from tpm.h

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---

V3: New in the series.
V4-V6: Resend.

drivers/char/tpm/tpm.h | 18 ++----------------
drivers/char/tpm/tpm1-cmd.c | 38 +++++++++++++++++++++-----------------
2 files changed, 23 insertions(+), 33 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 6895f183396b..51d147675b1f 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -382,13 +382,10 @@ typedef union {
struct tpm_output_header out;
} tpm_cmd_header;

-struct tpm_pcrread_out {
- u8 pcr_result[TPM_DIGEST_SIZE];
+struct tpm_cmd_t {
+ tpm_cmd_header header;
} __packed;

-struct tpm_pcrread_in {
- __be32 pcr_idx;
-} __packed;

/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
* bytes, but 128 is still a relatively large number of random bytes and
@@ -396,17 +393,6 @@ struct tpm_pcrread_in {
* compiler warnings about stack frame size. */
#define TPM_MAX_RNG_DATA 128

-typedef union {
- struct tpm_pcrread_in pcrread_in;
- struct tpm_pcrread_out pcrread_out;
-} tpm_cmd_params;
-
-struct tpm_cmd_t {
- tpm_cmd_header header;
- tpm_cmd_params params;
-} __packed;
-
-
/* A string buffer type for constructing TPM commands. This is based on the
* ideas of string buffer code in security/keys/trusted.h but is heap based
* in order to keep the stack usage minimal.
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index b5c4fa158c30..d30f336518f6 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -571,29 +571,33 @@ int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
return rc;
}

-#define TPM_ORDINAL_PCRREAD 21
-#define READ_PCR_RESULT_SIZE 30
-#define READ_PCR_RESULT_BODY_SIZE 20
-static const struct tpm_input_header pcrread_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(14),
- .ordinal = cpu_to_be32(TPM_ORDINAL_PCRREAD)
-};
-
+#define TPM_ORD_PCRREAD 21
int tpm1_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
+ struct tpm_buf buf;
int rc;
- struct tpm_cmd_t cmd;

- cmd.header.in = pcrread_header;
- cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
- rc = tpm_transmit_cmd(chip, NULL, &cmd, READ_PCR_RESULT_SIZE,
- READ_PCR_RESULT_BODY_SIZE, 0,
+ rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCRREAD);
+ if (rc)
+ return rc;
+
+ tpm_buf_append_u32(&buf, pcr_idx);
+
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+ TPM_DIGEST_SIZE, 0,
"attempting to read a pcr value");
+ if (rc)
+ goto out;

- if (rc == 0)
- memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
- TPM_DIGEST_SIZE);
+ if (tpm_buf_length(&buf) < TPM_DIGEST_SIZE) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ memcpy(res_buf, &buf.data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE);
+
+out:
+ tpm_buf_destroy(&buf);
return rc;
}

--
2.14.4


2018-10-17 06:52:01

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 18/20] tpm1: reimplement SAVESTATE using tpm_buf

In tpm1_pm_suspend() function reimplement,
TPM_ORD_SAVESTATE comamnd using tpm_buf.

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---

V3: New in the series.
V4-V6: Resend

drivers/char/tpm/tpm1-cmd.c | 22 ++++++++++++----------
1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 05b772477bac..d418a27a75e0 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -718,12 +718,6 @@ int tpm1_auto_startup(struct tpm_chip *chip)
}

#define TPM_ORD_SAVESTATE 152
-#define SAVESTATE_RESULT_SIZE 10
-static const struct tpm_input_header savestate_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(10),
- .ordinal = cpu_to_be32(TPM_ORD_SAVESTATE)
-};

/**
* tpm1_pm_suspend() - pm suspend handler
@@ -739,18 +733,22 @@ static const struct tpm_input_header savestate_header = {
int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr)
{
u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
- struct tpm_cmd_t cmd;
- int rc, try;
+ struct tpm_buf buf;
+ unsigned int try;
+ int rc;
+

/* for buggy tpm, flush pcrs with extend to selected dummy */
if (tpm_suspend_pcr)
rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash,
"extending dummy pcr before suspend");

+ rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE);
+ if (rc)
+ return rc;
/* now do the actual savestate */
for (try = 0; try < TPM_RETRY; try++) {
- cmd.header.in = savestate_header;
- rc = tpm_transmit_cmd(chip, NULL, &cmd, SAVESTATE_RESULT_SIZE,
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
0, 0, NULL);

/*
@@ -766,6 +764,8 @@ int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr)
if (rc != TPM_WARN_RETRY)
break;
tpm_msleep(TPM_TIMEOUT_RETRY);
+
+ tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE);
}

if (rc)
@@ -775,6 +775,8 @@ int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr)
dev_warn(&chip->dev, "TPM savestate took %dms\n",
try * TPM_TIMEOUT_RETRY);

+ tpm_buf_destroy(&buf);
+
return rc;
}

--
2.14.4


2018-10-17 06:52:03

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 19/20] tpm1: reimplement tpm1_continue_selftest() using tpm_buf

Reimplement tpm1_continue_selftest() using tpm_buf structure.
This is the last command using the old tpm_cmd_t structure
and now the structure can be removed.

Cc: Nayna Jain <[email protected]>
Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---

V3: New in the series.
V4: Resend.
V5: Fix &buf.data -> buf.data in tpm1_continue_selftest()
V6: Rebase.

drivers/char/tpm/tpm.h | 9 ---------
drivers/char/tpm/tpm1-cmd.c | 21 ++++++++++-----------
2 files changed, 10 insertions(+), 20 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index bf2ef1eeda50..e0778d19da98 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -377,15 +377,6 @@ enum tpm_sub_capabilities {
TPM_CAP_PROP_TIS_DURATION = 0x120,
};

-typedef union {
- struct tpm_input_header in;
- struct tpm_output_header out;
-} tpm_cmd_header;
-
-struct tpm_cmd_t {
- tpm_cmd_header header;
-} __packed;
-

/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18
* bytes, but 128 is still a relatively large number of random bytes and
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index d418a27a75e0..6b04648f8184 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -602,15 +602,8 @@ int tpm1_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
}

#define TPM_ORD_CONTINUE_SELFTEST 83
-#define CONTINUE_SELFTEST_RESULT_SIZE 10
-static const struct tpm_input_header continue_selftest_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(10),
- .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
-};
-
/**
- * tpm_continue_selftest -- run TPM's selftest
+ * tpm_continue_selftest() - run TPM's selftest
* @chip: TPM chip to use
*
* Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
@@ -618,12 +611,18 @@ static const struct tpm_input_header continue_selftest_header = {
*/
static int tpm1_continue_selftest(struct tpm_chip *chip)
{
+ struct tpm_buf buf;
int rc;
- struct tpm_cmd_t cmd;

- cmd.header.in = continue_selftest_header;
- rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
+ rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST);
+ if (rc)
+ return rc;
+
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
0, 0, "continue selftest");
+
+ tpm_buf_destroy(&buf);
+
return rc;
}

--
2.14.4


2018-10-17 06:52:05

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 20/20] tpm: use u32 instead of int for PCR index

The TPM specs defines PCR index as a positive number, and there is
no reason to use a signed number. It is also a possible security
issue as currently no functions check for a negative index,
which may become a large number when converted to u32.

Adjust the API to use u32 instead of int in all PCR related
functions.

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---
V3: New in the series.
V4: Separate unrelated change to another patches.
V5: Fix the commit message.
V6: Rebased.

drivers/char/tpm/tpm-interface.c | 6 +++---
drivers/char/tpm/tpm-sysfs.c | 2 +-
drivers/char/tpm/tpm.h | 10 +++++-----
drivers/char/tpm/tpm1-cmd.c | 6 +++---
drivers/char/tpm/tpm2-cmd.c | 5 ++---
include/linux/tpm.h | 11 +++++++----
security/integrity/ima/ima_crypto.c | 5 +++--
7 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index acd647476ae1..d9439f9abe78 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -38,7 +38,7 @@
* recently changed pcr on suspend, so force the flush
* with an extend to the selected _unused_ non-volatile pcr.
*/
-static int tpm_suspend_pcr;
+static u32 tpm_suspend_pcr;
module_param_named(suspend_pcr, tpm_suspend_pcr, uint, 0644);
MODULE_PARM_DESC(suspend_pcr,
"PCR to use for dummy writes to facilitate flush on suspend.");
@@ -455,7 +455,7 @@ EXPORT_SYMBOL_GPL(tpm_is_tpm2);
*
* Return: same as with tpm_transmit_cmd()
*/
-int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
+int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)
{
int rc;

@@ -485,7 +485,7 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read);
*
* Return: same as with tpm_transmit_cmd()
*/
-int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
+int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash)
{
int rc;
struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)];
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 96fc7433c57d..b88e08ec2c59 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -102,7 +102,7 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
cap_t cap;
u8 digest[TPM_DIGEST_SIZE];
ssize_t rc;
- int i, j, num_pcrs;
+ u32 i, j, num_pcrs;
char *str = buf;
struct tpm_chip *chip = to_tpm_chip(dev);

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index e0778d19da98..f27d1f38a93d 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -509,14 +509,14 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
int tpm_get_timeouts(struct tpm_chip *);
int tpm_auto_startup(struct tpm_chip *chip);

-int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr);
+int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr);
int tpm1_auto_startup(struct tpm_chip *chip);
int tpm1_do_selftest(struct tpm_chip *chip);
int tpm1_get_timeouts(struct tpm_chip *chip);
unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
-int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
+int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash,
const char *log_msg);
-int tpm1_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
+int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf);
ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length);
int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);
@@ -558,8 +558,8 @@ static inline u32 tpm2_rc_value(u32 rc)
}

int tpm2_get_timeouts(struct tpm_chip *chip);
-int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
-int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
+int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf);
+int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count,
struct tpm2_digest *digests);
int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max);
void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle,
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 6b04648f8184..6f306338953b 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -449,7 +449,7 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
}

#define TPM_ORD_PCR_EXTEND 20
-int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
+int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash,
const char *log_msg)
{
struct tpm_buf buf;
@@ -572,7 +572,7 @@ int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
}

#define TPM_ORD_PCRREAD 21
-int tpm1_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
+int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)
{
struct tpm_buf buf;
int rc;
@@ -729,7 +729,7 @@ int tpm1_auto_startup(struct tpm_chip *chip)
* * 0 on success,
* * < 0 on error.
*/
-int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr)
+int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr)
{
u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
struct tpm_buf buf;
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 6ca4fc0a0d6f..ae86fb0218ab 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -175,7 +175,7 @@ struct tpm2_pcr_read_out {
*
* Return: Same as with tpm_transmit_cmd.
*/
-int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
+int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)
{
int rc;
struct tpm_buf buf;
@@ -225,7 +225,7 @@ struct tpm2_null_auth_area {
*
* Return: Same as with tpm_transmit_cmd.
*/
-int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
+int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, u32 count,
struct tpm2_digest *digests)
{
struct tpm_buf buf;
@@ -272,7 +272,6 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
return rc;
}

-
struct tpm2_get_random_out {
__be16 size;
u8 buffer[TPM_MAX_RNG_DATA];
diff --git a/include/linux/tpm.h b/include/linux/tpm.h
index 4609b94142d4..b49a55cf775f 100644
--- a/include/linux/tpm.h
+++ b/include/linux/tpm.h
@@ -53,8 +53,8 @@ struct tpm_class_ops {
#if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)

extern int tpm_is_tpm2(struct tpm_chip *chip);
-extern int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
-extern int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash);
+extern int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf);
+extern int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash);
extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen);
extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max);
extern int tpm_seal_trusted(struct tpm_chip *chip,
@@ -69,15 +69,18 @@ static inline int tpm_is_tpm2(struct tpm_chip *chip)
{
return -ENODEV;
}
-static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
+
+static inline int tpm_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf)
{
return -ENODEV;
}
-static inline int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx,
+
+static inline int tpm_pcr_extend(struct tpm_chip *chip, u32 pcr_idx,
const u8 *hash)
{
return -ENODEV;
}
+
static inline int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
{
return -ENODEV;
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index 7e7e7e7c250a..959d9edc113a 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -629,7 +629,7 @@ int ima_calc_buffer_hash(const void *buf, loff_t len,
return calc_buffer_shash(buf, len, hash);
}

-static void __init ima_pcrread(int idx, u8 *pcr)
+static void __init ima_pcrread(u32 idx, u8 *pcr)
{
if (!ima_tpm_chip)
return;
@@ -645,7 +645,8 @@ static int __init ima_calc_boot_aggregate_tfm(char *digest,
struct crypto_shash *tfm)
{
u8 pcr_i[TPM_DIGEST_SIZE];
- int rc, i;
+ int rc;
+ u32 i;
SHASH_DESC_ON_STACK(shash, tfm);

shash->tfm = tfm;
--
2.14.4


2018-10-17 06:52:13

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 02/20] tpm: sort objects in the Makefile

Make the tpm Makefile a bit more in order by putting
objects in one column.


Signed-off-by: Tomas Winkler <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---
V2: 1. back to tpm-y notation
2. Partially sort files alphanumerically.
V3: Rebase
V4: Remove redunant sentence in commit message.
V5: Resend
V6: Resend
drivers/char/tpm/Makefile | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 4e9c33ca1f8f..efc785053627 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -3,9 +3,18 @@
# Makefile for the kernel tpm device drivers.
#
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 tpmrm-dev.o eventlog/common.o eventlog/tpm1.o \
- eventlog/tpm2.o tpm2-space.o
+tpm-y := tpm-chip.o
+tpm-y += tpm-dev-common.o
+tpm-y += tpm-dev.o
+tpm-y += tpm-interface.o
+tpm-y += tpm2-cmd.o
+tpm-y += tpmrm-dev.o
+tpm-y += tpm2-space.o
+tpm-y += tpm-sysfs.o
+tpm-y += eventlog/common.o
+tpm-y += eventlog/tpm1.o
+tpm-y += eventlog/tpm2.o
+
tpm-$(CONFIG_ACPI) += tpm_ppi.o eventlog/acpi.o
tpm-$(CONFIG_EFI) += eventlog/efi.o
tpm-$(CONFIG_OF) += eventlog/of.o
--
2.14.4


2018-10-17 06:52:40

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 12/20] tpm: add tpm_auto_startup() into tpm-interface.c

Add wrapper tpm_auto_startup() to tpm-interface.c
instead of open coded decision between TPM 1.x and TPM 2.x
in tpm-chip.c

Signed-off-by: Tomas Winkler <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---
V3: New in the series.
V4: Fix the commit message.
V5-V6: Resend.

drivers/char/tpm/tpm-chip.c | 11 +++--------
drivers/char/tpm/tpm-interface.c | 15 +++++++++++++++
drivers/char/tpm/tpm.h | 1 +
3 files changed, 19 insertions(+), 8 deletions(-)

diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
index 46caadca916a..32db84683c40 100644
--- a/drivers/char/tpm/tpm-chip.c
+++ b/drivers/char/tpm/tpm-chip.c
@@ -451,14 +451,9 @@ int tpm_chip_register(struct tpm_chip *chip)
{
int rc;

- if (chip->ops->flags & TPM_OPS_AUTO_STARTUP) {
- if (chip->flags & TPM_CHIP_FLAG_TPM2)
- rc = tpm2_auto_startup(chip);
- else
- rc = tpm1_auto_startup(chip);
- if (rc)
- return rc;
- }
+ rc = tpm_auto_startup(chip);
+ if (rc)
+ return rc;

tpm_sysfs_add_device(chip);

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 54b81700561b..69e007a198ce 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -545,6 +545,21 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
}
EXPORT_SYMBOL_GPL(tpm_send);

+int tpm_auto_startup(struct tpm_chip *chip)
+{
+ int rc;
+
+ if (!(chip->ops->flags & TPM_OPS_AUTO_STARTUP))
+ return 0;
+
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
+ rc = tpm2_auto_startup(chip);
+ else
+ rc = tpm1_auto_startup(chip);
+
+ return rc;
+}
+
/*
* We are about to suspend. Save the TPM state
* so that it can be restored.
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 2eb73f6966c3..daca1d0190b1 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -541,6 +541,7 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
size_t min_rsp_body_length, unsigned int flags,
const char *desc);
int tpm_get_timeouts(struct tpm_chip *);
+int tpm_auto_startup(struct tpm_chip *chip);

int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr);
int tpm1_auto_startup(struct tpm_chip *chip);
--
2.14.4


2018-10-17 06:52:40

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 09/20] tpm: move tpm 1.x selftest code from tpm-interface.c tpm1-cmd.c

Move the tpm1 selftest code functions to tpm1-cmd.c
and adjust callers to use the new function names.
1. tpm_pcr_read_dev() to tpm1_pcr_read_dev().
2. tpm_continue_selftest() to tpm1_continue_selftest().
3. tpm_do_selftest() to tpm1_do_selftest()

Signed-off-by: Tomas Winkler <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---
V2-V3: Rebase
V4: Fix the commit message.
V5: Resend.
V6: Rebase

drivers/char/tpm/st33zp24/st33zp24.c | 2 +-
drivers/char/tpm/tpm-interface.c | 148 +----------------------------------
drivers/char/tpm/tpm-sysfs.c | 2 +-
drivers/char/tpm/tpm.h | 5 +-
drivers/char/tpm/tpm1-cmd.c | 142 +++++++++++++++++++++++++++++++++
drivers/char/tpm/tpm_tis_core.c | 2 +-
6 files changed, 150 insertions(+), 151 deletions(-)

diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c
index abd675bec88c..64dc560859f2 100644
--- a/drivers/char/tpm/st33zp24/st33zp24.c
+++ b/drivers/char/tpm/st33zp24/st33zp24.c
@@ -649,7 +649,7 @@ int st33zp24_pm_resume(struct device *dev)
} else {
ret = tpm_pm_resume(dev);
if (!ret)
- tpm_do_selftest(chip);
+ tpm1_do_selftest(chip);
}
return ret;
} /* st33zp24_pm_resume() */
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index a72bf6ea8f05..43d3540a7875 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -467,59 +467,6 @@ int tpm_get_timeouts(struct tpm_chip *chip)
}
EXPORT_SYMBOL_GPL(tpm_get_timeouts);

-#define TPM_ORD_CONTINUE_SELFTEST 83
-#define CONTINUE_SELFTEST_RESULT_SIZE 10
-
-static const struct tpm_input_header continue_selftest_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(10),
- .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
-};
-
-/**
- * tpm_continue_selftest -- run TPM's selftest
- * @chip: TPM chip to use
- *
- * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
- * a TPM error code.
- */
-static int tpm_continue_selftest(struct tpm_chip *chip)
-{
- int rc;
- struct tpm_cmd_t cmd;
-
- cmd.header.in = continue_selftest_header;
- rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
- 0, 0, "continue selftest");
- return rc;
-}
-
-#define TPM_ORDINAL_PCRREAD 21
-#define READ_PCR_RESULT_SIZE 30
-#define READ_PCR_RESULT_BODY_SIZE 20
-static const struct tpm_input_header pcrread_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(14),
- .ordinal = cpu_to_be32(TPM_ORDINAL_PCRREAD)
-};
-
-int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
-{
- int rc;
- struct tpm_cmd_t cmd;
-
- cmd.header.in = pcrread_header;
- cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
- rc = tpm_transmit_cmd(chip, NULL, &cmd, READ_PCR_RESULT_SIZE,
- READ_PCR_RESULT_BODY_SIZE, 0,
- "attempting to read a pcr value");
-
- if (rc == 0)
- memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
- TPM_DIGEST_SIZE);
- return rc;
-}
-
/**
* tpm_is_tpm2 - do we a have a TPM2 chip?
* @chip: a &struct tpm_chip instance, %NULL for the default chip
@@ -560,10 +507,12 @@ int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
chip = tpm_find_get_ops(chip);
if (!chip)
return -ENODEV;
+
if (chip->flags & TPM_CHIP_FLAG_TPM2)
rc = tpm2_pcr_read(chip, pcr_idx, res_buf);
else
- rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf);
+ rc = tpm1_pcr_read_dev(chip, pcr_idx, res_buf);
+
tpm_put_ops(chip);
return rc;
}
@@ -614,97 +563,6 @@ int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
}
EXPORT_SYMBOL_GPL(tpm_pcr_extend);

-/**
- * tpm_do_selftest - have the TPM continue its selftest and wait until it
- * can receive further commands
- * @chip: TPM chip to use
- *
- * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
- * a TPM error code.
- */
-int tpm_do_selftest(struct tpm_chip *chip)
-{
- int rc;
- unsigned int loops;
- unsigned int delay_msec = 100;
- unsigned long duration;
- u8 dummy[TPM_DIGEST_SIZE];
-
- duration = tpm1_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST);
-
- loops = jiffies_to_msecs(duration) / delay_msec;
-
- rc = tpm_continue_selftest(chip);
- if (rc == TPM_ERR_INVALID_POSTINIT) {
- chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED;
- dev_info(&chip->dev, "TPM not ready (%d)\n", rc);
- }
- /* This may fail if there was no TPM driver during a suspend/resume
- * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST)
- */
- if (rc)
- return rc;
-
- do {
- /* Attempt to read a PCR value */
- rc = tpm_pcr_read_dev(chip, 0, dummy);
-
- /* Some buggy TPMs will not respond to tpm_tis_ready() for
- * around 300ms while the self test is ongoing, keep trying
- * until the self test duration expires. */
- if (rc == -ETIME) {
- dev_info(
- &chip->dev, HW_ERR
- "TPM command timed out during continue self test");
- tpm_msleep(delay_msec);
- continue;
- }
-
- if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
- dev_info(&chip->dev,
- "TPM is disabled/deactivated (0x%X)\n", rc);
- /* TPM is disabled and/or deactivated; driver can
- * proceed and TPM does handle commands for
- * suspend/resume correctly
- */
- return 0;
- }
- if (rc != TPM_WARN_DOING_SELFTEST)
- return rc;
- tpm_msleep(delay_msec);
- } while (--loops > 0);
-
- return rc;
-}
-EXPORT_SYMBOL_GPL(tpm_do_selftest);
-
-/**
- * tpm1_auto_startup - Perform the standard automatic TPM initialization
- * sequence
- * @chip: TPM chip to use
- *
- * Returns 0 on success, < 0 in case of fatal error.
- */
-int tpm1_auto_startup(struct tpm_chip *chip)
-{
- int rc;
-
- rc = tpm_get_timeouts(chip);
- if (rc)
- goto out;
- rc = tpm_do_selftest(chip);
- if (rc) {
- dev_err(&chip->dev, "TPM self test failed\n");
- goto out;
- }
-
- return rc;
-out:
- if (rc > 0)
- rc = -ENODEV;
- return rc;
-}
-
/**
* tpm_send - send a TPM command
* @chip: a &struct tpm_chip instance, %NULL for the default chip
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 008515314ae3..861acafd8f29 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -114,7 +114,7 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,

num_pcrs = be32_to_cpu(cap.num_pcrs);
for (i = 0; i < num_pcrs; i++) {
- rc = tpm_pcr_read_dev(chip, i, digest);
+ rc = tpm1_pcr_read_dev(chip, i, digest);
if (rc)
break;
str += sprintf(str, "PCR-%02d: ", i);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 22f89f41ad52..f284a98a9455 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -543,12 +543,12 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
int tpm_startup(struct tpm_chip *chip);
int tpm_get_timeouts(struct tpm_chip *);
int tpm1_auto_startup(struct tpm_chip *chip);
-int tpm_do_selftest(struct tpm_chip *chip);
-
+int tpm1_do_selftest(struct tpm_chip *chip);
int tpm1_get_timeouts(struct tpm_chip *chip);
unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
const char *log_msg);
+int tpm1_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length);
int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);
@@ -575,7 +575,6 @@ void tpm_chip_unregister(struct tpm_chip *chip);

void tpm_sysfs_add_device(struct tpm_chip *chip);

-int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);

#ifdef CONFIG_ACPI
extern void tpm_add_ppi(struct tpm_chip *chip);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index e02f0c1c822f..a69a02366c32 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -524,3 +524,145 @@ int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max)

return total ? total : -EIO;
}
+
+#define TPM_ORDINAL_PCRREAD 21
+#define READ_PCR_RESULT_SIZE 30
+#define READ_PCR_RESULT_BODY_SIZE 20
+static const struct tpm_input_header pcrread_header = {
+ .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+ .length = cpu_to_be32(14),
+ .ordinal = cpu_to_be32(TPM_ORDINAL_PCRREAD)
+};
+
+int tpm1_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
+{
+ int rc;
+ struct tpm_cmd_t cmd;
+
+ cmd.header.in = pcrread_header;
+ cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx);
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, READ_PCR_RESULT_SIZE,
+ READ_PCR_RESULT_BODY_SIZE, 0,
+ "attempting to read a pcr value");
+
+ if (rc == 0)
+ memcpy(res_buf, cmd.params.pcrread_out.pcr_result,
+ TPM_DIGEST_SIZE);
+ return rc;
+}
+
+#define TPM_ORD_CONTINUE_SELFTEST 83
+#define CONTINUE_SELFTEST_RESULT_SIZE 10
+static const struct tpm_input_header continue_selftest_header = {
+ .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+ .length = cpu_to_be32(10),
+ .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
+};
+
+/**
+ * tpm_continue_selftest -- run TPM's selftest
+ * @chip: TPM chip to use
+ *
+ * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
+ * a TPM error code.
+ */
+static int tpm1_continue_selftest(struct tpm_chip *chip)
+{
+ int rc;
+ struct tpm_cmd_t cmd;
+
+ cmd.header.in = continue_selftest_header;
+ rc = tpm_transmit_cmd(chip, NULL, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
+ 0, 0, "continue selftest");
+ return rc;
+}
+
+/**
+ * tpm1_do_selftest - have the TPM continue its selftest and wait until it
+ * can receive further commands
+ * @chip: TPM chip to use
+ *
+ * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
+ * a TPM error code.
+ */
+int tpm1_do_selftest(struct tpm_chip *chip)
+{
+ int rc;
+ unsigned int loops;
+ unsigned int delay_msec = 100;
+ unsigned long duration;
+ u8 dummy[TPM_DIGEST_SIZE];
+
+ duration = tpm1_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST);
+
+ loops = jiffies_to_msecs(duration) / delay_msec;
+
+ rc = tpm1_continue_selftest(chip);
+ if (rc == TPM_ERR_INVALID_POSTINIT) {
+ chip->flags |= TPM_CHIP_FLAG_ALWAYS_POWERED;
+ dev_info(&chip->dev, "TPM not ready (%d)\n", rc);
+ }
+ /* This may fail if there was no TPM driver during a suspend/resume
+ * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST)
+ */
+ if (rc)
+ return rc;
+
+ do {
+ /* Attempt to read a PCR value */
+ rc = tpm1_pcr_read_dev(chip, 0, dummy);
+
+ /* Some buggy TPMs will not respond to tpm_tis_ready() for
+ * around 300ms while the self test is ongoing, keep trying
+ * until the self test duration expires.
+ */
+ if (rc == -ETIME) {
+ dev_info(&chip->dev, HW_ERR "TPM command timed out during continue self test");
+ tpm_msleep(delay_msec);
+ continue;
+ }
+
+ if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) {
+ dev_info(&chip->dev, "TPM is disabled/deactivated (0x%X)\n",
+ rc);
+ /* TPM is disabled and/or deactivated; driver can
+ * proceed and TPM does handle commands for
+ * suspend/resume correctly
+ */
+ return 0;
+ }
+ if (rc != TPM_WARN_DOING_SELFTEST)
+ return rc;
+ tpm_msleep(delay_msec);
+ } while (--loops > 0);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm1_do_selftest);
+
+/**
+ * tpm1_auto_startup - Perform the standard automatic TPM initialization
+ * sequence
+ * @chip: TPM chip to use
+ *
+ * Returns 0 on success, < 0 in case of fatal error.
+ */
+int tpm1_auto_startup(struct tpm_chip *chip)
+{
+ int rc;
+
+ rc = tpm1_get_timeouts(chip);
+ if (rc)
+ goto out;
+ rc = tpm1_do_selftest(chip);
+ if (rc) {
+ dev_err(&chip->dev, "TPM self test failed\n");
+ goto out;
+ }
+
+ return rc;
+out:
+ if (rc > 0)
+ rc = -ENODEV;
+ return rc;
+}
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index ced01ec146b5..bf7e49cfa643 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -1056,7 +1056,7 @@ int tpm_tis_resume(struct device *dev)
* an error code but for unknown reason it isn't handled.
*/
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
- tpm_do_selftest(chip);
+ tpm1_do_selftest(chip);

return 0;
}
--
2.14.4


2018-10-17 06:52:44

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 10/20] tpm: factor out tpm 1.x pm suspend flow into tpm1-cmd.c

Factor out TPM 1.x suspend flow from tpm-interface.c into a new function
tpm1_pm_suspend() in tpm1-cmd.c

Signed-off-by: Tomas Winkler <[email protected]>
---
V2-V3: Rebase
V4: 1. Add kdoc for tpm1_pm_suspend().
2. Fix commit message.
V5: Adjust the kdoc to the new standard.
V6: Rebase

drivers/char/tpm/tpm-interface.c | 55 ++++--------------------------------
drivers/char/tpm/tpm.h | 2 ++
drivers/char/tpm/tpm1-cmd.c | 61 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 68 insertions(+), 50 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 43d3540a7875..e7f220f691f9 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -586,15 +586,6 @@ int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
}
EXPORT_SYMBOL_GPL(tpm_send);

-#define TPM_ORD_SAVESTATE 152
-#define SAVESTATE_RESULT_SIZE 10
-
-static const struct tpm_input_header savestate_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(10),
- .ordinal = cpu_to_be32(TPM_ORD_SAVESTATE)
-};
-
/*
* We are about to suspend. Save the TPM state
* so that it can be restored.
@@ -602,54 +593,18 @@ static const struct tpm_input_header savestate_header = {
int tpm_pm_suspend(struct device *dev)
{
struct tpm_chip *chip = dev_get_drvdata(dev);
- struct tpm_cmd_t cmd;
- int rc, try;
-
- u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
+ int rc = 0;

- if (chip == NULL)
+ if (!chip)
return -ENODEV;

if (chip->flags & TPM_CHIP_FLAG_ALWAYS_POWERED)
return 0;

- if (chip->flags & TPM_CHIP_FLAG_TPM2) {
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
tpm2_shutdown(chip, TPM2_SU_STATE);
- return 0;
- }
-
- /* for buggy tpm, flush pcrs with extend to selected dummy */
- if (tpm_suspend_pcr)
- rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash,
- "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, NULL, &cmd, SAVESTATE_RESULT_SIZE,
- 0, 0, NULL);
-
- /*
- * If the TPM indicates that it is too busy to respond to
- * this command then retry before giving up. It can take
- * several seconds for this TPM to be ready.
- *
- * This can happen if the TPM has already been sent the
- * SaveState command before the driver has loaded. TCG 1.2
- * specification states that any communication after SaveState
- * may cause the TPM to invalidate previously saved state.
- */
- if (rc != TPM_WARN_RETRY)
- break;
- tpm_msleep(TPM_TIMEOUT_RETRY);
- }
-
- if (rc)
- dev_err(&chip->dev,
- "Error (%d) sending savestate before suspend\n", rc);
- else if (try > 0)
- dev_warn(&chip->dev, "TPM savestate took %dms\n",
- try * TPM_TIMEOUT_RETRY);
+ else
+ rc = tpm1_pm_suspend(chip, tpm_suspend_pcr);

return rc;
}
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f284a98a9455..754f7bcb15fa 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -542,6 +542,8 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
const char *desc);
int tpm_startup(struct tpm_chip *chip);
int tpm_get_timeouts(struct tpm_chip *);
+
+int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr);
int tpm1_auto_startup(struct tpm_chip *chip);
int tpm1_do_selftest(struct tpm_chip *chip);
int tpm1_get_timeouts(struct tpm_chip *chip);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index a69a02366c32..3bd9f1fa77ce 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -666,3 +666,64 @@ int tpm1_auto_startup(struct tpm_chip *chip)
rc = -ENODEV;
return rc;
}
+
+#define TPM_ORD_SAVESTATE 152
+#define SAVESTATE_RESULT_SIZE 10
+static const struct tpm_input_header savestate_header = {
+ .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
+ .length = cpu_to_be32(10),
+ .ordinal = cpu_to_be32(TPM_ORD_SAVESTATE)
+};
+
+/**
+ * tpm1_pm_suspend() - pm suspend handler
+ * @chip: TPM chip to use.
+ * @tpm_suspend_pcr: flush pcr for buggy TPM chips.
+ *
+ * The functions saves the TPM state to be restored on resume.
+ *
+ * Return:
+ * * 0 on success,
+ * * < 0 on error.
+ */
+int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr)
+{
+ u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 };
+ struct tpm_cmd_t cmd;
+ int rc, try;
+
+ /* for buggy tpm, flush pcrs with extend to selected dummy */
+ if (tpm_suspend_pcr)
+ rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash,
+ "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, NULL, &cmd, SAVESTATE_RESULT_SIZE,
+ 0, 0, NULL);
+
+ /*
+ * If the TPM indicates that it is too busy to respond to
+ * this command then retry before giving up. It can take
+ * several seconds for this TPM to be ready.
+ *
+ * This can happen if the TPM has already been sent the
+ * SaveState command before the driver has loaded. TCG 1.2
+ * specification states that any communication after SaveState
+ * may cause the TPM to invalidate previously saved state.
+ */
+ if (rc != TPM_WARN_RETRY)
+ break;
+ tpm_msleep(TPM_TIMEOUT_RETRY);
+ }
+
+ if (rc)
+ dev_err(&chip->dev, "Error (%d) sending savestate before suspend\n",
+ rc);
+ else if (try > 0)
+ dev_warn(&chip->dev, "TPM savestate took %dms\n",
+ try * TPM_TIMEOUT_RETRY);
+
+ return rc;
+}
--
2.14.4


2018-10-17 06:52:50

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 11/20] tpm: factor out tpm_startup function

TPM manual startup is used only from within TPM 1.x or TPM 2.x
code, hence remove tpm_startup() function from tpm-interface.c
and add two static functions implementations tpm1_startup()
and tpm2_startup() into to tpm1-cmd.c and tpm2-cmd.c respectively.

Signed-off-by: Tomas Winkler <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---
V2-V2: Resend.
V4: Fix the commit message.
V5: 1. A small fix in the kdoc.
2. Fixed Jarkko's name in Tested-by.
V6: Rebase

drivers/char/tpm/tpm-interface.c | 41 ----------------------------------------
drivers/char/tpm/tpm.h | 1 -
drivers/char/tpm/tpm1-cmd.c | 37 +++++++++++++++++++++++++++++++++++-
drivers/char/tpm/tpm2-cmd.c | 34 +++++++++++++++++++++++++++++++--
4 files changed, 68 insertions(+), 45 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index e7f220f691f9..54b81700561b 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -414,47 +414,6 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
}
EXPORT_SYMBOL_GPL(tpm_transmit_cmd);

-#define TPM_ORD_STARTUP 153
-#define TPM_ST_CLEAR 1
-
-/**
- * tpm_startup - turn on the TPM
- * @chip: TPM chip to use
- *
- * Normally the firmware should start the TPM. This function is provided as a
- * workaround if this does not happen. A legal case for this could be for
- * example when a TPM emulator is used.
- *
- * Return: same as tpm_transmit_cmd()
- */
-int tpm_startup(struct tpm_chip *chip)
-{
- struct tpm_buf buf;
- int rc;
-
- dev_info(&chip->dev, "starting up the TPM manually\n");
-
- if (chip->flags & TPM_CHIP_FLAG_TPM2) {
- rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
- if (rc < 0)
- return rc;
-
- tpm_buf_append_u16(&buf, TPM2_SU_CLEAR);
- } else {
- rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
- if (rc < 0)
- return rc;
-
- tpm_buf_append_u16(&buf, TPM_ST_CLEAR);
- }
-
- rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
- "attempting to start the TPM");
-
- tpm_buf_destroy(&buf);
- return rc;
-}
-
int tpm_get_timeouts(struct tpm_chip *chip)
{
if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 754f7bcb15fa..2eb73f6966c3 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -540,7 +540,6 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
void *buf, size_t bufsiz,
size_t min_rsp_body_length, unsigned int flags,
const char *desc);
-int tpm_startup(struct tpm_chip *chip);
int tpm_get_timeouts(struct tpm_chip *);

int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index 3bd9f1fa77ce..8a84db315676 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -308,6 +308,40 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
return duration;
}

+#define TPM_ORD_STARTUP 153
+#define TPM_ST_CLEAR 1
+
+/**
+ * tpm_startup() - turn on the TPM
+ * @chip: TPM chip to use
+ *
+ * Normally the firmware should start the TPM. This function is provided as a
+ * workaround if this does not happen. A legal case for this could be for
+ * example when a TPM emulator is used.
+ *
+ * Return: same as tpm_transmit_cmd()
+ */
+static int tpm1_startup(struct tpm_chip *chip)
+{
+ struct tpm_buf buf;
+ int rc;
+
+ dev_info(&chip->dev, "starting up the TPM manually\n");
+
+ rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP);
+ if (rc < 0)
+ return rc;
+
+ tpm_buf_append_u16(&buf, TPM_ST_CLEAR);
+
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
+ "attempting to start the TPM");
+
+ tpm_buf_destroy(&buf);
+
+ return rc;
+}
+
int tpm1_get_timeouts(struct tpm_chip *chip)
{
cap_t cap;
@@ -317,7 +351,7 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
sizeof(cap.timeout));
if (rc == TPM_ERR_INVALID_POSTINIT) {
- if (tpm_startup(chip))
+ if (tpm1_startup(chip))
return rc;

rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
@@ -727,3 +761,4 @@ int tpm1_pm_suspend(struct tpm_chip *chip, int tpm_suspend_pcr)

return rc;
}
+
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index dd2e98f4de08..6ca4fc0a0d6f 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -948,6 +948,36 @@ static int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip)
return rc;
}

+/**
+ * tpm2_startup - turn on the TPM
+ * @chip: TPM chip to use
+ *
+ * Normally the firmware should start the TPM. This function is provided as a
+ * workaround if this does not happen. A legal case for this could be for
+ * example when a TPM emulator is used.
+ *
+ * Return: same as tpm_transmit_cmd()
+ */
+
+static int tpm2_startup(struct tpm_chip *chip)
+{
+ struct tpm_buf buf;
+ int rc;
+
+ dev_info(&chip->dev, "starting up the TPM manually\n");
+
+ rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP);
+ if (rc < 0)
+ return rc;
+
+ tpm_buf_append_u16(&buf, TPM2_SU_CLEAR);
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE, 0, 0,
+ "attempting to start the TPM");
+ tpm_buf_destroy(&buf);
+
+ return rc;
+}
+
/**
* tpm2_auto_startup - Perform the standard automatic TPM initialization
* sequence
@@ -959,7 +989,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)
{
int rc;

- rc = tpm_get_timeouts(chip);
+ rc = tpm2_get_timeouts(chip);
if (rc)
goto out;

@@ -968,7 +998,7 @@ int tpm2_auto_startup(struct tpm_chip *chip)
goto out;

if (rc == TPM2_RC_INITIALIZE) {
- rc = tpm_startup(chip);
+ rc = tpm2_startup(chip);
if (rc)
goto out;

--
2.14.4


2018-10-17 06:53:13

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 17/20] tmp1: rename tpm1_pcr_read_dev to tpm1_pcr_read()

Rename tpm1_pcr_read_dev to tpm1_pcr_read() to match
the counterpart tpm2_pcr_read().

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
---

V4: New in the series
V5-V6: Resend.

drivers/char/tpm/tpm-interface.c | 2 +-
drivers/char/tpm/tpm-sysfs.c | 2 +-
drivers/char/tpm/tpm.h | 2 +-
drivers/char/tpm/tpm1-cmd.c | 4 ++--
4 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 8e1d2bc2df82..acd647476ae1 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -466,7 +466,7 @@ int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
if (chip->flags & TPM_CHIP_FLAG_TPM2)
rc = tpm2_pcr_read(chip, pcr_idx, res_buf);
else
- rc = tpm1_pcr_read_dev(chip, pcr_idx, res_buf);
+ rc = tpm1_pcr_read(chip, pcr_idx, res_buf);

tpm_put_ops(chip);
return rc;
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 861acafd8f29..96fc7433c57d 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -114,7 +114,7 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,

num_pcrs = be32_to_cpu(cap.num_pcrs);
for (i = 0; i < num_pcrs; i++) {
- rc = tpm1_pcr_read_dev(chip, i, digest);
+ rc = tpm1_pcr_read(chip, i, digest);
if (rc)
break;
str += sprintf(str, "PCR-%02d: ", i);
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 51d147675b1f..bf2ef1eeda50 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -525,7 +525,7 @@ int tpm1_get_timeouts(struct tpm_chip *chip);
unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
const char *log_msg);
-int tpm1_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
+int tpm1_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
const char *desc, size_t min_cap_length);
int tpm1_get_random(struct tpm_chip *chip, u8 *out, size_t max);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index d30f336518f6..05b772477bac 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -572,7 +572,7 @@ int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max)
}

#define TPM_ORD_PCRREAD 21
-int tpm1_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
+int tpm1_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
struct tpm_buf buf;
int rc;
@@ -660,7 +660,7 @@ int tpm1_do_selftest(struct tpm_chip *chip)

do {
/* Attempt to read a PCR value */
- rc = tpm1_pcr_read_dev(chip, 0, dummy);
+ rc = tpm1_pcr_read(chip, 0, dummy);

/* Some buggy TPMs will not respond to tpm_tis_ready() for
* around 300ms while the self test is ongoing, keep trying
--
2.14.4


2018-10-17 06:53:38

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 01/20] tpm2: add new tpm2 commands according to TCG 1.36

1. TPM2_CC_LAST has moved from 182 to 193
2. Convert tpm2_ordinal_duration from an array into a switch statement,
as there are not so many commands that require special duration
relative to a number of commands, the switch statement function
is called tpm2_ordinal_duration_index().
3. Fix kdoc comments for tpm2_calc_ordinal_duration().

Signed-off-by: Tomas Winkler <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---
V2-V3: Rebase.
V4: 1. Fix kdoc
2. Rename tpm2_ordinal_duration() to tpm2_ordinal_duration_index()
3. Move the two functions close to each other in the file.
V5: Adjust the kdoc to the new standard.
V6: Remove redundant comma in the kdoc.

drivers/char/tpm/tpm.h | 41 +++++---
drivers/char/tpm/tpm2-cmd.c | 241 +++++++++++++++++---------------------------
2 files changed, 118 insertions(+), 164 deletions(-)

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index f20dc8ece348..0f08518b525d 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -134,22 +134,31 @@ enum tpm2_algorithms {
};

enum tpm2_command_codes {
- TPM2_CC_FIRST = 0x011F,
- TPM2_CC_CREATE_PRIMARY = 0x0131,
- TPM2_CC_SELF_TEST = 0x0143,
- TPM2_CC_STARTUP = 0x0144,
- TPM2_CC_SHUTDOWN = 0x0145,
- 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,
- TPM2_CC_GET_RANDOM = 0x017B,
- TPM2_CC_PCR_READ = 0x017E,
- TPM2_CC_PCR_EXTEND = 0x0182,
- TPM2_CC_LAST = 0x018F,
+ TPM2_CC_FIRST = 0x011F,
+ TPM2_CC_HIERARCHY_CONTROL = 0x0121,
+ TPM2_CC_HIERARCHY_CHANGE_AUTH = 0x0129,
+ TPM2_CC_CREATE_PRIMARY = 0x0131,
+ TPM2_CC_SEQUENCE_COMPLETE = 0x013E,
+ TPM2_CC_SELF_TEST = 0x0143,
+ TPM2_CC_STARTUP = 0x0144,
+ TPM2_CC_SHUTDOWN = 0x0145,
+ TPM2_CC_NV_READ = 0x014E,
+ TPM2_CC_CREATE = 0x0153,
+ TPM2_CC_LOAD = 0x0157,
+ TPM2_CC_SEQUENCE_UPDATE = 0x015C,
+ TPM2_CC_UNSEAL = 0x015E,
+ TPM2_CC_CONTEXT_LOAD = 0x0161,
+ TPM2_CC_CONTEXT_SAVE = 0x0162,
+ TPM2_CC_FLUSH_CONTEXT = 0x0165,
+ TPM2_CC_VERIFY_SIGNATURE = 0x0177,
+ TPM2_CC_GET_CAPABILITY = 0x017A,
+ TPM2_CC_GET_RANDOM = 0x017B,
+ TPM2_CC_PCR_READ = 0x017E,
+ TPM2_CC_PCR_EXTEND = 0x0182,
+ TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185,
+ TPM2_CC_HASH_SEQUENCE_START = 0x0186,
+ TPM2_CC_CREATE_LOADED = 0x0191,
+ TPM2_CC_LAST = 0x0193, /* Spec 1.36 */
};

enum tpm2_permanent_handles {
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 3acf4fd4e5a5..d26b439976bc 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -40,129 +40,100 @@ static struct tpm2_hash tpm2_hash_map[] = {
{HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},
};

-/*
- * Array with one entry per ordinal defining the maximum amount
- * of time the chip could take to return the result. The values
- * of the SHORT, MEDIUM, and LONG durations are taken from the
- * PC Client Profile (PTP) specification.
- * LONG_LONG is for commands that generates keys which empirically
- * takes longer time on some systems.
+/**
+ * tpm2_ordinal_duration_index() - returns an index to the chip duration table
+ * @ordinal: TPM command ordinal.
+ *
+ * The function returns an index to the chip duration table
+ * (enum tpm_duration), that describes the maximum amount of
+ * time the chip could take to return the result for a particular ordinal.
+ *
+ * The values of the MEDIUM, and LONG durations are taken
+ * from the PC Client Profile (PTP) specification (750, 2000 msec)
+ *
+ * LONG_LONG is for commands that generates keys which empirically takes
+ * a longer time on some systems.
+ *
+ * Return:
+ * * TPM_MEDIUM
+ * * TPM_LONG
+ * * TPM_LONG_LONG
+ * * TPM_UNDEFINED
*/
-static const u8 tpm2_ordinal_duration[TPM2_CC_LAST - TPM2_CC_FIRST + 1] = {
- TPM_UNDEFINED, /* 11F */
- TPM_UNDEFINED, /* 120 */
- TPM_LONG, /* 121 */
- TPM_UNDEFINED, /* 122 */
- TPM_UNDEFINED, /* 123 */
- TPM_UNDEFINED, /* 124 */
- TPM_UNDEFINED, /* 125 */
- TPM_UNDEFINED, /* 126 */
- TPM_UNDEFINED, /* 127 */
- TPM_UNDEFINED, /* 128 */
- TPM_LONG, /* 129 */
- TPM_UNDEFINED, /* 12a */
- TPM_UNDEFINED, /* 12b */
- TPM_UNDEFINED, /* 12c */
- TPM_UNDEFINED, /* 12d */
- TPM_UNDEFINED, /* 12e */
- TPM_UNDEFINED, /* 12f */
- TPM_UNDEFINED, /* 130 */
- TPM_LONG_LONG, /* 131 */
- TPM_UNDEFINED, /* 132 */
- TPM_UNDEFINED, /* 133 */
- TPM_UNDEFINED, /* 134 */
- TPM_UNDEFINED, /* 135 */
- TPM_UNDEFINED, /* 136 */
- TPM_UNDEFINED, /* 137 */
- TPM_UNDEFINED, /* 138 */
- TPM_UNDEFINED, /* 139 */
- TPM_UNDEFINED, /* 13a */
- TPM_UNDEFINED, /* 13b */
- TPM_UNDEFINED, /* 13c */
- TPM_UNDEFINED, /* 13d */
- TPM_MEDIUM, /* 13e */
- TPM_UNDEFINED, /* 13f */
- TPM_UNDEFINED, /* 140 */
- TPM_UNDEFINED, /* 141 */
- TPM_UNDEFINED, /* 142 */
- TPM_LONG, /* 143 */
- TPM_MEDIUM, /* 144 */
- TPM_UNDEFINED, /* 145 */
- TPM_UNDEFINED, /* 146 */
- TPM_UNDEFINED, /* 147 */
- TPM_UNDEFINED, /* 148 */
- TPM_UNDEFINED, /* 149 */
- TPM_UNDEFINED, /* 14a */
- TPM_UNDEFINED, /* 14b */
- TPM_UNDEFINED, /* 14c */
- TPM_UNDEFINED, /* 14d */
- TPM_LONG, /* 14e */
- TPM_UNDEFINED, /* 14f */
- TPM_UNDEFINED, /* 150 */
- TPM_UNDEFINED, /* 151 */
- TPM_UNDEFINED, /* 152 */
- TPM_LONG_LONG, /* 153 */
- TPM_UNDEFINED, /* 154 */
- TPM_UNDEFINED, /* 155 */
- TPM_UNDEFINED, /* 156 */
- TPM_UNDEFINED, /* 157 */
- TPM_UNDEFINED, /* 158 */
- TPM_UNDEFINED, /* 159 */
- TPM_UNDEFINED, /* 15a */
- TPM_UNDEFINED, /* 15b */
- TPM_MEDIUM, /* 15c */
- TPM_UNDEFINED, /* 15d */
- TPM_UNDEFINED, /* 15e */
- TPM_UNDEFINED, /* 15f */
- TPM_UNDEFINED, /* 160 */
- TPM_UNDEFINED, /* 161 */
- TPM_UNDEFINED, /* 162 */
- TPM_UNDEFINED, /* 163 */
- TPM_UNDEFINED, /* 164 */
- TPM_UNDEFINED, /* 165 */
- TPM_UNDEFINED, /* 166 */
- TPM_UNDEFINED, /* 167 */
- TPM_UNDEFINED, /* 168 */
- TPM_UNDEFINED, /* 169 */
- TPM_UNDEFINED, /* 16a */
- TPM_UNDEFINED, /* 16b */
- TPM_UNDEFINED, /* 16c */
- TPM_UNDEFINED, /* 16d */
- TPM_UNDEFINED, /* 16e */
- TPM_UNDEFINED, /* 16f */
- TPM_UNDEFINED, /* 170 */
- TPM_UNDEFINED, /* 171 */
- TPM_UNDEFINED, /* 172 */
- TPM_UNDEFINED, /* 173 */
- TPM_UNDEFINED, /* 174 */
- TPM_UNDEFINED, /* 175 */
- TPM_UNDEFINED, /* 176 */
- TPM_LONG, /* 177 */
- TPM_UNDEFINED, /* 178 */
- TPM_UNDEFINED, /* 179 */
- TPM_MEDIUM, /* 17a */
- TPM_LONG, /* 17b */
- TPM_UNDEFINED, /* 17c */
- TPM_UNDEFINED, /* 17d */
- TPM_UNDEFINED, /* 17e */
- TPM_UNDEFINED, /* 17f */
- TPM_UNDEFINED, /* 180 */
- TPM_UNDEFINED, /* 181 */
- TPM_MEDIUM, /* 182 */
- TPM_UNDEFINED, /* 183 */
- TPM_UNDEFINED, /* 184 */
- TPM_MEDIUM, /* 185 */
- TPM_MEDIUM, /* 186 */
- TPM_UNDEFINED, /* 187 */
- TPM_UNDEFINED, /* 188 */
- TPM_UNDEFINED, /* 189 */
- TPM_UNDEFINED, /* 18a */
- TPM_UNDEFINED, /* 18b */
- TPM_UNDEFINED, /* 18c */
- TPM_UNDEFINED, /* 18d */
- TPM_UNDEFINED, /* 18e */
- TPM_UNDEFINED /* 18f */
-};
+static u8 tpm2_ordinal_duration_index(u32 ordinal)
+{
+ switch (ordinal) {
+ /* Startup */
+ case TPM2_CC_STARTUP: /* 144 */
+ return TPM_MEDIUM;
+
+ case TPM2_CC_SELF_TEST: /* 143 */
+ return TPM_LONG;
+
+ case TPM2_CC_GET_RANDOM: /* 17B */
+ return TPM_LONG;
+
+ case TPM2_CC_SEQUENCE_UPDATE: /* 15C */
+ return TPM_MEDIUM;
+ case TPM2_CC_SEQUENCE_COMPLETE: /* 13E */
+ return TPM_MEDIUM;
+ case TPM2_CC_EVENT_SEQUENCE_COMPLETE: /* 185 */
+ return TPM_MEDIUM;
+ case TPM2_CC_HASH_SEQUENCE_START: /* 186 */
+ return TPM_MEDIUM;
+
+ case TPM2_CC_VERIFY_SIGNATURE: /* 177 */
+ return TPM_LONG;
+
+ case TPM2_CC_PCR_EXTEND: /* 182 */
+ return TPM_MEDIUM;
+
+ case TPM2_CC_HIERARCHY_CONTROL: /* 121 */
+ return TPM_LONG;
+ case TPM2_CC_HIERARCHY_CHANGE_AUTH: /* 129 */
+ return TPM_LONG;
+
+ case TPM2_CC_GET_CAPABILITY: /* 17A */
+ return TPM_MEDIUM;
+
+ case TPM2_CC_NV_READ: /* 14E */
+ return TPM_LONG;
+
+ case TPM2_CC_CREATE_PRIMARY: /* 131 */
+ return TPM_LONG_LONG;
+ case TPM2_CC_CREATE: /* 153 */
+ return TPM_LONG_LONG;
+ case TPM2_CC_CREATE_LOADED: /* 191 */
+ return TPM_LONG_LONG;
+
+ default:
+ return TPM_UNDEFINED;
+ }
+}
+
+/**
+ * tpm2_calc_ordinal_duration() - calculate the maximum command duration
+ * @chip: TPM chip to use.
+ * @ordinal: TPM command ordinal.
+ *
+ * The function returns the maximum amount of time the chip could take
+ * to return the result for a particular ordinal in jiffies.
+ *
+ * Return: A maximal duration time for an ordinal in jiffies.
+ */
+unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
+{
+ unsigned int index;
+
+ index = tpm2_ordinal_duration_index(ordinal);
+
+ if (index != TPM_UNDEFINED)
+ return chip->duration[index];
+ else
+ return msecs_to_jiffies(TPM2_DURATION_DEFAULT);
+}
+EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration);
+

struct tpm2_pcr_read_out {
__be32 update_cnt;
@@ -748,32 +719,6 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type)
tpm_buf_destroy(&buf);
}

-/*
- * tpm2_calc_ordinal_duration() - maximum duration for a command
- *
- * @chip: TPM chip to use.
- * @ordinal: command code number.
- *
- * Return: maximum duration for a command
- */
-unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
-{
- int index = TPM_UNDEFINED;
- int duration = 0;
-
- if (ordinal >= TPM2_CC_FIRST && ordinal <= TPM2_CC_LAST)
- index = tpm2_ordinal_duration[ordinal - TPM2_CC_FIRST];
-
- if (index != TPM_UNDEFINED)
- duration = chip->duration[index];
-
- if (duration <= 0)
- duration = msecs_to_jiffies(TPM2_DURATION_DEFAULT);
-
- return duration;
-}
-EXPORT_SYMBOL_GPL(tpm2_calc_ordinal_duration);
-
/**
* tpm2_do_selftest() - ensure that all self tests have passed
*
--
2.14.4


2018-10-17 06:53:55

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 05/20] tpm: factor out tpm_get_timeouts()

Factor out tpm_get_timeouts() into tpm2_get_timeouts()
and tpm1_get_timeouts()

V2-V3: Rebase
V4: Fix the commit message.
V5: Resend.
V6: Remove tpm1_auto_startup() declaration.

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---
drivers/char/tpm/tpm-interface.c | 127 ++-------------------------------------
drivers/char/tpm/tpm.h | 3 +
drivers/char/tpm/tpm1-cmd.c | 106 ++++++++++++++++++++++++++++++++
drivers/char/tpm/tpm2-cmd.c | 22 +++++++
4 files changed, 135 insertions(+), 123 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index ca09f84bfb27..20f5c15584e4 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -503,132 +503,13 @@ EXPORT_SYMBOL_GPL(tpm_getcap);

int tpm_get_timeouts(struct tpm_chip *chip)
{
- cap_t cap;
- unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4];
- ssize_t rc;
-
if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)
return 0;

- if (chip->flags & TPM_CHIP_FLAG_TPM2) {
- /* Fixed timeouts for TPM2 */
- chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
- chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
- chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
- chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);
- chip->duration[TPM_SHORT] =
- msecs_to_jiffies(TPM2_DURATION_SHORT);
- chip->duration[TPM_MEDIUM] =
- msecs_to_jiffies(TPM2_DURATION_MEDIUM);
- chip->duration[TPM_LONG] =
- msecs_to_jiffies(TPM2_DURATION_LONG);
- chip->duration[TPM_LONG_LONG] =
- msecs_to_jiffies(TPM2_DURATION_LONG_LONG);
-
- chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
- return 0;
- }
-
- rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
- sizeof(cap.timeout));
- if (rc == TPM_ERR_INVALID_POSTINIT) {
- if (tpm_startup(chip))
- return rc;
-
- rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
- "attempting to determine the timeouts",
- sizeof(cap.timeout));
- }
-
- if (rc) {
- dev_err(&chip->dev,
- "A TPM error (%zd) occurred attempting to determine the timeouts\n",
- rc);
- return rc;
- }
-
- timeout_old[0] = jiffies_to_usecs(chip->timeout_a);
- timeout_old[1] = jiffies_to_usecs(chip->timeout_b);
- timeout_old[2] = jiffies_to_usecs(chip->timeout_c);
- timeout_old[3] = jiffies_to_usecs(chip->timeout_d);
- timeout_chip[0] = be32_to_cpu(cap.timeout.a);
- timeout_chip[1] = be32_to_cpu(cap.timeout.b);
- timeout_chip[2] = be32_to_cpu(cap.timeout.c);
- timeout_chip[3] = be32_to_cpu(cap.timeout.d);
- memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff));
-
- /*
- * Provide ability for vendor overrides of timeout values in case
- * of misreporting.
- */
- if (chip->ops->update_timeouts != NULL)
- chip->timeout_adjusted =
- chip->ops->update_timeouts(chip, timeout_eff);
-
- if (!chip->timeout_adjusted) {
- /* Restore default if chip reported 0 */
- int i;
-
- for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) {
- if (timeout_eff[i])
- continue;
-
- timeout_eff[i] = timeout_old[i];
- chip->timeout_adjusted = true;
- }
-
- if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) {
- /* timeouts in msec rather usec */
- for (i = 0; i != ARRAY_SIZE(timeout_eff); i++)
- timeout_eff[i] *= 1000;
- chip->timeout_adjusted = true;
- }
- }
-
- /* Report adjusted timeouts */
- if (chip->timeout_adjusted) {
- dev_info(&chip->dev,
- HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n",
- timeout_chip[0], timeout_eff[0],
- timeout_chip[1], timeout_eff[1],
- timeout_chip[2], timeout_eff[2],
- timeout_chip[3], timeout_eff[3]);
- }
-
- chip->timeout_a = usecs_to_jiffies(timeout_eff[0]);
- chip->timeout_b = usecs_to_jiffies(timeout_eff[1]);
- chip->timeout_c = usecs_to_jiffies(timeout_eff[2]);
- chip->timeout_d = usecs_to_jiffies(timeout_eff[3]);
-
- rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap,
- "attempting to determine the durations",
- sizeof(cap.duration));
- if (rc)
- return rc;
-
- chip->duration[TPM_SHORT] =
- usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short));
- chip->duration[TPM_MEDIUM] =
- usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium));
- chip->duration[TPM_LONG] =
- usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long));
- chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */
-
- /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
- * value wrong and apparently reports msecs rather than usecs. So we
- * fix up the resulting too-small TPM_SHORT value to make things work.
- * We also scale the TPM_MEDIUM and -_LONG values by 1000.
- */
- if (chip->duration[TPM_SHORT] < (HZ / 100)) {
- chip->duration[TPM_SHORT] = HZ;
- chip->duration[TPM_MEDIUM] *= 1000;
- chip->duration[TPM_LONG] *= 1000;
- chip->duration_adjusted = true;
- dev_info(&chip->dev, "Adjusting TPM timeout parameters.");
- }
-
- chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
- return 0;
+ if (chip->flags & TPM_CHIP_FLAG_TPM2)
+ return tpm2_get_timeouts(chip);
+ else
+ return tpm1_get_timeouts(chip);
}
EXPORT_SYMBOL_GPL(tpm_get_timeouts);

diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 73511cd89bef..4ea51bbdbfae 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -546,6 +546,8 @@ ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
int tpm_get_timeouts(struct tpm_chip *);
int tpm1_auto_startup(struct tpm_chip *chip);
int tpm_do_selftest(struct tpm_chip *chip);
+
+int tpm1_get_timeouts(struct tpm_chip *chip);
unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm_pm_suspend(struct device *dev);
@@ -585,6 +587,7 @@ static inline u32 tpm2_rc_value(u32 rc)
return (rc & BIT(7)) ? rc & 0xff : rc;
}

+int tpm2_get_timeouts(struct tpm_chip *chip);
int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf);
int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, u32 count,
struct tpm2_digest *digests);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index dfbe9c60cbcf..978946748ea3 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -307,3 +307,109 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal)
else
return duration;
}
+
+int tpm1_get_timeouts(struct tpm_chip *chip)
+{
+ cap_t cap;
+ unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4];
+ ssize_t rc;
+
+ rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
+ sizeof(cap.timeout));
+ if (rc == TPM_ERR_INVALID_POSTINIT) {
+ if (tpm_startup(chip))
+ return rc;
+
+ rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
+ "attempting to determine the timeouts",
+ sizeof(cap.timeout));
+ }
+
+ if (rc) {
+ dev_err(&chip->dev, "A TPM error (%zd) occurred attempting to determine the timeouts\n",
+ rc);
+ return rc;
+ }
+
+ timeout_old[0] = jiffies_to_usecs(chip->timeout_a);
+ timeout_old[1] = jiffies_to_usecs(chip->timeout_b);
+ timeout_old[2] = jiffies_to_usecs(chip->timeout_c);
+ timeout_old[3] = jiffies_to_usecs(chip->timeout_d);
+ timeout_chip[0] = be32_to_cpu(cap.timeout.a);
+ timeout_chip[1] = be32_to_cpu(cap.timeout.b);
+ timeout_chip[2] = be32_to_cpu(cap.timeout.c);
+ timeout_chip[3] = be32_to_cpu(cap.timeout.d);
+ memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff));
+
+ /*
+ * Provide ability for vendor overrides of timeout values in case
+ * of misreporting.
+ */
+ if (chip->ops->update_timeouts)
+ chip->timeout_adjusted =
+ chip->ops->update_timeouts(chip, timeout_eff);
+
+ if (!chip->timeout_adjusted) {
+ /* Restore default if chip reported 0 */
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) {
+ if (timeout_eff[i])
+ continue;
+
+ timeout_eff[i] = timeout_old[i];
+ chip->timeout_adjusted = true;
+ }
+
+ if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) {
+ /* timeouts in msec rather usec */
+ for (i = 0; i != ARRAY_SIZE(timeout_eff); i++)
+ timeout_eff[i] *= 1000;
+ chip->timeout_adjusted = true;
+ }
+ }
+
+ /* Report adjusted timeouts */
+ if (chip->timeout_adjusted) {
+ dev_info(&chip->dev, HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n",
+ timeout_chip[0], timeout_eff[0],
+ timeout_chip[1], timeout_eff[1],
+ timeout_chip[2], timeout_eff[2],
+ timeout_chip[3], timeout_eff[3]);
+ }
+
+ chip->timeout_a = usecs_to_jiffies(timeout_eff[0]);
+ chip->timeout_b = usecs_to_jiffies(timeout_eff[1]);
+ chip->timeout_c = usecs_to_jiffies(timeout_eff[2]);
+ chip->timeout_d = usecs_to_jiffies(timeout_eff[3]);
+
+ rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap,
+ "attempting to determine the durations",
+ sizeof(cap.duration));
+ if (rc)
+ return rc;
+
+ chip->duration[TPM_SHORT] =
+ usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_short));
+ chip->duration[TPM_MEDIUM] =
+ usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_medium));
+ chip->duration[TPM_LONG] =
+ usecs_to_jiffies(be32_to_cpu(cap.duration.tpm_long));
+ chip->duration[TPM_LONG_LONG] = 0; /* not used under 1.2 */
+
+ /* The Broadcom BCM0102 chipset in a Dell Latitude D820 gets the above
+ * value wrong and apparently reports msecs rather than usecs. So we
+ * fix up the resulting too-small TPM_SHORT value to make things work.
+ * We also scale the TPM_MEDIUM and -_LONG values by 1000.
+ */
+ if (chip->duration[TPM_SHORT] < (HZ / 100)) {
+ chip->duration[TPM_SHORT] = HZ;
+ chip->duration[TPM_MEDIUM] *= 1000;
+ chip->duration[TPM_LONG] *= 1000;
+ chip->duration_adjusted = true;
+ dev_info(&chip->dev, "Adjusting TPM timeout parameters.");
+ }
+
+ chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
+ return 0;
+}
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c
index 3eef5565286d..dd2e98f4de08 100644
--- a/drivers/char/tpm/tpm2-cmd.c
+++ b/drivers/char/tpm/tpm2-cmd.c
@@ -40,6 +40,28 @@ static struct tpm2_hash tpm2_hash_map[] = {
{HASH_ALGO_SM3_256, TPM2_ALG_SM3_256},
};

+int tpm2_get_timeouts(struct tpm_chip *chip)
+{
+ /* Fixed timeouts for TPM2 */
+ chip->timeout_a = msecs_to_jiffies(TPM2_TIMEOUT_A);
+ chip->timeout_b = msecs_to_jiffies(TPM2_TIMEOUT_B);
+ chip->timeout_c = msecs_to_jiffies(TPM2_TIMEOUT_C);
+ chip->timeout_d = msecs_to_jiffies(TPM2_TIMEOUT_D);
+
+ /* PTP spec timeouts */
+ chip->duration[TPM_SHORT] = msecs_to_jiffies(TPM2_DURATION_SHORT);
+ chip->duration[TPM_MEDIUM] = msecs_to_jiffies(TPM2_DURATION_MEDIUM);
+ chip->duration[TPM_LONG] = msecs_to_jiffies(TPM2_DURATION_LONG);
+
+ /* Key creation commands long timeouts */
+ chip->duration[TPM_LONG_LONG] =
+ msecs_to_jiffies(TPM2_DURATION_LONG_LONG);
+
+ chip->flags |= TPM_CHIP_FLAG_HAVE_TIMEOUTS;
+
+ return 0;
+}
+
/**
* tpm2_ordinal_duration_index() - returns an index to the chip duration table
* @ordinal: TPM command ordinal.
--
2.14.4


2018-10-17 06:54:17

by Tomas Winkler

[permalink] [raw]
Subject: [PATCH v6 07/20] tpm: move tpm_getcap to tpm1-cmd.c

1. Move tpm_getcap to tpm1-cmd. Rename the function to tpm1_getcap.
2. Remove unused tpm_getcap_header with unused constant
as this functionality is already implemented using tpm_buf construct.

Fixes warning:
drivers/char/tpm/tpm-interface.c:452:38: warning: ‘tpm_getcap_header’ defined but not used [-Wunused-const-variable=]
static const struct tpm_input_header tpm_getcap_header = {
^~~~~~~~~~~~~~~~~
3. Drop unused TPM_DIGEST_SIZE. It's already defined in
include/linux/tpm.h

Signed-off-by: Tomas Winkler <[email protected]>
Reviewed-by: Jarkko Sakkinen <[email protected]>
Tested-by: Jarkko Sakkinen <[email protected]>
---
V2-V3: Rebase
V4-V6: Resend

drivers/char/tpm/tpm-interface.c | 47 +-----------------------------------
drivers/char/tpm/tpm-sysfs.c | 48 ++++++++++++++++++-------------------
drivers/char/tpm/tpm.h | 4 ++--
drivers/char/tpm/tpm1-cmd.c | 51 +++++++++++++++++++++++++++++++++-------
drivers/char/tpm/tpm_tis_core.c | 2 +-
5 files changed, 71 insertions(+), 81 deletions(-)

diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
index 177795b408ff..486e211b03a0 100644
--- a/drivers/char/tpm/tpm-interface.c
+++ b/drivers/char/tpm/tpm-interface.c
@@ -455,52 +455,6 @@ int tpm_startup(struct tpm_chip *chip)
return rc;
}

-#define TPM_DIGEST_SIZE 20
-#define TPM_RET_CODE_IDX 6
-#define TPM_INTERNAL_RESULT_SIZE 200
-#define TPM_ORD_GET_CAP 101
-#define TPM_ORD_GET_RANDOM 70
-
-static const struct tpm_input_header tpm_getcap_header = {
- .tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
- .length = cpu_to_be32(22),
- .ordinal = cpu_to_be32(TPM_ORD_GET_CAP)
-};
-
-ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
- const char *desc, size_t min_cap_length)
-{
- struct tpm_buf buf;
- int rc;
-
- rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP);
- if (rc)
- return rc;
-
- if (subcap_id == TPM_CAP_VERSION_1_1 ||
- subcap_id == TPM_CAP_VERSION_1_2) {
- tpm_buf_append_u32(&buf, subcap_id);
- tpm_buf_append_u32(&buf, 0);
- } else {
- if (subcap_id == TPM_CAP_FLAG_PERM ||
- subcap_id == TPM_CAP_FLAG_VOL)
- tpm_buf_append_u32(&buf, TPM_CAP_FLAG);
- else
- tpm_buf_append_u32(&buf, TPM_CAP_PROP);
-
- tpm_buf_append_u32(&buf, 4);
- tpm_buf_append_u32(&buf, subcap_id);
- }
- rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
- min_cap_length, 0, desc);
- if (!rc)
- *cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4];
-
- tpm_buf_destroy(&buf);
- return rc;
-}
-EXPORT_SYMBOL_GPL(tpm_getcap);
-
int tpm_get_timeouts(struct tpm_chip *chip)
{
if (chip->flags & TPM_CHIP_FLAG_HAVE_TIMEOUTS)
@@ -858,6 +812,7 @@ int tpm_pm_resume(struct device *dev)
}
EXPORT_SYMBOL_GPL(tpm_pm_resume);

+#define TPM_ORD_GET_RANDOM 70
#define TPM_GETRANDOM_RESULT_SIZE 18
static const struct tpm_input_header tpm_getrandom_header = {
.tag = cpu_to_be16(TPM_TAG_RQU_COMMAND),
diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c
index 83a77a445538..008515314ae3 100644
--- a/drivers/char/tpm/tpm-sysfs.c
+++ b/drivers/char/tpm/tpm-sysfs.c
@@ -106,9 +106,9 @@ static ssize_t pcrs_show(struct device *dev, struct device_attribute *attr,
char *str = buf;
struct tpm_chip *chip = to_tpm_chip(dev);

- rc = tpm_getcap(chip, TPM_CAP_PROP_PCR, &cap,
- "attempting to determine the number of PCRS",
- sizeof(cap.num_pcrs));
+ rc = tpm1_getcap(chip, TPM_CAP_PROP_PCR, &cap,
+ "attempting to determine the number of PCRS",
+ sizeof(cap.num_pcrs));
if (rc)
return 0;

@@ -132,9 +132,9 @@ static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
cap_t cap;
ssize_t rc;

- rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
- "attempting to determine the permanent enabled state",
- sizeof(cap.perm_flags));
+ rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
+ "attempting to determine the permanent enabled state",
+ sizeof(cap.perm_flags));
if (rc)
return 0;

@@ -149,9 +149,9 @@ static ssize_t active_show(struct device *dev, struct device_attribute *attr,
cap_t cap;
ssize_t rc;

- rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
- "attempting to determine the permanent active state",
- sizeof(cap.perm_flags));
+ rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_PERM, &cap,
+ "attempting to determine the permanent active state",
+ sizeof(cap.perm_flags));
if (rc)
return 0;

@@ -166,9 +166,9 @@ static ssize_t owned_show(struct device *dev, struct device_attribute *attr,
cap_t cap;
ssize_t rc;

- rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap,
- "attempting to determine the owner state",
- sizeof(cap.owned));
+ rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_PROP_OWNER, &cap,
+ "attempting to determine the owner state",
+ sizeof(cap.owned));
if (rc)
return 0;

@@ -183,9 +183,9 @@ static ssize_t temp_deactivated_show(struct device *dev,
cap_t cap;
ssize_t rc;

- rc = tpm_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap,
- "attempting to determine the temporary state",
- sizeof(cap.stclear_flags));
+ rc = tpm1_getcap(to_tpm_chip(dev), TPM_CAP_FLAG_VOL, &cap,
+ "attempting to determine the temporary state",
+ sizeof(cap.stclear_flags));
if (rc)
return 0;

@@ -202,18 +202,18 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
ssize_t rc;
char *str = buf;

- rc = tpm_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap,
- "attempting to determine the manufacturer",
- sizeof(cap.manufacturer_id));
+ rc = tpm1_getcap(chip, TPM_CAP_PROP_MANUFACTURER, &cap,
+ "attempting to determine the manufacturer",
+ sizeof(cap.manufacturer_id));
if (rc)
return 0;
str += sprintf(str, "Manufacturer: 0x%x\n",
be32_to_cpu(cap.manufacturer_id));

/* Try to get a TPM version 1.2 TPM_CAP_VERSION_INFO */
- rc = tpm_getcap(chip, TPM_CAP_VERSION_1_2, &cap,
- "attempting to determine the 1.2 version",
- sizeof(cap.tpm_version_1_2));
+ rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_2, &cap,
+ "attempting to determine the 1.2 version",
+ sizeof(cap.tpm_version_1_2));
if (!rc) {
str += sprintf(str,
"TCG version: %d.%d\nFirmware version: %d.%d\n",
@@ -223,9 +223,9 @@ static ssize_t caps_show(struct device *dev, struct device_attribute *attr,
cap.tpm_version_1_2.revMinor);
} else {
/* Otherwise just use TPM_STRUCT_VER */
- rc = tpm_getcap(chip, TPM_CAP_VERSION_1_1, &cap,
- "attempting to determine the 1.1 version",
- sizeof(cap.tpm_version));
+ rc = tpm1_getcap(chip, TPM_CAP_VERSION_1_1, &cap,
+ "attempting to determine the 1.1 version",
+ sizeof(cap.tpm_version));
if (rc)
return 0;
str += sprintf(str,
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 221b6dcd15a1..05c386b3ab12 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -541,8 +541,6 @@ ssize_t tpm_transmit_cmd(struct tpm_chip *chip, struct tpm_space *space,
size_t min_rsp_body_length, unsigned int flags,
const char *desc);
int tpm_startup(struct tpm_chip *chip);
-ssize_t tpm_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
- const char *desc, size_t min_cap_length);
int tpm_get_timeouts(struct tpm_chip *);
int tpm1_auto_startup(struct tpm_chip *chip);
int tpm_do_selftest(struct tpm_chip *chip);
@@ -551,6 +549,8 @@ int tpm1_get_timeouts(struct tpm_chip *chip);
unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
const char *log_msg);
+ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
+ const char *desc, size_t min_cap_length);
unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
int tpm_pm_suspend(struct device *dev);
int tpm_pm_resume(struct device *dev);
diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c
index ec242397e6dc..3bd079587ef5 100644
--- a/drivers/char/tpm/tpm1-cmd.c
+++ b/drivers/char/tpm/tpm1-cmd.c
@@ -314,15 +314,15 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4];
ssize_t rc;

- rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
- sizeof(cap.timeout));
+ rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, NULL,
+ sizeof(cap.timeout));
if (rc == TPM_ERR_INVALID_POSTINIT) {
if (tpm_startup(chip))
return rc;

- rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
- "attempting to determine the timeouts",
- sizeof(cap.timeout));
+ rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap,
+ "attempting to determine the timeouts",
+ sizeof(cap.timeout));
}

if (rc) {
@@ -383,9 +383,9 @@ int tpm1_get_timeouts(struct tpm_chip *chip)
chip->timeout_c = usecs_to_jiffies(timeout_eff[2]);
chip->timeout_d = usecs_to_jiffies(timeout_eff[3]);

- rc = tpm_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap,
- "attempting to determine the durations",
- sizeof(cap.duration));
+ rc = tpm1_getcap(chip, TPM_CAP_PROP_TIS_DURATION, &cap,
+ "attempting to determine the durations",
+ sizeof(cap.duration));
if (rc)
return rc;

@@ -434,3 +434,38 @@ int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
tpm_buf_destroy(&buf);
return rc;
}
+
+#define TPM_ORD_GET_CAP 101
+ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap,
+ const char *desc, size_t min_cap_length)
+{
+ struct tpm_buf buf;
+ int rc;
+
+ rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP);
+ if (rc)
+ return rc;
+
+ if (subcap_id == TPM_CAP_VERSION_1_1 ||
+ subcap_id == TPM_CAP_VERSION_1_2) {
+ tpm_buf_append_u32(&buf, subcap_id);
+ tpm_buf_append_u32(&buf, 0);
+ } else {
+ if (subcap_id == TPM_CAP_FLAG_PERM ||
+ subcap_id == TPM_CAP_FLAG_VOL)
+ tpm_buf_append_u32(&buf, TPM_CAP_FLAG);
+ else
+ tpm_buf_append_u32(&buf, TPM_CAP_PROP);
+
+ tpm_buf_append_u32(&buf, 4);
+ tpm_buf_append_u32(&buf, subcap_id);
+ }
+ rc = tpm_transmit_cmd(chip, NULL, buf.data, PAGE_SIZE,
+ min_cap_length, 0, desc);
+ if (!rc)
+ *cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4];
+
+ tpm_buf_destroy(&buf);
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm1_getcap);
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
index f9e73d0f9386..ced01ec146b5 100644
--- a/drivers/char/tpm/tpm_tis_core.c
+++ b/drivers/char/tpm/tpm_tis_core.c
@@ -664,7 +664,7 @@ static int tpm_tis_gen_interrupt(struct tpm_chip *chip)
if (chip->flags & TPM_CHIP_FLAG_TPM2)
return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc);
else
- return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc,
+ return tpm1_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc,
0);
}

--
2.14.4


2018-10-17 11:58:37

by Nayna Jain

[permalink] [raw]
Subject: Re: [PATCH v6 03/20] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c



On 10/17/2018 12:15 PM, Tomas Winkler wrote:
> diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c
> index caa86b19c76d..5d20e98b844f 100644
> --- a/drivers/char/tpm/tpm_i2c_nuvoton.c
> +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
> @@ -370,6 +370,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
> struct i2c_client *client = to_i2c_client(dev);
> u32 ordinal;
> size_t count = 0;
> + unsigned long duration;
> int burst_count, bytes2write, retries, rc = -EIO;
>
> for (retries = 0; retries < TPM_RETRY; retries++) {
> @@ -455,12 +456,11 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf, size_t len)
> return rc;
> }
> ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> - rc = i2c_nuvoton_wait_for_data_avail(chip,
> - tpm_calc_ordinal_duration(chip,
> - ordinal),
> - &priv->read_queue);
> + duration = tpm1_calc_ordinal_duration(chip, ordinal);


This version of the patch didn't address my previous comment -
"The original code in the nuvoton driver does not differentiate between
TPM 1.2 and TPM 2.0 as it does in tpm_tis_core.c.
Before making any changes, I would first fix it, so that it could easily
be backported. Only then do the refactoring."

Thanks & Regards,
   - Nayna


> + rc = i2c_nuvoton_wait_for_data_avail(chip, duration, &priv->read_queue);
> if (rc) {
> - dev_err(dev, "%s() timeout command duration\n", __func__);
> + dev_err(dev, "%s() timeout command duration %ld\n",
> + __func__, duration);
> i2c_nuvoton_ready(chip);
> return rc;
> }
> diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
> index d2345d9fd7b5..14c332104de4 100644
> --- a/drivers/char/tpm/tpm_tis_core.c
> +++ b/drivers/char/tpm/tpm_tis_core.c
> @@ -476,7 +476,7 @@ static int tpm_tis_send_main(struct tpm_chip *chip, const u8 *buf, size_t len)
> if (chip->flags & TPM_CHIP_FLAG_TPM2)
> dur = tpm2_calc_ordinal_duration(chip, ordinal);
> else
> - dur = tpm_calc_ordinal_duration(chip, ordinal);
> + dur = tpm1_calc_ordinal_duration(chip, ordinal);
>
> if (wait_for_tpm_stat
> (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, dur,
> diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c
> index b150f87f38f5..77097229bf49 100644
> --- a/drivers/char/tpm/xen-tpmfront.c
> +++ b/drivers/char/tpm/xen-tpmfront.c
> @@ -164,7 +164,7 @@ static int vtpm_send(struct tpm_chip *chip, u8 *buf, size_t count)
> notify_remote_via_evtchn(priv->evtchn);
>
> ordinal = be32_to_cpu(((struct tpm_input_header*)buf)->ordinal);
> - duration = tpm_calc_ordinal_duration(chip, ordinal);
> + duration = tpm1_calc_ordinal_duration(chip, ordinal);
>
> if (wait_for_tpm_stat(chip, VTPM_STATUS_IDLE, duration,
> &priv->read_queue, true) < 0) {


2018-10-17 12:26:44

by Tomas Winkler

[permalink] [raw]
Subject: RE: [PATCH v6 03/20] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c

>
>
>
> On 10/17/2018 12:15 PM, Tomas Winkler wrote:
> > diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c
> > b/drivers/char/tpm/tpm_i2c_nuvoton.c
> > index caa86b19c76d..5d20e98b844f 100644
> > --- a/drivers/char/tpm/tpm_i2c_nuvoton.c
> > +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c
> > @@ -370,6 +370,7 @@ static int i2c_nuvoton_send(struct tpm_chip *chip,
> u8 *buf, size_t len)
> > struct i2c_client *client = to_i2c_client(dev);
> > u32 ordinal;
> > size_t count = 0;
> > + unsigned long duration;
> > int burst_count, bytes2write, retries, rc = -EIO;
> >
> > for (retries = 0; retries < TPM_RETRY; retries++) { @@ -455,12
> > +456,11 @@ static int i2c_nuvoton_send(struct tpm_chip *chip, u8 *buf,
> size_t len)
> > return rc;
> > }
> > ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> > - rc = i2c_nuvoton_wait_for_data_avail(chip,
> > - tpm_calc_ordinal_duration(chip,
> > - ordinal),
> > - &priv->read_queue);
> > + duration = tpm1_calc_ordinal_duration(chip, ordinal);
>
>
> This version of the patch didn't address my previous comment - "The original
> code in the nuvoton driver does not differentiate between TPM 1.2 and TPM
> 2.0 as it does in tpm_tis_core.c.
> Before making any changes, I would first fix it, so that it could easily be
> backported. Only then do the refactoring."

This patch doesn't change the original behavior, just change the name of the function, so there is no regression.
I would suggest there is another bug in those drivers/devices that is orthogonal to this refactoring and should not block this from merging.
According to what you say it can call just tpm_calc_oridnal_duration() instead of tpm1_calc_ordinal_duration(chip, ordinal),
but I prefer that someone that has those devices will do that change on top of this series as I cannot test it.

Thanks
Tomas

2018-10-17 15:13:40

by Nayna Jain

[permalink] [raw]
Subject: Re: [PATCH v6 03/20] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c



On 10/17/2018 05:54 PM, Winkler, Tomas wrote:
>>
>>> ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
>>> - rc = i2c_nuvoton_wait_for_data_avail(chip,
>>> - tpm_calc_ordinal_duration(chip,
>>> - ordinal),
>>> - &priv->read_queue);
>>> + duration = tpm1_calc_ordinal_duration(chip, ordinal);
>>
>> This version of the patch didn't address my previous comment - "The original
>> code in the nuvoton driver does not differentiate between TPM 1.2 and TPM
>> 2.0 as it does in tpm_tis_core.c.
>> Before making any changes, I would first fix it, so that it could easily be
>> backported. Only then do the refactoring."
> This patch doesn't change the original behavior, just change the name of the function, so there is no regression.
> I would suggest there is another bug in those drivers/devices that is orthogonal to this refactoring and should not block this from merging.

The problem is that you are inadvertently fixing a bug without realizing
it - [Patch 04/20]. Bug fixes should be addressed independently
of this change, so that they can be backported properly.

> According to what you say it can call just tpm_calc_oridnal_duration() instead of tpm1_calc_ordinal_duration(chip, ordinal),
> but I prefer that someone that has those devices will do that change on top of this series as I cannot test it.

The problem is:

1. This patch calls tpm1_calc_ordinal_duration for both the TPM 1.2 and
TPM 2.0.
2. In the next patch, it adds a new function tpm_calc_ordinal_duration
as a wrapper for both the TPM 1.2 and TPM 2.0. After this change when it
calls tpm_calc_ordinal_duration(),
it now calls different functions for TPM 1.2 and TPM 2.0. This is a
change in behavior.

Thanks & Regards,
   - Nayna

> Thanks
> Tomas
>


2018-10-17 15:29:23

by Tomas Winkler

[permalink] [raw]
Subject: RE: [PATCH v6 03/20] tpm: factor out tpm 1.x duration calculation to tpm1-cmd.c


>
>
> On 10/17/2018 05:54 PM, Winkler, Tomas wrote:
> >>
> >>> ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
> >>> - rc = i2c_nuvoton_wait_for_data_avail(chip,
> >>> - tpm_calc_ordinal_duration(chip,
> >>> - ordinal),
> >>> - &priv->read_queue);
> >>> + duration = tpm1_calc_ordinal_duration(chip, ordinal);
> >>
> >> This version of the patch didn't address my previous comment - "The
> >> original code in the nuvoton driver does not differentiate between
> >> TPM 1.2 and TPM
> >> 2.0 as it does in tpm_tis_core.c.
> >> Before making any changes, I would first fix it, so that it could
> >> easily be backported. Only then do the refactoring."
> > This patch doesn't change the original behavior, just change the name of
> the function, so there is no regression.
> > I would suggest there is another bug in those drivers/devices that is
> orthogonal to this refactoring and should not block this from merging.
>
> The problem is that you are inadvertently fixing a bug without realizing it -
> [Patch 04/20]. Bug fixes should be addressed independently of this change,
> so that they can be backported properly.
>
This would be ideal, but that's happen more than often that the fix cannot be applied w/o changes to older kernels.
I can send that patch, are you able to test it? Frankly nobody complained about it so I'm not sure what to do.

> > According to what you say it can call just
> > tpm_calc_oridnal_duration() instead of tpm1_calc_ordinal_duration(chip,
> ordinal), but I prefer that someone that has those devices will do that
> change on top of this series as I cannot test it.
>
> The problem is:
>
> 1. This patch calls tpm1_calc_ordinal_duration for both the TPM 1.2 and
> TPM 2.0.
That's correct
> 2. In the next patch, it adds a new function tpm_calc_ordinal_duration as a
> wrapper for both the TPM 1.2 and TPM 2.0. After this change when it calls
> tpm_calc_ordinal_duration(), it now calls different functions for TPM 1.2 and
> TPM 2.0. This is a change in behavior.
That's not correct, I missed that. Either someone can test the TPM 2.0 device or I need to revert it for nuvoton, in the next patch.

Thanks
Tomas