security/tpm: make tis_probe() return tpm_family
Via an out parameter. This is needed to be able to dynamically pick TSS implementation based on the information discovered on probing. Change-Id: I5006e0cdfef76ff79ce9e1cf280fcd5515ae01b0 Ticket: https://ticket.coreboot.org/issues/433 Signed-off-by: Sergii Dmytruk <sergii.dmytruk@3mdeb.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/69159 Reviewed-by: Martin L Roth <gaumless@gmail.com> Reviewed-by: Jérémy Compostella <jeremy.compostella@intel.com> Reviewed-by: Julius Werner <jwerner@chromium.org> Reviewed-by: Christian Walter <christian.walter@9elements.com> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
This commit is contained in:
committed by
Martin L Roth
parent
4b76273ac9
commit
febf9b9f24
@@ -46,7 +46,7 @@ static tpm_result_t crb_tpm_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, u
|
|||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
tis_sendrecv_fn tis_probe(void)
|
tis_sendrecv_fn tis_probe(enum tpm_family *family)
|
||||||
{
|
{
|
||||||
struct tpm2_info info;
|
struct tpm2_info info;
|
||||||
|
|
||||||
@@ -54,6 +54,10 @@ tis_sendrecv_fn tis_probe(void)
|
|||||||
if (tpm2_init())
|
if (tpm2_init())
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
/* CRB interface exists only in TPM2 */
|
||||||
|
if (family != NULL)
|
||||||
|
*family = TPM_2;
|
||||||
|
|
||||||
tpm2_get_info(&info);
|
tpm2_get_info(&info);
|
||||||
|
|
||||||
printk(BIOS_INFO, "Initialized TPM device %s revision %d\n", tis_get_dev_name(&info),
|
printk(BIOS_INFO, "Initialized TPM device %s revision %d\n", tis_get_dev_name(&info),
|
||||||
|
@@ -424,8 +424,11 @@ static void cr50_vendor_init(struct tpm_chip *chip)
|
|||||||
chip->cancel = &cr50_i2c_tis_ready;
|
chip->cancel = &cr50_i2c_tis_ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr)
|
tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr, enum tpm_family *family)
|
||||||
{
|
{
|
||||||
|
/* cr50 is TPM2 */
|
||||||
|
if (family != NULL)
|
||||||
|
*family = TPM_2;
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -118,9 +118,9 @@ static tpm_result_t i2c_tpm_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
|
|||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
tis_sendrecv_fn tis_probe(void)
|
tis_sendrecv_fn tis_probe(enum tpm_family *family)
|
||||||
{
|
{
|
||||||
if (tpm_vendor_probe(CONFIG_DRIVER_TPM_I2C_BUS, CONFIG_DRIVER_TPM_I2C_ADDR))
|
if (tpm_vendor_probe(CONFIG_DRIVER_TPM_I2C_BUS, CONFIG_DRIVER_TPM_I2C_ADDR, family))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (tpm_vendor_init(&chip, CONFIG_DRIVER_TPM_I2C_BUS, CONFIG_DRIVER_TPM_I2C_ADDR))
|
if (tpm_vendor_init(&chip, CONFIG_DRIVER_TPM_I2C_BUS, CONFIG_DRIVER_TPM_I2C_ADDR))
|
||||||
|
@@ -107,7 +107,19 @@ static tpm_result_t i2c_tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
|
|||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
tis_sendrecv_fn tis_probe(void)
|
tis_sendrecv_fn tis_probe(enum tpm_family *family)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
* Can't query version or really anything as the device doesn't support
|
||||||
|
* much through this interface (can't specify address on accesses).
|
||||||
|
*
|
||||||
|
* Hence the assumption is that whatever TPM version is enabled at
|
||||||
|
* compile-time defines what the device supports. The check is written
|
||||||
|
* in a way to give TPM 1 preference even if support for both versions
|
||||||
|
* is compiled in.
|
||||||
|
*/
|
||||||
|
if (family != NULL)
|
||||||
|
*family = CONFIG(TPM1) ? TPM_1 : TPM_2;
|
||||||
|
|
||||||
return &i2c_tis_sendrecv;
|
return &i2c_tis_sendrecv;
|
||||||
}
|
}
|
||||||
|
@@ -451,13 +451,29 @@ out_err:
|
|||||||
|
|
||||||
/* Initialization of I2C TPM */
|
/* Initialization of I2C TPM */
|
||||||
|
|
||||||
tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr)
|
tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr, enum tpm_family *family)
|
||||||
{
|
{
|
||||||
struct stopwatch sw;
|
struct stopwatch sw;
|
||||||
uint8_t buf = 0;
|
uint8_t buf = 0;
|
||||||
int ret;
|
int ret;
|
||||||
long sw_run_duration = SLEEP_DURATION_PROBE_MS;
|
long sw_run_duration = SLEEP_DURATION_PROBE_MS;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Infineon "I2C Protocol Stack Specification v0.20" is supposedly a
|
||||||
|
* simple adoption of the LPC TIS Protocol to the I2C Bus, but looking
|
||||||
|
* at "TCG PC Client Specific TIS" doesn't confirm that and Infineon's
|
||||||
|
* specification isn't publicly available.
|
||||||
|
*
|
||||||
|
* Because it's unknown how to access information about TPM version of
|
||||||
|
* the device in this case, the assumption is that whatever TPM version
|
||||||
|
* is enabled at compile-time defines what the device supports. And
|
||||||
|
* since this driver doesn't appear to be used with TPM 2 devices, the
|
||||||
|
* check is written in a way to give TPM 1 preference even if support
|
||||||
|
* for both versions is compiled in.
|
||||||
|
*/
|
||||||
|
if (family != NULL)
|
||||||
|
*family = CONFIG(TPM1) ? TPM_1 : TPM_2;
|
||||||
|
|
||||||
tpm_dev.chip_type = UNKNOWN;
|
tpm_dev.chip_type = UNKNOWN;
|
||||||
tpm_dev.bus = bus;
|
tpm_dev.bus = bus;
|
||||||
tpm_dev.addr = addr;
|
tpm_dev.addr = addr;
|
||||||
|
@@ -12,6 +12,7 @@
|
|||||||
#ifndef __DRIVERS_TPM_SLB9635_I2C_TPM_H__
|
#ifndef __DRIVERS_TPM_SLB9635_I2C_TPM_H__
|
||||||
#define __DRIVERS_TPM_SLB9635_I2C_TPM_H__
|
#define __DRIVERS_TPM_SLB9635_I2C_TPM_H__
|
||||||
|
|
||||||
|
#include <security/tpm/tis.h>
|
||||||
#include <security/tpm/tss_errors.h>
|
#include <security/tpm/tss_errors.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ struct tpm_chip {
|
|||||||
|
|
||||||
/* ---------- Interface for TPM vendor ------------ */
|
/* ---------- Interface for TPM vendor ------------ */
|
||||||
|
|
||||||
tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr);
|
tpm_result_t tpm_vendor_probe(unsigned int bus, uint32_t addr, enum tpm_family *family);
|
||||||
|
|
||||||
tpm_result_t tpm_vendor_init(struct tpm_chip *chip, unsigned int bus, uint32_t dev_addr);
|
tpm_result_t tpm_vendor_init(struct tpm_chip *chip, unsigned int bus, uint32_t dev_addr);
|
||||||
|
|
||||||
|
@@ -78,12 +78,6 @@
|
|||||||
/* 1 second is plenty for anything TPM does.*/
|
/* 1 second is plenty for anything TPM does.*/
|
||||||
#define MAX_DELAY_US USECS_PER_SEC
|
#define MAX_DELAY_US USECS_PER_SEC
|
||||||
|
|
||||||
enum tpm_family {
|
|
||||||
TPM_UNKNOWN = 0,
|
|
||||||
TPM_1 = 1,
|
|
||||||
TPM_2 = 2,
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Structures defined below allow creating descriptions of TPM vendor/device
|
* Structures defined below allow creating descriptions of TPM vendor/device
|
||||||
* ID information for run time discovery.
|
* ID information for run time discovery.
|
||||||
@@ -380,8 +374,10 @@ static tpm_result_t tis_command_ready(u8 locality)
|
|||||||
* Returns TPM_SUCCESS on success (the device is found or was found during
|
* Returns TPM_SUCCESS on success (the device is found or was found during
|
||||||
* an earlier invocation) or TPM_CB_FAIL if the device is not found.
|
* an earlier invocation) or TPM_CB_FAIL if the device is not found.
|
||||||
*/
|
*/
|
||||||
static tpm_result_t pc80_tis_probe(void)
|
static tpm_result_t pc80_tis_probe(enum tpm_family *family)
|
||||||
{
|
{
|
||||||
|
static enum tpm_family tpm_family;
|
||||||
|
|
||||||
const char *device_name = NULL;
|
const char *device_name = NULL;
|
||||||
const char *vendor_name = NULL;
|
const char *vendor_name = NULL;
|
||||||
const struct device_name *dev;
|
const struct device_name *dev;
|
||||||
@@ -389,11 +385,13 @@ static tpm_result_t pc80_tis_probe(void)
|
|||||||
u16 vid, did;
|
u16 vid, did;
|
||||||
u8 locality = 0, intf_type;
|
u8 locality = 0, intf_type;
|
||||||
int i;
|
int i;
|
||||||
enum tpm_family family;
|
|
||||||
const char *family_str;
|
const char *family_str;
|
||||||
|
|
||||||
if (vendor_dev_id)
|
if (vendor_dev_id) {
|
||||||
|
if (family != NULL)
|
||||||
|
*family = tpm_family;
|
||||||
return TPM_SUCCESS; /* Already probed. */
|
return TPM_SUCCESS; /* Already probed. */
|
||||||
|
}
|
||||||
|
|
||||||
didvid = tpm_read_did_vid(0);
|
didvid = tpm_read_did_vid(0);
|
||||||
if (!didvid || (didvid == 0xffffffff)) {
|
if (!didvid || (didvid == 0xffffffff)) {
|
||||||
@@ -409,10 +407,10 @@ static tpm_result_t pc80_tis_probe(void)
|
|||||||
switch (intf_version) {
|
switch (intf_version) {
|
||||||
case 0:
|
case 0:
|
||||||
case 2:
|
case 2:
|
||||||
family = TPM_1;
|
tpm_family = TPM_1;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
family = TPM_2;
|
tpm_family = TPM_2;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("%s: Unexpected TPM interface version: %d\n", __func__,
|
printf("%s: Unexpected TPM interface version: %d\n", __func__,
|
||||||
@@ -420,7 +418,7 @@ static tpm_result_t pc80_tis_probe(void)
|
|||||||
return TPM_CB_PROBE_FAILURE;
|
return TPM_CB_PROBE_FAILURE;
|
||||||
}
|
}
|
||||||
} else if (intf_type == 0) {
|
} else if (intf_type == 0) {
|
||||||
family = TPM_2;
|
tpm_family = TPM_2;
|
||||||
} else {
|
} else {
|
||||||
printf("%s: Unexpected TPM interface type: %d\n", __func__, intf_type);
|
printf("%s: Unexpected TPM interface type: %d\n", __func__, intf_type);
|
||||||
return TPM_CB_PROBE_FAILURE;
|
return TPM_CB_PROBE_FAILURE;
|
||||||
@@ -439,7 +437,7 @@ static tpm_result_t pc80_tis_probe(void)
|
|||||||
}
|
}
|
||||||
dev = &vendor_names[i].dev_names[j];
|
dev = &vendor_names[i].dev_names[j];
|
||||||
while (dev->dev_id != 0xffff) {
|
while (dev->dev_id != 0xffff) {
|
||||||
if (dev->dev_id == did && dev->family == family) {
|
if (dev->dev_id == did && dev->family == tpm_family) {
|
||||||
device_name = dev->dev_name;
|
device_name = dev->dev_name;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -449,7 +447,7 @@ static tpm_result_t pc80_tis_probe(void)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
family_str = (family == TPM_1 ? "TPM 1.2" : "TPM 2.0");
|
family_str = (tpm_family == TPM_1 ? "TPM 1.2" : "TPM 2.0");
|
||||||
if (vendor_name == NULL) {
|
if (vendor_name == NULL) {
|
||||||
printk(BIOS_INFO, "Found %s 0x%04x by 0x%04x\n", family_str, did, vid);
|
printk(BIOS_INFO, "Found %s 0x%04x by 0x%04x\n", family_str, did, vid);
|
||||||
} else if (device_name == NULL) {
|
} else if (device_name == NULL) {
|
||||||
@@ -460,6 +458,8 @@ static tpm_result_t pc80_tis_probe(void)
|
|||||||
device_name, did, vendor_name, vid);
|
device_name, did, vendor_name, vid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (family != NULL)
|
||||||
|
*family = tpm_family;
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -720,12 +720,15 @@ static tpm_result_t pc80_tpm_sendrecv(const uint8_t *sendbuf, size_t send_size,
|
|||||||
/*
|
/*
|
||||||
* tis_probe()
|
* tis_probe()
|
||||||
*
|
*
|
||||||
* Probe for the TPM device and set it up for use within locality 0. Returns
|
* Probe for the TPM device and set it up for use within locality 0.
|
||||||
* pointer to send-receive function on success or NULL on failure.
|
*
|
||||||
|
* @tpm_family - pointer to tpm_family which is set to TPM family of the device.
|
||||||
|
*
|
||||||
|
* Returns pointer to send-receive function on success or NULL on failure.
|
||||||
*/
|
*/
|
||||||
tis_sendrecv_fn tis_probe(void)
|
tis_sendrecv_fn tis_probe(enum tpm_family *family)
|
||||||
{
|
{
|
||||||
if (pc80_tis_probe())
|
if (pc80_tis_probe(family))
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
if (pc80_tis_open())
|
if (pc80_tis_open())
|
||||||
|
@@ -40,7 +40,7 @@ static tpm_result_t tpm_sendrecv(const uint8_t *sendbuf, size_t sbuf_size,
|
|||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
tis_sendrecv_fn tis_probe(void)
|
tis_sendrecv_fn tis_probe(enum tpm_family *family)
|
||||||
{
|
{
|
||||||
struct spi_slave spi;
|
struct spi_slave spi;
|
||||||
struct tpm2_info info;
|
struct tpm2_info info;
|
||||||
@@ -56,6 +56,10 @@ tis_sendrecv_fn tis_probe(void)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* tpm2_process_command() is used unconditionally in tpm_sendrecv() */
|
||||||
|
if (family != NULL)
|
||||||
|
*family = TPM_2;
|
||||||
|
|
||||||
tpm2_get_info(&info);
|
tpm2_get_info(&info);
|
||||||
|
|
||||||
printk(BIOS_INFO, "Initialized TPM device %s revision %d\n",
|
printk(BIOS_INFO, "Initialized TPM device %s revision %d\n",
|
||||||
|
@@ -32,6 +32,12 @@ enum tis_status {
|
|||||||
TPM_STS_RESPONSE_RETRY = (1 << 1),
|
TPM_STS_RESPONSE_RETRY = (1 << 1),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum tpm_family {
|
||||||
|
TPM_UNKNOWN = 0,
|
||||||
|
TPM_1 = 1,
|
||||||
|
TPM_2 = 2,
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tis_sendrecv()
|
* tis_sendrecv()
|
||||||
*
|
*
|
||||||
@@ -50,13 +56,16 @@ typedef tpm_result_t (*tis_sendrecv_fn)(const u8 *sendbuf, size_t send_size, u8
|
|||||||
/*
|
/*
|
||||||
* tis_probe()
|
* tis_probe()
|
||||||
*
|
*
|
||||||
* Probe for the TPM device and set it up for use within locality 0. Returns
|
* Probe for the TPM device and set it up for use within locality 0.
|
||||||
* pointer to send-receive function on success or NULL on failure.
|
*
|
||||||
|
* @family - pointer which is set to TPM family of the device
|
||||||
|
*
|
||||||
|
* Returns pointer to send-receive function on success or NULL on failure.
|
||||||
*
|
*
|
||||||
* Do not call this explicitly, it's meant to be used exclusively by TSS
|
* Do not call this explicitly, it's meant to be used exclusively by TSS
|
||||||
* implementation (tlcl_lib_init() function to be specific).
|
* implementation (tlcl_lib_init() function to be specific).
|
||||||
*/
|
*/
|
||||||
tis_sendrecv_fn tis_probe(void);
|
tis_sendrecv_fn tis_probe(enum tpm_family *family);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* tis_vendor_write()
|
* tis_vendor_write()
|
||||||
|
@@ -153,13 +153,20 @@ static tpm_result_t send(const uint8_t *command)
|
|||||||
|
|
||||||
tpm_result_t tlcl_lib_init(void)
|
tpm_result_t tlcl_lib_init(void)
|
||||||
{
|
{
|
||||||
|
enum tpm_family family;
|
||||||
|
|
||||||
if (tis_sendrecv != NULL)
|
if (tis_sendrecv != NULL)
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
|
|
||||||
tis_sendrecv = tis_probe();
|
tis_sendrecv = tis_probe(&family);
|
||||||
if (tis_sendrecv == NULL)
|
if (tis_sendrecv == NULL)
|
||||||
return TPM_CB_NO_DEVICE;
|
return TPM_CB_NO_DEVICE;
|
||||||
|
|
||||||
|
if (family != TPM_1) {
|
||||||
|
tis_sendrecv = NULL;
|
||||||
|
return TPM_CB_INTERNAL_INCONSISTENCY;
|
||||||
|
}
|
||||||
|
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -211,15 +211,24 @@ tpm_result_t tlcl_clear_control(bool disable)
|
|||||||
/* This function is called directly by vboot, uses vboot return types. */
|
/* This function is called directly by vboot, uses vboot return types. */
|
||||||
tpm_result_t tlcl_lib_init(void)
|
tpm_result_t tlcl_lib_init(void)
|
||||||
{
|
{
|
||||||
|
enum tpm_family family;
|
||||||
|
|
||||||
if (tis_sendrecv != NULL)
|
if (tis_sendrecv != NULL)
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
|
|
||||||
tis_sendrecv = tis_probe();
|
tis_sendrecv = tis_probe(&family);
|
||||||
if (tis_sendrecv == NULL) {
|
if (tis_sendrecv == NULL) {
|
||||||
printk(BIOS_ERR, "%s: tis_probe returned error\n", __func__);
|
printk(BIOS_ERR, "%s: tis_probe returned error\n", __func__);
|
||||||
return TPM_CB_NO_DEVICE;
|
return TPM_CB_NO_DEVICE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (family != TPM_2) {
|
||||||
|
tis_sendrecv = NULL;
|
||||||
|
printk(BIOS_ERR, "%s: tis_probe returned unsupported TPM family: %d\n",
|
||||||
|
__func__, family);
|
||||||
|
return TPM_CB_INTERNAL_INCONSISTENCY;
|
||||||
|
}
|
||||||
|
|
||||||
return TPM_SUCCESS;
|
return TPM_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user