summaryrefslogtreecommitdiffstats
path: root/src/boot
diff options
context:
space:
mode:
authorMikko Ylinen <mikko.ylinen@intel.com>2024-01-18 12:34:09 +0100
committerLuca Boccassi <luca.boccassi@gmail.com>2024-01-24 22:30:12 +0100
commit7ff0e0a5e0ecd19ed9178f6e3fd85d9091993f5a (patch)
tree129571bad24d026f79e00da911489f2134948d6e /src/boot
parentmkosi: install libip4tc2 in debian/ubuntu (diff)
downloadsystemd-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.c79
-rw-r--r--src/boot/efi/proto/cc-measurement.h67
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);
+};