code: https://github.com/qizhangz/edk2/tree/NvIndexExtend
Signed-off-by: Qi Zhang <qi1.zh...@intel.com> Cc: Jiewen Yao <jiewen....@intel.com> Cc: Jian J Wang <jian.j.w...@intel.com> Cc: Rahul Kumar <rahul1.ku...@intel.com> Cc: Qi Zhang <qi1.zh...@intel.com> --- SecurityPkg/Include/Library/Tpm2CommandLib.h | 21 +++ .../HashLibBaseCryptoRouterDxe.c | 86 +++++++++++-- .../Library/Tpm2CommandLib/Tpm2NVStorage.c | 120 ++++++++++++++++++ SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c | 25 +++- 4 files changed, 238 insertions(+), 14 deletions(-) diff --git a/SecurityPkg/Include/Library/Tpm2CommandLib.h b/SecurityPkg/Include/Library/Tpm2CommandLib.h index a2fb97f18d..f2ff3a5c0c 100644 --- a/SecurityPkg/Include/Library/Tpm2CommandLib.h +++ b/SecurityPkg/Include/Library/Tpm2CommandLib.h @@ -467,6 +467,27 @@ Tpm2NvGlobalWriteLock ( IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL ); +/** + This command extends a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace(). + + @param[in] AuthHandle the handle indicating the source of the authorization value. + @param[in] NvIndex The NV Index of the area to extend. + @param[in] AuthSession Auth Session context + @param[in] InData The data to extend. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. +**/ +EFI_STATUS +EFIAPI +Tpm2NvExtend ( + IN TPMI_RH_NV_AUTH AuthHandle, + IN TPMI_RH_NV_INDEX NvIndex, + IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPM2B_MAX_BUFFER *InData + ); + /** This command is used to cause an update to the indicated PCR. The digests parameter contains one or more tagged digest value identified by an algorithm ID. diff --git a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c index ee8fe6e06e..591cbfcb79 100644 --- a/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c +++ b/SecurityPkg/Library/HashLibBaseCryptoRouter/HashLibBaseCryptoRouterDxe.c @@ -16,6 +16,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent #include <Library/MemoryAllocationLib.h> #include <Library/PcdLib.h> #include <Library/HashLib.h> +#include <Protocol/Tcg2Protocol.h> #include "HashLibBaseCryptoRouterCommon.h" @@ -128,6 +129,49 @@ HashUpdate ( return EFI_SUCCESS; } +/** + extend Data to NvIndex. + + @param NvIndex NvIndex to be extended. + @param DataSize Data size. + @param Data Data to be extended. + + @retval EFI_SUCCESS Data is extended to NvIndex successfully. +**/ +EFI_STATUS +EFIAPI +Tpm2ExtendNvIndex ( + TPMI_RH_NV_INDEX NvIndex, + UINT16 DataSize, + BYTE *Data + ) +{ + EFI_STATUS Status; + TPMI_RH_NV_AUTH AuthHandle; + TPM2B_MAX_BUFFER NvExtendData; + + AuthHandle = TPM_RH_PLATFORM; + ZeroMem (&NvExtendData, sizeof (NvExtendData)); + CopyMem (NvExtendData.buffer, Data, DataSize); + NvExtendData.size = DataSize; + Status = Tpm2NvExtend ( + AuthHandle, + NvIndex, + NULL, + &NvExtendData + ); + if (EFI_ERROR (Status)) { + DEBUG (( + DEBUG_ERROR, + "Extend TPM NV index failed, Index: 0x%x Status: %d\n", + NvIndex, + Status + )); + } + + return Status; +} + /** Hash sequence complete and extend to PCR. @@ -149,11 +193,16 @@ HashCompleteAndExtend ( OUT TPML_DIGEST_VALUES *DigestList ) { - TPML_DIGEST_VALUES Digest; - HASH_HANDLE *HashCtx; - UINTN Index; - EFI_STATUS Status; - UINT32 HashMask; + TPML_DIGEST_VALUES Digest; + HASH_HANDLE *HashCtx; + UINTN Index; + EFI_STATUS Status; + UINT32 HashMask; + TPML_DIGEST_VALUES TcgPcrEvent2Digest; + EFI_TCG2_EVENT_ALGORITHM_BITMAP TpmHashAlgorithmBitmap; + UINT32 ActivePcrBanks; + UINT32 *BufferPtr; + UINT32 DigestListBinSize; if (mHashInterfaceCount == 0) { return EFI_UNSUPPORTED; @@ -175,10 +224,29 @@ HashCompleteAndExtend ( FreePool (HashCtx); - Status = Tpm2PcrExtend ( - PcrIndex, - DigestList - ); + if (PcrIndex <= MAX_PCR_INDEX) { + Status = Tpm2PcrExtend ( + PcrIndex, + DigestList + ); + } else { + Status = Tpm2GetCapabilitySupportedAndActivePcrs (&TpmHashAlgorithmBitmap, &ActivePcrBanks); + ASSERT_EFI_ERROR (Status); + ActivePcrBanks = ActivePcrBanks & mSupportedHashMaskCurrent; + ZeroMem (&TcgPcrEvent2Digest, sizeof (TcgPcrEvent2Digest)); + BufferPtr = CopyDigestListToBuffer (&TcgPcrEvent2Digest, DigestList, ActivePcrBanks); + DigestListBinSize = (UINT32)((UINT8 *)BufferPtr - (UINT8 *)&TcgPcrEvent2Digest); + + // + // Extend to TPM NvIndex + // + Status = Tpm2ExtendNvIndex ( + PcrIndex, + (UINT16)DigestListBinSize, + (BYTE *)&TcgPcrEvent2Digest + ); + } + return Status; } diff --git a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c index 5077ace7c2..6f8badad3f 100644 --- a/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c +++ b/SecurityPkg/Library/Tpm2CommandLib/Tpm2NVStorage.c @@ -148,6 +148,22 @@ typedef struct { TPMS_AUTH_RESPONSE AuthSession; } TPM2_NV_GLOBALWRITELOCK_RESPONSE; +typedef struct { + TPM2_COMMAND_HEADER Header; + TPMI_RH_NV_AUTH AuthHandle; + TPMI_RH_NV_INDEX NvIndex; + UINT32 AuthSessionSize; + TPMS_AUTH_COMMAND AuthSession; + TPM2B_MAX_BUFFER Data; + UINT16 Offset; +} TPM2_NV_EXTEND_COMMAND; + +typedef struct { + TPM2_RESPONSE_HEADER Header; + UINT32 AuthSessionSize; + TPMS_AUTH_RESPONSE AuthSession; +} TPM2_NV_EXTEND_RESPONSE; + #pragma pack() /** @@ -1052,3 +1068,107 @@ Done: ZeroMem (&RecvBuffer, sizeof (RecvBuffer)); return Status; } + +/** + This command extends a value to an area in NV memory that was previously defined by TPM2_NV_DefineSpace(). + + @param[in] AuthHandle the handle indicating the source of the authorization value. + @param[in] NvIndex The NV Index of the area to extend. + @param[in] AuthSession Auth Session context + @param[in] InData The data to extend. + + @retval EFI_SUCCESS Operation completed successfully. + @retval EFI_DEVICE_ERROR The command was unsuccessful. + @retval EFI_NOT_FOUND The command was returned successfully, but NvIndex is not found. +**/ +EFI_STATUS +EFIAPI +Tpm2NvExtend ( + IN TPMI_RH_NV_AUTH AuthHandle, + IN TPMI_RH_NV_INDEX NvIndex, + IN TPMS_AUTH_COMMAND *AuthSession OPTIONAL, + IN TPM2B_MAX_BUFFER *InData + ) +{ + EFI_STATUS Status; + TPM2_NV_EXTEND_COMMAND SendBuffer; + TPM2_NV_EXTEND_RESPONSE RecvBuffer; + UINT32 SendBufferSize; + UINT32 RecvBufferSize; + UINT8 *Buffer; + UINT32 SessionInfoSize; + TPM_RC ResponseCode; + + // + // Construct command + // + SendBuffer.Header.tag = SwapBytes16 (TPM_ST_SESSIONS); + SendBuffer.Header.commandCode = SwapBytes32 (TPM_CC_NV_Extend); + + SendBuffer.AuthHandle = SwapBytes32 (AuthHandle); + SendBuffer.NvIndex = SwapBytes32 (NvIndex); + + // + // Add in Auth session + // + Buffer = (UINT8 *)&SendBuffer.AuthSession; + + // sessionInfoSize + SessionInfoSize = CopyAuthSessionCommand (AuthSession, Buffer); + Buffer += SessionInfoSize; + SendBuffer.AuthSessionSize = SwapBytes32 (SessionInfoSize); + + WriteUnaligned16 ((UINT16 *)Buffer, SwapBytes16 (InData->size)); + Buffer += sizeof (UINT16); + CopyMem (Buffer, InData->buffer, InData->size); + Buffer += InData->size; + + SendBufferSize = (UINT32)(Buffer - (UINT8 *)&SendBuffer); + SendBuffer.Header.paramSize = SwapBytes32 (SendBufferSize); + + // + // send Tpm command + // + RecvBufferSize = sizeof (RecvBuffer); + Status = Tpm2SubmitCommand (SendBufferSize, (UINT8 *)&SendBuffer, &RecvBufferSize, (UINT8 *)&RecvBuffer); + if (EFI_ERROR (Status)) { + goto Done; + } + + if (RecvBufferSize < sizeof (TPM2_RESPONSE_HEADER)) { + DEBUG ((DEBUG_ERROR, "Tpm2NvExtend - RecvBufferSize Error - %x\n", RecvBufferSize)); + Status = EFI_DEVICE_ERROR; + goto Done; + } + + ResponseCode = SwapBytes32 (RecvBuffer.Header.responseCode); + if (ResponseCode != TPM_RC_SUCCESS) { + DEBUG ((DEBUG_ERROR, "Tpm2NvExtend - responseCode - %x\n", ResponseCode)); + } + + switch (ResponseCode) { + case TPM_RC_SUCCESS: + // return data + break; + case TPM_RC_ATTRIBUTES: + Status = EFI_UNSUPPORTED; + break; + case TPM_RC_NV_AUTHORIZATION: + Status = EFI_SECURITY_VIOLATION; + break; + case TPM_RC_NV_LOCKED: + Status = EFI_ACCESS_DENIED; + break; + default: + Status = EFI_DEVICE_ERROR; + break; + } + +Done: + // + // Clear AuthSession Content + // + ZeroMem (&SendBuffer, sizeof (SendBuffer)); + ZeroMem (&RecvBuffer, sizeof (RecvBuffer)); + return Status; +} diff --git a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c index f6ea8b2bbf..423122e2e1 100644 --- a/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c +++ b/SecurityPkg/Tcg/Tcg2Dxe/Tcg2Dxe.c @@ -1230,10 +1230,25 @@ TcgDxeHashLogExtendEvent ( // // Do not do TPM extend for EV_NO_ACTION // - Status = EFI_SUCCESS; - InitNoActionEvent (&NoActionEvent, NewEventHdr->EventSize); - if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) { - Status = TcgDxeLogHashEvent (&(NoActionEvent.Digests), NewEventHdr, NewEventData); + if (NewEventHdr->PCRIndex <= MAX_PCR_INDEX) { + Status = EFI_SUCCESS; + InitNoActionEvent (&NoActionEvent, NewEventHdr->EventSize); + if ((Flags & EFI_TCG2_EXTEND_ONLY) == 0) { + Status = TcgDxeLogHashEvent (&(NoActionEvent.Digests), NewEventHdr, NewEventData); + } + } else { + // + // Extend to NvIndex + // + Status = HashAndExtend ( + NewEventHdr->PCRIndex, + HashData, + (UINTN)HashDataLen, + &DigestList + ); + if (!EFI_ERROR (Status)) { + Status = TcgDxeLogHashEvent (&DigestList, NewEventHdr, NewEventData); + } } return Status; @@ -1317,7 +1332,7 @@ Tcg2HashLogExtendEvent ( return EFI_INVALID_PARAMETER; } - if (Event->Header.PCRIndex > MAX_PCR_INDEX) { + if ((Event->Header.EventType != EV_NO_ACTION) && (Event->Header.PCRIndex > MAX_PCR_INDEX)) { return EFI_INVALID_PARAMETER; } -- 2.26.2.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#91083): https://edk2.groups.io/g/devel/message/91083 Mute This Topic: https://groups.io/mt/92200625/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-