verifiers: Core TPM support

Add support for performing basic TPM measurements. Right now this only
supports extending PCRs statically and only on UEFI. In future we might
want to have some sort of mechanism for choosing which events get logged
to which PCRs, but this seems like a good default policy and we can wait
to see whether anyone  has a use case before adding more complexity.

Signed-off-by: Matthew Garrett <mjg59@google.com>
Reviewed-by: Daniel Kiper <daniel.kiper@oracle.com>
This commit is contained in:
Matthew Garrett 2018-11-29 11:28:09 -08:00 committed by Vincent Batts
parent 8d6447d496
commit f4f4e3c715
17 changed files with 616 additions and 146 deletions

View file

@ -2489,6 +2489,13 @@ module = {
common = commands/testspeed.c; common = commands/testspeed.c;
}; };
module = {
name = tpm;
common = commands/tpm.c;
efi = commands/efi/tpm.c;
enable = x86_64_efi;
};
module = { module = {
name = tr; name = tr;
common = commands/tr.c; common = commands/tr.c;

View file

@ -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 <http://www.gnu.org/licenses/>.
*
* EFI TPM support code.
*/
#include <grub/err.h>
#include <grub/i18n.h>
#include <grub/efi/api.h>
#include <grub/efi/efi.h>
#include <grub/efi/tpm.h>
#include <grub/mm.h>
#include <grub/tpm.h>
#include <grub/term.h>
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);
}

102
grub-core/commands/tpm.c Normal file
View file

@ -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 <http://www.gnu.org/licenses/>.
*
* Core TPM support code.
*/
#include <grub/err.h>
#include <grub/i18n.h>
#include <grub/misc.h>
#include <grub/mm.h>
#include <grub/tpm.h>
#include <grub/term.h>
#include <grub/verify.h>
#include <grub/dl.h>
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);
}

View file

@ -730,7 +730,7 @@ grub_dl_load_file (const char *filename)
opens of the same device. */ opens of the same device. */
grub_file_close (file); 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(); grub_print_error();
mod = grub_dl_load_core (core, size); mod = grub_dl_load_core (core, size);

View file

@ -27,6 +27,7 @@
#include <grub/efi/efi.h> #include <grub/efi/efi.h>
#include <grub/i386/tsc.h> #include <grub/i386/tsc.h>
#include <grub/loader.h> #include <grub/loader.h>
#include <grub/tpm.h>
void void
grub_machine_init (void) grub_machine_init (void)

View file

@ -7,13 +7,8 @@
grub_err_t grub_err_t
grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, 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; return grub_tpm_log_event (buf, size, pcr, description);
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;
} }

View file

@ -106,9 +106,5 @@ grub_create_loader_cmdline (int argc, char *argv[], char *buf,
*buf = 0; *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); return grub_verify_string (orig_buf, type);
} }

View file

@ -169,8 +169,9 @@ grub_cmd_initrd (grub_command_t cmd __attribute__ ((unused)),
argv[i]); argv[i]);
goto fail; goto fail;
} }
grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "grub_linuxefi", "Initrd"); // TODO figure out the GRUB_VERIFY_ equivalent for this one
grub_print_error(); //grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "Initrd");
//grub_print_error();
ptr += cursize; ptr += cursize;
grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4)); grub_memset (ptr, 0, ALIGN_UP_OVERHEAD (cursize, 4));
ptr += 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; goto fail;
} }
grub_tpm_measure (kernel, filelen, GRUB_BINARY_PCR, "grub_linuxefi", "Kernel"); // TODO figure out the GRUB_VERIFY_ equivalent for this one
grub_print_error(); //grub_tpm_measure (kernel, filelen, GRUB_BINARY_PCR, "Kernel");
//grub_print_error();
if (! grub_linuxefi_secure_validate (kernel, filelen)) if (! grub_linuxefi_secure_validate (kernel, filelen))
{ {

View file

@ -681,8 +681,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
} }
grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "grub_linux", "Kernel"); // TODO figure out the GRUB_VERIFY_ equivalent for this one
grub_print_error(); //grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "Kernel");
//grub_print_error();
grub_memcpy (&lh, kernel, sizeof (lh)); grub_memcpy (&lh, kernel, sizeof (lh));

View file

@ -174,8 +174,9 @@ grub_multiboot_load (grub_file_t file, const char *filename)
return grub_errno; return grub_errno;
} }
grub_tpm_measure((unsigned char*)buffer, len, GRUB_BINARY_PCR, "grub_multiboot", filename); // TODO figure out the GRUB_VERIFY_ equivalent for this one
grub_print_error(); //grub_tpm_measure((unsigned char*)buffer, len, GRUB_BINARY_PCR, filename);
//grub_print_error();
header = find_header (buffer, len); header = find_header (buffer, len);

View file

@ -161,8 +161,9 @@ grub_cmd_linux (grub_command_t cmd __attribute__ ((unused)),
goto fail; goto fail;
} }
grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "grub_linux16", "Kernel"); // TODO figure out the GRUB_VERIFY_ equivalent for this one
grub_print_error(); //grub_tpm_measure (kernel, len, GRUB_BINARY_PCR, "Kernel");
//grub_print_error();
grub_memcpy (&lh, kernel, sizeof (lh)); grub_memcpy (&lh, kernel, sizeof (lh));
kernel_offset = sizeof (lh); kernel_offset = sizeof (lh);

View file

@ -289,8 +289,9 @@ grub_initrd_load (struct grub_linux_initrd_context *initrd_ctx,
grub_initrd_close (initrd_ctx); grub_initrd_close (initrd_ctx);
return grub_errno; return grub_errno;
} }
grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "grub_initrd", "Initrd"); // TODO figure out the GRUB_VERIFY_ equivalent for this one
grub_print_error(); //grub_tpm_measure (ptr, cursize, GRUB_BINARY_PCR, "Initrd");
//grub_print_error();
ptr += cursize; ptr += cursize;
} }

View file

@ -438,8 +438,9 @@ grub_cmd_module (grub_command_t cmd __attribute__ ((unused)),
} }
grub_file_close (file); grub_file_close (file);
grub_tpm_measure (module, size, GRUB_BINARY_PCR, "grub_multiboot", argv[0]); // TODO figure out the GRUB_VERIFY_ equivalent for this one
grub_print_error(); //grub_tpm_measure (module, size, GRUB_BINARY_PCR, argv[0]);
//grub_print_error();
return GRUB_ERR_NONE; return GRUB_ERR_NONE;
} }

View file

@ -132,8 +132,9 @@ grub_multiboot2_load (grub_file_t file, const char *filename)
COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0); COMPILE_TIME_ASSERT (MULTIBOOT_HEADER_ALIGN % 4 == 0);
grub_tpm_measure ((unsigned char *)mld.buffer, len, GRUB_BINARY_PCR, "grub_multiboot", filename); // TODO figure out the GRUB_VERIFY_ equivalent for this one
grub_print_error(); //grub_tpm_measure ((unsigned char *)mld.buffer, len, GRUB_BINARY_PCR, filename);
//grub_print_error();
header = find_header (mld.buffer, len); header = find_header (mld.buffer, len);

View file

@ -960,9 +960,6 @@ grub_script_execute_cmdline (struct grub_script_cmd *cmd)
argv.args[i]); argv.args[i]);
} }
cmdstring[cmdlen - 1] = '\0'; 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_verify_string (cmdstring, GRUB_VERIFY_COMMAND);
grub_free (cmdstring); grub_free (cmdstring);
invert = 0; invert = 0;

View file

@ -1,6 +1,6 @@
/* /*
* GRUB -- GRand Unified Bootloader * 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 * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * 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_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 }}; #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 Major;
grub_efi_uint8_t Minor; grub_efi_uint8_t Minor;
grub_efi_uint8_t RevMajor; grub_efi_uint8_t RevMajor;
grub_efi_uint8_t RevMinor; grub_efi_uint8_t RevMinor;
} TCG_VERSION; };
typedef struct __TCG_VERSION TCG_VERSION;
typedef struct _TCG_EFI_BOOT_SERVICE_CAPABILITY { struct __TCG_EFI_BOOT_SERVICE_CAPABILITY
grub_efi_uint8_t Size; /// Size of this structure. {
/* Size of this structure. */
grub_efi_uint8_t Size;
TCG_VERSION StructureVersion; TCG_VERSION StructureVersion;
TCG_VERSION ProtocolSpecVersion; TCG_VERSION ProtocolSpecVersion;
grub_efi_uint8_t HashAlgorithmBitmap; /// Hash algorithms . /* Hash algorithms supported by this TPM. */
char TPMPresentFlag; /// 00h = TPM not present. grub_efi_uint8_t HashAlgorithmBitmap;
char TPMDeactivatedFlag; /// 01h = TPM currently deactivated. /* 1 if TPM present. */
} TCG_EFI_BOOT_SERVICE_CAPABILITY; 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 PCRIndex;
grub_efi_uint32_t EventType; grub_efi_uint32_t EventType;
grub_efi_uint8_t digest[20]; grub_efi_uint8_t digest[20];
grub_efi_uint32_t EventSize; grub_efi_uint32_t EventSize;
grub_efi_uint8_t Event[1]; grub_efi_uint8_t Event[1];
} TCG_PCR_EVENT; };
typedef struct tdTCG_PCR_EVENT TCG_PCR_EVENT;
struct grub_efi_tpm_protocol struct grub_efi_tpm_protocol
{ {
grub_efi_status_t (*status_check) (struct grub_efi_tpm_protocol *this, 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_uint32_t *TCGFeatureFlags,
grub_efi_physical_address_t *EventLogLocation, grub_efi_physical_address_t *
grub_efi_physical_address_t *EventLogLastEntry); EventLogLocation,
grub_efi_physical_address_t *
EventLogLastEntry);
grub_efi_status_t (*hash_all) (struct grub_efi_tpm_protocol *this, grub_efi_status_t (*hash_all) (struct grub_efi_tpm_protocol *this,
grub_efi_uint8_t *HashData, grub_efi_uint8_t *HashData,
grub_efi_uint64_t HashLen, grub_efi_uint64_t HashLen,
@ -63,18 +80,24 @@ struct grub_efi_tpm_protocol
TCG_PCR_EVENT *TCGLogData, TCG_PCR_EVENT *TCGLogData,
grub_efi_uint32_t *EventNumber, grub_efi_uint32_t *EventNumber,
grub_efi_uint32_t Flags); grub_efi_uint32_t Flags);
grub_efi_status_t (*pass_through_to_tpm) (struct grub_efi_tpm_protocol *this, grub_efi_status_t (*pass_through_to_tpm) (struct grub_efi_tpm_protocol *
grub_efi_uint32_t TpmInputParameterBlockSize, this,
grub_efi_uint8_t *TpmInputParameterBlock, grub_efi_uint32_t
grub_efi_uint32_t TpmOutputParameterBlockSize, TpmInputParameterBlockSize,
grub_efi_uint8_t *TpmOutputParameterBlock); 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_status_t (*log_extend_event) (struct grub_efi_tpm_protocol *this,
grub_efi_physical_address_t HashData, grub_efi_physical_address_t HashData,
grub_efi_uint64_t HashDataLen, grub_efi_uint64_t HashDataLen,
grub_efi_uint32_t AlgorithmId, grub_efi_uint32_t AlgorithmId,
TCG_PCR_EVENT *TCGLogData, TCG_PCR_EVENT *TCGLogData,
grub_efi_uint32_t *EventNumber, 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; typedef struct grub_efi_tpm_protocol grub_efi_tpm_protocol_t;
@ -83,12 +106,15 @@ 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_LOG_FORMAT;
typedef grub_efi_uint32_t EFI_TCG2_EVENT_ALGORITHM_BITMAP; 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 Major;
grub_efi_uint8_t Minor; 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 { struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY
{
grub_efi_uint8_t Size; grub_efi_uint8_t Size;
EFI_TCG2_VERSION StructureVersion; EFI_TCG2_VERSION StructureVersion;
EFI_TCG2_VERSION ProtocolVersion; EFI_TCG2_VERSION ProtocolVersion;
@ -100,7 +126,8 @@ typedef struct tdEFI_TCG2_BOOT_SERVICE_CAPABILITY {
grub_efi_uint32_t ManufacturerID; grub_efi_uint32_t ManufacturerID;
grub_efi_uint32_t NumberOfPcrBanks; grub_efi_uint32_t NumberOfPcrBanks;
EFI_TCG2_EVENT_ALGORITHM_BITMAP ActivePcrBanks; 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_PCRINDEX;
typedef grub_efi_uint32_t TCG_EVENTTYPE; typedef grub_efi_uint32_t TCG_EVENTTYPE;
@ -112,42 +139,58 @@ typedef struct tdEFI_TCG2_EVENT_HEADER {
TCG_EVENTTYPE EventType; TCG_EVENTTYPE EventType;
} GRUB_PACKED EFI_TCG2_EVENT_HEADER; } GRUB_PACKED EFI_TCG2_EVENT_HEADER;
typedef struct tdEFI_TCG2_EVENT { struct tdEFI_TCG2_EVENT
{
grub_efi_uint32_t Size; grub_efi_uint32_t Size;
EFI_TCG2_EVENT_HEADER Header; EFI_TCG2_EVENT_HEADER Header;
grub_efi_uint8_t Event[1]; grub_efi_uint8_t Event[1];
} GRUB_PACKED EFI_TCG2_EVENT; } GRUB_PACKED;
typedef struct tdEFI_TCG2_EVENT EFI_TCG2_EVENT;
struct grub_efi_tpm2_protocol struct grub_efi_tpm2_protocol
{ {
grub_efi_status_t (*get_capability) (struct grub_efi_tpm2_protocol *this, 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, grub_efi_status_t (*get_event_log) (struct grub_efi_tpm2_protocol *this,
EFI_TCG2_EVENT_LOG_FORMAT EventLogFormat, EFI_TCG2_EVENT_LOG_FORMAT
grub_efi_physical_address_t *EventLogLocation, EventLogFormat,
grub_efi_physical_address_t *EventLogLastEntry, grub_efi_physical_address_t *
EventLogLocation,
grub_efi_physical_address_t *
EventLogLastEntry,
grub_efi_boolean_t *EventLogTruncated); grub_efi_boolean_t *EventLogTruncated);
grub_efi_status_t (*hash_log_extend_event) (struct grub_efi_tpm2_protocol *this, grub_efi_status_t (*hash_log_extend_event) (struct grub_efi_tpm2_protocol *
grub_efi_uint64_t Flags, this, grub_efi_uint64_t Flags,
grub_efi_physical_address_t DataToHash, grub_efi_physical_address_t *
DataToHash,
grub_efi_uint64_t DataToHashLen, grub_efi_uint64_t DataToHashLen,
EFI_TCG2_EVENT *EfiTcgEvent); EFI_TCG2_EVENT *EfiTcgEvent);
grub_efi_status_t (*submit_command) (struct grub_efi_tpm2_protocol *this, 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_uint8_t *InputParameterBlock,
grub_efi_uint32_t OutputParameterBlockSize, grub_efi_uint32_t
grub_efi_uint8_t *OutputParameterBlock); OutputParameterBlockSize,
grub_efi_status_t (*get_active_pcr_blanks) (struct grub_efi_tpm2_protocol *this, grub_efi_uint8_t *
grub_efi_uint32_t *ActivePcrBanks); OutputParameterBlock);
grub_efi_status_t (*set_active_pcr_banks) (struct grub_efi_tpm2_protocol *this, grub_efi_status_t (*get_active_pcr_blanks) (struct grub_efi_tpm2_protocol *
grub_efi_uint32_t ActivePcrBanks); this,
grub_efi_status_t (*get_result_of_set_active_pcr_banks) (struct grub_efi_tpm2_protocol *this, grub_efi_uint32_t *
grub_efi_uint32_t *OperationPresent, ActivePcrBanks);
grub_efi_uint32_t *Response); 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; typedef struct grub_efi_tpm2_protocol grub_efi_tpm2_protocol_t;
#define TCG_ALG_SHA 0x00000004
#endif #endif

View file

@ -1,6 +1,6 @@
/* /*
* GRUB -- GRand Unified Bootloader * 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 * GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
@ -19,6 +19,9 @@
#ifndef GRUB_TPM_HEADER #ifndef GRUB_TPM_HEADER
#define GRUB_TPM_HEADER 1 #define GRUB_TPM_HEADER 1
#define GRUB_STRING_PCR 8
#define GRUB_BINARY_PCR 9
#define SHA1_DIGEST_SIZE 20 #define SHA1_DIGEST_SIZE 20
#define TPM_BASE 0x0 #define TPM_BASE 0x0
@ -26,16 +29,14 @@
#define TPM_AUTHFAIL (TPM_BASE + 0x1) #define TPM_AUTHFAIL (TPM_BASE + 0x1)
#define TPM_BADINDEX (TPM_BASE + 0x2) #define TPM_BADINDEX (TPM_BASE + 0x2)
#define GRUB_ASCII_PCR 8
#define GRUB_BINARY_PCR 9
#define TPM_TAG_RQU_COMMAND 0x00C1 #define TPM_TAG_RQU_COMMAND 0x00C1
#define TPM_ORD_Extend 0x14 #define TPM_ORD_Extend 0x14
#define EV_IPL 0x0d #define EV_IPL 0x0d
/* TCG_PassThroughToTPM Input Parameter Block */ /* TCG_PassThroughToTPM Input Parameter Block. */
typedef struct { typedef struct
{
grub_uint16_t IPBLength; grub_uint16_t IPBLength;
grub_uint16_t Reserved1; grub_uint16_t Reserved1;
grub_uint16_t OPBLength; grub_uint16_t OPBLength;
@ -43,52 +44,39 @@ typedef struct {
grub_uint8_t TPMOperandIn[1]; grub_uint8_t TPMOperandIn[1];
} GRUB_PACKED PassThroughToTPM_InputParamBlock; } GRUB_PACKED PassThroughToTPM_InputParamBlock;
/* TCG_PassThroughToTPM Output Parameter Block */ /* TCG_PassThroughToTPM Output Parameter Block. */
typedef struct { typedef struct
{
grub_uint16_t OPBLength; grub_uint16_t OPBLength;
grub_uint16_t Reserved; grub_uint16_t Reserved;
grub_uint8_t TPMOperandOut[1]; grub_uint8_t TPMOperandOut[1];
} GRUB_PACKED PassThroughToTPM_OutputParamBlock; } GRUB_PACKED PassThroughToTPM_OutputParamBlock;
typedef struct { typedef struct
{
grub_uint16_t tag; grub_uint16_t tag;
grub_uint32_t paramSize; grub_uint32_t paramSize;
grub_uint32_t ordinal; grub_uint32_t ordinal;
grub_uint32_t pcrNum; grub_uint32_t pcrNum;
grub_uint8_t inDigest[SHA1_DIGEST_SIZE]; /* The 160 bit value representing the event to be recorded. */ /* The 160 bit value representing the event to be recorded. */
grub_uint8_t inDigest[SHA1_DIGEST_SIZE];
} GRUB_PACKED ExtendIncoming; } GRUB_PACKED ExtendIncoming;
/* TPM_Extend Outgoing Operand */ /* TPM_Extend Outgoing Operand. */
typedef struct { typedef struct
{
grub_uint16_t tag; grub_uint16_t tag;
grub_uint32_t paramSize; grub_uint32_t paramSize;
grub_uint32_t returnCode; grub_uint32_t returnCode;
grub_uint8_t outDigest[SHA1_DIGEST_SIZE]; /* The PCR value after execution of the command. */ /* The PCR value after execution of the command. */
grub_uint8_t outDigest[SHA1_DIGEST_SIZE];
} GRUB_PACKED ExtendOutgoing; } GRUB_PACKED ExtendOutgoing;
grub_err_t EXPORT_FUNC(grub_tpm_measure) (unsigned char *buf, grub_size_t size, grub_err_t grub_tpm_measure (unsigned char *buf, grub_size_t size,
grub_uint8_t pcr, const char *kind, grub_uint8_t pcr, const char *description);
const char *description); grub_err_t grub_tpm_init (void);
#if defined (GRUB_MACHINE_EFI) || defined (GRUB_MACHINE_PCBIOS) grub_err_t grub_tpm_execute (PassThroughToTPM_InputParamBlock *inbuf,
grub_err_t grub_tpm_execute(PassThroughToTPM_InputParamBlock *inbuf, PassThroughToTPM_OutputParamBlock *outbuf);
PassThroughToTPM_OutputParamBlock *outbuf); grub_err_t grub_tpm_log_event (unsigned char *buf, grub_size_t size,
grub_err_t grub_tpm_log_event(unsigned char *buf, grub_size_t size,
grub_uint8_t pcr, const char *description); 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
#endif #endif