diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def index 8b413c380..db2264ff5 100644 --- a/grub-core/Makefile.core.def +++ b/grub-core/Makefile.core.def @@ -2489,6 +2489,13 @@ module = { common = commands/testspeed.c; }; +module = { + name = tpm; + common = commands/tpm.c; + efi = commands/efi/tpm.c; + enable = x86_64_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 000000000..563ceba7a --- /dev/null +++ b/grub-core/commands/efi/tpm.c @@ -0,0 +1,333 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + * + * EFI TPM support code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +typedef TCG_PCR_EVENT grub_tpm_event_t; + +static grub_efi_guid_t tpm_guid = EFI_TPM_GUID; +static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID; + +static grub_efi_handle_t *grub_tpm_handle; +static grub_uint8_t grub_tpm_version; + +static grub_int8_t tpm1_present = -1; +static grub_int8_t tpm2_present = -1; + +static grub_efi_boolean_t +grub_tpm1_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; + + if (tpm1_present != -1) + return (grub_efi_boolean_t) tpm1_present; + + caps.Size = (grub_uint8_t) sizeof (caps); + + status = efi_call_5 (tpm->status_check, tpm, &caps, &flags, &eventlog, + &lastevent); + + if (status != GRUB_EFI_SUCCESS || caps.TPMDeactivatedFlag + || !caps.TPMPresentFlag) + return tpm1_present = 0; + + return tpm1_present = 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); + + if (tpm2_present != -1) + return (grub_efi_boolean_t) tpm2_present; + + status = efi_call_2 (tpm->get_capability, tpm, &caps); + + if (status != GRUB_EFI_SUCCESS || !caps.TPMPresentFlag) + return tpm2_present = 0; + + return tpm2_present = 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; + + if (grub_tpm_handle != NULL) + { + *tpm_handle = &grub_tpm_handle; + *protocol_version = grub_tpm_version; + return 1; + } + + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm_guid, NULL, + &num_handles); + if (handles && num_handles > 0) + { + grub_tpm_handle = handles[0]; + *tpm_handle = handles[0]; + grub_tpm_version = 1; + *protocol_version = 1; + return 1; + } + + handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm2_guid, NULL, + &num_handles); + if (handles && num_handles > 0) + { + grub_tpm_handle = handles[0]; + *tpm_handle = handles[0]; + grub_tpm_version = 2; + *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, &tpm_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!grub_tpm1_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) +{ + grub_efi_status_t status; + grub_efi_tpm2_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, &tpm2_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!grub_tpm2_present (tpm)) + return 0; + + /* UEFI TPM protocol takes the raw operand block, no param block header. */ + status = efi_call_5 (tpm->submit_command, 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")); + } +} + +grub_err_t +grub_tpm_execute (PassThroughToTPM_InputParamBlock *inbuf, + PassThroughToTPM_OutputParamBlock *outbuf) +{ + grub_efi_handle_t tpm_handle; + grub_uint8_t protocol_version; + + /* Absence of a TPM isn't a failure. */ + if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) + return 0; + + if (protocol_version == 1) + return grub_tpm1_execute (tpm_handle, inbuf, outbuf); + else + return grub_tpm2_execute (tpm_handle, inbuf, outbuf); +} + +static grub_err_t +grub_tpm1_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + grub_tpm_event_t *event; + grub_efi_status_t status; + grub_efi_tpm_protocol_t *tpm; + grub_efi_physical_address_t lastevent; + grub_uint32_t algorithm; + grub_uint32_t eventnum = 0; + + tpm = grub_efi_open_protocol (tpm_handle, &tpm_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!grub_tpm1_present (tpm)) + return 0; + + event = grub_zalloc (sizeof (*event) + grub_strlen (description) + 1); + if (!event) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + N_("cannot allocate TPM event buffer")); + + event->PCRIndex = pcr; + event->EventType = EV_IPL; + event->EventSize = grub_strlen (description) + 1; + grub_memcpy (event->Event, description, event->EventSize); + + algorithm = TCG_ALG_SHA; + status = efi_call_7 (tpm->log_extend_event, tpm, buf, (grub_uint64_t) size, + algorithm, event, &eventnum, &lastevent); + + 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_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, + grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + EFI_TCG2_EVENT *event; + grub_efi_status_t status; + grub_efi_tpm2_protocol_t *tpm; + + tpm = grub_efi_open_protocol (tpm_handle, &tpm2_guid, + GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (!grub_tpm2_present (tpm)) + return 0; + + event = + grub_zalloc (sizeof (EFI_TCG2_EVENT) + grub_strlen (description) + 1); + if (!event) + return grub_error (GRUB_ERR_OUT_OF_MEMORY, + N_("cannot allocate TPM event buffer")); + + event->Header.HeaderSize = sizeof (EFI_TCG2_EVENT_HEADER); + event->Header.HeaderVersion = 1; + event->Header.PCRIndex = pcr; + event->Header.EventType = EV_IPL; + event->Size = + sizeof (*event) - sizeof (event->Event) + grub_strlen (description) + 1; + grub_memcpy (event->Event, description, grub_strlen (description) + 1); + + status = efi_call_5 (tpm->hash_log_extend_event, tpm, 0, buf, + (grub_uint64_t) size, event); + + 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")); + } +} + +grub_err_t +grub_tpm_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + grub_efi_handle_t tpm_handle; + grub_efi_uint8_t protocol_version; + + if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) + return 0; + + if (protocol_version == 1) + return grub_tpm1_log_event (tpm_handle, buf, size, pcr, description); + else + return grub_tpm2_log_event (tpm_handle, buf, size, pcr, description); +} diff --git a/grub-core/commands/tpm.c b/grub-core/commands/tpm.c new file mode 100644 index 000000000..1441c494d --- /dev/null +++ b/grub-core/commands/tpm.c @@ -0,0 +1,102 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2018 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + * + * Core TPM support code. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +GRUB_MOD_LICENSE ("GPLv3+"); + +grub_err_t +grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + return grub_tpm_log_event (buf, size, pcr, description); +} + +static grub_err_t +grub_tpm_verify_init (grub_file_t io, + enum grub_file_type type __attribute__ ((unused)), + void **context, enum grub_verify_flags *flags) +{ + *context = io->name; + *flags |= GRUB_VERIFY_FLAGS_SINGLE_CHUNK; + return GRUB_ERR_NONE; +} + +static grub_err_t +grub_tpm_verify_write (void *context, void *buf, grub_size_t size) +{ + return grub_tpm_measure (buf, size, GRUB_BINARY_PCR, context); +} + +static grub_err_t +grub_tpm_verify_string (char *str, enum grub_verify_string_type type) +{ + const char *prefix = NULL; + char *description; + grub_err_t status; + + switch (type) + { + case GRUB_VERIFY_KERNEL_CMDLINE: + prefix = "kernel_cmdline: "; + break; + case GRUB_VERIFY_MODULE_CMDLINE: + prefix = "module_cmdline: "; + break; + case GRUB_VERIFY_COMMAND: + prefix = "grub_cmd: "; + break; + } + description = grub_malloc (grub_strlen (str) + grub_strlen (prefix) + 1); + if (!description) + return grub_errno; + grub_memcpy (description, prefix, grub_strlen (prefix)); + grub_memcpy (description + grub_strlen (prefix), str, + grub_strlen (str) + 1); + status = + grub_tpm_measure ((unsigned char *) str, grub_strlen (str), + GRUB_STRING_PCR, description); + grub_free (description); + return status; +} + +struct grub_file_verifier grub_tpm_verifier = { + .name = "tpm", + .init = grub_tpm_verify_init, + .write = grub_tpm_verify_write, + .verify_string = grub_tpm_verify_string, +}; + +GRUB_MOD_INIT (tpm) +{ + grub_verifier_register (&grub_tpm_verifier); +} + +GRUB_MOD_FINI (tpm) +{ + grub_verifier_unregister (&grub_tpm_verifier); +} diff --git a/grub-core/kern/dl.c b/grub-core/kern/dl.c index a02af418a..3bcf56aad 100644 --- a/grub-core/kern/dl.c +++ b/grub-core/kern/dl.c @@ -730,7 +730,7 @@ grub_dl_load_file (const char *filename) opens of the same device. */ grub_file_close (file); - grub_tpm_measure(core, size, GRUB_BINARY_PCR, "grub_module", filename); + grub_tpm_measure(core, size, GRUB_BINARY_PCR, filename); grub_print_error(); mod = grub_dl_load_core (core, size); diff --git a/grub-core/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c index a28316cc6..da499aba0 100644 --- a/grub-core/kern/i386/efi/init.c +++ b/grub-core/kern/i386/efi/init.c @@ -27,6 +27,7 @@ #include #include #include +#include void grub_machine_init (void) diff --git a/grub-core/kern/tpm.c b/grub-core/kern/tpm.c index e5e8fced6..9841d8d38 100644 --- a/grub-core/kern/tpm.c +++ b/grub-core/kern/tpm.c @@ -7,13 +7,8 @@ grub_err_t grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, - const char *kind, const char *description) + const char *description) { - grub_err_t ret; - char *desc = grub_xasprintf("%s %s", kind, description); - if (!desc) - return GRUB_ERR_OUT_OF_MEMORY; - ret = grub_tpm_log_event(buf, size, pcr, desc); - grub_free(desc); - return ret; + return grub_tpm_log_event (buf, size, pcr, description); } + diff --git a/grub-core/lib/cmdline.c b/grub-core/lib/cmdline.c index b37155053..ecfbe3409 100644 --- a/grub-core/lib/cmdline.c +++ b/grub-core/lib/cmdline.c @@ -106,9 +106,5 @@ grub_create_loader_cmdline (int argc, char *argv[], char *buf, *buf = 0; - grub_tpm_measure ((void *)orig_buf, grub_strlen (orig_buf), GRUB_ASCII_PCR, - "grub_kernel_cmdline", orig_buf); - grub_print_error(); - return grub_verify_string (orig_buf, type); } diff --git a/grub-core/loader/i386/efi/linux.c b/grub-core/loader/i386/efi/linux.c index 22a3618d8..fc3d949c9 100644 --- a/grub-core/loader/i386/efi/linux.c +++ b/grub-core/loader/i386/efi/linux.c @@ -169,8 +169,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)), argv[i]); goto fail; } - grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "grub_linuxefi", "Initrd"); - grub_print_error(); + // TODO figure out the GRUB_VERIFY_ equivalent for this one + //grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "Initrd"); + //grub_print_error(); ptr += cursize; grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); ptr += ALIGN_UP_OVERHEAD (cursize, 4); @@ -226,8 +227,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } - grub_tpm_measure (kernel, filelen, GRUB_BINARY_PCR, "grub_linuxefi", "Kernel"); - grub_print_error(); + // TODO figure out the GRUB_VERIFY_ equivalent for this one + //grub_tpm_measure (kernel, filelen, GRUB_BINARY_PCR, "Kernel"); + //grub_print_error(); if (! grub_linuxefi_secure_validate (kernel, filelen)) { diff --git a/grub-core/loader/i386/linux.c b/grub-core/loader/i386/linux.c index be746ce74..7841d6ce8 100644 --- a/grub-core/loader/i386/linux.c +++ b/grub-core/loader/i386/linux.c @@ -681,8 +681,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } - grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "grub_linux", "Kernel"); - grub_print_error(); + // TODO figure out the GRUB_VERIFY_ equivalent for this one + //grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "Kernel"); + //grub_print_error(); grub_memcpy (&lh, kernel, sizeof (lh)); diff --git a/grub-core/loader/i386/multiboot_mbi.c b/grub-core/loader/i386/multiboot_mbi.c index ee74a4b46..468349f84 100644 --- a/grub-core/loader/i386/multiboot_mbi.c +++ b/grub-core/loader/i386/multiboot_mbi.c @@ -174,8 +174,9 @@ grub_multiboot_load (grub_file_t file, const char *filename) return grub_errno; } - grub_tpm_measure((unsigned char*)buffer, len, GRUB_BINARY_PCR, "grub_multiboot", filename); - grub_print_error(); + // TODO figure out the GRUB_VERIFY_ equivalent for this one + //grub_tpm_measure((unsigned char*)buffer, len, GRUB_BINARY_PCR, filename); + //grub_print_error(); header = find_header (buffer, len); diff --git a/grub-core/loader/i386/pc/linux.c b/grub-core/loader/i386/pc/linux.c index 7493e7341..c25e0dad1 100644 --- a/grub-core/loader/i386/pc/linux.c +++ b/grub-core/loader/i386/pc/linux.c @@ -161,8 +161,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)), goto fail; } - grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "grub_linux16", "Kernel"); - grub_print_error(); + // TODO figure out the GRUB_VERIFY_ equivalent for this one + //grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "Kernel"); + //grub_print_error(); grub_memcpy (&lh, kernel, sizeof (lh)); kernel_offset = sizeof (lh); diff --git a/grub-core/loader/linux.c b/grub-core/loader/linux.c index e1079f140..4b185cb15 100644 --- a/grub-core/loader/linux.c +++ b/grub-core/loader/linux.c @@ -289,8 +289,9 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx, grub_initrd_close (initrd_ctx); return grub_errno; } - grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "grub_initrd", "Initrd"); - grub_print_error(); + // TODO figure out the GRUB_VERIFY_ equivalent for this one + //grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "Initrd"); + //grub_print_error(); ptr += cursize; } diff --git a/grub-core/loader/multiboot.c b/grub-core/loader/multiboot.c index d0f045628..c16489de9 100644 --- a/grub-core/loader/multiboot.c +++ b/grub-core/loader/multiboot.c @@ -438,8 +438,9 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)), } grub_file_close (file); - grub_tpm_measure (module, size, GRUB_BINARY_PCR, "grub_multiboot", argv[0]); - grub_print_error(); + // TODO figure out the GRUB_VERIFY_ equivalent for this one + //grub_tpm_measure (module, size, GRUB_BINARY_PCR, argv[0]); + //grub_print_error(); return GRUB_ERR_NONE; } diff --git a/grub-core/loader/multiboot_mbi2.c b/grub-core/loader/multiboot_mbi2.c index 1a48305fa..ab8d99c28 100644 --- a/grub-core/loader/multiboot_mbi2.c +++ b/grub-core/loader/multiboot_mbi2.c @@ -132,8 +132,9 @@ grub_multiboot2_load (grub_file_t file, const char *filename) COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0); - grub_tpm_measure ((unsigned char *)mld.buffer, len, GRUB_BINARY_PCR, "grub_multiboot", filename); - grub_print_error(); + // TODO figure out the GRUB_VERIFY_ equivalent for this one + //grub_tpm_measure ((unsigned char *)mld.buffer, len, GRUB_BINARY_PCR, filename); + //grub_print_error(); header = find_header (mld.buffer, len); diff --git a/grub-core/script/execute.c b/grub-core/script/execute.c index 9da5b10a5..0144c5698 100644 --- a/grub-core/script/execute.c +++ b/grub-core/script/execute.c @@ -960,9 +960,6 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd) argv.args[i]); } cmdstring[cmdlen - 1] = '\0'; - grub_tpm_measure ((unsigned char *)cmdstring, cmdlen, GRUB_ASCII_PCR, - "grub_cmd", cmdstring); - grub_print_error(); grub_verify_string (cmdstring, GRUB_VERIFY_COMMAND); grub_free (cmdstring); invert = 0; diff --git a/include/grub/efi/tpm.h b/include/grub/efi/tpm.h index 63d8a0fe7..2d7630137 100644 --- a/include/grub/efi/tpm.h +++ b/include/grub/efi/tpm.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2015 Free Software Foundation, Inc. + * Copyright (C) 2018 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,37 +22,54 @@ #define EFI_TPM_GUID {0xf541796d, 0xa62e, 0x4954, {0xa7, 0x75, 0x95, 0x84, 0xf6, 0x1b, 0x9c, 0xdd }}; #define EFI_TPM2_GUID {0x607f766c, 0x7455, 0x42be, {0x93, 0x0b, 0xe4, 0xd7, 0x6d, 0xb2, 0x72, 0x0f }}; -typedef struct { +#define TCG_ALG_SHA 0x00000004 + +/* These structs are as defined in the TCG EFI Protocol Specification, family 2.0. */ + +struct __TCG_VERSION +{ grub_efi_uint8_t Major; grub_efi_uint8_t Minor; grub_efi_uint8_t RevMajor; grub_efi_uint8_t RevMinor; -} TCG_VERSION; +}; +typedef struct __TCG_VERSION TCG_VERSION; -typedef struct _TCG_EFI_BOOT_SERVICE_CAPABILITY { - grub_efi_uint8_t Size; /// Size of this structure. - TCG_VERSION StructureVersion; - TCG_VERSION ProtocolSpecVersion; - grub_efi_uint8_t HashAlgorithmBitmap; /// Hash algorithms . - char TPMPresentFlag; /// 00h = TPM not present. - char TPMDeactivatedFlag; /// 01h = TPM currently deactivated. -} TCG_EFI_BOOT_SERVICE_CAPABILITY; +struct __TCG_EFI_BOOT_SERVICE_CAPABILITY +{ + /* Size of this structure. */ + grub_efi_uint8_t Size; + TCG_VERSION StructureVersion; + TCG_VERSION ProtocolSpecVersion; + /* Hash algorithms supported by this TPM. */ + grub_efi_uint8_t HashAlgorithmBitmap; + /* 1 if TPM present. */ + char TPMPresentFlag; + /* 1 if TPM deactivated. */ + char TPMDeactivatedFlag; +}; +typedef struct __TCG_EFI_BOOT_SERVICE_CAPABILITY TCG_EFI_BOOT_SERVICE_CAPABILITY; -typedef struct { +struct tdTCG_PCR_EVENT +{ grub_efi_uint32_t PCRIndex; grub_efi_uint32_t EventType; - grub_efi_uint8_t digest[20]; + grub_efi_uint8_t digest[20]; grub_efi_uint32_t EventSize; grub_efi_uint8_t Event[1]; -} TCG_PCR_EVENT; +}; +typedef struct tdTCG_PCR_EVENT TCG_PCR_EVENT; struct grub_efi_tpm_protocol { grub_efi_status_t (*status_check) (struct grub_efi_tpm_protocol *this, - TCG_EFI_BOOT_SERVICE_CAPABILITY *ProtocolCapability, + TCG_EFI_BOOT_SERVICE_CAPABILITY * + ProtocolCapability, grub_efi_uint32_t *TCGFeatureFlags, - grub_efi_physical_address_t *EventLogLocation, - grub_efi_physical_address_t *EventLogLastEntry); + grub_efi_physical_address_t * + EventLogLocation, + grub_efi_physical_address_t * + EventLogLastEntry); grub_efi_status_t (*hash_all) (struct grub_efi_tpm_protocol *this, grub_efi_uint8_t *HashData, grub_efi_uint64_t HashLen, @@ -63,18 +80,24 @@ struct grub_efi_tpm_protocol TCG_PCR_EVENT *TCGLogData, grub_efi_uint32_t *EventNumber, grub_efi_uint32_t Flags); - grub_efi_status_t (*pass_through_to_tpm) (struct grub_efi_tpm_protocol *this, - grub_efi_uint32_t TpmInputParameterBlockSize, - grub_efi_uint8_t *TpmInputParameterBlock, - grub_efi_uint32_t TpmOutputParameterBlockSize, - grub_efi_uint8_t *TpmOutputParameterBlock); + grub_efi_status_t (*pass_through_to_tpm) (struct grub_efi_tpm_protocol * + this, + grub_efi_uint32_t + TpmInputParameterBlockSize, + grub_efi_uint8_t * + TpmInputParameterBlock, + grub_efi_uint32_t + TpmOutputParameterBlockSize, + grub_efi_uint8_t * + TpmOutputParameterBlock); grub_efi_status_t (*log_extend_event) (struct grub_efi_tpm_protocol *this, grub_efi_physical_address_t HashData, grub_efi_uint64_t HashDataLen, grub_efi_uint32_t AlgorithmId, TCG_PCR_EVENT *TCGLogData, grub_efi_uint32_t *EventNumber, - grub_efi_physical_address_t *EventLogLastEntry); + grub_efi_physical_address_t * + EventLogLastEntry); }; typedef struct grub_efi_tpm_protocol grub_efi_tpm_protocol_t; @@ -83,24 +106,28 @@ typedef grub_efi_uint32_t EFI_TCG2_EVENT_LOG_BITMAP; typedef grub_efi_uint32_t EFI_TCG2_EVENT_LOG_FORMAT; typedef grub_efi_uint32_t EFI_TCG2_EVENT_ALGORITHM_BITMAP; -typedef struct tdEFI_TCG2_VERSION { +struct tdEFI_TCG2_VERSION +{ grub_efi_uint8_t Major; grub_efi_uint8_t Minor; -} GRUB_PACKED EFI_TCG2_VERSION; +} GRUB_PACKED; +typedef struct tdEFI_TCG2_VERSION EFI_TCG2_VERSION; -typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY { - grub_efi_uint8_t Size; - EFI_TCG2_VERSION StructureVersion; - EFI_TCG2_VERSION ProtocolVersion; +struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY +{ + grub_efi_uint8_t Size; + EFI_TCG2_VERSION StructureVersion; + EFI_TCG2_VERSION ProtocolVersion; EFI_TCG2_EVENT_ALGORITHM_BITMAP HashAlgorithmBitmap; - EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs; - grub_efi_boolean_t TPMPresentFlag; - grub_efi_uint16_t MaxCommandSize; - grub_efi_uint16_t MaxResponseSize; - grub_efi_uint32_t ManufacturerID; - grub_efi_uint32_t NumberOfPcrBanks; + EFI_TCG2_EVENT_LOG_BITMAP SupportedEventLogs; + grub_efi_boolean_t TPMPresentFlag; + grub_efi_uint16_t MaxCommandSize; + grub_efi_uint16_t MaxResponseSize; + grub_efi_uint32_t ManufacturerID; + grub_efi_uint32_t NumberOfPcrBanks; EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks; -} EFI_TCG2_BOOT_SERVICE_CAPABILITY; +}; +typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY EFI_TCG2_BOOT_SERVICE_CAPABILITY; typedef grub_efi_uint32_t TCG_PCRINDEX; typedef grub_efi_uint32_t TCG_EVENTTYPE; @@ -112,42 +139,58 @@ typedef struct tdEFI_TCG2_EVENT_HEADER { TCG_EVENTTYPE EventType; } GRUB_PACKED EFI_TCG2_EVENT_HEADER; -typedef struct tdEFI_TCG2_EVENT { - grub_efi_uint32_t Size; +struct tdEFI_TCG2_EVENT +{ + grub_efi_uint32_t Size; EFI_TCG2_EVENT_HEADER Header; - grub_efi_uint8_t Event[1]; -} GRUB_PACKED EFI_TCG2_EVENT; + grub_efi_uint8_t Event[1]; +} GRUB_PACKED; +typedef struct tdEFI_TCG2_EVENT EFI_TCG2_EVENT; struct grub_efi_tpm2_protocol { grub_efi_status_t (*get_capability) (struct grub_efi_tpm2_protocol *this, - EFI_TCG2_BOOT_SERVICE_CAPABILITY *ProtocolCapability); + EFI_TCG2_BOOT_SERVICE_CAPABILITY * + ProtocolCapability); grub_efi_status_t (*get_event_log) (struct grub_efi_tpm2_protocol *this, - EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat, - grub_efi_physical_address_t *EventLogLocation, - grub_efi_physical_address_t *EventLogLastEntry, + EFI_TCG2_EVENT_LOG_FORMAT + EventLogFormat, + grub_efi_physical_address_t * + EventLogLocation, + grub_efi_physical_address_t * + EventLogLastEntry, grub_efi_boolean_t *EventLogTruncated); - grub_efi_status_t (*hash_log_extend_event) (struct grub_efi_tpm2_protocol *this, - grub_efi_uint64_t Flags, - grub_efi_physical_address_t DataToHash, + grub_efi_status_t (*hash_log_extend_event) (struct grub_efi_tpm2_protocol * + this, grub_efi_uint64_t Flags, + grub_efi_physical_address_t * + DataToHash, grub_efi_uint64_t DataToHashLen, EFI_TCG2_EVENT *EfiTcgEvent); grub_efi_status_t (*submit_command) (struct grub_efi_tpm2_protocol *this, - grub_efi_uint32_t InputParameterBlockSize, + grub_efi_uint32_t + InputParameterBlockSize, grub_efi_uint8_t *InputParameterBlock, - grub_efi_uint32_t OutputParameterBlockSize, - grub_efi_uint8_t *OutputParameterBlock); - grub_efi_status_t (*get_active_pcr_blanks) (struct grub_efi_tpm2_protocol *this, - grub_efi_uint32_t *ActivePcrBanks); - grub_efi_status_t (*set_active_pcr_banks) (struct grub_efi_tpm2_protocol *this, - grub_efi_uint32_t ActivePcrBanks); - grub_efi_status_t (*get_result_of_set_active_pcr_banks) (struct grub_efi_tpm2_protocol *this, - grub_efi_uint32_t *OperationPresent, - grub_efi_uint32_t *Response); + grub_efi_uint32_t + OutputParameterBlockSize, + grub_efi_uint8_t * + OutputParameterBlock); + grub_efi_status_t (*get_active_pcr_blanks) (struct grub_efi_tpm2_protocol * + this, + grub_efi_uint32_t * + ActivePcrBanks); + grub_efi_status_t (*set_active_pcr_banks) (struct grub_efi_tpm2_protocol * + this, + grub_efi_uint32_t + ActivePcrBanks); + grub_efi_status_t (*get_result_of_set_active_pcr_banks) (struct + grub_efi_tpm2_protocol + *this, + grub_efi_uint32_t * + OperationPresent, + grub_efi_uint32_t * + Response); }; typedef struct grub_efi_tpm2_protocol grub_efi_tpm2_protocol_t; -#define TCG_ALG_SHA 0x00000004 - #endif diff --git a/include/grub/tpm.h b/include/grub/tpm.h index 972a5edc8..dfcbe8372 100644 --- a/include/grub/tpm.h +++ b/include/grub/tpm.h @@ -1,6 +1,6 @@ /* * GRUB -- GRand Unified Bootloader - * Copyright (C) 2015 Free Software Foundation, Inc. + * Copyright (C) 2018 Free Software Foundation, Inc. * * GRUB is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,76 +19,64 @@ #ifndef GRUB_TPM_HEADER #define GRUB_TPM_HEADER 1 +#define GRUB_STRING_PCR 8 +#define GRUB_BINARY_PCR 9 + #define SHA1_DIGEST_SIZE 20 -#define TPM_BASE 0x0 -#define TPM_SUCCESS TPM_BASE +#define TPM_BASE 0x0 +#define TPM_SUCCESS TPM_BASE #define TPM_AUTHFAIL (TPM_BASE + 0x1) #define TPM_BADINDEX (TPM_BASE + 0x2) -#define GRUB_ASCII_PCR 8 -#define GRUB_BINARY_PCR 9 - #define TPM_TAG_RQU_COMMAND 0x00C1 #define TPM_ORD_Extend 0x14 #define EV_IPL 0x0d -/* TCG_PassThroughToTPM Input Parameter Block */ -typedef struct { - grub_uint16_t IPBLength; - grub_uint16_t Reserved1; - grub_uint16_t OPBLength; - grub_uint16_t Reserved2; - grub_uint8_t TPMOperandIn[1]; +/* TCG_PassThroughToTPM Input Parameter Block. */ +typedef struct +{ + grub_uint16_t IPBLength; + grub_uint16_t Reserved1; + grub_uint16_t OPBLength; + grub_uint16_t Reserved2; + grub_uint8_t TPMOperandIn[1]; } GRUB_PACKED PassThroughToTPM_InputParamBlock; -/* TCG_PassThroughToTPM Output Parameter Block */ -typedef struct { - grub_uint16_t OPBLength; - grub_uint16_t Reserved; - grub_uint8_t TPMOperandOut[1]; +/* TCG_PassThroughToTPM Output Parameter Block. */ +typedef struct +{ + grub_uint16_t OPBLength; + grub_uint16_t Reserved; + grub_uint8_t TPMOperandOut[1]; } GRUB_PACKED PassThroughToTPM_OutputParamBlock; -typedef struct { - grub_uint16_t tag; - grub_uint32_t paramSize; - grub_uint32_t ordinal; - grub_uint32_t pcrNum; - grub_uint8_t inDigest[SHA1_DIGEST_SIZE]; /* The 160 bit value representing the event to be recorded. */ +typedef struct +{ + grub_uint16_t tag; + grub_uint32_t paramSize; + grub_uint32_t ordinal; + grub_uint32_t pcrNum; + /* The 160 bit value representing the event to be recorded. */ + grub_uint8_t inDigest[SHA1_DIGEST_SIZE]; } GRUB_PACKED ExtendIncoming; -/* TPM_Extend Outgoing Operand */ -typedef struct { - grub_uint16_t tag; - grub_uint32_t paramSize; - grub_uint32_t returnCode; - grub_uint8_t outDigest[SHA1_DIGEST_SIZE]; /* The PCR value after execution of the command. */ +/* TPM_Extend Outgoing Operand. */ +typedef struct +{ + grub_uint16_t tag; + grub_uint32_t paramSize; + grub_uint32_t returnCode; + /* The PCR value after execution of the command. */ + grub_uint8_t outDigest[SHA1_DIGEST_SIZE]; } GRUB_PACKED ExtendOutgoing; -grub_err_t EXPORT_FUNC(grub_tpm_measure) (unsigned char *buf, grub_size_t size, - grub_uint8_t pcr, const char *kind, - const char *description); -#if defined (GRUB_MACHINE_EFI) || defined (GRUB_MACHINE_PCBIOS) -grub_err_t grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf, - PassThroughToTPM_OutputParamBlock *outbuf); -grub_err_t grub_tpm_log_event(unsigned char *buf, grub_size_t size, - grub_uint8_t pcr, const char *description); -#else -static inline grub_err_t grub_tpm_execute( - PassThroughToTPM_InputParamBlock *inbuf __attribute__ ((unused)), - PassThroughToTPM_OutputParamBlock *outbuf __attribute__ ((unused))) -{ - return 0; -}; -static inline grub_err_t grub_tpm_log_event( - unsigned char *buf __attribute__ ((unused)), - grub_size_t size __attribute__ ((unused)), - grub_uint8_t pcr __attribute__ ((unused)), - const char *description __attribute__ ((unused))) -{ - return 0; -}; -#endif - +grub_err_t grub_tpm_measure (unsigned char *buf, grub_size_t size, + grub_uint8_t pcr, const char *description); +grub_err_t grub_tpm_init (void); +grub_err_t grub_tpm_execute (PassThroughToTPM_InputParamBlock *inbuf, + PassThroughToTPM_OutputParamBlock *outbuf); +grub_err_t grub_tpm_log_event (unsigned char *buf, grub_size_t size, + grub_uint8_t pcr, const char *description); #endif