On Wed, Jul 05, 2017 at 02:19:57PM -0700, Matthew Garrett wrote:
> Add support for performing basic TPM measurements. Right now this only
> supports extending PCRs statically and only on UEFI.
> ---
> grub-core/Makefile.core.def| 7 +
> grub-core/commands/efi/tpm.c | 282
> +
> grub-core/commands/tpm.c | 87 +
> grub-core/kern/i386/efi/init.c | 1 +
> include/grub/efi/tpm.h | 153 ++
> include/grub/tpm.h | 74 +++
> 6 files changed, 604 insertions(+)
> create mode 100644 grub-core/commands/efi/tpm.c
> create mode 100644 grub-core/commands/tpm.c
> create mode 100644 include/grub/efi/tpm.h
> create mode 100644 include/grub/tpm.h
>
> diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
> index 16c4d0ea5..ca1caa1fe 100644
> --- a/grub-core/Makefile.core.def
> +++ b/grub-core/Makefile.core.def
> @@ -2375,6 +2375,13 @@ module = {
>common = commands/testspeed.c;
> };
>
> +module = {
> + name = tpm;
> + common = commands/tpm.c;
> + efi = commands/efi/tpm.c;
> + enable = efi;
> +};
> +
> module = {
>name = tr;
>common = commands/tr.c;
> diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c
> new file mode 100644
> index 0..c9fb3c133
> --- /dev/null
> +++ b/grub-core/commands/efi/tpm.c
> @@ -0,0 +1,282 @@
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +#include
> +
> +static grub_efi_guid_t tpm_guid = EFI_TPM_GUID;
> +static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID;
> +
> +static grub_efi_boolean_t grub_tpm_present(grub_efi_tpm_protocol_t *tpm)
> +{
> + grub_efi_status_t status;
> + TCG_EFI_BOOT_SERVICE_CAPABILITY caps;
> + grub_uint32_t flags;
> + grub_efi_physical_address_t eventlog, lastevent;
> +
> + caps.Size = (grub_uint8_t)sizeof(caps);
> +
> + status = efi_call_5(tpm->status_check, tpm, , , ,
> + );
> +
> + if (status != GRUB_EFI_SUCCESS || caps.TPMDeactivatedFlag
> + || !caps.TPMPresentFlag)
> +return 0;
> +
> + return 1;
> +}
> +
> +static grub_efi_boolean_t grub_tpm2_present(grub_efi_tpm2_protocol_t *tpm)
> +{
> + grub_efi_status_t status;
> + EFI_TCG2_BOOT_SERVICE_CAPABILITY caps;
> +
> + caps.Size = (grub_uint8_t)sizeof(caps);
> +
> + status = efi_call_2(tpm->get_capability, tpm, );
> +
> + if (status != GRUB_EFI_SUCCESS || !caps.TPMPresentFlag)
> +return 0;
> +
> + return 1;
> +}
> +
> +static grub_efi_boolean_t grub_tpm_handle_find(grub_efi_handle_t *tpm_handle,
> +grub_efi_uint8_t
> *protocol_version)
> +{
> + grub_efi_handle_t *handles;
> + grub_efi_uintn_t num_handles;
> +
> + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, _guid, NULL,
> + _handles);
> + if (handles && num_handles > 0) {
> +*tpm_handle = handles[0];
> +*protocol_version = 1;
> +return 1;
> + }
> +
> + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, _guid, NULL,
> + _handles);
> + if (handles && num_handles > 0) {
> +*tpm_handle = handles[0];
> +*protocol_version = 2;
> +return 1;
> + }
> +
> + return 0;
> +}
> +
> +static grub_err_t
> +grub_tpm1_execute(grub_efi_handle_t tpm_handle,
> + PassThroughToTPM_InputParamBlock *inbuf,
> + PassThroughToTPM_OutputParamBlock *outbuf)
> +{
> + grub_efi_status_t status;
> + grub_efi_tpm_protocol_t *tpm;
> + grub_uint32_t inhdrsize = sizeof(*inbuf) - sizeof(inbuf->TPMOperandIn);
> + grub_uint32_t outhdrsize = sizeof(*outbuf) - sizeof(outbuf->TPMOperandOut);
> +
> + tpm = grub_efi_open_protocol (tpm_handle, _guid,
> + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
> +
> + if (!grub_tpm_present(tpm))
> +return 0;
> +
> + /* UEFI TPM protocol takes the raw operand block, no param block header */
> + status = efi_call_5 (tpm->pass_through_to_tpm, tpm,
> +inbuf->IPBLength - inhdrsize, inbuf->TPMOperandIn,
> +outbuf->OPBLength - outhdrsize, outbuf->TPMOperandOut);
> +
> + switch (status) {
> + case GRUB_EFI_SUCCESS:
> +return 0;
> + case GRUB_EFI_DEVICE_ERROR:
> +return grub_error (GRUB_ERR_IO, N_("Command failed"));
> + case GRUB_EFI_INVALID_PARAMETER:
> +return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Invalid parameter"));
> + case GRUB_EFI_BUFFER_TOO_SMALL:
> +return grub_error (GRUB_ERR_BAD_ARGUMENT, N_("Output buffer too small"));
> + case GRUB_EFI_NOT_FOUND:
> +return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("TPM unavailable"));
> + default:
> +return grub_error (GRUB_ERR_UNKNOWN_DEVICE, N_("Unknown TPM error"));
> + }
> +}
> +
> +static grub_err_t
> +grub_tpm2_execute(grub_efi_handle_t tpm_handle,
> + PassThroughToTPM_InputParamBlock *inbuf,
> + PassThroughToTPM_OutputParamBlock *outbuf)
> +{
> +