]> git.proxmox.com Git - mirror_edk2.git/blobdiff - SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c
Add TPM2 implementation.
[mirror_edk2.git] / SecurityPkg / Library / HashLibTpm2 / HashLibTpm2.c
diff --git a/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c b/SecurityPkg/Library/HashLibTpm2/HashLibTpm2.c
new file mode 100644 (file)
index 0000000..b2e01af
--- /dev/null
@@ -0,0 +1,342 @@
+/** @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