Files
slimbootloader/BootloaderCommonPkg/Library/TpmLib/TpmEventLog.c
T

489 lines
15 KiB
C
Raw Normal View History

2021-11-10 11:36:23 +00:00
/** @file
TPM Event Log library routines to provide TCG Event Log support.
For more details, consult 'Event Logging' chapter in TCG PC Client
Platform Firmware Profile specification.
Copyright (c) 2017 - 2023, Intel Corporation. All rights reserved.<BR>
2021-11-10 11:36:23 +00:00
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <PiPei.h>
2021-11-10 11:36:23 +00:00
#include <Library/DebugLib.h>
#include <Library/BaseLib.h>
#include <Library/BaseMemoryLib.h>
#include <Library/CryptoLib.h>
#include <Library/BootloaderCommonLib.h>
#include <Library/MemoryAllocationLib.h>
#include <Library/TpmLib.h>
#include <Library/PcdLib.h>
#include <Library/HobLib.h>
2021-11-10 11:36:23 +00:00
#include <Pi/PiBootMode.h>
#include <IndustryStandard/Tpm2Acpi.h>
#include "Tpm2CommandLib.h"
#include "TpmLibInternal.h"
#include "TpmEventLog.h"
/**
Get the TCG log area info from TPM Lib Private data.
@param[out] Lasa Pointer to the Log area start address.
@param[out] Laml Log area minimum length.
**/
VOID
GetTCGLasa (
OUT UINT32 *Lasa,
OUT UINT32 *Laml
)
{
TPM_LIB_PRIVATE_DATA *TpmLibData;
TpmLibData = TpmLibGetPrivateData ();
if (TpmLibData != NULL) {
*Lasa = (UINT32) (TpmLibData->LogAreaStartAddress);
*Laml = TpmLibData->LogAreaMinLength;
} else {
*Lasa = 0;
*Laml = 0;
}
}
/**
Get the size of the compressed TCG 2.0 event.
@param[in] EventHdr address of the event header.
@retval size of the event..
**/
UINT32
GetCompressedTCGEventSize (
IN CONST TCG_PCR_EVENT2_HDR *EventHdr
)
{
UINT8 *Loc;
UINT32 Count;
UINT32 EventSize;
TPMI_ALG_HASH HashAlg;
Loc = (UINT8 *)EventHdr;
// Get the number of digests available in this event
CopyMem (&Count, &EventHdr->Digests.count, sizeof (Count));
if (Count != 0) {
Loc = (UINT8 *) & (EventHdr->Digests.digests[0].hashAlg);
while (Count != 0) {
// Get the HashAlgorithm
CopyMem (&HashAlg, Loc, sizeof (TPMI_ALG_HASH));
Loc += sizeof (TPMI_ALG_HASH);
Loc += GetHashSizeFromAlgo (HashAlg);
--Count;
}
// Get the event description size
CopyMem (&EventSize, Loc, sizeof (EventSize));
Loc += sizeof (EventSize) + EventSize;
}
return (UINT32)(Loc - (UINT8 *)EventHdr);
}
/**
Get the size of the uncompressed TCG 2.0 event.
@param[in] EventHdr address of the event header.
@retval size of the event..
**/
UINT32
GetUnCompressedTCGEventSize (
IN CONST TCG_PCR_EVENT2_HDR *EventHdr
)
{
UINT32 Count;
UINT32 EventSize;
EventSize = sizeof(*EventHdr) - sizeof(TPML_DIGEST_VALUES);
EventSize += sizeof(EventHdr->Digests.count);
2021-11-10 11:36:23 +00:00
for (Count = 0 ; Count < EventHdr->Digests.count; Count++) {
EventSize += sizeof (TPMI_ALG_HASH);
2021-11-10 11:36:23 +00:00
EventSize += GetHashSizeFromAlgo (EventHdr->Digests.digests[Count].hashAlg);
}
EventSize += EventHdr->EventSize;
return EventSize;
}
/**
Allocate and initialize TCG Event Log.
@retval RETURN_SUCCESS Operation completed successfully.
@retval Others Unable to create TCG event log.
**/
RETURN_STATUS
TpmTcgLogInit (
VOID
)
{
UINT64 Lasa;
TPM_LIB_PRIVATE_DATA *TpmLibData;
Lasa = (UINT64) (UINTN) AllocatePages (EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)));
if (Lasa != 0) {
DEBUG ((DEBUG_INFO, "TCG Event Log created at 0x%8X \n", (UINT32)Lasa));
// @todo UEFI BIOS fills the buffer with 0xFF. If we do this we will have to check for the
// presence of 0xFFFFFFFF in EventSize to determine the location for new event while updating
// TCG Event log
ZeroMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcgLogAreaMinLen));
TpmLibSetEventLogData (Lasa, PcdGet32 (PcdTcgLogAreaMinLen));
TpmLibData = TpmLibGetPrivateData ();
if (TpmLibData != NULL) {
TpmLogSpecIDEvent (TpmLibData->ActivePcrBanks);
}
} else {
DEBUG ((DEBUG_WARN, "Unable to allocate memory for TCG Event log.\n"));
return RETURN_OUT_OF_RESOURCES;
}
return RETURN_SUCCESS;
}
/**
Create a TPM event log from bootloader
@retval RETURN_SUCCESS Operation completed successfully.
@retval Others Unable to create TCG event log.
**/
RETURN_STATUS
EFIAPI
CreateTpmEventLogHob (
)
{
VOID *HobData;
TCG_PCR_EVENT2 *TcgPcrEvent2;
UINT8 *DigestBuffer;
UINT32 Lasa; //LogAreaStartAddress
UINT32 Laml; //LogAreaMinimumLength
TCG_PCR_EVENT2_HDR *EmptySlot;
TCG_PCR_EVENT_HDR *FirstEvent;
UINT32 EventSize;
UINT32 HobSize;
UINT32 *EventSizePtr;
GetTCGLasa (&Lasa, &Laml);
if (Lasa == 0 || Laml == 0 ) {
DEBUG ((DEBUG_WARN, "Unable to get log area for TCG 2.0 format events !!\n"));
return RETURN_BUFFER_TOO_SMALL;
}
FirstEvent = (TCG_PCR_EVENT_HDR *)(UINTN)Lasa;
EmptySlot = (TCG_PCR_EVENT2_HDR *)
((UINT8 *)FirstEvent + sizeof (TCG_PCR_EVENT_HDR) + FirstEvent->EventSize);
while (EmptySlot < (TCG_PCR_EVENT2_HDR *)(UINTN)(Lasa + Laml - 1)) {
HobSize = sizeof(EmptySlot->PCRIndex) + sizeof(EmptySlot->EventType) + GetDigestListSize (&EmptySlot->Digests);
EventSizePtr = (UINT32 *) ((UINT8 *) EmptySlot + HobSize);
HobSize = HobSize + sizeof(EmptySlot->EventSize) + *EventSizePtr;
HobData = BuildGuidHob (
&gTcgEvent2EntryHobGuid,
HobSize
);
if (HobData == NULL) {
return EFI_OUT_OF_RESOURCES;
}
TcgPcrEvent2 = HobData;
TcgPcrEvent2->PCRIndex = EmptySlot->PCRIndex;
TcgPcrEvent2->EventType = EmptySlot->EventType;
DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;
DigestBuffer = CopyDigestListToBuffer (DigestBuffer, &EmptySlot->Digests, HASH_ALG_SHA256);
CopyMem (DigestBuffer, EventSizePtr, sizeof(TcgPcrEvent2->EventSize));
DigestBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize);
CopyMem (DigestBuffer, (UINT8 *) ((UINT8 *) EventSizePtr + sizeof(EmptySlot->EventType)), *EventSizePtr);
EventSize = GetCompressedTCGEventSize (EmptySlot);
if (EventSize == 0) {
break;
} else {
EmptySlot = (TCG_PCR_EVENT2_HDR *) ((UINT8 *)EmptySlot + EventSize);
}
}
return EFI_SUCCESS;
}
2021-11-10 11:36:23 +00:00
/**
Add a new PCR event in TCG 2.0 log.
@param[in] Loc memory address where event needs to be copied.
@param[in] EventHdr header of the event.
@param[in] EventData Description of the event.
**/
VOID
AddEventTCGLog (
IN UINT8 *Loc,
IN CONST TCG_PCR_EVENT2_HDR *EventHdr,
IN CONST UINT8 *EventData
)
{
TPMI_ALG_HASH HashAlg;
UINT32 Idx;
DEBUG ((DEBUG_INFO, "Adding event in TCG event log at : 0x%08X \n", Loc));
// Copy the PCR index and event type
CopyMem (Loc, EventHdr, sizeof (TCG_PCRINDEX) + sizeof (TCG_EVENTTYPE));
Loc += sizeof (TCG_PCRINDEX) + sizeof (TCG_EVENTTYPE);
// Copy the digest count
CopyMem (Loc, & (EventHdr->Digests.count), sizeof (EventHdr->Digests.count));
Loc += sizeof (EventHdr->Digests.count);
for (Idx = 0 ; Idx < EventHdr->Digests.count; Idx++) {
HashAlg = EventHdr->Digests.digests[Idx].hashAlg;
// Copy the HashAlgorithm
CopyMem (Loc, &HashAlg, sizeof (TPMI_ALG_HASH));
Loc += sizeof (TPMI_ALG_HASH);
// Copy the hash
CopyMem (Loc, & (EventHdr->Digests.digests[Idx].digest), GetHashSizeFromAlgo (HashAlg));
DEBUG ((DEBUG_INFO, "HASH Extended %llx\n", EventHdr->Digests.digests[Idx].digest));
2021-11-10 11:36:23 +00:00
Loc += GetHashSizeFromAlgo (HashAlg);
}
// Copy the event size and event description
CopyMem (Loc, & (EventHdr->EventSize), sizeof (EventHdr->EventSize));
Loc += sizeof (EventHdr->EventSize);
CopyMem (Loc, EventData, EventHdr->EventSize);
return;
}
2021-11-10 11:36:23 +00:00
/**
Log the Specification ID Version event in TCG 2.0 Event Log.
This event is not extended in PCR's.
@param[in] ActivePcr Currently Active PCR banks in TPM.
@retval RETURN_SUCCESS Operation completed successfully.
@retval Others Unable to log Spec ID event in TCG Event log.
**/
RETURN_STATUS
TpmLogSpecIDEvent (
IN UINT32 ActivePcr
)
{
UINT32 Lasa; //LogAreaStartAddress
UINT32 Laml; //LogAreaMinimumLength
TCG_PCR_EVENT_HDR *FirstPcrEvent;
TCG_EfiSpecIDEventStruct *SpecIdEvent;
TCG_EfiSpecIdEventAlgorithmSize *DigestSize;
UINT32 NumberOfAlgorithms;
UINT8 *VendorInfoSize;
GetTCGLasa (&Lasa, &Laml);
if (Lasa == 0 || Laml == 0 ) {
DEBUG ((DEBUG_WARN, "Unable to get log area for TCG 2.0 format events !!\n"));
return RETURN_BUFFER_TOO_SMALL;
}
// Create the event in TPM 1.2 format
FirstPcrEvent = (TCG_PCR_EVENT_HDR *)(UINTN)Lasa;
FirstPcrEvent->PCRIndex = 0;
FirstPcrEvent->EventType = EV_NO_ACTION;
ZeroMem (FirstPcrEvent->Digest.digest, sizeof (FirstPcrEvent->Digest));
SpecIdEvent = (TCG_EfiSpecIDEventStruct *) (Lasa + sizeof (*FirstPcrEvent));
CopyMem (SpecIdEvent->signature, (VOID *)TCG_EfiSpecIDEventStruct_SIGNATURE_03, sizeof (SpecIdEvent->signature));
SpecIdEvent->platformClass = 0;
SpecIdEvent->specVersionMajor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MAJOR_TPM2;
SpecIdEvent->specVersionMinor = TCG_EfiSpecIDEventStruct_SPEC_VERSION_MINOR_TPM2;
SpecIdEvent->specErrata = TCG_EfiSpecIDEventStruct_SPEC_ERRATA_TPM2;
SpecIdEvent->uintnSize = sizeof (UINTN) / sizeof (UINT32);
NumberOfAlgorithms = 0;
DigestSize = (TCG_EfiSpecIdEventAlgorithmSize *) ((UINT8 *)SpecIdEvent + sizeof (*SpecIdEvent) + sizeof (
NumberOfAlgorithms));
if ((ActivePcr & HASH_ALG_SHA256) != 0) {
DigestSize[NumberOfAlgorithms].algorithmId = TPM_ALG_SHA256;
DigestSize[NumberOfAlgorithms].digestSize = SHA256_DIGEST_SIZE;
NumberOfAlgorithms++;
}
if ((ActivePcr & HASH_ALG_SHA384) != 0) {
DigestSize[NumberOfAlgorithms].algorithmId = TPM_ALG_SHA384;
DigestSize[NumberOfAlgorithms].digestSize = SHA384_DIGEST_SIZE;
NumberOfAlgorithms++;
}
if ((ActivePcr & HASH_ALG_SHA512) != 0) {
DigestSize[NumberOfAlgorithms].algorithmId = TPM_ALG_SHA512;
DigestSize[NumberOfAlgorithms].digestSize = SHA512_DIGEST_SIZE;
NumberOfAlgorithms++;
}
if ((ActivePcr & HASH_ALG_SM3_256) != 0) {
DigestSize[NumberOfAlgorithms].algorithmId = TPM_ALG_SM3_256;
DigestSize[NumberOfAlgorithms].digestSize = SM3_DIGEST_SIZE;
NumberOfAlgorithms++;
}
DigestSize = &DigestSize[NumberOfAlgorithms];
CopyMem (SpecIdEvent + 1, &NumberOfAlgorithms, sizeof (NumberOfAlgorithms));
VendorInfoSize = (UINT8 *)DigestSize;
*VendorInfoSize = 0;
FirstPcrEvent->EventSize = sizeof (*SpecIdEvent)
+ sizeof (NumberOfAlgorithms)
+ (NumberOfAlgorithms * sizeof (TCG_EfiSpecIdEventAlgorithmSize))
+ sizeof (UINT8)
+ *VendorInfoSize;
return RETURN_SUCCESS;
}
/**
Log a PCR event in TCG 2.0 format.
@param[in] EventHdr New event which needs to be logged.
@param[in] EventData New event data or description.
@retval RETURN_SUCCESS Operation completed successfully.
@retval Others Unable to log event in TCG Event log.
**/
RETURN_STATUS
EFIAPI
2021-11-10 11:36:23 +00:00
TpmLogEvent (
IN CONST TCG_PCR_EVENT2_HDR *EventHdr,
IN CONST UINT8 *EventData
)
{
UINT32 Lasa; //LogAreaStartAddress
UINT32 Laml; //LogAreaMinimumLength
UINT32 EventSize;
TCG_PCR_EVENT2_HDR *EmptySlot;
TCG_PCR_EVENT_HDR *FirstEvent;
GetTCGLasa (&Lasa, &Laml);
if (Lasa == 0 || Laml == 0 ) {
DEBUG ((DEBUG_WARN, "Unable to get log area for TCG 2.0 format events !!\n"));
return RETURN_BUFFER_TOO_SMALL;
}
2021-11-10 11:36:23 +00:00
// Navigate log area to Locate the empty space for new event log
// Note : First Event is of type TPM 1.2 (TCG_PCR_EVENT_HDR)
FirstEvent = (TCG_PCR_EVENT_HDR *)(UINTN)Lasa;
EmptySlot = (TCG_PCR_EVENT2_HDR *)
((UINT8 *)FirstEvent + sizeof (TCG_PCR_EVENT_HDR) + FirstEvent->EventSize);
while (EmptySlot < (TCG_PCR_EVENT2_HDR *)(UINTN)(Lasa + Laml - 1)) {
EventSize = GetCompressedTCGEventSize (EmptySlot);
if (EventSize == 0) {
break;
} else {
EmptySlot = (TCG_PCR_EVENT2_HDR *) ((UINT8 *)EmptySlot + EventSize);
}
}
// Before adding new event, check if there is enough space available.
EventSize = GetUnCompressedTCGEventSize (EventHdr);
if (((UINT8 *)EmptySlot + EventSize) <= (UINT8 *)(UINTN)(Lasa + Laml - 1)) {
// Add the new event in the TCG 2.0 log area
AddEventTCGLog ((UINT8 *)EmptySlot, EventHdr, EventData);
} else {
DEBUG ((DEBUG_WARN, "Insufficient space : Event not logged in TCG Event log!!\n"));
}
return RETURN_SUCCESS;
}
/**
Log Startup Locality event in TCG event log.
@param[in] StartupLocality Locality from which TPM_Startup was performed.
**/
VOID
TpmLogLocalityEvent (
IN UINT8 StartupLocality,
IN UINT32 ActivePcrBanks
)
{
TCG_EfiStartupLocalityEvent StartupLocalityEvent;
TCG_PCR_EVENT2_HDR PcrEventHdr;
TPML_DIGEST_VALUES *Digests;
TPM_LIB_PRIVATE_DATA *TpmLibData;
CopyMem (StartupLocalityEvent.Signature, TCG_EfiStartupLocalityEvent_SIGNATURE,
sizeof (StartupLocalityEvent.Signature));
StartupLocalityEvent.StartupLocality = StartupLocality;
PcrEventHdr.PCRIndex = 0;
PcrEventHdr.EventType = EV_NO_ACTION;
PcrEventHdr.EventSize = sizeof (StartupLocalityEvent);
Digests = &PcrEventHdr.Digests;
Digests->count = 0;
TpmLibData = TpmLibGetPrivateData ();
if (TpmLibData != NULL) {
ActivePcrBanks = TpmLibData->ActivePcrBanks;
}
if ((ActivePcrBanks & HASH_ALG_SHA256) != 0) {
Digests->digests[Digests->count].hashAlg = TPM_ALG_SHA256;
ZeroMem (& (Digests->digests[Digests->count].digest), GetHashSizeFromAlgo (TPM_ALG_SHA256));
Digests->count = Digests->count + 1;
}
if ((ActivePcrBanks & HASH_ALG_SHA384) != 0) {
Digests->digests[Digests->count].hashAlg = TPM_ALG_SHA384;
ZeroMem (& (Digests->digests[Digests->count].digest), GetHashSizeFromAlgo (TPM_ALG_SHA384));
Digests->count = Digests->count + 1;
}
if ((ActivePcrBanks & HASH_ALG_SHA512) != 0) {
Digests->digests[Digests->count].hashAlg = TPM_ALG_SHA512;
ZeroMem (& (Digests->digests[Digests->count].digest), GetHashSizeFromAlgo (TPM_ALG_SHA512));
Digests->count = Digests->count + 1;
}
if ((ActivePcrBanks & HASH_ALG_SM3_256) != 0) {
Digests->digests[Digests->count].hashAlg = TPM_ALG_SM3_256;
ZeroMem (& (Digests->digests[Digests->count].digest), GetHashSizeFromAlgo (TPM_ALG_SM3_256));
Digests->count = Digests->count + 1;
}
TpmLogEvent ( &PcrEventHdr, (const UINT8 *)&StartupLocalityEvent);
}