--- /dev/null
+/** @file\r
+ Ihis library uses TPM2 device to calculation hash.\r
+\r
+Copyright (c) 2013, Intel Corporation. All rights reserved. <BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution. The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+**/\r
+\r
+#include <PiPei.h>\r
+#include <Library/BaseLib.h>\r
+#include <Library/BaseMemoryLib.h>\r
+#include <Library/Tpm2CommandLib.h>\r
+#include <Library/DebugLib.h>\r
+#include <Library/MemoryAllocationLib.h>\r
+#include <Library/HashLib.h>\r
+#include <Library/PcdLib.h>\r
+#include <Protocol/TrEEProtocol.h>\r
+\r
+typedef struct {\r
+ TPM_ALG_ID AlgoId;\r
+ UINT32 Mask;\r
+} TPM2_HASH_MASK;\r
+\r
+TPM2_HASH_MASK mTpm2HashMask[] = {\r
+ {TPM_ALG_SHA1, TREE_BOOT_HASH_ALG_SHA1},\r
+ {TPM_ALG_SHA256, TREE_BOOT_HASH_ALG_SHA256},\r
+ {TPM_ALG_SHA384, TREE_BOOT_HASH_ALG_SHA384},\r
+ {TPM_ALG_SHA512, TREE_BOOT_HASH_ALG_SHA512},\r
+};\r
+\r
+/**\r
+ The function get algorith from hash mask info.\r
+\r
+ @return Hash algorithm\r
+**/\r
+TPM_ALG_ID\r
+Tpm2GetAlgoFromHashMask (\r
+ VOID\r
+ )\r
+{\r
+ UINT32 HashMask;\r
+ UINTN Index;\r
+\r
+ HashMask = PcdGet32 (PcdTpm2HashMask);\r
+ for (Index = 0; Index < sizeof(mTpm2HashMask)/sizeof(mTpm2HashMask[0]); Index++) {\r
+ if (mTpm2HashMask[Index].Mask == HashMask) {\r
+ return mTpm2HashMask[Index].AlgoId;\r
+ }\r
+ }\r
+\r
+ return TPM_ALG_NULL;\r
+}\r
+\r
+/**\r
+ Start hash sequence.\r
+\r
+ @param HashHandle Hash handle.\r
+\r
+ @retval EFI_SUCCESS Hash sequence start and HandleHandle returned.\r
+ @retval EFI_OUT_OF_RESOURCES No enough resource to start hash.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashStart (\r
+ OUT HASH_HANDLE *HashHandle\r
+ )\r
+{\r
+ TPMI_DH_OBJECT SequenceHandle;\r
+ EFI_STATUS Status;\r
+ TPM_ALG_ID AlgoId;\r
+\r
+ AlgoId = Tpm2GetAlgoFromHashMask ();\r
+\r
+ Status = Tpm2HashSequenceStart (AlgoId, &SequenceHandle);\r
+ if (!EFI_ERROR (Status)) {\r
+ *HashHandle = (HASH_HANDLE)SequenceHandle;\r
+ }\r
+ return Status;\r
+}\r
+\r
+/**\r
+ Update hash sequence data.\r
+\r
+ @param HashHandle Hash handle.\r
+ @param DataToHash Data to be hashed.\r
+ @param DataToHashLen Data size.\r
+\r
+ @retval EFI_SUCCESS Hash sequence updated.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashUpdate (\r
+ IN HASH_HANDLE HashHandle,\r
+ IN VOID *DataToHash,\r
+ IN UINTN DataToHashLen\r
+ )\r
+{\r
+ UINT8 *Buffer;\r
+ UINT64 HashLen;\r
+ TPM2B_MAX_BUFFER HashBuffer;\r
+ EFI_STATUS Status;\r
+\r
+ Buffer = (UINT8 *)(UINTN)DataToHash;\r
+ for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {\r
+\r
+ HashBuffer.size = sizeof(HashBuffer.buffer);\r
+ CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));\r
+ Buffer += sizeof(HashBuffer.buffer);\r
+\r
+ Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Last one\r
+ //\r
+ HashBuffer.size = (UINT16)HashLen;\r
+ CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);\r
+ Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Hash sequence complete and extend to PCR.\r
+\r
+ @param HashHandle Hash handle.\r
+ @param PcrIndex PCR to be extended.\r
+ @param DataToHash Data to be hashed.\r
+ @param DataToHashLen Data size.\r
+ @param DigestList Digest list.\r
+\r
+ @retval EFI_SUCCESS Hash sequence complete and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashCompleteAndExtend (\r
+ IN HASH_HANDLE HashHandle,\r
+ IN TPMI_DH_PCR PcrIndex,\r
+ IN VOID *DataToHash,\r
+ IN UINTN DataToHashLen,\r
+ OUT TPML_DIGEST_VALUES *DigestList\r
+ )\r
+{\r
+ UINT8 *Buffer;\r
+ UINT64 HashLen;\r
+ TPM2B_MAX_BUFFER HashBuffer;\r
+ EFI_STATUS Status;\r
+ TPM_ALG_ID AlgoId;\r
+ TPM2B_DIGEST Result;\r
+\r
+ AlgoId = Tpm2GetAlgoFromHashMask ();\r
+\r
+ Buffer = (UINT8 *)(UINTN)DataToHash;\r
+ for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {\r
+\r
+ HashBuffer.size = sizeof(HashBuffer.buffer);\r
+ CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));\r
+ Buffer += sizeof(HashBuffer.buffer);\r
+\r
+ Status = Tpm2SequenceUpdate((TPMI_DH_OBJECT)HashHandle, &HashBuffer);\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+\r
+ //\r
+ // Last one\r
+ //\r
+ HashBuffer.size = (UINT16)HashLen;\r
+ CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);\r
+\r
+ ZeroMem(DigestList, sizeof(*DigestList));\r
+ DigestList->count = HASH_COUNT;\r
+\r
+ if (AlgoId == TPM_ALG_NULL) {\r
+ Status = Tpm2EventSequenceComplete (\r
+ PcrIndex,\r
+ (TPMI_DH_OBJECT)HashHandle,\r
+ &HashBuffer,\r
+ DigestList\r
+ );\r
+ } else {\r
+ Status = Tpm2SequenceComplete (\r
+ (TPMI_DH_OBJECT)HashHandle,\r
+ &HashBuffer,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+\r
+ DigestList->count = 1;\r
+ DigestList->digests[0].hashAlg = AlgoId;\r
+ CopyMem (&DigestList->digests[0].digest, Result.buffer, Result.size);\r
+ Status = Tpm2PcrExtend (\r
+ PcrIndex,\r
+ DigestList\r
+ );\r
+ }\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ Hash data and extend to PCR.\r
+\r
+ @param PcrIndex PCR to be extended.\r
+ @param DataToHash Data to be hashed.\r
+ @param DataToHashLen Data size.\r
+ @param DigestList Digest list.\r
+\r
+ @retval EFI_SUCCESS Hash data and DigestList is returned.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+HashAndExtend (\r
+ IN TPMI_DH_PCR PcrIndex,\r
+ IN VOID *DataToHash,\r
+ IN UINTN DataToHashLen,\r
+ OUT TPML_DIGEST_VALUES *DigestList\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINT8 *Buffer;\r
+ UINT64 HashLen;\r
+ TPMI_DH_OBJECT SequenceHandle;\r
+ TPM2B_MAX_BUFFER HashBuffer;\r
+ TPM_ALG_ID AlgoId;\r
+ TPM2B_EVENT EventData;\r
+ TPM2B_DIGEST Result;\r
+\r
+ DEBUG((EFI_D_INFO, "\n HashAndExtend Entry \n"));\r
+\r
+ SequenceHandle = 0xFFFFFFFF; // Know bad value\r
+\r
+ AlgoId = Tpm2GetAlgoFromHashMask ();\r
+\r
+ if ((AlgoId == TPM_ALG_NULL) && (DataToHashLen <= sizeof(EventData.buffer))) {\r
+ EventData.size = (UINT16)DataToHashLen;\r
+ CopyMem (EventData.buffer, DataToHash, DataToHashLen);\r
+ Status = Tpm2PcrEvent (PcrIndex, &EventData, DigestList);\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ Status = Tpm2HashSequenceStart(AlgoId, &SequenceHandle);\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ DEBUG((EFI_D_INFO, "\n Tpm2HashSequenceStart Success \n"));\r
+\r
+ Buffer = (UINT8 *)(UINTN)DataToHash;\r
+ for (HashLen = DataToHashLen; HashLen > sizeof(HashBuffer.buffer); HashLen -= sizeof(HashBuffer.buffer)) {\r
+\r
+ HashBuffer.size = sizeof(HashBuffer.buffer);\r
+ CopyMem(HashBuffer.buffer, Buffer, sizeof(HashBuffer.buffer));\r
+ Buffer += sizeof(HashBuffer.buffer);\r
+\r
+ Status = Tpm2SequenceUpdate(SequenceHandle, &HashBuffer);\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ }\r
+ DEBUG((EFI_D_INFO, "\n Tpm2SequenceUpdate Success \n"));\r
+\r
+ HashBuffer.size = (UINT16)HashLen;\r
+ CopyMem(HashBuffer.buffer, Buffer, (UINTN)HashLen);\r
+\r
+ ZeroMem(DigestList, sizeof(*DigestList));\r
+ DigestList->count = HASH_COUNT;\r
+\r
+ if (AlgoId == TPM_ALG_NULL) {\r
+ Status = Tpm2EventSequenceComplete (\r
+ PcrIndex,\r
+ SequenceHandle,\r
+ &HashBuffer,\r
+ DigestList\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ DEBUG((EFI_D_INFO, "\n Tpm2EventSequenceComplete Success \n"));\r
+ } else {\r
+ Status = Tpm2SequenceComplete (\r
+ SequenceHandle,\r
+ &HashBuffer,\r
+ &Result\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ DEBUG((EFI_D_INFO, "\n Tpm2SequenceComplete Success \n"));\r
+\r
+ DigestList->count = 1;\r
+ DigestList->digests[0].hashAlg = AlgoId;\r
+ CopyMem (&DigestList->digests[0].digest, Result.buffer, Result.size);\r
+ Status = Tpm2PcrExtend (\r
+ PcrIndex,\r
+ DigestList\r
+ );\r
+ if (EFI_ERROR(Status)) {\r
+ return EFI_DEVICE_ERROR;\r
+ }\r
+ DEBUG((EFI_D_INFO, "\n Tpm2PcrExtend Success \n"));\r
+ }\r
+\r
+ return EFI_SUCCESS;\r
+}\r
+\r
+/**\r
+ This service register Hash.\r
+\r
+ @param HashInterface Hash interface\r
+\r
+ @retval EFI_SUCCESS This hash interface is registered successfully.\r
+ @retval EFI_UNSUPPORTED System does not support register this interface.\r
+ @retval EFI_ALREADY_STARTED System already register this interface.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RegisterHashInterfaceLib (\r
+ IN HASH_INTERFACE *HashInterface\r
+ )\r
+{\r
+ return EFI_UNSUPPORTED;\r
+}
\ No newline at end of file