diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-04 14:48:27 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-10-04 14:48:27 -0700 |
commit | a3443cda5588985a2724d6d0f4a5f04e625be6eb (patch) | |
tree | e6ce34ee3f8a887906f3a589dd9d2d2fc516953b /drivers/char | |
parent | 3cd013ab79e8e5c58fbd50fc09fceb6260a92a68 (diff) | |
parent | 1306d8e1c09fdc8ecb9ef235e2116352f810f9c5 (diff) | |
download | blackbird-obmc-linux-a3443cda5588985a2724d6d0f4a5f04e625be6eb.tar.gz blackbird-obmc-linux-a3443cda5588985a2724d6d0f4a5f04e625be6eb.zip |
Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull security subsystem updates from James Morris:
SELinux/LSM:
- overlayfs support, necessary for container filesystems
LSM:
- finally remove the kernel_module_from_file hook
Smack:
- treat signal delivery as an 'append' operation
TPM:
- lots of bugfixes & updates
Audit:
- new audit data type: LSM_AUDIT_DATA_FILE
* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: (47 commits)
Revert "tpm/tpm_crb: implement tpm crb idle state"
Revert "tmp/tpm_crb: fix Intel PTT hw bug during idle state"
Revert "tpm/tpm_crb: open code the crb_init into acpi_add"
Revert "tmp/tpm_crb: implement runtime pm for tpm_crb"
lsm,audit,selinux: Introduce a new audit data type LSM_AUDIT_DATA_FILE
tmp/tpm_crb: implement runtime pm for tpm_crb
tpm/tpm_crb: open code the crb_init into acpi_add
tmp/tpm_crb: fix Intel PTT hw bug during idle state
tpm/tpm_crb: implement tpm crb idle state
tpm: add check for minimum buffer size in tpm_transmit()
tpm: constify TPM 1.x header structures
tpm/tpm_crb: fix the over 80 characters checkpatch warring
tpm/tpm_crb: drop useless cpu_to_le32 when writing to registers
tpm/tpm_crb: cache cmd_size register value.
tmp/tpm_crb: drop include to platform_device
tpm/tpm_tis: remove unused itpm variable
tpm_crb: fix incorrect values of cmdReady and goIdle bits
tpm_crb: refine the naming of constants
tpm_crb: remove wmb()'s
tpm_crb: fix crb_req_canceled behavior
...
Diffstat (limited to 'drivers/char')
-rw-r--r-- | drivers/char/tpm/st33zp24/st33zp24.c | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-dev.c | 2 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-interface.c | 84 | ||||
-rw-r--r-- | drivers/char/tpm/tpm-sysfs.c | 4 | ||||
-rw-r--r-- | drivers/char/tpm/tpm.h | 46 | ||||
-rw-r--r-- | drivers/char/tpm/tpm2-cmd.c | 121 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_crb.c | 50 | ||||
-rw-r--r-- | drivers/char/tpm/tpm_tis_core.c | 24 |
8 files changed, 170 insertions, 163 deletions
diff --git a/drivers/char/tpm/st33zp24/st33zp24.c b/drivers/char/tpm/st33zp24/st33zp24.c index c2ee30451e41..6f060c76217b 100644 --- a/drivers/char/tpm/st33zp24/st33zp24.c +++ b/drivers/char/tpm/st33zp24/st33zp24.c @@ -589,8 +589,6 @@ int st33zp24_probe(void *phy_id, const struct st33zp24_phy_ops *ops, chip->flags |= TPM_CHIP_FLAG_IRQ; disable_irq_nosync(tpm_dev->irq); - - tpm_gen_interrupt(chip); } return tpm_chip_register(chip); diff --git a/drivers/char/tpm/tpm-dev.c b/drivers/char/tpm/tpm-dev.c index f5d452151c6b..912ad30be585 100644 --- a/drivers/char/tpm/tpm-dev.c +++ b/drivers/char/tpm/tpm-dev.c @@ -145,7 +145,7 @@ static ssize_t tpm_write(struct file *file, const char __user *buf, return -EPIPE; } out_size = tpm_transmit(priv->chip, priv->data_buffer, - sizeof(priv->data_buffer)); + sizeof(priv->data_buffer), 0); tpm_put_ops(priv->chip); if (out_size < 0) { diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 1abe2d7a2610..8de61876f633 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c @@ -330,13 +330,16 @@ EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); /* * Internal kernel interface to transmit TPM commands */ -ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, - size_t bufsiz) +ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, + unsigned int flags) { ssize_t rc; u32 count, ordinal; unsigned long stop; + if (bufsiz < TPM_HEADER_SIZE) + return -EINVAL; + if (bufsiz > TPM_BUFSIZE) bufsiz = TPM_BUFSIZE; @@ -350,7 +353,8 @@ ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, return -E2BIG; } - mutex_lock(&chip->tpm_mutex); + if (!(flags & TPM_TRANSMIT_UNLOCKED)) + mutex_lock(&chip->tpm_mutex); rc = chip->ops->send(chip, (u8 *) buf, count); if (rc < 0) { @@ -393,20 +397,21 @@ out_recv: dev_err(&chip->dev, "tpm_transmit: tpm_recv: error %zd\n", rc); out: - mutex_unlock(&chip->tpm_mutex); + if (!(flags & TPM_TRANSMIT_UNLOCKED)) + mutex_unlock(&chip->tpm_mutex); return rc; } #define TPM_DIGEST_SIZE 20 #define TPM_RET_CODE_IDX 6 -ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, - int len, const char *desc) +ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, + int len, unsigned int flags, const char *desc) { - struct tpm_output_header *header; + const struct tpm_output_header *header; int err; - len = tpm_transmit(chip, (u8 *) cmd, len); + len = tpm_transmit(chip, (const u8 *)cmd, len, flags); if (len < 0) return len; else if (len < TPM_HEADER_SIZE) @@ -453,26 +458,13 @@ ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap, tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); tpm_cmd.params.getcap_in.subcap = subcap_id; } - rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, desc); + rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, + desc); if (!rc) *cap = tpm_cmd.params.getcap_out.cap; return rc; } - -void tpm_gen_interrupt(struct tpm_chip *chip) -{ - struct tpm_cmd_t tpm_cmd; - ssize_t rc; - - tpm_cmd.header.in = tpm_getcap_header; - tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; - tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); - tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; - - rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, - "attempting to determine the timeouts"); -} -EXPORT_SYMBOL_GPL(tpm_gen_interrupt); +EXPORT_SYMBOL_GPL(tpm_getcap); #define TPM_ORD_STARTUP cpu_to_be32(153) #define TPM_ST_CLEAR cpu_to_be16(1) @@ -490,7 +482,7 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type) start_cmd.header.in = tpm_startup_header; start_cmd.params.startup_in.startup_type = startup_type; - return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, + return tpm_transmit_cmd(chip, &start_cmd, TPM_INTERNAL_RESULT_SIZE, 0, "attempting to start the TPM"); } @@ -521,7 +513,8 @@ int tpm_get_timeouts(struct tpm_chip *chip) tpm_cmd.params.getcap_in.cap = TPM_CAP_PROP; tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; - rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, NULL); + rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, + NULL); if (rc == TPM_ERR_INVALID_POSTINIT) { /* The TPM is not started, we are the first to talk to it. @@ -535,7 +528,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_TIMEOUT; rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, - NULL); + 0, NULL); } if (rc) { dev_err(&chip->dev, @@ -596,7 +589,7 @@ duration: tpm_cmd.params.getcap_in.subcap_size = cpu_to_be32(4); tpm_cmd.params.getcap_in.subcap = TPM_CAP_PROP_TIS_DURATION; - rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, + rc = tpm_transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, 0, "attempting to determine the durations"); if (rc) return rc; @@ -633,7 +626,7 @@ EXPORT_SYMBOL_GPL(tpm_get_timeouts); #define TPM_ORD_CONTINUE_SELFTEST 83 #define CONTINUE_SELFTEST_RESULT_SIZE 10 -static struct tpm_input_header continue_selftest_header = { +static const struct tpm_input_header continue_selftest_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(10), .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), @@ -652,14 +645,14 @@ static int tpm_continue_selftest(struct tpm_chip *chip) struct tpm_cmd_t cmd; cmd.header.in = continue_selftest_header; - rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, + rc = tpm_transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, 0, "continue selftest"); return rc; } #define TPM_ORDINAL_PCRREAD cpu_to_be32(21) #define READ_PCR_RESULT_SIZE 30 -static struct tpm_input_header pcrread_header = { +static const struct tpm_input_header pcrread_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(14), .ordinal = TPM_ORDINAL_PCRREAD @@ -672,7 +665,7 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) cmd.header.in = pcrread_header; cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); - rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, + rc = tpm_transmit_cmd(chip, &cmd, READ_PCR_RESULT_SIZE, 0, "attempting to read a pcr value"); if (rc == 0) @@ -745,7 +738,7 @@ EXPORT_SYMBOL_GPL(tpm_pcr_read); */ #define TPM_ORD_PCR_EXTEND cpu_to_be32(20) #define EXTEND_PCR_RESULT_SIZE 34 -static struct tpm_input_header pcrextend_header = { +static const struct tpm_input_header pcrextend_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(34), .ordinal = TPM_ORD_PCR_EXTEND @@ -770,7 +763,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) cmd.header.in = pcrextend_header; cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); - rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, + rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, 0, "attempting extend a PCR value"); tpm_put_ops(chip); @@ -792,7 +785,7 @@ int tpm_do_selftest(struct tpm_chip *chip) unsigned int loops; unsigned int delay_msec = 100; unsigned long duration; - struct tpm_cmd_t cmd; + u8 dummy[TPM_DIGEST_SIZE]; duration = tpm_calc_ordinal_duration(chip, TPM_ORD_CONTINUE_SELFTEST); @@ -807,9 +800,8 @@ int tpm_do_selftest(struct tpm_chip *chip) do { /* Attempt to read a PCR value */ - cmd.header.in = pcrread_header; - cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); - rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); + rc = tpm_pcr_read_dev(chip, 0, dummy); + /* Some buggy TPMs will not respond to tpm_tis_ready() for * around 300ms while the self test is ongoing, keep trying * until the self test duration expires. */ @@ -824,7 +816,6 @@ int tpm_do_selftest(struct tpm_chip *chip) if (rc < TPM_HEADER_SIZE) return -EFAULT; - rc = be32_to_cpu(cmd.header.out.return_code); if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { dev_info(&chip->dev, "TPM is disabled/deactivated (0x%X)\n", rc); @@ -879,7 +870,7 @@ int tpm_send(u32 chip_num, void *cmd, size_t buflen) if (chip == NULL) return -ENODEV; - rc = tpm_transmit_cmd(chip, cmd, buflen, "attempting tpm_cmd"); + rc = tpm_transmit_cmd(chip, cmd, buflen, 0, "attempting tpm_cmd"); tpm_put_ops(chip); return rc; @@ -949,7 +940,7 @@ EXPORT_SYMBOL_GPL(wait_for_tpm_stat); #define TPM_ORD_SAVESTATE cpu_to_be32(152) #define SAVESTATE_RESULT_SIZE 10 -static struct tpm_input_header savestate_header = { +static const struct tpm_input_header savestate_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(10), .ordinal = TPM_ORD_SAVESTATE @@ -981,14 +972,15 @@ int tpm_pm_suspend(struct device *dev) cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(tpm_suspend_pcr); memcpy(cmd.params.pcrextend_in.hash, dummy_hash, TPM_DIGEST_SIZE); - rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, + rc = tpm_transmit_cmd(chip, &cmd, EXTEND_PCR_RESULT_SIZE, 0, "extending dummy pcr before suspend"); } /* now do the actual savestate */ for (try = 0; try < TPM_RETRY; try++) { cmd.header.in = savestate_header; - rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, NULL); + rc = tpm_transmit_cmd(chip, &cmd, SAVESTATE_RESULT_SIZE, 0, + NULL); /* * If the TPM indicates that it is too busy to respond to @@ -1032,7 +1024,7 @@ int tpm_pm_resume(struct device *dev) EXPORT_SYMBOL_GPL(tpm_pm_resume); #define TPM_GETRANDOM_RESULT_SIZE 18 -static struct tpm_input_header tpm_getrandom_header = { +static const struct tpm_input_header tpm_getrandom_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(14), .ordinal = TPM_ORD_GET_RANDOM @@ -1072,8 +1064,8 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); err = tpm_transmit_cmd(chip, &tpm_cmd, - TPM_GETRANDOM_RESULT_SIZE + num_bytes, - "attempting get random"); + TPM_GETRANDOM_RESULT_SIZE + num_bytes, + 0, "attempting get random"); if (err) break; diff --git a/drivers/char/tpm/tpm-sysfs.c b/drivers/char/tpm/tpm-sysfs.c index b46cf70c8b16..a76ab4af9fb2 100644 --- a/drivers/char/tpm/tpm-sysfs.c +++ b/drivers/char/tpm/tpm-sysfs.c @@ -22,7 +22,7 @@ #define READ_PUBEK_RESULT_SIZE 314 #define TPM_ORD_READPUBEK cpu_to_be32(124) -static struct tpm_input_header tpm_readpubek_header = { +static const struct tpm_input_header tpm_readpubek_header = { .tag = TPM_TAG_RQU_COMMAND, .length = cpu_to_be32(30), .ordinal = TPM_ORD_READPUBEK @@ -39,7 +39,7 @@ static ssize_t pubek_show(struct device *dev, struct device_attribute *attr, struct tpm_chip *chip = to_tpm_chip(dev); tpm_cmd.header.in = tpm_readpubek_header; - err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, + err = tpm_transmit_cmd(chip, &tpm_cmd, READ_PUBEK_RESULT_SIZE, 0, "attempting to read the PUBEK"); if (err) goto out; diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 3e32d5bd2dc6..4d183c97f6a6 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h @@ -476,32 +476,35 @@ extern dev_t tpm_devt; extern const struct file_operations tpm_fops; extern struct idr dev_nums_idr; +enum tpm_transmit_flags { + TPM_TRANSMIT_UNLOCKED = BIT(0), +}; + +ssize_t tpm_transmit(struct tpm_chip *chip, const u8 *buf, size_t bufsiz, + unsigned int flags); +ssize_t tpm_transmit_cmd(struct tpm_chip *chip, const void *cmd, int len, + unsigned int flags, const char *desc); ssize_t tpm_getcap(struct tpm_chip *chip, __be32 subcap_id, cap_t *cap, const char *desc); -ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, - size_t bufsiz); -ssize_t tpm_transmit_cmd(struct tpm_chip *chip, void *cmd, int len, - const char *desc); -extern int tpm_get_timeouts(struct tpm_chip *); -extern void tpm_gen_interrupt(struct tpm_chip *); +int tpm_get_timeouts(struct tpm_chip *); int tpm1_auto_startup(struct tpm_chip *chip); -extern int tpm_do_selftest(struct tpm_chip *); -extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); -extern int tpm_pm_suspend(struct device *); -extern int tpm_pm_resume(struct device *); -extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, - wait_queue_head_t *, bool); +int tpm_do_selftest(struct tpm_chip *chip); +unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); +int tpm_pm_suspend(struct device *dev); +int tpm_pm_resume(struct device *dev); +int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, + wait_queue_head_t *queue, bool check_cancel); struct tpm_chip *tpm_chip_find_get(int chip_num); __must_check int tpm_try_get_ops(struct tpm_chip *chip); void tpm_put_ops(struct tpm_chip *chip); -extern struct tpm_chip *tpm_chip_alloc(struct device *dev, - const struct tpm_class_ops *ops); -extern struct tpm_chip *tpmm_chip_alloc(struct device *pdev, - const struct tpm_class_ops *ops); -extern int tpm_chip_register(struct tpm_chip *chip); -extern void tpm_chip_unregister(struct tpm_chip *chip); +struct tpm_chip *tpm_chip_alloc(struct device *dev, + const struct tpm_class_ops *ops); +struct tpm_chip *tpmm_chip_alloc(struct device *pdev, + const struct tpm_class_ops *ops); +int tpm_chip_register(struct tpm_chip *chip); +void tpm_chip_unregister(struct tpm_chip *chip); void tpm_sysfs_add_device(struct tpm_chip *chip); @@ -528,8 +531,7 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, const char *desc); int tpm2_auto_startup(struct tpm_chip *chip); -extern void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); -extern unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *, u32); -extern int tpm2_gen_interrupt(struct tpm_chip *chip); -extern int tpm2_probe(struct tpm_chip *chip); +void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type); +unsigned long tpm2_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); +int tpm2_probe(struct tpm_chip *chip); #endif diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 0c75c3f1689f..7df55d58c939 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -282,7 +282,7 @@ int tpm2_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) sizeof(cmd.params.pcrread_in.pcr_select)); cmd.params.pcrread_in.pcr_select[pcr_idx >> 3] = 1 << (pcr_idx & 0x7); - rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), + rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, "attempting to read a pcr value"); if (rc == 0) { buf = cmd.params.pcrread_out.digest; @@ -330,7 +330,7 @@ int tpm2_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) cmd.params.pcrextend_in.hash_alg = cpu_to_be16(TPM2_ALG_SHA1); memcpy(cmd.params.pcrextend_in.digest, hash, TPM_DIGEST_SIZE); - rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), + rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, "attempting extend a PCR value"); return rc; @@ -376,7 +376,7 @@ int tpm2_get_random(struct tpm_chip *chip, u8 *out, size_t max) cmd.header.in = tpm2_getrandom_header; cmd.params.getrandom_in.size = cpu_to_be16(num_bytes); - err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), + err = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, "attempting get random"); if (err) break; @@ -434,12 +434,12 @@ static void tpm2_buf_append_auth(struct tpm_buf *buf, u32 session_handle, } /** - * tpm2_seal_trusted() - seal a trusted key - * @chip_num: A specific chip number for the request or TPM_ANY_NUM - * @options: authentication values and other options + * tpm2_seal_trusted() - seal the payload of a trusted key + * @chip_num: TPM chip to use * @payload: the key data in clear and encrypted form + * @options: authentication values and other options * - * Returns < 0 on error and 0 on success. + * Return: < 0 on error and 0 on success. */ int tpm2_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, @@ -512,7 +512,7 @@ int tpm2_seal_trusted(struct tpm_chip *chip, goto out; } - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "sealing data"); + rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, 0, "sealing data"); if (rc) goto out; @@ -538,10 +538,18 @@ out: return rc; } -static int tpm2_load(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options, - u32 *blob_handle) +/** + * tpm2_load_cmd() - execute a TPM2_Load command + * @chip_num: TPM chip to use + * @payload: the key data in clear and encrypted form + * @options: authentication values and other options + * + * Return: same as with tpm_transmit_cmd + */ +static int tpm2_load_cmd(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options, + u32 *blob_handle, unsigned int flags) { struct tpm_buf buf; unsigned int private_len; @@ -576,7 +584,7 @@ static int tpm2_load(struct tpm_chip *chip, goto out; } - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "loading blob"); + rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, "loading blob"); if (!rc) *blob_handle = be32_to_cpup( (__be32 *) &buf.data[TPM_HEADER_SIZE]); @@ -590,7 +598,16 @@ out: return rc; } -static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) +/** + * tpm2_flush_context_cmd() - execute a TPM2_FlushContext command + * @chip_num: TPM chip to use + * @payload: the key data in clear and encrypted form + * @options: authentication values and other options + * + * Return: same as with tpm_transmit_cmd + */ +static void tpm2_flush_context_cmd(struct tpm_chip *chip, u32 handle, + unsigned int flags) { struct tpm_buf buf; int rc; @@ -604,7 +621,8 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) tpm_buf_append_u32(&buf, handle); - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "flushing context"); + rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, + "flushing context"); if (rc) dev_warn(&chip->dev, "0x%08x was not flushed, rc=%d\n", handle, rc); @@ -612,10 +630,18 @@ static void tpm2_flush_context(struct tpm_chip *chip, u32 handle) tpm_buf_destroy(&buf); } -static int tpm2_unseal(struct tpm_chip *chip, - struct trusted_key_payload *payload, - struct trusted_key_options *options, - u32 blob_handle) +/** + * tpm2_unseal_cmd() - execute a TPM2_Unload command + * @chip_num: TPM chip to use + * @payload: the key data in clear and encrypted form + * @options: authentication values and other options + * + * Return: same as with tpm_transmit_cmd + */ +static int tpm2_unseal_cmd(struct tpm_chip *chip, + struct trusted_key_payload *payload, + struct trusted_key_options *options, + u32 blob_handle, unsigned int flags) { struct tpm_buf buf; u16 data_len; @@ -635,7 +661,7 @@ static int tpm2_unseal(struct tpm_chip *chip, options->blobauth /* hmac */, TPM_DIGEST_SIZE); - rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, "unsealing"); + rc = tpm_transmit_cmd(chip, buf.data, PAGE_SIZE, flags, "unsealing"); if (rc > 0) rc = -EPERM; @@ -654,12 +680,12 @@ static int tpm2_unseal(struct tpm_chip *chip, } /** - * tpm_unseal_trusted() - unseal a trusted key - * @chip_num: A specific chip number for the request or TPM_ANY_NUM - * @options: authentication values and other options + * tpm_unseal_trusted() - unseal the payload of a trusted key + * @chip_num: TPM chip to use * @payload: the key data in clear and encrypted form + * @options: authentication values and other options * - * Returns < 0 on error and 0 on success. + * Return: < 0 on error and 0 on success. */ int tpm2_unseal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, @@ -668,14 +694,17 @@ int tpm2_unseal_trusted(struct tpm_chip *chip, u32 blob_handle; int rc; - rc = tpm2_load(chip, payload, options, &blob_handle); + mutex_lock(&chip->tpm_mutex); + rc = tpm2_load_cmd(chip, payload, options, &blob_handle, + TPM_TRANSMIT_UNLOCKED); if (rc) - return rc; - - rc = tpm2_unseal(chip, payload, options, blob_handle); - - tpm2_flush_context(chip, blob_handle); + goto out; + rc = tpm2_unseal_cmd(chip, payload, options, blob_handle, + TPM_TRANSMIT_UNLOCKED); + tpm2_flush_context_cmd(chip, blob_handle, TPM_TRANSMIT_UNLOCKED); +out: + mutex_unlock(&chip->tpm_mutex); return rc; } @@ -701,12 +730,13 @@ ssize_t tpm2_get_tpm_pt(struct tpm_chip *chip, u32 property_id, u32 *value, cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(property_id); cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); - rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), desc); + rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, desc); if (!rc) *value = be32_to_cpu(cmd.params.get_tpm_pt_out.value); return rc; } +EXPORT_SYMBOL_GPL(tpm2_get_tpm_pt); #define TPM2_STARTUP_IN_SIZE \ (sizeof(struct tpm_input_header) + \ @@ -735,7 +765,7 @@ static int tpm2_startup(struct tpm_chip *chip, u16 startup_type) cmd.header.in = tpm2_startup_header; cmd.params.startup_in.startup_type = cpu_to_be16(startup_type); - return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), + return tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, "attempting to start the TPM"); } @@ -763,7 +793,7 @@ void tpm2_shutdown(struct tpm_chip *chip, u16 shutdown_type) cmd.header.in = tpm2_shutdown_header; cmd.params.startup_in.startup_type = cpu_to_be16(shutdown_type); - rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), "stopping the TPM"); + rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, "stopping the TPM"); /* In places where shutdown command is sent there's no much we can do * except print the error code on a system failure. @@ -828,7 +858,7 @@ static int tpm2_start_selftest(struct tpm_chip *chip, bool full) cmd.header.in = tpm2_selftest_header; cmd.params.selftest_in.full_test = full; - rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, + rc = tpm_transmit_cmd(chip, &cmd, TPM2_SELF_TEST_IN_SIZE, 0, "continue selftest"); /* At least some prototype chips seem to give RC_TESTING error @@ -880,7 +910,7 @@ static int tpm2_do_selftest(struct tpm_chip *chip) cmd.params.pcrread_in.pcr_select[1] = 0x00; cmd.params.pcrread_in.pcr_select[2] = 0x00; - rc = tpm_transmit_cmd(chip, (u8 *) &cmd, sizeof(cmd), NULL); + rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, NULL); if (rc < 0) break; @@ -895,23 +925,6 @@ static int tpm2_do_selftest(struct tpm_chip *chip) } /** - * tpm2_gen_interrupt() - generate an interrupt - * @chip: TPM chip to use - * - * 0 is returned when the operation is successful. If a negative number is - * returned it remarks a POSIX error code. If a positive number is returned - * it remarks a TPM error. - */ -int tpm2_gen_interrupt(struct tpm_chip *chip) -{ - u32 dummy; - - return tpm2_get_tpm_pt(chip, 0x100, &dummy, - "attempting to generate an interrupt"); -} -EXPORT_SYMBOL_GPL(tpm2_gen_interrupt); - -/** * tpm2_probe() - probe TPM 2.0 * @chip: TPM chip to use * @@ -928,11 +941,9 @@ int tpm2_probe(struct tpm_chip *chip) cmd.params.get_tpm_pt_in.property_id = cpu_to_be32(0x100); cmd.params.get_tpm_pt_in.property_cnt = cpu_to_be32(1); - rc = tpm_transmit(chip, (const char *) &cmd, sizeof(cmd)); + rc = tpm_transmit_cmd(chip, &cmd, sizeof(cmd), 0, NULL); if (rc < 0) return rc; - else if (rc < TPM_HEADER_SIZE) - return -EFAULT; if (be16_to_cpu(cmd.header.out.tag) == TPM2_ST_NO_SESSIONS) chip->flags |= TPM_CHIP_FLAG_TPM2; diff --git a/drivers/char/tpm/tpm_crb.c b/drivers/char/tpm/tpm_crb.c index 018c382554ba..a7c870af916c 100644 --- a/drivers/char/tpm/tpm_crb.c +++ b/drivers/char/tpm/tpm_crb.c @@ -19,7 +19,6 @@ #include <linux/highmem.h> #include <linux/rculist.h> #include <linux/module.h> -#include <linux/platform_device.h> #include "tpm.h" #define ACPI_SIG_TPM2 "TPM2" @@ -34,14 +33,14 @@ enum crb_defaults { CRB_ACPI_START_INDEX = 1, }; -enum crb_ca_request { - CRB_CA_REQ_GO_IDLE = BIT(0), - CRB_CA_REQ_CMD_READY = BIT(1), +enum crb_ctrl_req { + CRB_CTRL_REQ_CMD_READY = BIT(0), + CRB_CTRL_REQ_GO_IDLE = BIT(1), }; -enum crb_ca_status { - CRB_CA_STS_ERROR = BIT(0), - CRB_CA_STS_TPM_IDLE = BIT(1), +enum crb_ctrl_sts { + CRB_CTRL_STS_ERROR = BIT(0), + CRB_CTRL_STS_TPM_IDLE = BIT(1), }; enum crb_start { @@ -67,7 +66,7 @@ struct crb_control_area { } __packed; enum crb_status { - CRB_STS_COMPLETE = BIT(0), + CRB_DRV_STS_COMPLETE = BIT(0), }; enum crb_flags { @@ -81,6 +80,7 @@ struct crb_priv { struct crb_control_area __iomem *cca; u8 __iomem *cmd; u8 __iomem *rsp; + u32 cmd_size; }; static SIMPLE_DEV_PM_OPS(crb_pm, tpm_pm_suspend, tpm_pm_resume); @@ -92,7 +92,7 @@ static u8 crb_status(struct tpm_chip *chip) if ((ioread32(&priv->cca->start) & CRB_START_INVOKE) != CRB_START_INVOKE) - sts |= CRB_STS_COMPLETE; + sts |= CRB_DRV_STS_COMPLETE; return sts; } @@ -106,7 +106,7 @@ static int crb_recv(struct tpm_chip *chip, u8 *buf, size_t count) if (count < 6) return -EIO; - if (ioread32(&priv->cca->sts) & CRB_CA_STS_ERROR) + if (ioread32(&priv->cca->sts) & CRB_CTRL_STS_ERROR) return -EIO; memcpy_fromio(buf, priv->rsp, 6); @@ -142,11 +142,14 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) struct crb_priv *priv = dev_get_drvdata(&chip->dev); int rc = 0; - if (len > ioread32(&priv->cca->cmd_size)) { - dev_err(&chip->dev, - "invalid command count value %x %zx\n", - (unsigned int) len, - (size_t) ioread32(&priv->cca->cmd_size)); + /* Zero the cancel register so that the next command will not get + * canceled. + */ + iowrite32(0, &priv->cca->cancel); + + if (len > priv->cmd_size) { + dev_err(&chip->dev, "invalid command count value %zd %d\n", + len, priv->cmd_size); return -E2BIG; } @@ -156,7 +159,7 @@ static int crb_send(struct tpm_chip *chip, u8 *buf, size_t len) wmb(); if (priv->flags & CRB_FL_CRB_START) - iowrite32(cpu_to_le32(CRB_START_INVOKE), &priv->cca->start); + iowrite32(CRB_START_INVOKE, &priv->cca->start); if (priv->flags & CRB_FL_ACPI_START) rc = crb_do_acpi_start(chip); @@ -168,15 +171,10 @@ static void crb_cancel(struct tpm_chip *chip) { struct crb_priv *priv = dev_get_drvdata(&chip->dev); - iowrite32(cpu_to_le32(CRB_CANCEL_INVOKE), &priv->cca->cancel); - - /* Make sure that cmd is populated before issuing cancel. */ - wmb(); + iowrite32(CRB_CANCEL_INVOKE, &priv->cca->cancel); if ((priv->flags & CRB_FL_ACPI_START) && crb_do_acpi_start(chip)) dev_err(&chip->dev, "ACPI Start failed\n"); - - iowrite32(0, &priv->cca->cancel); } static bool crb_req_canceled(struct tpm_chip *chip, u8 status) @@ -194,8 +192,8 @@ static const struct tpm_class_ops tpm_crb = { .send = crb_send, .cancel = crb_cancel, .req_canceled = crb_req_canceled, - .req_complete_mask = CRB_STS_COMPLETE, - .req_complete_val = CRB_STS_COMPLETE, + .req_complete_mask = CRB_DRV_STS_COMPLETE, + .req_complete_val = CRB_DRV_STS_COMPLETE, }; static int crb_init(struct acpi_device *device, struct crb_priv *priv) @@ -265,8 +263,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, acpi_dev_free_resource_list(&resources); if (resource_type(&io_res) != IORESOURCE_MEM) { - dev_err(dev, - FW_BUG "TPM2 ACPI table does not define a memory resource\n"); + dev_err(dev, FW_BUG "TPM2 ACPI table does not define a memory resource\n"); return -EINVAL; } @@ -302,6 +299,7 @@ static int crb_map_io(struct acpi_device *device, struct crb_priv *priv, dev_err(dev, FW_BUG "overlapping command and response buffer sizes are not identical"); return -EINVAL; } + priv->cmd_size = cmd_size; priv->rsp = priv->cmd; return 0; diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index d66f51b3648e..e3bf31b37138 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c @@ -440,7 +440,6 @@ static int probe_itpm(struct tpm_chip *chip) 0x00, 0x00, 0x00, 0xf1 }; size_t len = sizeof(cmd_getticks); - bool itpm; u16 vendor; rc = tpm_tis_read16(priv, TPM_DID_VID(0), &vendor); @@ -451,8 +450,6 @@ static int probe_itpm(struct tpm_chip *chip) if (vendor != TPM_VID_INTEL) return 0; - itpm = false; - rc = tpm_tis_send_data(chip, cmd_getticks, len); if (rc == 0) goto out; @@ -460,8 +457,6 @@ static int probe_itpm(struct tpm_chip *chip) tpm_tis_ready(chip); release_locality(chip, priv->locality, 0); - itpm = true; - rc = tpm_tis_send_data(chip, cmd_getticks, len); if (rc == 0) { dev_info(&chip->dev, "Detected an iTPM.\n"); @@ -526,6 +521,18 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) return IRQ_HANDLED; } +static int tpm_tis_gen_interrupt(struct tpm_chip *chip) +{ + const char *desc = "attempting to generate an interrupt"; + u32 cap2; + cap_t cap; + + if (chip->flags & TPM_CHIP_FLAG_TPM2) + return tpm2_get_tpm_pt(chip, 0x100, &cap2, desc); + else + return tpm_getcap(chip, TPM_CAP_PROP_TIS_TIMEOUT, &cap, desc); +} + /* Register the IRQ and issue a command that will cause an interrupt. If an * irq is seen then leave the chip setup for IRQ operation, otherwise reverse * everything and leave in polling mode. Returns 0 on success. @@ -575,10 +582,9 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask, /* Generate an interrupt by having the core call through to * tpm_tis_send */ - if (chip->flags & TPM_CHIP_FLAG_TPM2) - tpm2_gen_interrupt(chip); - else - tpm_gen_interrupt(chip); + rc = tpm_tis_gen_interrupt(chip); + if (rc < 0) + return rc; /* tpm_tis_send will either confirm the interrupt is working or it * will call disable_irq which undoes all of the above. |