grub-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 3/3] Core TPM support


From: Matthew Garrett
Subject: [PATCH 3/3] Core TPM support
Date: Wed, 14 Jun 2017 17:42:45 -0700

Add support for performing basic TPM measurements. Right now this only
supports extending PCRs statically and only on UEFI.
---
 grub-core/Makefile.am          |   1 +
 grub-core/Makefile.core.def    |   2 +
 grub-core/kern/efi/tpm.c       | 282 +++++++++++++++++++++++++++++++++++++++++
 grub-core/kern/i386/efi/init.c |   2 +
 grub-core/kern/tpm.c           |  81 ++++++++++++
 include/grub/efi/tpm.h         | 153 ++++++++++++++++++++++
 include/grub/tpm.h             |  94 ++++++++++++++
 7 files changed, 615 insertions(+)
 create mode 100644 grub-core/kern/efi/tpm.c
 create mode 100644 grub-core/kern/tpm.c
 create mode 100644 include/grub/efi/tpm.h
 create mode 100644 include/grub/tpm.h

diff --git a/grub-core/Makefile.am b/grub-core/Makefile.am
index ef2b66e0f..cc641bc36 100644
--- a/grub-core/Makefile.am
+++ b/grub-core/Makefile.am
@@ -92,6 +92,7 @@ KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/term.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/time.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/mm_private.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/net.h
+KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/tpm.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/memory.h
 KERNEL_HEADER_FILES += $(top_srcdir)/include/grub/verify.h
 
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
index ab0f29960..2bdb6cafd 100644
--- a/grub-core/Makefile.core.def
+++ b/grub-core/Makefile.core.def
@@ -129,6 +129,7 @@ kernel = {
   common = kern/rescue_parser.c;
   common = kern/rescue_reader.c;
   common = kern/term.c;
+  common = kern/tpm.c;
   common = kern/verifiers.c;
 
   noemu = kern/compiler-rt.c;
@@ -192,6 +193,7 @@ kernel = {
   efi = term/efi/console.c;
   efi = kern/acpi.c;
   efi = kern/efi/acpi.c;
+  efi = kern/efi/tpm.c;
   i386_coreboot = kern/i386/pc/acpi.c;
   i386_multiboot = kern/i386/pc/acpi.c;
   i386_coreboot = kern/acpi.c;
diff --git a/grub-core/kern/efi/tpm.c b/grub-core/kern/efi/tpm.c
new file mode 100644
index 000000000..c9fb3c133
--- /dev/null
+++ b/grub-core/kern/efi/tpm.c
@@ -0,0 +1,282 @@
+#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>
+
+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, &caps, &flags, &eventlog,
+                     &lastevent);
+
+  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, &caps);
+
+  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, &tpm_guid, NULL,
+                                   &num_handles);
+  if (handles && num_handles > 0) {
+    *tpm_handle = handles[0];
+    *protocol_version = 1;
+    return 1;
+  }
+
+  handles = grub_efi_locate_handle (GRUB_EFI_BY_PROTOCOL, &tpm2_guid, NULL,
+                                   &num_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, &tpm_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)
+{
+  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;
+
+  /* It's not a hard failure for there to be no TPM */
+  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);
+  }
+}
+
+typedef struct {
+       grub_uint32_t pcrindex;
+       grub_uint32_t eventtype;
+       grub_uint8_t digest[20];
+       grub_uint32_t eventsize;
+       grub_uint8_t event[1];
+} Event;
+
+
+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)
+{
+  Event *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_tpm_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/kern/i386/efi/init.c b/grub-core/kern/i386/efi/init.c
index a28316cc6..7306df91e 100644
--- a/grub-core/kern/i386/efi/init.c
+++ b/grub-core/kern/i386/efi/init.c
@@ -27,12 +27,14 @@
 #include <grub/efi/efi.h>
 #include <grub/i386/tsc.h>
 #include <grub/loader.h>
+#include <grub/tpm.h>
 
 void
 grub_machine_init (void)
 {
   grub_efi_init ();
   grub_tsc_init ();
+  grub_tpm_init ();
 }
 
 void
diff --git a/grub-core/kern/tpm.c b/grub-core/kern/tpm.c
new file mode 100644
index 000000000..62972ec36
--- /dev/null
+++ b/grub-core/kern/tpm.c
@@ -0,0 +1,81 @@
+#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>
+
+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, 9, context);
+}
+
+static void
+grub_tpm_verify_close (void *ctxt __attribute__ ((unused)))
+{
+  return;
+}
+
+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), 8,
+                            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,
+  .close = grub_tpm_verify_close,
+  .verify_string = grub_tpm_verify_string,
+};
+
+grub_err_t
+grub_tpm_init (void)
+{
+  grub_verifier_register (&grub_tpm_verifier);
+  return GRUB_ERR_NONE;
+}
diff --git a/include/grub/efi/tpm.h b/include/grub/efi/tpm.h
new file mode 100644
index 000000000..e2aff4a3c
--- /dev/null
+++ b/include/grub/efi/tpm.h
@@ -0,0 +1,153 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2015  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/>.
+ */
+
+#ifndef GRUB_EFI_TPM_HEADER
+#define GRUB_EFI_TPM_HEADER 1
+
+#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 {
+  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_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;
+
+typedef struct {
+  grub_efi_uint32_t PCRIndex;
+  grub_efi_uint32_t EventType;
+  grub_efi_uint8_t digest[20];
+  grub_efi_uint32_t EventSize;
+  grub_efi_uint8_t  Event[1];
+} 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,
+                                    grub_efi_uint32_t *TCGFeatureFlags,
+                                    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,
+                                grub_efi_uint32_t AlgorithmId,
+                                grub_efi_uint64_t *HashedDataLen,
+                                grub_efi_uint8_t **HashedDataResult);
+  grub_efi_status_t (*log_event) (struct grub_efi_tpm_protocol *this,
+                                 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 (*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);
+};
+
+typedef struct grub_efi_tpm_protocol grub_efi_tpm_protocol_t;
+
+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 {
+  grub_efi_uint8_t Major;
+  grub_efi_uint8_t Minor;
+} GRUB_PACKED EFI_TCG2_VERSION;
+
+typedef 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_ALGORITHM_BITMAP ActivePcrBanks;
+} EFI_TCG2_BOOT_SERVICE_CAPABILITY;
+
+typedef grub_efi_uint32_t TCG_PCRINDEX;
+typedef grub_efi_uint32_t TCG_EVENTTYPE;
+
+typedef struct tdEFI_TCG2_EVENT_HEADER {
+  grub_efi_uint32_t HeaderSize;
+  grub_efi_uint16_t HeaderVersion;
+  TCG_PCRINDEX PCRIndex;
+  TCG_EVENTTYPE EventType;
+} GRUB_PACKED EFI_TCG2_EVENT_HEADER;
+
+typedef 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;
+
+struct grub_efi_tpm2_protocol
+{
+  grub_efi_status_t (*get_capability) (struct grub_efi_tpm2_protocol *this,
+                                      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,
+                                     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_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_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);
+};
+
+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
new file mode 100644
index 000000000..dd905b829
--- /dev/null
+++ b/include/grub/tpm.h
@@ -0,0 +1,94 @@
+/*
+ *  GRUB  --  GRand Unified Bootloader
+ *  Copyright (C) 2015  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/>.
+ */
+
+#ifndef GRUB_TPM_HEADER
+#define GRUB_TPM_HEADER 1
+
+#define SHA1_DIGEST_SIZE 20
+
+#define TPM_BASE 0x0
+#define TPM_SUCCESS TPM_BASE
+#define TPM_AUTHFAIL (TPM_BASE + 0x1)
+#define TPM_BADINDEX (TPM_BASE + 0x2)
+
+#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];
+} GRUB_PACKED PassThroughToTPM_InputParamBlock;
+
+/* 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. */
+} 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. */
+} GRUB_PACKED ExtendOutgoing;
+
+grub_err_t EXPORT_FUNC(grub_tpm_measure) (unsigned char *buf, grub_size_t size,
+                                         grub_uint8_t pcr,
+                                         const char *description);
+#if defined (GRUB_MACHINE_EFI)
+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);
+#else
+static inline grub_err_t grub_tpm_init(void) {};
+
+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
-- 
2.13.1.518.g3df882009-goog




reply via email to

[Prev in Thread] Current Thread [Next in Thread]