From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: Lu Ken Date: Wed, 13 Jul 2022 10:06:12 +0800 Subject: [PATCH] efi/tpm: Add EFI_CC_MEASUREMENT_PROTOCOL support The EFI_CC_MEASUREMENT_PROTOCOL abstracts the measurement for virtual firmware in confidential computing environment. It is similar to the EFI_TCG2_PROTOCOL. It was proposed by Intel and ARM and approved by UEFI organization. It is defined in Intel GHCI specification: https://cdrdv2.intel.com/v1/dl/getContent/726790 . The EDKII header file is available at https://github.com/tianocore/edk2/blob/master/MdePkg/Include/Protocol/CcMeasurement.h . Signed-off-by: Lu Ken Reviewed-by: Daniel Kiper (cherry picked from commit 4c76565b6cb885b7e144dc27f3612066844e2d19) --- grub-core/commands/efi/tpm.c | 48 ++++++++++++++ include/grub/efi/cc.h | 151 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 199 insertions(+) create mode 100644 include/grub/efi/cc.h diff --git a/grub-core/commands/efi/tpm.c b/grub-core/commands/efi/tpm.c index bb59599721..ae09c1bf8b 100644 --- a/grub-core/commands/efi/tpm.c +++ b/grub-core/commands/efi/tpm.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ typedef TCG_PCR_EVENT grub_tpm_event_t; static grub_efi_guid_t tpm_guid = EFI_TPM_GUID; static grub_efi_guid_t tpm2_guid = EFI_TPM2_GUID; +static grub_efi_guid_t cc_measurement_guid = GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID; static grub_efi_handle_t *grub_tpm_handle; static grub_uint8_t grub_tpm_version; @@ -221,6 +223,50 @@ grub_tpm2_log_event (grub_efi_handle_t tpm_handle, unsigned char *buf, return grub_efi_log_event_status (status); } +static void +grub_cc_log_event (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, + const char *description) +{ + grub_efi_cc_event_t *event; + grub_efi_status_t status; + grub_efi_cc_protocol_t *cc; + grub_efi_cc_mr_index_t mr; + + cc = grub_efi_locate_protocol (&cc_measurement_guid, NULL); + if (cc == NULL) + return; + + status = efi_call_3 (cc->map_pcr_to_mr_index, cc, pcr, &mr); + if (status != GRUB_EFI_SUCCESS) + { + grub_efi_log_event_status (status); + return; + } + + event = grub_zalloc (sizeof (grub_efi_cc_event_t) + + grub_strlen (description) + 1); + if (event == NULL) + { + grub_error (GRUB_ERR_OUT_OF_MEMORY, N_("cannot allocate CC event buffer")); + return; + } + + event->Header.HeaderSize = sizeof (grub_efi_cc_event_header_t); + event->Header.HeaderVersion = GRUB_EFI_CC_EVENT_HEADER_VERSION; + event->Header.MrIndex = mr; + event->Header.EventType = EV_IPL; + event->Size = sizeof (*event) + grub_strlen (description) + 1; + grub_strcpy ((char *) event->Event, description); + + status = efi_call_5 (cc->hash_log_extend_event, cc, 0, + (grub_efi_physical_address_t)(grub_addr_t) buf, + (grub_efi_uint64_t) size, event); + grub_free (event); + + if (status != GRUB_EFI_SUCCESS) + grub_efi_log_event_status (status); +} + grub_err_t grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, const char *description) @@ -228,6 +274,8 @@ grub_tpm_measure (unsigned char *buf, grub_size_t size, grub_uint8_t pcr, grub_efi_handle_t tpm_handle; grub_efi_uint8_t protocol_version; + grub_cc_log_event(buf, size, pcr, description); + if (!grub_tpm_handle_find (&tpm_handle, &protocol_version)) return 0; diff --git a/include/grub/efi/cc.h b/include/grub/efi/cc.h new file mode 100644 index 0000000000..8960306890 --- /dev/null +++ b/include/grub/efi/cc.h @@ -0,0 +1,151 @@ +/* + * GRUB -- GRand Unified Bootloader + * Copyright (C) 2022 Free Software Foundation, Inc. + * + * GRUB is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GRUB is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GRUB. If not, see . + */ + +#ifndef GRUB_EFI_CC_H +#define GRUB_EFI_CC_H 1 + +#include +#include +#include + +#define GRUB_EFI_CC_MEASUREMENT_PROTOCOL_GUID \ + { 0x96751a3d, 0x72f4, 0x41a6, \ + { 0xa7, 0x94, 0xed, 0x5d, 0x0e, 0x67, 0xae, 0x6b } \ + }; + +struct grub_efi_cc_version +{ + grub_efi_uint8_t Major; + grub_efi_uint8_t Minor; +}; +typedef struct grub_efi_cc_version grub_efi_cc_version_t; + +/* EFI_CC Type/SubType definition. */ +#define GRUB_EFI_CC_TYPE_NONE 0 +#define GRUB_EFI_CC_TYPE_SEV 1 +#define GRUB_EFI_CC_TYPE_TDX 2 + +struct grub_efi_cc_type +{ + grub_efi_uint8_t Type; + grub_efi_uint8_t SubType; +}; +typedef struct grub_efi_cc_type grub_efi_cc_type_t; + +typedef grub_efi_uint32_t grub_efi_cc_event_log_bitmap_t; +typedef grub_efi_uint32_t grub_efi_cc_event_log_format_t; +typedef grub_efi_uint32_t grub_efi_cc_event_algorithm_bitmap_t; +typedef grub_efi_uint32_t grub_efi_cc_mr_index_t; + +/* Intel TDX measure register index. */ +#define GRUB_TDX_MR_INDEX_MRTD 0 +#define GRUB_TDX_MR_INDEX_RTMR0 1 +#define GRUB_TDX_MR_INDEX_RTMR1 2 +#define GRUB_TDX_MR_INDEX_RTMR2 3 +#define GRUB_TDX_MR_INDEX_RTMR3 4 + +#define GRUB_EFI_CC_EVENT_LOG_FORMAT_TCG_2 0x00000002 +#define GRUB_EFI_CC_BOOT_HASH_ALG_SHA384 0x00000004 +#define GRUB_EFI_CC_EVENT_HEADER_VERSION 1 + +struct grub_efi_cc_event_header +{ + /* Size of the event header itself (sizeof(EFI_TD_EVENT_HEADER)). */ + grub_efi_uint32_t HeaderSize; + + /* + * Header version. For this version of this specification, + * the value shall be 1. + */ + grub_efi_uint16_t HeaderVersion; + + /* Index of the MR that shall be extended. */ + grub_efi_cc_mr_index_t MrIndex; + + /* Type of the event that shall be extended (and optionally logged). */ + grub_efi_uint32_t EventType; +} GRUB_PACKED; +typedef struct grub_efi_cc_event_header grub_efi_cc_event_header_t; + +struct grub_efi_cc_event +{ + /* Total size of the event including the Size component, the header and the Event data. */ + grub_efi_uint32_t Size; + grub_efi_cc_event_header_t Header; + grub_efi_uint8_t Event[0]; +} GRUB_PACKED; +typedef struct grub_efi_cc_event grub_efi_cc_event_t; + +struct grub_efi_cc_boot_service_capability +{ + /* Allocated size of the structure. */ + grub_efi_uint8_t Size; + + /* + * Version of the grub_efi_cc_boot_service_capability_t structure itself. + * For this version of the protocol, the Major version shall be set to 1 + * and the Minor version shall be set to 1. + */ + grub_efi_cc_version_t StructureVersion; + + /* + * Version of the EFI TD protocol. + * For this version of the protocol, the Major version shall be set to 1 + * and the Minor version shall be set to 1. + */ + grub_efi_cc_version_t ProtocolVersion; + + /* Supported hash algorithms. */ + grub_efi_cc_event_algorithm_bitmap_t HashAlgorithmBitmap; + + /* Bitmap of supported event log formats. */ + grub_efi_cc_event_log_bitmap_t SupportedEventLogs; + + /* Indicates the CC type. */ + grub_efi_cc_type_t CcType; +}; +typedef struct grub_efi_cc_boot_service_capability grub_efi_cc_boot_service_capability_t; + +struct grub_efi_cc_protocol +{ + grub_efi_status_t + (*get_capability) (struct grub_efi_cc_protocol *this, + grub_efi_cc_boot_service_capability_t *ProtocolCapability); + + grub_efi_status_t + (*get_event_log) (struct grub_efi_cc_protocol *this, + grub_efi_cc_event_log_format_t EventLogFormat, + grub_efi_physical_address_t *EventLogLocation, + grub_efi_physical_address_t *EventLogLastEntry, + grub_efi_boolean_t *EventLogTruncated); + + grub_efi_status_t + (*hash_log_extend_event) (struct grub_efi_cc_protocol *this, + grub_efi_uint64_t Flags, + grub_efi_physical_address_t DataToHash, + grub_efi_uint64_t DataToHashLen, + grub_efi_cc_event_t *EfiCcEvent); + + grub_efi_status_t + (*map_pcr_to_mr_index) (struct grub_efi_cc_protocol *this, + grub_efi_uint32_t PcrIndex, + grub_efi_cc_mr_index_t *MrIndex); +}; +typedef struct grub_efi_cc_protocol grub_efi_cc_protocol_t; + +#endif