tpmdd updates for Linux v5.9
-----BEGIN PGP SIGNATURE----- iJYEABYIAD4WIQRE6pSOnaBC00OEHEIaerohdGur0gUCXxp/7yAcamFya2tvLnNh a2tpbmVuQGxpbnV4LmludGVsLmNvbQAKCRAaerohdGur0keXAQDcGHPuKqZupIm6 YRKskWPg9IDeuA7E/Edeey1BksjU8gEAqf1ghVyFM0Tzhd8uWiy2PGwZOvb5MyX8 wL3dCnv3VwA= =Yg1/ -----END PGP SIGNATURE----- Merge tag 'tpmdd-next-v5.9' of git://git.infradead.org/users/jjs/linux-tpmdd Pull tpm updates from Jarkko Sakkinen: "An issue was fixed with the TPM space buffer size. The buffer is used to store in-TPM objects while swapped out of the TPM for a /dev/tpmrm0 session. The code incorrectly used PAGE_SIZE, which obviously can vary. With these changes the buffer has a fixed size of 16 kB. In addition, this contains support for acquiring TPM even log from TPM2 ACPI table. This method is used by QEMU in particular" * tag 'tpmdd-next-v5.9' of git://git.infradead.org/users/jjs/linux-tpmdd: tpm: Add support for event log pointer found in TPM2 ACPI table acpi: Extend TPM2 ACPI table with missing log fields tpm: Unify the mismatching TPM space buffer sizes tpm: Require that all digests are present in TCG_PCR_EVENT2 structures
This commit is contained in:
commit
92b7e4923f
|
@ -49,9 +49,9 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
|
|||
void __iomem *virt;
|
||||
u64 len, start;
|
||||
struct tpm_bios_log *log;
|
||||
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2)
|
||||
return -ENODEV;
|
||||
struct acpi_table_tpm2 *tbl;
|
||||
struct acpi_tpm2_phy *tpm2_phy;
|
||||
int format;
|
||||
|
||||
log = &chip->log;
|
||||
|
||||
|
@ -61,23 +61,44 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
|
|||
if (!chip->acpi_dev_handle)
|
||||
return -ENODEV;
|
||||
|
||||
/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
|
||||
status = acpi_get_table(ACPI_SIG_TCPA, 1,
|
||||
(struct acpi_table_header **)&buff);
|
||||
if (chip->flags & TPM_CHIP_FLAG_TPM2) {
|
||||
status = acpi_get_table("TPM2", 1,
|
||||
(struct acpi_table_header **)&tbl);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
if (tbl->header.length <
|
||||
sizeof(*tbl) + sizeof(struct acpi_tpm2_phy))
|
||||
return -ENODEV;
|
||||
|
||||
switch(buff->platform_class) {
|
||||
case BIOS_SERVER:
|
||||
len = buff->server.log_max_len;
|
||||
start = buff->server.log_start_addr;
|
||||
break;
|
||||
case BIOS_CLIENT:
|
||||
default:
|
||||
len = buff->client.log_max_len;
|
||||
start = buff->client.log_start_addr;
|
||||
break;
|
||||
tpm2_phy = (void *)tbl + sizeof(*tbl);
|
||||
len = tpm2_phy->log_area_minimum_length;
|
||||
|
||||
start = tpm2_phy->log_area_start_address;
|
||||
if (!start || !len)
|
||||
return -ENODEV;
|
||||
|
||||
format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
|
||||
} else {
|
||||
/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */
|
||||
status = acpi_get_table(ACPI_SIG_TCPA, 1,
|
||||
(struct acpi_table_header **)&buff);
|
||||
if (ACPI_FAILURE(status))
|
||||
return -ENODEV;
|
||||
|
||||
switch (buff->platform_class) {
|
||||
case BIOS_SERVER:
|
||||
len = buff->server.log_max_len;
|
||||
start = buff->server.log_start_addr;
|
||||
break;
|
||||
case BIOS_CLIENT:
|
||||
default:
|
||||
len = buff->client.log_max_len;
|
||||
start = buff->client.log_start_addr;
|
||||
break;
|
||||
}
|
||||
|
||||
format = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
|
||||
}
|
||||
if (!len) {
|
||||
dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
|
||||
|
@ -98,7 +119,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 EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
|
||||
return format;
|
||||
|
||||
err:
|
||||
kfree(log->bios_event_log);
|
||||
|
|
|
@ -386,13 +386,8 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
|
|||
chip->cdev.owner = THIS_MODULE;
|
||||
chip->cdevs.owner = THIS_MODULE;
|
||||
|
||||
chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!chip->work_space.context_buf) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
chip->work_space.session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (!chip->work_space.session_buf) {
|
||||
rc = tpm2_init_space(&chip->work_space, TPM2_SPACE_BUFFER_SIZE);
|
||||
if (rc) {
|
||||
rc = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,9 @@ enum tpm_addr {
|
|||
|
||||
#define TPM_TAG_RQU_COMMAND 193
|
||||
|
||||
/* TPM2 specific constants. */
|
||||
#define TPM2_SPACE_BUFFER_SIZE 16384 /* 16 kB */
|
||||
|
||||
struct stclear_flags_t {
|
||||
__be16 tag;
|
||||
u8 deactivated;
|
||||
|
@ -228,7 +231,7 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal);
|
|||
int tpm2_probe(struct tpm_chip *chip);
|
||||
int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip);
|
||||
int tpm2_find_cc(struct tpm_chip *chip, u32 cc);
|
||||
int tpm2_init_space(struct tpm_space *space);
|
||||
int tpm2_init_space(struct tpm_space *space, unsigned int buf_size);
|
||||
void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space);
|
||||
void tpm2_flush_space(struct tpm_chip *chip);
|
||||
int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
|
||||
|
|
|
@ -38,18 +38,21 @@ static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space)
|
|||
}
|
||||
}
|
||||
|
||||
int tpm2_init_space(struct tpm_space *space)
|
||||
int tpm2_init_space(struct tpm_space *space, unsigned int buf_size)
|
||||
{
|
||||
space->context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
space->context_buf = kzalloc(buf_size, GFP_KERNEL);
|
||||
if (!space->context_buf)
|
||||
return -ENOMEM;
|
||||
|
||||
space->session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
space->session_buf = kzalloc(buf_size, GFP_KERNEL);
|
||||
if (space->session_buf == NULL) {
|
||||
kfree(space->context_buf);
|
||||
/* Prevent caller getting a dangling pointer. */
|
||||
space->context_buf = NULL;
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
space->buf_size = buf_size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -311,8 +314,10 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
|
|||
sizeof(space->context_tbl));
|
||||
memcpy(&chip->work_space.session_tbl, &space->session_tbl,
|
||||
sizeof(space->session_tbl));
|
||||
memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE);
|
||||
memcpy(chip->work_space.session_buf, space->session_buf, PAGE_SIZE);
|
||||
memcpy(chip->work_space.context_buf, space->context_buf,
|
||||
space->buf_size);
|
||||
memcpy(chip->work_space.session_buf, space->session_buf,
|
||||
space->buf_size);
|
||||
|
||||
rc = tpm2_load_space(chip);
|
||||
if (rc) {
|
||||
|
@ -492,7 +497,7 @@ static int tpm2_save_space(struct tpm_chip *chip)
|
|||
continue;
|
||||
|
||||
rc = tpm2_save_context(chip, space->context_tbl[i],
|
||||
space->context_buf, PAGE_SIZE,
|
||||
space->context_buf, space->buf_size,
|
||||
&offset);
|
||||
if (rc == -ENOENT) {
|
||||
space->context_tbl[i] = 0;
|
||||
|
@ -509,9 +514,8 @@ static int tpm2_save_space(struct tpm_chip *chip)
|
|||
continue;
|
||||
|
||||
rc = tpm2_save_context(chip, space->session_tbl[i],
|
||||
space->session_buf, PAGE_SIZE,
|
||||
space->session_buf, space->buf_size,
|
||||
&offset);
|
||||
|
||||
if (rc == -ENOENT) {
|
||||
/* handle error saving session, just forget it */
|
||||
space->session_tbl[i] = 0;
|
||||
|
@ -557,8 +561,10 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
|
|||
sizeof(space->context_tbl));
|
||||
memcpy(&space->session_tbl, &chip->work_space.session_tbl,
|
||||
sizeof(space->session_tbl));
|
||||
memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE);
|
||||
memcpy(space->session_buf, chip->work_space.session_buf, PAGE_SIZE);
|
||||
memcpy(space->context_buf, chip->work_space.context_buf,
|
||||
space->buf_size);
|
||||
memcpy(space->session_buf, chip->work_space.session_buf,
|
||||
space->buf_size);
|
||||
|
||||
return 0;
|
||||
out:
|
||||
|
|
|
@ -21,7 +21,7 @@ static int tpmrm_open(struct inode *inode, struct file *file)
|
|||
if (priv == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
rc = tpm2_init_space(&priv->space);
|
||||
rc = tpm2_init_space(&priv->space, TPM2_SPACE_BUFFER_SIZE);
|
||||
if (rc) {
|
||||
kfree(priv);
|
||||
return -ENOMEM;
|
||||
|
|
|
@ -415,6 +415,13 @@ struct acpi_table_tpm2 {
|
|||
/* Platform-specific data follows */
|
||||
};
|
||||
|
||||
/* Optional trailer for revision 4 holding platform-specific data */
|
||||
struct acpi_tpm2_phy {
|
||||
u8 start_method_specific[12];
|
||||
u32 log_area_minimum_length;
|
||||
u64 log_area_start_address;
|
||||
};
|
||||
|
||||
/* Values for start_method above */
|
||||
|
||||
#define ACPI_TPM2_NOT_ALLOWED 0
|
||||
|
|
|
@ -96,6 +96,7 @@ struct tpm_space {
|
|||
u8 *context_buf;
|
||||
u32 session_tbl[3];
|
||||
u8 *session_buf;
|
||||
u32 buf_size;
|
||||
};
|
||||
|
||||
struct tpm_bios_log {
|
||||
|
|
|
@ -211,9 +211,16 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event,
|
|||
|
||||
efispecid = (struct tcg_efi_specid_event_head *)event_header->event;
|
||||
|
||||
/* Check if event is malformed. */
|
||||
/*
|
||||
* Perform validation of the event in order to identify malformed
|
||||
* events. This function may be asked to parse arbitrary byte sequences
|
||||
* immediately following a valid event log. The caller expects this
|
||||
* function to recognize that the byte sequence is not a valid event
|
||||
* and to return an event size of 0.
|
||||
*/
|
||||
if (memcmp(efispecid->signature, TCG_SPECID_SIG,
|
||||
sizeof(TCG_SPECID_SIG)) || count > efispecid->num_algs) {
|
||||
sizeof(TCG_SPECID_SIG)) ||
|
||||
!efispecid->num_algs || count != efispecid->num_algs) {
|
||||
size = 0;
|
||||
goto out;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue