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