BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=3625 DxeTpmMeasurementLib supports TPM based measurement in DXE phase. After CcMeasurementProtocol is introduced, CC based measurement needs to be supported in DxeTpmMeasurementLib as well. A platform should have only one RTS/RTR. Only one of (virtual)TPM1.2, (virtual)TPM2.0 and CC MR exists. Then only one TCG_SERVICE_PROTOCOL, TCG2_PROTOCOL, CC_MEASUREMENT_PROTOCOL is exposed. In this library when do measurement only one of above 3 protocols will be called. Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Liming Gao <gaoliming@byosoft.com.cn> Cc: Zhiguang Liu <zhiguang.liu@intel.com> Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Sami Mujawar <sami.mujawar@arm.com> Cc: Gerd Hoffmann <kraxel@redhat.com> Reviewed-by: Sami Mujawar <sami.mujawar@arm.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com> Signed-off-by: Min Xu <min.m.xu@intel.com>
		
			
				
	
	
		
			294 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			294 lines
		
	
	
		
			9.2 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  This library is used by other modules to measure data to TPM and Confidential
 | 
						|
  Computing (CC) measure registers.
 | 
						|
 | 
						|
Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved. <BR>
 | 
						|
SPDX-License-Identifier: BSD-2-Clause-Patent
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <PiDxe.h>
 | 
						|
 | 
						|
#include <Protocol/TcgService.h>
 | 
						|
#include <Protocol/Tcg2Protocol.h>
 | 
						|
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/TpmMeasurementLib.h>
 | 
						|
 | 
						|
#include <Guid/Acpi.h>
 | 
						|
#include <IndustryStandard/Acpi.h>
 | 
						|
#include <Protocol/CcMeasurement.h>
 | 
						|
 | 
						|
/**
 | 
						|
  Tpm12 measure and log data, and extend the measurement result into a specific PCR.
 | 
						|
 | 
						|
  @param[in]  PcrIndex         PCR Index.
 | 
						|
  @param[in]  EventType        Event type.
 | 
						|
  @param[in]  EventLog         Measurement event log.
 | 
						|
  @param[in]  LogLen           Event log length in bytes.
 | 
						|
  @param[in]  HashData         The start of the data buffer to be hashed, extended.
 | 
						|
  @param[in]  HashDataLen      The length, in bytes, of the buffer referenced by HashData
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Operation completed successfully.
 | 
						|
  @retval EFI_UNSUPPORTED       TPM device not available.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Out of memory.
 | 
						|
  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
Tpm12MeasureAndLogData (
 | 
						|
  IN UINT32  PcrIndex,
 | 
						|
  IN UINT32  EventType,
 | 
						|
  IN VOID    *EventLog,
 | 
						|
  IN UINT32  LogLen,
 | 
						|
  IN VOID    *HashData,
 | 
						|
  IN UINT64  HashDataLen
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
  EFI_TCG_PROTOCOL      *TcgProtocol;
 | 
						|
  TCG_PCR_EVENT         *TcgEvent;
 | 
						|
  EFI_PHYSICAL_ADDRESS  EventLogLastEntry;
 | 
						|
  UINT32                EventNumber;
 | 
						|
 | 
						|
  TcgEvent = NULL;
 | 
						|
 | 
						|
  //
 | 
						|
  // Tpm activation state is checked in HashLogExtendEvent
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiTcgProtocolGuid, NULL, (VOID **)&TcgProtocol);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  TcgEvent = (TCG_PCR_EVENT *)AllocateZeroPool (sizeof (TCG_PCR_EVENT_HDR) + LogLen);
 | 
						|
  if (TcgEvent == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  TcgEvent->PCRIndex  = PcrIndex;
 | 
						|
  TcgEvent->EventType = EventType;
 | 
						|
  TcgEvent->EventSize = LogLen;
 | 
						|
  CopyMem (&TcgEvent->Event[0], EventLog, LogLen);
 | 
						|
  EventNumber = 1;
 | 
						|
  Status      = TcgProtocol->HashLogExtendEvent (
 | 
						|
                               TcgProtocol,
 | 
						|
                               (EFI_PHYSICAL_ADDRESS)(UINTN)HashData,
 | 
						|
                               HashDataLen,
 | 
						|
                               TPM_ALG_SHA,
 | 
						|
                               TcgEvent,
 | 
						|
                               &EventNumber,
 | 
						|
                               &EventLogLastEntry
 | 
						|
                               );
 | 
						|
 | 
						|
  FreePool (TcgEvent);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Tpm20 measure and log data, and extend the measurement result into a specific PCR.
 | 
						|
 | 
						|
  @param[in]  PcrIndex         PCR Index.
 | 
						|
  @param[in]  EventType        Event type.
 | 
						|
  @param[in]  EventLog         Measurement event log.
 | 
						|
  @param[in]  LogLen           Event log length in bytes.
 | 
						|
  @param[in]  HashData         The start of the data buffer to be hashed, extended.
 | 
						|
  @param[in]  HashDataLen      The length, in bytes, of the buffer referenced by HashData
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Operation completed successfully.
 | 
						|
  @retval EFI_UNSUPPORTED       TPM device not available.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Out of memory.
 | 
						|
  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
Tpm20MeasureAndLogData (
 | 
						|
  IN UINT32  PcrIndex,
 | 
						|
  IN UINT32  EventType,
 | 
						|
  IN VOID    *EventLog,
 | 
						|
  IN UINT32  LogLen,
 | 
						|
  IN VOID    *HashData,
 | 
						|
  IN UINT64  HashDataLen
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS         Status;
 | 
						|
  EFI_TCG2_PROTOCOL  *Tcg2Protocol;
 | 
						|
  EFI_TCG2_EVENT     *Tcg2Event;
 | 
						|
 | 
						|
  //
 | 
						|
  // TPMPresentFlag is checked in HashLogExtendEvent
 | 
						|
  //
 | 
						|
  Status = gBS->LocateProtocol (&gEfiTcg2ProtocolGuid, NULL, (VOID **)&Tcg2Protocol);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  Tcg2Event = (EFI_TCG2_EVENT *)AllocateZeroPool (LogLen + sizeof (EFI_TCG2_EVENT));
 | 
						|
  if (Tcg2Event == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  Tcg2Event->Size                 = (UINT32)LogLen + sizeof (EFI_TCG2_EVENT) - sizeof (Tcg2Event->Event);
 | 
						|
  Tcg2Event->Header.HeaderSize    = sizeof (EFI_TCG2_EVENT_HEADER);
 | 
						|
  Tcg2Event->Header.HeaderVersion = EFI_TCG2_EVENT_HEADER_VERSION;
 | 
						|
  Tcg2Event->Header.PCRIndex      = PcrIndex;
 | 
						|
  Tcg2Event->Header.EventType     = EventType;
 | 
						|
  CopyMem (&Tcg2Event->Event[0], EventLog, LogLen);
 | 
						|
 | 
						|
  Status = Tcg2Protocol->HashLogExtendEvent (
 | 
						|
                           Tcg2Protocol,
 | 
						|
                           0,
 | 
						|
                           (EFI_PHYSICAL_ADDRESS)(UINTN)HashData,
 | 
						|
                           HashDataLen,
 | 
						|
                           Tcg2Event
 | 
						|
                           );
 | 
						|
  FreePool (Tcg2Event);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Cc measure and log data, and extend the measurement result into a
 | 
						|
  specific CC MR.
 | 
						|
 | 
						|
  @param[in]  CcProtocol       Instance of CC measurement protocol
 | 
						|
  @param[in]  PcrIndex         PCR Index.
 | 
						|
  @param[in]  EventType        Event type.
 | 
						|
  @param[in]  EventLog         Measurement event log.
 | 
						|
  @param[in]  LogLen           Event log length in bytes.
 | 
						|
  @param[in]  HashData         The start of the data buffer to be hashed, extended.
 | 
						|
  @param[in]  HashDataLen      The length, in bytes, of the buffer referenced by HashData
 | 
						|
 | 
						|
  @retval EFI_SUCCESS           Operation completed successfully.
 | 
						|
  @retval EFI_UNSUPPORTED       CC guest not available.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Out of memory.
 | 
						|
  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
 | 
						|
  @retval EFI_INVALID_PARAMETER The input parameter is invalid.
 | 
						|
**/
 | 
						|
STATIC
 | 
						|
EFI_STATUS
 | 
						|
CcMeasureAndLogData (
 | 
						|
  IN EFI_CC_MEASUREMENT_PROTOCOL  *CcProtocol,
 | 
						|
  IN UINT32                       PcrIndex,
 | 
						|
  IN UINT32                       EventType,
 | 
						|
  IN VOID                         *EventLog,
 | 
						|
  IN UINT32                       LogLen,
 | 
						|
  IN VOID                         *HashData,
 | 
						|
  IN UINT64                       HashDataLen
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS       Status;
 | 
						|
  EFI_CC_EVENT     *EfiCcEvent;
 | 
						|
  EFI_CC_MR_INDEX  MrIndex;
 | 
						|
 | 
						|
  if (CcProtocol == NULL) {
 | 
						|
    return EFI_INVALID_PARAMETER;
 | 
						|
  }
 | 
						|
 | 
						|
  Status = CcProtocol->MapPcrToMrIndex (CcProtocol, PcrIndex, &MrIndex);
 | 
						|
  if (EFI_ERROR (Status)) {
 | 
						|
    return Status;
 | 
						|
  }
 | 
						|
 | 
						|
  EfiCcEvent = (EFI_CC_EVENT *)AllocateZeroPool (LogLen + sizeof (EFI_CC_EVENT));
 | 
						|
  if (EfiCcEvent == NULL) {
 | 
						|
    return EFI_OUT_OF_RESOURCES;
 | 
						|
  }
 | 
						|
 | 
						|
  EfiCcEvent->Size                 = (UINT32)LogLen + sizeof (EFI_CC_EVENT) - sizeof (EfiCcEvent->Event);
 | 
						|
  EfiCcEvent->Header.HeaderSize    = sizeof (EFI_CC_EVENT_HEADER);
 | 
						|
  EfiCcEvent->Header.HeaderVersion = EFI_CC_EVENT_HEADER_VERSION;
 | 
						|
  EfiCcEvent->Header.MrIndex       = MrIndex;
 | 
						|
  EfiCcEvent->Header.EventType     = EventType;
 | 
						|
  CopyMem (&EfiCcEvent->Event[0], EventLog, LogLen);
 | 
						|
 | 
						|
  Status = CcProtocol->HashLogExtendEvent (
 | 
						|
                         CcProtocol,
 | 
						|
                         0,
 | 
						|
                         (EFI_PHYSICAL_ADDRESS)(UINTN)HashData,
 | 
						|
                         HashDataLen,
 | 
						|
                         EfiCcEvent
 | 
						|
                         );
 | 
						|
  FreePool (EfiCcEvent);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
  Tpm measure and log data, and extend the measurement result into a specific PCR.
 | 
						|
 | 
						|
  @param[in]  PcrIndex         PCR Index.
 | 
						|
  @param[in]  EventType        Event type.
 | 
						|
  @param[in]  EventLog         Measurement event log.
 | 
						|
  @param[in]  LogLen           Event log length in bytes.
 | 
						|
  @param[in]  HashData         The start of the data buffer to be hashed, extended.
 | 
						|
  @param[in]  HashDataLen      The length, in bytes, of the buffer referenced by HashData
 | 
						|
 | 
						|
  @retval EFI_SUCCESS               Operation completed successfully.
 | 
						|
  @retval EFI_UNSUPPORTED       TPM device not available.
 | 
						|
  @retval EFI_OUT_OF_RESOURCES  Out of memory.
 | 
						|
  @retval EFI_DEVICE_ERROR      The operation was unsuccessful.
 | 
						|
**/
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TpmMeasureAndLogData (
 | 
						|
  IN UINT32  PcrIndex,
 | 
						|
  IN UINT32  EventType,
 | 
						|
  IN VOID    *EventLog,
 | 
						|
  IN UINT32  LogLen,
 | 
						|
  IN VOID    *HashData,
 | 
						|
  IN UINT64  HashDataLen
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS                   Status;
 | 
						|
  EFI_CC_MEASUREMENT_PROTOCOL  *CcProtocol;
 | 
						|
 | 
						|
  Status = gBS->LocateProtocol (&gEfiCcMeasurementProtocolGuid, NULL, (VOID **)&CcProtocol);
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    //
 | 
						|
    // Try to measure using Cc measurement protocol
 | 
						|
    //
 | 
						|
    Status = CcMeasureAndLogData (
 | 
						|
               CcProtocol,
 | 
						|
               PcrIndex,
 | 
						|
               EventType,
 | 
						|
               EventLog,
 | 
						|
               LogLen,
 | 
						|
               HashData,
 | 
						|
               HashDataLen
 | 
						|
               );
 | 
						|
  } else {
 | 
						|
    //
 | 
						|
    // Try to measure using Tpm20 protocol
 | 
						|
    //
 | 
						|
    Status = Tpm20MeasureAndLogData (
 | 
						|
               PcrIndex,
 | 
						|
               EventType,
 | 
						|
               EventLog,
 | 
						|
               LogLen,
 | 
						|
               HashData,
 | 
						|
               HashDataLen
 | 
						|
               );
 | 
						|
 | 
						|
    if (EFI_ERROR (Status)) {
 | 
						|
      //
 | 
						|
      // Try to measure using Tpm1.2 protocol
 | 
						|
      //
 | 
						|
      Status = Tpm12MeasureAndLogData (
 | 
						|
                 PcrIndex,
 | 
						|
                 EventType,
 | 
						|
                 EventLog,
 | 
						|
                 LogLen,
 | 
						|
                 HashData,
 | 
						|
                 HashDataLen
 | 
						|
                 );
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 |