Skip to content

Commit 7a49148

Browse files
committed
Merge: RHEL-30322: Add support for the EFI_CC_MEASUREMENT_PROTOCOL in the EFI stub
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/3996 JIRA: https://issues.redhat.com/browse/RHEL-30322 When the kernel is directly booted from EFI, the kernel's EFI stub must measure the kernel command line and the measure the initrd when it's loaded by use of a LINUX_EFI_INITRD_MEDIA_GUID device path. Signed-off-by: Lenny Szubowicz <lszubowi@redhat.com> Approved-by: Tony Camuso <tcamuso@redhat.com> Approved-by: Desnes Nunes <desnesn@redhat.com> Approved-by: CKI KWF Bot <cki-ci-bot+kwf-gitlab-com@redhat.com> Merged-by: Lucas Zampieri <lzampier@redhat.com>
2 parents f53fa27 + 167ec8b commit 7a49148

File tree

8 files changed

+221
-70
lines changed

8 files changed

+221
-70
lines changed

drivers/firmware/efi/efi.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -590,7 +590,8 @@ static const efi_config_table_type_t common_tables[] __initconst = {
590590
{EFI_MEMORY_ATTRIBUTES_TABLE_GUID, &efi_mem_attr_table, "MEMATTR" },
591591
{LINUX_EFI_RANDOM_SEED_TABLE_GUID, &efi_rng_seed, "RNG" },
592592
{LINUX_EFI_TPM_EVENT_LOG_GUID, &efi.tpm_log, "TPMEventLog" },
593-
{LINUX_EFI_TPM_FINAL_LOG_GUID, &efi.tpm_final_log, "TPMFinalLog" },
593+
{EFI_TCG2_FINAL_EVENTS_TABLE_GUID, &efi.tpm_final_log, "TPMFinalLog" },
594+
{EFI_CC_FINAL_EVENTS_TABLE_GUID, &efi.tpm_final_log, "CCFinalLog" },
594595
{LINUX_EFI_MEMRESERVE_TABLE_GUID, &mem_reserve, "MEMRESERVE" },
595596
{LINUX_EFI_INITRD_MEDIA_GUID, &initrd, "INITRD" },
596597
{EFI_RT_PROPERTIES_TABLE_GUID, &rt_prop, "RTPROP" },

drivers/firmware/efi/libstub/efi-stub-helper.c

Lines changed: 70 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include <linux/efi.h>
1313
#include <linux/kernel.h>
14+
#include <linux/overflow.h>
1415
#include <asm/efi.h>
1516
#include <asm/setup.h>
1617

@@ -193,7 +194,7 @@ void efi_apply_loadoptions_quirk(const void **load_options, u32 *load_options_si
193194
*load_options_size = load_option_unpacked.optional_data_size;
194195
}
195196

196-
enum efistub_event {
197+
enum efistub_event_type {
197198
EFISTUB_EVT_INITRD,
198199
EFISTUB_EVT_LOAD_OPTIONS,
199200
EFISTUB_EVT_COUNT,
@@ -219,54 +220,95 @@ static const struct {
219220
},
220221
};
221222

223+
static_assert(sizeof(efi_tcg2_event_t) == sizeof(efi_cc_event_t));
224+
225+
union efistub_event {
226+
efi_tcg2_event_t tcg2_data;
227+
efi_cc_event_t cc_data;
228+
};
229+
230+
struct efistub_measured_event {
231+
union efistub_event event_data;
232+
TCG_PCClientTaggedEvent tagged_event __packed;
233+
};
234+
222235
static efi_status_t efi_measure_tagged_event(unsigned long load_addr,
223236
unsigned long load_size,
224-
enum efistub_event event)
237+
enum efistub_event_type event)
225238
{
239+
union {
240+
efi_status_t
241+
(__efiapi *hash_log_extend_event)(void *, u64, efi_physical_addr_t,
242+
u64, const union efistub_event *);
243+
struct { u32 hash_log_extend_event; } mixed_mode;
244+
} method;
245+
struct efistub_measured_event *evt;
246+
int size = struct_size(evt, tagged_event.tagged_event_data,
247+
events[event].event_data_len);
226248
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
227249
efi_tcg2_protocol_t *tcg2 = NULL;
250+
union efistub_event ev;
228251
efi_status_t status;
252+
void *protocol;
229253

230254
efi_bs_call(locate_protocol, &tcg2_guid, NULL, (void **)&tcg2);
231255
if (tcg2) {
232-
struct efi_measured_event {
233-
efi_tcg2_event_t event_data;
234-
efi_tcg2_tagged_event_t tagged_event;
235-
u8 tagged_event_data[];
236-
} *evt;
237-
int size = sizeof(*evt) + events[event].event_data_len;
238-
239-
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size,
240-
(void **)&evt);
241-
if (status != EFI_SUCCESS)
242-
goto fail;
243-
244-
evt->event_data = (struct efi_tcg2_event){
256+
ev.tcg2_data = (struct efi_tcg2_event){
245257
.event_size = size,
246-
.event_header.header_size = sizeof(evt->event_data.event_header),
258+
.event_header.header_size = sizeof(ev.tcg2_data.event_header),
247259
.event_header.header_version = EFI_TCG2_EVENT_HEADER_VERSION,
248260
.event_header.pcr_index = events[event].pcr_index,
249261
.event_header.event_type = EV_EVENT_TAG,
250262
};
263+
protocol = tcg2;
264+
method.hash_log_extend_event =
265+
(void *)efi_table_attr(tcg2, hash_log_extend_event);
266+
} else {
267+
efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
268+
efi_cc_protocol_t *cc = NULL;
251269

252-
evt->tagged_event = (struct efi_tcg2_tagged_event){
253-
.tagged_event_id = events[event].event_id,
254-
.tagged_event_data_size = events[event].event_data_len,
255-
};
256-
257-
memcpy(evt->tagged_event_data, events[event].event_data,
258-
events[event].event_data_len);
270+
efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
271+
if (!cc)
272+
return EFI_UNSUPPORTED;
259273

260-
status = efi_call_proto(tcg2, hash_log_extend_event, 0,
261-
load_addr, load_size, &evt->event_data);
262-
efi_bs_call(free_pool, evt);
274+
ev.cc_data = (struct efi_cc_event){
275+
.event_size = size,
276+
.event_header.header_size = sizeof(ev.cc_data.event_header),
277+
.event_header.header_version = EFI_CC_EVENT_HEADER_VERSION,
278+
.event_header.event_type = EV_EVENT_TAG,
279+
};
263280

281+
status = efi_call_proto(cc, map_pcr_to_mr_index,
282+
events[event].pcr_index,
283+
&ev.cc_data.event_header.mr_index);
264284
if (status != EFI_SUCCESS)
265285
goto fail;
266-
return EFI_SUCCESS;
286+
287+
protocol = cc;
288+
method.hash_log_extend_event =
289+
(void *)efi_table_attr(cc, hash_log_extend_event);
267290
}
268291

269-
return EFI_UNSUPPORTED;
292+
status = efi_bs_call(allocate_pool, EFI_LOADER_DATA, size, (void **)&evt);
293+
if (status != EFI_SUCCESS)
294+
goto fail;
295+
296+
*evt = (struct efistub_measured_event) {
297+
.event_data = ev,
298+
.tagged_event.tagged_event_id = events[event].event_id,
299+
.tagged_event.tagged_event_data_size = events[event].event_data_len,
300+
};
301+
302+
memcpy(evt->tagged_event.tagged_event_data, events[event].event_data,
303+
events[event].event_data_len);
304+
305+
status = efi_fn_call(&method, hash_log_extend_event, protocol, 0,
306+
load_addr, load_size, &evt->event_data);
307+
efi_bs_call(free_pool, evt);
308+
309+
if (status == EFI_SUCCESS)
310+
return EFI_SUCCESS;
311+
270312
fail:
271313
efi_warn("Failed to measure data for event %d: 0x%lx\n", event, status);
272314
return status;

drivers/firmware/efi/libstub/efi-stub.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ efi_status_t efi_stub_common(efi_handle_t handle,
159159

160160
si = setup_graphics();
161161

162-
efi_retrieve_tpm2_eventlog();
162+
efi_retrieve_eventlog();
163163

164164
/* Ask the firmware to clear memory on unclean shutdown */
165165
efi_enable_reset_attack_mitigation();

drivers/firmware/efi/libstub/efistub.h

Lines changed: 88 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -843,14 +843,14 @@ struct efi_tcg2_event {
843843
/* u8[] event follows here */
844844
} __packed;
845845

846-
struct efi_tcg2_tagged_event {
847-
u32 tagged_event_id;
848-
u32 tagged_event_data_size;
849-
/* u8 tagged event data follows here */
850-
} __packed;
846+
/* from TCG PC Client Platform Firmware Profile Specification */
847+
typedef struct tdTCG_PCClientTaggedEvent {
848+
u32 tagged_event_id;
849+
u32 tagged_event_data_size;
850+
u8 tagged_event_data[];
851+
} TCG_PCClientTaggedEvent;
851852

852853
typedef struct efi_tcg2_event efi_tcg2_event_t;
853-
typedef struct efi_tcg2_tagged_event efi_tcg2_tagged_event_t;
854854
typedef union efi_tcg2_protocol efi_tcg2_protocol_t;
855855

856856
union efi_tcg2_protocol {
@@ -882,6 +882,87 @@ union efi_tcg2_protocol {
882882
} mixed_mode;
883883
};
884884

885+
typedef struct {
886+
u8 major;
887+
u8 minor;
888+
} efi_cc_version_t;
889+
890+
typedef struct {
891+
u8 type;
892+
u8 sub_type;
893+
} efi_cc_type_t;
894+
895+
/* EFI CC type/subtype defines */
896+
#define EFI_CC_TYPE_NONE 0
897+
#define EFI_CC_TYPE_AMD_SEV 1
898+
#define EFI_CC_TYPE_INTEL_TDX 2
899+
900+
typedef u32 efi_cc_mr_index_t;
901+
902+
struct efi_cc_event {
903+
u32 event_size;
904+
struct {
905+
u32 header_size;
906+
u16 header_version;
907+
u32 mr_index;
908+
u32 event_type;
909+
} __packed event_header;
910+
/* u8[] event follows here */
911+
} __packed;
912+
913+
typedef struct efi_cc_event efi_cc_event_t;
914+
915+
typedef u32 efi_cc_event_log_bitmap_t;
916+
typedef u32 efi_cc_event_log_format_t;
917+
typedef u32 efi_cc_event_algorithm_bitmap_t;
918+
919+
typedef struct {
920+
u8 size;
921+
efi_cc_version_t structure_version;
922+
efi_cc_version_t protocol_version;
923+
efi_cc_event_algorithm_bitmap_t hash_algorithm_bitmap;
924+
efi_cc_event_log_bitmap_t supported_event_logs;
925+
efi_cc_type_t cc_type;
926+
} efi_cc_boot_service_cap_t;
927+
928+
#define EFI_CC_EVENT_HEADER_VERSION 1
929+
930+
#define EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004
931+
932+
#define EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002
933+
934+
typedef union efi_cc_protocol efi_cc_protocol_t;
935+
936+
union efi_cc_protocol {
937+
struct {
938+
efi_status_t
939+
(__efiapi *get_capability)(efi_cc_protocol_t *,
940+
efi_cc_boot_service_cap_t *);
941+
942+
efi_status_t
943+
(__efiapi *get_event_log)(efi_cc_protocol_t *,
944+
efi_cc_event_log_format_t,
945+
efi_physical_addr_t *,
946+
efi_physical_addr_t *,
947+
efi_bool_t *);
948+
949+
efi_status_t
950+
(__efiapi *hash_log_extend_event)(efi_cc_protocol_t *, u64,
951+
efi_physical_addr_t, u64,
952+
const efi_cc_event_t *);
953+
954+
efi_status_t
955+
(__efiapi *map_pcr_to_mr_index)(efi_cc_protocol_t *, u32,
956+
efi_cc_mr_index_t *);
957+
};
958+
struct {
959+
u32 get_capability;
960+
u32 get_event_log;
961+
u32 hash_log_extend_event;
962+
u32 map_pcr_to_mr_index;
963+
} mixed_mode;
964+
};
965+
885966
typedef union efi_load_file_protocol efi_load_file_protocol_t;
886967
typedef union efi_load_file_protocol efi_load_file2_protocol_t;
887968

@@ -1053,7 +1134,7 @@ static inline void
10531134
efi_enable_reset_attack_mitigation(void) { }
10541135
#endif
10551136

1056-
void efi_retrieve_tpm2_eventlog(void);
1137+
void efi_retrieve_eventlog(void);
10571138

10581139
struct screen_info *alloc_screen_info(void);
10591140
struct screen_info *__alloc_screen_info(void);

drivers/firmware/efi/libstub/tpm.c

Lines changed: 54 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -47,39 +47,18 @@ void efi_enable_reset_attack_mitigation(void)
4747

4848
#endif
4949

50-
void efi_retrieve_tpm2_eventlog(void)
50+
static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_location,
51+
efi_physical_addr_t log_last_entry,
52+
efi_bool_t truncated,
53+
struct efi_tcg2_final_events_table *final_events_table)
5154
{
52-
efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
5355
efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
5456
efi_status_t status;
55-
efi_physical_addr_t log_location = 0, log_last_entry = 0;
5657
struct linux_efi_tpm_eventlog *log_tbl = NULL;
57-
struct efi_tcg2_final_events_table *final_events_table = NULL;
5858
unsigned long first_entry_addr, last_entry_addr;
5959
size_t log_size, last_entry_size;
60-
efi_bool_t truncated;
61-
int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
62-
efi_tcg2_protocol_t *tcg2_protocol = NULL;
6360
int final_events_size = 0;
6461

65-
status = efi_bs_call(locate_protocol, &tcg2_guid, NULL,
66-
(void **)&tcg2_protocol);
67-
if (status != EFI_SUCCESS)
68-
return;
69-
70-
status = efi_call_proto(tcg2_protocol, get_event_log, version,
71-
&log_location, &log_last_entry, &truncated);
72-
73-
if (status != EFI_SUCCESS || !log_location) {
74-
version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
75-
status = efi_call_proto(tcg2_protocol, get_event_log, version,
76-
&log_location, &log_last_entry,
77-
&truncated);
78-
if (status != EFI_SUCCESS || !log_location)
79-
return;
80-
81-
}
82-
8362
first_entry_addr = (unsigned long) log_location;
8463

8564
/*
@@ -93,8 +72,10 @@ void efi_retrieve_tpm2_eventlog(void)
9372
* get_event_log only returns the address of the last entry.
9473
* We need to calculate its size to deduce the full size of
9574
* the logs.
75+
*
76+
* CC Event log also uses TCG2 format, handle it same as TPM2.
9677
*/
97-
if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) {
78+
if (version > EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2) {
9879
/*
9980
* The TCG2 log format has variable length entries,
10081
* and the information to decode the hash algorithms
@@ -127,8 +108,6 @@ void efi_retrieve_tpm2_eventlog(void)
127108
* Figure out whether any events have already been logged to the
128109
* final events structure, and if so how much space they take up
129110
*/
130-
if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
131-
final_events_table = get_efi_config_table(LINUX_EFI_TPM_FINAL_LOG_GUID);
132111
if (final_events_table && final_events_table->nr_events) {
133112
struct tcg_pcr_event2_head *header;
134113
int offset;
@@ -165,3 +144,50 @@ void efi_retrieve_tpm2_eventlog(void)
165144
err_free:
166145
efi_bs_call(free_pool, log_tbl);
167146
}
147+
148+
void efi_retrieve_eventlog(void)
149+
{
150+
struct efi_tcg2_final_events_table *final_events_table = NULL;
151+
efi_physical_addr_t log_location = 0, log_last_entry = 0;
152+
efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
153+
int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
154+
efi_tcg2_protocol_t *tpm2 = NULL;
155+
efi_bool_t truncated;
156+
efi_status_t status;
157+
158+
status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
159+
if (status == EFI_SUCCESS) {
160+
status = efi_call_proto(tpm2, get_event_log, version, &log_location,
161+
&log_last_entry, &truncated);
162+
163+
if (status != EFI_SUCCESS || !log_location) {
164+
version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
165+
status = efi_call_proto(tpm2, get_event_log, version,
166+
&log_location, &log_last_entry,
167+
&truncated);
168+
} else {
169+
final_events_table =
170+
get_efi_config_table(EFI_TCG2_FINAL_EVENTS_TABLE_GUID);
171+
}
172+
} else {
173+
efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
174+
efi_cc_protocol_t *cc = NULL;
175+
176+
status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
177+
if (status != EFI_SUCCESS)
178+
return;
179+
180+
version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
181+
status = efi_call_proto(cc, get_event_log, version, &log_location,
182+
&log_last_entry, &truncated);
183+
184+
final_events_table =
185+
get_efi_config_table(EFI_CC_FINAL_EVENTS_TABLE_GUID);
186+
}
187+
188+
if (status != EFI_SUCCESS || !log_location)
189+
return;
190+
191+
efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
192+
truncated, final_events_table);
193+
}

0 commit comments

Comments
 (0)