|
|
d3c3ab |
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
|
d3c3ab |
From: Stefan Berger <stefanb@linux.ibm.com>
|
|
|
d3c3ab |
Date: Sun, 15 Mar 2020 12:37:10 -0400
|
|
|
d3c3ab |
Subject: [PATCH] ibmvtpm: Add support for trusted boot using a vTPM 2.0
|
|
|
d3c3ab |
|
|
|
d3c3ab |
Add support for trusted boot using a vTPM 2.0 on the IBM IEEE1275
|
|
|
d3c3ab |
PowerPC platform. With this patch grub now measures text and binary data
|
|
|
d3c3ab |
into the TPM's PCRs 8 and 9 in the same way as the x86_64 platform
|
|
|
d3c3ab |
does.
|
|
|
d3c3ab |
|
|
|
d3c3ab |
This patch requires Daniel Axtens's patches for claiming more memory.
|
|
|
d3c3ab |
|
|
|
d3c3ab |
For vTPM support to work on PowerVM, system driver levels 1010.30
|
|
|
d3c3ab |
or 1020.00 are required.
|
|
|
d3c3ab |
|
|
|
d3c3ab |
Note: Previous versions of firmware levels with the 2hash-ext-log
|
|
|
d3c3ab |
API call have a bug that, once this API call is invoked, has the
|
|
|
d3c3ab |
effect of disabling the vTPM driver under Linux causing an error
|
|
|
d3c3ab |
message to be displayed in the Linux kernel log. Those users will
|
|
|
d3c3ab |
have to update their machines to the firmware levels mentioned
|
|
|
d3c3ab |
above.
|
|
|
d3c3ab |
|
|
|
d3c3ab |
Cc: Eric Snowberg <eric.snowberg@oracle.com>
|
|
|
d3c3ab |
Signed-off-by: Stefan Berger <stefanb@linux.ibm.com>
|
|
|
d3c3ab |
(cherry picked from commit d3e5a8e6ecb8b87701135d97f45d27bbfbf731a2)
|
|
|
d3c3ab |
---
|
|
|
d3c3ab |
grub-core/Makefile.core.def | 7 ++
|
|
|
d3c3ab |
grub-core/commands/ieee1275/ibmvtpm.c | 152 ++++++++++++++++++++++++++++++++++
|
|
|
d3c3ab |
include/grub/ieee1275/ieee1275.h | 3 +
|
|
|
d3c3ab |
docs/grub.texi | 3 +-
|
|
|
d3c3ab |
4 files changed, 164 insertions(+), 1 deletion(-)
|
|
|
d3c3ab |
create mode 100644 grub-core/commands/ieee1275/ibmvtpm.c
|
|
|
d3c3ab |
|
|
|
d3c3ab |
diff --git a/grub-core/Makefile.core.def b/grub-core/Makefile.core.def
|
|
|
d3c3ab |
index 97abc01f06..407d68f917 100644
|
|
|
d3c3ab |
--- a/grub-core/Makefile.core.def
|
|
|
d3c3ab |
+++ b/grub-core/Makefile.core.def
|
|
|
d3c3ab |
@@ -1172,6 +1172,13 @@ module = {
|
|
|
d3c3ab |
enable = powerpc_ieee1275;
|
|
|
d3c3ab |
};
|
|
|
d3c3ab |
|
|
|
d3c3ab |
+module = {
|
|
|
d3c3ab |
+ name = tpm;
|
|
|
d3c3ab |
+ common = commands/tpm.c;
|
|
|
d3c3ab |
+ ieee1275 = commands/ieee1275/ibmvtpm.c;
|
|
|
d3c3ab |
+ enable = powerpc_ieee1275;
|
|
|
d3c3ab |
+};
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
module = {
|
|
|
d3c3ab |
name = terminal;
|
|
|
d3c3ab |
common = commands/terminal.c;
|
|
|
d3c3ab |
diff --git a/grub-core/commands/ieee1275/ibmvtpm.c b/grub-core/commands/ieee1275/ibmvtpm.c
|
|
|
d3c3ab |
new file mode 100644
|
|
|
d3c3ab |
index 0000000000..e68b8448bc
|
|
|
d3c3ab |
--- /dev/null
|
|
|
d3c3ab |
+++ b/grub-core/commands/ieee1275/ibmvtpm.c
|
|
|
d3c3ab |
@@ -0,0 +1,152 @@
|
|
|
d3c3ab |
+/*
|
|
|
d3c3ab |
+ * GRUB -- GRand Unified Bootloader
|
|
|
d3c3ab |
+ * Copyright (C) 2021 Free Software Foundation, Inc.
|
|
|
d3c3ab |
+ * Copyright (C) 2021 IBM Corporation
|
|
|
d3c3ab |
+ *
|
|
|
d3c3ab |
+ * GRUB is free software: you can redistribute it and/or modify
|
|
|
d3c3ab |
+ * it under the terms of the GNU General Public License as published by
|
|
|
d3c3ab |
+ * the Free Software Foundation, either version 3 of the License, or
|
|
|
d3c3ab |
+ * (at your option) any later version.
|
|
|
d3c3ab |
+ *
|
|
|
d3c3ab |
+ * GRUB is distributed in the hope that it will be useful,
|
|
|
d3c3ab |
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
d3c3ab |
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
d3c3ab |
+ * GNU General Public License for more details.
|
|
|
d3c3ab |
+ *
|
|
|
d3c3ab |
+ * You should have received a copy of the GNU General Public License
|
|
|
d3c3ab |
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
|
|
|
d3c3ab |
+ *
|
|
|
d3c3ab |
+ * IBM vTPM support code.
|
|
|
d3c3ab |
+ */
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+#include <grub/err.h>
|
|
|
d3c3ab |
+#include <grub/types.h>
|
|
|
d3c3ab |
+#include <grub/tpm.h>
|
|
|
d3c3ab |
+#include <grub/ieee1275/ieee1275.h>
|
|
|
d3c3ab |
+#include <grub/mm.h>
|
|
|
d3c3ab |
+#include <grub/misc.h>
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+static grub_ieee1275_ihandle_t tpm_ihandle;
|
|
|
d3c3ab |
+static grub_uint8_t tpm_version;
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+#define IEEE1275_IHANDLE_INVALID ((grub_ieee1275_ihandle_t)0)
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+static void
|
|
|
d3c3ab |
+tpm_get_tpm_version (void)
|
|
|
d3c3ab |
+{
|
|
|
d3c3ab |
+ grub_ieee1275_phandle_t vtpm;
|
|
|
d3c3ab |
+ char buffer[20];
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ if (!grub_ieee1275_finddevice ("/vdevice/vtpm", &vtpm) &&
|
|
|
d3c3ab |
+ !grub_ieee1275_get_property (vtpm, "compatible", buffer,
|
|
|
d3c3ab |
+ sizeof (buffer), NULL) &&
|
|
|
d3c3ab |
+ !grub_strcmp (buffer, "IBM,vtpm20"))
|
|
|
d3c3ab |
+ tpm_version = 2;
|
|
|
d3c3ab |
+}
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+static grub_err_t
|
|
|
d3c3ab |
+tpm_init (void)
|
|
|
d3c3ab |
+{
|
|
|
d3c3ab |
+ static int init_success = 0;
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ if (!init_success)
|
|
|
d3c3ab |
+ {
|
|
|
d3c3ab |
+ if (grub_ieee1275_open ("/vdevice/vtpm", &tpm_ihandle) < 0) {
|
|
|
d3c3ab |
+ tpm_ihandle = IEEE1275_IHANDLE_INVALID;
|
|
|
d3c3ab |
+ return GRUB_ERR_UNKNOWN_DEVICE;
|
|
|
d3c3ab |
+ }
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ init_success = 1;
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ tpm_get_tpm_version ();
|
|
|
d3c3ab |
+ }
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ return GRUB_ERR_NONE;
|
|
|
d3c3ab |
+}
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+static int
|
|
|
d3c3ab |
+ibmvtpm_2hash_ext_log (grub_uint8_t pcrindex,
|
|
|
d3c3ab |
+ grub_uint32_t eventtype,
|
|
|
d3c3ab |
+ const char *description,
|
|
|
d3c3ab |
+ grub_size_t description_size,
|
|
|
d3c3ab |
+ void *buf, grub_size_t size)
|
|
|
d3c3ab |
+{
|
|
|
d3c3ab |
+ struct tpm_2hash_ext_log
|
|
|
d3c3ab |
+ {
|
|
|
d3c3ab |
+ struct grub_ieee1275_common_hdr common;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t method;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t ihandle;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t size;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t buf;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t description_size;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t description;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t eventtype;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t pcrindex;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t catch_result;
|
|
|
d3c3ab |
+ grub_ieee1275_cell_t rc;
|
|
|
d3c3ab |
+ }
|
|
|
d3c3ab |
+ args;
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ INIT_IEEE1275_COMMON (&args.common, "call-method", 8, 2);
|
|
|
d3c3ab |
+ args.method = (grub_ieee1275_cell_t) "2hash-ext-log";
|
|
|
d3c3ab |
+ args.ihandle = tpm_ihandle;
|
|
|
d3c3ab |
+ args.pcrindex = pcrindex;
|
|
|
d3c3ab |
+ args.eventtype = eventtype;
|
|
|
d3c3ab |
+ args.description = (grub_ieee1275_cell_t) description;
|
|
|
d3c3ab |
+ args.description_size = description_size;
|
|
|
d3c3ab |
+ args.buf = (grub_ieee1275_cell_t) buf;
|
|
|
d3c3ab |
+ args.size = (grub_ieee1275_cell_t) size;
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ if (IEEE1275_CALL_ENTRY_FN (&args) == -1)
|
|
|
d3c3ab |
+ return -1;
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ /*
|
|
|
d3c3ab |
+ * catch_result is set if firmware does not support 2hash-ext-log
|
|
|
d3c3ab |
+ * rc is GRUB_IEEE1275_CELL_FALSE (0) on failure
|
|
|
d3c3ab |
+ */
|
|
|
d3c3ab |
+ if ((args.catch_result) || args.rc == GRUB_IEEE1275_CELL_FALSE)
|
|
|
d3c3ab |
+ return -1;
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ return 0;
|
|
|
d3c3ab |
+}
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+static grub_err_t
|
|
|
d3c3ab |
+tpm2_log_event (unsigned char *buf,
|
|
|
d3c3ab |
+ grub_size_t size, grub_uint8_t pcr,
|
|
|
d3c3ab |
+ const char *description)
|
|
|
d3c3ab |
+{
|
|
|
d3c3ab |
+ static int error_displayed = 0;
|
|
|
d3c3ab |
+ int err;
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ err = ibmvtpm_2hash_ext_log (pcr, EV_IPL,
|
|
|
d3c3ab |
+ description,
|
|
|
d3c3ab |
+ grub_strlen(description) + 1,
|
|
|
d3c3ab |
+ buf, size);
|
|
|
d3c3ab |
+ if (err && !error_displayed)
|
|
|
d3c3ab |
+ {
|
|
|
d3c3ab |
+ error_displayed++;
|
|
|
d3c3ab |
+ return grub_error (GRUB_ERR_BAD_DEVICE,
|
|
|
d3c3ab |
+ "2HASH-EXT-LOG failed: Firmware is likely too old.\n");
|
|
|
d3c3ab |
+ }
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ return GRUB_ERR_NONE;
|
|
|
d3c3ab |
+}
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+grub_err_t
|
|
|
d3c3ab |
+grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr,
|
|
|
d3c3ab |
+ const char *description)
|
|
|
d3c3ab |
+{
|
|
|
d3c3ab |
+ grub_err_t err = tpm_init();
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ /* Absence of a TPM isn't a failure. */
|
|
|
d3c3ab |
+ if (err != GRUB_ERR_NONE)
|
|
|
d3c3ab |
+ return GRUB_ERR_NONE;
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ grub_dprintf ("tpm", "log_event, pcr = %d, size = 0x%" PRIxGRUB_SIZE ", %s\n",
|
|
|
d3c3ab |
+ pcr, size, description);
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ if (tpm_version == 2)
|
|
|
d3c3ab |
+ return tpm2_log_event (buf, size, pcr, description);
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
+ return GRUB_ERR_NONE;
|
|
|
d3c3ab |
+}
|
|
|
d3c3ab |
diff --git a/include/grub/ieee1275/ieee1275.h b/include/grub/ieee1275/ieee1275.h
|
|
|
d3c3ab |
index e0a6c2ce1e..f4c85265fe 100644
|
|
|
d3c3ab |
--- a/include/grub/ieee1275/ieee1275.h
|
|
|
d3c3ab |
+++ b/include/grub/ieee1275/ieee1275.h
|
|
|
d3c3ab |
@@ -24,6 +24,9 @@
|
|
|
d3c3ab |
#include <grub/types.h>
|
|
|
d3c3ab |
#include <grub/machine/ieee1275.h>
|
|
|
d3c3ab |
|
|
|
d3c3ab |
+#define GRUB_IEEE1275_CELL_FALSE ((grub_ieee1275_cell_t) 0)
|
|
|
d3c3ab |
+#define GRUB_IEEE1275_CELL_TRUE ((grub_ieee1275_cell_t) -1)
|
|
|
d3c3ab |
+
|
|
|
d3c3ab |
struct grub_ieee1275_mem_region
|
|
|
d3c3ab |
{
|
|
|
d3c3ab |
unsigned int start;
|
|
|
d3c3ab |
diff --git a/docs/grub.texi b/docs/grub.texi
|
|
|
d3c3ab |
index a4da9c2a1b..c433240f34 100644
|
|
|
d3c3ab |
--- a/docs/grub.texi
|
|
|
d3c3ab |
+++ b/docs/grub.texi
|
|
|
d3c3ab |
@@ -6221,7 +6221,8 @@ tpm module is loaded. As such it is recommended that the tpm module be built
|
|
|
d3c3ab |
into @file{core.img} in order to avoid a potential gap in measurement between
|
|
|
d3c3ab |
@file{core.img} being loaded and the tpm module being loaded.
|
|
|
d3c3ab |
|
|
|
d3c3ab |
-Measured boot is currently only supported on EFI platforms.
|
|
|
d3c3ab |
+Measured boot is currently only supported on EFI and IBM IEEE1275 PowerPC
|
|
|
d3c3ab |
+platforms.
|
|
|
d3c3ab |
|
|
|
d3c3ab |
@node Lockdown
|
|
|
d3c3ab |
@section Lockdown when booting on a secure setup
|