Skip to content

Commit 47045fa

Browse files
stefanbergeraik
authored andcommitted
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>
1 parent 73f621e commit 47045fa

File tree

7 files changed

+196
-0
lines changed

7 files changed

+196
-0
lines changed

board-qemu/slof/vtpm-sml.fs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,14 @@ s" ibm,vtpm" 2dup device-name device-type
4242
THEN
4343
;
4444

45+
: measure-gpt ( )
46+
0 7 separator-event
47+
tpm-measure-gpt
48+
?dup IF
49+
." VTPM: Error code from tpm-measure-gpt: " . cr
50+
THEN
51+
;
52+
4553
: leave-firmware ( -- )
4654
tpm-leave-firmware ( errcode )
4755
?dup IF

lib/libtpm/tcgbios.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ static struct {
6969
#define TPM2_ALG_SHA512_FLAG (1 << 3)
7070
#define TPM2_ALG_SM3_256_FLAG (1 << 4)
7171

72+
static const uint8_t ZeroGuid[16] = { 0 };
73+
74+
static UEFI_GPT_DATA *uefi_gpt_data;
75+
static size_t uefi_gpt_data_size;
76+
7277
/*
7378
* TPM 2 logs are written in little endian format.
7479
*/
@@ -925,6 +930,89 @@ uint32_t tpm_measure_bcv_mbr(uint32_t bootdrv, const uint8_t *addr,
925930
addr + 0x1b8, 0x48);
926931
}
927932

933+
/*
934+
* This is the first function to call when measuring a GPT table.
935+
* It allocates memory for the data to log which are 'measured' later on.
936+
*/
937+
void tpm_gpt_set_lba1(const uint8_t *addr, uint32_t length)
938+
{
939+
if (!tpm_is_working())
940+
return;
941+
942+
SLOF_free_mem(uefi_gpt_data, uefi_gpt_data_size);
943+
944+
uefi_gpt_data_size = sizeof(UEFI_GPT_DATA);
945+
uefi_gpt_data = SLOF_alloc_mem(uefi_gpt_data_size);
946+
if (!uefi_gpt_data)
947+
return;
948+
949+
memcpy(&uefi_gpt_data->EfiPartitionHeader,
950+
addr, sizeof(uefi_gpt_data->EfiPartitionHeader));
951+
uefi_gpt_data->NumberOfPartitions = 0;
952+
}
953+
954+
/*
955+
* This function adds a GPT entry to the data to measure. It must
956+
* be called after tpm_gpt_set_lba1.
957+
*/
958+
void tpm_gpt_add_entry(const uint8_t *addr, uint32_t length)
959+
{
960+
size_t sz;
961+
UEFI_PARTITION_ENTRY *upe = (void *)addr;
962+
void *tmp;
963+
964+
if (!tpm_is_working() ||
965+
!uefi_gpt_data ||
966+
length < sizeof(*upe) ||
967+
!memcmp(upe->partTypeGuid, ZeroGuid, sizeof(ZeroGuid)))
968+
return;
969+
970+
sz = offset_of(UEFI_GPT_DATA, Partitions) +
971+
(uefi_gpt_data->NumberOfPartitions + 1)
972+
* sizeof(UEFI_PARTITION_ENTRY);
973+
if (sz > uefi_gpt_data_size) {
974+
tmp = SLOF_alloc_mem(sz);
975+
if (!tmp)
976+
goto err_no_mem;
977+
978+
memcpy(tmp, uefi_gpt_data, uefi_gpt_data_size);
979+
SLOF_free_mem(uefi_gpt_data, uefi_gpt_data_size);
980+
uefi_gpt_data = tmp;
981+
uefi_gpt_data_size = sz;
982+
}
983+
984+
memcpy(&uefi_gpt_data->Partitions[uefi_gpt_data->NumberOfPartitions],
985+
addr,
986+
sizeof(UEFI_PARTITION_ENTRY));
987+
uefi_gpt_data->NumberOfPartitions++;
988+
989+
return;
990+
991+
err_no_mem:
992+
SLOF_free_mem(uefi_gpt_data, uefi_gpt_data_size);
993+
uefi_gpt_data_size = 0;
994+
uefi_gpt_data = NULL;
995+
}
996+
997+
/*
998+
* tpm_measure_gpt finally measures the GPT table and adds an entry
999+
* to the log.
1000+
*/
1001+
uint32_t tpm_measure_gpt(void)
1002+
{
1003+
size_t sz;
1004+
1005+
if (!tpm_is_working())
1006+
return TCGBIOS_GENERAL_ERROR;
1007+
1008+
sz = offset_of(UEFI_GPT_DATA, Partitions) +
1009+
uefi_gpt_data->NumberOfPartitions * sizeof(UEFI_PARTITION_ENTRY);
1010+
1011+
return tpm_add_measurement_to_log(5, EV_EFI_GPT_EVENT,
1012+
(const char *)uefi_gpt_data, sz,
1013+
(const uint8_t *)uefi_gpt_data, sz);
1014+
}
1015+
9281016
uint32_t tpm_measure_scrtm(void)
9291017
{
9301018
uint32_t rc;

lib/libtpm/tcgbios.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,8 @@ uint32_t tpm_driver_get_failure_reason(void);
2929
void tpm_driver_set_failure_reason(uint32_t errcode);
3030
bool tpm_is_working(void);
3131
void tpm20_menu(void);
32+
void tpm_gpt_set_lba1(const uint8_t *addr, uint32_t length);
33+
void tpm_gpt_add_entry(const uint8_t *addr, uint32_t length);
34+
uint32_t tpm_measure_gpt(void);
3235

3336
#endif /* TCGBIOS_H */

lib/libtpm/tcgbios_int.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#define EV_S_CRTM_VERSION 8
4040
#define EV_IPL 13
4141
#define EV_IPL_PARTITION_DATA 14
42+
#define EV_EFI_EVENT_BASE 0x80000000
43+
#define EV_EFI_GPT_EVENT (EV_EFI_EVENT_BASE + 0x6)
4244

4345
#define BCV_DEVICE_HDD 0x80
4446

@@ -91,6 +93,44 @@ struct TCG_EfiSpecIdEventStruct {
9193
*/
9294
} __attribute__((packed));
9395

96+
/* EFI related data structures for logging */
97+
typedef struct {
98+
uint64_t signature;
99+
uint32_t revision;
100+
uint32_t size;
101+
uint32_t crc32;
102+
uint8_t reserved[4];
103+
} __attribute__((packed)) UEFI_TABLE_HEADER;
104+
105+
typedef struct {
106+
UEFI_TABLE_HEADER header;
107+
uint64_t currentLba;
108+
uint64_t backupLba;
109+
uint64_t firstLba;
110+
uint64_t lastLba;
111+
uint8_t diskGuid[16];
112+
uint64_t partEntryLba;
113+
uint32_t numPartEntry;
114+
uint32_t partEntrySize;
115+
uint32_t partArrayCrc32;
116+
uint8_t reserved[420];
117+
} __attribute__((packed)) UEFI_PARTITION_TABLE_HEADER;
118+
119+
typedef struct {
120+
uint8_t partTypeGuid[16];
121+
uint8_t partGuid[16];
122+
uint64_t firstLba;
123+
uint64_t lastLba;
124+
uint64_t attribute;
125+
uint8_t partName[72];
126+
} __attribute__((packed)) UEFI_PARTITION_ENTRY;
127+
128+
typedef struct {
129+
UEFI_PARTITION_TABLE_HEADER EfiPartitionHeader;
130+
uint64_t NumberOfPartitions;
131+
UEFI_PARTITION_ENTRY Partitions[0];
132+
} __attribute__((packed)) UEFI_GPT_DATA;
133+
94134
/* Input and Output headers for all TPM commands */
95135
struct tpm_req_header {
96136
uint16_t tag;

lib/libtpm/tpm.code

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,3 +137,35 @@ MIRP
137137
PRIM(tpm20_X2d_menu)
138138
tpm20_menu();
139139
MIRP
140+
141+
/*************************************************************************/
142+
/* Set the LBA1 of the GPT */
143+
/* SLOF: tpm-gpt-set-lba1 ( addr length -- ) */
144+
/* LIBTPM: tpm_gpt_set_lba1(addr, length) */
145+
/*************************************************************************/
146+
PRIM(tpm_X2d_gpt_X2d_set_X2d_lba1)
147+
int length = TOS.u; POP;
148+
void *addr = TOS.a; POP;
149+
tpm_gpt_set_lba1(addr, length);
150+
MIRP
151+
152+
/*************************************************************************/
153+
/* Add a GPT table entry */
154+
/* SLOF: tpm-gpt-add-entry ( addr length -- ) */
155+
/* LIBTPM: tpm_gpt_add_entry(addr, length) */
156+
/*************************************************************************/
157+
PRIM(tpm_X2d_gpt_X2d_add_X2d_entry)
158+
int length = TOS.u; POP;
159+
void *addr = TOS.a; POP;
160+
tpm_gpt_add_entry(addr, length);
161+
MIRP
162+
163+
/*************************************************************************/
164+
/* Measure and log GPT EVENT */
165+
/* SLOF: tpm-measure-gpt ( -- errcode ) */
166+
/* LIBTPM: errcode = tpm_measure_gpt() */
167+
/*************************************************************************/
168+
PRIM(tpm_X2d_measure_X2d_gpt)
169+
PUSH;
170+
TOS.n = tpm_measure_gpt();
171+
MIRP

lib/libtpm/tpm.in

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ cod(tpm-measure-scrtm)
2525
cod(tpm-driver-get-failure-reason)
2626
cod(tpm-driver-set-failure-reason)
2727
cod(tpm20-menu)
28+
cod(tpm-gpt-set-lba1)
29+
cod(tpm-gpt-add-entry)
30+
cod(tpm-measure-gpt)

slof/fs/packages/disk-label.fs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,27 @@ CREATE GPT-LINUX-PARTITION 10 allot
431431
block gpt>signature x@ GPT-SIGNATURE =
432432
;
433433

434+
\ Measure the GPT partition table by collecting its LBA1
435+
\ and GPT Entries and then measuring them.
436+
\ This function modifies 'block' and 'seek-pos'
437+
438+
: measure-gpt-partition ( -- )
439+
s" /ibm,vtpm" find-node ?dup IF
440+
get-gpt-partition 0= if drop EXIT THEN
441+
442+
block block-size tpm-gpt-set-lba1
443+
444+
block gpt>num-part-entry l@-le
445+
1+ 1 ?DO
446+
seek-pos 0 seek drop
447+
block gpt-part-size read drop
448+
block gpt-part-size tpm-gpt-add-entry
449+
seek-pos gpt-part-size + to seek-pos
450+
LOOP
451+
s" measure-gpt" rot $call-static
452+
THEN
453+
;
454+
434455
: load-from-gpt-prep-partition ( addr -- size )
435456
get-gpt-partition 0= IF false EXIT THEN
436457
block gpt>num-part-entry l@-le dup 0= IF false exit THEN
@@ -465,6 +486,7 @@ CREATE GPT-LINUX-PARTITION 10 allot
465486
;
466487

467488
: try-gpt-dos-partition ( -- true|false )
489+
measure-gpt-partition
468490
get-gpt-partition 0= IF false EXIT THEN
469491
block gpt>num-part-entry l@-le dup 0= IF false EXIT THEN
470492
1+ 1 ?DO

0 commit comments

Comments
 (0)