diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c index 096e3ef6eb..593130779e 100644 --- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c @@ -3,6 +3,7 @@ Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.
(C) Copyright 2016 Hewlett Packard Enterprise Development LP
+Copyright (c) Qualcomm Technologies, Inc. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -26,6 +27,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include #include #include +#include #include #include @@ -1585,6 +1587,180 @@ EFI_TCG2_PROTOCOL mTcg2Protocol = { Tcg2GetResultOfSetActivePcrBanks, }; +/** + Add an event to the TCG2 event log using the supplied digest list. + + This is the EDKII_LOG_TCG2_EVENT_PROTOCOL.LogEvent implementation. It logs + the event described by Tcg2Event together with the caller-supplied digests in + DigestList, mirroring the logging portion of Tcg2HashLogExtendEvent but + without computing any digest or extending a PCR. It is intended for callers + that have already performed, or intentionally skipped, the PCR extend and + only need the event recorded in the log. + + The caller is responsible for providing digests that are consistent with the + platform's active PCR banks; DigestList and Tcg2Event are validated for + self-consistency before anything is written to the log. + + @param[in] This Pointer to the EDKII_LOG_TCG2_EVENT_PROTOCOL + instance. + @param[in] DigestList Pointer to a TPML_DIGEST_VALUES structure + containing the digests to record for the event. + @param[in] DigestListSize Size, in bytes, of the buffer pointed to by + DigestList. + @param[in] Tcg2Event Pointer to an EFI_TCG2_EVENT structure that + describes the event to log. + @param[in] Tcg2EventSize Size, in bytes, of the buffer pointed to by + Tcg2Event. + + @retval EFI_SUCCESS The event was added to the event log. + @retval EFI_INVALID_PARAMETER A parameter is NULL, zero, or otherwise + inconsistent (for example, DigestListSize does + not match the described digests). + @retval EFI_BUFFER_TOO_SMALL Tcg2EventSize is too small for the described + event. + @retval EFI_DEVICE_ERROR The TPM is not present or the event could not + be logged. +**/ +EFI_STATUS +EFIAPI +Tcg2LogEvent ( + IN EDKII_LOG_TCG2_EVENT_PROTOCOL *This, + IN VOID *DigestList, + IN UINTN DigestListSize, + IN VOID *Tcg2Event, + IN UINTN Tcg2EventSize + ) +{ + EFI_STATUS Status; + TCG_PCR_EVENT_HDR NewEventHdr; + EFI_TCG2_EVENT *Event; + TPML_DIGEST_VALUES *DigestValues; + UINT32 DigestCount; + UINT32 DigestIndex; + UINT16 DigestSize; + UINTN ExpectedSize; + + DEBUG ((DEBUG_INFO, "Tcg2LogEvent ...\n")); + + // + // Reject NULL pointers and zero-length buffers up front. + // + if ((This == NULL) || (DigestList == NULL) || (DigestListSize == 0) || + (Tcg2Event == NULL) || (Tcg2EventSize == 0)) + { + return EFI_INVALID_PARAMETER; + } + + DigestValues = (TPML_DIGEST_VALUES *)DigestList; + + // + // The buffer must be large enough to hold the fixed TPML_DIGEST_VALUES + // header before its digest count can be trusted. + // + if (DigestListSize < OFFSET_OF (TPML_DIGEST_VALUES, digests)) { + return EFI_INVALID_PARAMETER; + } + + DigestCount = DigestValues->count; + if ((DigestCount == 0) || (DigestCount > HASH_COUNT)) { + return EFI_INVALID_PARAMETER; + } + + // + // Walk the variable-length digest array, accumulating the exact size implied + // by each digest's hash algorithm. This both validates every algorithm and + // guards against a digest that would run past the end of the buffer. + // + ExpectedSize = OFFSET_OF (TPML_DIGEST_VALUES, digests); + for (DigestIndex = 0; DigestIndex < DigestCount; DigestIndex++) { + DigestSize = GetHashSizeFromAlgo (DigestValues->digests[DigestIndex].hashAlg); + + if (DigestSize == 0) { + return EFI_INVALID_PARAMETER; + } + + ExpectedSize += sizeof (TPMI_ALG_HASH) + DigestSize; + if (ExpectedSize > DigestListSize) { + return EFI_INVALID_PARAMETER; + } + } + + // + // The accumulated size must match DigestListSize exactly; a larger buffer + // implies trailing or malformed data. + // + if (ExpectedSize != DigestListSize) { + return EFI_INVALID_PARAMETER; + } + + // + // Logging requires a present TPM. + // + if (!mTcgDxeData.BsCap.TPMPresentFlag) { + return EFI_DEVICE_ERROR; + } + + Event = (EFI_TCG2_EVENT *)Tcg2Event; + + // + // Validate the EFI_TCG2_EVENT: it must be large enough for the fixed fields, + // carry the expected header size and version, and declare a self-consistent + // Size that fits within the caller-supplied buffer. + // + if (Tcg2EventSize < OFFSET_OF (EFI_TCG2_EVENT, Event)) { + return EFI_BUFFER_TOO_SMALL; + } + + if (Event->Header.HeaderSize != sizeof (EFI_TCG2_EVENT_HEADER)) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Header.HeaderVersion != EFI_TCG2_EVENT_HEADER_VERSION) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Size < Event->Header.HeaderSize + sizeof (Event->Size)) { + return EFI_INVALID_PARAMETER; + } + + if (Event->Size > Tcg2EventSize) { + return EFI_BUFFER_TOO_SMALL; + } + + // + // Every event except EV_NO_ACTION must target a valid PCR index. + // + if ((Event->Header.EventType != EV_NO_ACTION) && (Event->Header.PCRIndex > MAX_PCR_INDEX)) { + return EFI_INVALID_PARAMETER; + } + + // + // Build the internal event header and hand it to the shared log routine. + // EventSize is the payload length: total Size minus the leading UINT32 Size + // field and the event header. + // + NewEventHdr.PCRIndex = Event->Header.PCRIndex; + NewEventHdr.EventType = Event->Header.EventType; + NewEventHdr.EventSize = Event->Size - sizeof (UINT32) - Event->Header.HeaderSize; + + Status = TcgDxeLogHashEvent ( + DigestValues, + &NewEventHdr, + Event->Event + ); + + DEBUG ((DEBUG_VERBOSE, "Tcg2LogEvent - %r\n", Status)); + return Status; +} + +// +// Instance of the EDKII Log TCG2 Event Protocol produced by this driver. +// +EDKII_LOG_TCG2_EVENT_PROTOCOL mLogTcg2EventProtocol = { + EDKII_LOG_TCG2_EVENT_PROTOCOL_REVISION, + Tcg2LogEvent +}; + /** Initialize the Event Log and log events passed from the PEI phase. @@ -2746,6 +2922,8 @@ InstallTcg2 ( &Handle, &gEfiTcg2ProtocolGuid, &mTcg2Protocol, + &gEdkiiLogTcg2EventProtocolGuid, + &mLogTcg2EventProtocol, NULL ); return Status; diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf index d291c03254..9734e83710 100644 --- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.inf @@ -17,6 +17,7 @@ # buffer overflow, integer overflow. # # Copyright (c) 2015 - 2024, Intel Corporation. All rights reserved.
+# Copyright (c) Qualcomm Technologies, Inc. All rights reserved.
# SPDX-License-Identifier: BSD-2-Clause-Patent # ## @@ -91,6 +92,7 @@ [Protocols] gEfiTcg2ProtocolGuid ## PRODUCES + gEdkiiLogTcg2EventProtocolGuid ## PRODUCES gEfiTcg2FinalEventsTableGuid ## PRODUCES gEfiMpServiceProtocolGuid ## SOMETIMES_CONSUMES gEfiVariableWriteArchProtocolGuid ## NOTIFY