Skip to content

Commit

Permalink
tcgbios: Measure the GPT table
Browse files Browse the repository at this point in the history
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 <[email protected]>
Signed-off-by: Alexey Kardashevskiy <[email protected]>
  • Loading branch information
stefanberger authored and aik committed Feb 21, 2020
1 parent 8a6b0d7 commit 16a1867
Show file tree
Hide file tree
Showing 7 changed files with 196 additions and 0 deletions.
8 changes: 8 additions & 0 deletions board-qemu/slof/vtpm-sml.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
88 changes: 88 additions & 0 deletions lib/libtpm/tcgbios.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
*/
Expand Down Expand Up @@ -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;
Expand Down
3 changes: 3 additions & 0 deletions lib/libtpm/tcgbios.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
40 changes: 40 additions & 0 deletions lib/libtpm/tcgbios_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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;
Expand Down
32 changes: 32 additions & 0 deletions lib/libtpm/tpm.code
Original file line number Diff line number Diff line change
Expand Up @@ -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
3 changes: 3 additions & 0 deletions lib/libtpm/tpm.in
Original file line number Diff line number Diff line change
Expand Up @@ -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)
22 changes: 22 additions & 0 deletions slof/fs/packages/disk-label.fs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit 16a1867

Please sign in to comment.