diff options
| author | Mark Brown <broonie@kernel.org> | 2026-08-21 14:07:32 +0100 |
|---|---|---|
| committer | Mark Brown <broonie@kernel.org> | 2026-08-21 14:07:32 +0100 |
| commit | fcae5e60ac2d0ae896691970c2a704ef81a67aed (patch) | |
| tree | 87203e087f7a3bc3041b30a99b379e64d57092ed | |
| parent | f06a9a5f98c172aa8a20939c0dbdddc8e420ec84 (diff) | |
| parent | aa754fea2bccbcc9ac6ed2c523ada20c06fe8e8d (diff) | |
| download | linux-next-fcae5e60ac2d0ae896691970c2a704ef81a67aed.tar.gz linux-next-fcae5e60ac2d0ae896691970c2a704ef81a67aed.zip | |
Merge branch 'for-next-tpm' of https://git.kernel.org/pub/scm/linux/kernel/git/jarkko/linux-tpmdd.git
| -rw-r--r-- | drivers/char/tpm/Kconfig | 3 | ||||
| -rw-r--r-- | drivers/char/tpm/st33zp24/st33zp24.c | 13 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm-buf.c | 145 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm-sysfs.c | 26 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm.h | 180 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm1-cmd.c | 180 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 321 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm2-sessions.c | 164 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm2-space.c | 57 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_i2c_nuvoton.c | 8 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_tis_core.h | 64 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_tis_i2c_cr50.c | 4 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_tis_spi.h | 8 | ||||
| -rw-r--r-- | drivers/char/tpm/tpm_vtpm_proxy.c | 30 | ||||
| -rw-r--r-- | include/keys/trusted_tpm.h | 1 | ||||
| -rw-r--r-- | include/linux/tpm.h | 230 | ||||
| -rw-r--r-- | include/linux/tpm_buf.h | 60 | ||||
| -rw-r--r-- | include/linux/tpm_command.h | 518 | ||||
| -rw-r--r-- | include/linux/tpm_eventlog.h | 2 | ||||
| -rw-r--r-- | include/linux/tpm_ptp.h | 133 | ||||
| -rw-r--r-- | security/keys/trusted-keys/trusted_tpm1.c | 47 | ||||
| -rw-r--r-- | security/keys/trusted-keys/trusted_tpm2.c | 166 |
22 files changed, 1256 insertions, 1104 deletions
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 8a8f692b6088..5f672f2c01b0 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig @@ -163,8 +163,7 @@ config TCG_NSC config TCG_ATMEL tristate "Atmel TPM Interface" - depends on HAS_IOPORT_MAP - depends on HAS_IOPORT + depends on X86 help If you have a TPM security chip from Atmel say Yes and it will be accessible from within Linux. To compile this driver diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index e2b7451ea7cc..c15a9b7aaff8 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c @@ -93,7 +93,9 @@ static u8 st33zp24_status(struct tpm_chip *chip) struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); u8 data; - tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1); + if (tpm_dev->ops->recv(tpm_dev->phy_id, TPM_STS, &data, 1) != 1) + return 0; + return data; } @@ -104,10 +106,10 @@ static bool check_locality(struct tpm_chip *chip) { struct st33zp24_dev *tpm_dev = dev_get_drvdata(&chip->dev); u8 data; - u8 status; + int status; status = tpm_dev->ops->recv(tpm_dev->phy_id, TPM_ACCESS, &data, 1); - if (status && (data & + if (status == 1 && (data & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) return true; @@ -506,11 +508,8 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops, ret = devm_request_irq(dev, irq, tpm_ioserirq_handler, IRQF_TRIGGER_HIGH, "TPM SERIRQ management", chip); - if (ret < 0) { - dev_err(&chip->dev, "TPM SERIRQ signals %d not available\n", - irq); + if (ret < 0) goto _tpm_clean_answer; - } intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_STS_VALID_INT diff --git a/drivers/char/tpm/tpm-buf.c b/drivers/char/tpm/tpm-buf.c index dc882fc9fa9e..233e81d3f149 100644 --- a/drivers/char/tpm/tpm-buf.c +++ b/drivers/char/tpm/tpm-buf.c @@ -3,86 +3,114 @@ * Handling of TPM command and other buffers. */ -#include <linux/tpm_command.h> #include <linux/module.h> -#include <linux/tpm.h> +#include <linux/tpm_command.h> +#include <linux/tpm_buf.h> -/** - * tpm_buf_init() - Allocate and initialize a TPM command - * @buf: A &tpm_buf - * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS - * @ordinal: A command ordinal - * - * Return: 0 or -ENOMEM - */ -int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal) +static void __tpm_buf_size_invariant(struct tpm_buf *buf, u16 buf_size) { - buf->data = (u8 *)__get_free_page(GFP_KERNEL); - if (!buf->data) - return -ENOMEM; - - tpm_buf_reset(buf, tag, ordinal); - return 0; + u32 buf_size_2 = (u32)buf->capacity + (u32)sizeof(*buf); + + if (!buf->capacity) { + if (buf_size > TPM_BUFSIZE) { + WARN(1, "%s: size overflow: %u\n", __func__, buf_size); + buf->flags |= TPM_BUF_INVALID; + } + } else { + if (buf_size != buf_size_2) { + WARN(1, "%s: size mismatch: %u != %u\n", __func__, + buf_size, buf_size_2); + buf->flags |= TPM_BUF_INVALID; + } + } } -EXPORT_SYMBOL_GPL(tpm_buf_init); -/** - * tpm_buf_reset() - Initialize a TPM command - * @buf: A &tpm_buf - * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS - * @ordinal: A command ordinal - */ -void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) +static void __tpm_buf_reset(struct tpm_buf *buf, u16 buf_size, u16 tag, + u32 ordinal) { struct tpm_header *head = (struct tpm_header *)buf->data; + __tpm_buf_size_invariant(buf, buf_size); + + if (buf->flags & TPM_BUF_INVALID) + return; + WARN_ON(tag != TPM_TAG_RQU_COMMAND && tag != TPM2_ST_NO_SESSIONS && tag != TPM2_ST_SESSIONS && tag != 0); buf->flags = 0; buf->length = sizeof(*head); + buf->capacity = buf_size - sizeof(*buf); + buf->handles = 0; head->tag = cpu_to_be16(tag); head->length = cpu_to_be32(sizeof(*head)); head->ordinal = cpu_to_be32(ordinal); +} + +static void __tpm_buf_reset_sized(struct tpm_buf *buf, u16 buf_size) +{ + __tpm_buf_size_invariant(buf, buf_size); + + if (buf->flags & TPM_BUF_INVALID) + return; + + buf->flags = TPM_BUF_TPM2B; + buf->length = 2; + buf->capacity = buf_size - sizeof(*buf); buf->handles = 0; + buf->data[0] = 0; + buf->data[1] = 0; } -EXPORT_SYMBOL_GPL(tpm_buf_reset); /** - * tpm_buf_init_sized() - Allocate and initialize a sized (TPM2B) buffer - * @buf: A @tpm_buf - * - * Return: 0 or -ENOMEM + * tpm_buf_init() - Initialize a TPM command + * @buf: A &tpm_buf + * @buf_size: Size of the buffer. */ -int tpm_buf_init_sized(struct tpm_buf *buf) +void tpm_buf_init(struct tpm_buf *buf, u16 buf_size) { - buf->data = (u8 *)__get_free_page(GFP_KERNEL); - if (!buf->data) - return -ENOMEM; + memset(buf, 0, buf_size); + __tpm_buf_reset(buf, buf_size, TPM_TAG_RQU_COMMAND, 0); +} +EXPORT_SYMBOL_GPL(tpm_buf_init); - tpm_buf_reset_sized(buf); - return 0; +/** + * tpm_buf_init_sized() - Initialize a sized buffer + * @buf: A &tpm_buf + * @buf_size: Size of the buffer. + */ +void tpm_buf_init_sized(struct tpm_buf *buf, u16 buf_size) +{ + memset(buf, 0, buf_size); + __tpm_buf_reset_sized(buf, buf_size); } EXPORT_SYMBOL_GPL(tpm_buf_init_sized); /** - * tpm_buf_reset_sized() - Initialize a sized buffer + * tpm_buf_reset() - Re-initialize a TPM command * @buf: A &tpm_buf + * @tag: TPM_TAG_RQU_COMMAND, TPM2_ST_NO_SESSIONS or TPM2_ST_SESSIONS + * @ordinal: A command ordinal */ -void tpm_buf_reset_sized(struct tpm_buf *buf) +void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal) { - buf->flags = TPM_BUF_TPM2B; - buf->length = 2; - buf->data[0] = 0; - buf->data[1] = 0; + u16 buf_size = buf->capacity + sizeof(*buf); + + __tpm_buf_reset(buf, buf_size, tag, ordinal); } -EXPORT_SYMBOL_GPL(tpm_buf_reset_sized); +EXPORT_SYMBOL_GPL(tpm_buf_reset); -void tpm_buf_destroy(struct tpm_buf *buf) +/** + * tpm_buf_reset_sized() - Re-initialize a sized buffer + * @buf: A &tpm_buf + */ +void tpm_buf_reset_sized(struct tpm_buf *buf) { - free_page((unsigned long)buf->data); + u16 buf_size = buf->capacity + sizeof(*buf); + + __tpm_buf_reset_sized(buf, buf_size); } -EXPORT_SYMBOL_GPL(tpm_buf_destroy); +EXPORT_SYMBOL_GPL(tpm_buf_reset_sized); /** * tpm_buf_length() - Return the number of bytes consumed by the data @@ -90,7 +118,7 @@ EXPORT_SYMBOL_GPL(tpm_buf_destroy); * * Return: The number of bytes consumed by the buffer */ -u32 tpm_buf_length(struct tpm_buf *buf) +u16 tpm_buf_length(struct tpm_buf *buf) { return buf->length; } @@ -104,13 +132,14 @@ EXPORT_SYMBOL_GPL(tpm_buf_length); */ void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_length) { - /* Return silently if overflow has already happened. */ - if (buf->flags & TPM_BUF_OVERFLOW) + u32 total_length = (u32)buf->length + (u32)new_length; + + if (buf->flags & TPM_BUF_INVALID) return; - if ((buf->length + new_length) > PAGE_SIZE) { + if (total_length > (u32)buf->capacity) { WARN(1, "tpm_buf: write overflow\n"); - buf->flags |= TPM_BUF_OVERFLOW; + buf->flags |= TPM_BUF_INVALID; return; } @@ -148,17 +177,20 @@ EXPORT_SYMBOL_GPL(tpm_buf_append_u32); /** * tpm_buf_append_handle() - Add a handle - * @chip: &tpm_chip instance * @buf: &tpm_buf instance * @handle: a TPM object handle * * Add a handle to the buffer, and increase the count tracking the number of * handles in the command buffer. Works only for command buffers. */ -void tpm_buf_append_handle(struct tpm_chip *chip, struct tpm_buf *buf, u32 handle) +void tpm_buf_append_handle(struct tpm_buf *buf, u32 handle) { + if (buf->flags & TPM_BUF_INVALID) + return; + if (buf->flags & TPM_BUF_TPM2B) { - dev_err(&chip->dev, "Invalid buffer type (TPM2B)\n"); + WARN(1, "tpm-buf: invalid type: TPM2B\n"); + buf->flags |= TPM_BUF_INVALID; return; } @@ -177,14 +209,13 @@ static void tpm_buf_read(struct tpm_buf *buf, off_t *offset, size_t count, void { off_t next_offset; - /* Return silently if overflow has already happened. */ - if (buf->flags & TPM_BUF_BOUNDARY_ERROR) + if (buf->flags & TPM_BUF_INVALID) return; next_offset = *offset + count; if (next_offset > buf->length) { WARN(1, "tpm_buf: read out of boundary\n"); - buf->flags |= TPM_BUF_BOUNDARY_ERROR; + buf->flags |= TPM_BUF_INVALID; return; } diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index 94231f052ea7..d915307ae833 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -32,28 +32,35 @@ struct tpm_readpubek_out { static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, char *buf) { - struct tpm_buf tpm_buf; struct tpm_readpubek_out *out; int i; char *str = buf; struct tpm_chip *chip = to_tpm_chip(dev); char anti_replay[20]; + struct tpm_buf *tpm_buf __free(kfree) = NULL; memset(&anti_replay, 0, sizeof(anti_replay)); if (tpm_try_get_ops(chip)) return 0; - if (tpm_buf_init(&tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK)) - goto out_ops; + tpm_buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!tpm_buf) { + tpm_put_ops(chip); + return 0; + } - tpm_buf_append(&tpm_buf, anti_replay, sizeof(anti_replay)); + tpm_buf_init(tpm_buf, TPM_BUFSIZE); + tpm_buf_reset(tpm_buf, TPM_TAG_RQU_COMMAND, TPM_ORD_READPUBEK); + tpm_buf_append(tpm_buf, anti_replay, sizeof(anti_replay)); - if (tpm_transmit_cmd(chip, &tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE, - "attempting to read the PUBEK")) - goto out_buf; + if (tpm_transmit_cmd(chip, tpm_buf, READ_PUBEK_RESULT_MIN_BODY_SIZE, + "attempting to read the PUBEK")) { + tpm_put_ops(chip); + return 0; + } - out = (struct tpm_readpubek_out *)&tpm_buf.data[10]; + out = (struct tpm_readpubek_out *)&tpm_buf->data[10]; str += sprintf(str, "Algorithm: %4ph\n" @@ -71,9 +78,6 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, for (i = 0; i < 256; i += 16) str += sprintf(str, "%16ph\n", &out->modulus[i]); -out_buf: - tpm_buf_destroy(&tpm_buf); -out_ops: tpm_put_ops(chip); return str - buf; } diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 87d68ddf270a..fa554c5ad80b 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -33,7 +33,6 @@ #endif #define TPM_MINOR 224 /* officially assigned */ -#define TPM_BUFSIZE 4096 #define TPM_NUM_DEVICES 65536 #define TPM_RETRY 50 @@ -52,185 +51,6 @@ enum tpm_addr { TPM_ADDR = 0x4E, }; -#define TPM_WARN_RETRY 0x800 -#define TPM_WARN_DOING_SELFTEST 0x802 -#define TPM_ERR_DEACTIVATED 0x6 -#define TPM_ERR_DISABLED 0x7 -#define TPM_ERR_FAILEDSELFTEST 0x1C -#define TPM_ERR_INVALID_POSTINIT 38 - -#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; - u8 disableForceClear; - u8 physicalPresence; - u8 physicalPresenceLock; - u8 bGlobalLock; -} __packed; - -struct tpm1_version { - u8 major; - u8 minor; - u8 rev_major; - u8 rev_minor; -} __packed; - -struct tpm1_version2 { - __be16 tag; - struct tpm1_version version; -} __packed; - -struct timeout_t { - __be32 a; - __be32 b; - __be32 c; - __be32 d; -} __packed; - -struct duration_t { - __be32 tpm_short; - __be32 tpm_medium; - __be32 tpm_long; -} __packed; - -struct permanent_flags_t { - __be16 tag; - u8 disable; - u8 ownership; - u8 deactivated; - u8 readPubek; - u8 disableOwnerClear; - u8 allowMaintenance; - u8 physicalPresenceLifetimeLock; - u8 physicalPresenceHWEnable; - u8 physicalPresenceCMDEnable; - u8 CEKPUsed; - u8 TPMpost; - u8 TPMpostLock; - u8 FIPS; - u8 operator; - u8 enableRevokeEK; - u8 nvLocked; - u8 readSRKPub; - u8 tpmEstablished; - u8 maintenanceDone; - u8 disableFullDALogicInfo; -} __packed; - -typedef union { - struct permanent_flags_t perm_flags; - struct stclear_flags_t stclear_flags; - __u8 owned; - __be32 num_pcrs; - struct tpm1_version version1; - struct tpm1_version2 version2; - __be32 manufacturer_id; - struct timeout_t timeout; - struct duration_t duration; -} cap_t; - -enum tpm_capabilities { - TPM_CAP_FLAG = 4, - TPM_CAP_PROP = 5, - TPM_CAP_VERSION_1_1 = 0x06, - TPM_CAP_VERSION_1_2 = 0x1A, -}; - -enum tpm_sub_capabilities { - TPM_CAP_PROP_PCR = 0x101, - TPM_CAP_PROP_MANUFACTURER = 0x103, - TPM_CAP_FLAG_PERM = 0x108, - TPM_CAP_FLAG_VOL = 0x109, - TPM_CAP_PROP_OWNER = 0x111, - TPM_CAP_PROP_TIS_TIMEOUT = 0x115, - TPM_CAP_PROP_TIS_DURATION = 0x120, -}; - -enum tpm2_pt_props { - TPM2_PT_NONE = 0x00000000, - TPM2_PT_GROUP = 0x00000100, - TPM2_PT_FIXED = TPM2_PT_GROUP * 1, - TPM2_PT_FAMILY_INDICATOR = TPM2_PT_FIXED + 0, - TPM2_PT_LEVEL = TPM2_PT_FIXED + 1, - TPM2_PT_REVISION = TPM2_PT_FIXED + 2, - TPM2_PT_DAY_OF_YEAR = TPM2_PT_FIXED + 3, - TPM2_PT_YEAR = TPM2_PT_FIXED + 4, - TPM2_PT_MANUFACTURER = TPM2_PT_FIXED + 5, - TPM2_PT_VENDOR_STRING_1 = TPM2_PT_FIXED + 6, - TPM2_PT_VENDOR_STRING_2 = TPM2_PT_FIXED + 7, - TPM2_PT_VENDOR_STRING_3 = TPM2_PT_FIXED + 8, - TPM2_PT_VENDOR_STRING_4 = TPM2_PT_FIXED + 9, - TPM2_PT_VENDOR_TPM_TYPE = TPM2_PT_FIXED + 10, - TPM2_PT_FIRMWARE_VERSION_1 = TPM2_PT_FIXED + 11, - TPM2_PT_FIRMWARE_VERSION_2 = TPM2_PT_FIXED + 12, - TPM2_PT_INPUT_BUFFER = TPM2_PT_FIXED + 13, - TPM2_PT_HR_TRANSIENT_MIN = TPM2_PT_FIXED + 14, - TPM2_PT_HR_PERSISTENT_MIN = TPM2_PT_FIXED + 15, - TPM2_PT_HR_LOADED_MIN = TPM2_PT_FIXED + 16, - TPM2_PT_ACTIVE_SESSIONS_MAX = TPM2_PT_FIXED + 17, - TPM2_PT_PCR_COUNT = TPM2_PT_FIXED + 18, - TPM2_PT_PCR_SELECT_MIN = TPM2_PT_FIXED + 19, - TPM2_PT_CONTEXT_GAP_MAX = TPM2_PT_FIXED + 20, - TPM2_PT_NV_COUNTERS_MAX = TPM2_PT_FIXED + 22, - TPM2_PT_NV_INDEX_MAX = TPM2_PT_FIXED + 23, - TPM2_PT_MEMORY = TPM2_PT_FIXED + 24, - TPM2_PT_CLOCK_UPDATE = TPM2_PT_FIXED + 25, - TPM2_PT_CONTEXT_HASH = TPM2_PT_FIXED + 26, - TPM2_PT_CONTEXT_SYM = TPM2_PT_FIXED + 27, - TPM2_PT_CONTEXT_SYM_SIZE = TPM2_PT_FIXED + 28, - TPM2_PT_ORDERLY_COUNT = TPM2_PT_FIXED + 29, - TPM2_PT_MAX_COMMAND_SIZE = TPM2_PT_FIXED + 30, - TPM2_PT_MAX_RESPONSE_SIZE = TPM2_PT_FIXED + 31, - TPM2_PT_MAX_DIGEST = TPM2_PT_FIXED + 32, - TPM2_PT_MAX_OBJECT_CONTEXT = TPM2_PT_FIXED + 33, - TPM2_PT_MAX_SESSION_CONTEXT = TPM2_PT_FIXED + 34, - TPM2_PT_PS_FAMILY_INDICATOR = TPM2_PT_FIXED + 35, - TPM2_PT_PS_LEVEL = TPM2_PT_FIXED + 36, - TPM2_PT_PS_REVISION = TPM2_PT_FIXED + 37, - TPM2_PT_PS_DAY_OF_YEAR = TPM2_PT_FIXED + 38, - TPM2_PT_PS_YEAR = TPM2_PT_FIXED + 39, - TPM2_PT_SPLIT_MAX = TPM2_PT_FIXED + 40, - TPM2_PT_TOTAL_COMMANDS = TPM2_PT_FIXED + 41, - TPM2_PT_LIBRARY_COMMANDS = TPM2_PT_FIXED + 42, - TPM2_PT_VENDOR_COMMANDS = TPM2_PT_FIXED + 43, - TPM2_PT_NV_BUFFER_MAX = TPM2_PT_FIXED + 44, - TPM2_PT_MODES = TPM2_PT_FIXED + 45, - TPM2_PT_MAX_CAP_BUFFER = TPM2_PT_FIXED + 46, - TPM2_PT_VAR = TPM2_PT_GROUP * 2, - TPM2_PT_PERMANENT = TPM2_PT_VAR + 0, - TPM2_PT_STARTUP_CLEAR = TPM2_PT_VAR + 1, - TPM2_PT_HR_NV_INDEX = TPM2_PT_VAR + 2, - TPM2_PT_HR_LOADED = TPM2_PT_VAR + 3, - TPM2_PT_HR_LOADED_AVAIL = TPM2_PT_VAR + 4, - TPM2_PT_HR_ACTIVE = TPM2_PT_VAR + 5, - TPM2_PT_HR_ACTIVE_AVAIL = TPM2_PT_VAR + 6, - TPM2_PT_HR_TRANSIENT_AVAIL = TPM2_PT_VAR + 7, - TPM2_PT_HR_PERSISTENT = TPM2_PT_VAR + 8, - TPM2_PT_HR_PERSISTENT_AVAIL = TPM2_PT_VAR + 9, - TPM2_PT_NV_COUNTERS = TPM2_PT_VAR + 10, - TPM2_PT_NV_COUNTERS_AVAIL = TPM2_PT_VAR + 11, - TPM2_PT_ALGORITHM_SET = TPM2_PT_VAR + 12, - TPM2_PT_LOADED_CURVES = TPM2_PT_VAR + 13, - TPM2_PT_LOCKOUT_COUNTER = TPM2_PT_VAR + 14, - TPM2_PT_MAX_AUTH_FAIL = TPM2_PT_VAR + 15, - TPM2_PT_LOCKOUT_INTERVAL = TPM2_PT_VAR + 16, - TPM2_PT_LOCKOUT_RECOVERY = TPM2_PT_VAR + 17, - TPM2_PT_NV_WRITE_RECOVERY = TPM2_PT_VAR + 18, - TPM2_PT_AUDIT_COUNTER_0 = TPM2_PT_VAR + 19, - TPM2_PT_AUDIT_COUNTER_1 = TPM2_PT_VAR + 20, -}; - -/* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 - * bytes, but 128 is still a relatively large number of random bytes and - * anything much bigger causes users of struct tpm_cmd_t to start getting - * compiler warnings about stack frame size. */ -#define TPM_MAX_RNG_DATA 128 - extern const struct class tpm_class; extern const struct class tpmrm_class; extern dev_t tpm_devt; diff --git a/drivers/char/tpm/tpm1-cmd.c b/drivers/char/tpm/tpm1-cmd.c index b49a790f1bd5..7a8606e8c711 100644 --- a/drivers/char/tpm/tpm1-cmd.c +++ b/drivers/char/tpm/tpm1-cmd.c @@ -22,8 +22,6 @@ #include "tpm.h" -#define TPM_MAX_ORDINAL 243 - /* * Array with one entry per ordinal defining the maximum amount * of time the chip could take to return the result. The ordinal @@ -308,9 +306,6 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) return duration; } -#define TPM_ORD_STARTUP 153 -#define TPM_ST_CLEAR 1 - /** * tpm1_startup() - turn on the TPM * @chip: TPM chip to use @@ -323,20 +318,18 @@ unsigned long tpm1_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal) */ static int tpm1_startup(struct tpm_chip *chip) { - struct tpm_buf buf; - int rc; + struct tpm_buf *buf __free(kfree) = NULL; dev_info(&chip->dev, "starting up the TPM manually\n"); - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); - if (rc < 0) - return rc; - - tpm_buf_append_u16(&buf, TPM_ST_CLEAR); + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM"); - tpm_buf_destroy(&buf); - return rc; + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_STARTUP); + tpm_buf_append_u16(buf, TPM_ST_CLEAR); + return tpm_transmit_cmd(chip, buf, 0, "attempting to start the TPM"); } int tpm1_get_timeouts(struct tpm_chip *chip) @@ -459,64 +452,56 @@ int tpm1_get_timeouts(struct tpm_chip *chip) return 0; } -#define TPM_ORD_PCR_EXTEND 20 int tpm1_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, const u8 *hash, const char *log_msg) { - struct tpm_buf buf; - int rc; + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); - if (rc) - return rc; + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_EXTEND); + tpm_buf_append_u32(buf, pcr_idx); + tpm_buf_append(buf, hash, TPM_DIGEST_SIZE); - tpm_buf_append_u32(&buf, pcr_idx); - tpm_buf_append(&buf, hash, TPM_DIGEST_SIZE); - - rc = tpm_transmit_cmd(chip, &buf, TPM_DIGEST_SIZE, log_msg); - tpm_buf_destroy(&buf); - return rc; + return tpm_transmit_cmd(chip, buf, TPM_DIGEST_SIZE, log_msg); } -#define TPM_ORD_GET_CAP 101 ssize_t tpm1_getcap(struct tpm_chip *chip, u32 subcap_id, cap_t *cap, const char *desc, size_t min_cap_length) { - struct tpm_buf buf; int rc; - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_CAP); if (subcap_id == TPM_CAP_VERSION_1_1 || subcap_id == TPM_CAP_VERSION_1_2) { - tpm_buf_append_u32(&buf, subcap_id); - tpm_buf_append_u32(&buf, 0); + tpm_buf_append_u32(buf, subcap_id); + tpm_buf_append_u32(buf, 0); } else { if (subcap_id == TPM_CAP_FLAG_PERM || subcap_id == TPM_CAP_FLAG_VOL) - tpm_buf_append_u32(&buf, TPM_CAP_FLAG); + tpm_buf_append_u32(buf, TPM_CAP_FLAG); else - tpm_buf_append_u32(&buf, TPM_CAP_PROP); + tpm_buf_append_u32(buf, TPM_CAP_PROP); - tpm_buf_append_u32(&buf, 4); - tpm_buf_append_u32(&buf, subcap_id); + tpm_buf_append_u32(buf, 4); + tpm_buf_append_u32(buf, subcap_id); } - rc = tpm_transmit_cmd(chip, &buf, min_cap_length, desc); + + rc = tpm_transmit_cmd(chip, buf, min_cap_length, desc); if (!rc) - *cap = *(cap_t *)&buf.data[TPM_HEADER_SIZE + 4]; - tpm_buf_destroy(&buf); + *cap = *(cap_t *)&buf->data[TPM_HEADER_SIZE + 4]; + return rc; } EXPORT_SYMBOL_GPL(tpm1_getcap); -#define TPM_ORD_GET_RANDOM 70 -struct tpm1_get_random_out { - __be32 rng_data_len; - u8 rng_data[TPM_MAX_RNG_DATA]; -} __packed; - /** * tpm1_get_random() - get random bytes from the TPM's RNG * @chip: a &struct tpm_chip instance @@ -530,86 +515,80 @@ struct tpm1_get_random_out { int tpm1_get_random(struct tpm_chip *chip, u8 *dest, size_t max) { struct tpm1_get_random_out *out; + struct tpm_buf *buf __free(kfree) = NULL; u32 num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA); - struct tpm_buf buf; u32 total = 0; int retries = 5; u32 recd; int rc; - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); - if (rc) - return rc; + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); do { - tpm_buf_append_u32(&buf, num_bytes); + tpm_buf_append_u32(buf, num_bytes); - rc = tpm_transmit_cmd(chip, &buf, sizeof(out->rng_data_len), + rc = tpm_transmit_cmd(chip, buf, sizeof(out->rng_data_len), "attempting get random"); if (rc) { if (rc > 0) rc = -EIO; - goto out; + return rc; } - out = (struct tpm1_get_random_out *)&buf.data[TPM_HEADER_SIZE]; + out = (struct tpm1_get_random_out *)&buf->data[TPM_HEADER_SIZE]; recd = be32_to_cpu(out->rng_data_len); - if (recd > num_bytes) { - rc = -EFAULT; - goto out; - } + if (recd > num_bytes) + return -EFAULT; + + if (tpm_buf_length(buf) < TPM_HEADER_SIZE + + sizeof(out->rng_data_len) + recd) + return -EFAULT; - if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + - sizeof(out->rng_data_len) + recd) { - rc = -EFAULT; - goto out; - } memcpy(dest, out->rng_data, recd); dest += recd; total += recd; num_bytes -= recd; - tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_GET_RANDOM); } while (retries-- && total < max); rc = total ? (int)total : -EIO; -out: - tpm_buf_destroy(&buf); + return rc; } -#define TPM_ORD_PCRREAD 21 int tpm1_pcr_read(struct tpm_chip *chip, u32 pcr_idx, u8 *res_buf) { - struct tpm_buf buf; int rc; - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCRREAD); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - tpm_buf_append_u32(&buf, pcr_idx); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_PCR_READ); + tpm_buf_append_u32(buf, pcr_idx); - rc = tpm_transmit_cmd(chip, &buf, TPM_DIGEST_SIZE, + rc = tpm_transmit_cmd(chip, buf, TPM_DIGEST_SIZE, "attempting to read a pcr value"); if (rc) - goto out; + return rc; - if (tpm_buf_length(&buf) < TPM_DIGEST_SIZE) { - rc = -EFAULT; - goto out; - } + if (tpm_buf_length(buf) < TPM_DIGEST_SIZE) + return -EFAULT; - memcpy(res_buf, &buf.data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE); + memcpy(res_buf, &buf->data[TPM_HEADER_SIZE], TPM_DIGEST_SIZE); -out: - tpm_buf_destroy(&buf); return rc; } -#define TPM_ORD_CONTINUE_SELFTEST 83 /** * tpm1_continue_selftest() - run TPM's selftest * @chip: TPM chip to use @@ -619,16 +598,13 @@ out: */ static int tpm1_continue_selftest(struct tpm_chip *chip) { - struct tpm_buf buf; - int rc; - - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - rc = tpm_transmit_cmd(chip, &buf, 0, "continue selftest"); - tpm_buf_destroy(&buf); - return rc; + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_CONTINUE_SELFTEST); + return tpm_transmit_cmd(chip, buf, 0, "continue selftest"); } /** @@ -726,8 +702,6 @@ out: return rc; } -#define TPM_ORD_SAVESTATE 152 - /** * tpm1_pm_suspend() - pm suspend handler * @chip: TPM chip to use. @@ -742,22 +716,24 @@ out: int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr) { u8 dummy_hash[TPM_DIGEST_SIZE] = { 0 }; - struct tpm_buf buf; unsigned int try; + struct tpm_buf *buf __free(kfree) = NULL; int rc; - /* for buggy tpm, flush pcrs with extend to selected dummy */ if (tpm_suspend_pcr) rc = tpm1_pcr_extend(chip, tpm_suspend_pcr, dummy_hash, "extending dummy pcr before suspend"); + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); - if (rc) - return rc; /* now do the actual savestate */ for (try = 0; try < TPM_RETRY; try++) { - rc = tpm_transmit_cmd(chip, &buf, 0, NULL); + rc = tpm_transmit_cmd(chip, buf, 0, NULL); /* * If the TPM indicates that it is too busy to respond to * this command then retry before giving up. It can take @@ -772,7 +748,7 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr) break; tpm_msleep(TPM_TIMEOUT_RETRY); - tpm_buf_reset(&buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SAVESTATE); } if (rc) @@ -782,8 +758,6 @@ int tpm1_pm_suspend(struct tpm_chip *chip, u32 tpm_suspend_pcr) dev_warn(&chip->dev, "TPM savestate took %dms\n", try * TPM_TIMEOUT_RETRY); - tpm_buf_destroy(&buf); - return rc; } diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 52ee350da867..48cec39995fe 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -94,17 +94,6 @@ unsigned long tpm2_calc_ordinal_duration(u32 ordinal) return msecs_to_jiffies(TPM2_DURATION_DEFAULT); } -struct tpm2_pcr_read_out { - __be32 update_cnt; - __be32 pcr_selects_cnt; - __be16 hash_alg; - u8 pcr_select_size; - u8 pcr_select[TPM2_PCR_SELECT_MIN]; - __be32 digests_cnt; - __be16 digest_size; - u8 digest[]; -} __packed; - /** * tpm2_pcr_read() - read a PCR value * @chip: TPM chip to use. @@ -119,12 +108,13 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, { int i; int rc; - struct tpm_buf buf; struct tpm2_pcr_read_out *out; u8 pcr_select[TPM2_PCR_SELECT_MIN] = {0}; u16 digest_size; u16 expected_digest_size = 0; + struct tpm_buf *buf __free(kfree) = NULL; + if (pcr_idx >= TPM2_PLATFORM_PCR) return -EINVAL; @@ -139,36 +129,35 @@ int tpm2_pcr_read(struct tpm_chip *chip, u32 pcr_idx, expected_digest_size = chip->allocated_banks[i].digest_size; } - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ); - if (rc) - return rc; + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_PCR_READ); pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); - tpm_buf_append_u32(&buf, 1); - tpm_buf_append_u16(&buf, digest->alg_id); - tpm_buf_append_u8(&buf, TPM2_PCR_SELECT_MIN); - tpm_buf_append(&buf, (const unsigned char *)pcr_select, + tpm_buf_append_u32(buf, 1); + tpm_buf_append_u16(buf, digest->alg_id); + tpm_buf_append_u8(buf, TPM2_PCR_SELECT_MIN); + tpm_buf_append(buf, (const unsigned char *)pcr_select, sizeof(pcr_select)); - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to read a pcr value"); + rc = tpm_transmit_cmd(chip, buf, 0, "attempting to read a pcr value"); if (rc) - goto out; + return rc; - out = (struct tpm2_pcr_read_out *)&buf.data[TPM_HEADER_SIZE]; + out = (struct tpm2_pcr_read_out *)&buf->data[TPM_HEADER_SIZE]; digest_size = be16_to_cpu(out->digest_size); if (digest_size > sizeof(digest->digest) || - (!digest_size_ptr && digest_size != expected_digest_size)) { - rc = -EINVAL; - goto out; - } + (!digest_size_ptr && digest_size != expected_digest_size)) + return -EINVAL; if (digest_size_ptr) *digest_size_ptr = digest_size; memcpy(digest->digest, out->digest, digest_size); -out: - tpm_buf_destroy(&buf); return rc; } @@ -184,7 +173,7 @@ out: int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, struct tpm_digest *digests) { - struct tpm_buf buf; + struct tpm_buf *buf __free(kfree) = NULL; int rc; int i; @@ -194,55 +183,49 @@ int tpm2_pcr_extend(struct tpm_chip *chip, u32 pcr_idx, return rc; } - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND); - if (rc) { + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { if (!disable_pcr_integrity) tpm2_end_auth_session(chip); - return rc; + return -ENOMEM; } + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_PCR_EXTEND); + if (!disable_pcr_integrity) { - rc = tpm_buf_append_name(chip, &buf, pcr_idx, NULL); + rc = tpm_buf_append_name(chip, buf, pcr_idx, NULL); if (rc) { - tpm_buf_destroy(&buf); + tpm2_end_auth_session(chip); return rc; } - tpm_buf_append_hmac_session(chip, &buf, 0, NULL, 0); + tpm_buf_append_hmac_session(chip, buf, 0, NULL, 0); } else { - tpm_buf_append_handle(chip, &buf, pcr_idx); - tpm_buf_append_auth(chip, &buf, NULL, 0); + tpm_buf_append_handle(buf, pcr_idx); + tpm_buf_append_auth(chip, buf, NULL, 0); } - tpm_buf_append_u32(&buf, chip->nr_allocated_banks); + tpm_buf_append_u32(buf, chip->nr_allocated_banks); for (i = 0; i < chip->nr_allocated_banks; i++) { - tpm_buf_append_u16(&buf, digests[i].alg_id); - tpm_buf_append(&buf, (const unsigned char *)&digests[i].digest, + tpm_buf_append_u16(buf, digests[i].alg_id); + tpm_buf_append(buf, (const unsigned char *)&digests[i].digest, chip->allocated_banks[i].digest_size); } if (!disable_pcr_integrity) { - rc = tpm_buf_fill_hmac_session(chip, &buf); - if (rc) { - tpm_buf_destroy(&buf); + rc = tpm_buf_fill_hmac_session(chip, buf); + if (rc) return rc; - } } - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting extend a PCR value"); + rc = tpm_transmit_cmd(chip, buf, 0, "attempting extend a PCR value"); if (!disable_pcr_integrity) - rc = tpm_buf_check_hmac_response(chip, &buf, rc); - - tpm_buf_destroy(&buf); + rc = tpm_buf_check_hmac_response(chip, buf, rc); return rc; } -struct tpm2_get_random_out { - __be16 size; - u8 buffer[TPM_MAX_RNG_DATA]; -} __packed; - /** * tpm2_get_random() - get random bytes from the TPM RNG * @@ -258,7 +241,6 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) { struct tpm2_get_random_out *out; struct tpm_header *head; - struct tpm_buf buf; u32 recd; u32 num_bytes = max; int err; @@ -267,6 +249,8 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) u8 *dest_ptr = dest; off_t offset; + struct tpm_buf *buf __free(kfree) = NULL; + if (!num_bytes || max > TPM_MAX_RNG_DATA) return -EINVAL; @@ -274,55 +258,58 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) if (err) return err; - err = tpm_buf_init(&buf, 0, 0); - if (err) { + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { tpm2_end_auth_session(chip); - return err; + return -ENOMEM; } + tpm_buf_init(buf, TPM_BUFSIZE); + do { - tpm_buf_reset(&buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_GET_RANDOM); if (tpm2_chip_auth(chip)) { - tpm_buf_append_hmac_session(chip, &buf, + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_ENCRYPT | TPM2_SA_CONTINUE_SESSION, NULL, 0); } else { - offset = buf.handles * 4 + TPM_HEADER_SIZE; - head = (struct tpm_header *)buf.data; - if (tpm_buf_length(&buf) == offset) + offset = buf->handles * 4 + TPM_HEADER_SIZE; + head = (struct tpm_header *)buf->data; + if (tpm_buf_length(buf) == offset) head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); } - tpm_buf_append_u16(&buf, num_bytes); - err = tpm_buf_fill_hmac_session(chip, &buf); + tpm_buf_append_u16(buf, num_bytes); + err = tpm_buf_fill_hmac_session(chip, buf); if (err) - goto out; + return err; - err = tpm_transmit_cmd(chip, &buf, + err = tpm_transmit_cmd(chip, buf, offsetof(struct tpm2_get_random_out, buffer), "attempting get random"); - err = tpm_buf_check_hmac_response(chip, &buf, err); + err = tpm_buf_check_hmac_response(chip, buf, err); if (err) { if (err > 0) err = -EIO; - goto out; + tpm2_end_auth_session(chip); + return err; } - head = (struct tpm_header *)buf.data; + head = (struct tpm_header *)buf->data; offset = TPM_HEADER_SIZE; /* Skip the parameter size field: */ if (be16_to_cpu(head->tag) == TPM2_ST_SESSIONS) offset += 4; - out = (struct tpm2_get_random_out *)&buf.data[offset]; + out = (struct tpm2_get_random_out *)&buf->data[offset]; recd = min_t(u32, be16_to_cpu(out->size), num_bytes); - if (tpm_buf_length(&buf) < + if (tpm_buf_length(buf) < TPM_HEADER_SIZE + offsetof(struct tpm2_get_random_out, buffer) + recd) { - err = -EFAULT; - goto out; + tpm2_end_auth_session(chip); + return -EFAULT; } memcpy(dest_ptr, out->buffer, recd); @@ -331,13 +318,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *dest, size_t max) num_bytes -= recd; } while (retries-- && total < max); - tpm_buf_destroy(&buf); - return total ? total : -EIO; -out: - tpm_buf_destroy(&buf); - tpm2_end_auth_session(chip); - return err; } /** @@ -347,31 +328,21 @@ out: */ void tpm2_flush_context(struct tpm_chip *chip, u32 handle) { - struct tpm_buf buf; - int rc; - - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); - if (rc) { + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { dev_warn(&chip->dev, "0x%08x was not flushed, out of memory\n", handle); return; } - tpm_buf_append_u32(&buf, handle); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_FLUSH_CONTEXT); + tpm_buf_append_u32(buf, handle); - tpm_transmit_cmd(chip, &buf, 0, "flushing context"); - tpm_buf_destroy(&buf); + tpm_transmit_cmd(chip, buf, 0, "flushing context"); } EXPORT_SYMBOL_GPL(tpm2_flush_context); -struct tpm2_get_cap_out { - u8 more_data; - __be32 subcap_id; - __be32 property_cnt; - __be32 property_id; - __be32 value; -} __packed; - /** * tpm2_get_tpm_pt() - get value of a TPM_CAP_TPM_PROPERTIES type property * @chip: a &tpm_chip instance @@ -387,19 +358,21 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, const char *desc) { struct tpm2_get_cap_out *out; - struct tpm_buf buf; int rc; - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); - if (rc) - return rc; - tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); - tpm_buf_append_u32(&buf, property_id); - tpm_buf_append_u32(&buf, 1); - rc = tpm_transmit_cmd(chip, &buf, 0, NULL); + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + tpm_buf_append_u32(buf, TPM2_CAP_TPM_PROPERTIES); + tpm_buf_append_u32(buf, property_id); + tpm_buf_append_u32(buf, 1); + rc = tpm_transmit_cmd(chip, buf, 0, NULL); if (!rc) { out = (struct tpm2_get_cap_out *) - &buf.data[TPM_HEADER_SIZE]; + &buf->data[TPM_HEADER_SIZE]; /* * To prevent failing boot up of some systems, Infineon TPM2.0 * returns SUCCESS on TPM2_Startup in field upgrade mode. Also @@ -411,7 +384,6 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, else rc = -ENODATA; } - tpm_buf_destroy(&buf); return rc; } EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt); @@ -428,15 +400,14 @@ EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt); */ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) { - struct tpm_buf buf; - int rc; - - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN); - if (rc) + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) return; - tpm_buf_append_u16(&buf, shutdown_type); - tpm_transmit_cmd(chip, &buf, 0, "stopping the TPM"); - tpm_buf_destroy(&buf); + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SHUTDOWN); + tpm_buf_append_u16(buf, shutdown_type); + tpm_transmit_cmd(chip, buf, 0, "stopping the TPM"); } /** @@ -454,20 +425,21 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) */ static int tpm2_do_selftest(struct tpm_chip *chip) { - struct tpm_buf buf; int full; int rc; for (full = 0; full < 2; full++) { - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) = NULL; - tpm_buf_append_u8(&buf, full); - rc = tpm_transmit_cmd(chip, &buf, 0, - "attempting the self test"); - tpm_buf_destroy(&buf); + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_SELF_TEST); + tpm_buf_append_u8(buf, full); + rc = tpm_transmit_cmd(chip, buf, 0, + "attempting the self test"); if (rc == TPM2_RC_TESTING) rc = TPM2_RC_SUCCESS; if (rc == TPM2_RC_INITIALIZE || rc == TPM2_RC_SUCCESS) @@ -492,23 +464,24 @@ static int tpm2_do_selftest(struct tpm_chip *chip) int tpm2_probe(struct tpm_chip *chip) { struct tpm_header *out; - struct tpm_buf buf; int rc; - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); - if (rc) - return rc; - tpm_buf_append_u32(&buf, TPM2_CAP_TPM_PROPERTIES); - tpm_buf_append_u32(&buf, TPM_PT_TOTAL_COMMANDS); - tpm_buf_append_u32(&buf, 1); - rc = tpm_transmit_cmd(chip, &buf, 0, NULL); + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + tpm_buf_append_u32(buf, TPM2_CAP_TPM_PROPERTIES); + tpm_buf_append_u32(buf, TPM_PT_TOTAL_COMMANDS); + tpm_buf_append_u32(buf, 1); + rc = tpm_transmit_cmd(chip, buf, 0, NULL); /* We ignore TPM return codes on purpose. */ if (rc >= 0) { - out = (struct tpm_header *)buf.data; + out = (struct tpm_header *)buf->data; if (be16_to_cpu(out->tag) == TPM2_ST_NO_SESSIONS) chip->flags |= TPM_CHIP_FLAG_TPM2; } - tpm_buf_destroy(&buf); return 0; } EXPORT_SYMBOL_GPL(tpm2_probe); @@ -539,16 +512,9 @@ static int tpm2_init_bank_info(struct tpm_chip *chip, u32 bank_index) return tpm2_pcr_read(chip, 0, &digest, &bank->digest_size); } -struct tpm2_pcr_selection { - __be16 hash_alg; - u8 size_of_select; - u8 pcr_select[3]; -} __packed; - ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) { struct tpm2_pcr_selection pcr_selection; - struct tpm_buf buf; void *marker; void *end; void *pcr_select_offset; @@ -560,31 +526,32 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) int rc; int i = 0; - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); - if (rc) - return rc; + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - tpm_buf_append_u32(&buf, TPM2_CAP_PCRS); - tpm_buf_append_u32(&buf, 0); - tpm_buf_append_u32(&buf, 1); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + tpm_buf_append_u32(buf, TPM2_CAP_PCRS); + tpm_buf_append_u32(buf, 0); + tpm_buf_append_u32(buf, 1); - rc = tpm_transmit_cmd(chip, &buf, 9, "get tpm pcr allocation"); + rc = tpm_transmit_cmd(chip, buf, 9, "get tpm pcr allocation"); if (rc) - goto out; + return rc; nr_possible_banks = be32_to_cpup( - (__be32 *)&buf.data[TPM_HEADER_SIZE + 5]); + (__be32 *)&buf->data[TPM_HEADER_SIZE + 5]); if (nr_possible_banks > TPM2_MAX_PCR_BANKS) { pr_err("tpm: out of bank capacity: %u > %u\n", nr_possible_banks, TPM2_MAX_PCR_BANKS); - rc = -ENOMEM; - goto out; + return -ENOMEM; } - marker = &buf.data[TPM_HEADER_SIZE + 9]; + marker = &buf->data[TPM_HEADER_SIZE + 9]; - rsp_len = be32_to_cpup((__be32 *)&buf.data[2]); - end = &buf.data[rsp_len]; + rsp_len = be32_to_cpup((__be32 *)&buf->data[2]); + end = &buf->data[rsp_len]; for (i = 0; i < nr_possible_banks; i++) { pcr_select_offset = marker + @@ -616,21 +583,20 @@ ssize_t tpm2_get_pcr_allocation(struct tpm_chip *chip) } chip->nr_allocated_banks = nr_alloc_banks; -out: - tpm_buf_destroy(&buf); return rc; } int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) { - struct tpm_buf buf; u32 nr_commands; __be32 *attrs; u32 cc; int i; int rc; + struct tpm_buf *buf __free(kfree) = NULL; + rc = tpm2_get_tpm_pt(chip, TPM_PT_TOTAL_COMMANDS, &nr_commands, NULL); if (rc) goto out; @@ -647,30 +613,31 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) goto out; } - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); - if (rc) + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { + rc = -ENOMEM; goto out; + } - tpm_buf_append_u32(&buf, TPM2_CAP_COMMANDS); - tpm_buf_append_u32(&buf, TPM2_CC_FIRST); - tpm_buf_append_u32(&buf, nr_commands); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_GET_CAPABILITY); + tpm_buf_append_u32(buf, TPM2_CAP_COMMANDS); + tpm_buf_append_u32(buf, TPM2_CC_FIRST); + tpm_buf_append_u32(buf, nr_commands); - rc = tpm_transmit_cmd(chip, &buf, 9 + 4 * nr_commands, NULL); - if (rc) { - tpm_buf_destroy(&buf); + rc = tpm_transmit_cmd(chip, buf, 9 + 4 * nr_commands, NULL); + if (rc) goto out; - } if (nr_commands != - be32_to_cpup((__be32 *)&buf.data[TPM_HEADER_SIZE + 5])) { + be32_to_cpup((__be32 *)&buf->data[TPM_HEADER_SIZE + 5])) { rc = -EFAULT; - tpm_buf_destroy(&buf); goto out; } chip->nr_commands = nr_commands; - attrs = (__be32 *)&buf.data[TPM_HEADER_SIZE + 9]; + attrs = (__be32 *)&buf->data[TPM_HEADER_SIZE + 9]; for (i = 0; i < nr_commands; i++, attrs++) { chip->cc_attrs_tbl[i] = be32_to_cpup(attrs); cc = chip->cc_attrs_tbl[i] & 0xFFFF; @@ -682,8 +649,6 @@ int tpm2_get_cc_attrs_tbl(struct tpm_chip *chip) } } - tpm_buf_destroy(&buf); - out: if (rc > 0) rc = -ENODEV; @@ -704,20 +669,18 @@ EXPORT_SYMBOL_GPL(tpm2_get_cc_attrs_tbl); static int tpm2_startup(struct tpm_chip *chip) { - struct tpm_buf buf; - int rc; + struct tpm_buf *buf __free(kfree) = NULL; dev_info(&chip->dev, "starting up the TPM manually\n"); - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); - if (rc < 0) - return rc; - - tpm_buf_append_u16(&buf, TPM2_SU_CLEAR); - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to start the TPM"); - tpm_buf_destroy(&buf); + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - return rc; + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_STARTUP); + tpm_buf_append_u16(buf, TPM2_SU_CLEAR); + return tpm_transmit_cmd(chip, buf, 0, "attempting to start the TPM"); } /** diff --git a/drivers/char/tpm/tpm2-sessions.c b/drivers/char/tpm/tpm2-sessions.c index a1ae5e1829cb..cf8f1fd6790b 100644 --- a/drivers/char/tpm/tpm2-sessions.c +++ b/drivers/char/tpm/tpm2-sessions.c @@ -167,8 +167,8 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) { u32 mso = tpm2_handle_mso(handle); off_t offset = TPM_HEADER_SIZE; + struct tpm_buf *buf __free(kfree) = NULL; int rc, name_size_alg; - struct tpm_buf buf; if (mso != TPM2_MSO_PERSISTENT && mso != TPM2_MSO_VOLATILE && mso != TPM2_MSO_NVRAM) { @@ -176,50 +176,40 @@ static int tpm2_read_public(struct tpm_chip *chip, u32 handle, void *name) return sizeof(u32); } - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC); - if (rc) - return rc; + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - tpm_buf_append_u32(&buf, handle); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_READ_PUBLIC); + tpm_buf_append_u32(buf, handle); - rc = tpm_transmit_cmd(chip, &buf, 0, "TPM2_ReadPublic"); - if (rc) { - tpm_buf_destroy(&buf); + rc = tpm_transmit_cmd(chip, buf, 0, "TPM2_ReadPublic"); + if (rc) return tpm_ret_to_err(rc); - } /* Skip TPMT_PUBLIC: */ - offset += tpm_buf_read_u16(&buf, &offset); + offset += tpm_buf_read_u16(buf, &offset); /* * Ensure space for the length field of TPM2B_NAME and hashAlg field of * TPMT_HA (the extra four bytes). */ - if (offset + 4 > tpm_buf_length(&buf)) { - tpm_buf_destroy(&buf); + if (offset + 4 > tpm_buf_length(buf)) return -EIO; - } - rc = tpm_buf_read_u16(&buf, &offset); - name_size_alg = name_size(&buf.data[offset]); - - if (name_size_alg < 0) { - tpm_buf_destroy(&buf); + rc = tpm_buf_read_u16(buf, &offset); + name_size_alg = name_size(&buf->data[offset]); + if (name_size_alg < 0) return name_size_alg; - } - if (rc != name_size_alg) { - tpm_buf_destroy(&buf); + if (rc != name_size_alg) return -EIO; - } - if (offset + rc > tpm_buf_length(&buf)) { - tpm_buf_destroy(&buf); + if (offset + rc > tpm_buf_length(buf)) return -EIO; - } - memcpy(name, &buf.data[offset], rc); - tpm_buf_destroy(&buf); + memcpy(name, &buf->data[offset], rc); return name_size_alg; } #endif /* CONFIG_TCG_TPM2_HMAC */ @@ -260,7 +250,7 @@ int tpm_buf_append_name(struct tpm_chip *chip, struct tpm_buf *buf, #endif if (!tpm2_chip_auth(chip)) { - tpm_buf_append_handle(chip, buf, handle); + tpm_buf_append_handle(buf, handle); return 0; } @@ -1005,8 +995,8 @@ err: */ int tpm2_start_auth_session(struct tpm_chip *chip) { + struct tpm_buf *buf __free(kfree) = NULL; struct tpm2_auth *auth; - struct tpm_buf buf; u32 null_key; int rc; @@ -1020,58 +1010,61 @@ int tpm2_start_auth_session(struct tpm_chip *chip) return -ENOMEM; rc = tpm2_load_null(chip, &null_key); - if (rc) - goto out; + if (rc) { + kfree_sensitive(auth); + return rc; + } auth->session = TPM_HEADER_SIZE; - rc = tpm_buf_init(&buf, TPM2_ST_NO_SESSIONS, TPM2_CC_START_AUTH_SESS); - if (rc) - goto out; + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { + kfree_sensitive(auth); + return -ENOMEM; + } + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_NO_SESSIONS, TPM2_CC_START_AUTH_SESS); /* salt key handle */ - tpm_buf_append_u32(&buf, null_key); + tpm_buf_append_u32(buf, null_key); /* bind key handle */ - tpm_buf_append_u32(&buf, TPM2_RH_NULL); + tpm_buf_append_u32(buf, TPM2_RH_NULL); /* nonce caller */ get_random_bytes(auth->our_nonce, sizeof(auth->our_nonce)); - tpm_buf_append_u16(&buf, sizeof(auth->our_nonce)); - tpm_buf_append(&buf, auth->our_nonce, sizeof(auth->our_nonce)); + tpm_buf_append_u16(buf, sizeof(auth->our_nonce)); + tpm_buf_append(buf, auth->our_nonce, sizeof(auth->our_nonce)); /* append encrypted salt and squirrel away unencrypted in auth */ - rc = tpm_buf_append_salt(&buf, chip, auth); + rc = tpm_buf_append_salt(buf, chip, auth); if (rc) { tpm2_flush_context(chip, null_key); - tpm_buf_destroy(&buf); - goto out; + kfree_sensitive(auth); + return rc; } /* session type (HMAC, audit or policy) */ - tpm_buf_append_u8(&buf, TPM2_SE_HMAC); + tpm_buf_append_u8(buf, TPM2_SE_HMAC); /* symmetric encryption parameters */ /* symmetric algorithm */ - tpm_buf_append_u16(&buf, TPM_ALG_AES); + tpm_buf_append_u16(buf, TPM_ALG_AES); /* bits for symmetric algorithm */ - tpm_buf_append_u16(&buf, AES_KEY_BITS); + tpm_buf_append_u16(buf, AES_KEY_BITS); /* symmetric algorithm mode (must be CFB) */ - tpm_buf_append_u16(&buf, TPM_ALG_CFB); + tpm_buf_append_u16(buf, TPM_ALG_CFB); /* hash algorithm for session */ - tpm_buf_append_u16(&buf, TPM_ALG_SHA256); + tpm_buf_append_u16(buf, TPM_ALG_SHA256); - rc = tpm_ret_to_err(tpm_transmit_cmd(chip, &buf, 0, "StartAuthSession")); + rc = tpm_ret_to_err(tpm_transmit_cmd(chip, buf, 0, "StartAuthSession")); tpm2_flush_context(chip, null_key); if (rc == TPM2_RC_SUCCESS) - rc = tpm2_parse_start_auth_session(auth, &buf); - - tpm_buf_destroy(&buf); + rc = tpm2_parse_start_auth_session(auth, buf); if (rc == TPM2_RC_SUCCESS) { chip->auth = auth; return 0; } -out: kfree_sensitive(auth); return rc; } @@ -1285,19 +1278,21 @@ static int tpm2_parse_create_primary(struct tpm_chip *chip, struct tpm_buf *buf, static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy, u32 *handle, u8 *name) { + struct tpm_buf *template __free(kfree) = NULL; + struct tpm_buf *buf __free(kfree) = NULL; int rc; - struct tpm_buf buf; - struct tpm_buf template; - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_PRIMARY); - if (rc) - return rc; + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; - rc = tpm_buf_init_sized(&template); - if (rc) { - tpm_buf_destroy(&buf); - return rc; - } + template = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!template) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE_PRIMARY); + tpm_buf_init_sized(template, TPM_BUFSIZE); /* * create the template. Note: in order for userspace to @@ -1309,75 +1304,72 @@ static int tpm2_create_primary(struct tpm_chip *chip, u32 hierarchy, */ /* key type */ - tpm_buf_append_u16(&template, TPM_ALG_ECC); + tpm_buf_append_u16(template, TPM_ALG_ECC); /* name algorithm */ - tpm_buf_append_u16(&template, TPM_ALG_SHA256); + tpm_buf_append_u16(template, TPM_ALG_SHA256); /* object properties */ - tpm_buf_append_u32(&template, TPM2_OA_NULL_KEY); + tpm_buf_append_u32(template, TPM2_OA_NULL_KEY); /* sauth policy (empty) */ - tpm_buf_append_u16(&template, 0); + tpm_buf_append_u16(template, 0); /* BEGIN parameters: key specific; for ECC*/ /* symmetric algorithm */ - tpm_buf_append_u16(&template, TPM_ALG_AES); + tpm_buf_append_u16(template, TPM_ALG_AES); /* bits for symmetric algorithm */ - tpm_buf_append_u16(&template, AES_KEY_BITS); + tpm_buf_append_u16(template, AES_KEY_BITS); /* algorithm mode (must be CFB) */ - tpm_buf_append_u16(&template, TPM_ALG_CFB); + tpm_buf_append_u16(template, TPM_ALG_CFB); /* scheme (NULL means any scheme) */ - tpm_buf_append_u16(&template, TPM_ALG_NULL); + tpm_buf_append_u16(template, TPM_ALG_NULL); /* ECC Curve ID */ - tpm_buf_append_u16(&template, TPM2_ECC_NIST_P256); + tpm_buf_append_u16(template, TPM2_ECC_NIST_P256); /* KDF Scheme */ - tpm_buf_append_u16(&template, TPM_ALG_NULL); + tpm_buf_append_u16(template, TPM_ALG_NULL); /* unique: key specific; for ECC it is two zero size points */ - tpm_buf_append_u16(&template, 0); - tpm_buf_append_u16(&template, 0); + tpm_buf_append_u16(template, 0); + tpm_buf_append_u16(template, 0); /* END parameters */ /* primary handle */ - tpm_buf_append_u32(&buf, hierarchy); - tpm_buf_append_empty_auth(&buf, TPM2_RS_PW); + tpm_buf_append_u32(buf, hierarchy); + tpm_buf_append_empty_auth(buf, TPM2_RS_PW); /* sensitive create size is 4 for two empty buffers */ - tpm_buf_append_u16(&buf, 4); + tpm_buf_append_u16(buf, 4); /* sensitive create auth data (empty) */ - tpm_buf_append_u16(&buf, 0); + tpm_buf_append_u16(buf, 0); /* sensitive create sensitive data (empty) */ - tpm_buf_append_u16(&buf, 0); + tpm_buf_append_u16(buf, 0); /* the public template */ - tpm_buf_append(&buf, template.data, template.length); - tpm_buf_destroy(&template); + tpm_buf_append(buf, template->data, template->length); /* outside info (empty) */ - tpm_buf_append_u16(&buf, 0); + tpm_buf_append_u16(buf, 0); /* creation PCR (none) */ - tpm_buf_append_u32(&buf, 0); + tpm_buf_append_u32(buf, 0); - rc = tpm_transmit_cmd(chip, &buf, 0, + rc = tpm_transmit_cmd(chip, buf, 0, "attempting to create NULL primary"); if (rc == TPM2_RC_SUCCESS) - rc = tpm2_parse_create_primary(chip, &buf, handle, hierarchy, + rc = tpm2_parse_create_primary(chip, buf, handle, hierarchy, name); - tpm_buf_destroy(&buf); - return rc; } diff --git a/drivers/char/tpm/tpm2-space.c b/drivers/char/tpm/tpm2-space.c index 60354cd53b5c..5b0f233db898 100644 --- a/drivers/char/tpm/tpm2-space.c +++ b/drivers/char/tpm/tpm2-space.c @@ -15,19 +15,6 @@ #include <linux/unaligned.h> #include "tpm.h" -enum tpm2_handle_types { - TPM2_HT_HMAC_SESSION = 0x02000000, - TPM2_HT_POLICY_SESSION = 0x03000000, - TPM2_HT_TRANSIENT = 0x80000000, -}; - -struct tpm2_context { - __be64 sequence; - __be32 saved_handle; - __be32 hierarchy; - __be16 blob_size; -} __packed; - static void tpm2_flush_sessions(struct tpm_chip *chip, struct tpm_space *space) { int i; @@ -71,24 +58,25 @@ void tpm2_del_space(struct tpm_chip *chip, struct tpm_space *space) int tpm2_load_context(struct tpm_chip *chip, u8 *buf, unsigned int *offset, u32 *handle) { - struct tpm_buf tbuf; struct tpm2_context *ctx; unsigned int body_size; int rc; - rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD); - if (rc) - return rc; + struct tpm_buf *tbuf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; + + tpm_buf_init(tbuf, TPM_BUFSIZE); + tpm_buf_reset(tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_LOAD); ctx = (struct tpm2_context *)&buf[*offset]; body_size = sizeof(*ctx) + be16_to_cpu(ctx->blob_size); - tpm_buf_append(&tbuf, &buf[*offset], body_size); + tpm_buf_append(tbuf, &buf[*offset], body_size); - rc = tpm_transmit_cmd(chip, &tbuf, 4, NULL); + rc = tpm_transmit_cmd(chip, tbuf, 4, NULL); if (rc < 0) { dev_warn(&chip->dev, "%s: failed with a system error %d\n", __func__, rc); - tpm_buf_destroy(&tbuf); return -EFAULT; } else if (tpm2_rc_value(rc) == TPM2_RC_HANDLE || rc == TPM2_RC_REFERENCE_H0) { @@ -103,64 +91,55 @@ int tpm2_load_context(struct tpm_chip *chip, u8 *buf, * flushed outside the space */ *handle = 0; - tpm_buf_destroy(&tbuf); return -ENOENT; } else if (tpm2_rc_value(rc) == TPM2_RC_INTEGRITY) { - tpm_buf_destroy(&tbuf); return -EINVAL; } else if (rc > 0) { dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", __func__, rc); - tpm_buf_destroy(&tbuf); return -EFAULT; } - *handle = be32_to_cpup((__be32 *)&tbuf.data[TPM_HEADER_SIZE]); + *handle = be32_to_cpup((__be32 *)&tbuf->data[TPM_HEADER_SIZE]); *offset += body_size; - - tpm_buf_destroy(&tbuf); return 0; } int tpm2_save_context(struct tpm_chip *chip, u32 handle, u8 *buf, unsigned int buf_size, unsigned int *offset) { - struct tpm_buf tbuf; unsigned int body_size; int rc; - rc = tpm_buf_init(&tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE); - if (rc) - return rc; + struct tpm_buf *tbuf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!tbuf) + return -ENOMEM; - tpm_buf_append_u32(&tbuf, handle); + tpm_buf_init(tbuf, TPM_BUFSIZE); + tpm_buf_reset(tbuf, TPM2_ST_NO_SESSIONS, TPM2_CC_CONTEXT_SAVE); + tpm_buf_append_u32(tbuf, handle); - rc = tpm_transmit_cmd(chip, &tbuf, 0, NULL); + rc = tpm_transmit_cmd(chip, tbuf, 0, NULL); if (rc < 0) { dev_warn(&chip->dev, "%s: failed with a system error %d\n", __func__, rc); - tpm_buf_destroy(&tbuf); return -EFAULT; } else if (tpm2_rc_value(rc) == TPM2_RC_REFERENCE_H0) { - tpm_buf_destroy(&tbuf); return -ENOENT; } else if (rc) { dev_warn(&chip->dev, "%s: failed with a TPM error 0x%04X\n", __func__, rc); - tpm_buf_destroy(&tbuf); return -EFAULT; } - body_size = tpm_buf_length(&tbuf) - TPM_HEADER_SIZE; + body_size = tpm_buf_length(tbuf) - TPM_HEADER_SIZE; if ((*offset + body_size) > buf_size) { dev_warn(&chip->dev, "%s: out of backing storage\n", __func__); - tpm_buf_destroy(&tbuf); return -ENOMEM; } - memcpy(&buf[*offset], &tbuf.data[TPM_HEADER_SIZE], body_size); + memcpy(&buf[*offset], &tbuf->data[TPM_HEADER_SIZE], body_size); *offset += body_size; - tpm_buf_destroy(&tbuf); return 0; } diff --git a/drivers/char/tpm/tpm_i2c_nuvoton.c b/drivers/char/tpm/tpm_i2c_nuvoton.c index d44903b29929..c84afb29d548 100644 --- a/drivers/char/tpm/tpm_i2c_nuvoton.c +++ b/drivers/char/tpm/tpm_i2c_nuvoton.c @@ -182,8 +182,10 @@ static int i2c_nuvoton_wait_for_stat(struct tpm_chip *chip, u8 mask, u8 value, timeout); if (rc > 0) return 0; - /* At this point we know that the SINT pin is asserted, so we - * do not need to do i2c_nuvoton_check_status */ + + disable_irq(priv->irq); + if (rc < 0) + return rc; } else { unsigned long ten_msec, stop; bool status_valid; @@ -574,8 +576,6 @@ static int i2c_nuvoton_probe(struct i2c_client *client) dev_name(&chip->dev), chip); if (rc) { - dev_err(dev, "%s() Unable to request irq: %d for use\n", - __func__, priv->irq); priv->irq = 0; } else { chip->flags |= TPM_CHIP_FLAG_IRQ; diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index aa6d78898ef3..d737b3d67411 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h @@ -19,71 +19,9 @@ #ifndef __TPM_TIS_CORE_H__ #define __TPM_TIS_CORE_H__ +#include <linux/tpm_ptp.h> #include "tpm.h" -enum tis_access { - TPM_ACCESS_VALID = 0x80, - TPM_ACCESS_ACTIVE_LOCALITY = 0x20, - TPM_ACCESS_REQUEST_PENDING = 0x04, - TPM_ACCESS_REQUEST_USE = 0x02, -}; - -enum tis_status { - TPM_STS_VALID = 0x80, - TPM_STS_COMMAND_READY = 0x40, - TPM_STS_GO = 0x20, - TPM_STS_DATA_AVAIL = 0x10, - TPM_STS_DATA_EXPECT = 0x08, - TPM_STS_RESPONSE_RETRY = 0x02, - TPM_STS_READ_ZERO = 0x23, /* bits that must be zero on read */ -}; - -enum tis_int_flags { - TPM_GLOBAL_INT_ENABLE = 0x80000000, - TPM_INTF_BURST_COUNT_STATIC = 0x100, - TPM_INTF_CMD_READY_INT = 0x080, - TPM_INTF_INT_EDGE_FALLING = 0x040, - TPM_INTF_INT_EDGE_RISING = 0x020, - TPM_INTF_INT_LEVEL_LOW = 0x010, - TPM_INTF_INT_LEVEL_HIGH = 0x008, - TPM_INTF_LOCALITY_CHANGE_INT = 0x004, - TPM_INTF_STS_VALID_INT = 0x002, - TPM_INTF_DATA_AVAIL_INT = 0x001, -}; - -enum tis_defaults { - TIS_MEM_LEN = 0x5000, - TIS_SHORT_TIMEOUT = 750, /* ms */ - TIS_LONG_TIMEOUT = 4000, /* 4 secs */ - TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */ - TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */ -}; - -/* Some timeout values are needed before it is known whether the chip is - * TPM 1.0 or TPM 2.0. - */ -#define TIS_TIMEOUT_A_MAX max_t(int, TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A) -#define TIS_TIMEOUT_B_MAX max_t(int, TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B) -#define TIS_TIMEOUT_C_MAX max_t(int, TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C) -#define TIS_TIMEOUT_D_MAX max_t(int, TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D) - -#define TPM_ACCESS(l) (0x0000 | ((l) << 12)) -#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) -#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) -#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) -#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) -#define TPM_STS(l) (0x0018 | ((l) << 12)) -#define TPM_STS3(l) (0x001b | ((l) << 12)) -#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) - -#define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) -#define TPM_RID(l) (0x0F04 | ((l) << 12)) - -#define LPC_CNTRL_OFFSET 0x84 -#define LPC_CLKRUN_EN (1 << 2) -#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 -#define ILB_REMAP_SIZE 0x100 - enum tpm_tis_flags { TPM_TIS_ITPM_WORKAROUND = 0, TPM_TIS_INVALID_STATUS = 1, diff --git a/drivers/char/tpm/tpm_tis_i2c_cr50.c b/drivers/char/tpm/tpm_tis_i2c_cr50.c index b48cacacc066..7f828fae70d3 100644 --- a/drivers/char/tpm/tpm_tis_i2c_cr50.c +++ b/drivers/char/tpm/tpm_tis_i2c_cr50.c @@ -751,10 +751,8 @@ static int tpm_cr50_i2c_probe(struct i2c_client *client) rc = devm_request_irq(dev, client->irq, tpm_cr50_i2c_int_handler, IRQF_TRIGGER_FALLING | IRQF_NO_AUTOEN, dev->driver->name, chip); - if (rc < 0) { - dev_err(dev, "Failed to probe IRQ %d\n", client->irq); + if (rc < 0) return rc; - } priv->irq = client->irq; } else { diff --git a/drivers/char/tpm/tpm_tis_spi.h b/drivers/char/tpm/tpm_tis_spi.h index d0f66f6f1931..ced416ecd92c 100644 --- a/drivers/char/tpm/tpm_tis_spi.h +++ b/drivers/char/tpm/tpm_tis_spi.h @@ -40,8 +40,12 @@ static inline int cr50_spi_probe(struct spi_device *spi) } #endif -#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_TCG_TIS_SPI_CR50) -extern int tpm_tis_spi_resume(struct device *dev); +#if defined(CONFIG_PM_SLEEP) + #if defined(CONFIG_TCG_TIS_SPI_CR50) + extern int tpm_tis_spi_resume(struct device *dev); + #else + #define tpm_tis_spi_resume tpm_tis_resume + #endif #else #define tpm_tis_spi_resume NULL #endif diff --git a/drivers/char/tpm/tpm_vtpm_proxy.c b/drivers/char/tpm/tpm_vtpm_proxy.c index 7bb0f4d4a2ed..b81fd2a537df 100644 --- a/drivers/char/tpm/tpm_vtpm_proxy.c +++ b/drivers/char/tpm/tpm_vtpm_proxy.c @@ -395,40 +395,36 @@ static bool vtpm_proxy_tpm_req_canceled(struct tpm_chip *chip, u8 status) static int vtpm_proxy_request_locality(struct tpm_chip *chip, int locality) { - struct tpm_buf buf; int rc; const struct tpm_header *header; struct proxy_dev *proxy_dev = dev_get_drvdata(&chip->dev); + struct tpm_buf *buf __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) + return -ENOMEM; + + tpm_buf_init(buf, TPM_BUFSIZE); if (chip->flags & TPM_CHIP_FLAG_TPM2) - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, - TPM2_CC_SET_LOCALITY); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_SET_LOCALITY); else - rc = tpm_buf_init(&buf, TPM_TAG_RQU_COMMAND, - TPM_ORD_SET_LOCALITY); - if (rc) - return rc; - tpm_buf_append_u8(&buf, locality); + tpm_buf_reset(buf, TPM_TAG_RQU_COMMAND, TPM_ORD_SET_LOCALITY); + + tpm_buf_append_u8(buf, locality); proxy_dev->state |= STATE_DRIVER_COMMAND; - rc = tpm_transmit_cmd(chip, &buf, 0, "attempting to set locality"); + rc = tpm_transmit_cmd(chip, buf, 0, "attempting to set locality"); proxy_dev->state &= ~STATE_DRIVER_COMMAND; - if (rc < 0) { - locality = rc; - goto out; - } + if (rc < 0) + return rc; - header = (const struct tpm_header *)buf.data; + header = (const struct tpm_header *)buf->data; rc = be32_to_cpu(header->return_code); if (rc) locality = -1; -out: - tpm_buf_destroy(&buf); - return locality; } diff --git a/include/keys/trusted_tpm.h b/include/keys/trusted_tpm.h index 0fadc6a4f166..3a0fa3bc8454 100644 --- a/include/keys/trusted_tpm.h +++ b/include/keys/trusted_tpm.h @@ -3,7 +3,6 @@ #define __TRUSTED_TPM_H #include <keys/trusted-type.h> -#include <linux/tpm_command.h> extern struct trusted_key_ops trusted_key_tpm_ops; diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 202da079d500..0db277af45c3 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h @@ -25,10 +25,8 @@ #include <crypto/hash_info.h> #include <crypto/aes.h> -#define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ - -#define TPM2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE -#define TPM2_MAX_PCR_BANKS 8 +#include <linux/tpm_command.h> +#include <linux/tpm_buf.h> struct tpm_chip; struct trusted_key_payload; @@ -36,49 +34,6 @@ struct trusted_key_options; /* opaque structure, holds auth session parameters like the session key */ struct tpm2_auth; -enum tpm2_session_types { - TPM2_SE_HMAC = 0x00, - TPM2_SE_POLICY = 0x01, - TPM2_SE_TRIAL = 0x02, -}; - -/* if you add a new hash to this, increment TPM_MAX_HASHES below */ -enum tpm_algorithms { - TPM_ALG_ERROR = 0x0000, - TPM_ALG_SHA1 = 0x0004, - TPM_ALG_AES = 0x0006, - TPM_ALG_KEYEDHASH = 0x0008, - TPM_ALG_SHA256 = 0x000B, - TPM_ALG_SHA384 = 0x000C, - TPM_ALG_SHA512 = 0x000D, - TPM_ALG_NULL = 0x0010, - TPM_ALG_SM3_256 = 0x0012, - TPM_ALG_ECC = 0x0023, - TPM_ALG_CFB = 0x0043, -}; - -/* - * maximum number of hashing algorithms a TPM can have. This is - * basically a count of every hash in tpm_algorithms above - */ -#define TPM_MAX_HASHES 5 - -enum tpm2_curves { - TPM2_ECC_NONE = 0x0000, - TPM2_ECC_NIST_P256 = 0x0003, -}; - -struct tpm_digest { - u16 alg_id; - u8 digest[TPM2_MAX_DIGEST_SIZE]; -} __packed; - -struct tpm_bank_info { - u16 alg_id; - u16 digest_size; - u16 crypto_id; -}; - enum TPM_OPS_FLAGS { TPM_OPS_AUTO_STARTUP = BIT(0), }; @@ -136,7 +91,7 @@ struct tpm_chip_seqops { const struct seq_operations *seqops; }; -/* fixed define for the curve we use which is NIST_P256 */ +/* Fixed define for the curve we use which is NIST_P256 */ #define EC_PT_SZ 32 /* @@ -218,124 +173,11 @@ struct tpm_chip { #endif }; -#define TPM_HEADER_SIZE 10 - -enum tpm2_const { - TPM2_PLATFORM_PCR = 24, - TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), -}; - -enum tpm2_timeouts { - TPM2_TIMEOUT_A = 750, - TPM2_TIMEOUT_B = 4000, - TPM2_TIMEOUT_C = 200, - TPM2_TIMEOUT_D = 30, -}; - -enum tpm2_durations { - TPM2_DURATION_SHORT = 20, - TPM2_DURATION_LONG = 2000, - TPM2_DURATION_DEFAULT = 120000, -}; - -enum tpm2_structures { - TPM2_ST_NO_SESSIONS = 0x8001, - TPM2_ST_SESSIONS = 0x8002, - TPM2_ST_CREATION = 0x8021, -}; - -/* Indicates from what layer of the software stack the error comes from */ -#define TSS2_RC_LAYER_SHIFT 16 -#define TSS2_RESMGR_TPM_RC_LAYER (11 << TSS2_RC_LAYER_SHIFT) - -enum tpm2_return_codes { - TPM2_RC_SUCCESS = 0x0000, - TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ - TPM2_RC_HANDLE = 0x008B, - TPM2_RC_INTEGRITY = 0x009F, - TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ - TPM2_RC_FAILURE = 0x0101, - TPM2_RC_DISABLED = 0x0120, - TPM2_RC_UPGRADE = 0x012D, - TPM2_RC_COMMAND_CODE = 0x0143, - TPM2_RC_TESTING = 0x090A, /* RC_WARN */ - TPM2_RC_REFERENCE_H0 = 0x0910, - TPM2_RC_RETRY = 0x0922, - TPM2_RC_SESSION_MEMORY = 0x0903, -}; - -enum tpm2_command_codes { - TPM2_CC_FIRST = 0x011F, - TPM2_CC_HIERARCHY_CONTROL = 0x0121, - TPM2_CC_HIERARCHY_CHANGE_AUTH = 0x0129, - TPM2_CC_CREATE_PRIMARY = 0x0131, - TPM2_CC_SEQUENCE_COMPLETE = 0x013E, - TPM2_CC_SELF_TEST = 0x0143, - TPM2_CC_STARTUP = 0x0144, - TPM2_CC_SHUTDOWN = 0x0145, - TPM2_CC_NV_READ = 0x014E, - TPM2_CC_CREATE = 0x0153, - TPM2_CC_LOAD = 0x0157, - TPM2_CC_SEQUENCE_UPDATE = 0x015C, - TPM2_CC_UNSEAL = 0x015E, - TPM2_CC_CONTEXT_LOAD = 0x0161, - TPM2_CC_CONTEXT_SAVE = 0x0162, - TPM2_CC_FLUSH_CONTEXT = 0x0165, - TPM2_CC_READ_PUBLIC = 0x0173, - TPM2_CC_START_AUTH_SESS = 0x0176, - TPM2_CC_VERIFY_SIGNATURE = 0x0177, - TPM2_CC_GET_CAPABILITY = 0x017A, - TPM2_CC_GET_RANDOM = 0x017B, - TPM2_CC_PCR_READ = 0x017E, - TPM2_CC_PCR_EXTEND = 0x0182, - TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185, - TPM2_CC_HASH_SEQUENCE_START = 0x0186, - TPM2_CC_CREATE_LOADED = 0x0191, - TPM2_CC_LAST = 0x0193, /* Spec 1.36 */ -}; - -enum tpm2_permanent_handles { - TPM2_RH_NULL = 0x40000007, - TPM2_RS_PW = 0x40000009, -}; - -/* Most Significant Octet for key types */ -enum tpm2_mso_type { - TPM2_MSO_NVRAM = 0x01, - TPM2_MSO_SESSION = 0x02, - TPM2_MSO_POLICY = 0x03, - TPM2_MSO_PERMANENT = 0x40, - TPM2_MSO_VOLATILE = 0x80, - TPM2_MSO_PERSISTENT = 0x81, -}; - static inline enum tpm2_mso_type tpm2_handle_mso(u32 handle) { return handle >> 24; } -enum tpm2_capabilities { - TPM2_CAP_HANDLES = 1, - TPM2_CAP_COMMANDS = 2, - TPM2_CAP_PCRS = 5, - TPM2_CAP_TPM_PROPERTIES = 6, -}; - -enum tpm2_properties { - TPM_PT_TOTAL_COMMANDS = 0x0129, -}; - -enum tpm2_startup_types { - TPM2_SU_CLEAR = 0x0000, - TPM2_SU_STATE = 0x0001, -}; - -enum tpm2_cc_attrs { - TPM2_CC_ATTR_CHANDLES = 25, - TPM2_CC_ATTR_RHANDLE = 28, - TPM2_CC_ATTR_VENDOR = 29, -}; - #define TPM_VID_INTEL 0x8086 #define TPM_VID_WINBOND 0x1050 #define TPM_VID_STM 0x104A @@ -359,77 +201,11 @@ enum tpm_chip_flags { #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev) -struct tpm_header { - __be16 tag; - __be32 length; - union { - __be32 ordinal; - __be32 return_code; - }; -} __packed; - -enum tpm_buf_flags { - /* the capacity exceeded: */ - TPM_BUF_OVERFLOW = BIT(0), - /* TPM2B format: */ - TPM_BUF_TPM2B = BIT(1), - /* read out of boundary: */ - TPM_BUF_BOUNDARY_ERROR = BIT(2), -}; - -/* - * A string buffer type for constructing TPM commands. - */ -struct tpm_buf { - u32 flags; - u32 length; - u8 *data; - u8 handles; -}; - -enum tpm2_object_attributes { - TPM2_OA_FIXED_TPM = BIT(1), - TPM2_OA_ST_CLEAR = BIT(2), - TPM2_OA_FIXED_PARENT = BIT(4), - TPM2_OA_SENSITIVE_DATA_ORIGIN = BIT(5), - TPM2_OA_USER_WITH_AUTH = BIT(6), - TPM2_OA_ADMIN_WITH_POLICY = BIT(7), - TPM2_OA_NO_DA = BIT(10), - TPM2_OA_ENCRYPTED_DUPLICATION = BIT(11), - TPM2_OA_RESTRICTED = BIT(16), - TPM2_OA_DECRYPT = BIT(17), - TPM2_OA_SIGN = BIT(18), -}; - -enum tpm2_session_attributes { - TPM2_SA_CONTINUE_SESSION = BIT(0), - TPM2_SA_AUDIT_EXCLUSIVE = BIT(1), - TPM2_SA_AUDIT_RESET = BIT(3), - TPM2_SA_DECRYPT = BIT(5), - TPM2_SA_ENCRYPT = BIT(6), - TPM2_SA_AUDIT = BIT(7), -}; - struct tpm2_hash { unsigned int crypto_id; unsigned int tpm_id; }; -int tpm_buf_init(struct tpm_buf *buf, u16 tag, u32 ordinal); -void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal); -int tpm_buf_init_sized(struct tpm_buf *buf); -void tpm_buf_reset_sized(struct tpm_buf *buf); -void tpm_buf_destroy(struct tpm_buf *buf); -u32 tpm_buf_length(struct tpm_buf *buf); -void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_length); -void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value); -void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value); -void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value); -u8 tpm_buf_read_u8(struct tpm_buf *buf, off_t *offset); -u16 tpm_buf_read_u16(struct tpm_buf *buf, off_t *offset); -u32 tpm_buf_read_u32(struct tpm_buf *buf, off_t *offset); -void tpm_buf_append_handle(struct tpm_chip *chip, struct tpm_buf *buf, u32 handle); - /* * Check if TPM device is in the firmware upgrade mode. */ diff --git a/include/linux/tpm_buf.h b/include/linux/tpm_buf.h new file mode 100644 index 000000000000..f8c105d8b8bf --- /dev/null +++ b/include/linux/tpm_buf.h @@ -0,0 +1,60 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Following copyright information was take from the original file + * <include/linux/tpm.h> where the definitions were moved from: + * + * Copyright (C) 2004,2007,2008 IBM Corporation + * + * Authors: + * Leendert van Doorn <leendert@watson.ibm.com> + * Dave Safford <safford@watson.ibm.com> + * Reiner Sailer <sailer@watson.ibm.com> + * Kylene Hall <kjhall@us.ibm.com> + * Debora Velarde <dvelarde@us.ibm.com> + * + * Maintained by: <tpmdd_devel@lists.sourceforge.net> + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + */ + +#ifndef __LINUX_TPM_BUF_H__ +#define __LINUX_TPM_BUF_H__ + +#include <linux/types.h> +#include <linux/bits.h> + +enum tpm_buf_flags { + /* TPM2B format: */ + TPM_BUF_TPM2B = BIT(0), + /* The buffer is in invalid and unusable state: */ + TPM_BUF_INVALID = BIT(1), +}; + +/* + * A buffer for constructing and parsing TPM commands, responses and sized + * (TPM2B) buffers. + */ +struct tpm_buf { + u8 flags; + u8 handles; + u16 length; + u16 capacity; + u8 data[]; +}; + +void tpm_buf_init(struct tpm_buf *buf, u16 buf_size); +void tpm_buf_init_sized(struct tpm_buf *buf, u16 buf_size); +void tpm_buf_reset(struct tpm_buf *buf, u16 tag, u32 ordinal); +void tpm_buf_reset_sized(struct tpm_buf *buf); +u16 tpm_buf_length(struct tpm_buf *buf); +void tpm_buf_append(struct tpm_buf *buf, const u8 *new_data, u16 new_length); +void tpm_buf_append_u8(struct tpm_buf *buf, const u8 value); +void tpm_buf_append_u16(struct tpm_buf *buf, const u16 value); +void tpm_buf_append_u32(struct tpm_buf *buf, const u32 value); +u8 tpm_buf_read_u8(struct tpm_buf *buf, off_t *offset); +u16 tpm_buf_read_u16(struct tpm_buf *buf, off_t *offset); +u32 tpm_buf_read_u32(struct tpm_buf *buf, off_t *offset); +void tpm_buf_append_handle(struct tpm_buf *buf, u32 handle); + +#endif diff --git a/include/linux/tpm_command.h b/include/linux/tpm_command.h index f5c03e9c3913..fc446a1282e2 100644 --- a/include/linux/tpm_command.h +++ b/include/linux/tpm_command.h @@ -2,28 +2,520 @@ #ifndef __LINUX_TPM_COMMAND_H__ #define __LINUX_TPM_COMMAND_H__ +#include <crypto/sha2.h> + /* - * TPM Command constants from specifications at - * http://www.trustedcomputinggroup.org + * == TPM 1 Family Chips == + * + * TPM 1.2 Main Specification: + * https://trustedcomputinggroup.org/resource/tpm-main-specification/ */ +#define TPM_MAX_ORDINAL 243 + /* Command TAGS */ -#define TPM_TAG_RQU_COMMAND 193 -#define TPM_TAG_RQU_AUTH1_COMMAND 194 -#define TPM_TAG_RQU_AUTH2_COMMAND 195 -#define TPM_TAG_RSP_COMMAND 196 -#define TPM_TAG_RSP_AUTH1_COMMAND 197 -#define TPM_TAG_RSP_AUTH2_COMMAND 198 +enum tpm_command_tags { + TPM_TAG_RQU_COMMAND = 193, + TPM_TAG_RQU_AUTH1_COMMAND = 194, + TPM_TAG_RQU_AUTH2_COMMAND = 195, + TPM_TAG_RSP_COMMAND = 196, + TPM_TAG_RSP_AUTH1_COMMAND = 197, + TPM_TAG_RSP_AUTH2_COMMAND = 198, +}; /* Command Ordinals */ -#define TPM_ORD_GETRANDOM 70 -#define TPM_ORD_OSAP 11 -#define TPM_ORD_OIAP 10 -#define TPM_ORD_SEAL 23 -#define TPM_ORD_UNSEAL 24 +enum tpm_command_ordinals { + TPM_ORD_CONTINUE_SELFTEST = 83, + TPM_ORD_GET_CAP = 101, + TPM_ORD_GET_RANDOM = 70, + TPM_ORD_PCR_EXTEND = 20, + TPM_ORD_PCR_READ = 21, + TPM_ORD_OSAP = 11, + TPM_ORD_OIAP = 10, + TPM_ORD_SAVESTATE = 152, + TPM_ORD_SEAL = 23, + TPM_ORD_STARTUP = 153, + TPM_ORD_UNSEAL = 24, +}; + +enum tpm_capabilities { + TPM_CAP_FLAG = 4, + TPM_CAP_PROP = 5, + TPM_CAP_VERSION_1_1 = 0x06, + TPM_CAP_VERSION_1_2 = 0x1A, +}; + +enum tpm_sub_capabilities { + TPM_CAP_PROP_PCR = 0x101, + TPM_CAP_PROP_MANUFACTURER = 0x103, + TPM_CAP_FLAG_PERM = 0x108, + TPM_CAP_FLAG_VOL = 0x109, + TPM_CAP_PROP_OWNER = 0x111, + TPM_CAP_PROP_TIS_TIMEOUT = 0x115, + TPM_CAP_PROP_TIS_DURATION = 0x120, +}; + +/* Return Codes */ +enum tpm_return_codes { + TPM_BASE_MASK = 0, + TPM_NON_FATAL_MASK = 0x00000800, + TPM_SUCCESS = TPM_BASE_MASK + 0, + TPM_ERR_DEACTIVATED = TPM_BASE_MASK + 6, + TPM_ERR_DISABLED = TPM_BASE_MASK + 7, + TPM_ERR_FAIL = TPM_BASE_MASK + 9, + TPM_ERR_FAILEDSELFTEST = TPM_BASE_MASK + 28, + TPM_ERR_INVALID_POSTINIT = TPM_BASE_MASK + 38, + TPM_ERR_INVALID_FAMILY = TPM_BASE_MASK + 55, + TPM_WARN_RETRY = TPM_BASE_MASK + TPM_NON_FATAL_MASK + 0, + TPM_WARN_DOING_SELFTEST = TPM_BASE_MASK + TPM_NON_FATAL_MASK + 2, +}; + +struct stclear_flags_t { + __be16 tag; + u8 deactivated; + u8 disableForceClear; + u8 physicalPresence; + u8 physicalPresenceLock; + u8 bGlobalLock; +} __packed; + +struct tpm1_version { + u8 major; + u8 minor; + u8 rev_major; + u8 rev_minor; +} __packed; + +struct tpm1_version2 { + __be16 tag; + struct tpm1_version version; +} __packed; + +struct timeout_t { + __be32 a; + __be32 b; + __be32 c; + __be32 d; +} __packed; + +struct duration_t { + __be32 tpm_short; + __be32 tpm_medium; + __be32 tpm_long; +} __packed; + +struct permanent_flags_t { + __be16 tag; + u8 disable; + u8 ownership; + u8 deactivated; + u8 readPubek; + u8 disableOwnerClear; + u8 allowMaintenance; + u8 physicalPresenceLifetimeLock; + u8 physicalPresenceHWEnable; + u8 physicalPresenceCMDEnable; + u8 CEKPUsed; + u8 TPMpost; + u8 TPMpostLock; + u8 FIPS; + u8 operator; + u8 enableRevokeEK; + u8 nvLocked; + u8 readSRKPub; + u8 tpmEstablished; + u8 maintenanceDone; + u8 disableFullDALogicInfo; +} __packed; + +typedef union { + struct permanent_flags_t perm_flags; + struct stclear_flags_t stclear_flags; + __u8 owned; + __be32 num_pcrs; + struct tpm1_version version1; + struct tpm1_version2 version2; + __be32 manufacturer_id; + struct timeout_t timeout; + struct duration_t duration; +} cap_t; + +/* + * 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 + * bytes, but 128 is still a relatively large number of random bytes and + * anything much bigger causes users of struct tpm_cmd_t to start getting + * compiler warnings about stack frame size. + */ +#define TPM_MAX_RNG_DATA 128 + +struct tpm1_get_random_out { + __be32 rng_data_len; + u8 rng_data[TPM_MAX_RNG_DATA]; +} __packed; /* Other constants */ #define SRKHANDLE 0x40000000 #define TPM_NONCE_SIZE 20 +#define TPM_ST_CLEAR 1 + +/* + * == TPM 2 Family Chips == + * + * TPM 2.0 Library + * https://trustedcomputinggroup.org/resource/tpm-library-specification/ + */ + +/* TPM2 specific constants. */ +#define TPM2_SPACE_BUFFER_SIZE 16384 /* 16 kB */ + +enum tpm2_session_types { + TPM2_SE_HMAC = 0x00, + TPM2_SE_POLICY = 0x01, + TPM2_SE_TRIAL = 0x02, +}; + +enum tpm2_timeouts { + TPM2_TIMEOUT_A = 750, + TPM2_TIMEOUT_B = 4000, + TPM2_TIMEOUT_C = 200, + TPM2_TIMEOUT_D = 30, + TPM2_DURATION_SHORT = 20, + TPM2_DURATION_MEDIUM = 750, + TPM2_DURATION_LONG = 2000, + TPM2_DURATION_LONG_LONG = 300000, + TPM2_DURATION_DEFAULT = 120000, +}; + +enum tpm2_structures { + TPM2_ST_NO_SESSIONS = 0x8001, + TPM2_ST_SESSIONS = 0x8002, + TPM2_ST_CREATION = 0x8021, +}; + +/* Indicates from what layer of the software stack the error comes from */ +#define TSS2_RC_LAYER_SHIFT 16 +#define TSS2_RESMGR_TPM_RC_LAYER (11 << TSS2_RC_LAYER_SHIFT) + +enum tpm2_return_codes { + TPM2_RC_SUCCESS = 0x0000, + TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ + TPM2_RC_HANDLE = 0x008B, + TPM2_RC_INTEGRITY = 0x009F, + TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ + TPM2_RC_FAILURE = 0x0101, + TPM2_RC_DISABLED = 0x0120, + TPM2_RC_UPGRADE = 0x012D, + TPM2_RC_COMMAND_CODE = 0x0143, + TPM2_RC_TESTING = 0x090A, /* RC_WARN */ + TPM2_RC_REFERENCE_H0 = 0x0910, + TPM2_RC_RETRY = 0x0922, + TPM2_RC_SESSION_MEMORY = 0x0903, +}; + +enum tpm2_command_codes { + TPM2_CC_FIRST = 0x011F, + TPM2_CC_HIERARCHY_CONTROL = 0x0121, + TPM2_CC_HIERARCHY_CHANGE_AUTH = 0x0129, + TPM2_CC_CREATE_PRIMARY = 0x0131, + TPM2_CC_SEQUENCE_COMPLETE = 0x013E, + TPM2_CC_SELF_TEST = 0x0143, + TPM2_CC_STARTUP = 0x0144, + TPM2_CC_SHUTDOWN = 0x0145, + TPM2_CC_NV_READ = 0x014E, + TPM2_CC_CREATE = 0x0153, + TPM2_CC_LOAD = 0x0157, + TPM2_CC_SEQUENCE_UPDATE = 0x015C, + TPM2_CC_UNSEAL = 0x015E, + TPM2_CC_CONTEXT_LOAD = 0x0161, + TPM2_CC_CONTEXT_SAVE = 0x0162, + TPM2_CC_FLUSH_CONTEXT = 0x0165, + TPM2_CC_READ_PUBLIC = 0x0173, + TPM2_CC_START_AUTH_SESS = 0x0176, + TPM2_CC_VERIFY_SIGNATURE = 0x0177, + TPM2_CC_GET_CAPABILITY = 0x017A, + TPM2_CC_GET_RANDOM = 0x017B, + TPM2_CC_PCR_READ = 0x017E, + TPM2_CC_PCR_EXTEND = 0x0182, + TPM2_CC_EVENT_SEQUENCE_COMPLETE = 0x0185, + TPM2_CC_HASH_SEQUENCE_START = 0x0186, + TPM2_CC_CREATE_LOADED = 0x0191, + TPM2_CC_LAST = 0x0193, /* Spec 1.36 */ +}; + +enum tpm2_capabilities { + TPM2_CAP_HANDLES = 1, + TPM2_CAP_COMMANDS = 2, + TPM2_CAP_PCRS = 5, + TPM2_CAP_TPM_PROPERTIES = 6, +}; + +enum tpm2_properties { + TPM_PT_TOTAL_COMMANDS = 0x0129, +}; + +enum tpm2_startup_types { + TPM2_SU_CLEAR = 0x0000, + TPM2_SU_STATE = 0x0001, +}; + +enum tpm2_cc_attrs { + TPM2_CC_ATTR_CHANDLES = 25, + TPM2_CC_ATTR_RHANDLE = 28, + TPM2_CC_ATTR_VENDOR = 29, +}; + +enum tpm2_permanent_handles { + TPM2_RH_NULL = 0x40000007, + TPM2_RS_PW = 0x40000009, +}; + +/* Most Significant Octet for key types */ +enum tpm2_mso_type { + TPM2_MSO_NVRAM = 0x01, + TPM2_MSO_SESSION = 0x02, + TPM2_MSO_POLICY = 0x03, + TPM2_MSO_PERMANENT = 0x40, + TPM2_MSO_VOLATILE = 0x80, + TPM2_MSO_PERSISTENT = 0x81, +}; + +enum tpm2_curves { + TPM2_ECC_NONE = 0x0000, + TPM2_ECC_NIST_P256 = 0x0003, +}; + +enum tpm2_object_attributes { + TPM2_OA_FIXED_TPM = BIT(1), + TPM2_OA_ST_CLEAR = BIT(2), + TPM2_OA_FIXED_PARENT = BIT(4), + TPM2_OA_SENSITIVE_DATA_ORIGIN = BIT(5), + TPM2_OA_USER_WITH_AUTH = BIT(6), + TPM2_OA_ADMIN_WITH_POLICY = BIT(7), + TPM2_OA_NO_DA = BIT(10), + TPM2_OA_ENCRYPTED_DUPLICATION = BIT(11), + TPM2_OA_RESTRICTED = BIT(16), + TPM2_OA_DECRYPT = BIT(17), + TPM2_OA_SIGN = BIT(18), +}; + +enum tpm2_session_attributes { + TPM2_SA_CONTINUE_SESSION = BIT(0), + TPM2_SA_AUDIT_EXCLUSIVE = BIT(1), + TPM2_SA_AUDIT_RESET = BIT(3), + TPM2_SA_DECRYPT = BIT(5), + TPM2_SA_ENCRYPT = BIT(6), + TPM2_SA_AUDIT = BIT(7), +}; + +enum tpm2_pcr_select { + TPM2_PLATFORM_PCR = 24, + TPM2_PCR_SELECT_MIN = ((TPM2_PLATFORM_PCR + 7) / 8), +}; + +enum tpm2_handle_types { + TPM2_HT_HMAC_SESSION = 0x02000000, + TPM2_HT_POLICY_SESSION = 0x03000000, + TPM2_HT_TRANSIENT = 0x80000000, +}; + +enum tpm2_pt_props { + TPM2_PT_NONE = 0x00000000, + TPM2_PT_GROUP = 0x00000100, + TPM2_PT_FIXED = TPM2_PT_GROUP * 1, + TPM2_PT_FAMILY_INDICATOR = TPM2_PT_FIXED + 0, + TPM2_PT_LEVEL = TPM2_PT_FIXED + 1, + TPM2_PT_REVISION = TPM2_PT_FIXED + 2, + TPM2_PT_DAY_OF_YEAR = TPM2_PT_FIXED + 3, + TPM2_PT_YEAR = TPM2_PT_FIXED + 4, + TPM2_PT_MANUFACTURER = TPM2_PT_FIXED + 5, + TPM2_PT_VENDOR_STRING_1 = TPM2_PT_FIXED + 6, + TPM2_PT_VENDOR_STRING_2 = TPM2_PT_FIXED + 7, + TPM2_PT_VENDOR_STRING_3 = TPM2_PT_FIXED + 8, + TPM2_PT_VENDOR_STRING_4 = TPM2_PT_FIXED + 9, + TPM2_PT_VENDOR_TPM_TYPE = TPM2_PT_FIXED + 10, + TPM2_PT_FIRMWARE_VERSION_1 = TPM2_PT_FIXED + 11, + TPM2_PT_FIRMWARE_VERSION_2 = TPM2_PT_FIXED + 12, + TPM2_PT_INPUT_BUFFER = TPM2_PT_FIXED + 13, + TPM2_PT_HR_TRANSIENT_MIN = TPM2_PT_FIXED + 14, + TPM2_PT_HR_PERSISTENT_MIN = TPM2_PT_FIXED + 15, + TPM2_PT_HR_LOADED_MIN = TPM2_PT_FIXED + 16, + TPM2_PT_ACTIVE_SESSIONS_MAX = TPM2_PT_FIXED + 17, + TPM2_PT_PCR_COUNT = TPM2_PT_FIXED + 18, + TPM2_PT_PCR_SELECT_MIN = TPM2_PT_FIXED + 19, + TPM2_PT_CONTEXT_GAP_MAX = TPM2_PT_FIXED + 20, + TPM2_PT_NV_COUNTERS_MAX = TPM2_PT_FIXED + 22, + TPM2_PT_NV_INDEX_MAX = TPM2_PT_FIXED + 23, + TPM2_PT_MEMORY = TPM2_PT_FIXED + 24, + TPM2_PT_CLOCK_UPDATE = TPM2_PT_FIXED + 25, + TPM2_PT_CONTEXT_HASH = TPM2_PT_FIXED + 26, + TPM2_PT_CONTEXT_SYM = TPM2_PT_FIXED + 27, + TPM2_PT_CONTEXT_SYM_SIZE = TPM2_PT_FIXED + 28, + TPM2_PT_ORDERLY_COUNT = TPM2_PT_FIXED + 29, + TPM2_PT_MAX_COMMAND_SIZE = TPM2_PT_FIXED + 30, + TPM2_PT_MAX_RESPONSE_SIZE = TPM2_PT_FIXED + 31, + TPM2_PT_MAX_DIGEST = TPM2_PT_FIXED + 32, + TPM2_PT_MAX_OBJECT_CONTEXT = TPM2_PT_FIXED + 33, + TPM2_PT_MAX_SESSION_CONTEXT = TPM2_PT_FIXED + 34, + TPM2_PT_PS_FAMILY_INDICATOR = TPM2_PT_FIXED + 35, + TPM2_PT_PS_LEVEL = TPM2_PT_FIXED + 36, + TPM2_PT_PS_REVISION = TPM2_PT_FIXED + 37, + TPM2_PT_PS_DAY_OF_YEAR = TPM2_PT_FIXED + 38, + TPM2_PT_PS_YEAR = TPM2_PT_FIXED + 39, + TPM2_PT_SPLIT_MAX = TPM2_PT_FIXED + 40, + TPM2_PT_TOTAL_COMMANDS = TPM2_PT_FIXED + 41, + TPM2_PT_LIBRARY_COMMANDS = TPM2_PT_FIXED + 42, + TPM2_PT_VENDOR_COMMANDS = TPM2_PT_FIXED + 43, + TPM2_PT_NV_BUFFER_MAX = TPM2_PT_FIXED + 44, + TPM2_PT_MODES = TPM2_PT_FIXED + 45, + TPM2_PT_MAX_CAP_BUFFER = TPM2_PT_FIXED + 46, + TPM2_PT_VAR = TPM2_PT_GROUP * 2, + TPM2_PT_PERMANENT = TPM2_PT_VAR + 0, + TPM2_PT_STARTUP_CLEAR = TPM2_PT_VAR + 1, + TPM2_PT_HR_NV_INDEX = TPM2_PT_VAR + 2, + TPM2_PT_HR_LOADED = TPM2_PT_VAR + 3, + TPM2_PT_HR_LOADED_AVAIL = TPM2_PT_VAR + 4, + TPM2_PT_HR_ACTIVE = TPM2_PT_VAR + 5, + TPM2_PT_HR_ACTIVE_AVAIL = TPM2_PT_VAR + 6, + TPM2_PT_HR_TRANSIENT_AVAIL = TPM2_PT_VAR + 7, + TPM2_PT_HR_PERSISTENT = TPM2_PT_VAR + 8, + TPM2_PT_HR_PERSISTENT_AVAIL = TPM2_PT_VAR + 9, + TPM2_PT_NV_COUNTERS = TPM2_PT_VAR + 10, + TPM2_PT_NV_COUNTERS_AVAIL = TPM2_PT_VAR + 11, + TPM2_PT_ALGORITHM_SET = TPM2_PT_VAR + 12, + TPM2_PT_LOADED_CURVES = TPM2_PT_VAR + 13, + TPM2_PT_LOCKOUT_COUNTER = TPM2_PT_VAR + 14, + TPM2_PT_MAX_AUTH_FAIL = TPM2_PT_VAR + 15, + TPM2_PT_LOCKOUT_INTERVAL = TPM2_PT_VAR + 16, + TPM2_PT_LOCKOUT_RECOVERY = TPM2_PT_VAR + 17, + TPM2_PT_NV_WRITE_RECOVERY = TPM2_PT_VAR + 18, + TPM2_PT_AUDIT_COUNTER_0 = TPM2_PT_VAR + 19, + TPM2_PT_AUDIT_COUNTER_1 = TPM2_PT_VAR + 20, +}; + +struct tpm2_pcr_read_out { + __be32 update_cnt; + __be32 pcr_selects_cnt; + __be16 hash_alg; + u8 pcr_select_size; + u8 pcr_select[TPM2_PCR_SELECT_MIN]; + __be32 digests_cnt; + __be16 digest_size; + u8 digest[]; +} __packed; + +struct tpm2_get_random_out { + __be16 size; + u8 buffer[TPM_MAX_RNG_DATA]; +} __packed; + +struct tpm2_get_cap_out { + u8 more_data; + __be32 subcap_id; + __be32 property_cnt; + __be32 property_id; + __be32 value; +} __packed; + +struct tpm2_pcr_selection { + __be16 hash_alg; + u8 size_of_select; + u8 pcr_select[3]; +} __packed; + +struct tpm2_context { + __be64 sequence; + __be32 saved_handle; + __be32 hierarchy; + __be16 blob_size; +} __packed; + +/* + * == TPM Common Defs == + */ + +#define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ +#define TPM_BUFSIZE 4096 + +/* + * SHA-512 is, as of today, the largest digest in the TCG algorithm repository. + */ +#define TPM2_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE + +/* + * A TPM name digest i.e., TPMT_HA, is a concatenation of TPM_ALG_ID of the + * name algorithm and hash of TPMT_PUBLIC. + */ +#define TPM2_MAX_NAME_SIZE (TPM2_MAX_DIGEST_SIZE + 2) + +/* + * Fixed define for the size of a name. This is actually HASHALG size + * plus 2, so 32 for SHA256 + */ +#define TPM2_NULL_NAME_SIZE 34 + +/* + * The maximum number of PCR banks. + */ +#define TPM2_MAX_PCR_BANKS 8 + +/* If you add a new hash to this, increment TPM_MAX_HASHES below */ +enum tpm_algorithms { + TPM_ALG_ERROR = 0x0000, + TPM_ALG_SHA1 = 0x0004, + TPM_ALG_AES = 0x0006, + TPM_ALG_KEYEDHASH = 0x0008, + TPM_ALG_SHA256 = 0x000B, + TPM_ALG_SHA384 = 0x000C, + TPM_ALG_SHA512 = 0x000D, + TPM_ALG_NULL = 0x0010, + TPM_ALG_SM3_256 = 0x0012, + TPM_ALG_ECC = 0x0023, + TPM_ALG_CFB = 0x0043, +}; + +/* + * The locality (0 - 4) for a TPM, as defined in section 3.2 of the + * Client Platform Profile Specification. + */ +enum tpm_localities { + TPM_LOCALITY_0 = 0, /* Static RTM */ + TPM_LOCALITY_1 = 1, /* Dynamic OS */ + TPM_LOCALITY_2 = 2, /* DRTM Environment */ + TPM_LOCALITY_3 = 3, /* Aux Components */ + TPM_LOCALITY_4 = 4, /* CPU DRTM Establishment */ + TPM_MAX_LOCALITY = TPM_LOCALITY_4 +}; + +/* + * Structure to represent active PCR algorithm banks usable by the + * TPM chip. + */ +struct tpm_bank_info { + u16 alg_id; + u16 digest_size; + u16 crypto_id; +}; + +/* + * Maximum number of hashing algorithms a TPM can have. This is + * basically a count of every hash in tpm_algorithms above + */ +#define TPM_MAX_HASHES 5 + +struct tpm_digest { + u16 alg_id; + u8 digest[TPM2_MAX_DIGEST_SIZE]; +} __packed; + +#define TPM_HEADER_SIZE 10 + +struct tpm_header { + __be16 tag; + __be32 length; + union { + __be32 ordinal; + __be32 return_code; + }; +} __packed; #endif diff --git a/include/linux/tpm_eventlog.h b/include/linux/tpm_eventlog.h index aff8ea2fa98e..40fe92eb7deb 100644 --- a/include/linux/tpm_eventlog.h +++ b/include/linux/tpm_eventlog.h @@ -3,7 +3,7 @@ #ifndef __LINUX_TPM_EVENTLOG_H__ #define __LINUX_TPM_EVENTLOG_H__ -#include <linux/tpm.h> +#include <linux/tpm_command.h> #define TCG_EVENT_NAME_LEN_MAX 255 #define MAX_TEXT_EVENT 1000 /* Max event string length */ diff --git a/include/linux/tpm_ptp.h b/include/linux/tpm_ptp.h new file mode 100644 index 000000000000..e80ed810a269 --- /dev/null +++ b/include/linux/tpm_ptp.h @@ -0,0 +1,133 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Following copyright information was take from the original file + * <drivers/char/tpm/tpm_tis_core.h> where the definitions were moved + * from: + * + * Copyright (C) 2005, 2006 IBM Corporation + * Copyright (C) 2014, 2015 Intel Corporation + * + * Authors: + * Leendert van Doorn <leendert@watson.ibm.com> + * Kylene Hall <kjhall@us.ibm.com> + * + * Maintained by: <tpmdd-devel@lists.sourceforge.net> + * + * Device driver for TCG/TCPA TPM (trusted platform module). + * Specifications at www.trustedcomputinggroup.org + * + * This device driver implements the TPM interface as defined in + * the TCG TPM Interface Spec version 1.2, revision 1.0. + */ + +#ifndef __LINUX_TPM_PTP_H__ +#define __LINUX_TPM_PTP_H__ + +/* + * TCG PC Client Platform TPM Profile (PTP) Specification + * https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/ + */ + +/* TIS/FIFO macros and definitions */ + +enum tis_access { + TPM_ACCESS_VALID = 0x80, + TPM_ACCESS_ACTIVE_LOCALITY = 0x20, /* (R) */ + TPM_ACCESS_RELINQUISH_LOCALITY = 0x20, /* (W) */ + TPM_ACCESS_REQUEST_PENDING = 0x04, /* (W) */ + TPM_ACCESS_REQUEST_USE = 0x02, /* (W) */ +}; + +enum tis_status { + TPM_STS_VALID = 0x80, /* (R) */ + TPM_STS_COMMAND_READY = 0x40, /* (R) */ + TPM_STS_DATA_AVAIL = 0x10, /* (R) */ + TPM_STS_DATA_EXPECT = 0x08, /* (R) */ + TPM_STS_GO = 0x20, /* (W) */ + TPM_STS_RESPONSE_RETRY = 0x02, /* (R) */ + TPM_STS_READ_ZERO = 0x23, /* bits that must be zero on read */ +}; + +enum tis_int_flags { + TPM_GLOBAL_INT_ENABLE = 0x80000000, + TPM_INTF_BURST_COUNT_STATIC = 0x100, + TPM_INTF_CMD_READY_INT = 0x080, + TPM_INTF_INT_EDGE_FALLING = 0x040, + TPM_INTF_INT_EDGE_RISING = 0x020, + TPM_INTF_INT_LEVEL_LOW = 0x010, + TPM_INTF_INT_LEVEL_HIGH = 0x008, + TPM_INTF_LOCALITY_CHANGE_INT = 0x004, + TPM_INTF_STS_VALID_INT = 0x002, + TPM_INTF_DATA_AVAIL_INT = 0x001, +}; + +enum tis_defaults { + TIS_MEM_LEN = 0x5000, + TIS_SHORT_TIMEOUT = 750, /* ms */ + TIS_LONG_TIMEOUT = 4000, /* 4 secs */ + TIS_TIMEOUT_MIN_ATML = 14700, /* usecs */ + TIS_TIMEOUT_MAX_ATML = 15000, /* usecs */ +}; + +#define TIS_MEM_X86_LPC_BASE 0xFED40000 +#define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 + +enum tis_x86_defaults { + TIS_MEM_X86_LEN = 0x5000, + ILB_REMAP_SIZE = 0x100, + LPC_CNTRL_OFFSET = 0x84, + LPC_CLKRUN_EN = (1 << 2), +}; + +/* + * Some timeout values are needed before it is known whether the chip is + * TPM 1.0 or TPM 2.0. + */ +#define TIS_TIMEOUT_A_MAX max_t(int, TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_A) +#define TIS_TIMEOUT_B_MAX max_t(int, TIS_LONG_TIMEOUT, TPM2_TIMEOUT_B) +#define TIS_TIMEOUT_C_MAX max_t(int, TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_C) +#define TIS_TIMEOUT_D_MAX max_t(int, TIS_SHORT_TIMEOUT, TPM2_TIMEOUT_D) + +#define TPM_ACCESS(l) (0x0000 | ((l) << 12)) +#define TPM_INT_ENABLE(l) (0x0008 | ((l) << 12)) +#define TPM_INT_VECTOR(l) (0x000C | ((l) << 12)) +#define TPM_INT_STATUS(l) (0x0010 | ((l) << 12)) +#define TPM_INTF_CAPS(l) (0x0014 | ((l) << 12)) +#define TPM_STS(l) (0x0018 | ((l) << 12)) +#define TPM_STS3(l) (0x001b | ((l) << 12)) +#define TPM_DATA_FIFO(l) (0x0024 | ((l) << 12)) +#define TPM_INTF_ID(l) (0x0030 | ((l) << 12)) + +#define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) +#define TPM_RID(l) (0x0F04 | ((l) << 12)) + +/* TPM HW Interface and Capabilities */ +#define TPM_TIS_INTF_ACTIVE 0x00 +#define TPM_CRB_INTF_ACTIVE 0x01 + +#define TPM_INTID_INTERFACE_TYPE GENMASK(3, 0) +#define TPM_INTID_INTERFACE_VERSION GENMASK(7, 4) +#define TPM_INTID_CAP_LOCALITY BIT(8) +#define TPM_INTID_CAP_TIS BIT(13) +#define TPM_INTID_CAP_CRB BIT(14) +#define TPM_INTID_CAP_IF_RES GENMASK(16, 15) +#define TPM_INTID_INTERFACE_SELECTOR GENMASK(18, 17) +#define TPM_INTID_INTF_SEL_LOCK BIT(19) + +#define TPM_TIS_INTF_12 0x00 +#define TPM_TIS_INTF_13 0x02 +#define TPM2_TIS_INTF_13 0x03 + +#define TPM_INTF_DATA_AVAIL_INT_SUPPORT BIT(0) +#define TPM_INTF_STS_VALID_INT_SUPPORT BIT(1) +#define TPM_INTF_LOCALITY_CHANGE_INT_SUPPORT BIT(2) +#define TPM_INTF_INTERRUPT_LEVEL_HIGH BIT(3) +#define TPM_INTF_INTERRUPT_LEVEL_LOW BIT(4) +#define TPM_INTF_INTERRUPT_EDGE_RISING BIT(5) +#define TPM_INTF_INTERRUPT_EDGE_FALLING BIT(6) +#define TPM_INTF_COMMAND_READY_INT_SUPPORT BIT(7) +#define TPM_INTF_BURST_COUNT_STATIC BIT(8) +#define TPM_INTF_DATA_TRANSFER_SIZE_SUPPORT GENMASK(10, 9) +#define TPM_INTF_INTERFACE_VERSION GENMASK(30, 28) + +#endif diff --git a/security/keys/trusted-keys/trusted_tpm1.c b/security/keys/trusted-keys/trusted_tpm1.c index 13513819991e..bf0bf7f36970 100644 --- a/security/keys/trusted-keys/trusted_tpm1.c +++ b/security/keys/trusted-keys/trusted_tpm1.c @@ -18,7 +18,6 @@ #include <keys/trusted-type.h> #include <linux/key-type.h> #include <linux/tpm.h> -#include <linux/tpm_command.h> #include <keys/trusted_tpm.h> @@ -317,9 +316,8 @@ static int TSS_checkhmac2(unsigned char *buffer, * For key specific tpm requests, we will generate and send our * own TPM command packets using the drivers send function. */ -static int trusted_tpm_send(unsigned char *cmd, size_t buflen) +static int trusted_tpm_send(struct tpm_buf *buf) { - struct tpm_buf buf; int rc; if (!chip) @@ -329,12 +327,9 @@ static int trusted_tpm_send(unsigned char *cmd, size_t buflen) if (rc) return rc; - buf.flags = 0; - buf.length = buflen; - buf.data = cmd; - dump_tpm_buf(cmd); - rc = tpm_transmit_cmd(chip, &buf, 4, "sending data"); - dump_tpm_buf(cmd); + dump_tpm_buf(buf->data); + rc = tpm_transmit_cmd(chip, buf, 4, "sending data"); + dump_tpm_buf(buf->data); if (rc > 0) /* TPM error */ @@ -380,7 +375,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, tpm_buf_append_u32(tb, handle); tpm_buf_append(tb, ononce, TPM_NONCE_SIZE); - ret = trusted_tpm_send(tb->data, tb->length); + ret = trusted_tpm_send(tb); if (ret < 0) return ret; @@ -404,7 +399,7 @@ static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) return -ENODEV; tpm_buf_reset(tb, TPM_TAG_RQU_COMMAND, TPM_ORD_OIAP); - ret = trusted_tpm_send(tb->data, tb->length); + ret = trusted_tpm_send(tb); if (ret < 0) return ret; @@ -513,7 +508,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, tpm_buf_append_u8(tb, cont); tpm_buf_append(tb, td->pubauth, SHA1_DIGEST_SIZE); - ret = trusted_tpm_send(tb->data, tb->length); + ret = trusted_tpm_send(tb); if (ret < 0) goto out; @@ -604,7 +599,7 @@ static int tpm_unseal(struct tpm_buf *tb, tpm_buf_append_u8(tb, cont); tpm_buf_append(tb, authdata2, SHA1_DIGEST_SIZE); - ret = trusted_tpm_send(tb->data, tb->length); + ret = trusted_tpm_send(tb); if (ret < 0) { pr_info("authhmac failed (%d)\n", ret); return ret; @@ -631,23 +626,23 @@ static int tpm_unseal(struct tpm_buf *tb, static int key_seal(struct trusted_key_payload *p, struct trusted_key_options *o) { - struct tpm_buf tb; int ret; - ret = tpm_buf_init(&tb, 0, 0); - if (ret) - return ret; + struct tpm_buf *tb __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!tb) + return -ENOMEM; + + tpm_buf_init(tb, TPM_BUFSIZE); /* include migratable flag at end of sealed key */ p->key[p->key_len] = p->migratable; - ret = tpm_seal(&tb, o->keytype, o->keyhandle, o->keyauth, + ret = tpm_seal(tb, o->keytype, o->keyhandle, o->keyauth, p->key, p->key_len + 1, p->blob, &p->blob_len, o->blobauth, o->pcrinfo, o->pcrinfo_len); if (ret < 0) pr_info("srkseal failed (%d)\n", ret); - tpm_buf_destroy(&tb); return ret; } @@ -657,14 +652,15 @@ static int key_seal(struct trusted_key_payload *p, static int key_unseal(struct trusted_key_payload *p, struct trusted_key_options *o) { - struct tpm_buf tb; int ret; - ret = tpm_buf_init(&tb, 0, 0); - if (ret) - return ret; + struct tpm_buf *tb __free(kfree) = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!tb) + return -ENOMEM; + + tpm_buf_init(tb, TPM_BUFSIZE); - ret = tpm_unseal(&tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, + ret = tpm_unseal(tb, o->keyhandle, o->keyauth, p->blob, p->blob_len, o->blobauth, p->key, &p->key_len); if (ret < 0) pr_info("srkunseal failed (%d)\n", ret); @@ -672,7 +668,6 @@ static int key_unseal(struct trusted_key_payload *p, /* pull migratable flag out of sealed key */ p->migratable = p->key[--p->key_len]; - tpm_buf_destroy(&tb); return ret; } @@ -987,9 +982,9 @@ err_put: static void trusted_tpm_exit(void) { if (chip) { + unregister_key_type(&key_type_trusted); put_device(&chip->dev); kfree(digests); - unregister_key_type(&key_type_trusted); } } diff --git a/security/keys/trusted-keys/trusted_tpm2.c b/security/keys/trusted-keys/trusted_tpm2.c index 6340823f8b53..67225dd562a9 100644 --- a/security/keys/trusted-keys/trusted_tpm2.c +++ b/security/keys/trusted-keys/trusted_tpm2.c @@ -9,7 +9,6 @@ #include <linux/string.h> #include <linux/err.h> #include <linux/tpm.h> -#include <linux/tpm_command.h> #include <keys/trusted-type.h> #include <keys/trusted_tpm.h> @@ -234,7 +233,8 @@ int tpm2_seal_trusted(struct tpm_chip *chip, struct trusted_key_options *options) { off_t offset = TPM_HEADER_SIZE; - struct tpm_buf buf, sized; + struct tpm_buf *buf __free(kfree) = NULL; + struct tpm_buf *sized __free(kfree) = NULL; int blob_len = 0; int hash; u32 flags; @@ -255,97 +255,100 @@ int tpm2_seal_trusted(struct tpm_chip *chip, if (rc) goto out_put; - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); - if (rc) { + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { + rc = -ENOMEM; tpm2_end_auth_session(chip); goto out_put; } - rc = tpm_buf_init_sized(&sized); - if (rc) { - tpm_buf_destroy(&buf); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_CREATE); + + sized = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!sized) { + rc = -ENOMEM; tpm2_end_auth_session(chip); goto out_put; } - rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL); + tpm_buf_init_sized(sized, TPM_BUFSIZE); + + rc = tpm_buf_append_name(chip, buf, options->keyhandle, NULL); if (rc) goto out; - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_DECRYPT, + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_DECRYPT, options->keyauth, TPM_DIGEST_SIZE); /* sensitive */ - tpm_buf_append_u16(&sized, options->blobauth_len); + tpm_buf_append_u16(sized, options->blobauth_len); if (options->blobauth_len) - tpm_buf_append(&sized, options->blobauth, options->blobauth_len); + tpm_buf_append(sized, options->blobauth, options->blobauth_len); - tpm_buf_append_u16(&sized, payload->key_len); - tpm_buf_append(&sized, payload->key, payload->key_len); - tpm_buf_append(&buf, sized.data, sized.length); + tpm_buf_append_u16(sized, payload->key_len); + tpm_buf_append(sized, payload->key, payload->key_len); + tpm_buf_append(buf, sized->data, sized->length); /* public */ - tpm_buf_reset_sized(&sized); - tpm_buf_append_u16(&sized, TPM_ALG_KEYEDHASH); - tpm_buf_append_u16(&sized, hash); + tpm_buf_reset_sized(sized); + tpm_buf_append_u16(sized, TPM_ALG_KEYEDHASH); + tpm_buf_append_u16(sized, hash); /* key properties */ flags = 0; flags |= options->policydigest_len ? 0 : TPM2_OA_USER_WITH_AUTH; flags |= payload->migratable ? 0 : (TPM2_OA_FIXED_TPM | TPM2_OA_FIXED_PARENT); - tpm_buf_append_u32(&sized, flags); + tpm_buf_append_u32(sized, flags); /* policy */ - tpm_buf_append_u16(&sized, options->policydigest_len); + tpm_buf_append_u16(sized, options->policydigest_len); if (options->policydigest_len) - tpm_buf_append(&sized, options->policydigest, options->policydigest_len); + tpm_buf_append(sized, options->policydigest, options->policydigest_len); /* public parameters */ - tpm_buf_append_u16(&sized, TPM_ALG_NULL); - tpm_buf_append_u16(&sized, 0); + tpm_buf_append_u16(sized, TPM_ALG_NULL); + tpm_buf_append_u16(sized, 0); - tpm_buf_append(&buf, sized.data, sized.length); + tpm_buf_append(buf, sized->data, sized->length); /* outside info */ - tpm_buf_append_u16(&buf, 0); + tpm_buf_append_u16(buf, 0); /* creation PCR */ - tpm_buf_append_u32(&buf, 0); + tpm_buf_append_u32(buf, 0); - if (buf.flags & TPM_BUF_OVERFLOW) { + if (buf->flags & TPM_BUF_INVALID) { rc = -E2BIG; tpm2_end_auth_session(chip); goto out; } - rc = tpm_buf_fill_hmac_session(chip, &buf); + rc = tpm_buf_fill_hmac_session(chip, buf); if (rc) goto out; - rc = tpm_transmit_cmd(chip, &buf, 4, "sealing data"); - rc = tpm_buf_check_hmac_response(chip, &buf, rc); + rc = tpm_transmit_cmd(chip, buf, 4, "sealing data"); + rc = tpm_buf_check_hmac_response(chip, buf, rc); if (rc) goto out; - blob_len = tpm_buf_read_u32(&buf, &offset); - if (blob_len > MAX_BLOB_SIZE || buf.flags & TPM_BUF_BOUNDARY_ERROR) { + blob_len = tpm_buf_read_u32(buf, &offset); + if (blob_len > MAX_BLOB_SIZE || buf->flags & TPM_BUF_INVALID) { rc = -E2BIG; goto out; } - if (buf.length - offset < blob_len) { + if (buf->length - offset < blob_len) { rc = -EFAULT; goto out; } - blob_len = tpm2_key_encode(payload, options, &buf.data[offset], blob_len); + blob_len = tpm2_key_encode(payload, options, &buf->data[offset], blob_len); if (blob_len < 0) rc = blob_len; out: - tpm_buf_destroy(&sized); - tpm_buf_destroy(&buf); - if (!rc) payload->blob_len = blob_len; @@ -373,7 +376,7 @@ static int tpm2_load_cmd(struct tpm_chip *chip, u32 *blob_handle) { u8 *blob_ref __free(kfree) = NULL; - struct tpm_buf buf; + struct tpm_buf *buf __free(kfree) = NULL; unsigned int private_len; unsigned int public_len; unsigned int blob_len; @@ -427,39 +430,38 @@ static int tpm2_load_cmd(struct tpm_chip *chip, if (rc) return rc; - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); - if (rc) { + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { tpm2_end_auth_session(chip); - return rc; + return -ENOMEM; } - rc = tpm_buf_append_name(chip, &buf, options->keyhandle, NULL); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_LOAD); + + rc = tpm_buf_append_name(chip, buf, options->keyhandle, NULL); if (rc) - goto out; + return rc; - tpm_buf_append_hmac_session(chip, &buf, 0, options->keyauth, + tpm_buf_append_hmac_session(chip, buf, 0, options->keyauth, TPM_DIGEST_SIZE); - tpm_buf_append(&buf, blob, blob_len); + tpm_buf_append(buf, blob, blob_len); - if (buf.flags & TPM_BUF_OVERFLOW) { - rc = -E2BIG; + if (buf->flags & TPM_BUF_INVALID) { tpm2_end_auth_session(chip); - goto out; + return -E2BIG; } - rc = tpm_buf_fill_hmac_session(chip, &buf); + rc = tpm_buf_fill_hmac_session(chip, buf); if (rc) - goto out; + return rc; - rc = tpm_transmit_cmd(chip, &buf, 4, "loading blob"); - rc = tpm_buf_check_hmac_response(chip, &buf, rc); + rc = tpm_transmit_cmd(chip, buf, 4, "loading blob"); + rc = tpm_buf_check_hmac_response(chip, buf, rc); if (!rc) *blob_handle = be32_to_cpup( - (__be32 *) &buf.data[TPM_HEADER_SIZE]); - -out: - tpm_buf_destroy(&buf); + (__be32 *)&buf->data[TPM_HEADER_SIZE]); return tpm_ret_to_err(rc); } @@ -482,7 +484,7 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, u32 blob_handle) { struct tpm_header *head; - struct tpm_buf buf; + struct tpm_buf *buf __free(kfree) = NULL; u16 data_len; int offset; u8 *data; @@ -492,18 +494,21 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, if (rc) return rc; - rc = tpm_buf_init(&buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); - if (rc) { + buf = kzalloc(TPM_BUFSIZE, GFP_KERNEL); + if (!buf) { tpm2_end_auth_session(chip); - return rc; + return -ENOMEM; } - rc = tpm_buf_append_name(chip, &buf, blob_handle, NULL); + tpm_buf_init(buf, TPM_BUFSIZE); + tpm_buf_reset(buf, TPM2_ST_SESSIONS, TPM2_CC_UNSEAL); + + rc = tpm_buf_append_name(chip, buf, blob_handle, NULL); if (rc) - goto out; + return rc; if (!options->policyhandle) { - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_ENCRYPT, options->blobauth, options->blobauth_len); } else { @@ -518,39 +523,36 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, * could repeat our actions with the exfiltrated * password. */ - tpm2_buf_append_auth(&buf, options->policyhandle, + tpm2_buf_append_auth(buf, options->policyhandle, NULL /* nonce */, 0, 0, options->blobauth, options->blobauth_len); if (tpm2_chip_auth(chip)) { - tpm_buf_append_hmac_session(chip, &buf, TPM2_SA_ENCRYPT, NULL, 0); + tpm_buf_append_hmac_session(chip, buf, TPM2_SA_ENCRYPT, + NULL, 0); } else { - offset = buf.handles * 4 + TPM_HEADER_SIZE; - head = (struct tpm_header *)buf.data; - if (tpm_buf_length(&buf) == offset) + offset = buf->handles * 4 + TPM_HEADER_SIZE; + head = (struct tpm_header *)buf->data; + if (tpm_buf_length(buf) == offset) head->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); } } - rc = tpm_buf_fill_hmac_session(chip, &buf); + rc = tpm_buf_fill_hmac_session(chip, buf); if (rc) - goto out; + return rc; - rc = tpm_transmit_cmd(chip, &buf, 6, "unsealing"); - rc = tpm_buf_check_hmac_response(chip, &buf, rc); + rc = tpm_transmit_cmd(chip, buf, 6, "unsealing"); + rc = tpm_buf_check_hmac_response(chip, buf, rc); if (!rc) { data_len = be16_to_cpup( - (__be16 *) &buf.data[TPM_HEADER_SIZE + 4]); - if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE) { - rc = -EFAULT; - goto out; - } + (__be16 *)&buf->data[TPM_HEADER_SIZE + 4]); + if (data_len < MIN_KEY_SIZE || data_len > MAX_KEY_SIZE) + return -EFAULT; - if (tpm_buf_length(&buf) < TPM_HEADER_SIZE + 6 + data_len) { - rc = -EFAULT; - goto out; - } - data = &buf.data[TPM_HEADER_SIZE + 6]; + if (tpm_buf_length(buf) < TPM_HEADER_SIZE + 6 + data_len) + return -EFAULT; + data = &buf->data[TPM_HEADER_SIZE + 6]; if (payload->old_format) { /* migratable flag is at the end of the key */ @@ -567,8 +569,6 @@ static int tpm2_unseal_cmd(struct tpm_chip *chip, } } -out: - tpm_buf_destroy(&buf); return tpm_ret_to_err(rc); } |
