/** @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; | |
} |