On 11/12/20 7:49 PM, Heinrich Schuchardt wrote: > On 11/11/20 10:18 AM, Ilias Apalodimas wrote: >> Since U-boot EFI implementation is getting richer it makes sense to >> add support for EFI_TCG2_PROTOCOL taking advantage of any hardware TPM >> available on the device. >> >> This is the initial implementation of the protocol which only adds >> support for GetCapability(). It's limited in the newer and safer >> TPMv2 devices. >> >> Signed-off-by: Ilias Apalodimas <ilias.apalodi...@linaro.org> >> --- >> * changes since v3: >> - added check for maximum number of PCRs allowed >> - replaced multiple return Xl with goto out tags >> * changes since v2: >> - added description about include/efi_tcg2.h >> - switch bool to u8 for tpm_present_flag >> - removed superfluous 'default n' from Kconfig >> - use 'goto 'tag' when possible >> >> * changes since v1: >> - change return variable of platform_get_tpm2_device() when used >> - since more headers were included in patch #2 use them in offset >> calculations for all tpm commands >> - change the size of the response buffer regardless of what >> tpm2_get_capability() is doing >> include/efi_loader.h | 2 + >> include/efi_tcg2.h | 94 +++++++ >> lib/efi_loader/Kconfig | 7 + >> lib/efi_loader/Makefile | 1 + >> lib/efi_loader/efi_setup.c | 7 + >> lib/efi_loader/efi_tcg2.c | 539 +++++++++++++++++++++++++++++++++++++ >> 6 files changed, 650 insertions(+) >> create mode 100644 include/efi_tcg2.h >> create mode 100644 lib/efi_loader/efi_tcg2.c >> >> diff --git a/include/efi_loader.h b/include/efi_loader.h >> index f550ced56876..e5015d865ec9 100644 >> --- a/include/efi_loader.h >> +++ b/include/efi_loader.h >> @@ -405,6 +405,8 @@ efi_status_t efi_console_register(void); >> efi_status_t efi_disk_register(void); >> /* Called by efi_init_obj_list() to install EFI_RNG_PROTOCOL */ >> efi_status_t efi_rng_register(void); >> +/* Called by efi_init_obj_list() to install EFI_TCG2_PROTOCOL */ >> +efi_status_t efi_tcg2_register(void); >> /* Create handles and protocols for the partitions of a block device */ >> int efi_disk_create_partitions(efi_handle_t parent, struct blk_desc *desc, >> const char *if_typename, int diskid, >> diff --git a/include/efi_tcg2.h b/include/efi_tcg2.h >> new file mode 100644 >> index 000000000000..4214f767eaba >> --- /dev/null >> +++ b/include/efi_tcg2.h >> @@ -0,0 +1,94 @@ >> +/* SPDX-License-Identifier: GPL-2.0+ */ >> +/* >> + * Defines data structures and APIs that allow an OS to interact with UEFI >> + * firmware to query information about the device >> + * >> + * Copyright (c) 2020, Linaro Limited >> + */ >> + >> +#if !defined _EFI_TCG2_PROTOCOL_H_ >> +#define _EFI_TCG2_PROTOCOL_H_ >> + >> +#include <tpm-v2.h> >> + >> +#define EFI_TCG2_PROTOCOL_GUID \ >> + EFI_GUID(0x607f766c, 0x7455, 0x42be, 0x93, \ >> + 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f) >> + >> +/* TPMV2 only */ >> +#define TCG2_EVENT_LOG_FORMAT_TCG_2 0x00000002 >> + >> +/* SHA1, SHA256, SHA384, SHA512, TPM_ALG_SM3_256 */ >> +#define MAX_HASH_COUNT 5 >> +/* Algorithm Registry */ >> +#define EFI_TCG2_BOOT_HASH_ALG_SHA1 0x00000001 >> +#define EFI_TCG2_BOOT_HASH_ALG_SHA256 0x00000002 >> +#define EFI_TCG2_BOOT_HASH_ALG_SHA384 0x00000004 >> +#define EFI_TCG2_BOOT_HASH_ALG_SHA512 0x00000008 >> +#define EFI_TCG2_BOOT_HASH_ALG_SM3_256 0x00000010 >> + >> +typedef u32 efi_tcg_event_log_bitmap; >> +typedef u32 efi_tcg_event_log_format; >> +typedef u32 efi_tcg_event_algorithm_bitmap; >> + >> +struct efi_tcg2_version { >> + u8 major; >> + u8 minor; >> +}; >> + >> +struct efi_tcg2_event_header { >> + u32 header_size; >> + u16 header_version; >> + u32 pcr_index; >> + u32 event_type; >> +} __packed; >> + >> +struct efi_tcg2_event { >> + u32 size; >> + struct efi_tcg2_event_header header; >> + u8 event[]; >> +} __packed; >> + >> +struct efi_tcg2_boot_service_capability { >> + u8 size; >> + struct efi_tcg2_version structure_version; >> + struct efi_tcg2_version protocol_version; >> + efi_tcg_event_algorithm_bitmap hash_algorithm_bitmap; >> + efi_tcg_event_log_bitmap supported_event_logs; >> + u8 tpm_present_flag; >> + u16 max_command_size; >> + u16 max_response_size; >> + u32 manufacturer_id; >> + u32 number_of_pcr_banks; >> + efi_tcg_event_algorithm_bitmap active_pcr_banks; >> +}; >> + >> +#define boot_service_capability_min \ >> + sizeof(struct efi_tcg2_boot_service_capability) - \ >> + offsetof(struct efi_tcg2_boot_service_capability, number_of_pcr_banks) >> + >> +struct efi_tcg2_protocol { >> + efi_status_t (EFIAPI * get_capability)(struct efi_tcg2_protocol *this, >> + struct >> efi_tcg2_boot_service_capability *capability); >> + efi_status_t (EFIAPI * get_eventlog)(struct efi_tcg2_protocol *this, >> + efi_tcg_event_log_format >> log_format, >> + u64 *event_log_location, u64 >> *event_log_last_entry, >> + bool *event_log_truncated); >> + efi_status_t (EFIAPI * hash_log_extend_event)(struct efi_tcg2_protocol >> *this, >> + u64 flags, u64 >> data_to_hash, >> + u64 data_to_hash_len, >> + struct efi_tcg2_event >> *efi_tcg_event); >> + efi_status_t (EFIAPI * submit_command)(struct efi_tcg2_protocol *this, >> + u32 input_parameter_block_size, >> + u8 *input_parameter_block, >> + u32 output_parameter_block_size, >> + u8 *output_parameter_block); >> + efi_status_t (EFIAPI * get_active_pcr_banks)(struct efi_tcg2_protocol >> *this, >> + u32 *active_pcr_banks); >> + efi_status_t (EFIAPI * set_active_pcr_banks)(struct efi_tcg2_protocol >> *this, >> + u32 active_pcr_banks); >> + efi_status_t (EFIAPI * get_result_of_set_active_pcr_banks)(struct >> efi_tcg2_protocol *this, >> + u32 >> *operation_present, >> + u32 >> *response); >> +}; >> +#endif >> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig >> index 075481428cdf..29ea14b2ee2a 100644 >> --- a/lib/efi_loader/Kconfig >> +++ b/lib/efi_loader/Kconfig >> @@ -184,6 +184,13 @@ config EFI_RNG_PROTOCOL >> Provide a EFI_RNG_PROTOCOL implementation using the hardware random >> number generator of the platform. >> >> +config EFI_TCG2_PROTOCOL >> + bool "EFI_TCG2_PROTOCOL support" >> + depends on TPM_V2 >> + help >> + Provide a EFI_TCG2_PROTOCOL implementation using the TPM hardware >> + of the platform. >> + >> config EFI_LOAD_FILE2_INITRD >> bool "EFI_FILE_LOAD2_PROTOCOL for Linux initial ramdisk" >> default n >> diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile >> index 8892fb01e125..cd4b252a417c 100644 >> --- a/lib/efi_loader/Makefile >> +++ b/lib/efi_loader/Makefile >> @@ -53,6 +53,7 @@ obj-$(CONFIG_NET) += efi_net.o >> obj-$(CONFIG_GENERATE_ACPI_TABLE) += efi_acpi.o >> obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += efi_smbios.o >> obj-$(CONFIG_EFI_RNG_PROTOCOL) += efi_rng.o >> +obj-$(CONFIG_EFI_TCG2_PROTOCOL) += efi_tcg2.o >> obj-$(CONFIG_EFI_LOAD_FILE2_INITRD) += efi_load_initrd.o >> obj-y += efi_signature.o >> >> diff --git a/lib/efi_loader/efi_setup.c b/lib/efi_loader/efi_setup.c >> index 45226c5c1a53..e206b60bb82c 100644 >> --- a/lib/efi_loader/efi_setup.c >> +++ b/lib/efi_loader/efi_setup.c >> @@ -156,6 +156,13 @@ efi_status_t efi_init_obj_list(void) >> if (ret != EFI_SUCCESS) >> goto out; >> } >> + >> + if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { >> + ret = efi_tcg2_register(); >> + if (ret != EFI_SUCCESS) >> + goto out; >> + } >> + >> /* Initialize variable services */ >> ret = efi_init_variables(); >> if (ret != EFI_SUCCESS) >> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c >> new file mode 100644 >> index 000000000000..d600cff66af1 >> --- /dev/null >> +++ b/lib/efi_loader/efi_tcg2.c >> @@ -0,0 +1,539 @@ >> +// SPDX-License-Identifier: GPL-2.0+ >> +/* >> + * Defines APIs that allow an OS to interact with UEFI firmware to query >> + * information about the device. >> + * >> https://trustedcomputinggroup.org/resource/tcg-efi-protocol-specification/ >> + * >> + * Copyright (c) 2020, Linaro Limited >> + */ >> + >> +#define LOG_CATEGORY LOGC_EFI >> +#include <common.h> >> +#include <dm.h> >> +#include <efi_loader.h> >> +#include <efi_tcg2.h> >> +#include <log.h> >> +#include <tpm-v2.h> >> +#include <linux/unaligned/access_ok.h> >> +#include <linux/unaligned/generic.h> >> + >> +DECLARE_GLOBAL_DATA_PTR; >> + >> +/* >> + * When requesting TPM2_CAP_TPM_PROPERTIES the value is on a standard >> offset. >> + * Since the current tpm2_get_capability() response buffers starts at >> + * 'union tpmu_capabilities data' of 'struct tpms_capability_data', >> calculate >> + * the response size and offset once for all consumers >> + */ >> +#define TPM2_RESPONSE_BUFFER_SIZE (sizeof(struct tpms_capability_data) - \ >> + offsetof(struct tpms_capability_data, data)) >> +#define properties_offset (offsetof(struct tpml_tagged_tpm_property, >> tpm_property) + \ >> + offsetof(struct tpms_tagged_property, value)) >> + >> +const efi_guid_t efi_guid_tcg2_protocol = EFI_TCG2_PROTOCOL_GUID; >> + >> +/** >> + * platform_get_tpm_device() - retrieve TPM device >> + * >> + * This function retrieves the udevice implementing a TPM >> + * >> + * This function may be overridden if special initialization is needed. >> + * >> + * @dev: udevice >> + * Return: status code >> + */ >> +__weak efi_status_t platform_get_tpm2_device(struct udevice **dev) >> +{ >> + int ret; >> + struct udevice *devp; >> + >> + ret = uclass_get_device(UCLASS_TPM, 0, &devp); > > 'dm tree' on the sandbox shows: > > tpm 0 [ ] google_sandbox_tpm |-- tpm > tpm 1 [ ] sandbox_tpm2 |-- tpm2 > > You have to loop over all TPM devices and look for one supporting TPMv2 > using tpm_get_version(dev).
You must also ensure that the device is probed. for_each_tpm_device() does the probing for you: __weak efi_status_t platform_get_tpm2_device(struct udevice **dev) { for_each_tpm_device((*dev)) { if (tpm_get_version(*dev) == TPM_V2) return EFI_SUCCESS; } return EFI_NOT_FOUND; } Best regards Heinrich