diff options
author | Stefan Berger <stefanb@linux.vnet.ibm.com> | 2020-01-21 15:01:47 -0500 |
---|---|---|
committer | Alexey Kardashevskiy <aik@ozlabs.ru> | 2020-02-21 14:03:07 +1100 |
commit | 16a1867425ee88d8b674d2a51ada19ff7ddf1b42 (patch) | |
tree | 08b8badc52ef98e071989bef356ae723a2b47b2d | |
parent | 8a6b0d7061c5e504be2e378bd691a762307a1805 (diff) | |
download | SLOF-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.fs | 8 | ||||
-rw-r--r-- | lib/libtpm/tcgbios.c | 88 | ||||
-rw-r--r-- | lib/libtpm/tcgbios.h | 3 | ||||
-rw-r--r-- | lib/libtpm/tcgbios_int.h | 40 | ||||
-rw-r--r-- | lib/libtpm/tpm.code | 32 | ||||
-rw-r--r-- | lib/libtpm/tpm.in | 3 | ||||
-rw-r--r-- | slof/fs/packages/disk-label.fs | 22 |
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 |