diff options
author | Mikko Ylinen <mikko.ylinen@intel.com> | 2024-01-18 12:34:09 +0100 |
---|---|---|
committer | Luca Boccassi <luca.boccassi@gmail.com> | 2024-01-24 22:30:12 +0100 |
commit | 7ff0e0a5e0ecd19ed9178f6e3fd85d9091993f5a (patch) | |
tree | 129571bad24d026f79e00da911489f2134948d6e /src/boot | |
parent | mkosi: install libip4tc2 in debian/ubuntu (diff) | |
download | systemd-7ff0e0a5e0ecd19ed9178f6e3fd85d9091993f5a.tar.xz systemd-7ff0e0a5e0ecd19ed9178f6e3fd85d9091993f5a.zip |
efi: Add EFI CC measurement protocol to stub
In confidential computing, a virtual firmware may support measurement and
event log based upon the hardware Trusted Execution Environment (TEE)
capability.
The UEFI specification defines an interface between the virtual guest OS
and virtual firmware as EFI_CC_MEASUREMENT_PROTOCOL. The (vendor specific)
measurements are captured in the CC eventlog that follows the TCG2 format.
OVMF virtual firmware has the EFI_CC_MEASUREMENT_PROTOCOL support for
Intel Trust Domain Extensions (TDX). Intel TDX has 4 runtime measurement
registers (RTMR) defined as:
RTMR[0] for TDVF configuration
RTMR[1] for the TD OS loader and kernel
RTMR[2] for the OS application
RTMR[3] reserved for special usage only
The RTMR to PCR mappings are defined in the UEFI Spec 2.10 Section 38.4.1
as follows:
TPM PCR Index | CC Measurement Register Index | TDX-measurement register
------------------------------------------------------------------------
0 | 0 | MRTD
1, 7 | 1 | RTMR[0]
2-6 | 2 | RTMR[1]
8-15 | 3 | RTMR[2]
The CC measurement eventlog is currently exposed as a raw CCEL ACPI table
by the guest OS and the events can be replayed to check log matches with
the RTMR values.
Add EFI CC measurement protocol to stub to get the UKI components measured
and included in the remote attestation reports when vTPMs are not available.
Diffstat (limited to 'src/boot')
-rw-r--r-- | src/boot/efi/measure.c | 79 | ||||
-rw-r--r-- | src/boot/efi/proto/cc-measurement.h | 67 |
2 files changed, 142 insertions, 4 deletions
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; + + 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 */ - if (ret_measured) - *ret_measured = false; + if (ret_measured) + *ret_measured = false; - return EFI_SUCCESS; + 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); +}; |