audk/SecurityPkg/Library/DxeTpmMeasurementLib/DxeTpmMeasurementLib.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;
}