efi/libstub: Add get_event_log() support for CC platforms
authorKuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Thu, 15 Feb 2024 03:00:02 +0000 (03:00 +0000)
committerArd Biesheuvel <ardb@kernel.org>
Sat, 9 Mar 2024 10:37:17 +0000 (11:37 +0100)
To allow event log info access after boot, EFI boot stub extracts
the event log information and installs it in an EFI configuration
table. Currently, EFI boot stub only supports installation of event
log only for TPM 1.2 and TPM 2.0 protocols. Extend the same support
for CC protocol. Since CC platform also uses TCG2 format, reuse TPM2
support code as much as possible.

Link: https://uefi.org/specs/UEFI/2.10/38_Confidential_Computing.html#efi-cc-measurement-protocol
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
Link: https://lkml.kernel.org/r/0229a87e-fb19-4dad-99fc-4afd7ed4099a%40collabora.com
[ardb: Split out final events table handling to avoid version confusion]
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
drivers/firmware/efi/efi.c
drivers/firmware/efi/libstub/efi-stub.c
drivers/firmware/efi/libstub/efistub.h
drivers/firmware/efi/libstub/tpm.c
drivers/firmware/efi/libstub/x86-stub.c
include/linux/efi.h

index f6cfd29308d9570af7a6356b8f9dfa3429e66d3e..8859fb0b006d3b852225ffdd4040389844522cee 100644 (file)
@@ -598,6 +598,7 @@ static const efi_config_table_type_t common_tables[] __initconst = {
        {LINUX_EFI_RANDOM_SEED_TABLE_GUID,      &efi_rng_seed,          "RNG"           },
        {LINUX_EFI_TPM_EVENT_LOG_GUID,          &efi.tpm_log,           "TPMEventLog"   },
        {EFI_TCG2_FINAL_EVENTS_TABLE_GUID,      &efi.tpm_final_log,     "TPMFinalLog"   },
+       {EFI_CC_FINAL_EVENTS_TABLE_GUID,        &efi.tpm_final_log,     "CCFinalLog"    },
        {LINUX_EFI_MEMRESERVE_TABLE_GUID,       &mem_reserve,           "MEMRESERVE"    },
        {LINUX_EFI_INITRD_MEDIA_GUID,           &initrd,                "INITRD"        },
        {EFI_RT_PROPERTIES_TABLE_GUID,          &rt_prop,               "RTPROP"        },
index f9c1e8a2bd1d3e49b5e98bfa6d419fe9b74b075d..958a680e0660d44d6cdc81157ce5036172baf7a1 100644 (file)
@@ -167,7 +167,7 @@ efi_status_t efi_stub_common(efi_handle_t handle,
 
        si = setup_graphics();
 
-       efi_retrieve_tpm2_eventlog();
+       efi_retrieve_eventlog();
 
        /* Ask the firmware to clear memory on unclean shutdown */
        efi_enable_reset_attack_mitigation();
index 6b020aadcf948171376006d35b7546de4155ed68..df174edfc22855d82da7022ac9c07921c49d4796 100644 (file)
@@ -929,6 +929,8 @@ typedef struct {
 
 #define EFI_CC_BOOT_HASH_ALG_SHA384    0x00000004
 
+#define EFI_CC_EVENT_LOG_FORMAT_TCG_2  0x00000002
+
 typedef union efi_cc_protocol efi_cc_protocol_t;
 
 union efi_cc_protocol {
@@ -1140,7 +1142,7 @@ static inline void
 efi_enable_reset_attack_mitigation(void) { }
 #endif
 
-void efi_retrieve_tpm2_eventlog(void);
+void efi_retrieve_eventlog(void);
 
 struct screen_info *alloc_screen_info(void);
 struct screen_info *__alloc_screen_info(void);
index a880f7374c27a72defb3d75ae74b686b9e3459f2..df3182f2e63a562c75068880c8450a92194415a8 100644 (file)
@@ -47,39 +47,18 @@ void efi_enable_reset_attack_mitigation(void)
 
 #endif
 
-void efi_retrieve_tpm2_eventlog(void)
+static void efi_retrieve_tcg2_eventlog(int version, efi_physical_addr_t log_location,
+                                      efi_physical_addr_t log_last_entry,
+                                      efi_bool_t truncated,
+                                      struct efi_tcg2_final_events_table *final_events_table)
 {
-       efi_guid_t tcg2_guid = EFI_TCG2_PROTOCOL_GUID;
        efi_guid_t linux_eventlog_guid = LINUX_EFI_TPM_EVENT_LOG_GUID;
        efi_status_t status;
-       efi_physical_addr_t log_location = 0, log_last_entry = 0;
        struct linux_efi_tpm_eventlog *log_tbl = NULL;
-       struct efi_tcg2_final_events_table *final_events_table = NULL;
        unsigned long first_entry_addr, last_entry_addr;
        size_t log_size, last_entry_size;
-       efi_bool_t truncated;
-       int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
-       efi_tcg2_protocol_t *tcg2_protocol = NULL;
        int final_events_size = 0;
 
-       status = efi_bs_call(locate_protocol, &tcg2_guid, NULL,
-                            (void **)&tcg2_protocol);
-       if (status != EFI_SUCCESS)
-               return;
-
-       status = efi_call_proto(tcg2_protocol, get_event_log, version,
-                               &log_location, &log_last_entry, &truncated);
-
-       if (status != EFI_SUCCESS || !log_location) {
-               version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
-               status = efi_call_proto(tcg2_protocol, get_event_log, version,
-                                       &log_location, &log_last_entry,
-                                       &truncated);
-               if (status != EFI_SUCCESS || !log_location)
-                       return;
-
-       }
-
        first_entry_addr = (unsigned long) log_location;
 
        /*
@@ -93,8 +72,10 @@ void efi_retrieve_tpm2_eventlog(void)
                 * get_event_log only returns the address of the last entry.
                 * We need to calculate its size to deduce the full size of
                 * the logs.
+                *
+                * CC Event log also uses TCG2 format, handle it same as TPM2.
                 */
-               if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) {
+               if (version > EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2) {
                        /*
                         * The TCG2 log format has variable length entries,
                         * and the information to decode the hash algorithms
@@ -127,8 +108,6 @@ void efi_retrieve_tpm2_eventlog(void)
         * Figure out whether any events have already been logged to the
         * final events structure, and if so how much space they take up
         */
-       if (version == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2)
-               final_events_table = get_efi_config_table(EFI_TCG2_FINAL_EVENTS_TABLE_GUID);
        if (final_events_table && final_events_table->nr_events) {
                struct tcg_pcr_event2_head *header;
                int offset;
@@ -165,3 +144,50 @@ void efi_retrieve_tpm2_eventlog(void)
 err_free:
        efi_bs_call(free_pool, log_tbl);
 }
+
+void efi_retrieve_eventlog(void)
+{
+       struct efi_tcg2_final_events_table *final_events_table = NULL;
+       efi_physical_addr_t log_location = 0, log_last_entry = 0;
+       efi_guid_t tpm2_guid = EFI_TCG2_PROTOCOL_GUID;
+       int version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
+       efi_tcg2_protocol_t *tpm2 = NULL;
+       efi_bool_t truncated;
+       efi_status_t status;
+
+       status = efi_bs_call(locate_protocol, &tpm2_guid, NULL, (void **)&tpm2);
+       if (status == EFI_SUCCESS) {
+               status = efi_call_proto(tpm2, get_event_log, version, &log_location,
+                                       &log_last_entry, &truncated);
+
+               if (status != EFI_SUCCESS || !log_location) {
+                       version = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2;
+                       status = efi_call_proto(tpm2, get_event_log, version,
+                                               &log_location, &log_last_entry,
+                                               &truncated);
+               } else {
+                       final_events_table =
+                               get_efi_config_table(EFI_TCG2_FINAL_EVENTS_TABLE_GUID);
+               }
+       } else {
+               efi_guid_t cc_guid = EFI_CC_MEASUREMENT_PROTOCOL_GUID;
+               efi_cc_protocol_t *cc = NULL;
+
+               status = efi_bs_call(locate_protocol, &cc_guid, NULL, (void **)&cc);
+               if (status != EFI_SUCCESS)
+                       return;
+
+               version = EFI_CC_EVENT_LOG_FORMAT_TCG_2;
+               status = efi_call_proto(cc, get_event_log, version, &log_location,
+                                       &log_last_entry, &truncated);
+
+               final_events_table =
+                       get_efi_config_table(EFI_CC_FINAL_EVENTS_TABLE_GUID);
+       }
+
+       if (status != EFI_SUCCESS || !log_location)
+               return;
+
+       efi_retrieve_tcg2_eventlog(version, log_location, log_last_entry,
+                                  truncated, final_events_table);
+}
index 99429bc4b0c7eb0c639b84934fe614f8f8cb5721..d09aa13c7ff08df335231442c585e88320d66fed 100644 (file)
@@ -923,7 +923,7 @@ void __noreturn efi_stub_entry(efi_handle_t handle,
 
        efi_random_get_seed();
 
-       efi_retrieve_tpm2_eventlog();
+       efi_retrieve_eventlog();
 
        setup_graphics(boot_params);
 
index 2493d3d4429be1821234eba7f21455c89ef2b6b2..f0d56f106b60556939f4b7dce9611d4a4c8a9d7b 100644 (file)
@@ -402,6 +402,7 @@ void efi_native_runtime_setup(void);
 #define EFI_CERT_X509_SHA256_GUID              EFI_GUID(0x3bd2a492, 0x96c0, 0x4079, 0xb4, 0x20, 0xfc, 0xf9, 0x8e, 0xf1, 0x03, 0xed)
 #define EFI_CC_BLOB_GUID                       EFI_GUID(0x067b1f5f, 0xcf26, 0x44c5, 0x85, 0x54, 0x93, 0xd7, 0x77, 0x91, 0x2d, 0x42)
 #define EFI_CC_MEASUREMENT_PROTOCOL_GUID       EFI_GUID(0x96751a3d, 0x72f4, 0x41a6, 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b)
+#define EFI_CC_FINAL_EVENTS_TABLE_GUID         EFI_GUID(0xdd4a4648, 0x2de7, 0x4665, 0x96, 0x4d, 0x21, 0xd9, 0xef, 0x5f, 0xb4, 0x46)
 
 /*
  * This GUID is used to pass to the kernel proper the struct screen_info