From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga04.intel.com (mga04.intel.com [192.55.52.120]) by mx.groups.io with SMTP id smtpd.web10.156825.1673834233086912278 for ; Sun, 15 Jan 2023 17:57:13 -0800 Authentication-Results: mx.groups.io; dkim=fail reason="unable to parse pub key" header.i=@intel.com header.s=intel header.b=FaBDYrD/; spf=pass (domain: intel.com, ip: 192.55.52.120, mailfrom: min.m.xu@intel.com) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1673834233; x=1705370233; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=4FrvdYjaLFzzlg3d6RYKWPpaspEoIXFH/qoni3YTjxA=; b=FaBDYrD/pDQ72nCz0m+UrhUVaUNUF0lz6EpU3GjQjL1psVeDGjvJ4YZO TD9r3xbEKlrHEzGMHtzTA4yWDKYmyJEHLvxwMoj5Q7wTCWYnPO37vmESA XT53AaOYNAJrSe+CsMbd+3SSRczt9KMuD0v/MnKAigBWKjuK4EWhWgANc bPZCl3B2hoppXz2A3vknwSiGSBrNzjRJNu40NUI2bcKC9ARi2k3WzSzYN 3ofSwg82VRqByg3RijUAPwv6jjv41HK/dzbvZ1lSXCxLLtWW+emZpV3SG F/LXrZ2px8PiEoDwWT5qB2aTxYDyy7HRSu2cwyU+lVExVn4kLjXR3oGCS g==; X-IronPort-AV: E=McAfee;i="6500,9779,10591"; a="323068535" X-IronPort-AV: E=Sophos;i="5.97,219,1669104000"; d="scan'208";a="323068535" Received: from orsmga007.jf.intel.com ([10.7.209.58]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Jan 2023 17:57:12 -0800 X-IronPort-AV: E=McAfee;i="6500,9779,10591"; a="652111904" X-IronPort-AV: E=Sophos;i="5.97,219,1669104000"; d="scan'208";a="652111904" Received: from mxu9-mobl1.ccr.corp.intel.com ([10.249.174.76]) by orsmga007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Jan 2023 17:57:10 -0800 From: "Min Xu" To: devel@edk2.groups.io Cc: Min M Xu , Erdem Aktas , James Bottomley , Jiewen Yao , Gerd Hoffmann , Tom Lendacky , Michael Roth Subject: [PATCH V1 1/1] OvmfPkg/AcpiPlatformDxe: Measure ACPI table from QEMU in TDVF Date: Mon, 16 Jan 2023 09:56:58 +0800 Message-Id: <20230116015658.194-1-min.m.xu@intel.com> X-Mailer: git-send-email 2.29.2.windows.2 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Min M Xu https://bugzilla.tianocore.org/show_bug.cgi?id=4245 The ACPI tables are downloaded from QEMU. QEMU/VMM is treated as un-trusted in a td-guest. From the security perspective they should be measured and extended if possible. So that they can be audited later. The measurement protocol may be not installed. In this case it still returns EFI_SUCCESS. Cc: Erdem Aktas Cc: James Bottomley Cc: Jiewen Yao Cc: Gerd Hoffmann Cc: Tom Lendacky Cc: Michael Roth Signed-off-by: Min Xu --- OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf | 2 + OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c | 168 ++++++++++++++++++++ 2 files changed, 170 insertions(+) diff --git a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf index 8939dde42549..ae22bab38cf9 100644 --- a/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf +++ b/OvmfPkg/AcpiPlatformDxe/AcpiPlatformDxe.inf @@ -51,6 +51,8 @@ gEfiAcpiTableProtocolGuid # PROTOCOL ALWAYS_CONSUMED gEfiPciIoProtocolGuid # PROTOCOL SOMETIMES_CONSUMED gQemuAcpiTableNotifyProtocolGuid # PROTOCOL PRODUCES + gEfiCcMeasurementProtocolGuid # PROTOCOL SOMETIMES_CONSUMED + gEfiAcpiSdtProtocolGuid # PROTOCOL SOMETIMES_CONSUMED [Guids] gRootBridgesConnectedEventGroupGuid diff --git a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c index f0d81d6fd73d..f442850c2e00 100644 --- a/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c +++ b/OvmfPkg/AcpiPlatformDxe/QemuFwCfgAcpi.c @@ -18,6 +18,8 @@ #include // QemuFwCfgFindFile() #include // QemuFwCfgS3Enabled() #include // gBS +#include +#include #include "AcpiPlatform.h" @@ -812,12 +814,168 @@ UndoCmdWritePointer ( )); } +/** + Mesure firmware ACPI table with CcMeasurement Protocol + + @param[in] CcProtocol Pointer to the CcMeasurment Protocol + @param[in] EventData Pointer to the event data. + @param[in] EventSize Size of event data. + @param[in] CfgDataBase Configuration data base address. + @param[in] EventSize Size of configuration data . + @retval EFI_NOT_FOUND Cannot locate protocol. + @retval EFI_OUT_OF_RESOURCES Allocate zero pool failure. + @return Status codes returned by + mTcg2Protocol->HashLogExtendEvent. +**/ +STATIC +EFI_STATUS +EFIAPI +CcMeasureAcpiTable ( + IN EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol, + IN CHAR8 *EventData, + IN UINT32 EventSize, + IN EFI_PHYSICAL_ADDRESS CfgDataBase, + IN UINTN CfgDataLength + ) +{ + EFI_STATUS Status; + EFI_CC_EVENT *CcEvent; + UINT32 MrIndex; + + if (CcProtocol == NULL) { + return EFI_INVALID_PARAMETER; + } + + Status = CcProtocol->MapPcrToMrIndex (CcProtocol, 1, &MrIndex); + if (EFI_ERROR (Status)) { + return EFI_INVALID_PARAMETER; + } + + CcEvent = AllocateZeroPool (EventSize + sizeof (EFI_CC_EVENT) - sizeof (CcEvent->Event)); + if (CcEvent == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + CcEvent->Size = EventSize + sizeof (EFI_CC_EVENT) - sizeof (CcEvent->Event); + CcEvent->Header.EventType = EV_PLATFORM_CONFIG_FLAGS; + CcEvent->Header.MrIndex = MrIndex; + CcEvent->Header.HeaderSize = sizeof (EFI_CC_EVENT_HEADER); + CcEvent->Header.HeaderVersion = EFI_CC_EVENT_HEADER_VERSION; + CopyMem (&CcEvent->Event[0], EventData, EventSize); + + Status = CcProtocol->HashLogExtendEvent ( + CcProtocol, + 0, + CfgDataBase, + CfgDataLength, + CcEvent + ); + + FreePool (CcEvent); + + return Status; +} + // // We'll be saving the keys of installed tables so that we can roll them back // in case of failure. 128 tables should be enough for anyone (TM). // #define INSTALLED_TABLES_MAX 128 +/** + * The ACPI tables are downloaded from QEMU. From the security perspective these are + * external inputs and should be measured and extended if possible. So that they can + * be audited later. The measurement protocol may be not installed. In this case it + * still returns EFI_SUCCESS. + * + * @param InstalledKey Pointer to an array which contains the keys of the installed ACPI tables + * @param Length Length of the array + * @retval EFI_SUCCESS Successfully measure the ACPI tables + * @retval Others Other errors as indicated + */ +STATIC +EFI_STATUS +MeasureInstalledTablesFromQemu ( + IN UINTN *InstalledKey, + IN INT32 Length + ) +{ + EFI_STATUS Status; + UINTN Index1; + INT32 Index2; + EFI_ACPI_SDT_HEADER *Table; + EFI_ACPI_TABLE_VERSION Version; + UINTN TableKey; + EFI_ACPI_SDT_PROTOCOL *AcpiSdtProtocol; + EFI_CC_MEASUREMENT_PROTOCOL *CcProtocol = NULL; + + Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **)&CcProtocol); + if (EFI_ERROR (Status)) { + // + // CcMeasurement protocol is not installed. + // + return EFI_SUCCESS; + } + + Status = gBS->LocateProtocol (&gEfiAcpiSdtProtocolGuid, NULL, (void **)&AcpiSdtProtocol); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_ERROR, "Unable to locate ACPI SDT protocol.\n")); + return Status; + } + + Index1 = 0; + do { + Status = AcpiSdtProtocol->GetAcpiTable (Index1, &Table, &Version, &TableKey); + if (EFI_ERROR (Status)) { + if (Status == EFI_NOT_FOUND) { + // + // There is no more ACPI tables found. So we return with EFI_SUCCESS. + // + Status = EFI_SUCCESS; + } + + break; + } + + for (Index2 = 0; Index2 < Length; Index2++) { + if (TableKey == InstalledKey[Index2]) { + break; + } + } + + if (Index2 < Length) { + Status = CcMeasureAcpiTable ( + CcProtocol, + (CHAR8 *)&Table->Signature, + sizeof (Table->Signature), + (EFI_PHYSICAL_ADDRESS)(UINTN)Table, + Table->Length + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Measure ACPI table [%-4.4a] with Size = 0x%x failed! Status = %r\n", + (CONST CHAR8 *)&Table->Signature, + Table->Length, + Status + )); + break; + } else { + DEBUG (( + DEBUG_INFO, + "Measure ACPI table [%-4.4a] with Size = 0x%x\n", + (CONST CHAR8 *)&Table->Signature, + Table->Length + )); + } + } + + Index1++; + } while (TRUE); + + return Status; +} + /** Process a QEMU_LOADER_ADD_POINTER command in order to see if its target byte array is an ACPI table, and if so, install it. @@ -1247,6 +1405,16 @@ InstallQemuFwCfgTables ( } } + // + // Measure the ACPI tables which are downloaded from QEMU + // + if (Installed > 0) { + Status = MeasureInstalledTablesFromQemu (InstalledKey, Installed); + if (EFI_ERROR (Status)) { + goto UninstallAcpiTables; + } + } + // // Install a protocol to notify that the ACPI table provided by Qemu is // ready. -- 2.29.2.windows.2