mirror of
https://github.com/ukui/kernel.git
synced 2026-03-09 10:07:04 -07:00
tpm: TPM 2.0 baseline support
TPM 2.0 devices are separated by adding a field 'flags' to struct tpm_chip and defining a flag TPM_CHIP_FLAG_TPM2 for tagging them. This patch adds the following internal functions: - tpm2_get_random() - tpm2_get_tpm_pt() - tpm2_pcr_extend() - tpm2_pcr_read() - tpm2_startup() Additionally, the following exported functions are implemented for implementing TPM 2.0 device drivers: - tpm2_do_selftest() - tpm2_calc_ordinal_durations() - tpm2_gen_interrupt() The existing functions that are exported for the use for existing subsystems have been changed to check the flags field in struct tpm_chip and use appropriate TPM 2.0 counterpart if TPM_CHIP_FLAG_TPM2 is est. The code for tpm2_calc_ordinal_duration() and tpm2_startup() were originally written by Will Arthur. Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Signed-off-by: Will Arthur <will.c.arthur@intel.com> Reviewed-by: Jasob Gunthorpe <jason.gunthorpe@obsidianresearch.com> Reviewed-by: Stefan Berger <stefanb@linux.vnet.ibm.com> Reviewed-by: Peter Huewe <peterhuewe@gmx.de> Tested-by: Peter Huewe <peterhuewe@gmx.de> [phuewe: Fixed copy paste error * 2] Signed-off-by: Peter Huewe <peterhuewe@gmx.de>
This commit is contained in:
committed by
Peter Huewe
parent
313d21eeab
commit
7a1d7e6dd7
@@ -2,7 +2,7 @@
|
||||
# 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
|
||||
tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o
|
||||
tpm-$(CONFIG_ACPI) += tpm_ppi.o
|
||||
|
||||
ifdef CONFIG_ACPI
|
||||
|
||||
@@ -195,15 +195,18 @@ int tpm_chip_register(struct tpm_chip *chip)
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
rc = tpm_sysfs_add_device(chip);
|
||||
if (rc)
|
||||
goto del_misc;
|
||||
/* Populate sysfs for TPM1 devices. */
|
||||
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
|
||||
rc = tpm_sysfs_add_device(chip);
|
||||
if (rc)
|
||||
goto del_misc;
|
||||
|
||||
rc = tpm_add_ppi(chip);
|
||||
if (rc)
|
||||
goto del_sysfs;
|
||||
rc = tpm_add_ppi(chip);
|
||||
if (rc)
|
||||
goto del_sysfs;
|
||||
|
||||
chip->bios_dir = tpm_bios_log_setup(chip->devname);
|
||||
chip->bios_dir = tpm_bios_log_setup(chip->devname);
|
||||
}
|
||||
|
||||
/* Make the chip available. */
|
||||
spin_lock(&driver_lock);
|
||||
@@ -241,10 +244,12 @@ void tpm_chip_unregister(struct tpm_chip *chip)
|
||||
spin_unlock(&driver_lock);
|
||||
synchronize_rcu();
|
||||
|
||||
if (chip->bios_dir)
|
||||
tpm_bios_log_teardown(chip->bios_dir);
|
||||
tpm_remove_ppi(chip);
|
||||
tpm_sysfs_del_device(chip);
|
||||
if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) {
|
||||
if (chip->bios_dir)
|
||||
tpm_bios_log_teardown(chip->bios_dir);
|
||||
tpm_remove_ppi(chip);
|
||||
tpm_sysfs_del_device(chip);
|
||||
}
|
||||
|
||||
tpm_dev_del_device(chip);
|
||||
}
|
||||
|
||||
@@ -360,7 +360,10 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
|
||||
if (chip->vendor.irq)
|
||||
goto out_recv;
|
||||
|
||||
stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
||||
stop = jiffies + tpm2_calc_ordinal_duration(chip, ordinal);
|
||||
else
|
||||
stop = jiffies + tpm_calc_ordinal_duration(chip, ordinal);
|
||||
do {
|
||||
u8 status = chip->ops->status(chip);
|
||||
if ((status & chip->ops->req_complete_mask) ==
|
||||
@@ -484,6 +487,7 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
|
||||
{
|
||||
struct tpm_cmd_t start_cmd;
|
||||
start_cmd.header.in = tpm_startup_header;
|
||||
|
||||
start_cmd.params.startup_in.startup_type = startup_type;
|
||||
return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE,
|
||||
"attempting to start the TPM");
|
||||
@@ -680,7 +684,10 @@ int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf)
|
||||
chip = tpm_chip_find_get(chip_num);
|
||||
if (chip == NULL)
|
||||
return -ENODEV;
|
||||
rc = tpm_pcr_read_dev(chip, pcr_idx, res_buf);
|
||||
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);
|
||||
tpm_chip_put(chip);
|
||||
return rc;
|
||||
}
|
||||
@@ -714,6 +721,12 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
|
||||
if (chip == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
|
||||
rc = tpm2_pcr_extend(chip, pcr_idx, hash);
|
||||
tpm_chip_put(chip);
|
||||
return rc;
|
||||
}
|
||||
|
||||
cmd.header.in = pcrextend_header;
|
||||
cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx);
|
||||
memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE);
|
||||
@@ -974,6 +987,12 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max)
|
||||
if (chip == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
|
||||
err = tpm2_get_random(chip, out, max);
|
||||
tpm_chip_put(chip);
|
||||
return err;
|
||||
}
|
||||
|
||||
do {
|
||||
tpm_cmd.header.in = tpm_getrandom_header;
|
||||
tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes);
|
||||
|
||||
@@ -62,6 +62,59 @@ enum tpm_duration {
|
||||
#define TPM_ERR_INVALID_POSTINIT 38
|
||||
|
||||
#define TPM_HEADER_SIZE 10
|
||||
|
||||
enum tpm2_const {
|
||||
TPM2_PLATFORM_PCR = 24,
|
||||
TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8),
|
||||
TPM2_TIMEOUT_A = 750,
|
||||
TPM2_TIMEOUT_B = 2000,
|
||||
TPM2_TIMEOUT_C = 200,
|
||||
TPM2_TIMEOUT_D = 30,
|
||||
TPM2_DURATION_SHORT = 20,
|
||||
TPM2_DURATION_MEDIUM = 750,
|
||||
TPM2_DURATION_LONG = 2000,
|
||||
};
|
||||
|
||||
enum tpm2_structures {
|
||||
TPM2_ST_NO_SESSIONS = 0x8001,
|
||||
TPM2_ST_SESSIONS = 0x8002,
|
||||
};
|
||||
|
||||
enum tpm2_return_codes {
|
||||
TPM2_RC_INITIALIZE = 0x0100,
|
||||
TPM2_RC_TESTING = 0x090A,
|
||||
TPM2_RC_DISABLED = 0x0120,
|
||||
};
|
||||
|
||||
enum tpm2_algorithms {
|
||||
TPM2_ALG_SHA1 = 0x0004,
|
||||
};
|
||||
|
||||
enum tpm2_command_codes {
|
||||
TPM2_CC_FIRST = 0x011F,
|
||||
TPM2_CC_SELF_TEST = 0x0143,
|
||||
TPM2_CC_STARTUP = 0x0144,
|
||||
TPM2_CC_SHUTDOWN = 0x0145,
|
||||
TPM2_CC_GET_CAPABILITY = 0x017A,
|
||||
TPM2_CC_GET_RANDOM = 0x017B,
|
||||
TPM2_CC_PCR_READ = 0x017E,
|
||||
TPM2_CC_PCR_EXTEND = 0x0182,
|
||||
TPM2_CC_LAST = 0x018F,
|
||||
};
|
||||
|
||||
enum tpm2_permanent_handles {
|
||||
TPM2_RS_PW = 0x40000009,
|
||||
};
|
||||
|
||||
enum tpm2_capabilities {
|
||||
TPM2_CAP_TPM_PROPERTIES = 6,
|
||||
};
|
||||
|
||||
enum tpm2_startup_types {
|
||||
TPM2_SU_CLEAR = 0x0000,
|
||||
TPM2_SU_STATE = 0x0001,
|
||||
};
|
||||
|
||||
struct tpm_chip;
|
||||
|
||||
struct tpm_vendor_specific {
|
||||
@@ -99,6 +152,7 @@ struct tpm_vendor_specific {
|
||||
enum tpm_chip_flags {
|
||||
TPM_CHIP_FLAG_REGISTERED = BIT(0),
|
||||
TPM_CHIP_FLAG_PPI = BIT(1),
|
||||
TPM_CHIP_FLAG_TPM2 = BIT(2),
|
||||
};
|
||||
|
||||
struct tpm_chip {
|
||||
@@ -370,3 +424,15 @@ static inline void tpm_remove_ppi(struct tpm_chip *chip)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
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, const u8 *hash);
|
||||
int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max);
|
||||
ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id,
|
||||
u32 *value, const char *desc);
|
||||
|
||||
extern int tpm2_startup(struct tpm_chip *chip, u16 startup_type);
|
||||
extern int tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type);
|
||||
extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32);
|
||||
extern int tpm2_do_selftest(struct tpm_chip *chip);
|
||||
extern int tpm2_gen_interrupt(struct tpm_chip *chip, bool quiet);
|
||||
|
||||
617
drivers/char/tpm/tpm2-cmd.c
Normal file
617
drivers/char/tpm/tpm2-cmd.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user