X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=SecurityPkg%2FTcg%2FTcg2Dxe%2FTcg2Dxe.c;h=aa463b287e79819d1f20cdc9f0d27795b8cbd3c8;hb=83c10d2e8c28e9e556df77216c0aae72094065a9;hp=973e8cb5c7a1a5f25608e0260765e60fa1178d65;hpb=87361c6a54e52a61e85c3605dc57c924e5ae3870;p=mirror_edk2.git diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c index 973e8cb5c7..aa463b287e 100644 --- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c @@ -1,13 +1,14 @@ /** @file This module implements Tcg2 Protocol. - -Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.
-This program and the accompanying materials -are licensed and made available under the terms and conditions of the BSD License -which accompanies this distribution. The full text of the license may be found at + +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+This program and the accompanying materials +are licensed and made available under the terms and conditions of the BSD License +which accompanies this distribution. The full text of the license may be found at http://opensource.org/licenses/bsd-license.php -THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. **/ @@ -30,6 +31,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include @@ -126,6 +128,8 @@ EFI_HANDLE mImageHandle; PE/COFF image is external input, so this function will validate its data structure within this image buffer before use. + Notes: PE/COFF image is checked by BasePeCoffLib PeCoffLoaderGetImageInfo(). + @param[in] PCRIndex TPM PCR index @param[in] ImageAddress Start address of image buffer. @param[in] ImageSize Image size @@ -163,6 +167,82 @@ InternalDumpData ( } } +/** + + This function initialize TCG_PCR_EVENT2_HDR for EV_NO_ACTION Event Type other than EFI Specification ID event + The behavior is defined by TCG PC Client PFP Spec. Section 9.3.4 EV_NO_ACTION Event Types + + @param[in, out] NoActionEvent Event Header of EV_NO_ACTION Event + @param[in] EventSize Event Size of the EV_NO_ACTION Event + +**/ +VOID +InitNoActionEvent ( + IN OUT TCG_PCR_EVENT2_HDR *NoActionEvent, + IN UINT32 EventSize + ) +{ + UINT32 DigestListCount; + TPMI_ALG_HASH HashAlgId; + UINT8 *DigestBuffer; + + DigestBuffer = (UINT8 *)NoActionEvent->Digests.digests; + DigestListCount = 0; + + NoActionEvent->PCRIndex = 0; + NoActionEvent->EventType = EV_NO_ACTION; + + // + // Set Hash count & hashAlg accordingly, while Digest.digests[n].digest to all 0 + // + ZeroMem (&NoActionEvent->Digests, sizeof(NoActionEvent->Digests)); + + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) { + HashAlgId = TPM_ALG_SHA1; + CopyMem (DigestBuffer, &HashAlgId, sizeof(TPMI_ALG_HASH)); + DigestBuffer += sizeof(TPMI_ALG_HASH) + GetHashSizeFromAlgo (HashAlgId); + DigestListCount++; + } + + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) { + HashAlgId = TPM_ALG_SHA256; + CopyMem (DigestBuffer, &HashAlgId, sizeof(TPMI_ALG_HASH)); + DigestBuffer += sizeof(TPMI_ALG_HASH) + GetHashSizeFromAlgo (HashAlgId); + DigestListCount++; + } + + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) { + HashAlgId = TPM_ALG_SHA384; + CopyMem (DigestBuffer, &HashAlgId, sizeof(TPMI_ALG_HASH)); + DigestBuffer += sizeof(TPMI_ALG_HASH) + GetHashSizeFromAlgo (HashAlgId); + DigestListCount++; + } + + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) { + HashAlgId = TPM_ALG_SHA512; + CopyMem (DigestBuffer, &HashAlgId, sizeof(TPMI_ALG_HASH)); + DigestBuffer += sizeof(TPMI_ALG_HASH) + GetHashSizeFromAlgo (HashAlgId); + DigestListCount++; + } + + if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) { + HashAlgId = TPM_ALG_SM3_256; + CopyMem (DigestBuffer, &HashAlgId, sizeof(TPMI_ALG_HASH)); + DigestBuffer += sizeof(TPMI_ALG_HASH) + GetHashSizeFromAlgo (HashAlgId); + DigestListCount++; + } + + // + // Set Digests Count + // + WriteUnaligned32 ((UINT32 *)&NoActionEvent->Digests.count, DigestListCount); + + // + // Set Event Size + // + WriteUnaligned32((UINT32 *)DigestBuffer, EventSize); +} + /** This function dump raw data with colume format. @@ -198,33 +278,6 @@ InternalDumpHex ( } } -/** - 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 -IsZeroBuffer ( - 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 All processors EFI_CPU_LOCATION in system. LocationBuf is allocated inside the function Caller is responsible to free LocationBuf. @@ -319,11 +372,11 @@ GetProcessorsCpuLocation ( @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The command was unsuccessful. - The ProtocolCapability variable will not be populated. + The ProtocolCapability variable will not be populated. @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. The ProtocolCapability variable will not be populated. @retval EFI_BUFFER_TOO_SMALL The ProtocolCapability variable is too small to hold the full response. - It will be partially populated (required Size field will be set). + It will be partially populated (required Size field will be set). **/ EFI_STATUS EFIAPI @@ -332,20 +385,20 @@ Tcg2GetCapability ( IN OUT EFI_TCG2_BOOT_SERVICE_CAPABILITY *ProtocolCapability ) { - DEBUG ((EFI_D_INFO, "Tcg2GetCapability ...\n")); + DEBUG ((DEBUG_VERBOSE, "Tcg2GetCapability ...\n")); if ((This == NULL) || (ProtocolCapability == NULL)) { return EFI_INVALID_PARAMETER; } - - DEBUG ((EFI_D_INFO, "Size - 0x%x\n", ProtocolCapability->Size)); - DEBUG ((EFI_D_INFO, " 1.1 - 0x%x, 1.0 - 0x%x\n", sizeof(EFI_TCG2_BOOT_SERVICE_CAPABILITY), sizeof(TREE_BOOT_SERVICE_CAPABILITY_1_0))); + + DEBUG ((DEBUG_VERBOSE, "Size - 0x%x\n", ProtocolCapability->Size)); + DEBUG ((DEBUG_VERBOSE, " 1.1 - 0x%x, 1.0 - 0x%x\n", sizeof(EFI_TCG2_BOOT_SERVICE_CAPABILITY), sizeof(TREE_BOOT_SERVICE_CAPABILITY_1_0))); if (ProtocolCapability->Size < mTcgDxeData.BsCap.Size) { // // Handle the case that firmware support 1.1 but OS only support 1.0. // - if ((mTcgDxeData.BsCap.ProtocolVersion.Major > 0x01) || + if ((mTcgDxeData.BsCap.ProtocolVersion.Major > 0x01) || ((mTcgDxeData.BsCap.ProtocolVersion.Major == 0x01) && ((mTcgDxeData.BsCap.ProtocolVersion.Minor > 0x00)))) { if (ProtocolCapability->Size >= sizeof(TREE_BOOT_SERVICE_CAPABILITY_1_0)) { CopyMem (ProtocolCapability, &mTcgDxeData.BsCap, sizeof(TREE_BOOT_SERVICE_CAPABILITY_1_0)); @@ -363,7 +416,7 @@ Tcg2GetCapability ( } CopyMem (ProtocolCapability, &mTcgDxeData.BsCap, mTcgDxeData.BsCap.Size); - DEBUG ((EFI_D_INFO, "Tcg2GetCapability - %r\n", EFI_SUCCESS)); + DEBUG ((DEBUG_VERBOSE, "Tcg2GetCapability - %r\n", EFI_SUCCESS)); return EFI_SUCCESS; } @@ -510,7 +563,7 @@ DumpEvent2 ( /** This function returns size of TCG PCR event 2. - + @param[in] TcgPcrEvent2 TCG PCR event 2 structure. @return size of TCG PCR event 2. @@ -570,7 +623,7 @@ DumpEventLog ( UINTN NumberOfEvents; DEBUG ((EFI_D_INFO, "EventLogFormat: (0x%x)\n", EventLogFormat)); - + switch (EventLogFormat) { case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2: EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation; @@ -594,7 +647,7 @@ DumpEventLog ( break; case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2: // - // Dump first event + // Dump first event // EventHdr = (TCG_PCR_EVENT_HDR *)(UINTN)EventLogLocation; DumpEvent (EventHdr); @@ -629,7 +682,7 @@ DumpEventLog ( /** The EFI_TCG2_PROTOCOL Get Event Log function call allows a caller to - retrieve the address of a given event log and its last entry. + retrieve the address of a given event log and its last entry. @param[in] This Indicates the calling context @param[in] EventLogFormat The type of the event log for which the information is requested. @@ -727,14 +780,14 @@ Tcg2GetEventLog ( /** Add a new entry to the Event Log. - @param[in, out] EventLogPtr Pointer to the Event Log data. - @param[in, out] LogSize Size of the Event Log. + @param[in, out] EventLogPtr Pointer to the Event Log data. + @param[in, out] LogSize Size of the Event Log. @param[in] MaxSize Maximum size of the Event Log. - @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. + @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. @param[in] NewEventHdrSize New event header size. - @param[in] NewEventData Pointer to the new event data. + @param[in] NewEventData Pointer to the new event data. @param[in] NewEventSize New event data size. - + @retval EFI_SUCCESS The new event log entry was added. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. @@ -785,9 +838,9 @@ TcgCommLogEvent ( Add a new entry to the Event Log. @param[in] EventLogFormat The type of the event log for which the information is requested. - @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. + @param[in] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR/TCG_PCR_EVENT_EX data structure. @param[in] NewEventHdrSize New event header size. - @param[in] NewEventData Pointer to the new event data. + @param[in] NewEventData Pointer to the new event data. @param[in] NewEventSize New event data size. @retval EFI_SUCCESS The new event log entry was added. @@ -806,7 +859,7 @@ TcgDxeLogEvent ( EFI_STATUS Status; UINTN Index; TCG_EVENT_LOG_AREA_STRUCT *EventLogAreaStruct; - + for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { if (EventLogFormat == mTcg2EventInfo[Index].LogFormat) { break; @@ -817,11 +870,10 @@ TcgDxeLogEvent ( return EFI_INVALID_PARAMETER; } - if (!mTcgDxeData.GetEventLogCalled[Index]) { - EventLogAreaStruct = &mTcgDxeData.EventLogAreaStruct[Index]; - } else { - EventLogAreaStruct = &mTcgDxeData.FinalEventLogAreaStruct[Index]; - } + // + // Record to normal event log + // + EventLogAreaStruct = &mTcgDxeData.EventLogAreaStruct[Index]; if (EventLogAreaStruct->EventLogTruncated) { return EFI_VOLUME_FULL; @@ -837,80 +889,55 @@ TcgDxeLogEvent ( NewEventData, NewEventSize ); - - if (Status == EFI_DEVICE_ERROR) { - return EFI_DEVICE_ERROR; - } else if (Status == EFI_OUT_OF_RESOURCES) { + + if (Status == EFI_OUT_OF_RESOURCES) { EventLogAreaStruct->EventLogTruncated = TRUE; return EFI_VOLUME_FULL; } else if (Status == EFI_SUCCESS) { EventLogAreaStruct->EventLogStarted = TRUE; - if (mTcgDxeData.GetEventLogCalled[Index]) { - (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents ++; - } } - return Status; -} - -/** - This function get digest from digest list. - - @param HashAlg digest algorithm - @param DigestList digest list - @param 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 - ); + // + // If GetEventLog is called, record to FinalEventsTable, too. + // + if (mTcgDxeData.GetEventLogCalled[Index]) { + if (mTcgDxeData.FinalEventsTable[Index] == NULL) { + // + // no need for FinalEventsTable + // return EFI_SUCCESS; } - } - - return EFI_NOT_FOUND; -} - -/** - Get TPML_DIGEST_VALUES data size. - - @param[in] DigestList TPML_DIGEST_VALUES data. + EventLogAreaStruct = &mTcgDxeData.FinalEventLogAreaStruct[Index]; - @return TPML_DIGEST_VALUES data size. -**/ -UINT32 -GetDigestListSize ( - IN TPML_DIGEST_VALUES *DigestList - ) -{ - UINTN Index; - UINT16 DigestSize; - UINT32 TotalSize; + if (EventLogAreaStruct->EventLogTruncated) { + return EFI_VOLUME_FULL; + } - TotalSize = sizeof(DigestList->count); - for (Index = 0; Index < DigestList->count; Index++) { - DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg); - TotalSize += sizeof(DigestList->digests[Index].hashAlg) + DigestSize; + EventLogAreaStruct->LastEvent = (UINT8*)(UINTN)EventLogAreaStruct->Lasa; + Status = TcgCommLogEvent ( + &EventLogAreaStruct->LastEvent, + &EventLogAreaStruct->EventLogSize, + (UINTN)EventLogAreaStruct->Laml, + NewEventHdr, + NewEventHdrSize, + NewEventData, + NewEventSize + ); + if (Status == EFI_OUT_OF_RESOURCES) { + EventLogAreaStruct->EventLogTruncated = TRUE; + return EFI_VOLUME_FULL; + } else if (Status == EFI_SUCCESS) { + EventLogAreaStruct->EventLogStarted = TRUE; + // + // Increase the NumberOfEvents in FinalEventsTable + // + (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents ++; + DEBUG ((EFI_D_INFO, "FinalEventsTable->NumberOfEvents - 0x%x\n", (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents)); + DEBUG ((EFI_D_INFO, " Size - 0x%x\n", (UINTN)EventLogAreaStruct->EventLogSize)); + } } - return TotalSize; + return Status; } /** @@ -948,79 +975,55 @@ GetDigestListBinSize ( } /** - Return if hash alg is supported in TPM PCR bank. + Copy TPML_DIGEST_VALUES compact binary into a buffer - @param HashAlg Hash algorithm to be checked. + @param[in,out] Buffer Buffer to hold copied TPML_DIGEST_VALUES compact binary. + @param[in] DigestListBin TPML_DIGEST_VALUES compact binary buffer. + @param[in] HashAlgorithmMask HASH bits corresponding to the desired digests to copy. + @param[out] HashAlgorithmMaskCopied Pointer to HASH bits corresponding to the digests copied. - @retval TRUE Hash algorithm is supported. - @retval FALSE Hash algorithm is not supported. + @return The end of buffer to hold TPML_DIGEST_VALUES compact binary. **/ -BOOLEAN -IsHashAlgSupportedInPcrBank ( - IN TPMI_ALG_HASH HashAlg +VOID * +CopyDigestListBinToBuffer ( + IN OUT VOID *Buffer, + IN VOID *DigestListBin, + IN UINT32 HashAlgorithmMask, + OUT UINT32 *HashAlgorithmMaskCopied ) { - switch (HashAlg) { - case TPM_ALG_SHA1: - if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA1) != 0) { - return TRUE; - } - break; - case TPM_ALG_SHA256: - if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA256) != 0) { - return TRUE; - } - break; - case TPM_ALG_SHA384: - if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA384) != 0) { - return TRUE; - } - break; - case TPM_ALG_SHA512: - if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SHA512) != 0) { - return TRUE; - } - break; - case TPM_ALG_SM3_256: - if ((mTcgDxeData.BsCap.ActivePcrBanks & EFI_TCG2_BOOT_HASH_ALG_SM3_256) != 0) { - return TRUE; - } - break; - } - - return FALSE; -} + UINTN Index; + UINT16 DigestSize; + UINT32 Count; + TPMI_ALG_HASH HashAlg; + UINT32 DigestListCount; + UINT32 *DigestListCountPtr; -/** - Copy TPML_DIGEST_VALUES into a buffer + DigestListCountPtr = (UINT32 *) Buffer; + DigestListCount = 0; + (*HashAlgorithmMaskCopied) = 0; - @param[in,out] Buffer Buffer to hold TPML_DIGEST_VALUES. - @param[in] DigestList TPML_DIGEST_VALUES to be copied. + Count = ReadUnaligned32 (DigestListBin); + Buffer = (UINT8 *)Buffer + sizeof(Count); + DigestListBin = (UINT8 *)DigestListBin + sizeof(Count); + for (Index = 0; Index < Count; Index++) { + HashAlg = ReadUnaligned16 (DigestListBin); + DigestListBin = (UINT8 *)DigestListBin + sizeof(HashAlg); + DigestSize = GetHashSizeFromAlgo (HashAlg); - @return The end of buffer to hold TPML_DIGEST_VALUES. -**/ -VOID * -CopyDigestListToBuffer ( - IN OUT VOID *Buffer, - IN TPML_DIGEST_VALUES *DigestList - ) -{ - UINTN Index; - UINT16 DigestSize; - - CopyMem (Buffer, &DigestList->count, sizeof(DigestList->count)); - Buffer = (UINT8 *)Buffer + sizeof(DigestList->count); - for (Index = 0; Index < DigestList->count; Index++) { - if (!IsHashAlgSupportedInPcrBank (DigestList->digests[Index].hashAlg)) { - DEBUG ((EFI_D_ERROR, "WARNING: TPM2 Event log has HashAlg unsupported by PCR bank (0x%x)\n", DigestList->digests[Index].hashAlg)); - continue; + if (IsHashAlgSupportedInHashAlgorithmMask(HashAlg, HashAlgorithmMask)) { + CopyMem (Buffer, &HashAlg, sizeof(HashAlg)); + Buffer = (UINT8 *)Buffer + sizeof(HashAlg); + CopyMem (Buffer, DigestListBin, DigestSize); + Buffer = (UINT8 *)Buffer + DigestSize; + DigestListCount++; + (*HashAlgorithmMaskCopied) |= GetHashMaskFromAlgo (HashAlg); + } else { + DEBUG ((DEBUG_ERROR, "WARNING: CopyDigestListBinToBuffer Event log has HashAlg unsupported by PCR bank (0x%x)\n", HashAlg)); } - CopyMem (Buffer, &DigestList->digests[Index].hashAlg, sizeof(DigestList->digests[Index].hashAlg)); - Buffer = (UINT8 *)Buffer + sizeof(DigestList->digests[Index].hashAlg); - DigestSize = GetHashSizeFromAlgo (DigestList->digests[Index].hashAlg); - CopyMem (Buffer, &DigestList->digests[Index].digest, DigestSize); - Buffer = (UINT8 *)Buffer + DigestSize; + DigestListBin = (UINT8 *)DigestListBin + DigestSize; } + WriteUnaligned32 (DigestListCountPtr, DigestListCount); return Buffer; } @@ -1048,6 +1051,7 @@ TcgDxeLogHashEvent ( EFI_STATUS RetStatus; TCG_PCR_EVENT2 TcgPcrEvent2; UINT8 *DigestBuffer; + UINT32 *EventSizePtr; DEBUG ((EFI_D_INFO, "SupportedEventLogs - 0x%08x\n", mTcgDxeData.BsCap.SupportedEventLogs)); @@ -1057,7 +1061,7 @@ TcgDxeLogHashEvent ( DEBUG ((EFI_D_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); + Status = GetDigestFromDigestList (TPM_ALG_SHA1, DigestList, &NewEventHdr->Digest); if (!EFI_ERROR (Status)) { // // Enter critical region @@ -1084,9 +1088,8 @@ TcgDxeLogHashEvent ( TcgPcrEvent2.PCRIndex = NewEventHdr->PCRIndex; TcgPcrEvent2.EventType = NewEventHdr->EventType; DigestBuffer = (UINT8 *)&TcgPcrEvent2.Digest; - DigestBuffer = CopyDigestListToBuffer (DigestBuffer, DigestList); - CopyMem (DigestBuffer, &NewEventHdr->EventSize, sizeof(NewEventHdr->EventSize)); - DigestBuffer = DigestBuffer + sizeof(NewEventHdr->EventSize); + EventSizePtr = CopyDigestListToBuffer (DigestBuffer, DigestList, mTcgDxeData.BsCap.ActivePcrBanks); + CopyMem (EventSizePtr, &NewEventHdr->EventSize, sizeof(NewEventHdr->EventSize)); // // Enter critical region @@ -1095,7 +1098,7 @@ TcgDxeLogHashEvent ( Status = TcgDxeLogEvent ( mTcg2EventInfo[Index].LogFormat, &TcgPcrEvent2, - sizeof(TcgPcrEvent2.PCRIndex) + sizeof(TcgPcrEvent2.EventType) + GetDigestListSize (DigestList) + sizeof(TcgPcrEvent2.EventSize), + sizeof(TcgPcrEvent2.PCRIndex) + sizeof(TcgPcrEvent2.EventType) + GetDigestListBinSize (DigestBuffer) + sizeof(TcgPcrEvent2.EventSize), NewEventData, NewEventHdr->EventSize ); @@ -1119,11 +1122,11 @@ TcgDxeLogHashEvent ( and add an entry to the Event Log. @param[in] Flags Bitmap providing additional information. - @param[in] HashData Physical address of the start of the data buffer + @param[in] HashData Physical address of the start of the data buffer to be hashed, extended, and logged. @param[in] HashDataLen The length, in bytes, of the buffer referenced by HashData - @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. - @param[in] NewEventData Pointer to the new event data. + @param[in, out] NewEventHdr Pointer to a TCG_PCR_EVENT_HDR data structure. + @param[in] NewEventData Pointer to the new event data. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_OUT_OF_RESOURCES No enough memory to log the new event. @@ -1173,13 +1176,13 @@ TcgDxeHashLogExtendEvent ( /** The EFI_TCG2_PROTOCOL HashLogExtendEvent function call provides callers with an opportunity to extend and optionally log events without requiring - knowledge of actual TPM commands. + knowledge of actual TPM commands. The extend operation will occur even if this function cannot create an event - log entry (e.g. due to the event log being full). + log entry (e.g. due to the event log being full). @param[in] This Indicates the calling context @param[in] Flags Bitmap providing additional information. - @param[in] DataToHash Physical address of the start of the data buffer to be hashed. + @param[in] DataToHash Physical address of the start of the data buffer to be hashed. @param[in] DataToHashLen The length in bytes of the buffer referenced by DataToHash. @param[in] Event Pointer to data buffer containing information about the event. @@ -1203,7 +1206,7 @@ Tcg2HashLogExtendEvent ( TCG_PCR_EVENT_HDR NewEventHdr; TPML_DIGEST_VALUES DigestList; - DEBUG ((EFI_D_INFO, "Tcg2HashLogExtendEvent ...\n")); + DEBUG ((DEBUG_VERBOSE, "Tcg2HashLogExtendEvent ...\n")); if ((This == NULL) || (DataToHash == 0) || (Event == NULL)) { return EFI_INVALID_PARAMETER; @@ -1253,7 +1256,7 @@ Tcg2HashLogExtendEvent ( Event->Event ); } - DEBUG ((EFI_D_INFO, "Tcg2HashLogExtendEvent - %r\n", Status)); + DEBUG ((DEBUG_VERBOSE, "Tcg2HashLogExtendEvent - %r\n", Status)); return Status; } @@ -1269,7 +1272,7 @@ Tcg2HashLogExtendEvent ( @retval EFI_SUCCESS The command byte stream was successfully sent to the device and a response was successfully received. @retval EFI_DEVICE_ERROR The command was not successfully sent to the device or a response was not successfully received from the device. @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. - @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. + @retval EFI_BUFFER_TOO_SMALL The output parameter block is too small. **/ EFI_STATUS EFIAPI @@ -1295,10 +1298,10 @@ Tcg2SubmitCommand ( return EFI_DEVICE_ERROR; } - if (InputParameterBlockSize >= mTcgDxeData.BsCap.MaxCommandSize) { + if (InputParameterBlockSize > mTcgDxeData.BsCap.MaxCommandSize) { return EFI_INVALID_PARAMETER; } - if (OutputParameterBlockSize >= mTcgDxeData.BsCap.MaxResponseSize) { + if (OutputParameterBlockSize > mTcgDxeData.BsCap.MaxResponseSize) { return EFI_INVALID_PARAMETER; } @@ -1319,7 +1322,7 @@ Tcg2SubmitCommand ( @param[out] ActivePcrBanks Pointer to the variable receiving the bitmap of currently active PCR banks. @retval EFI_SUCCESS The bitmap of active PCR banks was stored in the ActivePcrBanks parameter. - @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. + @retval EFI_INVALID_PARAMETER One or more of the parameters are incorrect. **/ EFI_STATUS EFIAPI @@ -1409,7 +1412,7 @@ Tcg2GetResultOfSetActivePcrBanks ( if ((OperationPresent == NULL) || (Response == NULL)) { return EFI_INVALID_PARAMETER; } - + ReturnCode = Tcg2PhysicalPresenceLibReturnOperationResponseToOsFunction (OperationPresent, Response); if (ReturnCode == TCG_PP_RETURN_TPM_OPERATION_RESPONSE_SUCCESS) { return EFI_SUCCESS; @@ -1445,15 +1448,22 @@ SetupEventLog ( EFI_PEI_HOB_POINTERS GuidHob; EFI_PHYSICAL_ADDRESS Lasa; UINTN Index; + VOID *DigestListBin; + TPML_DIGEST_VALUES TempDigestListBin; UINT32 DigestListBinSize; + UINT8 *Event; UINT32 EventSize; + UINT32 *EventSizePtr; + UINT32 HashAlgorithmMaskCopied; TCG_EfiSpecIDEventStruct *TcgEfiSpecIdEventStruct; - UINT8 TempBuf[sizeof(TCG_EfiSpecIDEventStruct) + (HASH_COUNT * sizeof(TCG_EfiSpecIdEventAlgorithmSize)) + sizeof(UINT8)]; - TCG_PCR_EVENT_HDR FirstPcrEvent; + UINT8 TempBuf[sizeof(TCG_EfiSpecIDEventStruct) + sizeof(UINT32) + (HASH_COUNT * sizeof(TCG_EfiSpecIdEventAlgorithmSize)) + sizeof(UINT8)]; + TCG_PCR_EVENT_HDR SpecIdEvent; + TCG_PCR_EVENT2_HDR NoActionEvent; TCG_EfiSpecIdEventAlgorithmSize *DigestSize; TCG_EfiSpecIdEventAlgorithmSize *TempDigestSize; UINT8 *VendorInfoSize; UINT32 NumberOfAlgorithms; + TCG_EfiStartupLocalityEvent StartupLocalityEvent; DEBUG ((EFI_D_INFO, "SetupEventLog\n")); @@ -1463,10 +1473,9 @@ SetupEventLog ( for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { if ((mTcgDxeData.BsCap.SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { mTcgDxeData.EventLogAreaStruct[Index].EventLogFormat = mTcg2EventInfo[Index].LogFormat; - Lasa = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1); Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, + AllocateAnyPages, + EfiBootServicesData, EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcgLogAreaMinLen)), &Lasa ); @@ -1476,7 +1485,7 @@ SetupEventLog ( mTcgDxeData.EventLogAreaStruct[Index].Lasa = Lasa; mTcgDxeData.EventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcgLogAreaMinLen); // - // To initialize them as 0xFF is recommended + // To initialize them as 0xFF is recommended // because the OS can know the last entry for that. // SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcgLogAreaMinLen), 0xFF); @@ -1537,24 +1546,54 @@ SetupEventLog ( VendorInfoSize = (UINT8 *)TempDigestSize; *VendorInfoSize = 0; - // - // FirstPcrEvent - // - FirstPcrEvent.PCRIndex = 0; - FirstPcrEvent.EventType = EV_NO_ACTION; - ZeroMem (&FirstPcrEvent.Digest, sizeof(FirstPcrEvent.Digest)); - FirstPcrEvent.EventSize = (UINT32)GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct); + SpecIdEvent.PCRIndex = 0; + SpecIdEvent.EventType = EV_NO_ACTION; + ZeroMem (&SpecIdEvent.Digest, sizeof(SpecIdEvent.Digest)); + SpecIdEvent.EventSize = (UINT32)GetTcgEfiSpecIdEventStructSize (TcgEfiSpecIdEventStruct); // - // Record + // Log TcgEfiSpecIdEventStruct as the first Event. Event format is TCG_PCR_EVENT. + // TCG EFI Protocol Spec. Section 5.3 Event Log Header + // TCG PC Client PFP spec. Section 9.2 Measurement Event Entries and Log // Status = TcgDxeLogEvent ( mTcg2EventInfo[Index].LogFormat, - &FirstPcrEvent, - sizeof(FirstPcrEvent), + &SpecIdEvent, + sizeof(SpecIdEvent), (UINT8 *)TcgEfiSpecIdEventStruct, - FirstPcrEvent.EventSize + SpecIdEvent.EventSize ); + + // + // EfiStartupLocalityEvent. Event format is TCG_PCR_EVENT2 + // + GuidHob.Guid = GetFirstGuidHob (&gTpm2StartupLocalityHobGuid); + if (GuidHob.Guid != NULL) { + // + // Get Locality Indicator from StartupLocality HOB + // + StartupLocalityEvent.StartupLocality = *(UINT8 *)(GET_GUID_HOB_DATA (GuidHob.Guid)); + CopyMem (StartupLocalityEvent.Signature, TCG_EfiStartupLocalityEvent_SIGNATURE, sizeof(StartupLocalityEvent.Signature)); + DEBUG ((DEBUG_INFO, "SetupEventLog: Set Locality from HOB into StartupLocalityEvent 0x%02x\n", StartupLocalityEvent.StartupLocality)); + + // + // Initialize StartupLocalityEvent + // + InitNoActionEvent(&NoActionEvent, sizeof(StartupLocalityEvent)); + + // + // Log EfiStartupLocalityEvent as the second Event + // TCG PC Client PFP spec. Section 9.3.4.3 Startup Locality Event + // + Status = TcgDxeLogEvent ( + mTcg2EventInfo[Index].LogFormat, + &NoActionEvent, + sizeof(NoActionEvent.PCRIndex) + sizeof(NoActionEvent.EventType) + GetDigestListBinSize (&NoActionEvent.Digests) + sizeof(NoActionEvent.EventSize), + (UINT8 *)&StartupLocalityEvent, + sizeof(StartupLocalityEvent) + ); + + } } } } @@ -1564,45 +1603,56 @@ SetupEventLog ( // for (Index = 0; Index < sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0]); Index++) { if ((mTcgDxeData.BsCap.SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { - Lasa = (EFI_PHYSICAL_ADDRESS) (SIZE_4GB - 1); - Status = gBS->AllocatePages ( - AllocateMaxAddress, - EfiACPIMemoryNVS, - EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcg2FinalLogAreaLen)), - &Lasa - ); - if (EFI_ERROR (Status)) { - return Status; - } - SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcg2FinalLogAreaLen), 0xFF); + if (mTcg2EventInfo[Index].LogFormat == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) { + Status = gBS->AllocatePages ( + AllocateAnyPages, + EfiACPIMemoryNVS, + EFI_SIZE_TO_PAGES (PcdGet32 (PcdTcg2FinalLogAreaLen)), + &Lasa + ); + if (EFI_ERROR (Status)) { + return Status; + } + SetMem ((VOID *)(UINTN)Lasa, PcdGet32 (PcdTcg2FinalLogAreaLen), 0xFF); - // - // Initialize - // - mTcgDxeData.FinalEventsTable[Index] = (VOID *)(UINTN)Lasa; - (mTcgDxeData.FinalEventsTable[Index])->Version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION; - (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents = 0; - - mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogFormat = mTcg2EventInfo[Index].LogFormat; - mTcgDxeData.FinalEventLogAreaStruct[Index].Lasa = Lasa + sizeof(EFI_TCG2_FINAL_EVENTS_TABLE); - mTcgDxeData.FinalEventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcg2FinalLogAreaLen) - sizeof(EFI_TCG2_FINAL_EVENTS_TABLE); - mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogSize = 0; - mTcgDxeData.FinalEventLogAreaStruct[Index].LastEvent = (VOID *)(UINTN)mTcgDxeData.FinalEventLogAreaStruct[Index].Lasa; - mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogStarted = FALSE; - mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogTruncated = FALSE; + // + // Initialize + // + mTcgDxeData.FinalEventsTable[Index] = (VOID *)(UINTN)Lasa; + (mTcgDxeData.FinalEventsTable[Index])->Version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION; + (mTcgDxeData.FinalEventsTable[Index])->NumberOfEvents = 0; + + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogFormat = mTcg2EventInfo[Index].LogFormat; + mTcgDxeData.FinalEventLogAreaStruct[Index].Lasa = Lasa + sizeof(EFI_TCG2_FINAL_EVENTS_TABLE); + mTcgDxeData.FinalEventLogAreaStruct[Index].Laml = PcdGet32 (PcdTcg2FinalLogAreaLen) - sizeof(EFI_TCG2_FINAL_EVENTS_TABLE); + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogSize = 0; + mTcgDxeData.FinalEventLogAreaStruct[Index].LastEvent = (VOID *)(UINTN)mTcgDxeData.FinalEventLogAreaStruct[Index].Lasa; + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogStarted = FALSE; + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogTruncated = FALSE; - if (mTcg2EventInfo[Index].LogFormat == EFI_TCG2_EVENT_LOG_FORMAT_TCG_2) { // - // Install to configuration table + // Install to configuration table for EFI_TCG2_EVENT_LOG_FORMAT_TCG_2 // - Status = gBS->InstallConfigurationTable (&gEfiTcg2FinalEventsTableGuid, (VOID *)mTcgDxeData.FinalEventsTable[1]); + Status = gBS->InstallConfigurationTable (&gEfiTcg2FinalEventsTableGuid, (VOID *)mTcgDxeData.FinalEventsTable[Index]); if (EFI_ERROR (Status)) { return Status; } + } else { + // + // No need to handle EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2 + // + mTcgDxeData.FinalEventsTable[Index] = NULL; + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogFormat = mTcg2EventInfo[Index].LogFormat; + mTcgDxeData.FinalEventLogAreaStruct[Index].Lasa = 0; + mTcgDxeData.FinalEventLogAreaStruct[Index].Laml = 0; + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogSize = 0; + mTcgDxeData.FinalEventLogAreaStruct[Index].LastEvent = 0; + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogStarted = FALSE; + mTcgDxeData.FinalEventLogAreaStruct[Index].EventLogTruncated = FALSE; } } } - + // // 3. Sync data from PEI to DXE // @@ -1611,9 +1661,10 @@ SetupEventLog ( if ((mTcgDxeData.BsCap.SupportedEventLogs & mTcg2EventInfo[Index].LogFormat) != 0) { GuidHob.Raw = GetHobList (); Status = EFI_SUCCESS; - while (!EFI_ERROR (Status) && + while (!EFI_ERROR (Status) && (GuidHob.Raw = GetNextGuidHob (mTcg2EventInfo[Index].EventGuid, GuidHob.Raw)) != NULL) { - TcgEvent = GET_GUID_HOB_DATA (GuidHob.Guid); + TcgEvent = AllocateCopyPool (GET_GUID_HOB_DATA_SIZE (GuidHob.Guid), GET_GUID_HOB_DATA (GuidHob.Guid)); + ASSERT (TcgEvent != NULL); GuidHob.Raw = GET_NEXT_HOB (GuidHob); switch (mTcg2EventInfo[Index].LogFormat) { case EFI_TCG2_EVENT_LOG_FORMAT_TCG_1_2: @@ -1626,17 +1677,47 @@ SetupEventLog ( ); break; case EFI_TCG2_EVENT_LOG_FORMAT_TCG_2: - DigestListBinSize = GetDigestListBinSize ((UINT8 *)TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE)); - CopyMem (&EventSize, (UINT8 *)TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE) + DigestListBinSize, sizeof(UINT32)); + DigestListBin = (UINT8 *)TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE); + DigestListBinSize = GetDigestListBinSize (DigestListBin); + // + // Save event size. + // + CopyMem (&EventSize, (UINT8 *)DigestListBin + DigestListBinSize, sizeof(UINT32)); + Event = (UINT8 *)DigestListBin + DigestListBinSize + sizeof(UINT32); + // + // Filter inactive digest in the event2 log from PEI HOB. + // + CopyMem (&TempDigestListBin, DigestListBin, GetDigestListBinSize (DigestListBin)); + EventSizePtr = CopyDigestListBinToBuffer ( + DigestListBin, + &TempDigestListBin, + mTcgDxeData.BsCap.ActivePcrBanks, + &HashAlgorithmMaskCopied + ); + if (HashAlgorithmMaskCopied != mTcgDxeData.BsCap.ActivePcrBanks) { + DEBUG (( + DEBUG_ERROR, + "ERROR: The event2 log includes digest hash mask 0x%x, but required digest hash mask is 0x%x\n", + HashAlgorithmMaskCopied, + mTcgDxeData.BsCap.ActivePcrBanks + )); + } + // + // Restore event size. + // + CopyMem (EventSizePtr, &EventSize, sizeof(UINT32)); + DigestListBinSize = GetDigestListBinSize (DigestListBin); + Status = TcgDxeLogEvent ( mTcg2EventInfo[Index].LogFormat, TcgEvent, sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE) + DigestListBinSize + sizeof(UINT32), - (UINT8 *)TcgEvent + sizeof(TCG_PCRINDEX) + sizeof(TCG_EVENTTYPE) + DigestListBinSize + sizeof(UINT32), + Event, EventSize ); break; } + FreePool (TcgEvent); } } } @@ -1645,22 +1726,24 @@ SetupEventLog ( } /** - Measure and log an action string, and extend the measurement result into PCR[5]. + Measure and log an action string, and extend the measurement result into PCR[PCRIndex]. + + @param[in] PCRIndex PCRIndex to extend + @param[in] String A specific string that indicates an Action event. - @param[in] String A specific string that indicates an Action event. - @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The operation was unsuccessful. **/ EFI_STATUS TcgMeasureAction ( - IN CHAR8 *String + IN TPM_PCRINDEX PCRIndex, + IN CHAR8 *String ) { TCG_PCR_EVENT_HDR TcgEvent; - TcgEvent.PCRIndex = 5; + TcgEvent.PCRIndex = PCRIndex; TcgEvent.EventType = EV_EFI_ACTION; TcgEvent.EventSize = (UINT32)AsciiStrLen (String); return TcgDxeHashLogExtendEvent ( @@ -1695,7 +1778,7 @@ MeasureHandoffTables ( if (PcdGet8 (PcdTpmPlatformClass) == TCG_PLATFORM_TYPE_SERVER) { // - // Tcg Server spec. + // Tcg Server spec. // Measure each processor EFI_CPU_PHYSICAL_LOCATION with EV_TABLE_OF_DEVICES to PCR[1] // Status = GetProcessorsCpuLocation(&ProcessorLocBuf, &ProcessorNum); @@ -1727,7 +1810,7 @@ MeasureHandoffTables ( /** Measure and log Separator event, and extend the measurement result into a specific PCR. - @param[in] PCRIndex PCR index. + @param[in] PCRIndex PCR index. @retval EFI_SUCCESS Operation completed successfully. @retval EFI_DEVICE_ERROR The operation was unsuccessful. @@ -1759,13 +1842,13 @@ MeasureSeparatorEvent ( /** Measure and log an EFI variable, and extend the measurement result into a specific PCR. - @param[in] PCRIndex PCR Index. - @param[in] EventType Event type. + @param[in] PCRIndex PCR Index. + @param[in] EventType Event type. @param[in] VarName A Null-terminated string that is the name of the vendor's variable. @param[in] VendorGuid A unique identifier for the vendor. - @param[in] VarData The content of the variable data. - @param[in] VarSize The size of the variable data. - + @param[in] VarData The content of the variable data. + @param[in] VarSize The size of the variable data. + @retval EFI_SUCCESS Operation completed successfully. @retval EFI_OUT_OF_RESOURCES Out of memory. @retval EFI_DEVICE_ERROR The operation was unsuccessful. @@ -1784,7 +1867,7 @@ MeasureVariable ( EFI_STATUS Status; TCG_PCR_EVENT_HDR TcgEvent; UINTN VarNameLength; - EFI_VARIABLE_DATA_TREE *VarLog; + UEFI_VARIABLE_DATA *VarLog; DEBUG ((EFI_D_INFO, "Tcg2Dxe: MeasureVariable (Pcr - %x, EventType - %x, ", (UINTN)PCRIndex, (UINTN)EventType)); DEBUG ((EFI_D_INFO, "VariableName - %s, VendorGuid - %g)\n", VarName, VendorGuid)); @@ -1796,7 +1879,7 @@ MeasureVariable ( TcgEvent.EventSize = (UINT32)(sizeof (*VarLog) + VarNameLength * sizeof (*VarName) + VarSize - sizeof (VarLog->UnicodeName) - sizeof (VarLog->VariableData)); - VarLog = (EFI_VARIABLE_DATA_TREE *)AllocatePool (TcgEvent.EventSize); + VarLog = (UEFI_VARIABLE_DATA *)AllocatePool (TcgEvent.EventSize); if (VarLog == NULL) { return EFI_OUT_OF_RESOURCES; } @@ -1819,7 +1902,7 @@ MeasureVariable ( if (EventType == EV_EFI_VARIABLE_DRIVER_CONFIG) { // - // Digest is the event data (EFI_VARIABLE_DATA) + // Digest is the event data (UEFI_VARIABLE_DATA) // Status = TcgDxeHashLogExtendEvent ( 0, @@ -1829,6 +1912,7 @@ MeasureVariable ( (UINT8*)VarLog ); } else { + ASSERT (VarData != NULL); Status = TcgDxeHashLogExtendEvent ( 0, (UINT8*)VarData, @@ -1844,13 +1928,13 @@ MeasureVariable ( /** Read then Measure and log an EFI variable, and extend the measurement result into a specific PCR. - @param[in] PCRIndex PCR Index. - @param[in] EventType Event type. + @param[in] PCRIndex PCR Index. + @param[in] EventType Event type. @param[in] VarName A Null-terminated string that is the name of the vendor's variable. @param[in] VendorGuid A unique identifier for the vendor. - @param[out] VarSize The size of the variable data. - @param[out] VarData Pointer to the content of the variable. - + @param[out] VarSize The size of the variable data. + @param[out] VarData Pointer to the content of the variable. + @retval EFI_SUCCESS Operation completed successfully. @retval EFI_OUT_OF_RESOURCES Out of memory. @retval EFI_DEVICE_ERROR The operation was unsuccessful. @@ -1898,13 +1982,14 @@ ReadAndMeasureVariable ( } /** - Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[5]. + Read then Measure and log an EFI boot variable, and extend the measurement result into PCR[1]. +according to TCG PC Client PFP spec 0021 Section 2.4.4.2 @param[in] VarName A Null-terminated string that is the name of the vendor's variable. @param[in] VendorGuid A unique identifier for the vendor. - @param[out] VarSize The size of the variable data. - @param[out] VarData Pointer to the content of the variable. - + @param[out] VarSize The size of the variable data. + @param[out] VarData Pointer to the content of the variable. + @retval EFI_SUCCESS Operation completed successfully. @retval EFI_OUT_OF_RESOURCES Out of memory. @retval EFI_DEVICE_ERROR The operation was unsuccessful. @@ -1919,7 +2004,7 @@ ReadAndMeasureBootVariable ( ) { return ReadAndMeasureVariable ( - 5, + 1, EV_EFI_VARIABLE_BOOT, VarName, VendorGuid, @@ -1933,9 +2018,9 @@ ReadAndMeasureBootVariable ( @param[in] VarName A Null-terminated string that is the name of the vendor's variable. @param[in] VendorGuid A unique identifier for the vendor. - @param[out] VarSize The size of the variable data. - @param[out] VarData Pointer to the content of the variable. - + @param[out] VarSize The size of the variable data. + @param[out] VarData Pointer to the content of the variable. + @retval EFI_SUCCESS Operation completed successfully. @retval EFI_OUT_OF_RESOURCES Out of memory. @retval EFI_DEVICE_ERROR The operation was unsuccessful. @@ -2052,6 +2137,24 @@ MeasureAllSecureVariables ( } } + // + // Measure DBT if present and not empty + // + Status = GetVariable2 (EFI_IMAGE_SECURITY_DATABASE2, &gEfiImageSecurityDatabaseGuid, &Data, &DataSize); + if (!EFI_ERROR(Status)) { + Status = MeasureVariable ( + 7, + EV_EFI_VARIABLE_DRIVER_CONFIG, + EFI_IMAGE_SECURITY_DATABASE2, + &gEfiImageSecurityDatabaseGuid, + Data, + DataSize + ); + FreePool(Data); + } else { + DEBUG((DEBUG_INFO, "Skip measuring variable %s since it's deleted\n", EFI_IMAGE_SECURITY_DATABASE2)); + } + return EFI_SUCCESS; } @@ -2176,6 +2279,7 @@ OnReadyToBoot ( // 1. This is the first boot attempt. // Status = TcgMeasureAction ( + 4, EFI_CALLING_EFI_APPLICATION ); if (EFI_ERROR (Status)) { @@ -2189,7 +2293,7 @@ OnReadyToBoot ( for (PcrIndex = 0; PcrIndex < 7; PcrIndex++) { Status = MeasureSeparatorEvent (PcrIndex); if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Seperator Event not Measured. Error!\n")); + DEBUG ((DEBUG_ERROR, "Separator Event not Measured. Error!\n")); } } @@ -2209,11 +2313,24 @@ OnReadyToBoot ( // 6. Not first attempt, meaning a return from last attempt // Status = TcgMeasureAction ( + 4, EFI_RETURNING_FROM_EFI_APPLICATOIN ); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_RETURNING_FROM_EFI_APPLICATOIN)); } + + // + // 7. Next boot attempt, measure "Calling EFI Application from Boot Option" again + // TCG PC Client PFP spec Section 2.4.4.5 Step 4 + // + Status = TcgMeasureAction ( + 4, + EFI_CALLING_EFI_APPLICATION + ); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_ERROR, "%a not Measured. Error!\n", EFI_CALLING_EFI_APPLICATION)); + } } DEBUG ((EFI_D_INFO, "TPM2 Tcg2Dxe Measure Data when ReadyToBoot\n")); @@ -2246,6 +2363,7 @@ OnExitBootServices ( // Measure invocation of ExitBootServices, // Status = TcgMeasureAction ( + 5, EFI_EXIT_BOOT_SERVICES_INVOCATION ); if (EFI_ERROR (Status)) { @@ -2256,6 +2374,7 @@ OnExitBootServices ( // Measure success of ExitBootServices // Status = TcgMeasureAction ( + 5, EFI_EXIT_BOOT_SERVICES_SUCCEEDED ); if (EFI_ERROR (Status)) { @@ -2285,6 +2404,7 @@ OnExitBootServicesFailed ( // Measure Failure of ExitBootServices, // Status = TcgMeasureAction ( + 5, EFI_EXIT_BOOT_SERVICES_FAILED ); if (EFI_ERROR (Status)) { @@ -2293,9 +2413,71 @@ OnExitBootServicesFailed ( } +/** + This routine is called to properly shutdown the TPM before system reset. + It follow chapter "12.2.3 Startup State" in Trusted Platform Module Library + Part 1: Architecture, Revision 01.16. + + @param[in] ResetType The type of reset to perform. + @param[in] ResetStatus The status code for the reset. + @param[in] DataSize The size, in bytes, of ResetData. + @param[in] ResetData For a ResetType of EfiResetCold, EfiResetWarm, or + EfiResetShutdown the data buffer starts with a Null-terminated + string, optionally followed by additional binary data. + The string is a description that the caller may use to further + indicate the reason for the system reset. ResetData is only + valid if ResetStatus is something other than EFI_SUCCESS + unless the ResetType is EfiResetPlatformSpecific + where a minimum amount of ResetData is always required. + For a ResetType of EfiResetPlatformSpecific the data buffer + also starts with a Null-terminated string that is followed + by an EFI_GUID that describes the specific type of reset to perform. +**/ +VOID +EFIAPI +ShutdownTpmOnReset ( + IN EFI_RESET_TYPE ResetType, + IN EFI_STATUS ResetStatus, + IN UINTN DataSize, + IN VOID *ResetData OPTIONAL + ) +{ + EFI_STATUS Status; + Status = Tpm2Shutdown (TPM_SU_CLEAR); + DEBUG ((DEBUG_VERBOSE, "Tpm2Shutdown (SU_CLEAR) - %r\n", Status)); +} + +/** + Hook the system reset to properly shutdown TPM. + It follow chapter "12.2.3 Startup State" in Trusted Platform Module Library + Part 1: Architecture, Revision 01.16. + + @param[in] Event Event whose notification function is being invoked + @param[in] Context Pointer to the notification function's context +**/ +VOID +EFIAPI +OnResetNotificationInstall ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + EFI_RESET_NOTIFICATION_PROTOCOL *ResetNotify; + + Status = gBS->LocateProtocol (&gEfiResetNotificationProtocolGuid, NULL, (VOID **) &ResetNotify); + if (!EFI_ERROR (Status)) { + Status = ResetNotify->RegisterResetNotify (ResetNotify, ShutdownTpmOnReset); + ASSERT_EFI_ERROR (Status); + DEBUG ((DEBUG_VERBOSE, "TCG2: Hook system reset to properly shutdown TPM.\n")); + + gBS->CloseEvent (Event); + } +} + /** The function install Tcg2 protocol. - + @retval EFI_SUCCESS Tcg2 protocol is installed. @retval other Some error occurs. **/ @@ -2320,9 +2502,9 @@ InstallTcg2 ( /** The driver's entry point. It publishes EFI Tcg2 Protocol. - @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] ImageHandle The firmware allocated handle for the EFI image. @param[in] SystemTable A pointer to the EFI System Table. - + @retval EFI_SUCCESS The entry point is executed successfully. @retval other Some error occurs when executing this entry point. **/ @@ -2338,7 +2520,6 @@ DriverEntry ( VOID *Registration; UINT32 MaxCommandSize; UINT32 MaxResponseSize; - TPML_PCR_SELECTION Pcrs; UINTN Index; EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap; UINT32 ActivePCRBanks; @@ -2348,7 +2529,7 @@ DriverEntry ( if (CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceNoneGuid) || CompareGuid (PcdGetPtr(PcdTpmInstanceGuid), &gEfiTpmDeviceInstanceTpm12Guid)){ - DEBUG ((EFI_D_ERROR, "No TPM2 instance required!\n")); + DEBUG ((DEBUG_INFO, "No TPM2 instance required!\n")); return EFI_UNSUPPORTED; } @@ -2356,18 +2537,18 @@ DriverEntry ( DEBUG ((EFI_D_ERROR, "TPM2 error!\n")); return EFI_DEVICE_ERROR; } - + Status = Tpm2RequestUseTpm (); if (EFI_ERROR (Status)) { DEBUG ((EFI_D_ERROR, "TPM2 not detected!\n")); return Status; } - + // // Fill information // ASSERT (TCG_EVENT_LOG_AREA_COUNT_MAX == sizeof(mTcg2EventInfo)/sizeof(mTcg2EventInfo[0])); - + mTcgDxeData.BsCap.Size = sizeof(EFI_TCG2_BOOT_SERVICE_CAPABILITY); mTcgDxeData.BsCap.ProtocolVersion.Major = 1; mTcgDxeData.BsCap.ProtocolVersion.Minor = 1; @@ -2408,61 +2589,22 @@ DriverEntry ( // // Get supported PCR and current Active PCRs // - Status = Tpm2GetCapabilityPcrs (&Pcrs); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_ERROR, "Tpm2GetCapabilityPcrs fail!\n")); - TpmHashAlgorithmBitmap = EFI_TCG2_BOOT_HASH_ALG_SHA1; - NumberOfPCRBanks = 1; - ActivePCRBanks = EFI_TCG2_BOOT_HASH_ALG_SHA1; - } else { - DEBUG ((EFI_D_INFO, "Tpm2GetCapabilityPcrs Count - %08x\n", Pcrs.count)); - NumberOfPCRBanks = 0; - TpmHashAlgorithmBitmap = 0; - ActivePCRBanks = 0; - for (Index = 0; Index < Pcrs.count; Index++) { - DEBUG ((EFI_D_INFO, "hash - %x\n", Pcrs.pcrSelections[Index].hash)); - switch (Pcrs.pcrSelections[Index].hash) { - case TPM_ALG_SHA1: - TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SHA1; - NumberOfPCRBanks ++; - if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { - ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA1; - } - break; - case TPM_ALG_SHA256: - TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SHA256; - NumberOfPCRBanks ++; - if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { - ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA256; - } - break; - case TPM_ALG_SHA384: - TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SHA384; - NumberOfPCRBanks ++; - if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { - ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA384; - } - break; - case TPM_ALG_SHA512: - TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SHA512; - NumberOfPCRBanks ++; - if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { - ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SHA512; - } - break; - case TPM_ALG_SM3_256: - TpmHashAlgorithmBitmap |= EFI_TCG2_BOOT_HASH_ALG_SM3_256; - NumberOfPCRBanks ++; - if (!IsZeroBuffer (Pcrs.pcrSelections[Index].pcrSelect, Pcrs.pcrSelections[Index].sizeofSelect)) { - ActivePCRBanks |= EFI_TCG2_BOOT_HASH_ALG_SM3_256; - } - break; - } - } - } + Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePCRBanks); + ASSERT_EFI_ERROR (Status); + mTcgDxeData.BsCap.HashAlgorithmBitmap = TpmHashAlgorithmBitmap & PcdGet32 (PcdTcg2HashAlgorithmBitmap); mTcgDxeData.BsCap.ActivePcrBanks = ActivePCRBanks & PcdGet32 (PcdTcg2HashAlgorithmBitmap); + // + // Need calculate NumberOfPCRBanks here, because HashAlgorithmBitmap might be removed by PCD. + // + NumberOfPCRBanks = 0; + for (Index = 0; Index < 32; Index++) { + if ((mTcgDxeData.BsCap.HashAlgorithmBitmap & (1u << Index)) != 0) { + NumberOfPCRBanks++; + } + } + if (PcdGet32 (PcdTcg2NumberOfPCRBanks) == 0) { mTcgDxeData.BsCap.NumberOfPCRBanks = NumberOfPCRBanks; } else { @@ -2513,7 +2655,7 @@ DriverEntry ( ); // - // Measure Exit Boot Service failed + // Measure Exit Boot Service failed // Status = gBS->CreateEventEx ( EVT_NOTIFY_SIGNAL, @@ -2530,6 +2672,11 @@ DriverEntry ( // may update SecureBoot value based on last setting. // EfiCreateProtocolNotifyEvent (&gEfiVariableWriteArchProtocolGuid, TPL_CALLBACK, MeasureSecureBootPolicy, NULL, &Registration); + + // + // Hook the system reset to properly shutdown TPM. + // + EfiCreateProtocolNotifyEvent (&gEfiResetNotificationProtocolGuid, TPL_CALLBACK, OnResetNotificationInstall, NULL, &Registration); } //