1285 lines
36 KiB
C
1285 lines
36 KiB
C
/** @file
|
|
This file contains functions for creating TPM Event Log
|
|
|
|
@copyright
|
|
INTEL CONFIDENTIAL
|
|
Copyright 2016 - 2021 Intel Corporation.
|
|
|
|
The source code contained or described herein and all documents related to the
|
|
source code ("Material") are owned by Intel Corporation or its suppliers or
|
|
licensors. Title to the Material remains with Intel Corporation or its suppliers
|
|
and licensors. The Material may contain trade secrets and proprietary and
|
|
confidential information of Intel Corporation and its suppliers and licensors,
|
|
and is protected by worldwide copyright and trade secret laws and treaty
|
|
provisions. No part of the Material may be used, copied, reproduced, modified,
|
|
published, uploaded, posted, transmitted, distributed, or disclosed in any way
|
|
without Intel's prior express written permission.
|
|
|
|
No license under any patent, copyright, trade secret or other intellectual
|
|
property right is granted to or conferred upon you by disclosure or delivery
|
|
of the Materials, either expressly, by implication, inducement, estoppel or
|
|
otherwise. Any license under such intellectual property rights must be
|
|
express and approved by Intel in writing.
|
|
|
|
Unless otherwise agreed by Intel in writing, you may not remove or alter
|
|
this notice or any other notice embedded in Materials by Intel or
|
|
Intel's suppliers or licensors in any way.
|
|
|
|
This file contains a 'Sample Driver' and is licensed as such under the terms
|
|
of your license agreement with Intel or your vendor. This file may be modified
|
|
by the user, subject to the additional terms of the license agreement.
|
|
|
|
@par Specification
|
|
**/
|
|
|
|
#include <Library/PeiBootGuardEventLogLib.h>
|
|
|
|
#include <PiPei.h>
|
|
#include <IndustryStandard/FirmwareInterfaceTable.h>
|
|
#include <IndustryStandard/Tpm20.h>
|
|
#include <IndustryStandard/UefiTcgPlatform.h>
|
|
#include <Library/DebugLib.h>
|
|
#include <Library/BaseLib.h>
|
|
#include <Library/BaseMemoryLib.h>
|
|
#include <Library/MemoryAllocationLib.h>
|
|
#include <Library/PeiServicesLib.h>
|
|
#include <Library/HobLib.h>
|
|
#include <Library/IoLib.h>
|
|
#include <Library/PciSegmentLib.h>
|
|
#include <Library/BaseCryptLib.h>
|
|
#include <Library/Tpm12CommandLib.h>
|
|
#include <Library/Tpm2CommandLib.h>
|
|
#include <Library/Tpm2DeviceLib.h>
|
|
#include <Library/BootGuardLibVer1.h>
|
|
#include <Protocol/Tcg2Protocol.h>
|
|
#include <Guid/TcgEventHob.h>
|
|
#include <Ppi/FirmwareVolumeInfoMeasurementExcluded.h>
|
|
#include <Register/MeRegs.h>
|
|
#include <Register/CommonMsr.h>
|
|
#include <CpuRegs.h>
|
|
|
|
STATIC EFI_TCG2_EVENT_INFO_STRUCT mTcg2EventInfo[] = {
|
|
{&gTcgEventEntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2},
|
|
{&gTcgEvent2EntryHobGuid, EFI_TCG2_EVENT_LOG_FORMAT_TCG_2},
|
|
};
|
|
|
|
EFI_PEI_PPI_DESCRIPTOR mMeasurementExcludeFvPlatformPpiList = {
|
|
EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
|
|
&gPeiFvMeasurementExcludedPlatformPpiGuid,
|
|
NULL
|
|
};
|
|
|
|
/**
|
|
Dump raw data.
|
|
|
|
@param[in] Data raw data
|
|
@param[in] Size raw data size
|
|
|
|
**/
|
|
VOID
|
|
InternalDumpData (
|
|
IN UINT8 *Data,
|
|
IN UINTN Size
|
|
)
|
|
{
|
|
UINTN Index;
|
|
for (Index = 0; Index < Size; Index++) {
|
|
DEBUG ((DEBUG_INFO, "%02x", (UINTN)Data[Index]));
|
|
}
|
|
}
|
|
|
|
/**
|
|
Dump raw data with colume format.
|
|
|
|
@param[in] Data raw data
|
|
@param[in] Size raw data size
|
|
|
|
**/
|
|
VOID
|
|
InternalDumpHex (
|
|
IN UINT8 *Data,
|
|
IN UINTN Size
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINTN Count;
|
|
UINTN Left;
|
|
|
|
#define COLUME_SIZE (16 * 2)
|
|
|
|
Count = Size / COLUME_SIZE;
|
|
Left = Size % COLUME_SIZE;
|
|
for (Index = 0; Index < Count; Index++) {
|
|
DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));
|
|
InternalDumpData (Data + Index * COLUME_SIZE, COLUME_SIZE);
|
|
DEBUG ((DEBUG_INFO, "\n"));
|
|
}
|
|
|
|
if (Left != 0) {
|
|
DEBUG ((DEBUG_INFO, "%04x: ", Index * COLUME_SIZE));
|
|
InternalDumpData (Data + Index * COLUME_SIZE, Left);
|
|
DEBUG ((DEBUG_INFO, "\n"));
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check if buffer is all zero.
|
|
|
|
@param[in] Buffer Buffer to be checked.
|
|
@param[in] BufferSize Size of buffer to be checked.
|
|
|
|
@retval TRUE Buffer is all zero.
|
|
@retval FALSE Buffer is not all zero.
|
|
**/
|
|
BOOLEAN
|
|
IsZeroBufferLocal (
|
|
IN VOID *Buffer,
|
|
IN UINTN BufferSize
|
|
)
|
|
{
|
|
UINT8 *BufferData;
|
|
UINTN Index;
|
|
|
|
BufferData = Buffer;
|
|
for (Index = 0; Index < BufferSize; Index++) {
|
|
if (BufferData[Index] != 0) {
|
|
return FALSE;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
/**
|
|
Get digest from digest list.
|
|
|
|
@param[in] HashAlg digest algorithm
|
|
@param[in] DigestList digest list
|
|
@param[in] Digest digest
|
|
|
|
@retval EFI_SUCCESS Sha1Digest is found and returned.
|
|
@retval EFI_NOT_FOUND Sha1Digest is not found.
|
|
**/
|
|
EFI_STATUS
|
|
Tpm2GetDigestFromDigestList (
|
|
IN TPMI_ALG_HASH HashAlg,
|
|
IN TPML_DIGEST_VALUES *DigestList,
|
|
IN VOID *Digest
|
|
)
|
|
{
|
|
UINTN Index;
|
|
UINT16 DigestSize;
|
|
|
|
DigestSize = GetHashSizeFromAlgo (HashAlg);
|
|
for (Index = 0; Index < DigestList->count; Index++) {
|
|
if (DigestList->digests[Index].hashAlg == HashAlg) {
|
|
CopyMem (
|
|
Digest,
|
|
&DigestList->digests[Index].digest,
|
|
DigestSize
|
|
);
|
|
return EFI_SUCCESS;
|
|
}
|
|
}
|
|
|
|
return EFI_NOT_FOUND;
|
|
}
|
|
|
|
/**
|
|
Hash and log ACM extended event entry into the TCG Event Log.
|
|
|
|
@param[in] DigestList Pointer to a TPML_DIGEST_VALUES structure.
|
|
@param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure.
|
|
@param[in] NewEventData Pointer to the new event data.
|
|
|
|
@retval EFI_SUCCESS The new event log entry was added.
|
|
@retval EFI_OUT_OF_RESOURCES No enough memory to log the new event.
|
|
**/
|
|
EFI_STATUS
|
|
LogAcmPcrExtendedEvent (
|
|
IN TPML_DIGEST_VALUES *DigestList,
|
|
IN TCG_PCR_EVENT_HDR *NewEventHdr,
|
|
IN UINT8 *NewEventData
|
|
)
|
|
{
|
|
VOID *HobData;
|
|
EFI_STATUS Status;
|
|
UINTN Index;
|
|
EFI_STATUS RetStatus;
|
|
TCG_PCR_EVENT2 *TcgPcrEvent2;
|
|
UINT8 *DigestBuffer;
|
|
UINT32 SupportedEventLogs;
|
|
|
|
SupportedEventLogs = EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 | EFI_TCG2_EVENT_LOG_FORMAT_TCG_2;
|
|
DEBUG ((DEBUG_INFO, "SupportedEventLogs - 0x%08x\n", SupportedEventLogs));
|
|
|
|
RetStatus = EFI_SUCCESS;
|
|
for (Index = 0; Index < sizeof(mTcg2EventInfo) / sizeof(mTcg2EventInfo[0]); Index++) {
|
|
if ((SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) {
|
|
DEBUG((DEBUG_INFO, " LogFormat - 0x%08x\n", mTcg2EventInfo[Index].LogFormat));
|
|
switch (mTcg2EventInfo[Index].LogFormat) {
|
|
case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2:
|
|
Status = Tpm2GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest);
|
|
if (!EFI_ERROR (Status)) {
|
|
HobData = BuildGuidHob (
|
|
&gTcgEventEntryHobGuid,
|
|
sizeof (*NewEventHdr) + NewEventHdr->EventSize
|
|
);
|
|
if (HobData == NULL) {
|
|
RetStatus = EFI_OUT_OF_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
CopyMem (HobData, NewEventHdr, sizeof (*NewEventHdr));
|
|
HobData = (VOID *) ((UINT8*)HobData + sizeof (*NewEventHdr));
|
|
CopyMem (HobData, NewEventData, NewEventHdr->EventSize);
|
|
}
|
|
break;
|
|
|
|
case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2:
|
|
HobData = BuildGuidHob (
|
|
&gTcgEvent2EntryHobGuid,
|
|
sizeof(TcgPcrEvent2->PCRIndex) + sizeof(TcgPcrEvent2->EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2->EventSize) + NewEventHdr->EventSize
|
|
);
|
|
if (HobData == NULL) {
|
|
RetStatus = EFI_OUT_OF_RESOURCES;
|
|
break;
|
|
}
|
|
|
|
TcgPcrEvent2 = HobData;
|
|
TcgPcrEvent2->PCRIndex = NewEventHdr->PCRIndex;
|
|
TcgPcrEvent2->EventType = NewEventHdr->EventType;
|
|
DigestBuffer = (UINT8 *)&TcgPcrEvent2->Digest;
|
|
DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList, PcdGet32 (PcdTpm2HashMask));
|
|
CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(TcgPcrEvent2->EventSize));
|
|
DigestBuffer = DigestBuffer + sizeof(TcgPcrEvent2->EventSize);
|
|
CopyMem (DigestBuffer, NewEventData, NewEventHdr->EventSize);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
return RetStatus;
|
|
}
|
|
|
|
/**
|
|
Find FIT Entry address data by type
|
|
|
|
@param[in] Type FIT Entry type
|
|
|
|
@return FIT entry address data
|
|
**/
|
|
VOID *
|
|
FindFitEntryData (
|
|
IN UINT8 Type
|
|
)
|
|
{
|
|
FIRMWARE_INTERFACE_TABLE_ENTRY *FitEntry;
|
|
UINT32 EntryNum;
|
|
UINT64 FitTableOffset;
|
|
UINT32 Index;
|
|
|
|
FitTableOffset = *(UINT64 *)(UINTN)(BASE_4GB - 0x40);
|
|
FitEntry = (FIRMWARE_INTERFACE_TABLE_ENTRY *)(UINTN)FitTableOffset;
|
|
if (FitEntry[0].Address != *(UINT64 *)"_FIT_ ") {
|
|
return NULL;
|
|
}
|
|
if (FitEntry[0].Type != FIT_TYPE_00_HEADER) {
|
|
return NULL;
|
|
}
|
|
EntryNum = *(UINT32 *)(&FitEntry[0].Size[0]) & 0xFFFFFF;
|
|
for (Index = 0; Index < EntryNum; Index++) {
|
|
if (FitEntry[Index].Type == Type) {
|
|
return (VOID *)(UINTN)FitEntry[Index].Address;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Find ACM address
|
|
|
|
@return ACM address
|
|
**/
|
|
VOID *
|
|
FindAcm (
|
|
VOID
|
|
)
|
|
{
|
|
return FindFitEntryData (FIT_TYPE_02_STARTUP_ACM);
|
|
}
|
|
|
|
/**
|
|
Find BPM address
|
|
|
|
@return BPM address
|
|
**/
|
|
VOID *
|
|
FindBpm (
|
|
VOID
|
|
)
|
|
{
|
|
return FindFitEntryData (FIT_TYPE_0C_BOOT_POLICY_MANIFEST);
|
|
}
|
|
|
|
/**
|
|
Find KM address
|
|
|
|
@return KM address
|
|
**/
|
|
VOID *
|
|
FindKm (
|
|
VOID
|
|
)
|
|
{
|
|
return FindFitEntryData (FIT_TYPE_0B_KEY_MANIFEST);
|
|
}
|
|
|
|
/**
|
|
Find BPM element by structureID
|
|
|
|
@param[in] Bpm BPM address
|
|
@param[in] StructureID BPM element StructureID
|
|
|
|
@return BPM element
|
|
**/
|
|
VOID *
|
|
FindBpmElement (
|
|
IN BOOT_POLICY_MANIFEST_HEADER *Bpm,
|
|
IN UINT64 StructureId
|
|
)
|
|
{
|
|
BOOT_POLICY_MANIFEST_HEADER *BpmHeader;
|
|
IBB_ELEMENT *IbbElement;
|
|
TXT_ELEMENT *TxtElement;
|
|
PLATFORM_CONFIG_DATA_ELEMENT *PcdsElement;
|
|
PLATFORM_MANUFACTURER_ELEMENT *PmElement;
|
|
BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT *BpmSignatureElement;
|
|
UINT8 *Buffer;
|
|
|
|
Buffer = (UINT8 *)Bpm;
|
|
|
|
BpmHeader = (BOOT_POLICY_MANIFEST_HEADER *)Buffer;
|
|
if (*(UINT64 *)BpmHeader->StructureId != BOOT_POLICY_MANIFEST_HEADER_STRUCTURE_ID) {
|
|
return NULL;
|
|
}
|
|
if (StructureId == BOOT_POLICY_MANIFEST_HEADER_STRUCTURE_ID) {
|
|
return Buffer;
|
|
}
|
|
Buffer += sizeof(BOOT_POLICY_MANIFEST_HEADER);
|
|
|
|
IbbElement = (IBB_ELEMENT *)Buffer;
|
|
if (*(UINT64 *)IbbElement->StructureId != BOOT_POLICY_MANIFEST_IBB_ELEMENT_STRUCTURE_ID) {
|
|
return NULL;
|
|
}
|
|
if (StructureId == BOOT_POLICY_MANIFEST_IBB_ELEMENT_STRUCTURE_ID) {
|
|
return Buffer;
|
|
}
|
|
|
|
// Advance to end of IBB_ELEMENT structure
|
|
Buffer = (UINT8*) &(IbbElement->PostIbbHash);
|
|
Buffer += sizeof(UINT32) + IbbElement->PostIbbHash.Size;
|
|
Buffer += sizeof(UINT32); //entrypoint
|
|
|
|
if (StructureId == BOOT_POLICY_MANIFEST_IBB_ELEMENT_DIGEST_ID) {
|
|
return Buffer;
|
|
}
|
|
|
|
/* Need modification here, we can forward the pointer based on IBB digest list size field */
|
|
|
|
Buffer += sizeof(UINT32) + ((SHAX_HASH_STRUCTURE*)Buffer)->Size; //digest
|
|
Buffer += sizeof(UINT8) + (sizeof(IBB_SEGMENT) * (*Buffer)); //size * segmentcount
|
|
|
|
// Do we have TXT element in BPM?
|
|
// If so, advance to end of TXT_ELEMENT structure
|
|
TxtElement = (TXT_ELEMENT *)Buffer;
|
|
if (*(UINT64 *)TxtElement->StructureId == BOOT_POLICY_MANIFEST_TXT_ELEMENT_STRUCTURE_ID)
|
|
{
|
|
Buffer = (UINT8*) &(TxtElement->DigestList);
|
|
Buffer += sizeof(UINT32) + TxtElement->DigestList.Size;
|
|
Buffer += sizeof(UINT8) + (sizeof(IBB_SEGMENT) * (*Buffer)); //size * segmentcount
|
|
}
|
|
|
|
// Do we have Platform Config Data element in BPM?
|
|
// If so, advance to end of PLATFORM_CONFIG_DATA_ELEMENT structure
|
|
PcdsElement = (PLATFORM_CONFIG_DATA_ELEMENT *)Buffer;
|
|
if (*(UINT64 *)PcdsElement->StructureId == BOOT_POLICY_MANIFEST_PLATFORM_CONFIG_DATA_ELEMENT_STRUCTURE_ID)
|
|
{
|
|
Buffer += 11 + PcdsElement->SizeOfData;
|
|
}
|
|
|
|
// Do we have Platform Manufacturer element in BPM?
|
|
// If so, advance to end of PLATFORM_MANUFACTURER_ELEMENT structure
|
|
PmElement = (PLATFORM_MANUFACTURER_ELEMENT *)Buffer;
|
|
while (*(UINT64 *)PmElement->StructureId == BOOT_POLICY_MANIFEST_PLATFORM_MANUFACTURER_ELEMENT_STRUCTURE_ID) {
|
|
if (StructureId == BOOT_POLICY_MANIFEST_PLATFORM_MANUFACTURER_ELEMENT_STRUCTURE_ID) {
|
|
return Buffer;
|
|
}
|
|
Buffer += sizeof(PLATFORM_MANUFACTURER_ELEMENT) + PmElement->PmDataSize;
|
|
PmElement = (PLATFORM_MANUFACTURER_ELEMENT *)Buffer;
|
|
}
|
|
|
|
BpmSignatureElement = (BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT *)Buffer;
|
|
if (*(UINT64 *)BpmSignatureElement->StructureId != BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT_STRUCTURE_ID) {
|
|
return NULL;
|
|
}
|
|
if (StructureId == BOOT_POLICY_MANIFEST_SIGNATURE_ELEMENT_STRUCTURE_ID) {
|
|
return Buffer;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/**
|
|
Find BPM IBB element
|
|
|
|
@param[in] Bpm BPM address
|
|
|
|
@return BPM IBB element
|
|
**/
|
|
VOID *
|
|
FindBpmIbb (
|
|
IN BOOT_POLICY_MANIFEST_HEADER *Bpm
|
|
)
|
|
{
|
|
return FindBpmElement (Bpm, BOOT_POLICY_MANIFEST_IBB_ELEMENT_STRUCTURE_ID);
|
|
}
|
|
|
|
/**
|
|
Check if this NPW ACM
|
|
|
|
@retval TRUE This is NPW ACM
|
|
@retval FALSE This is NOT NPW ACM
|
|
**/
|
|
BOOLEAN
|
|
IsNpwAcm (
|
|
VOID
|
|
)
|
|
{
|
|
ACM_HEADER *Acm;
|
|
|
|
Acm = FindAcm ();
|
|
ASSERT (Acm != NULL);
|
|
if (Acm == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (((Acm->Flags & ACM_HEADER_FLAG_DEBUG_SIGNED) == 0) && (Acm->AcmSvn < ACM_NPW_SVN)) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check if this is VerifiedBoot
|
|
|
|
@retval TRUE This is VerifiedBoot
|
|
@retval FALSE This is NOT VerifiedBoot
|
|
**/
|
|
BOOLEAN
|
|
IsVerifiedBoot (
|
|
VOID
|
|
)
|
|
{
|
|
if ((AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO) & B_BOOT_GUARD_SACM_INFO_VERIFIED_BOOT) != 0) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Check if this is MeasuredBoot
|
|
|
|
@retval TRUE This is MeasuredBoot
|
|
@retval FALSE This is NOT MeasuredBoot
|
|
**/
|
|
BOOLEAN
|
|
IsMeasuredBoot (
|
|
VOID
|
|
)
|
|
{
|
|
if ((AsmReadMsr64 (MSR_BOOT_GUARD_SACM_INFO) & B_BOOT_GUARD_SACM_INFO_MEASURED_BOOT) != 0) {
|
|
return TRUE;
|
|
} else {
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
/**
|
|
Get ACM Policy Status
|
|
|
|
@return ACM Policy Status
|
|
**/
|
|
UINT64
|
|
GetAcmPolicySts (
|
|
VOID
|
|
)
|
|
{
|
|
UINT64 AcmPolicyStatus = MmioRead64 (MMIO_ACM_POLICY_STATUS);
|
|
|
|
return AcmPolicyStatus;
|
|
}
|
|
|
|
/**
|
|
Calculate SHA1 Hash
|
|
|
|
@param[in] Data data
|
|
@param[in] Size data size
|
|
@param[out] Digest SHA1 digest
|
|
**/
|
|
VOID
|
|
CreateSha1Hash (
|
|
IN UINT8 *Data,
|
|
IN UINTN Size,
|
|
OUT UINT8 *Digest
|
|
)
|
|
{
|
|
UINTN CtxSize;
|
|
VOID *HashCtx;
|
|
|
|
CtxSize = Sha1GetContextSize ();
|
|
HashCtx = AllocatePool (CtxSize);
|
|
ASSERT (HashCtx != NULL);
|
|
|
|
if (HashCtx != NULL){
|
|
Sha1Init (HashCtx);
|
|
Sha1Update (HashCtx, Data, Size);
|
|
Sha1Final (HashCtx, Digest);
|
|
FreePool (HashCtx);
|
|
|
|
DEBUG((DEBUG_INFO, "Sha1 Hash - \n"));
|
|
InternalDumpHex((UINT8 *)(Digest), 20);
|
|
}
|
|
|
|
return ;
|
|
}
|
|
|
|
/**
|
|
Calculate SHA256 Hash
|
|
|
|
@param[in] Data data
|
|
@param[in] Size data size
|
|
@param[out] Digest SHA256 digest
|
|
**/
|
|
VOID
|
|
CreateSha256Hash (
|
|
IN UINT8 *Data,
|
|
IN UINTN Size,
|
|
OUT UINT8 *Digest
|
|
)
|
|
{
|
|
UINTN CtxSize;
|
|
VOID *HashCtx;
|
|
|
|
CtxSize = Sha256GetContextSize ();
|
|
HashCtx = AllocatePool (CtxSize);
|
|
ASSERT (HashCtx != NULL);
|
|
|
|
if (HashCtx != NULL){
|
|
Sha256Init (HashCtx);
|
|
Sha256Update (HashCtx, Data, Size);
|
|
Sha256Final (HashCtx, Digest);
|
|
FreePool (HashCtx);
|
|
|
|
DEBUG((DEBUG_INFO, "Sha256 Hash - \n"));
|
|
InternalDumpHex((UINT8 *)(Digest), 32);
|
|
}
|
|
return ;
|
|
}
|
|
|
|
/**
|
|
Calculate SHA384 Hash
|
|
|
|
@param[in] Data data
|
|
@param[in] Size data size
|
|
@param[out] Digest SHA384 digest
|
|
**/
|
|
VOID
|
|
CreateSha384Hash (
|
|
IN UINT8 *Data,
|
|
IN UINTN Size,
|
|
OUT UINT8 *Digest
|
|
)
|
|
{
|
|
UINTN CtxSize;
|
|
VOID *HashCtx;
|
|
|
|
CtxSize = Sha384GetContextSize ();
|
|
HashCtx = AllocatePool (CtxSize);
|
|
ASSERT (HashCtx != NULL);
|
|
|
|
if (HashCtx != NULL){
|
|
Sha384Init (HashCtx);
|
|
Sha384Update (HashCtx, Data, Size);
|
|
Sha384Final (HashCtx, Digest);
|
|
FreePool (HashCtx);
|
|
|
|
DEBUG((DEBUG_INFO, "Sha384 Hash - \n"));
|
|
InternalDumpHex((UINT8 *)(Digest), 48);
|
|
}
|
|
return ;
|
|
}
|
|
|
|
|
|
/**
|
|
Calculate SM3 Hash
|
|
|
|
@param[in] Data data
|
|
@param[in] Size data size
|
|
@param[out] Digest SM3 digest
|
|
**/
|
|
VOID
|
|
CreateSm3Hash (
|
|
IN UINT8 *Data,
|
|
IN UINTN Size,
|
|
OUT UINT8 *Digest
|
|
)
|
|
{
|
|
UINTN CtxSize;
|
|
VOID *HashCtx;
|
|
|
|
CtxSize = Sm3GetContextSize ();
|
|
HashCtx = AllocatePool (CtxSize);
|
|
ASSERT (HashCtx != NULL);
|
|
|
|
if (HashCtx != NULL){
|
|
Sm3Init (HashCtx);
|
|
Sm3Update (HashCtx, Data, Size);
|
|
Sm3Final (HashCtx, Digest);
|
|
FreePool (HashCtx);
|
|
|
|
DEBUG((DEBUG_INFO, "Sm3 Hash - \n"));
|
|
InternalDumpHex((UINT8 *)(Digest), 32);
|
|
}
|
|
return ;
|
|
}
|
|
|
|
/**
|
|
Calculate DetailPCR extend value
|
|
|
|
@param[out] SHA1 DetailPCR digest
|
|
@param[out] SHA256 DetailPCR digest
|
|
@param[out] SHA384 DetailPCR digest
|
|
@param[out] SM3 DetailPCR digest
|
|
**/
|
|
VOID
|
|
CalculateDetailPCRExtendValue (
|
|
IN UINT32 ActivePcrBanks,
|
|
OUT UINT8 *Sha1Digest,
|
|
OUT UINT8 *Sha256Digest,
|
|
OUT UINT8 *Sha384Digest,
|
|
OUT UINT8 *Sm3Digest
|
|
)
|
|
{
|
|
ACM_HEADER *Acm;
|
|
KEY_MANIFEST_STRUCTURE *Km;
|
|
BOOT_POLICY_MANIFEST_HEADER *Bpm;
|
|
IBB_ELEMENT *BpmIbb;
|
|
MAX_DETAIL_PCR_DATA MaxDetailPcrData;
|
|
UINT8 *DetailPcrDataPtr;
|
|
UINT32 AcmSigSize=0;
|
|
UINT32 KmSigSize=0;
|
|
UINT32 BpmSigSize=0;
|
|
UINT32 DetailPcrDataSize;
|
|
UINT32 SavedDetailPcrDataSize;
|
|
UINT8 *CurrPos;
|
|
UINT16 KeyStructSize;
|
|
UINT16 KeyModulusSize;
|
|
UINT16 IbbDigestCount;
|
|
UINT16 IbbDigestSize;
|
|
UINT8 Idx;
|
|
HASH_LIST *IbbHashPtr;
|
|
|
|
Acm = FindAcm ();
|
|
ASSERT (Acm != NULL);
|
|
if (Acm == NULL) return;
|
|
|
|
Km = FindKm ();
|
|
ASSERT (Km != NULL);
|
|
if (Km == NULL) return;
|
|
|
|
//DEBUG ((DEBUG_INFO, "Key- manifest:\n"));
|
|
//InternalDumpHex ((UINT8 *)Km,0x255 );
|
|
|
|
Bpm = FindBpm ();
|
|
ASSERT (Bpm != NULL);
|
|
if (Bpm == NULL) return;
|
|
|
|
//DEBUG ((DEBUG_INFO, "BPM:\n"));
|
|
//InternalDumpHex ((UINT8 *)Bpm,0x3A1 );
|
|
|
|
BpmIbb = FindBpmIbb (Bpm);
|
|
ASSERT (BpmIbb != NULL);
|
|
if (BpmIbb == NULL) return;
|
|
|
|
//DEBUG ((DEBUG_INFO, "IBB:\n"));
|
|
//InternalDumpHex ((UINT8 *)BpmIbb,0x114 );
|
|
|
|
IbbHashPtr = (HASH_LIST*)FindBpmElement(Bpm, BOOT_POLICY_MANIFEST_IBB_ELEMENT_DIGEST_ID);
|
|
ASSERT (IbbHashPtr != NULL);
|
|
if (IbbHashPtr == NULL) return;
|
|
|
|
|
|
//
|
|
// Initialize the DETAIL_PCR_DATA structure
|
|
//
|
|
|
|
//
|
|
// Copy ACM policy status & ACM SVN
|
|
//
|
|
DetailPcrDataPtr = (UINT8*)&MaxDetailPcrData;
|
|
((DETAIL_PCR_DATA*)DetailPcrDataPtr)->AcmPolicySts = GetAcmPolicySts ();
|
|
((DETAIL_PCR_DATA*)DetailPcrDataPtr)->AcmSvn = Acm->AcmSvn;
|
|
// Print values
|
|
DEBUG ((DEBUG_INFO, "DetailPcrData:\n"));
|
|
DEBUG ((DEBUG_INFO, "AcmPolicySts - 0x%04lx\n", ((DETAIL_PCR_DATA*)DetailPcrDataPtr)->AcmPolicySts));
|
|
DEBUG ((DEBUG_INFO, "AcmSvn - 0x%04x\n", ((DETAIL_PCR_DATA*)DetailPcrDataPtr)->AcmSvn));
|
|
//
|
|
// Mask out mutable policies from ACM_POLICY_STS
|
|
//
|
|
if ((BpmIbb->Flags & IBB_FLAG_SRTM_AC ) != 0) {
|
|
DEBUG ((DEBUG_INFO, "DetailPcrData:SRTM_AC_MASK is applied for AcmPolicySts \n"));
|
|
((DETAIL_PCR_DATA*)DetailPcrDataPtr)->AcmPolicySts &= SRTM_AC_MASK;
|
|
}
|
|
//
|
|
// Advance
|
|
//
|
|
DetailPcrDataSize = sizeof(((DETAIL_PCR_DATA*)DetailPcrDataPtr)->AcmPolicySts) + sizeof(((DETAIL_PCR_DATA*)DetailPcrDataPtr)->AcmSvn);
|
|
DetailPcrDataPtr += DetailPcrDataSize;
|
|
|
|
//
|
|
// Copy ACM RSA signature
|
|
//
|
|
if (((ACM_HEADER *) Acm)->HeaderVersion == 0) {
|
|
AcmSigSize = RSA_KEY_SIZE_2K / 8;
|
|
CopyMem (
|
|
DetailPcrDataPtr,
|
|
(UINT8 *) ((ACM_HEADER *) Acm)->Rsa2048Sig,
|
|
AcmSigSize);
|
|
}
|
|
else {
|
|
AcmSigSize = RSA_KEY_SIZE_3K / 8;
|
|
CopyMem (
|
|
DetailPcrDataPtr,
|
|
(UINT8 *) ((ACM_HEADER_3 *) Acm)->Rsa3072Sig,
|
|
AcmSigSize);
|
|
}
|
|
//
|
|
// Print values
|
|
//
|
|
DEBUG ((DEBUG_INFO, "AcmRsaSignature: AcmSigSize= 0x%04x\n", AcmSigSize));
|
|
InternalDumpHex (DetailPcrDataPtr, AcmSigSize);
|
|
//
|
|
// Advance
|
|
//
|
|
DetailPcrDataSize += AcmSigSize;
|
|
DetailPcrDataPtr += AcmSigSize;
|
|
|
|
//
|
|
// Copy KM signature
|
|
//
|
|
|
|
CurrPos = ((UINT8*)Km + Km->KeySignatureOffset);
|
|
|
|
if (((KEY_AND_SIGNATURE_STRUCT*)CurrPos)->KeyAlg == TPM_ALG_RSA) {
|
|
|
|
// advance the pointer to version (1 byte) and Key_alg (2 byte)
|
|
CurrPos = (UINT8 *) (CurrPos + sizeof(UINT8) + sizeof(UINT16));
|
|
KeyModulusSize = (((KEY_STRUCT_HEADER *)(UINT8*)CurrPos)->KeySizeBits)/8; //modulus size in bytes
|
|
KeyStructSize = sizeof(UINT8) + sizeof(UINT16) + sizeof(UINT32) + KeyModulusSize;
|
|
CurrPos = CurrPos + KeyStructSize;
|
|
|
|
// Here we have reached up to SigScheme
|
|
if((*(UINT16*)CurrPos == TPM_ALG_RSASSA) || (*(UINT16*)CurrPos == TPM_ALG_RSAPSS)) {
|
|
CurrPos += sizeof(UINT16);
|
|
KmSigSize = (((SIGNATURE_STRUCT_HEADER*)CurrPos)->SigSizeBits)/8;
|
|
CurrPos += sizeof(UINT8) + sizeof(UINT16) + sizeof(UINT16); //Sirsion( 1 byte) + sigsize (2 bytes) + hash_alg (2 bytes)
|
|
|
|
//we have reached here to the signature data
|
|
DEBUG ((DEBUG_INFO, "KmSignature:\n"));
|
|
InternalDumpHex (CurrPos, KmSigSize);
|
|
|
|
CopyMem (
|
|
DetailPcrDataPtr,
|
|
CurrPos,
|
|
KmSigSize);
|
|
}
|
|
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "Unsupported KeyAlg\n"));
|
|
}
|
|
|
|
DetailPcrDataSize += KmSigSize;
|
|
DetailPcrDataPtr += KmSigSize;
|
|
|
|
//
|
|
// Copy BPM signature
|
|
//
|
|
|
|
CurrPos = NULL;
|
|
CurrPos = ((UINT8*)Bpm + Bpm->KeySignatureOffset);
|
|
DEBUG ((DEBUG_INFO, "BpmSignatureoffset:0x%04x\n", Bpm->KeySignatureOffset));
|
|
|
|
|
|
if(((KEY_AND_SIGNATURE_STRUCT*)CurrPos)->KeyAlg == TPM_ALG_RSA) {
|
|
|
|
// advance the pointer to version (1 byte) and Key_alg (2 byte)
|
|
CurrPos = (UINT8 *) (CurrPos + sizeof(UINT8) + sizeof(UINT16));
|
|
KeyModulusSize = (((KEY_STRUCT_HEADER *)(UINT8*) CurrPos)-> KeySizeBits)/8; //modulus size in bytes
|
|
KeyStructSize = sizeof(UINT8) + sizeof(UINT16) + sizeof(UINT32) + KeyModulusSize;
|
|
CurrPos = CurrPos + KeyStructSize;
|
|
|
|
// Here we have reached up to SigScheme
|
|
if((*(UINT16*)CurrPos == TPM_ALG_RSASSA) || (*(UINT16*)CurrPos == TPM_ALG_RSAPSS)) {
|
|
CurrPos += sizeof(UINT16);
|
|
BpmSigSize = (((SIGNATURE_STRUCT_HEADER*)CurrPos)->SigSizeBits)/8;
|
|
CurrPos += sizeof(UINT8) + sizeof(UINT16) + sizeof(UINT16) ;//Sirsion( 1 byte) + sigsize (2 bytes) + hash_alg (2 bytes)
|
|
|
|
//we have reached here to the signature data
|
|
DEBUG ((DEBUG_INFO, "BpmSignature:\n"));
|
|
InternalDumpHex (CurrPos, BpmSigSize);
|
|
|
|
CopyMem (
|
|
DetailPcrDataPtr,
|
|
CurrPos,
|
|
BpmSigSize);
|
|
}
|
|
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "Unsupported KeyAlg\n"));
|
|
}
|
|
|
|
DetailPcrDataSize += BpmSigSize;
|
|
DetailPcrDataPtr += BpmSigSize;
|
|
|
|
CurrPos = (UINT8 *)IbbHashPtr;
|
|
|
|
SavedDetailPcrDataSize = DetailPcrDataSize;
|
|
|
|
IbbDigestCount = ((HASH_LIST*)CurrPos)->Count;
|
|
DEBUG ((DEBUG_INFO, "IbbDigestCount = 0x%04x\n", IbbDigestCount));
|
|
//past size and count field
|
|
CurrPos += sizeof(UINT16) + sizeof(UINT16);
|
|
|
|
for(Idx = 0; Idx < IbbDigestCount ; Idx++) {
|
|
DEBUG ((DEBUG_INFO, "Idx = 0x%04x\n", Idx));
|
|
DEBUG ((DEBUG_INFO, "ActivePcrBanks = 0x%x\n", ActivePcrBanks));
|
|
|
|
if(((SHAX_HASH_STRUCTURE *)CurrPos)->HashAlg ==TPM_ALG_SHA1) {
|
|
IbbDigestSize = SHA1_DIGEST_SIZE;
|
|
CurrPos += sizeof(UINT16) + sizeof(UINT16);
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {
|
|
CopyMem (
|
|
DetailPcrDataPtr,
|
|
CurrPos,
|
|
IbbDigestSize);
|
|
|
|
InternalDumpHex (CurrPos, IbbDigestSize);
|
|
DetailPcrDataSize = SavedDetailPcrDataSize + IbbDigestSize;
|
|
CreateSha1Hash ((UINT8*)&MaxDetailPcrData, DetailPcrDataSize, (UINT8 *)Sha1Digest);
|
|
}
|
|
CurrPos += IbbDigestSize;
|
|
}
|
|
|
|
if(((SHAX_HASH_STRUCTURE *)CurrPos)->HashAlg ==TPM_ALG_SHA256) {
|
|
IbbDigestSize = SHA256_DIGEST_SIZE;
|
|
CurrPos += sizeof(UINT16) + sizeof(UINT16);
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {
|
|
CopyMem (
|
|
DetailPcrDataPtr,
|
|
CurrPos,
|
|
IbbDigestSize);
|
|
|
|
InternalDumpHex (CurrPos, IbbDigestSize);
|
|
DetailPcrDataSize = SavedDetailPcrDataSize + IbbDigestSize;
|
|
CreateSha256Hash ((UINT8*)&MaxDetailPcrData, DetailPcrDataSize, (UINT8 *)Sha256Digest);
|
|
}
|
|
CurrPos += IbbDigestSize;
|
|
}
|
|
|
|
if(((SHAX_HASH_STRUCTURE *)CurrPos)->HashAlg ==TPM_ALG_SHA384) {
|
|
IbbDigestSize = SHA384_DIGEST_SIZE;
|
|
CurrPos += sizeof(UINT16) + sizeof(UINT16);
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {
|
|
CopyMem (
|
|
DetailPcrDataPtr,
|
|
CurrPos,
|
|
IbbDigestSize);
|
|
|
|
InternalDumpHex (CurrPos, IbbDigestSize);
|
|
DetailPcrDataSize = SavedDetailPcrDataSize + IbbDigestSize;
|
|
CreateSha384Hash ((UINT8*)&MaxDetailPcrData, DetailPcrDataSize, (UINT8 *)Sha384Digest);
|
|
}
|
|
CurrPos += IbbDigestSize;
|
|
}
|
|
|
|
|
|
if(((SHAX_HASH_STRUCTURE *)CurrPos)->HashAlg ==TPM_ALG_SM3_256) {
|
|
IbbDigestSize = SM3_256_DIGEST_SIZE;
|
|
CurrPos += sizeof(UINT16) + sizeof(UINT16);
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {
|
|
CopyMem (
|
|
DetailPcrDataPtr,
|
|
CurrPos,
|
|
IbbDigestSize);
|
|
|
|
InternalDumpHex (CurrPos, IbbDigestSize);
|
|
DetailPcrDataSize = SavedDetailPcrDataSize + IbbDigestSize;
|
|
CreateSm3Hash ((UINT8*)&MaxDetailPcrData, DetailPcrDataSize, (UINT8 *)Sm3Digest);
|
|
}
|
|
CurrPos += IbbDigestSize;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
Create DetailPCR event log
|
|
|
|
@param[in] ActivePcrBanks Active PCR Banks
|
|
**/
|
|
VOID
|
|
CreateDetailPCREvent (
|
|
IN UINT32 ActivePcrBanks
|
|
)
|
|
{
|
|
TCG_PCR_EVENT_HDR NewEventHdr;
|
|
UINT8 Sha1[SHA1_DIGEST_SIZE];
|
|
UINT8 Sha256[SHA256_DIGEST_SIZE];
|
|
UINT8 Sha384[SHA384_DIGEST_SIZE];
|
|
UINT8 Sm3[SM3_256_DIGEST_SIZE];
|
|
TPML_DIGEST_VALUES DigestList;
|
|
|
|
NewEventHdr.PCRIndex = 0;
|
|
NewEventHdr.EventType = EV_S_CRTM_CONTENTS;
|
|
|
|
CalculateDetailPCRExtendValue (ActivePcrBanks, Sha1, Sha256, Sha384, Sm3);
|
|
DEBUG ((DEBUG_INFO, "CreateDetailPCREvent()\n"));
|
|
|
|
ZeroMem (&DigestList, sizeof(DigestList));
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {
|
|
DigestList.digests[DigestList.count].hashAlg = TPM_ALG_SHA1;
|
|
CopyMem (DigestList.digests[DigestList.count].digest.sha1, Sha1, SHA1_DIGEST_SIZE);
|
|
DigestList.count ++;
|
|
}
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {
|
|
DigestList.digests[DigestList.count].hashAlg = TPM_ALG_SHA256;
|
|
CopyMem (DigestList.digests[DigestList.count].digest.sha256, Sha256, SHA256_DIGEST_SIZE);
|
|
DigestList.count ++;
|
|
}
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {
|
|
DigestList.digests[DigestList.count].hashAlg = TPM_ALG_SHA384;
|
|
CopyMem (DigestList.digests[DigestList.count].digest.sha384, Sha384, SHA384_DIGEST_SIZE);
|
|
DigestList.count ++;
|
|
}
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {
|
|
DigestList.digests[DigestList.count].hashAlg = TPM_ALG_SM3_256;
|
|
CopyMem (DigestList.digests[DigestList.count].digest.sm3_256, Sm3, SM3_256_DIGEST_SIZE);
|
|
DigestList.count ++;
|
|
}
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) {
|
|
DEBUG ((DEBUG_INFO, "Unsupported PCR bank\n"));
|
|
}
|
|
|
|
if (IsNpwAcm()) {
|
|
NewEventHdr.EventSize = sizeof ("Boot Guard Debug Measured S-CRTM");
|
|
LogAcmPcrExtendedEvent (&DigestList, &NewEventHdr, (UINT8 *) "Boot Guard Debug Measured S-CRTM");
|
|
} else {
|
|
NewEventHdr.EventSize = sizeof ("Boot Guard Measured S-CRTM");
|
|
LogAcmPcrExtendedEvent (&DigestList, &NewEventHdr, (UINT8 *) "Boot Guard Measured S-CRTM");
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "End of CreateDetailPCREvent()\n"));
|
|
}
|
|
|
|
/**
|
|
Create Locality Startup event entry
|
|
|
|
The Startup Locality event should be placed in the log before any event which extends
|
|
PCR[0]. This allows software which needs to parse the TCG Event Log to initialize its
|
|
internal PCR[0] state correctly.
|
|
|
|
@param[in] StartupLocality TPM Startup Locality
|
|
@param[in] ActivePcrBanks Active PCR Banks
|
|
**/
|
|
VOID
|
|
CreateLocalityStartupEvent (
|
|
IN UINT8 StartupLocality,
|
|
IN UINT32 ActivePcrBanks
|
|
)
|
|
{
|
|
|
|
TCG_PCR_EVENT_HDR NewEventHdr;
|
|
UINT8 Sha1[SHA1_DIGEST_SIZE];
|
|
UINT8 Sha256[SHA256_DIGEST_SIZE];
|
|
UINT8 Sha384[SHA384_DIGEST_SIZE];
|
|
UINT8 Sm3[SM3_256_DIGEST_SIZE];
|
|
TPML_DIGEST_VALUES DigestList;
|
|
TCG_EFI_STARTUP_LOCALITY_EVENT LocalityEventData;
|
|
static CONST CHAR8 LocalityString[] = "StartupLocality\0";
|
|
|
|
ZeroMem (&Sha1, SHA1_DIGEST_SIZE);
|
|
ZeroMem (&Sha256, SHA256_DIGEST_SIZE);
|
|
ZeroMem (&Sha384, SHA384_DIGEST_SIZE);
|
|
ZeroMem (&Sm3, SM3_256_DIGEST_SIZE);
|
|
|
|
NewEventHdr.PCRIndex = 0;
|
|
NewEventHdr.EventType = EV_NO_ACTION;
|
|
|
|
ZeroMem (&DigestList, sizeof(DigestList));
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) {
|
|
DigestList.digests[DigestList.count].hashAlg = TPM_ALG_SHA1;
|
|
CopyMem (DigestList.digests[DigestList.count].digest.sha1, Sha1, SHA1_DIGEST_SIZE);
|
|
DigestList.count ++;
|
|
}
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) {
|
|
DigestList.digests[DigestList.count].hashAlg = TPM_ALG_SHA256;
|
|
CopyMem (DigestList.digests[DigestList.count].digest.sha256, Sha256, SHA256_DIGEST_SIZE);
|
|
DigestList.count ++;
|
|
}
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) {
|
|
DigestList.digests[DigestList.count].hashAlg = TPM_ALG_SHA384;
|
|
CopyMem (DigestList.digests[DigestList.count].digest.sha384, Sha384, SHA384_DIGEST_SIZE);
|
|
DigestList.count ++;
|
|
}
|
|
|
|
if ((ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) {
|
|
DigestList.digests[DigestList.count].hashAlg = TPM_ALG_SM3_256;
|
|
CopyMem (DigestList.digests[DigestList.count].digest.sm3_256, Sm3, SM3_256_DIGEST_SIZE);
|
|
DigestList.count ++;
|
|
}
|
|
|
|
NewEventHdr.EventSize = sizeof (TCG_EFI_STARTUP_LOCALITY_EVENT);
|
|
|
|
CopyMem (LocalityEventData.Signature, LocalityString, AsciiStrSize (LocalityString));
|
|
LocalityEventData.StartupLocality = StartupLocality;
|
|
|
|
LogAcmPcrExtendedEvent (&DigestList, &NewEventHdr,(UINT8 *) &LocalityEventData);
|
|
}
|
|
|
|
/**
|
|
Get Active PCR Banks.
|
|
|
|
@retval UINT32 Number of PCR Banks.
|
|
**/
|
|
|
|
UINT32
|
|
GetActivePcrBanks (
|
|
VOID
|
|
)
|
|
{
|
|
EFI_STATUS Status;
|
|
UINT32 ActivePcrBanks;
|
|
TPML_PCR_SELECTION Pcrs;
|
|
UINTN Index;
|
|
|
|
DEBUG ((DEBUG_INFO, "GetActivePcrBank!\n"));
|
|
|
|
Status = Tpm2GetCapabilityPcrs (&Pcrs);
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n"));
|
|
ActivePcrBanks = EFI_TCG2_BOOT_HASH_ALG_SHA1;
|
|
} else {
|
|
DEBUG ((DEBUG_INFO, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count));
|
|
ActivePcrBanks = 0;
|
|
for (Index = 0; Index < Pcrs.count; Index++) {
|
|
DEBUG ((DEBUG_INFO, "hash - %x\n", Pcrs.pcrSelections[Index].hash));
|
|
switch (Pcrs.pcrSelections[Index].hash) {
|
|
case TPM_ALG_SHA1:
|
|
if (!IsZeroBufferLocal (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
|
|
ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA1;
|
|
}
|
|
break;
|
|
case TPM_ALG_SHA256:
|
|
if (!IsZeroBufferLocal (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
|
|
ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA256;
|
|
}
|
|
break;
|
|
case TPM_ALG_SHA384:
|
|
if (!IsZeroBufferLocal (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
|
|
ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA384;
|
|
}
|
|
break;
|
|
case TPM_ALG_SHA512:
|
|
if (!IsZeroBufferLocal (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
|
|
ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA512;
|
|
}
|
|
break;
|
|
case TPM_ALG_SM3_256:
|
|
if (!IsZeroBufferLocal (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) {
|
|
ActivePcrBanks |= EFI_TCG2_BOOT_HASH_ALG_SM3_256;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return ActivePcrBanks;
|
|
}
|
|
|
|
/**
|
|
This function will replicate the data extended into the TPM by the Boot Guard ACM
|
|
and register the required events into the TCG event log.
|
|
**/
|
|
VOID
|
|
CreateTpmEventLog (
|
|
VOID
|
|
)
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
UINT32 ActivePcrBanks;
|
|
ACM_BIOS_POLICY AcmPolicySts;
|
|
UINT8 TpmStartupLocality;
|
|
|
|
DEBUG ((DEBUG_INFO, "CreateTpmEventLog ()\n"));
|
|
|
|
AcmPolicySts.Data = GetAcmPolicySts ();
|
|
|
|
//
|
|
// Initialize TPM device
|
|
//
|
|
Status = Tpm2RequestUseTpm ();
|
|
if (EFI_ERROR (Status)) {
|
|
DEBUG ((DEBUG_WARN, "TPM2 not detected!\n"));
|
|
}
|
|
|
|
ActivePcrBanks = GetActivePcrBanks ();
|
|
|
|
//
|
|
// Initialize TPM Startup locality to 0
|
|
//
|
|
TpmStartupLocality = LOCALITY_0_INDICATOR;
|
|
|
|
//
|
|
// If BootGuard ACM is the S-CRTM, check for the TPM Startup locality used.
|
|
// b'001--> BTG / b'010 (2) --> TXT / b'100 (4) --> PFR
|
|
//
|
|
if (AcmPolicySts.Bits.SCrtmStatus != 0) {
|
|
//
|
|
// Update TPM startup locality based on the ACM Policy Status TpmStartupLocality field:
|
|
// 0x0 : Startup Locality = 3
|
|
// 0x1 : Startup Locality = 0
|
|
//
|
|
if (AcmPolicySts.Bits.TpmStartupLocality == 0) {
|
|
TpmStartupLocality = LOCALITY_3_INDICATOR;
|
|
}
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "TpmStartupLocality = 0x%x\n", TpmStartupLocality));
|
|
CreateLocalityStartupEvent (TpmStartupLocality, ActivePcrBanks);
|
|
|
|
//
|
|
// If BootGuard ACM is the S-CRTM,
|
|
// create event logs from previous PCR extensions on behalf of ACM.
|
|
//
|
|
if (AcmPolicySts.Bits.SCrtmStatus != 0) {
|
|
CreateDetailPCREvent (ActivePcrBanks);
|
|
}
|
|
|
|
DEBUG ((DEBUG_INFO, "End of CreateTpmEventLog ()\n"));
|
|
}
|
|
|
|
/**
|
|
If Boot Guard already measured IBB, we do not need let TPM measure it again.
|
|
So we let BiosInfo PEIM register the Measurement Exclude PPI
|
|
and TPM driver knows this Fv should be excluded.
|
|
**/
|
|
VOID
|
|
ExcludeIbbFv (
|
|
VOID
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_INFO, "Excluding IBB FVs as Boot Guard did Measurement of PEI FV\n"));
|
|
PeiServicesInstallPpi (&mMeasurementExcludeFvPlatformPpiList);
|
|
}
|
|
|
|
/**
|
|
This is the library's callback entry point that will handle the TCG event logging
|
|
depending on the Boot Guard configuration.
|
|
|
|
@param[in] PeiServices Pointer to PEI Services Table.
|
|
@param[in] NotifyDesc Pointer to the descriptor for the Notification event that
|
|
caused this function to execute.
|
|
@param[in] Ppi Pointer to the PPI data associated with this function.
|
|
|
|
@retval EFI_SUCCESS The function completes successfully
|
|
@retval Others Bootguard not supported
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
CreateBootguardEventLogEntries (
|
|
IN EFI_PEI_SERVICES **PeiServices,
|
|
IN EFI_PEI_NOTIFY_DESCRIPTOR *NotifyDesc,
|
|
IN VOID *InvokePpi
|
|
)
|
|
{
|
|
BOOT_GUARD_INFO BootGuardInfo;
|
|
|
|
DEBUG ((DEBUG_INFO, "CreateBootguardEventLogEntries notify function\n"));
|
|
|
|
ZeroMem (&BootGuardInfo, sizeof(BOOT_GUARD_INFO));
|
|
GetBootGuardInfo (&BootGuardInfo);
|
|
|
|
if (BootGuardInfo.BootGuardCapability == TRUE) {
|
|
//
|
|
// Create TPM event log if not Sx Resume Type - S3/Deep-S3/FFS Resume
|
|
// Note: S4->S0 is similar to S5->S0
|
|
//
|
|
if(BootGuardInfo.ByPassTpmEventLog != TRUE) {
|
|
DEBUG ((DEBUG_INFO, "BIOS is Creating Event Log for ACM measurements\n"));
|
|
CreateTpmEventLog ();
|
|
//
|
|
// If Boot Guard already measured IBB, we do not need let TPM measure it again.
|
|
//
|
|
if (IsMeasuredBoot ()) {
|
|
ExcludeIbbFv ();
|
|
}
|
|
}
|
|
} else {
|
|
return EFI_UNSUPPORTED;
|
|
}
|
|
|
|
return EFI_SUCCESS;
|
|
}
|
|
|
|
STATIC EFI_PEI_NOTIFY_DESCRIPTOR mNotifyList = {
|
|
EFI_PEI_PPI_DESCRIPTOR_NOTIFY_CALLBACK | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
|
|
&gPeiTpmInitializationDonePpiGuid,
|
|
CreateBootguardEventLogEntries
|
|
};
|
|
|
|
/**
|
|
The constructor registers a callback to create the ACM measurements'
|
|
events into the TCG log, once the gEfiTpmDeviceSelectedGuid has been
|
|
produced by the TCG PEIM module.
|
|
|
|
@param FileHandle The handle of FFS header the loaded driver.
|
|
@param PeiServices The pointer to the PEI services.
|
|
|
|
@retval EFI_SUCCESS The constructor always returns EFI_SUCCESS.
|
|
|
|
**/
|
|
EFI_STATUS
|
|
EFIAPI
|
|
PeiBootGuardEventLogConstructor (
|
|
IN EFI_PEI_FILE_HANDLE FileHandle,
|
|
IN CONST EFI_PEI_SERVICES **PeiServices
|
|
)
|
|
{
|
|
DEBUG ((DEBUG_INFO, "PeiBootGuardEventLogConstructorEntry\n"));
|
|
PeiServicesNotifyPpi (&mNotifyList);
|
|
|
|
return EFI_SUCCESS;
|
|
}
|