diff options
Diffstat (limited to 'drivers/char/tpm/tpm2-space.c')
-rw-r--r-- | drivers/char/tpm/tpm2-space.c | 51 |
1 files changed, 46 insertions, 5 deletions
diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index 5d6487575074..92aea758d9c6 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -264,14 +264,54 @@ static int tpm2_map_command(struct tpm_chip *chip, u32 cc, u8 *cmd) return 0; } -int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, - u8 *cmd) +static int tpm_find_and_validate_cc(struct tpm_chip *chip, + struct tpm_space *space, + const void *cmd, size_t len) +{ + const struct tpm_header *header = (const void *)cmd; + int i; + u32 cc; + u32 attrs; + unsigned int nr_handles; + + if (len < TPM_HEADER_SIZE || !chip->nr_commands) + return -EINVAL; + + cc = be32_to_cpu(header->ordinal); + + i = tpm2_find_cc(chip, cc); + if (i < 0) { + dev_dbg(&chip->dev, "0x%04X is an invalid command\n", + cc); + return -EOPNOTSUPP; + } + + attrs = chip->cc_attrs_tbl[i]; + nr_handles = + 4 * ((attrs >> TPM2_CC_ATTR_CHANDLES) & GENMASK(2, 0)); + if (len < TPM_HEADER_SIZE + 4 * nr_handles) + goto err_len; + + return cc; +err_len: + dev_dbg(&chip->dev, "%s: insufficient command length %zu", __func__, + len); + return -EINVAL; +} + +int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u8 *cmd, + size_t cmdsiz) { int rc; + int cc; if (!space) return 0; + cc = tpm_find_and_validate_cc(chip, space, cmd, cmdsiz); + if (cc < 0) + return cc; + memcpy(&chip->work_space.context_tbl, &space->context_tbl, sizeof(space->context_tbl)); memcpy(&chip->work_space.session_tbl, &space->session_tbl, @@ -291,6 +331,7 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, return rc; } + chip->last_cc = cc; return 0; } @@ -490,7 +531,7 @@ static int tpm2_save_space(struct tpm_chip *chip) } int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, - u32 cc, void *buf, size_t *bufsiz) + void *buf, size_t *bufsiz) { struct tpm_header *header = buf; int rc; @@ -498,13 +539,13 @@ int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, if (!space) return 0; - rc = tpm2_map_response_header(chip, cc, buf, *bufsiz); + rc = tpm2_map_response_header(chip, chip->last_cc, buf, *bufsiz); if (rc) { tpm2_flush_space(chip); goto out; } - rc = tpm2_map_response_body(chip, cc, buf, *bufsiz); + rc = tpm2_map_response_body(chip, chip->last_cc, buf, *bufsiz); if (rc) { tpm2_flush_space(chip); goto out; |