diff --git a/src/boot/efi/measure.c b/src/boot/efi/measure.c index 01c97c883c..7e440b714e 100644 --- a/src/boot/efi/measure.c +++ b/src/boot/efi/measure.c @@ -5,6 +5,7 @@ #include "macro-fundamental.h" #include "measure.h" #include "memory-util-fundamental.h" +#include "proto/cc-measurement.h" #include "proto/tcg.h" #include "tpm2-pcr.h" #include "util.h" @@ -123,6 +124,69 @@ static EFI_STATUS tpm2_measure_to_pcr_and_event_log( tcg_event); } +static EFI_STATUS cc_measure_to_mr_and_event_log( + EFI_CC_MEASUREMENT_PROTOCOL *cc, + uint32_t pcrindex, + EFI_PHYSICAL_ADDRESS buffer, + uint64_t buffer_size, + const char16_t *description) { + + _cleanup_free_ EFI_CC_EVENT *event = NULL; + uint32_t mr; + EFI_STATUS err; + size_t desc_len; + + assert(cc); + assert(description); + + /* MapPcrToMrIndex service provides callers information on + * how the TPM PCR registers are mapped to the CC measurement + * registers (MR) in the vendor implementation. */ + err = cc->MapPcrToMrIndex(cc, pcrindex, &mr); + if (err != EFI_SUCCESS) + return EFI_NOT_FOUND; + + desc_len = strsize16(description); + event = xmalloc(offsetof(EFI_CC_EVENT, Event) + desc_len); + *event = (EFI_CC_EVENT) { + .Size = offsetof(EFI_CC_EVENT, Event) + desc_len, + .Header.HeaderSize = sizeof(EFI_CC_EVENT_HEADER), + .Header.HeaderVersion = EFI_CC_EVENT_HEADER_VERSION, + .Header.MrIndex = mr, + .Header.EventType = EV_IPL, + }; + + memcpy(event->Event, description, desc_len); + + return cc->HashLogExtendEvent( + cc, + 0, + buffer, + buffer_size, + event); +} + +static EFI_CC_MEASUREMENT_PROTOCOL *cc_interface_check(void) { + EFI_CC_BOOT_SERVICE_CAPABILITY capability = { + .Size = sizeof(capability), + }; + EFI_STATUS err; + EFI_CC_MEASUREMENT_PROTOCOL *cc; + + err = BS->LocateProtocol(MAKE_GUID_PTR(EFI_CC_MEASUREMENT_PROTOCOL), NULL, (void **) &cc); + if (err != EFI_SUCCESS) + return NULL; + + err = cc->GetCapability(cc, &capability); + if (err != EFI_SUCCESS) + return NULL; + + if (!(capability.SupportedEventLogs & EFI_CC_EVENT_LOG_FORMAT_TCG_2)) + return NULL; + + return cc; +} + static EFI_TCG_PROTOCOL *tcg1_interface_check(void) { EFI_PHYSICAL_ADDRESS event_log_location, event_log_last_entry; EFI_TCG_BOOT_SERVICE_CAPABILITY capability = { @@ -213,12 +277,19 @@ EFI_STATUS tpm_log_event(uint32_t pcrindex, EFI_PHYSICAL_ADDRESS buffer, size_t if (tpm1) err = tpm1_measure_to_pcr_and_event_log(tpm1, pcrindex, buffer, buffer_size, description); else { - /* No active TPM found, so don't return an error */ + EFI_CC_MEASUREMENT_PROTOCOL *cc; - if (ret_measured) - *ret_measured = false; + cc = cc_interface_check(); + if (cc) + err = cc_measure_to_mr_and_event_log(cc, pcrindex, buffer, buffer_size, description); + else { + /* No active TPM found, so don't return an error */ - return EFI_SUCCESS; + if (ret_measured) + *ret_measured = false; + + return EFI_SUCCESS; + } } } diff --git a/src/boot/efi/proto/cc-measurement.h b/src/boot/efi/proto/cc-measurement.h new file mode 100644 index 0000000000..9335ecf44c --- /dev/null +++ b/src/boot/efi/proto/cc-measurement.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: LGPL-2.1-or-later */ +#pragma once + +#include "efi.h" + +/* The UEFI specification defines the interface between the confidential virtual guest OS and + * virtual firmware as EFI_CC_MEASUREMENT_PROTOCOL. The measurements are captured in the CC eventlog + * that follows the TCG2 format. TPM PCR registers are mapped to vendor specific measurement registers + * and the mapping can be queried using MapPcrToMrIndex service as part of the protocol. + * + * The "Confidential Computing" section in the UEFI specification covers the details. */ + +#define EFI_CC_MEASUREMENT_PROTOCOL_GUID \ + GUID_DEF(0x96751a3d, 0x72f4, 0x41a6, 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b) + +#define EFI_CC_EVENT_HEADER_VERSION 1 +#define EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002 + +typedef struct { + uint8_t Type; + uint8_t SubType; +} EFI_CC_TYPE; + +typedef struct { + uint8_t Major; + uint8_t Minor; +} EFI_CC_VERSION; + +typedef struct { + uint8_t Size; + EFI_CC_VERSION StructureVersion; + EFI_CC_VERSION ProtocolVersion; + uint32_t HashAlgorithmBitmap; + uint32_t SupportedEventLogs; + EFI_CC_TYPE CcType; +} EFI_CC_BOOT_SERVICE_CAPABILITY; + +typedef struct { + uint32_t HeaderSize; + uint16_t HeaderVersion; + uint32_t MrIndex; + uint32_t EventType; +} _packed_ EFI_CC_EVENT_HEADER; + +typedef struct { + uint32_t Size; + EFI_CC_EVENT_HEADER Header; + uint8_t Event[]; +} _packed_ EFI_CC_EVENT; + +typedef struct EFI_CC_MEASUREMENT_PROTOCOL EFI_CC_MEASUREMENT_PROTOCOL; +struct EFI_CC_MEASUREMENT_PROTOCOL { + EFI_STATUS (EFIAPI *GetCapability)( + EFI_CC_MEASUREMENT_PROTOCOL *This, + EFI_CC_BOOT_SERVICE_CAPABILITY *ProtocolCapability); + void *GetEventLog; + EFI_STATUS (EFIAPI *HashLogExtendEvent)( + EFI_CC_MEASUREMENT_PROTOCOL *This, + uint64_t Flags, + EFI_PHYSICAL_ADDRESS DataToHash, + uint64_t DataToHashLen, + EFI_CC_EVENT *EfiCcEvent); + EFI_STATUS (EFIAPI *MapPcrToMrIndex)( + EFI_CC_MEASUREMENT_PROTOCOL *This, + uint32_t PcrIndex, + uint32_t *MrIndex); +};