aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Berger <stefanb@linux.vnet.ibm.com>2020-01-21 15:01:47 -0500
committerAlexey Kardashevskiy <aik@ozlabs.ru>2020-02-21 14:03:07 +1100
commit16a1867425ee88d8b674d2a51ada19ff7ddf1b42 (patch)
tree08b8badc52ef98e071989bef356ae723a2b47b2d
parent8a6b0d7061c5e504be2e378bd691a762307a1805 (diff)
downloadSLOF-16a1867425ee88d8b674d2a51ada19ff7ddf1b42.zip
SLOF-16a1867425ee88d8b674d2a51ada19ff7ddf1b42.tar.gz
SLOF-16a1867425ee88d8b674d2a51ada19ff7ddf1b42.tar.bz2
tcgbios: Measure the GPT table
Measure and log the GPT table including LBA1 and all GPT table entries with a non-zero Type GUID. We follow the specification "TCG PC Client Platform Firmware Profile Specification" for the format of what needs to be logged and measured. See section "Event Logging" subsection "Measuring UEFI Variables" for the UEFI_GPT_DATA structure. Signed-off-by: Stefan Berger <stefanb@linux.ibm.com> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
-rw-r--r--board-qemu/slof/vtpm-sml.fs8
-rw-r--r--lib/libtpm/tcgbios.c88
-rw-r--r--lib/libtpm/tcgbios.h3
-rw-r--r--lib/libtpm/tcgbios_int.h40
-rw-r--r--lib/libtpm/tpm.code32
-rw-r--r--lib/libtpm/tpm.in3
-rw-r--r--slof/fs/packages/disk-label.fs22
7 files changed, 196 insertions, 0 deletions
diff --git a/board-qemu/slof/vtpm-sml.fs b/board-qemu/slof/vtpm-sml.fs
index fd888fb..865db06 100644
--- a/board-qemu/slof/vtpm-sml.fs
+++ b/board-qemu/slof/vtpm-sml.fs
@@ -42,6 +42,14 @@ s" ibm,vtpm" 2dup device-name device-type
THEN
;
+: measure-gpt ( )
+ 0 7 separator-event
+ tpm-measure-gpt
+ ?dup IF
+ ." VTPM: Error code from tpm-measure-gpt: " . cr
+ THEN
+;
+
: leave-firmware ( -- )
tpm-leave-firmware ( errcode )
?dup IF
diff --git a/lib/libtpm/tcgbios.c b/lib/libtpm/tcgbios.c
index c5f8ccf..be6c3d1 100644
--- a/lib/libtpm/tcgbios.c
+++ b/lib/libtpm/tcgbios.c
@@ -69,6 +69,11 @@ static struct {
#define TPM2_ALG_SHA512_FLAG (1 << 3)
#define TPM2_ALG_SM3_256_FLAG (1 << 4)
+static const uint8_t ZeroGuid[16] = { 0 };
+
+static UEFI_GPT_DATA *uefi_gpt_data;
+static size_t uefi_gpt_data_size;
+
/*
* TPM 2 logs are written in little endian format.
*/
@@ -925,6 +930,89 @@ uint32_t tpm_measure_bcv_mbr(uint32_t bootdrv, const uint8_t *addr,
addr + 0x1b8, 0x48);
}
+/*
+ * This is the first function to call when measuring a GPT table.
+ * It allocates memory for the data to log which are 'measured' later on.
+ */
+void tpm_gpt_set_lba1(const uint8_t *addr, uint32_t length)
+{
+ if (!tpm_is_working())
+ return;
+
+ SLOF_free_mem(uefi_gpt_data, uefi_gpt_data_size);
+
+ uefi_gpt_data_size = sizeof(UEFI_GPT_DATA);
+ uefi_gpt_data = SLOF_alloc_mem(uefi_gpt_data_size);
+ if (!uefi_gpt_data)
+ return;
+
+ memcpy(&uefi_gpt_data->EfiPartitionHeader,
+ addr, sizeof(uefi_gpt_data->EfiPartitionHeader));
+ uefi_gpt_data->NumberOfPartitions = 0;
+}
+
+/*
+ * This function adds a GPT entry to the data to measure. It must
+ * be called after tpm_gpt_set_lba1.
+ */
+void tpm_gpt_add_entry(const uint8_t *addr, uint32_t length)
+{
+ size_t sz;
+ UEFI_PARTITION_ENTRY *upe = (void *)addr;
+ void *tmp;
+
+ if (!tpm_is_working() ||
+ !uefi_gpt_data ||
+ length < sizeof(*upe) ||
+ !memcmp(upe->partTypeGuid, ZeroGuid, sizeof(ZeroGuid)))
+ return;
+
+ sz = offset_of(UEFI_GPT_DATA, Partitions) +
+ (uefi_gpt_data->NumberOfPartitions + 1)
+ * sizeof(UEFI_PARTITION_ENTRY);
+ if (sz > uefi_gpt_data_size) {
+ tmp = SLOF_alloc_mem(sz);
+ if (!tmp)
+ goto err_no_mem;
+
+ memcpy(tmp, uefi_gpt_data, uefi_gpt_data_size);
+ SLOF_free_mem(uefi_gpt_data, uefi_gpt_data_size);
+ uefi_gpt_data = tmp;
+ uefi_gpt_data_size = sz;
+ }
+
+ memcpy(&uefi_gpt_data->Partitions[uefi_gpt_data->NumberOfPartitions],
+ addr,
+ sizeof(UEFI_PARTITION_ENTRY));
+ uefi_gpt_data->NumberOfPartitions++;
+
+ return;
+
+err_no_mem:
+ SLOF_free_mem(uefi_gpt_data, uefi_gpt_data_size);
+ uefi_gpt_data_size = 0;
+ uefi_gpt_data = NULL;
+}
+
+/*
+ * tpm_measure_gpt finally measures the GPT table and adds an entry
+ * to the log.
+ */
+uint32_t tpm_measure_gpt(void)
+{
+ size_t sz;
+
+ if (!tpm_is_working())
+ return TCGBIOS_GENERAL_ERROR;
+
+ sz = offset_of(UEFI_GPT_DATA, Partitions) +
+ uefi_gpt_data->NumberOfPartitions * sizeof(UEFI_PARTITION_ENTRY);
+
+ return tpm_add_measurement_to_log(5, EV_EFI_GPT_EVENT,
+ (const char *)uefi_gpt_data, sz,
+ (const uint8_t *)uefi_gpt_data, sz);
+}
+
uint32_t tpm_measure_scrtm(void)
{
uint32_t rc;
diff --git a/lib/libtpm/tcgbios.h b/lib/libtpm/tcgbios.h
index c4a2e71..8174d86 100644
--- a/lib/libtpm/tcgbios.h
+++ b/lib/libtpm/tcgbios.h
@@ -29,5 +29,8 @@ uint32_t tpm_driver_get_failure_reason(void);
void tpm_driver_set_failure_reason(uint32_t errcode);
bool tpm_is_working(void);
void tpm20_menu(void);
+void tpm_gpt_set_lba1(const uint8_t *addr, uint32_t length);
+void tpm_gpt_add_entry(const uint8_t *addr, uint32_t length);
+uint32_t tpm_measure_gpt(void);
#endif /* TCGBIOS_H */
diff --git a/lib/libtpm/tcgbios_int.h b/lib/libtpm/tcgbios_int.h
index 6892e6f..1a88402 100644
--- a/lib/libtpm/tcgbios_int.h
+++ b/lib/libtpm/tcgbios_int.h
@@ -39,6 +39,8 @@
#define EV_S_CRTM_VERSION 8
#define EV_IPL 13
#define EV_IPL_PARTITION_DATA 14
+#define EV_EFI_EVENT_BASE 0x80000000
+#define EV_EFI_GPT_EVENT (EV_EFI_EVENT_BASE + 0x6)
#define BCV_DEVICE_HDD 0x80
@@ -91,6 +93,44 @@ struct TCG_EfiSpecIdEventStruct {
*/
} __attribute__((packed));
+/* EFI related data structures for logging */
+typedef struct {
+ uint64_t signature;
+ uint32_t revision;
+ uint32_t size;
+ uint32_t crc32;
+ uint8_t reserved[4];
+} __attribute__((packed)) UEFI_TABLE_HEADER;
+
+typedef struct {
+ UEFI_TABLE_HEADER header;
+ uint64_t currentLba;
+ uint64_t backupLba;
+ uint64_t firstLba;
+ uint64_t lastLba;
+ uint8_t diskGuid[16];
+ uint64_t partEntryLba;
+ uint32_t numPartEntry;
+ uint32_t partEntrySize;
+ uint32_t partArrayCrc32;
+ uint8_t reserved[420];
+} __attribute__((packed)) UEFI_PARTITION_TABLE_HEADER;
+
+typedef struct {
+ uint8_t partTypeGuid[16];
+ uint8_t partGuid[16];
+ uint64_t firstLba;
+ uint64_t lastLba;
+ uint64_t attribute;
+ uint8_t partName[72];
+} __attribute__((packed)) UEFI_PARTITION_ENTRY;
+
+typedef struct {
+ UEFI_PARTITION_TABLE_HEADER EfiPartitionHeader;
+ uint64_t NumberOfPartitions;
+ UEFI_PARTITION_ENTRY Partitions[0];
+} __attribute__((packed)) UEFI_GPT_DATA;
+
/* Input and Output headers for all TPM commands */
struct tpm_req_header {
uint16_t tag;
diff --git a/lib/libtpm/tpm.code b/lib/libtpm/tpm.code
index b8f5669..205c608 100644
--- a/lib/libtpm/tpm.code
+++ b/lib/libtpm/tpm.code
@@ -137,3 +137,35 @@ MIRP
PRIM(tpm20_X2d_menu)
tpm20_menu();
MIRP
+
+/*************************************************************************/
+/* Set the LBA1 of the GPT */
+/* SLOF: tpm-gpt-set-lba1 ( addr length -- ) */
+/* LIBTPM: tpm_gpt_set_lba1(addr, length) */
+/*************************************************************************/
+PRIM(tpm_X2d_gpt_X2d_set_X2d_lba1)
+ int length = TOS.u; POP;
+ void *addr = TOS.a; POP;
+ tpm_gpt_set_lba1(addr, length);
+MIRP
+
+/*************************************************************************/
+/* Add a GPT table entry */
+/* SLOF: tpm-gpt-add-entry ( addr length -- ) */
+/* LIBTPM: tpm_gpt_add_entry(addr, length) */
+/*************************************************************************/
+PRIM(tpm_X2d_gpt_X2d_add_X2d_entry)
+ int length = TOS.u; POP;
+ void *addr = TOS.a; POP;
+ tpm_gpt_add_entry(addr, length);
+MIRP
+
+/*************************************************************************/
+/* Measure and log GPT EVENT */
+/* SLOF: tpm-measure-gpt ( -- errcode ) */
+/* LIBTPM: errcode = tpm_measure_gpt() */
+/*************************************************************************/
+PRIM(tpm_X2d_measure_X2d_gpt)
+ PUSH;
+ TOS.n = tpm_measure_gpt();
+MIRP
diff --git a/lib/libtpm/tpm.in b/lib/libtpm/tpm.in
index 590fee1..bdbc47d 100644
--- a/lib/libtpm/tpm.in
+++ b/lib/libtpm/tpm.in
@@ -25,3 +25,6 @@ cod(tpm-measure-scrtm)
cod(tpm-driver-get-failure-reason)
cod(tpm-driver-set-failure-reason)
cod(tpm20-menu)
+cod(tpm-gpt-set-lba1)
+cod(tpm-gpt-add-entry)
+cod(tpm-measure-gpt)
diff --git a/slof/fs/packages/disk-label.fs b/slof/fs/packages/disk-label.fs
index 969eb00..bb64022 100644
--- a/slof/fs/packages/disk-label.fs
+++ b/slof/fs/packages/disk-label.fs
@@ -431,6 +431,27 @@ CREATE GPT-LINUX-PARTITION 10 allot
block gpt>signature x@ GPT-SIGNATURE =
;
+\ Measure the GPT partition table by collecting its LBA1
+\ and GPT Entries and then measuring them.
+\ This function modifies 'block' and 'seek-pos'
+
+: measure-gpt-partition ( -- )
+ s" /ibm,vtpm" find-node ?dup IF
+ get-gpt-partition 0= if drop EXIT THEN
+
+ block block-size tpm-gpt-set-lba1
+
+ block gpt>num-part-entry l@-le
+ 1+ 1 ?DO
+ seek-pos 0 seek drop
+ block gpt-part-size read drop
+ block gpt-part-size tpm-gpt-add-entry
+ seek-pos gpt-part-size + to seek-pos
+ LOOP
+ s" measure-gpt" rot $call-static
+ THEN
+;
+
: load-from-gpt-prep-partition ( addr -- size )
get-gpt-partition 0= IF false EXIT THEN
block gpt>num-part-entry l@-le dup 0= IF false exit THEN
@@ -465,6 +486,7 @@ CREATE GPT-LINUX-PARTITION 10 allot
;
: try-gpt-dos-partition ( -- true|false )
+ measure-gpt-partition
get-gpt-partition 0= IF false EXIT THEN
block gpt>num-part-entry l@-le dup 0= IF false EXIT THEN
1+ 1 ?DO