diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-31 16:12:31 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2018-01-31 16:12:31 -0500 |
commit | ae0cb7be35fe6c7e8bcc816ec4185d0a37748cc1 (patch) | |
tree | 2453151c8d507502ce91c6827f3e8a35e1777996 | |
parent | 2a7149031457c5dd05f670737a9dd5d32524f145 (diff) | |
parent | ebceb1c87c0c482d47cb92dc3cc51d28f7387716 (diff) |
Merge branch 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull tpm updates from James Morris:
- reduce polling delays in tpm_tis
- support retrieving TPM 2.0 Event Log through EFI before
ExitBootServices
- replace tpm-rng.c with a hwrng device managed by the driver for each
TPM device
- TPM resource manager synthesizes TPM_RC_COMMAND_CODE response instead
of returning -EINVAL for unknown TPM commands. This makes user space
more sound.
- CLKRUN fixes:
* Keep #CLKRUN disable through the entier TPM command/response flow
* Check whether #CLKRUN is enabled before disabling and enabling it
again because enabling it breaks PS/2 devices on a system where it
is disabled
* 'next-tpm' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
tpm: remove unused variables
tpm: remove unused data fields from I2C and OF device ID tables
tpm: only attempt to disable the LPC CLKRUN if is already enabled
tpm: follow coding style for variable declaration in tpm_tis_core_init()
tpm: delete the TPM_TIS_CLK_ENABLE flag
tpm: Update MAINTAINERS for Jason Gunthorpe
tpm: Keep CLKRUN enabled throughout the duration of transmit_cmd()
tpm_tis: Move ilb_base_addr to tpm_tis_data
tpm2-cmd: allow more attempts for selftest execution
tpm: return a TPM_RC_COMMAND_CODE response if command is not implemented
tpm: Move Linux RNG connection to hwrng
tpm: use struct tpm_chip for tpm_chip_find_get()
tpm: parse TPM event logs based on EFI table
efi: call get_event_log before ExitBootServices
tpm: add event log format version
tpm: rename event log provider files
tpm: move tpm_eventlog.h outside of drivers folder
tpm: use tpm_msleep() value as max delay
tpm: reduce tpm polling delay in tpm_tis_core
tpm: move wait_for_tpm_stat() to respective driver files
33 files changed, 789 insertions, 443 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index bc29978d263c..7872d430e7b1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -13869,9 +13869,10 @@ F: drivers/platform/x86/toshiba-wmi.c | |||
13869 | TPM DEVICE DRIVER | 13869 | TPM DEVICE DRIVER |
13870 | M: Peter Huewe <peterhuewe@gmx.de> | 13870 | M: Peter Huewe <peterhuewe@gmx.de> |
13871 | M: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> | 13871 | M: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> |
13872 | R: Jason Gunthorpe <jgunthorpe@obsidianresearch.com> | 13872 | R: Jason Gunthorpe <jgg@ziepe.ca> |
13873 | L: linux-integrity@vger.kernel.org | 13873 | L: linux-integrity@vger.kernel.org |
13874 | Q: https://patchwork.kernel.org/project/linux-integrity/list/ | 13874 | Q: https://patchwork.kernel.org/project/linux-integrity/list/ |
13875 | W: https://kernsec.org/wiki/index.php/Linux_Kernel_Integrity | ||
13875 | T: git git://git.infradead.org/users/jjs/linux-tpmdd.git | 13876 | T: git git://git.infradead.org/users/jjs/linux-tpmdd.git |
13876 | S: Maintained | 13877 | S: Maintained |
13877 | F: drivers/char/tpm/ | 13878 | F: drivers/char/tpm/ |
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index e56dbc67e837..353e20c3f114 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -999,6 +999,7 @@ struct boot_params *efi_main(struct efi_config *c, | |||
999 | 999 | ||
1000 | /* Ask the firmware to clear memory on unclean shutdown */ | 1000 | /* Ask the firmware to clear memory on unclean shutdown */ |
1001 | efi_enable_reset_attack_mitigation(sys_table); | 1001 | efi_enable_reset_attack_mitigation(sys_table); |
1002 | efi_retrieve_tpm2_eventlog(sys_table); | ||
1002 | 1003 | ||
1003 | setup_graphics(boot_params); | 1004 | setup_graphics(boot_params); |
1004 | 1005 | ||
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index f6e3e5abc117..88044eda0ac6 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
@@ -306,19 +306,6 @@ config HW_RANDOM_POWERNV | |||
306 | 306 | ||
307 | If unsure, say Y. | 307 | If unsure, say Y. |
308 | 308 | ||
309 | config HW_RANDOM_TPM | ||
310 | tristate "TPM HW Random Number Generator support" | ||
311 | depends on TCG_TPM | ||
312 | default HW_RANDOM | ||
313 | ---help--- | ||
314 | This driver provides kernel-side support for the Random Number | ||
315 | Generator in the Trusted Platform Module | ||
316 | |||
317 | To compile this driver as a module, choose M here: the | ||
318 | module will be called tpm-rng. | ||
319 | |||
320 | If unsure, say Y. | ||
321 | |||
322 | config HW_RANDOM_HISI | 309 | config HW_RANDOM_HISI |
323 | tristate "Hisilicon Random Number Generator support" | 310 | tristate "Hisilicon Random Number Generator support" |
324 | depends on HW_RANDOM && ARCH_HISI | 311 | depends on HW_RANDOM && ARCH_HISI |
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index f3728d008fff..0ef05c61d9c8 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
@@ -27,7 +27,6 @@ obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o | |||
27 | obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o | 27 | obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o |
28 | obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o | 28 | obj-$(CONFIG_HW_RANDOM_POWERNV) += powernv-rng.o |
29 | obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o | 29 | obj-$(CONFIG_HW_RANDOM_HISI) += hisi-rng.o |
30 | obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o | ||
31 | obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o | 30 | obj-$(CONFIG_HW_RANDOM_BCM2835) += bcm2835-rng.o |
32 | obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o | 31 | obj-$(CONFIG_HW_RANDOM_IPROC_RNG200) += iproc-rng200.o |
33 | obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o | 32 | obj-$(CONFIG_HW_RANDOM_MSM) += msm-rng.o |
diff --git a/drivers/char/hw_random/tpm-rng.c b/drivers/char/hw_random/tpm-rng.c deleted file mode 100644 index d6d448266f07..000000000000 --- a/drivers/char/hw_random/tpm-rng.c +++ /dev/null | |||
@@ -1,50 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Kent Yoder IBM Corporation | ||
3 | * | ||
4 | * HWRNG interfaces to pull RNG data from a TPM | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/module.h> | ||
21 | #include <linux/hw_random.h> | ||
22 | #include <linux/tpm.h> | ||
23 | |||
24 | #define MODULE_NAME "tpm-rng" | ||
25 | |||
26 | static int tpm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) | ||
27 | { | ||
28 | return tpm_get_random(TPM_ANY_NUM, data, max); | ||
29 | } | ||
30 | |||
31 | static struct hwrng tpm_rng = { | ||
32 | .name = MODULE_NAME, | ||
33 | .read = tpm_rng_read, | ||
34 | }; | ||
35 | |||
36 | static int __init rng_init(void) | ||
37 | { | ||
38 | return hwrng_register(&tpm_rng); | ||
39 | } | ||
40 | module_init(rng_init); | ||
41 | |||
42 | static void __exit rng_exit(void) | ||
43 | { | ||
44 | hwrng_unregister(&tpm_rng); | ||
45 | } | ||
46 | module_exit(rng_exit); | ||
47 | |||
48 | MODULE_LICENSE("GPL v2"); | ||
49 | MODULE_AUTHOR("Kent Yoder <key@linux.vnet.ibm.com>"); | ||
50 | MODULE_DESCRIPTION("RNG driver for TPM devices"); | ||
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index a30352202f1f..18c81cbe4704 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
@@ -26,6 +26,17 @@ menuconfig TCG_TPM | |||
26 | 26 | ||
27 | if TCG_TPM | 27 | if TCG_TPM |
28 | 28 | ||
29 | config HW_RANDOM_TPM | ||
30 | bool "TPM HW Random Number Generator support" | ||
31 | depends on TCG_TPM && HW_RANDOM && !(TCG_TPM=y && HW_RANDOM=m) | ||
32 | default y | ||
33 | ---help--- | ||
34 | This setting exposes the TPM's Random Number Generator as a hwrng | ||
35 | device. This allows the kernel to collect randomness from the TPM at | ||
36 | boot, and provides the TPM randomines in /dev/hwrng. | ||
37 | |||
38 | If unsure, say Y. | ||
39 | |||
29 | config TCG_TIS_CORE | 40 | config TCG_TIS_CORE |
30 | tristate | 41 | tristate |
31 | ---help--- | 42 | ---help--- |
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 34b4bcf46f43..acd758381c58 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile | |||
@@ -6,8 +6,9 @@ obj-$(CONFIG_TCG_TPM) += tpm.o | |||
6 | tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \ | 6 | tpm-y := tpm-interface.o tpm-dev.o tpm-sysfs.o tpm-chip.o tpm2-cmd.o \ |
7 | tpm-dev-common.o tpmrm-dev.o tpm1_eventlog.o tpm2_eventlog.o \ | 7 | tpm-dev-common.o tpmrm-dev.o tpm1_eventlog.o tpm2_eventlog.o \ |
8 | tpm2-space.o | 8 | tpm2-space.o |
9 | tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_acpi.o | 9 | tpm-$(CONFIG_ACPI) += tpm_ppi.o tpm_eventlog_acpi.o |
10 | tpm-$(CONFIG_OF) += tpm_of.o | 10 | tpm-$(CONFIG_EFI) += tpm_eventlog_efi.o |
11 | tpm-$(CONFIG_OF) += tpm_eventlog_of.o | ||
11 | obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o | 12 | obj-$(CONFIG_TCG_TIS_CORE) += tpm_tis_core.o |
12 | obj-$(CONFIG_TCG_TIS) += tpm_tis.o | 13 | obj-$(CONFIG_TCG_TIS) += tpm_tis.o |
13 | obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o | 14 | obj-$(CONFIG_TCG_TIS_SPI) += tpm_tis_spi.o |
diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c index 0eca20c5a80c..0a62c19937b6 100644 --- a/drivers/char/tpm/tpm-chip.c +++ b/drivers/char/tpm/tpm-chip.c | |||
@@ -26,8 +26,9 @@ | |||
26 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
27 | #include <linux/freezer.h> | 27 | #include <linux/freezer.h> |
28 | #include <linux/major.h> | 28 | #include <linux/major.h> |
29 | #include <linux/tpm_eventlog.h> | ||
30 | #include <linux/hw_random.h> | ||
29 | #include "tpm.h" | 31 | #include "tpm.h" |
30 | #include "tpm_eventlog.h" | ||
31 | 32 | ||
32 | DEFINE_IDR(dev_nums_idr); | 33 | DEFINE_IDR(dev_nums_idr); |
33 | static DEFINE_MUTEX(idr_lock); | 34 | static DEFINE_MUTEX(idr_lock); |
@@ -80,21 +81,26 @@ void tpm_put_ops(struct tpm_chip *chip) | |||
80 | EXPORT_SYMBOL_GPL(tpm_put_ops); | 81 | EXPORT_SYMBOL_GPL(tpm_put_ops); |
81 | 82 | ||
82 | /** | 83 | /** |
83 | * tpm_chip_find_get() - return tpm_chip for a given chip number | 84 | * tpm_chip_find_get() - find and reserve a TPM chip |
84 | * @chip_num: id to find | 85 | * @chip: a &struct tpm_chip instance, %NULL for the default chip |
85 | * | 86 | * |
86 | * The return'd chip has been tpm_try_get_ops'd and must be released via | 87 | * Finds a TPM chip and reserves its class device and operations. The chip must |
87 | * tpm_put_ops | 88 | * be released with tpm_chip_put_ops() after use. |
89 | * | ||
90 | * Return: | ||
91 | * A reserved &struct tpm_chip instance. | ||
92 | * %NULL if a chip is not found. | ||
93 | * %NULL if the chip is not available. | ||
88 | */ | 94 | */ |
89 | struct tpm_chip *tpm_chip_find_get(int chip_num) | 95 | struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip) |
90 | { | 96 | { |
91 | struct tpm_chip *chip, *res = NULL; | 97 | struct tpm_chip *res = NULL; |
98 | int chip_num = 0; | ||
92 | int chip_prev; | 99 | int chip_prev; |
93 | 100 | ||
94 | mutex_lock(&idr_lock); | 101 | mutex_lock(&idr_lock); |
95 | 102 | ||
96 | if (chip_num == TPM_ANY_NUM) { | 103 | if (!chip) { |
97 | chip_num = 0; | ||
98 | do { | 104 | do { |
99 | chip_prev = chip_num; | 105 | chip_prev = chip_num; |
100 | chip = idr_get_next(&dev_nums_idr, &chip_num); | 106 | chip = idr_get_next(&dev_nums_idr, &chip_num); |
@@ -104,8 +110,7 @@ struct tpm_chip *tpm_chip_find_get(int chip_num) | |||
104 | } | 110 | } |
105 | } while (chip_prev != chip_num); | 111 | } while (chip_prev != chip_num); |
106 | } else { | 112 | } else { |
107 | chip = idr_find(&dev_nums_idr, chip_num); | 113 | if (!tpm_try_get_ops(chip)) |
108 | if (chip && !tpm_try_get_ops(chip)) | ||
109 | res = chip; | 114 | res = chip; |
110 | } | 115 | } |
111 | 116 | ||
@@ -387,6 +392,26 @@ static int tpm_add_legacy_sysfs(struct tpm_chip *chip) | |||
387 | 392 | ||
388 | return 0; | 393 | return 0; |
389 | } | 394 | } |
395 | |||
396 | static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait) | ||
397 | { | ||
398 | struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng); | ||
399 | |||
400 | return tpm_get_random(chip, data, max); | ||
401 | } | ||
402 | |||
403 | static int tpm_add_hwrng(struct tpm_chip *chip) | ||
404 | { | ||
405 | if (!IS_ENABLED(CONFIG_HW_RANDOM_TPM)) | ||
406 | return 0; | ||
407 | |||
408 | snprintf(chip->hwrng_name, sizeof(chip->hwrng_name), | ||
409 | "tpm-rng-%d", chip->dev_num); | ||
410 | chip->hwrng.name = chip->hwrng_name; | ||
411 | chip->hwrng.read = tpm_hwrng_read; | ||
412 | return hwrng_register(&chip->hwrng); | ||
413 | } | ||
414 | |||
390 | /* | 415 | /* |
391 | * tpm_chip_register() - create a character device for the TPM chip | 416 | * tpm_chip_register() - create a character device for the TPM chip |
392 | * @chip: TPM chip to use. | 417 | * @chip: TPM chip to use. |
@@ -419,11 +444,13 @@ int tpm_chip_register(struct tpm_chip *chip) | |||
419 | 444 | ||
420 | tpm_add_ppi(chip); | 445 | tpm_add_ppi(chip); |
421 | 446 | ||
447 | rc = tpm_add_hwrng(chip); | ||
448 | if (rc) | ||
449 | goto out_ppi; | ||
450 | |||
422 | rc = tpm_add_char_device(chip); | 451 | rc = tpm_add_char_device(chip); |
423 | if (rc) { | 452 | if (rc) |
424 | tpm_bios_log_teardown(chip); | 453 | goto out_hwrng; |
425 | return rc; | ||
426 | } | ||
427 | 454 | ||
428 | rc = tpm_add_legacy_sysfs(chip); | 455 | rc = tpm_add_legacy_sysfs(chip); |
429 | if (rc) { | 456 | if (rc) { |
@@ -432,6 +459,14 @@ int tpm_chip_register(struct tpm_chip *chip) | |||
432 | } | 459 | } |
433 | 460 | ||
434 | return 0; | 461 | return 0; |
462 | |||
463 | out_hwrng: | ||
464 | if (IS_ENABLED(CONFIG_HW_RANDOM_TPM)) | ||
465 | hwrng_unregister(&chip->hwrng); | ||
466 | out_ppi: | ||
467 | tpm_bios_log_teardown(chip); | ||
468 | |||
469 | return rc; | ||
435 | } | 470 | } |
436 | EXPORT_SYMBOL_GPL(tpm_chip_register); | 471 | EXPORT_SYMBOL_GPL(tpm_chip_register); |
437 | 472 | ||
@@ -451,6 +486,8 @@ EXPORT_SYMBOL_GPL(tpm_chip_register); | |||
451 | void tpm_chip_unregister(struct tpm_chip *chip) | 486 | void tpm_chip_unregister(struct tpm_chip *chip) |
452 | { | 487 | { |
453 | tpm_del_legacy_sysfs(chip); | 488 | tpm_del_legacy_sysfs(chip); |
489 | if (IS_ENABLED(CONFIG_HW_RANDOM_TPM)) | ||
490 | hwrng_unregister(&chip->hwrng); | ||
454 | tpm_bios_log_teardown(chip); | 491 | tpm_bios_log_teardown(chip); |
455 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 492 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
456 | cdev_device_del(&chip->cdevs, &chip->devs); | 493 | cdev_device_del(&chip->cdevs, &chip->devs); |
diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c index 1d6729be4cd6..76df4fbcf089 100644 --- a/drivers/char/tpm/tpm-interface.c +++ b/drivers/char/tpm/tpm-interface.c | |||
@@ -30,9 +30,9 @@ | |||
30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
31 | #include <linux/freezer.h> | 31 | #include <linux/freezer.h> |
32 | #include <linux/pm_runtime.h> | 32 | #include <linux/pm_runtime.h> |
33 | #include <linux/tpm_eventlog.h> | ||
33 | 34 | ||
34 | #include "tpm.h" | 35 | #include "tpm.h" |
35 | #include "tpm_eventlog.h" | ||
36 | 36 | ||
37 | #define TPM_MAX_ORDINAL 243 | 37 | #define TPM_MAX_ORDINAL 243 |
38 | #define TSC_MAX_ORDINAL 12 | 38 | #define TSC_MAX_ORDINAL 12 |
@@ -328,7 +328,7 @@ unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, | |||
328 | } | 328 | } |
329 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); | 329 | EXPORT_SYMBOL_GPL(tpm_calc_ordinal_duration); |
330 | 330 | ||
331 | static bool tpm_validate_command(struct tpm_chip *chip, | 331 | static int tpm_validate_command(struct tpm_chip *chip, |
332 | struct tpm_space *space, | 332 | struct tpm_space *space, |
333 | const u8 *cmd, | 333 | const u8 *cmd, |
334 | size_t len) | 334 | size_t len) |
@@ -340,10 +340,10 @@ static bool tpm_validate_command(struct tpm_chip *chip, | |||
340 | unsigned int nr_handles; | 340 | unsigned int nr_handles; |
341 | 341 | ||
342 | if (len < TPM_HEADER_SIZE) | 342 | if (len < TPM_HEADER_SIZE) |
343 | return false; | 343 | return -EINVAL; |
344 | 344 | ||
345 | if (!space) | 345 | if (!space) |
346 | return true; | 346 | return 0; |
347 | 347 | ||
348 | if (chip->flags & TPM_CHIP_FLAG_TPM2 && chip->nr_commands) { | 348 | if (chip->flags & TPM_CHIP_FLAG_TPM2 && chip->nr_commands) { |
349 | cc = be32_to_cpu(header->ordinal); | 349 | cc = be32_to_cpu(header->ordinal); |
@@ -352,7 +352,7 @@ static bool tpm_validate_command(struct tpm_chip *chip, | |||
352 | if (i < 0) { | 352 | if (i < 0) { |
353 | dev_dbg(&chip->dev, "0x%04X is an invalid command\n", | 353 | dev_dbg(&chip->dev, "0x%04X is an invalid command\n", |
354 | cc); | 354 | cc); |
355 | return false; | 355 | return -EOPNOTSUPP; |
356 | } | 356 | } |
357 | 357 | ||
358 | attrs = chip->cc_attrs_tbl[i]; | 358 | attrs = chip->cc_attrs_tbl[i]; |
@@ -362,11 +362,11 @@ static bool tpm_validate_command(struct tpm_chip *chip, | |||
362 | goto err_len; | 362 | goto err_len; |
363 | } | 363 | } |
364 | 364 | ||
365 | return true; | 365 | return 0; |
366 | err_len: | 366 | err_len: |
367 | dev_dbg(&chip->dev, | 367 | dev_dbg(&chip->dev, |
368 | "%s: insufficient command length %zu", __func__, len); | 368 | "%s: insufficient command length %zu", __func__, len); |
369 | return false; | 369 | return -EINVAL; |
370 | } | 370 | } |
371 | 371 | ||
372 | /** | 372 | /** |
@@ -391,8 +391,20 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | |||
391 | unsigned long stop; | 391 | unsigned long stop; |
392 | bool need_locality; | 392 | bool need_locality; |
393 | 393 | ||
394 | if (!tpm_validate_command(chip, space, buf, bufsiz)) | 394 | rc = tpm_validate_command(chip, space, buf, bufsiz); |
395 | return -EINVAL; | 395 | if (rc == -EINVAL) |
396 | return rc; | ||
397 | /* | ||
398 | * If the command is not implemented by the TPM, synthesize a | ||
399 | * response with a TPM2_RC_COMMAND_CODE return for user-space. | ||
400 | */ | ||
401 | if (rc == -EOPNOTSUPP) { | ||
402 | header->length = cpu_to_be32(sizeof(*header)); | ||
403 | header->tag = cpu_to_be16(TPM2_ST_NO_SESSIONS); | ||
404 | header->return_code = cpu_to_be32(TPM2_RC_COMMAND_CODE | | ||
405 | TSS2_RESMGR_TPM_RC_LAYER); | ||
406 | return bufsiz; | ||
407 | } | ||
396 | 408 | ||
397 | if (bufsiz > TPM_BUFSIZE) | 409 | if (bufsiz > TPM_BUFSIZE) |
398 | bufsiz = TPM_BUFSIZE; | 410 | bufsiz = TPM_BUFSIZE; |
@@ -413,6 +425,9 @@ ssize_t tpm_transmit(struct tpm_chip *chip, struct tpm_space *space, | |||
413 | if (chip->dev.parent) | 425 | if (chip->dev.parent) |
414 | pm_runtime_get_sync(chip->dev.parent); | 426 | pm_runtime_get_sync(chip->dev.parent); |
415 | 427 | ||
428 | if (chip->ops->clk_enable != NULL) | ||
429 | chip->ops->clk_enable(chip, true); | ||
430 | |||
416 | /* Store the decision as chip->locality will be changed. */ | 431 | /* Store the decision as chip->locality will be changed. */ |
417 | need_locality = chip->locality == -1; | 432 | need_locality = chip->locality == -1; |
418 | 433 | ||
@@ -489,6 +504,9 @@ out: | |||
489 | chip->locality = -1; | 504 | chip->locality = -1; |
490 | } | 505 | } |
491 | out_no_locality: | 506 | out_no_locality: |
507 | if (chip->ops->clk_enable != NULL) | ||
508 | chip->ops->clk_enable(chip, false); | ||
509 | |||
492 | if (chip->dev.parent) | 510 | if (chip->dev.parent) |
493 | pm_runtime_put_sync(chip->dev.parent); | 511 | pm_runtime_put_sync(chip->dev.parent); |
494 | 512 | ||
@@ -809,19 +827,20 @@ int tpm_pcr_read_dev(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | |||
809 | } | 827 | } |
810 | 828 | ||
811 | /** | 829 | /** |
812 | * tpm_is_tpm2 - is the chip a TPM2 chip? | 830 | * tpm_is_tpm2 - do we a have a TPM2 chip? |
813 | * @chip_num: tpm idx # or ANY | 831 | * @chip: a &struct tpm_chip instance, %NULL for the default chip |
814 | * | 832 | * |
815 | * Returns < 0 on error, and 1 or 0 on success depending whether the chip | 833 | * Return: |
816 | * is a TPM2 chip. | 834 | * 1 if we have a TPM2 chip. |
835 | * 0 if we don't have a TPM2 chip. | ||
836 | * A negative number for system errors (errno). | ||
817 | */ | 837 | */ |
818 | int tpm_is_tpm2(u32 chip_num) | 838 | int tpm_is_tpm2(struct tpm_chip *chip) |
819 | { | 839 | { |
820 | struct tpm_chip *chip; | ||
821 | int rc; | 840 | int rc; |
822 | 841 | ||
823 | chip = tpm_chip_find_get(chip_num); | 842 | chip = tpm_chip_find_get(chip); |
824 | if (chip == NULL) | 843 | if (!chip) |
825 | return -ENODEV; | 844 | return -ENODEV; |
826 | 845 | ||
827 | rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0; | 846 | rc = (chip->flags & TPM_CHIP_FLAG_TPM2) != 0; |
@@ -833,23 +852,19 @@ int tpm_is_tpm2(u32 chip_num) | |||
833 | EXPORT_SYMBOL_GPL(tpm_is_tpm2); | 852 | EXPORT_SYMBOL_GPL(tpm_is_tpm2); |
834 | 853 | ||
835 | /** | 854 | /** |
836 | * tpm_pcr_read - read a pcr value | 855 | * tpm_pcr_read - read a PCR value from SHA1 bank |
837 | * @chip_num: tpm idx # or ANY | 856 | * @chip: a &struct tpm_chip instance, %NULL for the default chip |
838 | * @pcr_idx: pcr idx to retrieve | 857 | * @pcr_idx: the PCR to be retrieved |
839 | * @res_buf: TPM_PCR value | 858 | * @res_buf: the value of the PCR |
840 | * size of res_buf is 20 bytes (or NULL if you don't care) | ||
841 | * | 859 | * |
842 | * The TPM driver should be built-in, but for whatever reason it | 860 | * Return: same as with tpm_transmit_cmd() |
843 | * isn't, protect against the chip disappearing, by incrementing | ||
844 | * the module usage count. | ||
845 | */ | 861 | */ |
846 | int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) | 862 | int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) |
847 | { | 863 | { |
848 | struct tpm_chip *chip; | ||
849 | int rc; | 864 | int rc; |
850 | 865 | ||
851 | chip = tpm_chip_find_get(chip_num); | 866 | chip = tpm_chip_find_get(chip); |
852 | if (chip == NULL) | 867 | if (!chip) |
853 | return -ENODEV; | 868 | return -ENODEV; |
854 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 869 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
855 | rc = tpm2_pcr_read(chip, pcr_idx, res_buf); | 870 | rc = tpm2_pcr_read(chip, pcr_idx, res_buf); |
@@ -889,25 +904,26 @@ static int tpm1_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash, | |||
889 | } | 904 | } |
890 | 905 | ||
891 | /** | 906 | /** |
892 | * tpm_pcr_extend - extend pcr value with hash | 907 | * tpm_pcr_extend - extend a PCR value in SHA1 bank. |
893 | * @chip_num: tpm idx # or AN& | 908 | * @chip: a &struct tpm_chip instance, %NULL for the default chip |
894 | * @pcr_idx: pcr idx to extend | 909 | * @pcr_idx: the PCR to be retrieved |
895 | * @hash: hash value used to extend pcr value | 910 | * @hash: the hash value used to extend the PCR value |
896 | * | 911 | * |
897 | * The TPM driver should be built-in, but for whatever reason it | 912 | * Note: with TPM 2.0 extends also those banks with a known digest size to the |
898 | * isn't, protect against the chip disappearing, by incrementing | 913 | * cryto subsystem in order to prevent malicious use of those PCR banks. In the |
899 | * the module usage count. | 914 | * future we should dynamically determine digest sizes. |
915 | * | ||
916 | * Return: same as with tpm_transmit_cmd() | ||
900 | */ | 917 | */ |
901 | int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | 918 | int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash) |
902 | { | 919 | { |
903 | int rc; | 920 | int rc; |
904 | struct tpm_chip *chip; | ||
905 | struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)]; | 921 | struct tpm2_digest digest_list[ARRAY_SIZE(chip->active_banks)]; |
906 | u32 count = 0; | 922 | u32 count = 0; |
907 | int i; | 923 | int i; |
908 | 924 | ||
909 | chip = tpm_chip_find_get(chip_num); | 925 | chip = tpm_chip_find_get(chip); |
910 | if (chip == NULL) | 926 | if (!chip) |
911 | return -ENODEV; | 927 | return -ENODEV; |
912 | 928 | ||
913 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | 929 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
@@ -1019,82 +1035,29 @@ out: | |||
1019 | return rc; | 1035 | return rc; |
1020 | } | 1036 | } |
1021 | 1037 | ||
1022 | int tpm_send(u32 chip_num, void *cmd, size_t buflen) | 1038 | /** |
1039 | * tpm_send - send a TPM command | ||
1040 | * @chip: a &struct tpm_chip instance, %NULL for the default chip | ||
1041 | * @cmd: a TPM command buffer | ||
1042 | * @buflen: the length of the TPM command buffer | ||
1043 | * | ||
1044 | * Return: same as with tpm_transmit_cmd() | ||
1045 | */ | ||
1046 | int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) | ||
1023 | { | 1047 | { |
1024 | struct tpm_chip *chip; | ||
1025 | int rc; | 1048 | int rc; |
1026 | 1049 | ||
1027 | chip = tpm_chip_find_get(chip_num); | 1050 | chip = tpm_chip_find_get(chip); |
1028 | if (chip == NULL) | 1051 | if (!chip) |
1029 | return -ENODEV; | 1052 | return -ENODEV; |
1030 | 1053 | ||
1031 | rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, 0, 0, | 1054 | rc = tpm_transmit_cmd(chip, NULL, cmd, buflen, 0, 0, |
1032 | "attempting tpm_cmd"); | 1055 | "attempting to a send a command"); |
1033 | tpm_put_ops(chip); | 1056 | tpm_put_ops(chip); |
1034 | return rc; | 1057 | return rc; |
1035 | } | 1058 | } |
1036 | EXPORT_SYMBOL_GPL(tpm_send); | 1059 | EXPORT_SYMBOL_GPL(tpm_send); |
1037 | 1060 | ||
1038 | static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, | ||
1039 | bool check_cancel, bool *canceled) | ||
1040 | { | ||
1041 | u8 status = chip->ops->status(chip); | ||
1042 | |||
1043 | *canceled = false; | ||
1044 | if ((status & mask) == mask) | ||
1045 | return true; | ||
1046 | if (check_cancel && chip->ops->req_canceled(chip, status)) { | ||
1047 | *canceled = true; | ||
1048 | return true; | ||
1049 | } | ||
1050 | return false; | ||
1051 | } | ||
1052 | |||
1053 | int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
1054 | wait_queue_head_t *queue, bool check_cancel) | ||
1055 | { | ||
1056 | unsigned long stop; | ||
1057 | long rc; | ||
1058 | u8 status; | ||
1059 | bool canceled = false; | ||
1060 | |||
1061 | /* check current status */ | ||
1062 | status = chip->ops->status(chip); | ||
1063 | if ((status & mask) == mask) | ||
1064 | return 0; | ||
1065 | |||
1066 | stop = jiffies + timeout; | ||
1067 | |||
1068 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { | ||
1069 | again: | ||
1070 | timeout = stop - jiffies; | ||
1071 | if ((long)timeout <= 0) | ||
1072 | return -ETIME; | ||
1073 | rc = wait_event_interruptible_timeout(*queue, | ||
1074 | wait_for_tpm_stat_cond(chip, mask, check_cancel, | ||
1075 | &canceled), | ||
1076 | timeout); | ||
1077 | if (rc > 0) { | ||
1078 | if (canceled) | ||
1079 | return -ECANCELED; | ||
1080 | return 0; | ||
1081 | } | ||
1082 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
1083 | clear_thread_flag(TIF_SIGPENDING); | ||
1084 | goto again; | ||
1085 | } | ||
1086 | } else { | ||
1087 | do { | ||
1088 | tpm_msleep(TPM_TIMEOUT); | ||
1089 | status = chip->ops->status(chip); | ||
1090 | if ((status & mask) == mask) | ||
1091 | return 0; | ||
1092 | } while (time_before(jiffies, stop)); | ||
1093 | } | ||
1094 | return -ETIME; | ||
1095 | } | ||
1096 | EXPORT_SYMBOL_GPL(wait_for_tpm_stat); | ||
1097 | |||
1098 | #define TPM_ORD_SAVESTATE 152 | 1061 | #define TPM_ORD_SAVESTATE 152 |
1099 | #define SAVESTATE_RESULT_SIZE 10 | 1062 | #define SAVESTATE_RESULT_SIZE 10 |
1100 | 1063 | ||
@@ -1187,16 +1150,15 @@ static const struct tpm_input_header tpm_getrandom_header = { | |||
1187 | }; | 1150 | }; |
1188 | 1151 | ||
1189 | /** | 1152 | /** |
1190 | * tpm_get_random() - Get random bytes from the tpm's RNG | 1153 | * tpm_get_random() - get random bytes from the TPM's RNG |
1191 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | 1154 | * @chip: a &struct tpm_chip instance, %NULL for the default chip |
1192 | * @out: destination buffer for the random bytes | 1155 | * @out: destination buffer for the random bytes |
1193 | * @max: the max number of bytes to write to @out | 1156 | * @max: the max number of bytes to write to @out |
1194 | * | 1157 | * |
1195 | * Returns < 0 on error and the number of bytes read on success | 1158 | * Return: same as with tpm_transmit_cmd() |
1196 | */ | 1159 | */ |
1197 | int tpm_get_random(u32 chip_num, u8 *out, size_t max) | 1160 | int tpm_get_random(struct tpm_chip *chip, u8 *out, size_t max) |
1198 | { | 1161 | { |
1199 | struct tpm_chip *chip; | ||
1200 | struct tpm_cmd_t tpm_cmd; | 1162 | struct tpm_cmd_t tpm_cmd; |
1201 | u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA), rlength; | 1163 | u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA), rlength; |
1202 | int err, total = 0, retries = 5; | 1164 | int err, total = 0, retries = 5; |
@@ -1205,8 +1167,8 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) | |||
1205 | if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) | 1167 | if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) |
1206 | return -EINVAL; | 1168 | return -EINVAL; |
1207 | 1169 | ||
1208 | chip = tpm_chip_find_get(chip_num); | 1170 | chip = tpm_chip_find_get(chip); |
1209 | if (chip == NULL) | 1171 | if (!chip) |
1210 | return -ENODEV; | 1172 | return -ENODEV; |
1211 | 1173 | ||
1212 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { | 1174 | if (chip->flags & TPM_CHIP_FLAG_TPM2) { |
@@ -1248,22 +1210,23 @@ int tpm_get_random(u32 chip_num, u8 *out, size_t max) | |||
1248 | EXPORT_SYMBOL_GPL(tpm_get_random); | 1210 | EXPORT_SYMBOL_GPL(tpm_get_random); |
1249 | 1211 | ||
1250 | /** | 1212 | /** |
1251 | * tpm_seal_trusted() - seal a trusted key | 1213 | * tpm_seal_trusted() - seal a trusted key payload |
1252 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | 1214 | * @chip: a &struct tpm_chip instance, %NULL for the default chip |
1253 | * @options: authentication values and other options | 1215 | * @options: authentication values and other options |
1254 | * @payload: the key data in clear and encrypted form | 1216 | * @payload: the key data in clear and encrypted form |
1255 | * | 1217 | * |
1256 | * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips | 1218 | * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in |
1257 | * are supported. | 1219 | * the keyring subsystem. |
1220 | * | ||
1221 | * Return: same as with tpm_transmit_cmd() | ||
1258 | */ | 1222 | */ |
1259 | int tpm_seal_trusted(u32 chip_num, struct trusted_key_payload *payload, | 1223 | int tpm_seal_trusted(struct tpm_chip *chip, struct trusted_key_payload *payload, |
1260 | struct trusted_key_options *options) | 1224 | struct trusted_key_options *options) |
1261 | { | 1225 | { |
1262 | struct tpm_chip *chip; | ||
1263 | int rc; | 1226 | int rc; |
1264 | 1227 | ||
1265 | chip = tpm_chip_find_get(chip_num); | 1228 | chip = tpm_chip_find_get(chip); |
1266 | if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2)) | 1229 | if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) |
1267 | return -ENODEV; | 1230 | return -ENODEV; |
1268 | 1231 | ||
1269 | rc = tpm2_seal_trusted(chip, payload, options); | 1232 | rc = tpm2_seal_trusted(chip, payload, options); |
@@ -1275,21 +1238,23 @@ EXPORT_SYMBOL_GPL(tpm_seal_trusted); | |||
1275 | 1238 | ||
1276 | /** | 1239 | /** |
1277 | * tpm_unseal_trusted() - unseal a trusted key | 1240 | * tpm_unseal_trusted() - unseal a trusted key |
1278 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | 1241 | * @chip: a &struct tpm_chip instance, %NULL for the default chip |
1279 | * @options: authentication values and other options | 1242 | * @options: authentication values and other options |
1280 | * @payload: the key data in clear and encrypted form | 1243 | * @payload: the key data in clear and encrypted form |
1244 | * | ||
1245 | * Note: only TPM 2.0 chip are supported. TPM 1.x implementation is located in | ||
1246 | * the keyring subsystem. | ||
1281 | * | 1247 | * |
1282 | * Returns < 0 on error and 0 on success. At the moment, only TPM 2.0 chips | 1248 | * Return: same as with tpm_transmit_cmd() |
1283 | * are supported. | ||
1284 | */ | 1249 | */ |
1285 | int tpm_unseal_trusted(u32 chip_num, struct trusted_key_payload *payload, | 1250 | int tpm_unseal_trusted(struct tpm_chip *chip, |
1251 | struct trusted_key_payload *payload, | ||
1286 | struct trusted_key_options *options) | 1252 | struct trusted_key_options *options) |
1287 | { | 1253 | { |
1288 | struct tpm_chip *chip; | ||
1289 | int rc; | 1254 | int rc; |
1290 | 1255 | ||
1291 | chip = tpm_chip_find_get(chip_num); | 1256 | chip = tpm_chip_find_get(chip); |
1292 | if (chip == NULL || !(chip->flags & TPM_CHIP_FLAG_TPM2)) | 1257 | if (!chip || !(chip->flags & TPM_CHIP_FLAG_TPM2)) |
1293 | return -ENODEV; | 1258 | return -ENODEV; |
1294 | 1259 | ||
1295 | rc = tpm2_unseal_trusted(chip, payload, options); | 1260 | rc = tpm2_unseal_trusted(chip, payload, options); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 528cffbd49d3..f895fba4e20d 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/delay.h> | 27 | #include <linux/delay.h> |
28 | #include <linux/fs.h> | 28 | #include <linux/fs.h> |
29 | #include <linux/hw_random.h> | ||
29 | #include <linux/mutex.h> | 30 | #include <linux/mutex.h> |
30 | #include <linux/sched.h> | 31 | #include <linux/sched.h> |
31 | #include <linux/platform_device.h> | 32 | #include <linux/platform_device.h> |
@@ -34,6 +35,7 @@ | |||
34 | #include <linux/acpi.h> | 35 | #include <linux/acpi.h> |
35 | #include <linux/cdev.h> | 36 | #include <linux/cdev.h> |
36 | #include <linux/highmem.h> | 37 | #include <linux/highmem.h> |
38 | #include <linux/tpm_eventlog.h> | ||
37 | #include <crypto/hash_info.h> | 39 | #include <crypto/hash_info.h> |
38 | 40 | ||
39 | #ifdef CONFIG_X86 | 41 | #ifdef CONFIG_X86 |
@@ -93,12 +95,17 @@ enum tpm2_structures { | |||
93 | TPM2_ST_SESSIONS = 0x8002, | 95 | TPM2_ST_SESSIONS = 0x8002, |
94 | }; | 96 | }; |
95 | 97 | ||
98 | /* Indicates from what layer of the software stack the error comes from */ | ||
99 | #define TSS2_RC_LAYER_SHIFT 16 | ||
100 | #define TSS2_RESMGR_TPM_RC_LAYER (11 << TSS2_RC_LAYER_SHIFT) | ||
101 | |||
96 | enum tpm2_return_codes { | 102 | enum tpm2_return_codes { |
97 | TPM2_RC_SUCCESS = 0x0000, | 103 | TPM2_RC_SUCCESS = 0x0000, |
98 | TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ | 104 | TPM2_RC_HASH = 0x0083, /* RC_FMT1 */ |
99 | TPM2_RC_HANDLE = 0x008B, | 105 | TPM2_RC_HANDLE = 0x008B, |
100 | TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ | 106 | TPM2_RC_INITIALIZE = 0x0100, /* RC_VER1 */ |
101 | TPM2_RC_DISABLED = 0x0120, | 107 | TPM2_RC_DISABLED = 0x0120, |
108 | TPM2_RC_COMMAND_CODE = 0x0143, | ||
102 | TPM2_RC_TESTING = 0x090A, /* RC_WARN */ | 109 | TPM2_RC_TESTING = 0x090A, /* RC_WARN */ |
103 | TPM2_RC_REFERENCE_H0 = 0x0910, | 110 | TPM2_RC_REFERENCE_H0 = 0x0910, |
104 | }; | 111 | }; |
@@ -210,6 +217,9 @@ struct tpm_chip { | |||
210 | int dev_num; /* /dev/tpm# */ | 217 | int dev_num; /* /dev/tpm# */ |
211 | unsigned long is_open; /* only one allowed */ | 218 | unsigned long is_open; /* only one allowed */ |
212 | 219 | ||
220 | char hwrng_name[64]; | ||
221 | struct hwrng hwrng; | ||
222 | |||
213 | struct mutex tpm_mutex; /* tpm is processing */ | 223 | struct mutex tpm_mutex; /* tpm is processing */ |
214 | 224 | ||
215 | unsigned long timeout_a; /* jiffies */ | 225 | unsigned long timeout_a; /* jiffies */ |
@@ -385,10 +395,6 @@ struct tpm_cmd_t { | |||
385 | tpm_cmd_params params; | 395 | tpm_cmd_params params; |
386 | } __packed; | 396 | } __packed; |
387 | 397 | ||
388 | struct tpm2_digest { | ||
389 | u16 alg_id; | ||
390 | u8 digest[SHA512_DIGEST_SIZE]; | ||
391 | } __packed; | ||
392 | 398 | ||
393 | /* A string buffer type for constructing TPM commands. This is based on the | 399 | /* A string buffer type for constructing TPM commands. This is based on the |
394 | * ideas of string buffer code in security/keys/trusted.h but is heap based | 400 | * ideas of string buffer code in security/keys/trusted.h but is heap based |
@@ -512,16 +518,14 @@ int tpm_do_selftest(struct tpm_chip *chip); | |||
512 | unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); | 518 | unsigned long tpm_calc_ordinal_duration(struct tpm_chip *chip, u32 ordinal); |
513 | int tpm_pm_suspend(struct device *dev); | 519 | int tpm_pm_suspend(struct device *dev); |
514 | int tpm_pm_resume(struct device *dev); | 520 | int tpm_pm_resume(struct device *dev); |
515 | int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
516 | wait_queue_head_t *queue, bool check_cancel); | ||
517 | 521 | ||
518 | static inline void tpm_msleep(unsigned int delay_msec) | 522 | static inline void tpm_msleep(unsigned int delay_msec) |
519 | { | 523 | { |
520 | usleep_range(delay_msec * 1000, | 524 | usleep_range((delay_msec * 1000) - TPM_TIMEOUT_RANGE_US, |
521 | (delay_msec * 1000) + TPM_TIMEOUT_RANGE_US); | 525 | delay_msec * 1000); |
522 | }; | 526 | }; |
523 | 527 | ||
524 | struct tpm_chip *tpm_chip_find_get(int chip_num); | 528 | struct tpm_chip *tpm_chip_find_get(struct tpm_chip *chip); |
525 | __must_check int tpm_try_get_ops(struct tpm_chip *chip); | 529 | __must_check int tpm_try_get_ops(struct tpm_chip *chip); |
526 | void tpm_put_ops(struct tpm_chip *chip); | 530 | void tpm_put_ops(struct tpm_chip *chip); |
527 | 531 | ||
@@ -575,4 +579,34 @@ int tpm2_prepare_space(struct tpm_chip *chip, struct tpm_space *space, u32 cc, | |||
575 | u8 *cmd); | 579 | u8 *cmd); |
576 | int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, | 580 | int tpm2_commit_space(struct tpm_chip *chip, struct tpm_space *space, |
577 | u32 cc, u8 *buf, size_t *bufsiz); | 581 | u32 cc, u8 *buf, size_t *bufsiz); |
582 | |||
583 | extern const struct seq_operations tpm2_binary_b_measurements_seqops; | ||
584 | |||
585 | #if defined(CONFIG_ACPI) | ||
586 | int tpm_read_log_acpi(struct tpm_chip *chip); | ||
587 | #else | ||
588 | static inline int tpm_read_log_acpi(struct tpm_chip *chip) | ||
589 | { | ||
590 | return -ENODEV; | ||
591 | } | ||
592 | #endif | ||
593 | #if defined(CONFIG_OF) | ||
594 | int tpm_read_log_of(struct tpm_chip *chip); | ||
595 | #else | ||
596 | static inline int tpm_read_log_of(struct tpm_chip *chip) | ||
597 | { | ||
598 | return -ENODEV; | ||
599 | } | ||
600 | #endif | ||
601 | #if defined(CONFIG_EFI) | ||
602 | int tpm_read_log_efi(struct tpm_chip *chip); | ||
603 | #else | ||
604 | static inline int tpm_read_log_efi(struct tpm_chip *chip) | ||
605 | { | ||
606 | return -ENODEV; | ||
607 | } | ||
608 | #endif | ||
609 | |||
610 | int tpm_bios_log_setup(struct tpm_chip *chip); | ||
611 | void tpm_bios_log_teardown(struct tpm_chip *chip); | ||
578 | #endif | 612 | #endif |
diff --git a/drivers/char/tpm/tpm1_eventlog.c b/drivers/char/tpm/tpm1_eventlog.c index 9a8605e500b5..add798bd69d0 100644 --- a/drivers/char/tpm/tpm1_eventlog.c +++ b/drivers/char/tpm/tpm1_eventlog.c | |||
@@ -21,13 +21,14 @@ | |||
21 | */ | 21 | */ |
22 | 22 | ||
23 | #include <linux/seq_file.h> | 23 | #include <linux/seq_file.h> |
24 | #include <linux/efi.h> | ||
24 | #include <linux/fs.h> | 25 | #include <linux/fs.h> |
25 | #include <linux/security.h> | 26 | #include <linux/security.h> |
26 | #include <linux/module.h> | 27 | #include <linux/module.h> |
27 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/tpm_eventlog.h> | ||
28 | 30 | ||
29 | #include "tpm.h" | 31 | #include "tpm.h" |
30 | #include "tpm_eventlog.h" | ||
31 | 32 | ||
32 | 33 | ||
33 | static const char* tcpa_event_type_strings[] = { | 34 | static const char* tcpa_event_type_strings[] = { |
@@ -371,6 +372,10 @@ static int tpm_read_log(struct tpm_chip *chip) | |||
371 | if (rc != -ENODEV) | 372 | if (rc != -ENODEV) |
372 | return rc; | 373 | return rc; |
373 | 374 | ||
375 | rc = tpm_read_log_efi(chip); | ||
376 | if (rc != -ENODEV) | ||
377 | return rc; | ||
378 | |||
374 | return tpm_read_log_of(chip); | 379 | return tpm_read_log_of(chip); |
375 | } | 380 | } |
376 | 381 | ||
@@ -388,11 +393,13 @@ int tpm_bios_log_setup(struct tpm_chip *chip) | |||
388 | { | 393 | { |
389 | const char *name = dev_name(&chip->dev); | 394 | const char *name = dev_name(&chip->dev); |
390 | unsigned int cnt; | 395 | unsigned int cnt; |
396 | int log_version; | ||
391 | int rc = 0; | 397 | int rc = 0; |
392 | 398 | ||
393 | rc = tpm_read_log(chip); | 399 | rc = tpm_read_log(chip); |
394 | if (rc) | 400 | if (rc < 0) |
395 | return rc; | 401 | return rc; |
402 | log_version = rc; | ||
396 | 403 | ||
397 | cnt = 0; | 404 | cnt = 0; |
398 | chip->bios_dir[cnt] = securityfs_create_dir(name, NULL); | 405 | chip->bios_dir[cnt] = securityfs_create_dir(name, NULL); |
@@ -404,7 +411,7 @@ int tpm_bios_log_setup(struct tpm_chip *chip) | |||
404 | cnt++; | 411 | cnt++; |
405 | 412 | ||
406 | chip->bin_log_seqops.chip = chip; | 413 | chip->bin_log_seqops.chip = chip; |
407 | if (chip->flags & TPM_CHIP_FLAG_TPM2) | 414 | if (log_version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) |
408 | chip->bin_log_seqops.seqops = | 415 | chip->bin_log_seqops.seqops = |
409 | &tpm2_binary_b_measurements_seqops; | 416 | &tpm2_binary_b_measurements_seqops; |
410 | else | 417 | else |
diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index f40d20671a78..c17e75348a99 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c | |||
@@ -849,28 +849,26 @@ static const struct tpm_input_header tpm2_selftest_header = { | |||
849 | static int tpm2_do_selftest(struct tpm_chip *chip) | 849 | static int tpm2_do_selftest(struct tpm_chip *chip) |
850 | { | 850 | { |
851 | int rc; | 851 | int rc; |
852 | unsigned int delay_msec = 20; | 852 | unsigned int delay_msec = 10; |
853 | long duration; | 853 | long duration; |
854 | struct tpm2_cmd cmd; | 854 | struct tpm2_cmd cmd; |
855 | 855 | ||
856 | duration = jiffies_to_msecs( | 856 | duration = jiffies_to_msecs( |
857 | tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST)); | 857 | tpm2_calc_ordinal_duration(chip, TPM2_CC_SELF_TEST)); |
858 | 858 | ||
859 | while (duration > 0) { | 859 | while (1) { |
860 | cmd.header.in = tpm2_selftest_header; | 860 | cmd.header.in = tpm2_selftest_header; |
861 | cmd.params.selftest_in.full_test = 0; | 861 | cmd.params.selftest_in.full_test = 0; |
862 | 862 | ||
863 | rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, | 863 | rc = tpm_transmit_cmd(chip, NULL, &cmd, TPM2_SELF_TEST_IN_SIZE, |
864 | 0, 0, "continue selftest"); | 864 | 0, 0, "continue selftest"); |
865 | 865 | ||
866 | if (rc != TPM2_RC_TESTING) | 866 | if (rc != TPM2_RC_TESTING || delay_msec >= duration) |
867 | break; | 867 | break; |
868 | 868 | ||
869 | tpm_msleep(delay_msec); | 869 | /* wait longer than before */ |
870 | duration -= delay_msec; | ||
871 | |||
872 | /* wait longer the next round */ | ||
873 | delay_msec *= 2; | 870 | delay_msec *= 2; |
871 | tpm_msleep(delay_msec); | ||
874 | } | 872 | } |
875 | 873 | ||
876 | return rc; | 874 | return rc; |
diff --git a/drivers/char/tpm/tpm2_eventlog.c b/drivers/char/tpm/tpm2_eventlog.c index 34a8afa69138..1ce4411292ba 100644 --- a/drivers/char/tpm/tpm2_eventlog.c +++ b/drivers/char/tpm/tpm2_eventlog.c | |||
@@ -21,9 +21,9 @@ | |||
21 | #include <linux/security.h> | 21 | #include <linux/security.h> |
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/tpm_eventlog.h> | ||
24 | 25 | ||
25 | #include "tpm.h" | 26 | #include "tpm.h" |
26 | #include "tpm_eventlog.h" | ||
27 | 27 | ||
28 | /* | 28 | /* |
29 | * calc_tpm2_event_size() - calculate the event size, where event | 29 | * calc_tpm2_event_size() - calculate the event size, where event |
diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_eventlog_acpi.c index 169edf3ce86d..66f19e93c216 100644 --- a/drivers/char/tpm/tpm_acpi.c +++ b/drivers/char/tpm/tpm_eventlog_acpi.c | |||
@@ -25,9 +25,9 @@ | |||
25 | #include <linux/module.h> | 25 | #include <linux/module.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/acpi.h> | 27 | #include <linux/acpi.h> |
28 | #include <linux/tpm_eventlog.h> | ||
28 | 29 | ||
29 | #include "tpm.h" | 30 | #include "tpm.h" |
30 | #include "tpm_eventlog.h" | ||
31 | 31 | ||
32 | struct acpi_tcpa { | 32 | struct acpi_tcpa { |
33 | struct acpi_table_header hdr; | 33 | struct acpi_table_header hdr; |
@@ -102,7 +102,7 @@ int tpm_read_log_acpi(struct tpm_chip *chip) | |||
102 | memcpy_fromio(log->bios_event_log, virt, len); | 102 | memcpy_fromio(log->bios_event_log, virt, len); |
103 | 103 | ||
104 | acpi_os_unmap_iomem(virt, len); | 104 | acpi_os_unmap_iomem(virt, len); |
105 | return 0; | 105 | return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; |
106 | 106 | ||
107 | err: | 107 | err: |
108 | kfree(log->bios_event_log); | 108 | kfree(log->bios_event_log); |
diff --git a/drivers/char/tpm/tpm_eventlog_efi.c b/drivers/char/tpm/tpm_eventlog_efi.c new file mode 100644 index 000000000000..e3f9ffd341d2 --- /dev/null +++ b/drivers/char/tpm/tpm_eventlog_efi.c | |||
@@ -0,0 +1,66 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Google | ||
3 | * | ||
4 | * Authors: | ||
5 | * Thiebaud Weksteen <tweek@google.com> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or | ||
8 | * modify it under the terms of the GNU General Public License | ||
9 | * as published by the Free Software Foundation; either version | ||
10 | * 2 of the License, or (at your option) any later version. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/efi.h> | ||
15 | #include <linux/tpm_eventlog.h> | ||
16 | |||
17 | #include "tpm.h" | ||
18 | |||
19 | /* read binary bios log from EFI configuration table */ | ||
20 | int tpm_read_log_efi(struct tpm_chip *chip) | ||
21 | { | ||
22 | |||
23 | struct linux_efi_tpm_eventlog *log_tbl; | ||
24 | struct tpm_bios_log *log; | ||
25 | u32 log_size; | ||
26 | u8 tpm_log_version; | ||
27 | |||
28 | if (!(chip->flags & TPM_CHIP_FLAG_TPM2)) | ||
29 | return -ENODEV; | ||
30 | |||
31 | if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) | ||
32 | return -ENODEV; | ||
33 | |||
34 | log = &chip->log; | ||
35 | |||
36 | log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl), MEMREMAP_WB); | ||
37 | if (!log_tbl) { | ||
38 | pr_err("Could not map UEFI TPM log table !\n"); | ||
39 | return -ENOMEM; | ||
40 | } | ||
41 | |||
42 | log_size = log_tbl->size; | ||
43 | memunmap(log_tbl); | ||
44 | |||
45 | log_tbl = memremap(efi.tpm_log, sizeof(*log_tbl) + log_size, | ||
46 | MEMREMAP_WB); | ||
47 | if (!log_tbl) { | ||
48 | pr_err("Could not map UEFI TPM log table payload!\n"); | ||
49 | return -ENOMEM; | ||
50 | } | ||
51 | |||
52 | /* malloc EventLog space */ | ||
53 | log->bios_event_log = kmalloc(log_size, GFP_KERNEL); | ||
54 | if (!log->bios_event_log) | ||
55 | goto err_memunmap; | ||
56 | memcpy(log->bios_event_log, log_tbl->log, log_size); | ||
57 | log->bios_event_log_end = log->bios_event_log + log_size; | ||
58 | |||
59 | tpm_log_version = log_tbl->version; | ||
60 | memunmap(log_tbl); | ||
61 | return tpm_log_version; | ||
62 | |||
63 | err_memunmap: | ||
64 | memunmap(log_tbl); | ||
65 | return -ENOMEM; | ||
66 | } | ||
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_eventlog_of.c index aadb7f464076..96fd5646f866 100644 --- a/drivers/char/tpm/tpm_of.c +++ b/drivers/char/tpm/tpm_eventlog_of.c | |||
@@ -17,9 +17,9 @@ | |||
17 | 17 | ||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/tpm_eventlog.h> | ||
20 | 21 | ||
21 | #include "tpm.h" | 22 | #include "tpm.h" |
22 | #include "tpm_eventlog.h" | ||
23 | 23 | ||
24 | int tpm_read_log_of(struct tpm_chip *chip) | 24 | int tpm_read_log_of(struct tpm_chip *chip) |
25 | { | 25 | { |
@@ -76,5 +76,7 @@ int tpm_read_log_of(struct tpm_chip *chip) | |||
76 | 76 | ||
77 | memcpy(log->bios_event_log, __va(base), size); | 77 | memcpy(log->bios_event_log, __va(base), size); |
78 | 78 | ||
79 | return 0; | 79 | if (chip->flags & TPM_CHIP_FLAG_TPM2) |
80 | return EFI_TCG2_EVENT_LOG_FORMAT_TCG_2; | ||
81 | return EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; | ||
80 | } | 82 | } |
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c index 79d6bbb58e39..c1dd39eaaeeb 100644 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ b/drivers/char/tpm/tpm_i2c_infineon.c | |||
@@ -665,9 +665,9 @@ out_err: | |||
665 | } | 665 | } |
666 | 666 | ||
667 | static const struct i2c_device_id tpm_tis_i2c_table[] = { | 667 | static const struct i2c_device_id tpm_tis_i2c_table[] = { |
668 | {"tpm_i2c_infineon", 0}, | 668 | {"tpm_i2c_infineon"}, |
669 | {"slb9635tt", 0}, | 669 | {"slb9635tt"}, |
670 | {"slb9645tt", 1}, | 670 | {"slb9645tt"}, |
671 | {}, | 671 | {}, |
672 | }; | 672 | }; |
673 | 673 | ||
@@ -675,24 +675,9 @@ MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table); | |||
675 | 675 | ||
676 | #ifdef CONFIG_OF | 676 | #ifdef CONFIG_OF |
677 | static const struct of_device_id tpm_tis_i2c_of_match[] = { | 677 | static const struct of_device_id tpm_tis_i2c_of_match[] = { |
678 | { | 678 | {.compatible = "infineon,tpm_i2c_infineon"}, |
679 | .name = "tpm_i2c_infineon", | 679 | {.compatible = "infineon,slb9635tt"}, |
680 | .type = "tpm", | 680 | {.compatible = "infineon,slb9645tt"}, |
681 | .compatible = "infineon,tpm_i2c_infineon", | ||
682 | .data = (void *)0 | ||
683 | }, | ||
684 | { | ||
685 | .name = "slb9635tt", | ||
686 | .type = "tpm", | ||
687 | .compatible = "infineon,slb9635tt", | ||
688 | .data = (void *)0 | ||
689 | }, | ||
690 | { | ||
691 | .name = "slb9645tt", | ||
692 | .type = "tpm", | ||
693 | .compatible = "infineon,slb9645tt", | ||
694 | .data = (void *)1 | ||
695 | }, | ||
696 | {}, | 681 | {}, |
697 | }; | 682 | }; |
698 | MODULE_DEVICE_TABLE(of, tpm_tis_i2c_of_match); | 683 | MODULE_DEVICE_TABLE(of, tpm_tis_i2c_of_match); |
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index e2d1055fb814..f08949a5f678 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
@@ -133,93 +133,14 @@ static int check_acpi_tpm2(struct device *dev) | |||
133 | } | 133 | } |
134 | #endif | 134 | #endif |
135 | 135 | ||
136 | #ifdef CONFIG_X86 | ||
137 | #define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 | ||
138 | #define ILB_REMAP_SIZE 0x100 | ||
139 | #define LPC_CNTRL_REG_OFFSET 0x84 | ||
140 | #define LPC_CLKRUN_EN (1 << 2) | ||
141 | |||
142 | static void __iomem *ilb_base_addr; | ||
143 | |||
144 | static inline bool is_bsw(void) | ||
145 | { | ||
146 | return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); | ||
147 | } | ||
148 | |||
149 | /** | ||
150 | * tpm_platform_begin_xfer() - clear LPC CLKRUN_EN i.e. clocks will be running | ||
151 | */ | ||
152 | static void tpm_platform_begin_xfer(void) | ||
153 | { | ||
154 | u32 clkrun_val; | ||
155 | |||
156 | if (!is_bsw()) | ||
157 | return; | ||
158 | |||
159 | clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); | ||
160 | |||
161 | /* Disable LPC CLKRUN# */ | ||
162 | clkrun_val &= ~LPC_CLKRUN_EN; | ||
163 | iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); | ||
164 | |||
165 | /* | ||
166 | * Write any random value on port 0x80 which is on LPC, to make | ||
167 | * sure LPC clock is running before sending any TPM command. | ||
168 | */ | ||
169 | outb(0xCC, 0x80); | ||
170 | |||
171 | } | ||
172 | |||
173 | /** | ||
174 | * tpm_platform_end_xfer() - set LPC CLKRUN_EN i.e. clocks can be turned off | ||
175 | */ | ||
176 | static void tpm_platform_end_xfer(void) | ||
177 | { | ||
178 | u32 clkrun_val; | ||
179 | |||
180 | if (!is_bsw()) | ||
181 | return; | ||
182 | |||
183 | clkrun_val = ioread32(ilb_base_addr + LPC_CNTRL_REG_OFFSET); | ||
184 | |||
185 | /* Enable LPC CLKRUN# */ | ||
186 | clkrun_val |= LPC_CLKRUN_EN; | ||
187 | iowrite32(clkrun_val, ilb_base_addr + LPC_CNTRL_REG_OFFSET); | ||
188 | |||
189 | /* | ||
190 | * Write any random value on port 0x80 which is on LPC, to make | ||
191 | * sure LPC clock is running before sending any TPM command. | ||
192 | */ | ||
193 | outb(0xCC, 0x80); | ||
194 | |||
195 | } | ||
196 | #else | ||
197 | static inline bool is_bsw(void) | ||
198 | { | ||
199 | return false; | ||
200 | } | ||
201 | |||
202 | static void tpm_platform_begin_xfer(void) | ||
203 | { | ||
204 | } | ||
205 | |||
206 | static void tpm_platform_end_xfer(void) | ||
207 | { | ||
208 | } | ||
209 | #endif | ||
210 | |||
211 | static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, | 136 | static int tpm_tcg_read_bytes(struct tpm_tis_data *data, u32 addr, u16 len, |
212 | u8 *result) | 137 | u8 *result) |
213 | { | 138 | { |
214 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 139 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
215 | 140 | ||
216 | tpm_platform_begin_xfer(); | ||
217 | |||
218 | while (len--) | 141 | while (len--) |
219 | *result++ = ioread8(phy->iobase + addr); | 142 | *result++ = ioread8(phy->iobase + addr); |
220 | 143 | ||
221 | tpm_platform_end_xfer(); | ||
222 | |||
223 | return 0; | 144 | return 0; |
224 | } | 145 | } |
225 | 146 | ||
@@ -228,13 +149,9 @@ static int tpm_tcg_write_bytes(struct tpm_tis_data *data, u32 addr, u16 len, | |||
228 | { | 149 | { |
229 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 150 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
230 | 151 | ||
231 | tpm_platform_begin_xfer(); | ||
232 | |||
233 | while (len--) | 152 | while (len--) |
234 | iowrite8(*value++, phy->iobase + addr); | 153 | iowrite8(*value++, phy->iobase + addr); |
235 | 154 | ||
236 | tpm_platform_end_xfer(); | ||
237 | |||
238 | return 0; | 155 | return 0; |
239 | } | 156 | } |
240 | 157 | ||
@@ -242,12 +159,8 @@ static int tpm_tcg_read16(struct tpm_tis_data *data, u32 addr, u16 *result) | |||
242 | { | 159 | { |
243 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 160 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
244 | 161 | ||
245 | tpm_platform_begin_xfer(); | ||
246 | |||
247 | *result = ioread16(phy->iobase + addr); | 162 | *result = ioread16(phy->iobase + addr); |
248 | 163 | ||
249 | tpm_platform_end_xfer(); | ||
250 | |||
251 | return 0; | 164 | return 0; |
252 | } | 165 | } |
253 | 166 | ||
@@ -255,12 +168,8 @@ static int tpm_tcg_read32(struct tpm_tis_data *data, u32 addr, u32 *result) | |||
255 | { | 168 | { |
256 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 169 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
257 | 170 | ||
258 | tpm_platform_begin_xfer(); | ||
259 | |||
260 | *result = ioread32(phy->iobase + addr); | 171 | *result = ioread32(phy->iobase + addr); |
261 | 172 | ||
262 | tpm_platform_end_xfer(); | ||
263 | |||
264 | return 0; | 173 | return 0; |
265 | } | 174 | } |
266 | 175 | ||
@@ -268,12 +177,8 @@ static int tpm_tcg_write32(struct tpm_tis_data *data, u32 addr, u32 value) | |||
268 | { | 177 | { |
269 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); | 178 | struct tpm_tis_tcg_phy *phy = to_tpm_tis_tcg_phy(data); |
270 | 179 | ||
271 | tpm_platform_begin_xfer(); | ||
272 | |||
273 | iowrite32(value, phy->iobase + addr); | 180 | iowrite32(value, phy->iobase + addr); |
274 | 181 | ||
275 | tpm_platform_end_xfer(); | ||
276 | |||
277 | return 0; | 182 | return 0; |
278 | } | 183 | } |
279 | 184 | ||
@@ -461,11 +366,6 @@ static int __init init_tis(void) | |||
461 | if (rc) | 366 | if (rc) |
462 | goto err_force; | 367 | goto err_force; |
463 | 368 | ||
464 | #ifdef CONFIG_X86 | ||
465 | if (is_bsw()) | ||
466 | ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, | ||
467 | ILB_REMAP_SIZE); | ||
468 | #endif | ||
469 | rc = platform_driver_register(&tis_drv); | 369 | rc = platform_driver_register(&tis_drv); |
470 | if (rc) | 370 | if (rc) |
471 | goto err_platform; | 371 | goto err_platform; |
@@ -484,10 +384,6 @@ err_pnp: | |||
484 | err_platform: | 384 | err_platform: |
485 | if (force_pdev) | 385 | if (force_pdev) |
486 | platform_device_unregister(force_pdev); | 386 | platform_device_unregister(force_pdev); |
487 | #ifdef CONFIG_X86 | ||
488 | if (is_bsw()) | ||
489 | iounmap(ilb_base_addr); | ||
490 | #endif | ||
491 | err_force: | 387 | err_force: |
492 | return rc; | 388 | return rc; |
493 | } | 389 | } |
@@ -497,10 +393,6 @@ static void __exit cleanup_tis(void) | |||
497 | pnp_unregister_driver(&tis_pnp_driver); | 393 | pnp_unregister_driver(&tis_pnp_driver); |
498 | platform_driver_unregister(&tis_drv); | 394 | platform_driver_unregister(&tis_drv); |
499 | 395 | ||
500 | #ifdef CONFIG_X86 | ||
501 | if (is_bsw()) | ||
502 | iounmap(ilb_base_addr); | ||
503 | #endif | ||
504 | if (force_pdev) | 396 | if (force_pdev) |
505 | platform_device_unregister(force_pdev); | 397 | platform_device_unregister(force_pdev); |
506 | } | 398 | } |
diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c index fdde971bc810..183a5f54d875 100644 --- a/drivers/char/tpm/tpm_tis_core.c +++ b/drivers/char/tpm/tpm_tis_core.c | |||
@@ -31,6 +31,74 @@ | |||
31 | #include "tpm.h" | 31 | #include "tpm.h" |
32 | #include "tpm_tis_core.h" | 32 | #include "tpm_tis_core.h" |
33 | 33 | ||
34 | /* This is a polling delay to check for status and burstcount. | ||
35 | * As per ddwg input, expectation is that status check and burstcount | ||
36 | * check should return within few usecs. | ||
37 | */ | ||
38 | #define TPM_POLL_SLEEP 1 /* msec */ | ||
39 | |||
40 | static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value); | ||
41 | |||
42 | static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, | ||
43 | bool check_cancel, bool *canceled) | ||
44 | { | ||
45 | u8 status = chip->ops->status(chip); | ||
46 | |||
47 | *canceled = false; | ||
48 | if ((status & mask) == mask) | ||
49 | return true; | ||
50 | if (check_cancel && chip->ops->req_canceled(chip, status)) { | ||
51 | *canceled = true; | ||
52 | return true; | ||
53 | } | ||
54 | return false; | ||
55 | } | ||
56 | |||
57 | static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, | ||
58 | unsigned long timeout, wait_queue_head_t *queue, | ||
59 | bool check_cancel) | ||
60 | { | ||
61 | unsigned long stop; | ||
62 | long rc; | ||
63 | u8 status; | ||
64 | bool canceled = false; | ||
65 | |||
66 | /* check current status */ | ||
67 | status = chip->ops->status(chip); | ||
68 | if ((status & mask) == mask) | ||
69 | return 0; | ||
70 | |||
71 | stop = jiffies + timeout; | ||
72 | |||
73 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { | ||
74 | again: | ||
75 | timeout = stop - jiffies; | ||
76 | if ((long)timeout <= 0) | ||
77 | return -ETIME; | ||
78 | rc = wait_event_interruptible_timeout(*queue, | ||
79 | wait_for_tpm_stat_cond(chip, mask, check_cancel, | ||
80 | &canceled), | ||
81 | timeout); | ||
82 | if (rc > 0) { | ||
83 | if (canceled) | ||
84 | return -ECANCELED; | ||
85 | return 0; | ||
86 | } | ||
87 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
88 | clear_thread_flag(TIF_SIGPENDING); | ||
89 | goto again; | ||
90 | } | ||
91 | } else { | ||
92 | do { | ||
93 | tpm_msleep(TPM_POLL_SLEEP); | ||
94 | status = chip->ops->status(chip); | ||
95 | if ((status & mask) == mask) | ||
96 | return 0; | ||
97 | } while (time_before(jiffies, stop)); | ||
98 | } | ||
99 | return -ETIME; | ||
100 | } | ||
101 | |||
34 | /* Before we attempt to access the TPM we must see that the valid bit is set. | 102 | /* Before we attempt to access the TPM we must see that the valid bit is set. |
35 | * The specification says that this bit is 0 at reset and remains 0 until the | 103 | * The specification says that this bit is 0 at reset and remains 0 until the |
36 | * 'TPM has gone through its self test and initialization and has established | 104 | * 'TPM has gone through its self test and initialization and has established |
@@ -164,7 +232,7 @@ static int get_burstcount(struct tpm_chip *chip) | |||
164 | burstcnt = (value >> 8) & 0xFFFF; | 232 | burstcnt = (value >> 8) & 0xFFFF; |
165 | if (burstcnt) | 233 | if (burstcnt) |
166 | return burstcnt; | 234 | return burstcnt; |
167 | tpm_msleep(TPM_TIMEOUT); | 235 | tpm_msleep(TPM_POLL_SLEEP); |
168 | } while (time_before(jiffies, stop)); | 236 | } while (time_before(jiffies, stop)); |
169 | return -EBUSY; | 237 | return -EBUSY; |
170 | } | 238 | } |
@@ -421,19 +489,28 @@ static bool tpm_tis_update_timeouts(struct tpm_chip *chip, | |||
421 | int i, rc; | 489 | int i, rc; |
422 | u32 did_vid; | 490 | u32 did_vid; |
423 | 491 | ||
492 | if (chip->ops->clk_enable != NULL) | ||
493 | chip->ops->clk_enable(chip, true); | ||
494 | |||
424 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); | 495 | rc = tpm_tis_read32(priv, TPM_DID_VID(0), &did_vid); |
425 | if (rc < 0) | 496 | if (rc < 0) |
426 | return rc; | 497 | goto out; |
427 | 498 | ||
428 | for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { | 499 | for (i = 0; i != ARRAY_SIZE(vendor_timeout_overrides); i++) { |
429 | if (vendor_timeout_overrides[i].did_vid != did_vid) | 500 | if (vendor_timeout_overrides[i].did_vid != did_vid) |
430 | continue; | 501 | continue; |
431 | memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, | 502 | memcpy(timeout_cap, vendor_timeout_overrides[i].timeout_us, |
432 | sizeof(vendor_timeout_overrides[i].timeout_us)); | 503 | sizeof(vendor_timeout_overrides[i].timeout_us)); |
433 | return true; | 504 | rc = true; |
434 | } | 505 | } |
435 | 506 | ||
436 | return false; | 507 | rc = false; |
508 | |||
509 | out: | ||
510 | if (chip->ops->clk_enable != NULL) | ||
511 | chip->ops->clk_enable(chip, false); | ||
512 | |||
513 | return rc; | ||
437 | } | 514 | } |
438 | 515 | ||
439 | /* | 516 | /* |
@@ -653,14 +730,73 @@ void tpm_tis_remove(struct tpm_chip *chip) | |||
653 | u32 interrupt; | 730 | u32 interrupt; |
654 | int rc; | 731 | int rc; |
655 | 732 | ||
733 | tpm_tis_clkrun_enable(chip, true); | ||
734 | |||
656 | rc = tpm_tis_read32(priv, reg, &interrupt); | 735 | rc = tpm_tis_read32(priv, reg, &interrupt); |
657 | if (rc < 0) | 736 | if (rc < 0) |
658 | interrupt = 0; | 737 | interrupt = 0; |
659 | 738 | ||
660 | tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt); | 739 | tpm_tis_write32(priv, reg, ~TPM_GLOBAL_INT_ENABLE & interrupt); |
740 | |||
741 | tpm_tis_clkrun_enable(chip, false); | ||
742 | |||
743 | if (priv->ilb_base_addr) | ||
744 | iounmap(priv->ilb_base_addr); | ||
661 | } | 745 | } |
662 | EXPORT_SYMBOL_GPL(tpm_tis_remove); | 746 | EXPORT_SYMBOL_GPL(tpm_tis_remove); |
663 | 747 | ||
748 | /** | ||
749 | * tpm_tis_clkrun_enable() - Keep clkrun protocol disabled for entire duration | ||
750 | * of a single TPM command | ||
751 | * @chip: TPM chip to use | ||
752 | * @value: 1 - Disable CLKRUN protocol, so that clocks are free running | ||
753 | * 0 - Enable CLKRUN protocol | ||
754 | * Call this function directly in tpm_tis_remove() in error or driver removal | ||
755 | * path, since the chip->ops is set to NULL in tpm_chip_unregister(). | ||
756 | */ | ||
757 | static void tpm_tis_clkrun_enable(struct tpm_chip *chip, bool value) | ||
758 | { | ||
759 | struct tpm_tis_data *data = dev_get_drvdata(&chip->dev); | ||
760 | u32 clkrun_val; | ||
761 | |||
762 | if (!IS_ENABLED(CONFIG_X86) || !is_bsw() || | ||
763 | !data->ilb_base_addr) | ||
764 | return; | ||
765 | |||
766 | if (value) { | ||
767 | data->clkrun_enabled++; | ||
768 | if (data->clkrun_enabled > 1) | ||
769 | return; | ||
770 | clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); | ||
771 | |||
772 | /* Disable LPC CLKRUN# */ | ||
773 | clkrun_val &= ~LPC_CLKRUN_EN; | ||
774 | iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); | ||
775 | |||
776 | /* | ||
777 | * Write any random value on port 0x80 which is on LPC, to make | ||
778 | * sure LPC clock is running before sending any TPM command. | ||
779 | */ | ||
780 | outb(0xCC, 0x80); | ||
781 | } else { | ||
782 | data->clkrun_enabled--; | ||
783 | if (data->clkrun_enabled) | ||
784 | return; | ||
785 | |||
786 | clkrun_val = ioread32(data->ilb_base_addr + LPC_CNTRL_OFFSET); | ||
787 | |||
788 | /* Enable LPC CLKRUN# */ | ||
789 | clkrun_val |= LPC_CLKRUN_EN; | ||
790 | iowrite32(clkrun_val, data->ilb_base_addr + LPC_CNTRL_OFFSET); | ||
791 | |||
792 | /* | ||
793 | * Write any random value on port 0x80 which is on LPC, to make | ||
794 | * sure LPC clock is running before sending any TPM command. | ||
795 | */ | ||
796 | outb(0xCC, 0x80); | ||
797 | } | ||
798 | } | ||
799 | |||
664 | static const struct tpm_class_ops tpm_tis = { | 800 | static const struct tpm_class_ops tpm_tis = { |
665 | .flags = TPM_OPS_AUTO_STARTUP, | 801 | .flags = TPM_OPS_AUTO_STARTUP, |
666 | .status = tpm_tis_status, | 802 | .status = tpm_tis_status, |
@@ -673,13 +809,17 @@ static const struct tpm_class_ops tpm_tis = { | |||
673 | .req_canceled = tpm_tis_req_canceled, | 809 | .req_canceled = tpm_tis_req_canceled, |
674 | .request_locality = request_locality, | 810 | .request_locality = request_locality, |
675 | .relinquish_locality = release_locality, | 811 | .relinquish_locality = release_locality, |
812 | .clk_enable = tpm_tis_clkrun_enable, | ||
676 | }; | 813 | }; |
677 | 814 | ||
678 | int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, | 815 | int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, |
679 | const struct tpm_tis_phy_ops *phy_ops, | 816 | const struct tpm_tis_phy_ops *phy_ops, |
680 | acpi_handle acpi_dev_handle) | 817 | acpi_handle acpi_dev_handle) |
681 | { | 818 | { |
682 | u32 vendor, intfcaps, intmask; | 819 | u32 vendor; |
820 | u32 intfcaps; | ||
821 | u32 intmask; | ||
822 | u32 clkrun_val; | ||
683 | u8 rid; | 823 | u8 rid; |
684 | int rc, probe; | 824 | int rc, probe; |
685 | struct tpm_chip *chip; | 825 | struct tpm_chip *chip; |
@@ -700,6 +840,23 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, | |||
700 | priv->phy_ops = phy_ops; | 840 | priv->phy_ops = phy_ops; |
701 | dev_set_drvdata(&chip->dev, priv); | 841 | dev_set_drvdata(&chip->dev, priv); |
702 | 842 | ||
843 | if (is_bsw()) { | ||
844 | priv->ilb_base_addr = ioremap(INTEL_LEGACY_BLK_BASE_ADDR, | ||
845 | ILB_REMAP_SIZE); | ||
846 | if (!priv->ilb_base_addr) | ||
847 | return -ENOMEM; | ||
848 | |||
849 | clkrun_val = ioread32(priv->ilb_base_addr + LPC_CNTRL_OFFSET); | ||
850 | /* Check if CLKRUN# is already not enabled in the LPC bus */ | ||
851 | if (!(clkrun_val & LPC_CLKRUN_EN)) { | ||
852 | iounmap(priv->ilb_base_addr); | ||
853 | priv->ilb_base_addr = NULL; | ||
854 | } | ||
855 | } | ||
856 | |||
857 | if (chip->ops->clk_enable != NULL) | ||
858 | chip->ops->clk_enable(chip, true); | ||
859 | |||
703 | if (wait_startup(chip, 0) != 0) { | 860 | if (wait_startup(chip, 0) != 0) { |
704 | rc = -ENODEV; | 861 | rc = -ENODEV; |
705 | goto out_err; | 862 | goto out_err; |
@@ -790,9 +947,20 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, | |||
790 | } | 947 | } |
791 | } | 948 | } |
792 | 949 | ||
793 | return tpm_chip_register(chip); | 950 | rc = tpm_chip_register(chip); |
951 | if (rc) | ||
952 | goto out_err; | ||
953 | |||
954 | if (chip->ops->clk_enable != NULL) | ||
955 | chip->ops->clk_enable(chip, false); | ||
956 | |||
957 | return 0; | ||
794 | out_err: | 958 | out_err: |
959 | if ((chip->ops != NULL) && (chip->ops->clk_enable != NULL)) | ||
960 | chip->ops->clk_enable(chip, false); | ||
961 | |||
795 | tpm_tis_remove(chip); | 962 | tpm_tis_remove(chip); |
963 | |||
796 | return rc; | 964 | return rc; |
797 | } | 965 | } |
798 | EXPORT_SYMBOL_GPL(tpm_tis_core_init); | 966 | EXPORT_SYMBOL_GPL(tpm_tis_core_init); |
@@ -804,22 +972,31 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | |||
804 | u32 intmask; | 972 | u32 intmask; |
805 | int rc; | 973 | int rc; |
806 | 974 | ||
975 | if (chip->ops->clk_enable != NULL) | ||
976 | chip->ops->clk_enable(chip, true); | ||
977 | |||
807 | /* reenable interrupts that device may have lost or | 978 | /* reenable interrupts that device may have lost or |
808 | * BIOS/firmware may have disabled | 979 | * BIOS/firmware may have disabled |
809 | */ | 980 | */ |
810 | rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq); | 981 | rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq); |
811 | if (rc < 0) | 982 | if (rc < 0) |
812 | return; | 983 | goto out; |
813 | 984 | ||
814 | rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); | 985 | rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask); |
815 | if (rc < 0) | 986 | if (rc < 0) |
816 | return; | 987 | goto out; |
817 | 988 | ||
818 | intmask |= TPM_INTF_CMD_READY_INT | 989 | intmask |= TPM_INTF_CMD_READY_INT |
819 | | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT | 990 | | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT |
820 | | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE; | 991 | | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE; |
821 | 992 | ||
822 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); | 993 | tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask); |
994 | |||
995 | out: | ||
996 | if (chip->ops->clk_enable != NULL) | ||
997 | chip->ops->clk_enable(chip, false); | ||
998 | |||
999 | return; | ||
823 | } | 1000 | } |
824 | 1001 | ||
825 | int tpm_tis_resume(struct device *dev) | 1002 | int tpm_tis_resume(struct device *dev) |
diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h index 6bbac319ff3b..d5c6a2e952b3 100644 --- a/drivers/char/tpm/tpm_tis_core.h +++ b/drivers/char/tpm/tpm_tis_core.h | |||
@@ -79,6 +79,11 @@ enum tis_defaults { | |||
79 | #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) | 79 | #define TPM_DID_VID(l) (0x0F00 | ((l) << 12)) |
80 | #define TPM_RID(l) (0x0F04 | ((l) << 12)) | 80 | #define TPM_RID(l) (0x0F04 | ((l) << 12)) |
81 | 81 | ||
82 | #define LPC_CNTRL_OFFSET 0x84 | ||
83 | #define LPC_CLKRUN_EN (1 << 2) | ||
84 | #define INTEL_LEGACY_BLK_BASE_ADDR 0xFED08000 | ||
85 | #define ILB_REMAP_SIZE 0x100 | ||
86 | |||
82 | enum tpm_tis_flags { | 87 | enum tpm_tis_flags { |
83 | TPM_TIS_ITPM_WORKAROUND = BIT(0), | 88 | TPM_TIS_ITPM_WORKAROUND = BIT(0), |
84 | }; | 89 | }; |
@@ -89,6 +94,8 @@ struct tpm_tis_data { | |||
89 | int irq; | 94 | int irq; |
90 | bool irq_tested; | 95 | bool irq_tested; |
91 | unsigned int flags; | 96 | unsigned int flags; |
97 | void __iomem *ilb_base_addr; | ||
98 | u16 clkrun_enabled; | ||
92 | wait_queue_head_t int_queue; | 99 | wait_queue_head_t int_queue; |
93 | wait_queue_head_t read_queue; | 100 | wait_queue_head_t read_queue; |
94 | const struct tpm_tis_phy_ops *phy_ops; | 101 | const struct tpm_tis_phy_ops *phy_ops; |
@@ -144,6 +151,15 @@ static inline int tpm_tis_write32(struct tpm_tis_data *data, u32 addr, | |||
144 | return data->phy_ops->write32(data, addr, value); | 151 | return data->phy_ops->write32(data, addr, value); |
145 | } | 152 | } |
146 | 153 | ||
154 | static inline bool is_bsw(void) | ||
155 | { | ||
156 | #ifdef CONFIG_X86 | ||
157 | return ((boot_cpu_data.x86_model == INTEL_FAM6_ATOM_AIRMONT) ? 1 : 0); | ||
158 | #else | ||
159 | return false; | ||
160 | #endif | ||
161 | } | ||
162 | |||
147 | void tpm_tis_remove(struct tpm_chip *chip); | 163 | void tpm_tis_remove(struct tpm_chip *chip); |
148 | int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, | 164 | int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq, |
149 | const struct tpm_tis_phy_ops *phy_ops, | 165 | const struct tpm_tis_phy_ops *phy_ops, |
diff --git a/drivers/char/tpm/xen-tpmfront.c b/drivers/char/tpm/xen-tpmfront.c index 656e8af95d52..911475d36800 100644 --- a/drivers/char/tpm/xen-tpmfront.c +++ b/drivers/char/tpm/xen-tpmfront.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/err.h> | 11 | #include <linux/err.h> |
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | #include <linux/freezer.h> | ||
13 | #include <xen/xen.h> | 14 | #include <xen/xen.h> |
14 | #include <xen/events.h> | 15 | #include <xen/events.h> |
15 | #include <xen/interface/io/tpmif.h> | 16 | #include <xen/interface/io/tpmif.h> |
@@ -39,6 +40,66 @@ enum status_bits { | |||
39 | VTPM_STATUS_CANCELED = 0x8, | 40 | VTPM_STATUS_CANCELED = 0x8, |
40 | }; | 41 | }; |
41 | 42 | ||
43 | static bool wait_for_tpm_stat_cond(struct tpm_chip *chip, u8 mask, | ||
44 | bool check_cancel, bool *canceled) | ||
45 | { | ||
46 | u8 status = chip->ops->status(chip); | ||
47 | |||
48 | *canceled = false; | ||
49 | if ((status & mask) == mask) | ||
50 | return true; | ||
51 | if (check_cancel && chip->ops->req_canceled(chip, status)) { | ||
52 | *canceled = true; | ||
53 | return true; | ||
54 | } | ||
55 | return false; | ||
56 | } | ||
57 | |||
58 | static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, | ||
59 | unsigned long timeout, wait_queue_head_t *queue, | ||
60 | bool check_cancel) | ||
61 | { | ||
62 | unsigned long stop; | ||
63 | long rc; | ||
64 | u8 status; | ||
65 | bool canceled = false; | ||
66 | |||
67 | /* check current status */ | ||
68 | status = chip->ops->status(chip); | ||
69 | if ((status & mask) == mask) | ||
70 | return 0; | ||
71 | |||
72 | stop = jiffies + timeout; | ||
73 | |||
74 | if (chip->flags & TPM_CHIP_FLAG_IRQ) { | ||
75 | again: | ||
76 | timeout = stop - jiffies; | ||
77 | if ((long)timeout <= 0) | ||
78 | return -ETIME; | ||
79 | rc = wait_event_interruptible_timeout(*queue, | ||
80 | wait_for_tpm_stat_cond(chip, mask, check_cancel, | ||
81 | &canceled), | ||
82 | timeout); | ||
83 | if (rc > 0) { | ||
84 | if (canceled) | ||
85 | return -ECANCELED; | ||
86 | return 0; | ||
87 | } | ||
88 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
89 | clear_thread_flag(TIF_SIGPENDING); | ||
90 | goto again; | ||
91 | } | ||
92 | } else { | ||
93 | do { | ||
94 | tpm_msleep(TPM_TIMEOUT); | ||
95 | status = chip->ops->status(chip); | ||
96 | if ((status & mask) == mask) | ||
97 | return 0; | ||
98 | } while (time_before(jiffies, stop)); | ||
99 | } | ||
100 | return -ETIME; | ||
101 | } | ||
102 | |||
42 | static u8 vtpm_status(struct tpm_chip *chip) | 103 | static u8 vtpm_status(struct tpm_chip *chip) |
43 | { | 104 | { |
44 | struct tpm_private *priv = dev_get_drvdata(&chip->dev); | 105 | struct tpm_private *priv = dev_get_drvdata(&chip->dev); |
diff --git a/drivers/firmware/efi/Makefile b/drivers/firmware/efi/Makefile index a3e73d6e8a43..cb805374f4bc 100644 --- a/drivers/firmware/efi/Makefile +++ b/drivers/firmware/efi/Makefile | |||
@@ -11,7 +11,7 @@ | |||
11 | KASAN_SANITIZE_runtime-wrappers.o := n | 11 | KASAN_SANITIZE_runtime-wrappers.o := n |
12 | 12 | ||
13 | obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o | 13 | obj-$(CONFIG_ACPI_BGRT) += efi-bgrt.o |
14 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o | 14 | obj-$(CONFIG_EFI) += efi.o vars.o reboot.o memattr.o tpm.o |
15 | obj-$(CONFIG_EFI) += capsule.o memmap.o | 15 | obj-$(CONFIG_EFI) += capsule.o memmap.o |
16 | obj-$(CONFIG_EFI_VARS) += efivars.o | 16 | obj-$(CONFIG_EFI_VARS) += efivars.o |
17 | obj-$(CONFIG_EFI_ESRT) += esrt.o | 17 | obj-$(CONFIG_EFI_ESRT) += esrt.o |
diff --git a/drivers/firmware/efi/efi.c b/drivers/firmware/efi/efi.c index 8ce70c2e73d5..cd42f66a7c85 100644 --- a/drivers/firmware/efi/efi.c +++ b/drivers/firmware/efi/efi.c | |||
@@ -52,6 +52,7 @@ struct efi __read_mostly efi = { | |||
52 | .properties_table = EFI_INVALID_TABLE_ADDR, | 52 | .properties_table = EFI_INVALID_TABLE_ADDR, |
53 | .mem_attr_table = EFI_INVALID_TABLE_ADDR, | 53 | .mem_attr_table = EFI_INVALID_TABLE_ADDR, |
54 | .rng_seed = EFI_INVALID_TABLE_ADDR, | 54 | .rng_seed = EFI_INVALID_TABLE_ADDR, |
55 | .tpm_log = EFI_INVALID_TABLE_ADDR | ||
55 | }; | 56 | }; |
56 | EXPORT_SYMBOL(efi); | 57 | EXPORT_SYMBOL(efi); |
57 | 58 | ||
@@ -464,6 +465,7 @@ static __initdata efi_config_table_type_t common_tables[] = { | |||
464 | {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, | 465 | {EFI_PROPERTIES_TABLE_GUID, "PROP", &efi.properties_table}, |
465 | {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, | 466 | {EFI_MEMORY_ATTRIBUTES_TABLE_GUID, "MEMATTR", &efi.mem_attr_table}, |
466 | {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed}, | 467 | {LINUX_EFI_RANDOM_SEED_TABLE_GUID, "RNG", &efi.rng_seed}, |
468 | {LINUX_EFI_TPM_EVENT_LOG_GUID, "TPMEventLog", &efi.tpm_log}, | ||
467 | {NULL_GUID, NULL, NULL}, | 469 | {NULL_GUID, NULL, NULL}, |
468 | }; | 470 | }; |
469 | 471 | ||
@@ -552,6 +554,8 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz, | |||
552 | if (efi_enabled(EFI_MEMMAP)) | 554 | if (efi_enabled(EFI_MEMMAP)) |
553 | efi_memattr_init(); | 555 | efi_memattr_init(); |
554 | 556 | ||
557 | efi_tpm_eventlog_init(); | ||
558 | |||
555 | /* Parse the EFI Properties table if it exists */ | 559 | /* Parse the EFI Properties table if it exists */ |
556 | if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { | 560 | if (efi.properties_table != EFI_INVALID_TABLE_ADDR) { |
557 | efi_properties_table_t *tbl; | 561 | efi_properties_table_t *tbl; |
diff --git a/drivers/firmware/efi/libstub/Makefile b/drivers/firmware/efi/libstub/Makefile index adaa4a964f0c..7b3ba40f0745 100644 --- a/drivers/firmware/efi/libstub/Makefile +++ b/drivers/firmware/efi/libstub/Makefile | |||
@@ -30,8 +30,7 @@ OBJECT_FILES_NON_STANDARD := y | |||
30 | # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. | 30 | # Prevents link failures: __sanitizer_cov_trace_pc() is not linked in. |
31 | KCOV_INSTRUMENT := n | 31 | KCOV_INSTRUMENT := n |
32 | 32 | ||
33 | lib-y := efi-stub-helper.o gop.o secureboot.o | 33 | lib-y := efi-stub-helper.o gop.o secureboot.o tpm.o |
34 | lib-$(CONFIG_RESET_ATTACK_MITIGATION) += tpm.o | ||
35 | 34 | ||
36 | # include the stub's generic dependencies from lib/ when building for ARM/arm64 | 35 | # include the stub's generic dependencies from lib/ when building for ARM/arm64 |
37 | arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c | 36 | arm-deps-y := fdt_rw.c fdt_ro.c fdt_wip.c fdt.c fdt_empty_tree.c fdt_sw.c |
diff --git a/drivers/firmware/efi/libstub/tpm.c b/drivers/firmware/efi/libstub/tpm.c index 6224cdbc9669..da661bf8cb96 100644 --- a/drivers/firmware/efi/libstub/tpm.c +++ b/drivers/firmware/efi/libstub/tpm.c | |||
@@ -4,15 +4,18 @@ | |||
4 | * Copyright (C) 2016 CoreOS, Inc | 4 | * Copyright (C) 2016 CoreOS, Inc |
5 | * Copyright (C) 2017 Google, Inc. | 5 | * Copyright (C) 2017 Google, Inc. |
6 | * Matthew Garrett <mjg59@google.com> | 6 | * Matthew Garrett <mjg59@google.com> |
7 | * Thiebaud Weksteen <tweek@google.com> | ||
7 | * | 8 | * |
8 | * This file is part of the Linux kernel, and is made available under the | 9 | * This file is part of the Linux kernel, and is made available under the |
9 | * terms of the GNU General Public License version 2. | 10 | * terms of the GNU General Public License version 2. |
10 | */ | 11 | */ |
11 | #include <linux/efi.h> | 12 | #include <linux/efi.h> |
13 | #include <linux/tpm_eventlog.h> | ||
12 | #include <asm/efi.h> | 14 | #include <asm/efi.h> |
13 | 15 | ||
14 | #include "efistub.h" | 16 | #include "efistub.h" |
15 | 17 | ||
18 | #ifdef CONFIG_RESET_ATTACK_MITIGATION | ||
16 | static const efi_char16_t efi_MemoryOverWriteRequest_name[] = { | 19 | static const efi_char16_t efi_MemoryOverWriteRequest_name[] = { |
17 | 'M', 'e', 'm', 'o', 'r', 'y', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't', | 20 | 'M', 'e', 'm', 'o', 'r', 'y', 'O', 'v', 'e', 'r', 'w', 'r', 'i', 't', |
18 | 'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 'n', 't', 'r', 'o', | 21 | 'e', 'R', 'e', 'q', 'u', 'e', 's', 't', 'C', 'o', 'n', 't', 'r', 'o', |
@@ -56,3 +59,81 @@ void efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) | |||
56 | EFI_VARIABLE_BOOTSERVICE_ACCESS | | 59 | EFI_VARIABLE_BOOTSERVICE_ACCESS | |
57 | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(val), &val); | 60 | EFI_VARIABLE_RUNTIME_ACCESS, sizeof(val), &val); |
58 | } | 61 | } |
62 | |||
63 | #endif | ||
64 | |||
65 | void efi_retrieve_tpm2_eventlog_1_2(efi_system_table_t *sys_table_arg) | ||
66 | { | ||
67 | efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID; | ||
68 | efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID; | ||
69 | efi_status_t status; | ||
70 | efi_physical_addr_t log_location, log_last_entry; | ||
71 | struct linux_efi_tpm_eventlog *log_tbl; | ||
72 | unsigned long first_entry_addr, last_entry_addr; | ||
73 | size_t log_size, last_entry_size; | ||
74 | efi_bool_t truncated; | ||
75 | void *tcg2_protocol; | ||
76 | |||
77 | status = efi_call_early(locate_protocol, &tcg2_guid, NULL, | ||
78 | &tcg2_protocol); | ||
79 | if (status != EFI_SUCCESS) | ||
80 | return; | ||
81 | |||
82 | status = efi_call_proto(efi_tcg2_protocol, get_event_log, tcg2_protocol, | ||
83 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2, | ||
84 | &log_location, &log_last_entry, &truncated); | ||
85 | if (status != EFI_SUCCESS) | ||
86 | return; | ||
87 | |||
88 | if (!log_location) | ||
89 | return; | ||
90 | first_entry_addr = (unsigned long) log_location; | ||
91 | |||
92 | /* | ||
93 | * We populate the EFI table even if the logs are empty. | ||
94 | */ | ||
95 | if (!log_last_entry) { | ||
96 | log_size = 0; | ||
97 | } else { | ||
98 | last_entry_addr = (unsigned long) log_last_entry; | ||
99 | /* | ||
100 | * get_event_log only returns the address of the last entry. | ||
101 | * We need to calculate its size to deduce the full size of | ||
102 | * the logs. | ||
103 | */ | ||
104 | last_entry_size = sizeof(struct tcpa_event) + | ||
105 | ((struct tcpa_event *) last_entry_addr)->event_size; | ||
106 | log_size = log_last_entry - log_location + last_entry_size; | ||
107 | } | ||
108 | |||
109 | /* Allocate space for the logs and copy them. */ | ||
110 | status = efi_call_early(allocate_pool, EFI_LOADER_DATA, | ||
111 | sizeof(*log_tbl) + log_size, | ||
112 | (void **) &log_tbl); | ||
113 | |||
114 | if (status != EFI_SUCCESS) { | ||
115 | efi_printk(sys_table_arg, | ||
116 | "Unable to allocate memory for event log\n"); | ||
117 | return; | ||
118 | } | ||
119 | |||
120 | memset(log_tbl, 0, sizeof(*log_tbl) + log_size); | ||
121 | log_tbl->size = log_size; | ||
122 | log_tbl->version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2; | ||
123 | memcpy(log_tbl->log, (void *) first_entry_addr, log_size); | ||
124 | |||
125 | status = efi_call_early(install_configuration_table, | ||
126 | &linux_eventlog_guid, log_tbl); | ||
127 | if (status != EFI_SUCCESS) | ||
128 | goto err_free; | ||
129 | return; | ||
130 | |||
131 | err_free: | ||
132 | efi_call_early(free_pool, log_tbl); | ||
133 | } | ||
134 | |||
135 | void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table_arg) | ||
136 | { | ||
137 | /* Only try to retrieve the logs in 1.2 format. */ | ||
138 | efi_retrieve_tpm2_eventlog_1_2(sys_table_arg); | ||
139 | } | ||
diff --git a/drivers/firmware/efi/tpm.c b/drivers/firmware/efi/tpm.c new file mode 100644 index 000000000000..0cbeb3d46b18 --- /dev/null +++ b/drivers/firmware/efi/tpm.c | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2017 Google, Inc. | ||
3 | * Thiebaud Weksteen <tweek@google.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #include <linux/efi.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/memblock.h> | ||
13 | |||
14 | #include <asm/early_ioremap.h> | ||
15 | |||
16 | /* | ||
17 | * Reserve the memory associated with the TPM Event Log configuration table. | ||
18 | */ | ||
19 | int __init efi_tpm_eventlog_init(void) | ||
20 | { | ||
21 | struct linux_efi_tpm_eventlog *log_tbl; | ||
22 | unsigned int tbl_size; | ||
23 | |||
24 | if (efi.tpm_log == EFI_INVALID_TABLE_ADDR) | ||
25 | return 0; | ||
26 | |||
27 | log_tbl = early_memremap(efi.tpm_log, sizeof(*log_tbl)); | ||
28 | if (!log_tbl) { | ||
29 | pr_err("Failed to map TPM Event Log table @ 0x%lx\n", | ||
30 | efi.tpm_log); | ||
31 | efi.tpm_log = EFI_INVALID_TABLE_ADDR; | ||
32 | return -ENOMEM; | ||
33 | } | ||
34 | |||
35 | tbl_size = sizeof(*log_tbl) + log_tbl->size; | ||
36 | memblock_reserve(efi.tpm_log, tbl_size); | ||
37 | early_memunmap(log_tbl, sizeof(*log_tbl)); | ||
38 | return 0; | ||
39 | } | ||
40 | |||
diff --git a/include/linux/efi.h b/include/linux/efi.h index 29fdf8029cf6..f5083aa72eae 100644 --- a/include/linux/efi.h +++ b/include/linux/efi.h | |||
@@ -475,6 +475,39 @@ typedef struct { | |||
475 | u64 get_all; | 475 | u64 get_all; |
476 | } apple_properties_protocol_64_t; | 476 | } apple_properties_protocol_64_t; |
477 | 477 | ||
478 | typedef struct { | ||
479 | u32 get_capability; | ||
480 | u32 get_event_log; | ||
481 | u32 hash_log_extend_event; | ||
482 | u32 submit_command; | ||
483 | u32 get_active_pcr_banks; | ||
484 | u32 set_active_pcr_banks; | ||
485 | u32 get_result_of_set_active_pcr_banks; | ||
486 | } efi_tcg2_protocol_32_t; | ||
487 | |||
488 | typedef struct { | ||
489 | u64 get_capability; | ||
490 | u64 get_event_log; | ||
491 | u64 hash_log_extend_event; | ||
492 | u64 submit_command; | ||
493 | u64 get_active_pcr_banks; | ||
494 | u64 set_active_pcr_banks; | ||
495 | u64 get_result_of_set_active_pcr_banks; | ||
496 | } efi_tcg2_protocol_64_t; | ||
497 | |||
498 | typedef u32 efi_tcg2_event_log_format; | ||
499 | |||
500 | typedef struct { | ||
501 | void *get_capability; | ||
502 | efi_status_t (*get_event_log)(efi_handle_t, efi_tcg2_event_log_format, | ||
503 | efi_physical_addr_t *, efi_physical_addr_t *, efi_bool_t *); | ||
504 | void *hash_log_extend_event; | ||
505 | void *submit_command; | ||
506 | void *get_active_pcr_banks; | ||
507 | void *set_active_pcr_banks; | ||
508 | void *get_result_of_set_active_pcr_banks; | ||
509 | } efi_tcg2_protocol_t; | ||
510 | |||
478 | /* | 511 | /* |
479 | * Types and defines for EFI ResetSystem | 512 | * Types and defines for EFI ResetSystem |
480 | */ | 513 | */ |
@@ -625,6 +658,7 @@ void efi_native_runtime_setup(void); | |||
625 | #define EFI_MEMORY_ATTRIBUTES_TABLE_GUID EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) | 658 | #define EFI_MEMORY_ATTRIBUTES_TABLE_GUID EFI_GUID(0xdcfa911d, 0x26eb, 0x469f, 0xa2, 0x20, 0x38, 0xb7, 0xdc, 0x46, 0x12, 0x20) |
626 | #define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) | 659 | #define EFI_CONSOLE_OUT_DEVICE_GUID EFI_GUID(0xd3b36f2c, 0xd551, 0x11d4, 0x9a, 0x46, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d) |
627 | #define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0) | 660 | #define APPLE_PROPERTIES_PROTOCOL_GUID EFI_GUID(0x91bd12fe, 0xf6c3, 0x44fb, 0xa5, 0xb7, 0x51, 0x22, 0xab, 0x30, 0x3a, 0xe0) |
661 | #define EFI_TCG2_PROTOCOL_GUID EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f) | ||
628 | 662 | ||
629 | #define EFI_IMAGE_SECURITY_DATABASE_GUID EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) | 663 | #define EFI_IMAGE_SECURITY_DATABASE_GUID EFI_GUID(0xd719b2cb, 0x3d3a, 0x4596, 0xa3, 0xbc, 0xda, 0xd0, 0x0e, 0x67, 0x65, 0x6f) |
630 | #define EFI_SHIM_LOCK_GUID EFI_GUID(0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23) | 664 | #define EFI_SHIM_LOCK_GUID EFI_GUID(0x605dab50, 0xe046, 0x4300, 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23) |
@@ -637,6 +671,7 @@ void efi_native_runtime_setup(void); | |||
637 | #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) | 671 | #define LINUX_EFI_ARM_SCREEN_INFO_TABLE_GUID EFI_GUID(0xe03fc20a, 0x85dc, 0x406e, 0xb9, 0x0e, 0x4a, 0xb5, 0x02, 0x37, 0x1d, 0x95) |
638 | #define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) | 672 | #define LINUX_EFI_LOADER_ENTRY_GUID EFI_GUID(0x4a67b082, 0x0a4c, 0x41cf, 0xb6, 0xc7, 0x44, 0x0b, 0x29, 0xbb, 0x8c, 0x4f) |
639 | #define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b) | 673 | #define LINUX_EFI_RANDOM_SEED_TABLE_GUID EFI_GUID(0x1ce1e5bc, 0x7ceb, 0x42f2, 0x81, 0xe5, 0x8a, 0xad, 0xf1, 0x80, 0xf5, 0x7b) |
674 | #define LINUX_EFI_TPM_EVENT_LOG_GUID EFI_GUID(0xb7799cb0, 0xeca2, 0x4943, 0x96, 0x67, 0x1f, 0xae, 0x07, 0xb7, 0x47, 0xfa) | ||
640 | 675 | ||
641 | typedef struct { | 676 | typedef struct { |
642 | efi_guid_t guid; | 677 | efi_guid_t guid; |
@@ -911,6 +946,7 @@ extern struct efi { | |||
911 | unsigned long properties_table; /* properties table */ | 946 | unsigned long properties_table; /* properties table */ |
912 | unsigned long mem_attr_table; /* memory attributes table */ | 947 | unsigned long mem_attr_table; /* memory attributes table */ |
913 | unsigned long rng_seed; /* UEFI firmware random seed */ | 948 | unsigned long rng_seed; /* UEFI firmware random seed */ |
949 | unsigned long tpm_log; /* TPM2 Event Log table */ | ||
914 | efi_get_time_t *get_time; | 950 | efi_get_time_t *get_time; |
915 | efi_set_time_t *set_time; | 951 | efi_set_time_t *set_time; |
916 | efi_get_wakeup_time_t *get_wakeup_time; | 952 | efi_get_wakeup_time_t *get_wakeup_time; |
@@ -1536,6 +1572,8 @@ static inline void | |||
1536 | efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) { } | 1572 | efi_enable_reset_attack_mitigation(efi_system_table_t *sys_table_arg) { } |
1537 | #endif | 1573 | #endif |
1538 | 1574 | ||
1575 | void efi_retrieve_tpm2_eventlog(efi_system_table_t *sys_table); | ||
1576 | |||
1539 | /* | 1577 | /* |
1540 | * Arch code can implement the following three template macros, avoiding | 1578 | * Arch code can implement the following three template macros, avoiding |
1541 | * reptition for the void/non-void return cases of {__,}efi_call_virt(): | 1579 | * reptition for the void/non-void return cases of {__,}efi_call_virt(): |
@@ -1603,4 +1641,12 @@ struct linux_efi_random_seed { | |||
1603 | u8 bits[]; | 1641 | u8 bits[]; |
1604 | }; | 1642 | }; |
1605 | 1643 | ||
1644 | struct linux_efi_tpm_eventlog { | ||
1645 | u32 size; | ||
1646 | u8 version; | ||
1647 | u8 log[]; | ||
1648 | }; | ||
1649 | |||
1650 | extern int efi_tpm_eventlog_init(void); | ||
1651 | |||
1606 | #endif /* _LINUX_EFI_H */ | 1652 | #endif /* _LINUX_EFI_H */ |
diff --git a/include/linux/tpm.h b/include/linux/tpm.h index 5a090f5ab335..bcdd3790e94d 100644 --- a/include/linux/tpm.h +++ b/include/linux/tpm.h | |||
@@ -24,11 +24,6 @@ | |||
24 | 24 | ||
25 | #define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ | 25 | #define TPM_DIGEST_SIZE 20 /* Max TPM v1.2 PCR size */ |
26 | 26 | ||
27 | /* | ||
28 | * Chip num is this value or a valid tpm idx | ||
29 | */ | ||
30 | #define TPM_ANY_NUM 0xFFFF | ||
31 | |||
32 | struct tpm_chip; | 27 | struct tpm_chip; |
33 | struct trusted_key_payload; | 28 | struct trusted_key_payload; |
34 | struct trusted_key_options; | 29 | struct trusted_key_options; |
@@ -50,46 +45,52 @@ struct tpm_class_ops { | |||
50 | unsigned long *timeout_cap); | 45 | unsigned long *timeout_cap); |
51 | int (*request_locality)(struct tpm_chip *chip, int loc); | 46 | int (*request_locality)(struct tpm_chip *chip, int loc); |
52 | void (*relinquish_locality)(struct tpm_chip *chip, int loc); | 47 | void (*relinquish_locality)(struct tpm_chip *chip, int loc); |
48 | void (*clk_enable)(struct tpm_chip *chip, bool value); | ||
53 | }; | 49 | }; |
54 | 50 | ||
55 | #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) | 51 | #if defined(CONFIG_TCG_TPM) || defined(CONFIG_TCG_TPM_MODULE) |
56 | 52 | ||
57 | extern int tpm_is_tpm2(u32 chip_num); | 53 | extern int tpm_is_tpm2(struct tpm_chip *chip); |
58 | extern int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf); | 54 | extern int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf); |
59 | extern int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash); | 55 | extern int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, const u8 *hash); |
60 | extern int tpm_send(u32 chip_num, void *cmd, size_t buflen); | 56 | extern int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen); |
61 | extern int tpm_get_random(u32 chip_num, u8 *data, size_t max); | 57 | extern int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max); |
62 | extern int tpm_seal_trusted(u32 chip_num, | 58 | extern int tpm_seal_trusted(struct tpm_chip *chip, |
63 | struct trusted_key_payload *payload, | 59 | struct trusted_key_payload *payload, |
64 | struct trusted_key_options *options); | 60 | struct trusted_key_options *options); |
65 | extern int tpm_unseal_trusted(u32 chip_num, | 61 | extern int tpm_unseal_trusted(struct tpm_chip *chip, |
66 | struct trusted_key_payload *payload, | 62 | struct trusted_key_payload *payload, |
67 | struct trusted_key_options *options); | 63 | struct trusted_key_options *options); |
68 | #else | 64 | #else |
69 | static inline int tpm_is_tpm2(u32 chip_num) | 65 | static inline int tpm_is_tpm2(struct tpm_chip *chip) |
70 | { | 66 | { |
71 | return -ENODEV; | 67 | return -ENODEV; |
72 | } | 68 | } |
73 | static inline int tpm_pcr_read(u32 chip_num, int pcr_idx, u8 *res_buf) { | 69 | static inline int tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) |
70 | { | ||
74 | return -ENODEV; | 71 | return -ENODEV; |
75 | } | 72 | } |
76 | static inline int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) { | 73 | static inline int tpm_pcr_extend(struct tpm_chip *chip, int pcr_idx, |
74 | const u8 *hash) | ||
75 | { | ||
77 | return -ENODEV; | 76 | return -ENODEV; |
78 | } | 77 | } |
79 | static inline int tpm_send(u32 chip_num, void *cmd, size_t buflen) { | 78 | static inline int tpm_send(struct tpm_chip *chip, void *cmd, size_t buflen) |
79 | { | ||
80 | return -ENODEV; | 80 | return -ENODEV; |
81 | } | 81 | } |
82 | static inline int tpm_get_random(u32 chip_num, u8 *data, size_t max) { | 82 | static inline int tpm_get_random(struct tpm_chip *chip, u8 *data, size_t max) |
83 | { | ||
83 | return -ENODEV; | 84 | return -ENODEV; |
84 | } | 85 | } |
85 | 86 | ||
86 | static inline int tpm_seal_trusted(u32 chip_num, | 87 | static inline int tpm_seal_trusted(struct tpm_chip *chip, |
87 | struct trusted_key_payload *payload, | 88 | struct trusted_key_payload *payload, |
88 | struct trusted_key_options *options) | 89 | struct trusted_key_options *options) |
89 | { | 90 | { |
90 | return -ENODEV; | 91 | return -ENODEV; |
91 | } | 92 | } |
92 | static inline int tpm_unseal_trusted(u32 chip_num, | 93 | static inline int tpm_unseal_trusted(struct tpm_chip *chip, |
93 | struct trusted_key_payload *payload, | 94 | struct trusted_key_payload *payload, |
94 | struct trusted_key_options *options) | 95 | struct trusted_key_options *options) |
95 | { | 96 | { |
diff --git a/drivers/char/tpm/tpm_eventlog.h b/include/linux/tpm_eventlog.h index 204466cc4d05..20d9da77fc11 100644 --- a/drivers/char/tpm/tpm_eventlog.h +++ b/include/linux/tpm_eventlog.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* SPDX-License-Identifier: GPL-2.0 */ | 1 | /* SPDX-License-Identifier: GPL-2.0 */ |
2 | 2 | ||
3 | #ifndef __TPM_EVENTLOG_H__ | 3 | #ifndef __LINUX_TPM_EVENTLOG_H__ |
4 | #define __TPM_EVENTLOG_H__ | 4 | #define __LINUX_TPM_EVENTLOG_H__ |
5 | 5 | ||
6 | #include <crypto/hash_info.h> | 6 | #include <crypto/hash_info.h> |
7 | 7 | ||
@@ -10,6 +10,9 @@ | |||
10 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | 10 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ |
11 | #define TPM2_ACTIVE_PCR_BANKS 3 | 11 | #define TPM2_ACTIVE_PCR_BANKS 3 |
12 | 12 | ||
13 | #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 0x1 | ||
14 | #define EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 0x2 | ||
15 | |||
13 | #ifdef CONFIG_PPC64 | 16 | #ifdef CONFIG_PPC64 |
14 | #define do_endian_conversion(x) be32_to_cpu(x) | 17 | #define do_endian_conversion(x) be32_to_cpu(x) |
15 | #else | 18 | #else |
@@ -105,6 +108,11 @@ struct tcg_event_field { | |||
105 | u8 event[0]; | 108 | u8 event[0]; |
106 | } __packed; | 109 | } __packed; |
107 | 110 | ||
111 | struct tpm2_digest { | ||
112 | u16 alg_id; | ||
113 | u8 digest[SHA512_DIGEST_SIZE]; | ||
114 | } __packed; | ||
115 | |||
108 | struct tcg_pcr_event2 { | 116 | struct tcg_pcr_event2 { |
109 | u32 pcr_idx; | 117 | u32 pcr_idx; |
110 | u32 event_type; | 118 | u32 event_type; |
@@ -113,26 +121,4 @@ struct tcg_pcr_event2 { | |||
113 | struct tcg_event_field event; | 121 | struct tcg_event_field event; |
114 | } __packed; | 122 | } __packed; |
115 | 123 | ||
116 | extern const struct seq_operations tpm2_binary_b_measurements_seqops; | ||
117 | |||
118 | #if defined(CONFIG_ACPI) | ||
119 | int tpm_read_log_acpi(struct tpm_chip *chip); | ||
120 | #else | ||
121 | static inline int tpm_read_log_acpi(struct tpm_chip *chip) | ||
122 | { | ||
123 | return -ENODEV; | ||
124 | } | ||
125 | #endif | ||
126 | #if defined(CONFIG_OF) | ||
127 | int tpm_read_log_of(struct tpm_chip *chip); | ||
128 | #else | ||
129 | static inline int tpm_read_log_of(struct tpm_chip *chip) | ||
130 | { | ||
131 | return -ENODEV; | ||
132 | } | ||
133 | #endif | ||
134 | |||
135 | int tpm_bios_log_setup(struct tpm_chip *chip); | ||
136 | void tpm_bios_log_teardown(struct tpm_chip *chip); | ||
137 | |||
138 | #endif | 124 | #endif |
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 9057b163c378..205bc69361ea 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c | |||
@@ -632,7 +632,7 @@ static void __init ima_pcrread(int idx, u8 *pcr) | |||
632 | if (!ima_used_chip) | 632 | if (!ima_used_chip) |
633 | return; | 633 | return; |
634 | 634 | ||
635 | if (tpm_pcr_read(TPM_ANY_NUM, idx, pcr) != 0) | 635 | if (tpm_pcr_read(NULL, idx, pcr) != 0) |
636 | pr_err("Error Communicating to TPM chip\n"); | 636 | pr_err("Error Communicating to TPM chip\n"); |
637 | } | 637 | } |
638 | 638 | ||
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index 2967d497a665..29b72cd2502e 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c | |||
@@ -110,7 +110,7 @@ int __init ima_init(void) | |||
110 | int rc; | 110 | int rc; |
111 | 111 | ||
112 | ima_used_chip = 0; | 112 | ima_used_chip = 0; |
113 | rc = tpm_pcr_read(TPM_ANY_NUM, 0, pcr_i); | 113 | rc = tpm_pcr_read(NULL, 0, pcr_i); |
114 | if (rc == 0) | 114 | if (rc == 0) |
115 | ima_used_chip = 1; | 115 | ima_used_chip = 1; |
116 | 116 | ||
diff --git a/security/integrity/ima/ima_queue.c b/security/integrity/ima/ima_queue.c index a02a86d51102..418f35e38015 100644 --- a/security/integrity/ima/ima_queue.c +++ b/security/integrity/ima/ima_queue.c | |||
@@ -145,7 +145,7 @@ static int ima_pcr_extend(const u8 *hash, int pcr) | |||
145 | if (!ima_used_chip) | 145 | if (!ima_used_chip) |
146 | return result; | 146 | return result; |
147 | 147 | ||
148 | result = tpm_pcr_extend(TPM_ANY_NUM, pcr, hash); | 148 | result = tpm_pcr_extend(NULL, pcr, hash); |
149 | if (result != 0) | 149 | if (result != 0) |
150 | pr_err("Error Communicating to TPM chip, result: %d\n", result); | 150 | pr_err("Error Communicating to TPM chip, result: %d\n", result); |
151 | return result; | 151 | return result; |
diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 98aa89ff7bfd..423776682025 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c | |||
@@ -355,13 +355,12 @@ out: | |||
355 | * For key specific tpm requests, we will generate and send our | 355 | * For key specific tpm requests, we will generate and send our |
356 | * own TPM command packets using the drivers send function. | 356 | * own TPM command packets using the drivers send function. |
357 | */ | 357 | */ |
358 | static int trusted_tpm_send(const u32 chip_num, unsigned char *cmd, | 358 | static int trusted_tpm_send(unsigned char *cmd, size_t buflen) |
359 | size_t buflen) | ||
360 | { | 359 | { |
361 | int rc; | 360 | int rc; |
362 | 361 | ||
363 | dump_tpm_buf(cmd); | 362 | dump_tpm_buf(cmd); |
364 | rc = tpm_send(chip_num, cmd, buflen); | 363 | rc = tpm_send(NULL, cmd, buflen); |
365 | dump_tpm_buf(cmd); | 364 | dump_tpm_buf(cmd); |
366 | if (rc > 0) | 365 | if (rc > 0) |
367 | /* Can't return positive return codes values to keyctl */ | 366 | /* Can't return positive return codes values to keyctl */ |
@@ -382,10 +381,10 @@ static int pcrlock(const int pcrnum) | |||
382 | 381 | ||
383 | if (!capable(CAP_SYS_ADMIN)) | 382 | if (!capable(CAP_SYS_ADMIN)) |
384 | return -EPERM; | 383 | return -EPERM; |
385 | ret = tpm_get_random(TPM_ANY_NUM, hash, SHA1_DIGEST_SIZE); | 384 | ret = tpm_get_random(NULL, hash, SHA1_DIGEST_SIZE); |
386 | if (ret != SHA1_DIGEST_SIZE) | 385 | if (ret != SHA1_DIGEST_SIZE) |
387 | return ret; | 386 | return ret; |
388 | return tpm_pcr_extend(TPM_ANY_NUM, pcrnum, hash) ? -EINVAL : 0; | 387 | return tpm_pcr_extend(NULL, pcrnum, hash) ? -EINVAL : 0; |
389 | } | 388 | } |
390 | 389 | ||
391 | /* | 390 | /* |
@@ -398,7 +397,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, | |||
398 | unsigned char ononce[TPM_NONCE_SIZE]; | 397 | unsigned char ononce[TPM_NONCE_SIZE]; |
399 | int ret; | 398 | int ret; |
400 | 399 | ||
401 | ret = tpm_get_random(TPM_ANY_NUM, ononce, TPM_NONCE_SIZE); | 400 | ret = tpm_get_random(NULL, ononce, TPM_NONCE_SIZE); |
402 | if (ret != TPM_NONCE_SIZE) | 401 | if (ret != TPM_NONCE_SIZE) |
403 | return ret; | 402 | return ret; |
404 | 403 | ||
@@ -410,7 +409,7 @@ static int osap(struct tpm_buf *tb, struct osapsess *s, | |||
410 | store32(tb, handle); | 409 | store32(tb, handle); |
411 | storebytes(tb, ononce, TPM_NONCE_SIZE); | 410 | storebytes(tb, ononce, TPM_NONCE_SIZE); |
412 | 411 | ||
413 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE); | 412 | ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); |
414 | if (ret < 0) | 413 | if (ret < 0) |
415 | return ret; | 414 | return ret; |
416 | 415 | ||
@@ -434,7 +433,7 @@ static int oiap(struct tpm_buf *tb, uint32_t *handle, unsigned char *nonce) | |||
434 | store16(tb, TPM_TAG_RQU_COMMAND); | 433 | store16(tb, TPM_TAG_RQU_COMMAND); |
435 | store32(tb, TPM_OIAP_SIZE); | 434 | store32(tb, TPM_OIAP_SIZE); |
436 | store32(tb, TPM_ORD_OIAP); | 435 | store32(tb, TPM_ORD_OIAP); |
437 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE); | 436 | ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); |
438 | if (ret < 0) | 437 | if (ret < 0) |
439 | return ret; | 438 | return ret; |
440 | 439 | ||
@@ -493,7 +492,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, | |||
493 | if (ret < 0) | 492 | if (ret < 0) |
494 | goto out; | 493 | goto out; |
495 | 494 | ||
496 | ret = tpm_get_random(TPM_ANY_NUM, td->nonceodd, TPM_NONCE_SIZE); | 495 | ret = tpm_get_random(NULL, td->nonceodd, TPM_NONCE_SIZE); |
497 | if (ret != TPM_NONCE_SIZE) | 496 | if (ret != TPM_NONCE_SIZE) |
498 | goto out; | 497 | goto out; |
499 | ordinal = htonl(TPM_ORD_SEAL); | 498 | ordinal = htonl(TPM_ORD_SEAL); |
@@ -542,7 +541,7 @@ static int tpm_seal(struct tpm_buf *tb, uint16_t keytype, | |||
542 | store8(tb, cont); | 541 | store8(tb, cont); |
543 | storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE); | 542 | storebytes(tb, td->pubauth, SHA1_DIGEST_SIZE); |
544 | 543 | ||
545 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE); | 544 | ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); |
546 | if (ret < 0) | 545 | if (ret < 0) |
547 | goto out; | 546 | goto out; |
548 | 547 | ||
@@ -603,7 +602,7 @@ static int tpm_unseal(struct tpm_buf *tb, | |||
603 | 602 | ||
604 | ordinal = htonl(TPM_ORD_UNSEAL); | 603 | ordinal = htonl(TPM_ORD_UNSEAL); |
605 | keyhndl = htonl(SRKHANDLE); | 604 | keyhndl = htonl(SRKHANDLE); |
606 | ret = tpm_get_random(TPM_ANY_NUM, nonceodd, TPM_NONCE_SIZE); | 605 | ret = tpm_get_random(NULL, nonceodd, TPM_NONCE_SIZE); |
607 | if (ret != TPM_NONCE_SIZE) { | 606 | if (ret != TPM_NONCE_SIZE) { |
608 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); | 607 | pr_info("trusted_key: tpm_get_random failed (%d)\n", ret); |
609 | return ret; | 608 | return ret; |
@@ -635,7 +634,7 @@ static int tpm_unseal(struct tpm_buf *tb, | |||
635 | store8(tb, cont); | 634 | store8(tb, cont); |
636 | storebytes(tb, authdata2, SHA1_DIGEST_SIZE); | 635 | storebytes(tb, authdata2, SHA1_DIGEST_SIZE); |
637 | 636 | ||
638 | ret = trusted_tpm_send(TPM_ANY_NUM, tb->data, MAX_BUF_SIZE); | 637 | ret = trusted_tpm_send(tb->data, MAX_BUF_SIZE); |
639 | if (ret < 0) { | 638 | if (ret < 0) { |
640 | pr_info("trusted_key: authhmac failed (%d)\n", ret); | 639 | pr_info("trusted_key: authhmac failed (%d)\n", ret); |
641 | return ret; | 640 | return ret; |
@@ -748,7 +747,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, | |||
748 | int i; | 747 | int i; |
749 | int tpm2; | 748 | int tpm2; |
750 | 749 | ||
751 | tpm2 = tpm_is_tpm2(TPM_ANY_NUM); | 750 | tpm2 = tpm_is_tpm2(NULL); |
752 | if (tpm2 < 0) | 751 | if (tpm2 < 0) |
753 | return tpm2; | 752 | return tpm2; |
754 | 753 | ||
@@ -917,7 +916,7 @@ static struct trusted_key_options *trusted_options_alloc(void) | |||
917 | struct trusted_key_options *options; | 916 | struct trusted_key_options *options; |
918 | int tpm2; | 917 | int tpm2; |
919 | 918 | ||
920 | tpm2 = tpm_is_tpm2(TPM_ANY_NUM); | 919 | tpm2 = tpm_is_tpm2(NULL); |
921 | if (tpm2 < 0) | 920 | if (tpm2 < 0) |
922 | return NULL; | 921 | return NULL; |
923 | 922 | ||
@@ -967,7 +966,7 @@ static int trusted_instantiate(struct key *key, | |||
967 | size_t key_len; | 966 | size_t key_len; |
968 | int tpm2; | 967 | int tpm2; |
969 | 968 | ||
970 | tpm2 = tpm_is_tpm2(TPM_ANY_NUM); | 969 | tpm2 = tpm_is_tpm2(NULL); |
971 | if (tpm2 < 0) | 970 | if (tpm2 < 0) |
972 | return tpm2; | 971 | return tpm2; |
973 | 972 | ||
@@ -1008,7 +1007,7 @@ static int trusted_instantiate(struct key *key, | |||
1008 | switch (key_cmd) { | 1007 | switch (key_cmd) { |
1009 | case Opt_load: | 1008 | case Opt_load: |
1010 | if (tpm2) | 1009 | if (tpm2) |
1011 | ret = tpm_unseal_trusted(TPM_ANY_NUM, payload, options); | 1010 | ret = tpm_unseal_trusted(NULL, payload, options); |
1012 | else | 1011 | else |
1013 | ret = key_unseal(payload, options); | 1012 | ret = key_unseal(payload, options); |
1014 | dump_payload(payload); | 1013 | dump_payload(payload); |
@@ -1018,13 +1017,13 @@ static int trusted_instantiate(struct key *key, | |||
1018 | break; | 1017 | break; |
1019 | case Opt_new: | 1018 | case Opt_new: |
1020 | key_len = payload->key_len; | 1019 | key_len = payload->key_len; |
1021 | ret = tpm_get_random(TPM_ANY_NUM, payload->key, key_len); | 1020 | ret = tpm_get_random(NULL, payload->key, key_len); |
1022 | if (ret != key_len) { | 1021 | if (ret != key_len) { |
1023 | pr_info("trusted_key: key_create failed (%d)\n", ret); | 1022 | pr_info("trusted_key: key_create failed (%d)\n", ret); |
1024 | goto out; | 1023 | goto out; |
1025 | } | 1024 | } |
1026 | if (tpm2) | 1025 | if (tpm2) |
1027 | ret = tpm_seal_trusted(TPM_ANY_NUM, payload, options); | 1026 | ret = tpm_seal_trusted(NULL, payload, options); |
1028 | else | 1027 | else |
1029 | ret = key_seal(payload, options); | 1028 | ret = key_seal(payload, options); |
1030 | if (ret < 0) | 1029 | if (ret < 0) |