Commit 92b7e492 authored by Linus Torvalds's avatar Linus Torvalds

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
parents c6fe44d9 85467f63
...@@ -49,9 +49,9 @@ int tpm_read_log_acpi(struct tpm_chip *chip) ...@@ -49,9 +49,9 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
void __iomem *virt; void __iomem *virt;
u64 len, start; u64 len, start;
struct tpm_bios_log *log; struct tpm_bios_log *log;
struct acpi_table_tpm2 *tbl;
if (chip->flags & TPM_CHIP_FLAG_TPM2) struct acpi_tpm2_phy *tpm2_phy;
return -ENODEV; int format;
log = &chip->log; log = &chip->log;
...@@ -61,23 +61,44 @@ int tpm_read_log_acpi(struct tpm_chip *chip) ...@@ -61,23 +61,44 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
if (!chip->acpi_dev_handle) if (!chip->acpi_dev_handle)
return -ENODEV; return -ENODEV;
/* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ if (chip->flags & TPM_CHIP_FLAG_TPM2) {
status = acpi_get_table(ACPI_SIG_TCPA, 1, status = acpi_get_table("TPM2", 1,
(struct acpi_table_header **)&buff); (struct acpi_table_header **)&tbl);
if (ACPI_FAILURE(status))
if (ACPI_FAILURE(status)) return -ENODEV;
return -ENODEV;
if (tbl->header.length <
switch(buff->platform_class) { sizeof(*tbl) + sizeof(struct acpi_tpm2_phy))
case BIOS_SERVER: return -ENODEV;
len = buff->server.log_max_len;
start = buff->server.log_start_addr; tpm2_phy = (void *)tbl + sizeof(*tbl);
break; len = tpm2_phy->log_area_minimum_length;
case BIOS_CLIENT:
default: start = tpm2_phy->log_area_start_address;
len = buff->client.log_max_len; if (!start || !len)
start = buff->client.log_start_addr; return -ENODEV;
break;
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) { if (!len) {
dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__); dev_warn(&chip->dev, "%s: TCPA log area empty\n", __func__);
...@@ -98,7 +119,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip) ...@@ -98,7 +119,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip)
memcpy_fromio(log->bios_event_log, virt, len); memcpy_fromio(log->bios_event_log, virt, len);
acpi_os_unmap_iomem(virt, len); acpi_os_unmap_iomem(virt, len);
return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; return format;
err: err:
kfree(log->bios_event_log); kfree(log->bios_event_log);
......
...@@ -386,13 +386,8 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev, ...@@ -386,13 +386,8 @@ struct tpm_chip *tpm_chip_alloc(struct device *pdev,
chip->cdev.owner = THIS_MODULE; chip->cdev.owner = THIS_MODULE;
chip->cdevs.owner = THIS_MODULE; chip->cdevs.owner = THIS_MODULE;
chip->work_space.context_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); rc = tpm2_init_space(&chip->work_space, TPM2_SPACE_BUFFER_SIZE);
if (!chip->work_space.context_buf) { if (rc) {
rc = -ENOMEM;
goto out;
}
chip->work_space.session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL);
if (!chip->work_space.session_buf) {
rc = -ENOMEM; rc = -ENOMEM;
goto out; goto out;
} }
......
...@@ -59,6 +59,9 @@ enum tpm_addr { ...@@ -59,6 +59,9 @@ enum tpm_addr {
#define TPM_TAG_RQU_COMMAND 193 #define TPM_TAG_RQU_COMMAND 193
/* TPM2 specific constants. */
#define TPM2_SPACE_BUFFER_SIZE 16384 /* 16 kB */
struct stclear_flags_t { struct stclear_flags_t {
__be16 tag; __be16 tag;
u8 deactivated; u8 deactivated;
...@@ -228,7 +231,7 @@ unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); ...@@ -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_probe(struct tpm_chip *chip);
int tpm2_get_cc_attrs_tbl(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_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_del_space(struct tpm_chip *chip, struct tpm_space *space);
void tpm2_flush_space(struct tpm_chip *chip); void tpm2_flush_space(struct tpm_chip *chip);
int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd, 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) ...@@ -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) if (!space->context_buf)
return -ENOMEM; return -ENOMEM;
space->session_buf = kzalloc(PAGE_SIZE, GFP_KERNEL); space->session_buf = kzalloc(buf_size, GFP_KERNEL);
if (space->session_buf == NULL) { if (space->session_buf == NULL) {
kfree(space->context_buf); kfree(space->context_buf);
/* Prevent caller getting a dangling pointer. */
space->context_buf = NULL;
return -ENOMEM; return -ENOMEM;
} }
space->buf_size = buf_size;
return 0; return 0;
} }
...@@ -311,8 +314,10 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd, ...@@ -311,8 +314,10 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd,
sizeof(space->context_tbl)); sizeof(space->context_tbl));
memcpy(&chip->work_space.session_tbl, &space->session_tbl, memcpy(&chip->work_space.session_tbl, &space->session_tbl,
sizeof(space->session_tbl)); sizeof(space->session_tbl));
memcpy(chip->work_space.context_buf, space->context_buf, PAGE_SIZE); memcpy(chip->work_space.context_buf, space->context_buf,
memcpy(chip->work_space.session_buf, space->session_buf, PAGE_SIZE); space->buf_size);
memcpy(chip->work_space.session_buf, space->session_buf,
space->buf_size);
rc = tpm2_load_space(chip); rc = tpm2_load_space(chip);
if (rc) { if (rc) {
...@@ -492,7 +497,7 @@ static int tpm2_save_space(struct tpm_chip *chip) ...@@ -492,7 +497,7 @@ static int tpm2_save_space(struct tpm_chip *chip)
continue; continue;
rc = tpm2_save_context(chip, space->context_tbl[i], rc = tpm2_save_context(chip, space->context_tbl[i],
space->context_buf, PAGE_SIZE, space->context_buf, space->buf_size,
&offset); &offset);
if (rc == -ENOENT) { if (rc == -ENOENT) {
space->context_tbl[i] = 0; space->context_tbl[i] = 0;
...@@ -509,9 +514,8 @@ static int tpm2_save_space(struct tpm_chip *chip) ...@@ -509,9 +514,8 @@ static int tpm2_save_space(struct tpm_chip *chip)
continue; continue;
rc = tpm2_save_context(chip, space->session_tbl[i], rc = tpm2_save_context(chip, space->session_tbl[i],
space->session_buf, PAGE_SIZE, space->session_buf, space->buf_size,
&offset); &offset);
if (rc == -ENOENT) { if (rc == -ENOENT) {
/* handle error saving session, just forget it */ /* handle error saving session, just forget it */
space->session_tbl[i] = 0; space->session_tbl[i] = 0;
...@@ -557,8 +561,10 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, ...@@ -557,8 +561,10 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space,
sizeof(space->context_tbl)); sizeof(space->context_tbl));
memcpy(&space->session_tbl, &chip->work_space.session_tbl, memcpy(&space->session_tbl, &chip->work_space.session_tbl,
sizeof(space->session_tbl)); sizeof(space->session_tbl));
memcpy(space->context_buf, chip->work_space.context_buf, PAGE_SIZE); memcpy(space->context_buf, chip->work_space.context_buf,
memcpy(space->session_buf, chip->work_space.session_buf, PAGE_SIZE); space->buf_size);
memcpy(space->session_buf, chip->work_space.session_buf,
space->buf_size);
return 0; return 0;
out: out:
......
...@@ -21,7 +21,7 @@ static int tpmrm_open(struct inode *inode, struct file *file) ...@@ -21,7 +21,7 @@ static int tpmrm_open(struct inode *inode, struct file *file)
if (priv == NULL) if (priv == NULL)
return -ENOMEM; return -ENOMEM;
rc = tpm2_init_space(&priv->space); rc = tpm2_init_space(&priv->space, TPM2_SPACE_BUFFER_SIZE);
if (rc) { if (rc) {
kfree(priv); kfree(priv);
return -ENOMEM; return -ENOMEM;
......
...@@ -415,6 +415,13 @@ struct acpi_table_tpm2 { ...@@ -415,6 +415,13 @@ struct acpi_table_tpm2 {
/* Platform-specific data follows */ /* 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 */ /* Values for start_method above */
#define ACPI_TPM2_NOT_ALLOWED 0 #define ACPI_TPM2_NOT_ALLOWED 0
......
...@@ -96,6 +96,7 @@ struct tpm_space { ...@@ -96,6 +96,7 @@ struct tpm_space {
u8 *context_buf; u8 *context_buf;
u32 session_tbl[3]; u32 session_tbl[3];
u8 *session_buf; u8 *session_buf;
u32 buf_size;
}; };
struct tpm_bios_log { struct tpm_bios_log {
......
...@@ -211,9 +211,16 @@ static inline int __calc_tpm2_event_size(struct tcg_pcr_event2_head *event, ...@@ -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; 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, 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; size = 0;
goto out; goto out;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment