alder_lake_bios/Intel/AlderLake/AlderLakePlatSamplePkg/Library/PeiBootGuardEventLogLib/PeiBootGuardEventLogLib.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;
}