Merge branch 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security

Pull tpm updates from James Morris:

 - reduce polling delays in tpm_tis

 - support retrieving TPM 2.0 Event Log through EFI before
   ExitBootServices

 - replace tpm-rng.c with a hwrng device managed by the driver for each
   TPM device

 - TPM resource manager synthesizes TPM_RC_COMMAND_CODE response instead
   of returning -EINVAL for unknown TPM commands. This makes user space
   more sound.

 - CLKRUN fixes:

    * Keep #CLKRUN disable through the entier TPM command/response flow

    * Check whether #CLKRUN is enabled before disabling and enabling it
      again because enabling it breaks PS/2 devices on a system where it
      is disabled

* 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  tpm: remove unused variables
  tpm: remove unused data fields from I2C and OF device ID tables
  tpm: only attempt to disable the LPC CLKRUN if is already enabled
  tpm: follow coding style for variable declaration in tpm_tis_core_init()
  tpm: delete the TPM_TIS_CLK_ENABLE flag
  tpm: Update MAINTAINERS for Jason Gunthorpe
  tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()
  tpm_tis: Move ilb_base_addr to tpm_tis_data
  tpm2-cmd: allow more attempts for selftest execution
  tpm: return a TPM_RC_COMMAND_CODE response if command is not implemented
  tpm: Move Linux RNG connection to hwrng
  tpm: use struct tpm_chip for tpm_chip_find_get()
  tpm: parse TPM event logs based on EFI table
  efi: call get_event_log before ExitBootServices
  tpm: add event log format version
  tpm: rename event log provider files
  tpm: move tpm_eventlog.h outside of drivers folder
  tpm: use tpm_msleep() value as max delay
  tpm: reduce tpm polling delay in tpm_tis_core
  tpm: move wait_for_tpm_stat() to respective driver files
This commit is contained in:
Linus Torvalds 2018-01-31 13:12:31 -08:00
commit ae0cb7be35
33 changed files with 789 additions and 443 deletions

View File

@ -13869,9 +13869,10 @@ F: drivers/platform/x86/toshiba-wmi.c
TPM DEVICE DRIVER
M: Peter Huewe <peterhuewe@gmx.de>
M: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
R: Jason Gunthorpe <jgunthorpe@obsidianresearch.com>
R: Jason Gunthorpe <jgg@ziepe.ca>
L: linux-integrity@vger.kernel.org
Q: https://patchwork.kernel.org/project/linux-integrity/list/
W: https://kernsec.org/wiki/index.php/Linux_Kernel_Integrity
T: git git://git.infradead.org/users/jjs/linux-tpmdd.git
S: Maintained
F: drivers/char/tpm/

View File

@ -999,6 +999,7 @@ struct boot_params *efi_main(struct efi_config *c,
/* Ask the firmware to clear memory on unclean shutdown */
efi_enable_reset_attack_mitigation(sys_table);
efi_retrieve_tpm2_eventlog(sys_table);
setup_graphics(boot_params);

View File

@ -306,19 +306,6 @@ config HW_RANDOM_POWERNV
If unsure, say Y.
config HW_RANDOM_TPM
tristate "TPM HW Random Number Generator support"
depends on TCG_TPM
default HW_RANDOM
---help---
This driver provides kernel-side support for the Random Number
Generator in the Trusted Platform Module
To compile this driver as a module, choose M here: the
module will be called tpm-rng.
If unsure, say Y.
config HW_RANDOM_HISI
tristate "Hisilicon Random Number Generator support"
depends on HW_RANDOM && ARCH_HISI

View File

@ -27,7 +27,6 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o
obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o
obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o
obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o
obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o
obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o
obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o

View File

@ -1,50 +0,0 @@
/*
* Copyright (C) 2012 Kent Yoder IBM Corporation
*
* HWRNG interfaces to pull RNG data from a TPM
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <linux/module.h>
#include <linux/hw_random.h>
#include <linux/tpm.h>
#define MODULE_NAME "tpm-rng"
static int tpm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
return tpm_get_random(TPM_ANY_NUM, data, max);
}
static struct hwrng tpm_rng = {
.name = MODULE_NAME,
.read = tpm_rng_read,
};
static int __init rng_init(void)
{
return hwrng_register(&tpm_rng);
}
module_init(rng_init);
static void __exit rng_exit(void)
{
hwrng_unregister(&tpm_rng);
}
module_exit(rng_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Kent Yoder <key@linux.vnet.ibm.com>");
MODULE_DESCRIPTION("RNG driver for TPM devices");

View File

@ -26,6 +26,17 @@ menuconfig TCG_TPM
if TCG_TPM
config HW_RANDOM_TPM
bool "TPM HW Random Number Generator support"
depends on TCG_TPM && HW_RANDOM && !(TCG_TPM=y && HW_RANDOM=m)
default y
---help---
This setting exposes the TPM's Random Number Generator as a hwrng
device. This allows the kernel to collect randomness from the TPM at
boot, and provides the TPM randomines in /dev/hwrng.
If unsure, say Y.
config TCG_TIS_CORE
tristate
---help---

View File

@ -6,8 +6,9 @@ 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 tpm1_eventlog.o tpm2_eventlog.o \
tpm2-space.o
tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o
tpm-$(CONFIG_OF) += tpm_of.o
tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_eventlog_acpi.o
tpm-$(CONFIG_EFI) += tpm_eventlog_efi.o
tpm-$(CONFIG_OF) += tpm_eventlog_of.o
obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o
obj-$(CONFIG_TCG_TIS) += tpm_tis.o
obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o

View File

@ -26,8 +26,9 @@
#include <linux/spinlock.h>
#include <linux/freezer.h>
#include <linux/major.h>
#include <linux/tpm_eventlog.h>
#include <linux/hw_random.h>
#include "tpm.h"
#include "tpm_eventlog.h"
DEFINE_IDR(dev_nums_idr);
static DEFINE_MUTEX(idr_lock);
@ -80,21 +81,26 @@ void tpm_put_ops(struct tpm_chip *chip)
EXPORT_SYMBOL_GPL(tpm_put_ops);
/**
* tpm_chip_find_get() - return tpm_chip for a given chip number
* @chip_num: id to find
* tpm_chip_find_get() - find and reserve a TPM chip
* @chip: a &struct tpm_chip instance, %NULL for the default chip
*
* The return'd chip has been tpm_try_get_ops'd and must be released via
* tpm_put_ops
* Finds a TPM chip and reserves its class device and operations. The chip must
* be released with tpm_chip_put_ops() after use.
*
* Return:
* A reserved &struct tpm_chip instance.
* %NULL if a chip is not found.
* %NULL if the chip is not available.
*/
struct tpm_chip *tpm_chip_find_get(int chip_num)
struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip)
{
struct tpm_chip *chip, *res = NULL;
struct tpm_chip *res = NULL;
int chip_num = 0;
int chip_prev;
mutex_lock(&idr_lock);
if (chip_num == TPM_ANY_NUM) {
chip_num = 0;
if (!chip) {
do {
chip_prev = chip_num;
chip = idr_get_next(&dev_nums_idr, &chip_num);
@ -104,8 +110,7 @@ struct tpm_chip *tpm_chip_find_get(int chip_num)
}
} while (chip_prev != chip_num);
} else {
chip = idr_find(&dev_nums_idr, chip_num);
if (chip && !tpm_try_get_ops(chip))
if (!tpm_try_get_ops(chip))
res = chip;
}
@ -387,6 +392,26 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip)
return 0;
}
static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
{
struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
return tpm_get_random(chip, data, max);
}
static int tpm_add_hwrng(struct tpm_chip *chip)
{
if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM))
return 0;
snprintf(chip->hwrng_name, sizeof(chip->hwrng_name),
"tpm-rng-%d", chip->dev_num);
chip->hwrng.name = chip->hwrng_name;
chip->hwrng.read = tpm_hwrng_read;
return hwrng_register(&chip->hwrng);
}
/*
* tpm_chip_register() - create a character device for the TPM chip
* @chip: TPM chip to use.
@ -419,11 +444,13 @@ int tpm_chip_register(struct tpm_chip *chip)
tpm_add_ppi(chip);
rc = tpm_add_hwrng(chip);
if (rc)
goto out_ppi;
rc = tpm_add_char_device(chip);
if (rc) {
tpm_bios_log_teardown(chip);
return rc;
}
if (rc)
goto out_hwrng;
rc = tpm_add_legacy_sysfs(chip);
if (rc) {
@ -432,6 +459,14 @@ int tpm_chip_register(struct tpm_chip *chip)
}
return 0;
out_hwrng:
if (IS_ENABLED(CONFIG_HW_RANDOM_TPM))
hwrng_unregister(&chip->hwrng);
out_ppi:
tpm_bios_log_teardown(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_chip_register);
@ -451,6 +486,8 @@ EXPORT_SYMBOL_GPL(tpm_chip_register);
void tpm_chip_unregister(struct tpm_chip *chip)
{
tpm_del_legacy_sysfs(chip);
if (IS_ENABLED(CONFIG_HW_RANDOM_TPM))
hwrng_unregister(&chip->hwrng);
tpm_bios_log_teardown(chip);
if (chip->flags & TPM_CHIP_FLAG_TPM2)
cdev_device_del(&chip->cdevs, &chip->devs);

View File

@ -30,9 +30,9 @@
#include <linux/spinlock.h>
#include <linux/freezer.h>
#include <linux/pm_runtime.h>
#include <linux/tpm_eventlog.h>
#include "tpm.h"
#include "tpm_eventlog.h"
#define TPM_MAX_ORDINAL 243
#define TSC_MAX_ORDINAL 12
@ -328,7 +328,7 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip,
}
EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration);
static bool tpm_validate_command(struct tpm_chip *chip,
static int tpm_validate_command(struct tpm_chip *chip,
struct tpm_space *space,
const u8 *cmd,
size_t len)
@ -340,10 +340,10 @@ static bool tpm_validate_command(struct tpm_chip *chip,
unsigned int nr_handles;
if (len < TPM_HEADER_SIZE)
return false;
return -EINVAL;
if (!space)
return true;
return 0;
if (chip->flags & TPM_CHIP_FLAG_TPM2 && chip->nr_commands) {
cc = be32_to_cpu(header->ordinal);
@ -352,7 +352,7 @@ static bool tpm_validate_command(struct tpm_chip *chip,
if (i < 0) {
dev_dbg(&chip->dev, "0x%04X is an invalid command\n",
cc);
return false;
return -EOPNOTSUPP;
}
attrs = chip->cc_attrs_tbl[i];
@ -362,11 +362,11 @@ static bool tpm_validate_command(struct tpm_chip *chip,
goto err_len;
}
return true;
return 0;
err_len:
dev_dbg(&chip->dev,
"%s: insufficient command length %zu", __func__, len);
return false;
return -EINVAL;
}
/**
@ -391,8 +391,20 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
unsigned long stop;
bool need_locality;
if (!tpm_validate_command(chip, space, buf, bufsiz))
return -EINVAL;
rc = tpm_validate_command(chip, space, buf, bufsiz);
if (rc == -EINVAL)
return rc;
/*
* If the command is not implemented by the TPM, synthesize a
* response with a TPM2_RC_COMMAND_CODE return for user-space.
*/
if (rc == -EOPNOTSUPP) {
header->length = cpu_to_be32(sizeof(*header));
header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS);
header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE |
TSS2_RESMGR_TPM_RC_LAYER);
return bufsiz;
}
if (bufsiz > TPM_BUFSIZE)
bufsiz = TPM_BUFSIZE;
@ -413,6 +425,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space,
if (chip->dev.parent)
pm_runtime_get_sync(chip->dev.parent);
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, true);
/* Store the decision as chip->locality will be changed. */
need_locality = chip->locality == -1;
@ -489,6 +504,9 @@ out:
chip->locality = -1;
}
out_no_locality:
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, false);
if (chip->dev.parent)
pm_runtime_put_sync(chip->dev.parent);
@ -809,19 +827,20 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
}
/**
* tpm_is_tpm2 - is the chip a TPM2 chip?
* @chip_num: tpm idx # or ANY
* tpm_is_tpm2 - do we a have a TPM2 chip?
* @chip: a &struct tpm_chip instance, %NULL for the default chip
*
* Returns < 0 on error, and 1 or 0 on success depending whether the chip
* is a TPM2 chip.
* Return:
* 1 if we have a TPM2 chip.
* 0 if we don't have a TPM2 chip.
* A negative number for system errors (errno).
*/
int tpm_is_tpm2(u32 chip_num)
int tpm_is_tpm2(struct tpm_chip *chip)
{
struct tpm_chip *chip;
int rc;
chip = tpm_chip_find_get(chip_num);
if (chip == NULL)
chip = tpm_chip_find_get(chip);
if (!chip)
return -ENODEV;
rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0;
@ -833,23 +852,19 @@ int tpm_is_tpm2(u32 chip_num)
EXPORT_SYMBOL_GPL(tpm_is_tpm2);
/**
* tpm_pcr_read - read a pcr value
* @chip_num: tpm idx # or ANY
* @pcr_idx: pcr idx to retrieve
* @res_buf: TPM_PCR value
* size of res_buf is 20 bytes (or NULL if you don't care)
* tpm_pcr_read - read a PCR value from SHA1 bank
* @chip: a &struct tpm_chip instance, %NULL for the default chip
* @pcr_idx: the PCR to be retrieved
* @res_buf: the value of the PCR
*
* The TPM driver should be built-in, but for whatever reason it
* isn't, protect against the chip disappearing, by incrementing
* the module usage count.
* Return: same as with tpm_transmit_cmd()
*/
int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
struct tpm_chip *chip;
int rc;
chip = tpm_chip_find_get(chip_num);
if (chip == NULL)
chip = tpm_chip_find_get(chip);
if (!chip)
return -ENODEV;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
rc = tpm2_pcr_read(chip, pcr_idx, res_buf);
@ -889,25 +904,26 @@ static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash,
}
/**
* tpm_pcr_extend - extend pcr value with hash
* @chip_num: tpm idx # or AN&
* @pcr_idx: pcr idx to extend
* @hash: hash value used to extend pcr value
* tpm_pcr_extend - extend a PCR value in SHA1 bank.
* @chip: a &struct tpm_chip instance, %NULL for the default chip
* @pcr_idx: the PCR to be retrieved
* @hash: the hash value used to extend the PCR value
*
* The TPM driver should be built-in, but for whatever reason it
* isn't, protect against the chip disappearing, by incrementing
* the module usage count.
* Note: with TPM 2.0 extends also those banks with a known digest size to the
* cryto subsystem in order to prevent malicious use of those PCR banks. In the
* future we should dynamically determine digest sizes.
*
* Return: same as with tpm_transmit_cmd()
*/
int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash)
{
int rc;
struct tpm_chip *chip;
struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)];
u32 count = 0;
int i;
chip = tpm_chip_find_get(chip_num);
if (chip == NULL)
chip = tpm_chip_find_get(chip);
if (!chip)
return -ENODEV;
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
@ -1019,82 +1035,29 @@ out:
return rc;
}
int tpm_send(u32 chip_num, void *cmd, size_t buflen)
/**
* tpm_send - send a TPM command
* @chip: a &struct tpm_chip instance, %NULL for the default chip
* @cmd: a TPM command buffer
* @buflen: the length of the TPM command buffer
*
* Return: same as with tpm_transmit_cmd()
*/
int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
{
struct tpm_chip *chip;
int rc;
chip = tpm_chip_find_get(chip_num);
if (chip == NULL)
chip = tpm_chip_find_get(chip);
if (!chip)
return -ENODEV;
rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, 0, 0,
"attempting tpm_cmd");
"attempting to a send a command");
tpm_put_ops(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_send);
static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
bool check_cancel, bool *canceled)
{
u8 status = chip->ops->status(chip);
*canceled = false;
if ((status & mask) == mask)
return true;
if (check_cancel && chip->ops->req_canceled(chip, status)) {
*canceled = true;
return true;
}
return false;
}
int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
wait_queue_head_t *queue, bool check_cancel)
{
unsigned long stop;
long rc;
u8 status;
bool canceled = false;
/* check current status */
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
stop = jiffies + timeout;
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
again:
timeout = stop - jiffies;
if ((long)timeout <= 0)
return -ETIME;
rc = wait_event_interruptible_timeout(*queue,
wait_for_tpm_stat_cond(chip, mask, check_cancel,
&canceled),
timeout);
if (rc > 0) {
if (canceled)
return -ECANCELED;
return 0;
}
if (rc == -ERESTARTSYS && freezing(current)) {
clear_thread_flag(TIF_SIGPENDING);
goto again;
}
} else {
do {
tpm_msleep(TPM_TIMEOUT);
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
} while (time_before(jiffies, stop));
}
return -ETIME;
}
EXPORT_SYMBOL_GPL(wait_for_tpm_stat);
#define TPM_ORD_SAVESTATE 152
#define SAVESTATE_RESULT_SIZE 10
@ -1187,16 +1150,15 @@ static const struct tpm_input_header tpm_getrandom_header = {
};
/**
* tpm_get_random() - Get random bytes from the tpm's RNG
* @chip_num: A specific chip number for the request or TPM_ANY_NUM
* @out: destination buffer for the random bytes
* @max: the max number of bytes to write to @out
* tpm_get_random() - get random bytes from the TPM's RNG
* @chip: a &struct tpm_chip instance, %NULL for the default chip
* @out: destination buffer for the random bytes
* @max: the max number of bytes to write to @out
*
* Returns < 0 on error and the number of bytes read on success
* Return: same as with tpm_transmit_cmd()
*/
int tpm_get_random(u32 chip_num, u8 *out, size_t max)
int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max)
{
struct tpm_chip *chip;
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;
@ -1205,8 +1167,8 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
if (!out || !num_bytes || max > TPM_MAX_RNG_DATA)
return -EINVAL;
chip = tpm_chip_find_get(chip_num);
if (chip == NULL)
chip = tpm_chip_find_get(chip);
if (!chip)
return -ENODEV;
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
@ -1248,22 +1210,23 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
EXPORT_SYMBOL_GPL(tpm_get_random);
/**
* tpm_seal_trusted() - seal a trusted key
* @chip_num: A specific chip number for the request or TPM_ANY_NUM
* @options: authentication values and other options
* @payload: the key data in clear and encrypted form
* tpm_seal_trusted() - seal a trusted key payload
* @chip: a &struct tpm_chip instance, %NULL for the default chip
* @options: authentication values and other options
* @payload: the key data in clear and encrypted form
*
* Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips
* are supported.
* Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in
* the keyring subsystem.
*
* Return: same as with tpm_transmit_cmd()
*/
int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload,
int tpm_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload,
struct trusted_key_options *options)
{
struct tpm_chip *chip;
int rc;
chip = tpm_chip_find_get(chip_num);
if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2))
chip = tpm_chip_find_get(chip);
if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2))
return -ENODEV;
rc = tpm2_seal_trusted(chip, payload, options);
@ -1275,21 +1238,23 @@ EXPORT_SYMBOL_GPL(tpm_seal_trusted);
/**
* tpm_unseal_trusted() - unseal a trusted key
* @chip_num: A specific chip number for the request or TPM_ANY_NUM
* @options: authentication values and other options
* @payload: the key data in clear and encrypted form
* @chip: a &struct tpm_chip instance, %NULL for the default chip
* @options: authentication values and other options
* @payload: the key data in clear and encrypted form
*
* Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips
* are supported.
* Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in
* the keyring subsystem.
*
* Return: same as with tpm_transmit_cmd()
*/
int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload,
int tpm_unseal_trusted(struct tpm_chip *chip,
struct trusted_key_payload *payload,
struct trusted_key_options *options)
{
struct tpm_chip *chip;
int rc;
chip = tpm_chip_find_get(chip_num);
if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2))
chip = tpm_chip_find_get(chip);
if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2))
return -ENODEV;
rc = tpm2_unseal_trusted(chip, payload, options);

View File

@ -26,6 +26,7 @@
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/fs.h>
#include <linux/hw_random.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/platform_device.h>
@ -34,6 +35,7 @@
#include <linux/acpi.h>
#include <linux/cdev.h>
#include <linux/highmem.h>
#include <linux/tpm_eventlog.h>
#include <crypto/hash_info.h>
#ifdef CONFIG_X86
@ -93,12 +95,17 @@ enum tpm2_structures {
TPM2_ST_SESSIONS = 0x8002,
};
/* Indicates from what layer of the software stack the error comes from */
#define TSS2_RC_LAYER_SHIFT 16
#define TSS2_RESMGR_TPM_RC_LAYER (11 << TSS2_RC_LAYER_SHIFT)
enum tpm2_return_codes {
TPM2_RC_SUCCESS = 0x0000,
TPM2_RC_HASH = 0x0083, /* RC_FMT1 */
TPM2_RC_HANDLE = 0x008B,
TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */
TPM2_RC_DISABLED = 0x0120,
TPM2_RC_COMMAND_CODE = 0x0143,
TPM2_RC_TESTING = 0x090A, /* RC_WARN */
TPM2_RC_REFERENCE_H0 = 0x0910,
};
@ -210,6 +217,9 @@ struct tpm_chip {
int dev_num; /* /dev/tpm# */
unsigned long is_open; /* only one allowed */
char hwrng_name[64];
struct hwrng hwrng;
struct mutex tpm_mutex; /* tpm is processing */
unsigned long timeout_a; /* jiffies */
@ -385,10 +395,6 @@ struct tpm_cmd_t {
tpm_cmd_params params;
} __packed;
struct tpm2_digest {
u16 alg_id;
u8 digest[SHA512_DIGEST_SIZE];
} __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
@ -512,16 +518,14 @@ int tpm_do_selftest(struct tpm_chip *chip);
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);
int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
wait_queue_head_t *queue, bool check_cancel);
static inline void tpm_msleep(unsigned int delay_msec)
{
usleep_range(delay_msec * 1000,
(delay_msec * 1000) + TPM_TIMEOUT_RANGE_US);
usleep_range((delay_msec * 1000) - TPM_TIMEOUT_RANGE_US,
delay_msec * 1000);
};
struct tpm_chip *tpm_chip_find_get(int chip_num);
struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip);
__must_check int tpm_try_get_ops(struct tpm_chip *chip);
void tpm_put_ops(struct tpm_chip *chip);
@ -575,4 +579,34 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc,
u8 *cmd);
int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
u32 cc, u8 *buf, size_t *bufsiz);
extern const struct seq_operations tpm2_binary_b_measurements_seqops;
#if defined(CONFIG_ACPI)
int tpm_read_log_acpi(struct tpm_chip *chip);
#else
static inline int tpm_read_log_acpi(struct tpm_chip *chip)
{
return -ENODEV;
}
#endif
#if defined(CONFIG_OF)
int tpm_read_log_of(struct tpm_chip *chip);
#else
static inline int tpm_read_log_of(struct tpm_chip *chip)
{
return -ENODEV;
}
#endif
#if defined(CONFIG_EFI)
int tpm_read_log_efi(struct tpm_chip *chip);
#else
static inline int tpm_read_log_efi(struct tpm_chip *chip)
{
return -ENODEV;
}
#endif
int tpm_bios_log_setup(struct tpm_chip *chip);
void tpm_bios_log_teardown(struct tpm_chip *chip);
#endif

View File

@ -21,13 +21,14 @@
*/
#include <linux/seq_file.h>
#include <linux/efi.h>
#include <linux/fs.h>
#include <linux/security.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/tpm_eventlog.h>
#include "tpm.h"
#include "tpm_eventlog.h"
static const char* tcpa_event_type_strings[] = {
@ -371,6 +372,10 @@ static int tpm_read_log(struct tpm_chip *chip)
if (rc != -ENODEV)
return rc;
rc = tpm_read_log_efi(chip);
if (rc != -ENODEV)
return rc;
return tpm_read_log_of(chip);
}
@ -388,11 +393,13 @@ int tpm_bios_log_setup(struct tpm_chip *chip)
{
const char *name = dev_name(&chip->dev);
unsigned int cnt;
int log_version;
int rc = 0;
rc = tpm_read_log(chip);
if (rc)
if (rc < 0)
return rc;
log_version = rc;
cnt = 0;
chip->bios_dir[cnt] = securityfs_create_dir(name, NULL);
@ -404,7 +411,7 @@ int tpm_bios_log_setup(struct tpm_chip *chip)
cnt++;
chip->bin_log_seqops.chip = chip;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
if (log_version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
chip->bin_log_seqops.seqops =
&tpm2_binary_b_measurements_seqops;
else

View File

@ -849,28 +849,26 @@ static const struct tpm_input_header tpm2_selftest_header = {
static int tpm2_do_selftest(struct tpm_chip *chip)
{
int rc;
unsigned int delay_msec = 20;
unsigned int delay_msec = 10;
long duration;
struct tpm2_cmd cmd;
duration = jiffies_to_msecs(
tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST));
while (duration > 0) {
while (1) {
cmd.header.in = tpm2_selftest_header;
cmd.params.selftest_in.full_test = 0;
rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE,
0, 0, "continue selftest");
if (rc != TPM2_RC_TESTING)
if (rc != TPM2_RC_TESTING || delay_msec >= duration)
break;
tpm_msleep(delay_msec);
duration -= delay_msec;
/* wait longer the next round */
/* wait longer than before */
delay_msec *= 2;
tpm_msleep(delay_msec);
}
return rc;

View File

@ -21,9 +21,9 @@
#include <linux/security.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/tpm_eventlog.h>
#include "tpm.h"
#include "tpm_eventlog.h"
/*
* calc_tpm2_event_size() - calculate the event size, where event

View File

@ -25,9 +25,9 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/acpi.h>
#include <linux/tpm_eventlog.h>
#include "tpm.h"
#include "tpm_eventlog.h"
struct acpi_tcpa {
struct acpi_table_header hdr;
@ -102,7 +102,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
memcpy_fromio(log->bios_event_log, virt, len);
acpi_os_unmap_iomem(virt, len);
return 0;
return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
err:
kfree(log->bios_event_log);

View File

@ -0,0 +1,66 @@
/*
* Copyright (C) 2017 Google
*
* Authors:
* Thiebaud Weksteen <tweek@google.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
*/
#include <linux/efi.h>
#include <linux/tpm_eventlog.h>
#include "tpm.h"
/* read binary bios log from EFI configuration table */
int tpm_read_log_efi(struct tpm_chip *chip)
{
struct linux_efi_tpm_eventlog *log_tbl;
struct tpm_bios_log *log;
u32 log_size;
u8 tpm_log_version;
if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
return -ENODEV;
if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
return -ENODEV;
log = &chip->log;
log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl), MEMREMAP_WB);
if (!log_tbl) {
pr_err("Could not map UEFI TPM log table !\n");
return -ENOMEM;
}
log_size = log_tbl->size;
memunmap(log_tbl);
log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size,
MEMREMAP_WB);
if (!log_tbl) {
pr_err("Could not map UEFI TPM log table payload!\n");
return -ENOMEM;
}
/* malloc EventLog space */
log->bios_event_log = kmalloc(log_size, GFP_KERNEL);
if (!log->bios_event_log)
goto err_memunmap;
memcpy(log->bios_event_log, log_tbl->log, log_size);
log->bios_event_log_end = log->bios_event_log + log_size;
tpm_log_version = log_tbl->version;
memunmap(log_tbl);
return tpm_log_version;
err_memunmap:
memunmap(log_tbl);
return -ENOMEM;
}

View File

@ -17,9 +17,9 @@
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/tpm_eventlog.h>
#include "tpm.h"
#include "tpm_eventlog.h"
int tpm_read_log_of(struct tpm_chip *chip)
{
@ -76,5 +76,7 @@ int tpm_read_log_of(struct tpm_chip *chip)
memcpy(log->bios_event_log, __va(base), size);
return 0;
if (chip->flags & TPM_CHIP_FLAG_TPM2)
return EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
}

View File

@ -665,9 +665,9 @@ out_err:
}
static const struct i2c_device_id tpm_tis_i2c_table[] = {
{"tpm_i2c_infineon", 0},
{"slb9635tt", 0},
{"slb9645tt", 1},
{"tpm_i2c_infineon"},
{"slb9635tt"},
{"slb9645tt"},
{},
};
@ -675,24 +675,9 @@ MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table);
#ifdef CONFIG_OF
static const struct of_device_id tpm_tis_i2c_of_match[] = {
{
.name = "tpm_i2c_infineon",
.type = "tpm",
.compatible = "infineon,tpm_i2c_infineon",
.data = (void *)0
},
{
.name = "slb9635tt",
.type = "tpm",
.compatible = "infineon,slb9635tt",
.data = (void *)0
},
{
.name = "slb9645tt",
.type = "tpm",
.compatible = "infineon,slb9645tt",
.data = (void *)1
},
{.compatible = "infineon,tpm_i2c_infineon"},
{.compatible = "infineon,slb9635tt"},
{.compatible = "infineon,slb9645tt"},
{},
};
MODULE_DEVICE_TABLE(of, tpm_tis_i2c_of_match);

View File

@ -133,93 +133,14 @@ static int check_acpi_tpm2(struct device *dev)
}
#endif
#ifdef CONFIG_X86
#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000
#define ILB_REMAP_SIZE 0x100
#define LPC_CNTRL_REG_OFFSET 0x84
#define LPC_CLKRUN_EN (1 << 2)
static void __iomem *ilb_base_addr;
static inline bool is_bsw(void)
{
return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0);
}
/**
* tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running
*/
static void tpm_platform_begin_xfer(void)
{
u32 clkrun_val;
if (!is_bsw())
return;
clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET);
/* Disable LPC CLKRUN# */
clkrun_val &= ~LPC_CLKRUN_EN;
iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET);
/*
* Write any random value on port 0x80 which is on LPC, to make
* sure LPC clock is running before sending any TPM command.
*/
outb(0xCC, 0x80);
}
/**
* tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off
*/
static void tpm_platform_end_xfer(void)
{
u32 clkrun_val;
if (!is_bsw())
return;
clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET);
/* Enable LPC CLKRUN# */
clkrun_val |= LPC_CLKRUN_EN;
iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET);
/*
* Write any random value on port 0x80 which is on LPC, to make
* sure LPC clock is running before sending any TPM command.
*/
outb(0xCC, 0x80);
}
#else
static inline bool is_bsw(void)
{
return false;
}
static void tpm_platform_begin_xfer(void)
{
}
static void tpm_platform_end_xfer(void)
{
}
#endif
static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
u8 *result)
{
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
while (len--)
*result++ = ioread8(phy->iobase + addr);
tpm_platform_end_xfer();
return 0;
}
@ -228,13 +149,9 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len,
{
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
while (len--)
iowrite8(*value++, phy->iobase + addr);
tpm_platform_end_xfer();
return 0;
}
@ -242,12 +159,8 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result)
{
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
*result = ioread16(phy->iobase + addr);
tpm_platform_end_xfer();
return 0;
}
@ -255,12 +168,8 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result)
{
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
*result = ioread32(phy->iobase + addr);
tpm_platform_end_xfer();
return 0;
}
@ -268,12 +177,8 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value)
{
struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data);
tpm_platform_begin_xfer();
iowrite32(value, phy->iobase + addr);
tpm_platform_end_xfer();
return 0;
}
@ -461,11 +366,6 @@ static int __init init_tis(void)
if (rc)
goto err_force;
#ifdef CONFIG_X86
if (is_bsw())
ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR,
ILB_REMAP_SIZE);
#endif
rc = platform_driver_register(&tis_drv);
if (rc)
goto err_platform;
@ -484,10 +384,6 @@ err_pnp:
err_platform:
if (force_pdev)
platform_device_unregister(force_pdev);
#ifdef CONFIG_X86
if (is_bsw())
iounmap(ilb_base_addr);
#endif
err_force:
return rc;
}
@ -497,10 +393,6 @@ static void __exit cleanup_tis(void)
pnp_unregister_driver(&tis_pnp_driver);
platform_driver_unregister(&tis_drv);
#ifdef CONFIG_X86
if (is_bsw())
iounmap(ilb_base_addr);
#endif
if (force_pdev)
platform_device_unregister(force_pdev);
}

View File

@ -31,6 +31,74 @@
#include "tpm.h"
#include "tpm_tis_core.h"
/* This is a polling delay to check for status and burstcount.
* As per ddwg input, expectation is that status check and burstcount
* check should return within few usecs.
*/
#define TPM_POLL_SLEEP 1 /* msec */
static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value);
static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
bool check_cancel, bool *canceled)
{
u8 status = chip->ops->status(chip);
*canceled = false;
if ((status & mask) == mask)
return true;
if (check_cancel && chip->ops->req_canceled(chip, status)) {
*canceled = true;
return true;
}
return false;
}
static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
unsigned long timeout, wait_queue_head_t *queue,
bool check_cancel)
{
unsigned long stop;
long rc;
u8 status;
bool canceled = false;
/* check current status */
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
stop = jiffies + timeout;
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
again:
timeout = stop - jiffies;
if ((long)timeout <= 0)
return -ETIME;
rc = wait_event_interruptible_timeout(*queue,
wait_for_tpm_stat_cond(chip, mask, check_cancel,
&canceled),
timeout);
if (rc > 0) {
if (canceled)
return -ECANCELED;
return 0;
}
if (rc == -ERESTARTSYS && freezing(current)) {
clear_thread_flag(TIF_SIGPENDING);
goto again;
}
} else {
do {
tpm_msleep(TPM_POLL_SLEEP);
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
} while (time_before(jiffies, stop));
}
return -ETIME;
}
/* Before we attempt to access the TPM we must see that the valid bit is set.
* The specification says that this bit is 0 at reset and remains 0 until the
* 'TPM has gone through its self test and initialization and has established
@ -164,7 +232,7 @@ static int get_burstcount(struct tpm_chip *chip)
burstcnt = (value >> 8) & 0xFFFF;
if (burstcnt)
return burstcnt;
tpm_msleep(TPM_TIMEOUT);
tpm_msleep(TPM_POLL_SLEEP);
} while (time_before(jiffies, stop));
return -EBUSY;
}
@ -421,19 +489,28 @@ static bool tpm_tis_update_timeouts(struct tpm_chip *chip,
int i, rc;
u32 did_vid;
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, true);
rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid);
if (rc < 0)
return rc;
goto out;
for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) {
if (vendor_timeout_overrides[i].did_vid != did_vid)
continue;
memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us,
sizeof(vendor_timeout_overrides[i].timeout_us));
return true;
rc = true;
}
return false;
rc = false;
out:
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, false);
return rc;
}
/*
@ -653,14 +730,73 @@ void tpm_tis_remove(struct tpm_chip *chip)
u32 interrupt;
int rc;
tpm_tis_clkrun_enable(chip, true);
rc = tpm_tis_read32(priv, reg, &interrupt);
if (rc < 0)
interrupt = 0;
tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt);
tpm_tis_clkrun_enable(chip, false);
if (priv->ilb_base_addr)
iounmap(priv->ilb_base_addr);
}
EXPORT_SYMBOL_GPL(tpm_tis_remove);
/**
* tpm_tis_clkrun_enable() - Keep clkrun protocol disabled for entire duration
* of a single TPM command
* @chip: TPM chip to use
* @value: 1 - Disable CLKRUN protocol, so that clocks are free running
* 0 - Enable CLKRUN protocol
* Call this function directly in tpm_tis_remove() in error or driver removal
* path, since the chip->ops is set to NULL in tpm_chip_unregister().
*/
static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value)
{
struct tpm_tis_data *data = dev_get_drvdata(&chip->dev);
u32 clkrun_val;
if (!IS_ENABLED(CONFIG_X86) || !is_bsw() ||
!data->ilb_base_addr)
return;
if (value) {
data->clkrun_enabled++;
if (data->clkrun_enabled > 1)
return;
clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
/* Disable LPC CLKRUN# */
clkrun_val &= ~LPC_CLKRUN_EN;
iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
/*
* Write any random value on port 0x80 which is on LPC, to make
* sure LPC clock is running before sending any TPM command.
*/
outb(0xCC, 0x80);
} else {
data->clkrun_enabled--;
if (data->clkrun_enabled)
return;
clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET);
/* Enable LPC CLKRUN# */
clkrun_val |= LPC_CLKRUN_EN;
iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET);
/*
* Write any random value on port 0x80 which is on LPC, to make
* sure LPC clock is running before sending any TPM command.
*/
outb(0xCC, 0x80);
}
}
static const struct tpm_class_ops tpm_tis = {
.flags = TPM_OPS_AUTO_STARTUP,
.status = tpm_tis_status,
@ -673,13 +809,17 @@ static const struct tpm_class_ops tpm_tis = {
.req_canceled = tpm_tis_req_canceled,
.request_locality = request_locality,
.relinquish_locality = release_locality,
.clk_enable = tpm_tis_clkrun_enable,
};
int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
const struct tpm_tis_phy_ops *phy_ops,
acpi_handle acpi_dev_handle)
{
u32 vendor, intfcaps, intmask;
u32 vendor;
u32 intfcaps;
u32 intmask;
u32 clkrun_val;
u8 rid;
int rc, probe;
struct tpm_chip *chip;
@ -700,6 +840,23 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
priv->phy_ops = phy_ops;
dev_set_drvdata(&chip->dev, priv);
if (is_bsw()) {
priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR,
ILB_REMAP_SIZE);
if (!priv->ilb_base_addr)
return -ENOMEM;
clkrun_val = ioread32(priv->ilb_base_addr + LPC_CNTRL_OFFSET);
/* Check if CLKRUN# is already not enabled in the LPC bus */
if (!(clkrun_val & LPC_CLKRUN_EN)) {
iounmap(priv->ilb_base_addr);
priv->ilb_base_addr = NULL;
}
}
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, true);
if (wait_startup(chip, 0) != 0) {
rc = -ENODEV;
goto out_err;
@ -790,9 +947,20 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
}
}
return tpm_chip_register(chip);
rc = tpm_chip_register(chip);
if (rc)
goto out_err;
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, false);
return 0;
out_err:
if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL))
chip->ops->clk_enable(chip, false);
tpm_tis_remove(chip);
return rc;
}
EXPORT_SYMBOL_GPL(tpm_tis_core_init);
@ -804,22 +972,31 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
u32 intmask;
int rc;
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, true);
/* reenable interrupts that device may have lost or
* BIOS/firmware may have disabled
*/
rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq);
if (rc < 0)
return;
goto out;
rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
if (rc < 0)
return;
goto out;
intmask |= TPM_INTF_CMD_READY_INT
| TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
| TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
out:
if (chip->ops->clk_enable != NULL)
chip->ops->clk_enable(chip, false);
return;
}
int tpm_tis_resume(struct device *dev)

View File

@ -79,6 +79,11 @@ enum tis_defaults {
#define TPM_DID_VID(l) (0x0F00 | ((l) << 12))
#define TPM_RID(l) (0x0F04 | ((l) << 12))
#define LPC_CNTRL_OFFSET 0x84
#define LPC_CLKRUN_EN (1 << 2)
#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000
#define ILB_REMAP_SIZE 0x100
enum tpm_tis_flags {
TPM_TIS_ITPM_WORKAROUND = BIT(0),
};
@ -89,6 +94,8 @@ struct tpm_tis_data {
int irq;
bool irq_tested;
unsigned int flags;
void __iomem *ilb_base_addr;
u16 clkrun_enabled;
wait_queue_head_t int_queue;
wait_queue_head_t read_queue;
const struct tpm_tis_phy_ops *phy_ops;
@ -144,6 +151,15 @@ static inline int tpm_tis_write32(struct tpm_tis_data *data, u32 addr,
return data->phy_ops->write32(data, addr, value);
}
static inline bool is_bsw(void)
{
#ifdef CONFIG_X86
return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0);
#else
return false;
#endif
}
void tpm_tis_remove(struct tpm_chip *chip);
int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
const struct tpm_tis_phy_ops *phy_ops,

View File

@ -10,6 +10,7 @@
#include <linux/errno.h>
#include <linux/err.h>
#include <linux/interrupt.h>
#include <linux/freezer.h>
#include <xen/xen.h>
#include <xen/events.h>
#include <xen/interface/io/tpmif.h>
@ -39,6 +40,66 @@ enum status_bits {
VTPM_STATUS_CANCELED = 0x8,
};
static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask,
bool check_cancel, bool *canceled)
{
u8 status = chip->ops->status(chip);
*canceled = false;
if ((status & mask) == mask)
return true;
if (check_cancel && chip->ops->req_canceled(chip, status)) {
*canceled = true;
return true;
}
return false;
}
static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
unsigned long timeout, wait_queue_head_t *queue,
bool check_cancel)
{
unsigned long stop;
long rc;
u8 status;
bool canceled = false;
/* check current status */
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
stop = jiffies + timeout;
if (chip->flags & TPM_CHIP_FLAG_IRQ) {
again:
timeout = stop - jiffies;
if ((long)timeout <= 0)
return -ETIME;
rc = wait_event_interruptible_timeout(*queue,
wait_for_tpm_stat_cond(chip, mask, check_cancel,
&canceled),
timeout);
if (rc > 0) {
if (canceled)
return -ECANCELED;
return 0;
}
if (rc == -ERESTARTSYS && freezing(current)) {
clear_thread_flag(TIF_SIGPENDING);
goto again;
}
} else {
do {
tpm_msleep(TPM_TIMEOUT);
status = chip->ops->status(chip);
if ((status & mask) == mask)
return 0;
} while (time_before(jiffies, stop));
}
return -ETIME;
}
static u8 vtpm_status(struct tpm_chip *chip)
{
struct tpm_private *priv = dev_get_drvdata(&chip->dev);

View File

@ -11,7 +11,7 @@
KASAN_SANITIZE_runtime-wrappers.o := n
obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o
obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o
obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o tpm.o
obj-$(CONFIG_EFI) += capsule.o memmap.o
obj-$(CONFIG_EFI_VARS) += efivars.o
obj-$(CONFIG_EFI_ESRT) += esrt.o

View File

@ -52,6 +52,7 @@ struct efi __read_mostly efi = {
.properties_table = EFI_INVALID_TABLE_ADDR,
.mem_attr_table = EFI_INVALID_TABLE_ADDR,
.rng_seed = EFI_INVALID_TABLE_ADDR,
.tpm_log = EFI_INVALID_TABLE_ADDR
};
EXPORT_SYMBOL(efi);
@ -464,6 +465,7 @@ static __initdata efi_config_table_type_t common_tables[] = {
{EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table},
{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table},
{LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed},
{LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log},
{NULL_GUID, NULL, NULL},
};
@ -552,6 +554,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
if (efi_enabled(EFI_MEMMAP))
efi_memattr_init();
efi_tpm_eventlog_init();
/* Parse the EFI Properties table if it exists */
if (efi.properties_table != EFI_INVALID_TABLE_ADDR) {
efi_properties_table_t *tbl;

View File

@ -30,8 +30,7 @@ OBJECT_FILES_NON_STANDARD := y
# Prevents link failures: __sanitizer_cov_trace_pc() is not linked in.
KCOV_INSTRUMENT := n
lib-y := efi-stub-helper.o gop.o secureboot.o
lib-$(CONFIG_RESET_ATTACK_MITIGATION) += tpm.o
lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o
# include the stub's generic dependencies from lib/ when building for ARM/arm64
arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c

View File

@ -4,15 +4,18 @@
* Copyright (C) 2016 CoreOS, Inc
* Copyright (C) 2017 Google, Inc.
* Matthew Garrett <mjg59@google.com>
* Thiebaud Weksteen <tweek@google.com>
*
* This file is part of the Linux kernel, and is made available under the
* terms of the GNU General Public License version 2.
*/
#include <linux/efi.h>
#include <linux/tpm_eventlog.h>
#include <asm/efi.h>
#include "efistub.h"
#ifdef CONFIG_RESET_ATTACK_MITIGATION
static const efi_char16_t efi_MemoryOverWriteRequest_name[] = {
'M', 'e', 'm', 'o', 'r', 'y', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't',
'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 'n', 't', 'r', 'o',
@ -56,3 +59,81 @@ void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg)
EFI_VARIABLE_BOOTSERVICE_ACCESS |
EFI_VARIABLE_RUNTIME_ACCESS, sizeof(val), &val);
}
#endif
void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg)
{
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
efi_status_t status;
efi_physical_addr_t log_location, log_last_entry;
struct linux_efi_tpm_eventlog *log_tbl;
unsigned long first_entry_addr, last_entry_addr;
size_t log_size, last_entry_size;
efi_bool_t truncated;
void *tcg2_protocol;
status = efi_call_early(locate_protocol, &tcg2_guid, NULL,
&tcg2_protocol);
if (status != EFI_SUCCESS)
return;
status = efi_call_proto(efi_tcg2_protocol, get_event_log, tcg2_protocol,
EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2,
&log_location, &log_last_entry, &truncated);
if (status != EFI_SUCCESS)
return;
if (!log_location)
return;
first_entry_addr = (unsigned long) log_location;
/*
* We populate the EFI table even if the logs are empty.
*/
if (!log_last_entry) {
log_size = 0;
} else {
last_entry_addr = (unsigned long) log_last_entry;
/*
* get_event_log only returns the address of the last entry.
* We need to calculate its size to deduce the full size of
* the logs.
*/
last_entry_size = sizeof(struct tcpa_event) +
((struct tcpa_event *) last_entry_addr)->event_size;
log_size = log_last_entry - log_location + last_entry_size;
}
/* Allocate space for the logs and copy them. */
status = efi_call_early(allocate_pool, EFI_LOADER_DATA,
sizeof(*log_tbl) + log_size,
(void **) &log_tbl);
if (status != EFI_SUCCESS) {
efi_printk(sys_table_arg,
"Unable to allocate memory for event log\n");
return;
}
memset(log_tbl, 0, sizeof(*log_tbl) + log_size);
log_tbl->size = log_size;
log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
memcpy(log_tbl->log, (void *) first_entry_addr, log_size);
status = efi_call_early(install_configuration_table,
&linux_eventlog_guid, log_tbl);
if (status != EFI_SUCCESS)
goto err_free;
return;
err_free:
efi_call_early(free_pool, log_tbl);
}
void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg)
{
/* Only try to retrieve the logs in 1.2 format. */
efi_retrieve_tpm2_eventlog_1_2(sys_table_arg);
}

View File

@ -0,0 +1,40 @@
/*
* Copyright (C) 2017 Google, Inc.
* Thiebaud Weksteen <tweek@google.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <linux/efi.h>
#include <linux/init.h>
#include <linux/memblock.h>
#include <asm/early_ioremap.h>
/*
* Reserve the memory associated with the TPM Event Log configuration table.
*/
int __init efi_tpm_eventlog_init(void)
{
struct linux_efi_tpm_eventlog *log_tbl;
unsigned int tbl_size;
if (efi.tpm_log == EFI_INVALID_TABLE_ADDR)
return 0;
log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl));
if (!log_tbl) {
pr_err("Failed to map TPM Event Log table @ 0x%lx\n",
efi.tpm_log);
efi.tpm_log = EFI_INVALID_TABLE_ADDR;
return -ENOMEM;
}
tbl_size = sizeof(*log_tbl) + log_tbl->size;
memblock_reserve(efi.tpm_log, tbl_size);
early_memunmap(log_tbl, sizeof(*log_tbl));
return 0;
}

View File

@ -475,6 +475,39 @@ typedef struct {
u64 get_all;
} apple_properties_protocol_64_t;
typedef struct {
u32 get_capability;
u32 get_event_log;
u32 hash_log_extend_event;
u32 submit_command;
u32 get_active_pcr_banks;
u32 set_active_pcr_banks;
u32 get_result_of_set_active_pcr_banks;
} efi_tcg2_protocol_32_t;
typedef struct {
u64 get_capability;
u64 get_event_log;
u64 hash_log_extend_event;
u64 submit_command;
u64 get_active_pcr_banks;
u64 set_active_pcr_banks;
u64 get_result_of_set_active_pcr_banks;
} efi_tcg2_protocol_64_t;
typedef u32 efi_tcg2_event_log_format;
typedef struct {
void *get_capability;
efi_status_t (*get_event_log)(efi_handle_t, efi_tcg2_event_log_format,
efi_physical_addr_t *, efi_physical_addr_t *, efi_bool_t *);
void *hash_log_extend_event;
void *submit_command;
void *get_active_pcr_banks;
void *set_active_pcr_banks;
void *get_result_of_set_active_pcr_banks;
} efi_tcg2_protocol_t;
/*
* Types and defines for EFI ResetSystem
*/
@ -625,6 +658,7 @@ void efi_native_runtime_setup(void);
#define EFI_MEMORY_ATTRIBUTES_TABLE_GUID EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20)
#define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d)
#define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0)
#define EFI_TCG2_PROTOCOL_GUID EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f)
#define EFI_IMAGE_SECURITY_DATABASE_GUID EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f)
#define EFI_SHIM_LOCK_GUID EFI_GUID(0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)
@ -637,6 +671,7 @@ void efi_native_runtime_setup(void);
#define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95)
#define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f)
#define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b)
#define LINUX_EFI_TPM_EVENT_LOG_GUID EFI_GUID(0xb7799cb0, 0xeca2, 0x4943, 0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa)
typedef struct {
efi_guid_t guid;
@ -911,6 +946,7 @@ extern struct efi {
unsigned long properties_table; /* properties table */
unsigned long mem_attr_table; /* memory attributes table */
unsigned long rng_seed; /* UEFI firmware random seed */
unsigned long tpm_log; /* TPM2 Event Log table */
efi_get_time_t *get_time;
efi_set_time_t *set_time;
efi_get_wakeup_time_t *get_wakeup_time;
@ -1536,6 +1572,8 @@ static inline void
efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) { }
#endif
void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table);
/*
* Arch code can implement the following three template macros, avoiding
* reptition for the void/non-void return cases of {__,}efi_call_virt():
@ -1603,4 +1641,12 @@ struct linux_efi_random_seed {
u8 bits[];
};
struct linux_efi_tpm_eventlog {
u32 size;
u8 version;
u8 log[];
};
extern int efi_tpm_eventlog_init(void);
#endif /* _LINUX_EFI_H */

View File

@ -24,11 +24,6 @@
#define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */
/*
* Chip num is this value or a valid tpm idx
*/
#define TPM_ANY_NUM 0xFFFF
struct tpm_chip;
struct trusted_key_payload;
struct trusted_key_options;
@ -50,46 +45,52 @@ struct tpm_class_ops {
unsigned long *timeout_cap);
int (*request_locality)(struct tpm_chip *chip, int loc);
void (*relinquish_locality)(struct tpm_chip *chip, int loc);
void (*clk_enable)(struct tpm_chip *chip, bool value);
};
#if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE)
extern int tpm_is_tpm2(u32 chip_num);
extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf);
extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash);
extern int tpm_send(u32 chip_num, void *cmd, size_t buflen);
extern int tpm_get_random(u32 chip_num, u8 *data, size_t max);
extern int tpm_seal_trusted(u32 chip_num,
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_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,
struct trusted_key_payload *payload,
struct trusted_key_options *options);
extern int tpm_unseal_trusted(u32 chip_num,
extern int tpm_unseal_trusted(struct tpm_chip *chip,
struct trusted_key_payload *payload,
struct trusted_key_options *options);
#else
static inline int tpm_is_tpm2(u32 chip_num)
static inline int tpm_is_tpm2(struct tpm_chip *chip)
{
return -ENODEV;
}
static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) {
static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
return -ENODEV;
}
static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) {
static inline int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx,
const u8 *hash)
{
return -ENODEV;
}
static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) {
static inline int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen)
{
return -ENODEV;
}
static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) {
static inline int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max)
{
return -ENODEV;
}
static inline int tpm_seal_trusted(u32 chip_num,
static inline int tpm_seal_trusted(struct tpm_chip *chip,
struct trusted_key_payload *payload,
struct trusted_key_options *options)
{
return -ENODEV;
}
static inline int tpm_unseal_trusted(u32 chip_num,
static inline int tpm_unseal_trusted(struct tpm_chip *chip,
struct trusted_key_payload *payload,
struct trusted_key_options *options)
{

View File

@ -1,7 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __TPM_EVENTLOG_H__
#define __TPM_EVENTLOG_H__
#ifndef __LINUX_TPM_EVENTLOG_H__
#define __LINUX_TPM_EVENTLOG_H__
#include <crypto/hash_info.h>
@ -10,6 +10,9 @@
#define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */
#define TPM2_ACTIVE_PCR_BANKS 3
#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x1
#define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x2
#ifdef CONFIG_PPC64
#define do_endian_conversion(x) be32_to_cpu(x)
#else
@ -105,6 +108,11 @@ struct tcg_event_field {
u8 event[0];
} __packed;
struct tpm2_digest {
u16 alg_id;
u8 digest[SHA512_DIGEST_SIZE];
} __packed;
struct tcg_pcr_event2 {
u32 pcr_idx;
u32 event_type;
@ -113,26 +121,4 @@ struct tcg_pcr_event2 {
struct tcg_event_field event;
} __packed;
extern const struct seq_operations tpm2_binary_b_measurements_seqops;
#if defined(CONFIG_ACPI)
int tpm_read_log_acpi(struct tpm_chip *chip);
#else
static inline int tpm_read_log_acpi(struct tpm_chip *chip)
{
return -ENODEV;
}
#endif
#if defined(CONFIG_OF)
int tpm_read_log_of(struct tpm_chip *chip);
#else
static inline int tpm_read_log_of(struct tpm_chip *chip)
{
return -ENODEV;
}
#endif
int tpm_bios_log_setup(struct tpm_chip *chip);
void tpm_bios_log_teardown(struct tpm_chip *chip);
#endif

View File

@ -632,7 +632,7 @@ static void __init ima_pcrread(int idx, u8 *pcr)
if (!ima_used_chip)
return;
if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0)
if (tpm_pcr_read(NULL, idx, pcr) != 0)
pr_err("Error Communicating to TPM chip\n");
}

View File

@ -110,7 +110,7 @@ int __init ima_init(void)
int rc;
ima_used_chip = 0;
rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i);
rc = tpm_pcr_read(NULL, 0, pcr_i);
if (rc == 0)
ima_used_chip = 1;

View File

@ -145,7 +145,7 @@ static int ima_pcr_extend(const u8 *hash, int pcr)
if (!ima_used_chip)
return result;
result = tpm_pcr_extend(TPM_ANY_NUM, pcr, hash);
result = tpm_pcr_extend(NULL, pcr, hash);
if (result != 0)
pr_err("Error Communicating to TPM chip, result: %d\n", result);
return result;

View File

@ -355,13 +355,12 @@ out:
* For key specific tpm requests, we will generate and send our
* own TPM command packets using the drivers send function.
*/
static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd,
size_t buflen)
static int trusted_tpm_send(unsigned char *cmd, size_t buflen)
{
int rc;
dump_tpm_buf(cmd);
rc = tpm_send(chip_num, cmd, buflen);
rc = tpm_send(NULL, cmd, buflen);
dump_tpm_buf(cmd);
if (rc > 0)
/* Can't return positive return codes values to keyctl */
@ -382,10 +381,10 @@ static int pcrlock(const int pcrnum)
if (!capable(CAP_SYS_ADMIN))
return -EPERM;
ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE);
ret = tpm_get_random(NULL, hash, SHA1_DIGEST_SIZE);
if (ret != SHA1_DIGEST_SIZE)
return ret;
return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0;
return tpm_pcr_extend(NULL, pcrnum, hash) ? -EINVAL : 0;
}
/*
@ -398,7 +397,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
unsigned char ononce[TPM_NONCE_SIZE];
int ret;
ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE);
ret = tpm_get_random(NULL, ononce, TPM_NONCE_SIZE);
if (ret != TPM_NONCE_SIZE)
return ret;
@ -410,7 +409,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s,
store32(tb, handle);
storebytes(tb, ononce, TPM_NONCE_SIZE);
ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
if (ret < 0)
return ret;
@ -434,7 +433,7 @@ static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce)
store16(tb, TPM_TAG_RQU_COMMAND);
store32(tb, TPM_OIAP_SIZE);
store32(tb, TPM_ORD_OIAP);
ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
if (ret < 0)
return ret;
@ -493,7 +492,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
if (ret < 0)
goto out;
ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE);
ret = tpm_get_random(NULL, td->nonceodd, TPM_NONCE_SIZE);
if (ret != TPM_NONCE_SIZE)
goto out;
ordinal = htonl(TPM_ORD_SEAL);
@ -542,7 +541,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype,
store8(tb, cont);
storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE);
ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
if (ret < 0)
goto out;
@ -603,7 +602,7 @@ static int tpm_unseal(struct tpm_buf *tb,
ordinal = htonl(TPM_ORD_UNSEAL);
keyhndl = htonl(SRKHANDLE);
ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE);
ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE);
if (ret != TPM_NONCE_SIZE) {
pr_info("trusted_key: tpm_get_random failed (%d)\n", ret);
return ret;
@ -635,7 +634,7 @@ static int tpm_unseal(struct tpm_buf *tb,
store8(tb, cont);
storebytes(tb, authdata2, SHA1_DIGEST_SIZE);
ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE);
ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE);
if (ret < 0) {
pr_info("trusted_key: authhmac failed (%d)\n", ret);
return ret;
@ -748,7 +747,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay,
int i;
int tpm2;
tpm2 = tpm_is_tpm2(TPM_ANY_NUM);
tpm2 = tpm_is_tpm2(NULL);
if (tpm2 < 0)
return tpm2;
@ -917,7 +916,7 @@ static struct trusted_key_options *trusted_options_alloc(void)
struct trusted_key_options *options;
int tpm2;
tpm2 = tpm_is_tpm2(TPM_ANY_NUM);
tpm2 = tpm_is_tpm2(NULL);
if (tpm2 < 0)
return NULL;
@ -967,7 +966,7 @@ static int trusted_instantiate(struct key *key,
size_t key_len;
int tpm2;
tpm2 = tpm_is_tpm2(TPM_ANY_NUM);
tpm2 = tpm_is_tpm2(NULL);
if (tpm2 < 0)
return tpm2;
@ -1008,7 +1007,7 @@ static int trusted_instantiate(struct key *key,
switch (key_cmd) {
case Opt_load:
if (tpm2)
ret = tpm_unseal_trusted(TPM_ANY_NUM, payload, options);
ret = tpm_unseal_trusted(NULL, payload, options);
else
ret = key_unseal(payload, options);
dump_payload(payload);
@ -1018,13 +1017,13 @@ static int trusted_instantiate(struct key *key,
break;
case Opt_new:
key_len = payload->key_len;
ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len);
ret = tpm_get_random(NULL, payload->key, key_len);
if (ret != key_len) {
pr_info("trusted_key: key_create failed (%d)\n", ret);
goto out;
}
if (tpm2)
ret = tpm_seal_trusted(TPM_ANY_NUM, payload, options);
ret = tpm_seal_trusted(NULL, payload, options);
else
ret = key_seal(payload, options);
if (ret < 0)