public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v5 1/1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
@ 2022-03-09  8:44 Li, Zhihao
  2022-03-14  5:50 ` [edk2-devel] " Yao, Jiewen
  0 siblings, 1 reply; 4+ messages in thread
From: Li, Zhihao @ 2022-03-09  8:44 UTC (permalink / raw)
  To: devel; +Cc: Jiewen Yao, Jian J Wang, Xiaoyu Lu, Guomin Jiang, Siyuan Fu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3596

Parallel hash function ParallelHash256HashAll, as defined in NIST's
Special Publication 800-185, published December 2016. It utilizes
multi-process to calculate the digest.

Some modifications to pass CI test.

Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Cc: Siyuan Fu <siyuan.fu@intel.com>
Cc: Zhihao Li <zhihao.li@intel.com>

Signed-off-by: Zhihao Li <zhihao.li@intel.com>
---
 CryptoPkg/Driver/Crypto.c                                             |  36 ++-
 CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                  | 282 ++++++++++++++++++++
 CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c               | 278 +++++++++++++++++++
 CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c           |  40 +++
 CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                       | 166 ++++++++++++
 CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                       | 107 ++++++++
 CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c       |  40 +++
 CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c                |  34 ++-
 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c      | 145 ++++++++++
 CryptoPkg/CryptoPkg.ci.yaml                                           |   4 +-
 CryptoPkg/Include/Library/BaseCryptLib.h                              |  31 ++-
 CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h                  |   8 +-
 CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf                       |   3 +-
 CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h               | 201 ++++++++++++++
 CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf                        |   3 +-
 CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf                    |   3 +-
 CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                        |   8 +-
 CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf               |   3 +-
 CryptoPkg/Library/Include/CrtLibSupport.h                             |   3 +-
 CryptoPkg/Private/Protocol/Crypto.h                                   |  31 +++
 CryptoPkg/Test/CryptoPkgHostUnitTest.dsc                              |   3 +
 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf |   4 +
 22 files changed, 1422 insertions(+), 11 deletions(-)

diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
index d5d6aa8e5820..35312e0818a0 100644
--- a/CryptoPkg/Driver/Crypto.c
+++ b/CryptoPkg/Driver/Crypto.c
@@ -3,7 +3,7 @@
   from BaseCryptLib and TlsLib.
 
   Copyright (C) Microsoft Corporation. All rights reserved.
-  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -1314,6 +1314,38 @@ CryptoServiceSha512HashAll (
   return CALL_BASECRYPTLIB (Sha512.Services.HashAll, Sha512HashAll, (Data, DataSize, HashValue), FALSE);
 }
 
+/**
+  Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
+  published December 2016.
+
+  @param[in]   Input            Pointer to the input message (X).
+  @param[in]   InputByteLen     The number(>0) of input bytes provided for the input data.
+  @param[in]   BlockSize        The size of each block (B).
+  @param[out]  Output           Pointer to the output buffer.
+  @param[in]   OutputByteLen    The desired number of output bytes (L).
+  @param[in]   Customization    Pointer to the customization string (S).
+  @param[in]   CustomByteLen    The length of the customization string in bytes.
+
+  @retval TRUE   ParallelHash256 digest computation succeeded.
+  @retval FALSE  ParallelHash256 digest computation failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+CryptoServiceParallelHash256HashAll (
+  IN CONST VOID   *Input,
+  IN       UINTN  InputByteLen,
+  IN       UINTN  BlockSize,
+  OUT      VOID   *Output,
+  IN       UINTN  OutputByteLen,
+  IN CONST VOID   *Customization,
+  IN       UINTN  CustomByteLen
+  )
+{
+  return CALL_BASECRYPTLIB (ParallelHash.Services.HashAll, ParallelHash256HashAll, (Input, InputByteLen, BlockSize, Output, OutputByteLen, Customization, CustomByteLen), FALSE);
+}
+
 /**
   Retrieves the size, in bytes, of the context buffer required for SM3 hash operations.
 
@@ -4590,6 +4622,8 @@ const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
   CryptoServiceSha512Update,
   CryptoServiceSha512Final,
   CryptoServiceSha512HashAll,
+  /// Parallel hash
+  CryptoServiceParallelHash256HashAll,
   /// X509
   CryptoServiceX509GetSubjectName,
   CryptoServiceX509GetCommonName,
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
new file mode 100644
index 000000000000..96e3c8eb02e1
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
@@ -0,0 +1,282 @@
+/** @file
+  cSHAKE-256 Digest Wrapper Implementations.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CryptParallelHash.h"
+
+#define  CSHAKE256_SECURITY_STRENGTH  256
+#define  CSHAKE256_RATE_IN_BYTES      136
+
+const CHAR8  mZeroPadding[CSHAKE256_RATE_IN_BYTES] = { 0 };
+
+/**
+  CShake256 initial function.
+
+  Initializes user-supplied memory pointed by CShake256Context as cSHAKE-256 hash context for
+  subsequent use.
+
+  @param[out] CShake256Context  Pointer to cSHAKE-256 context being initialized.
+  @param[in]  OutputLen         The desired number of output length in bytes.
+  @param[in]  Name              Pointer to the function name string.
+  @param[in]  NameLen           The length of the function name in bytes.
+  @param[in]  Customization     Pointer to the customization string.
+  @param[in]  CustomizationLen  The length of the customization string in bytes.
+
+  @retval TRUE   cSHAKE-256 context initialization succeeded.
+  @retval FALSE  cSHAKE-256 context initialization failed.
+  @retval FALSE  This interface is not supported.
+**/
+BOOLEAN
+EFIAPI
+CShake256Init (
+  OUT  VOID        *CShake256Context,
+  IN   UINTN       OutputLen,
+  IN   CONST VOID  *Name,
+  IN   UINTN       NameLen,
+  IN   CONST VOID  *Customization,
+  IN   UINTN       CustomizationLen
+  )
+{
+  BOOLEAN  Status;
+  UINT8    EncBuf[sizeof (UINTN) + 1];
+  UINTN    EncLen;
+  UINTN    AbsorbLen;
+  UINTN    PadLen;
+
+  //
+  // Check input parameters.
+  //
+  if ((CShake256Context == NULL) || (OutputLen == 0) || ((NameLen != 0) && (Name == NULL)) || ((CustomizationLen != 0) && (Customization == NULL))) {
+    return FALSE;
+  }
+
+  //
+  // Initialize KECCAK context with pad value and block size.
+  //
+  if ((NameLen == 0) && (CustomizationLen == 0)) {
+    //
+    // When N and S are both empty strings, cSHAKE(X, L, N, S) is equivalent to
+    // SHAKE as defined in FIPS 202.
+    //
+    Status = (BOOLEAN)KeccakInit (
+                        (Keccak1600_Ctx *)CShake256Context,
+                        '\x1f',
+                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
+                        OutputLen
+                        );
+
+    return Status;
+  } else {
+    Status = (BOOLEAN)KeccakInit (
+                        (Keccak1600_Ctx *)CShake256Context,
+                        '\x04',
+                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
+                        OutputLen
+                        );
+    if (!Status) {
+      return FALSE;
+    }
+
+    AbsorbLen = 0;
+    //
+    // Absorb Absorb bytepad(.., rate).
+    //
+    EncLen = LeftEncode (EncBuf, CSHAKE256_RATE_IN_BYTES);
+    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, EncBuf, EncLen);
+    if (!Status) {
+      return FALSE;
+    }
+
+    AbsorbLen += EncLen;
+
+    //
+    // Absorb encode_string(N).
+    //
+    EncLen = LeftEncode (EncBuf, NameLen * 8);
+    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, EncBuf, EncLen);
+    if (!Status) {
+      return FALSE;
+    }
+
+    AbsorbLen += EncLen;
+    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, Name, NameLen);
+    if (!Status) {
+      return FALSE;
+    }
+
+    AbsorbLen += NameLen;
+
+    //
+    // Absorb encode_string(S).
+    //
+    EncLen = LeftEncode (EncBuf, CustomizationLen * 8);
+    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, EncBuf, EncLen);
+    if (!Status) {
+      return FALSE;
+    }
+
+    AbsorbLen += EncLen;
+    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, Customization, CustomizationLen);
+    if (!Status) {
+      return FALSE;
+    }
+
+    AbsorbLen += CustomizationLen;
+
+    //
+    // Absorb zero padding up to rate.
+    //
+    PadLen = CSHAKE256_RATE_IN_BYTES - AbsorbLen % CSHAKE256_RATE_IN_BYTES;
+    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, mZeroPadding, PadLen);
+    if (!Status) {
+      return FALSE;
+    }
+
+    return TRUE;
+  }
+}
+
+/**
+  Digests the input data and updates cSHAKE-256 context.
+
+  This function performs cSHAKE-256 digest on a data buffer of the specified size.
+  It can be called multiple times to compute the digest of long or discontinuous data streams.
+  cSHAKE-256 context should be already correctly initialized by CShake256Init(), and should not be finalized
+  by CShake256Final(). Behavior with invalid context is undefined.
+
+  @param[in, out]  CShake256Context   Pointer to the cSHAKE-256 context.
+  @param[in]       Data               Pointer to the buffer containing the data to be hashed.
+  @param[in]       DataSize           Size of Data buffer in bytes.
+
+  @retval TRUE   cSHAKE-256 data digest succeeded.
+  @retval FALSE  cSHAKE-256 data digest failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+CShake256Update (
+  IN OUT  VOID        *CShake256Context,
+  IN      CONST VOID  *Data,
+  IN      UINTN       DataSize
+  )
+{
+  //
+  // Check input parameters.
+  //
+  if (CShake256Context == NULL) {
+    return FALSE;
+  }
+
+  //
+  // Check invalid parameters, in case that only DataLength was checked in OpenSSL.
+  //
+  if ((Data == NULL) && (DataSize != 0)) {
+    return FALSE;
+  }
+
+  return (BOOLEAN)(Sha3Update ((Keccak1600_Ctx *)CShake256Context, Data, DataSize));
+}
+
+/**
+  Completes computation of the cSHAKE-256 digest value.
+
+  This function completes cSHAKE-256 hash computation and retrieves the digest value into
+  the specified memory. After this function has been called, the cSHAKE-256 context cannot
+  be used again.
+  cSHAKE-256 context should be already correctly initialized by CShake256Init(), and should not be
+  finalized by CShake256Final(). Behavior with invalid cSHAKE-256 context is undefined.
+
+  @param[in, out]  CShake256Context  Pointer to the cSHAKE-256 context.
+  @param[out]      HashValue         Pointer to a buffer that receives the cSHAKE-256 digest
+                                     value.
+
+  @retval TRUE   cSHAKE-256 digest computation succeeded.
+  @retval FALSE  cSHAKE-256 digest computation failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+CShake256Final (
+  IN OUT  VOID   *CShake256Context,
+  OUT     UINT8  *HashValue
+  )
+{
+  //
+  // Check input parameters.
+  //
+  if ((CShake256Context == NULL) || (HashValue == NULL)) {
+    return FALSE;
+  }
+
+  //
+  // cSHAKE-256 Hash Finalization.
+  //
+  return (BOOLEAN)(Sha3Final ((Keccak1600_Ctx *)CShake256Context, HashValue));
+}
+
+/**
+  Computes the CSHAKE-256 message digest of a input data buffer.
+
+  This function performs the CSHAKE-256 message digest of a given data buffer, and places
+  the digest value into the specified memory.
+
+  @param[in]   Data               Pointer to the buffer containing the data to be hashed.
+  @param[in]   DataSize           Size of Data buffer in bytes.
+  @param[in]   OutputLen          Size of output in bytes.
+  @param[in]   Name               Pointer to the function name string.
+  @param[in]   NameLen            Size of the function name in bytes.
+  @param[in]   Customization      Pointer to the customization string.
+  @param[in]   CustomizationLen   Size of the customization string in bytes.
+  @param[out]  HashValue          Pointer to a buffer that receives the CSHAKE-256 digest
+                                  value.
+
+  @retval TRUE   CSHAKE-256 digest computation succeeded.
+  @retval FALSE  CSHAKE-256 digest computation failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+CShake256HashAll (
+  IN   CONST VOID  *Data,
+  IN   UINTN       DataSize,
+  IN   UINTN       OutputLen,
+  IN   CONST VOID  *Name,
+  IN   UINTN       NameLen,
+  IN   CONST VOID  *Customization,
+  IN   UINTN       CustomizationLen,
+  OUT  UINT8       *HashValue
+  )
+{
+  BOOLEAN         Status;
+  Keccak1600_Ctx  Ctx;
+
+  //
+  // Check input parameters.
+  //
+  if (HashValue == NULL) {
+    return FALSE;
+  }
+
+  if ((Data == NULL) && (DataSize != 0)) {
+    return FALSE;
+  }
+
+  Status = CShake256Init (&Ctx, OutputLen, Name, NameLen, Customization, CustomizationLen);
+  if (!Status) {
+    return FALSE;
+  }
+
+  Status = CShake256Update (&Ctx, Data, DataSize);
+  if (!Status) {
+    return FALSE;
+  }
+
+  return CShake256Final (&Ctx, HashValue);
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
new file mode 100644
index 000000000000..f7ce9dbf523e
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
@@ -0,0 +1,278 @@
+/** @file
+  ParallelHash Implementation.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "CryptParallelHash.h"
+#include <Library/MmServicesTableLib.h>
+#include <Library/SynchronizationLib.h>
+
+#define PARALLELHASH_CUSTOMIZATION  "ParallelHash"
+
+UINTN      mBlockNum;
+UINTN      mBlockSize;
+UINTN      mLastBlockSize;
+UINT8      *mInput;
+UINTN      mBlockResultSize;
+UINT8      *mBlockHashResult;
+BOOLEAN    *mBlockIsCompleted;
+SPIN_LOCK  *mSpinLockList;
+
+/**
+  Complete computation of digest of each block.
+
+  Each AP perform the function called by BSP.
+
+  @param[in] ProcedureArgument Argument of the procedure.
+**/
+VOID
+EFIAPI
+ParallelHashApExecute (
+  IN VOID  *ProcedureArgument
+  )
+{
+  UINTN    Index;
+  BOOLEAN  Status;
+
+  for (Index = 0; Index < mBlockNum; Index++) {
+    if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
+      //
+      // Completed, try next one.
+      //
+      if (mBlockIsCompleted[Index]) {
+        ReleaseSpinLock (&mSpinLockList[Index]);
+        continue;
+      }
+
+      //
+      // Calculate CShake256 for this block.
+      //
+      Status = CShake256HashAll (
+                 mInput + Index * mBlockSize,
+                 (Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
+                 mBlockResultSize,
+                 NULL,
+                 0,
+                 NULL,
+                 0,
+                 mBlockHashResult + Index * mBlockResultSize
+                 );
+      if (!EFI_ERROR (Status)) {
+        mBlockIsCompleted[Index] = TRUE;
+      }
+
+      ReleaseSpinLock (&mSpinLockList[Index]);
+    }
+  }
+}
+
+/**
+  Dispatch the block task to each AP in SMM mode.
+
+**/
+VOID
+EFIAPI
+MmDispatchBlockToAP (
+  VOID
+  )
+{
+  UINTN  Index;
+
+  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
+    if (Index != gMmst->CurrentlyExecutingCpu) {
+      gMmst->MmStartupThisAp (ParallelHashApExecute, Index, NULL);
+    }
+  }
+
+  return;
+}
+
+/**
+  Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
+  published December 2016.
+
+  @param[in]   Input            Pointer to the input message (X).
+  @param[in]   InputByteLen     The number(>0) of input bytes provided for the input data.
+  @param[in]   BlockSize        The size of each block (B).
+  @param[out]  Output           Pointer to the output buffer.
+  @param[in]   OutputByteLen    The desired number of output bytes (L).
+  @param[in]   Customization    Pointer to the customization string (S).
+  @param[in]   CustomByteLen    The length of the customization string in bytes.
+
+  @retval TRUE   ParallelHash256 digest computation succeeded.
+  @retval FALSE  ParallelHash256 digest computation failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ParallelHash256HashAll (
+  IN CONST VOID   *Input,
+  IN       UINTN  InputByteLen,
+  IN       UINTN  BlockSize,
+  OUT      VOID   *Output,
+  IN       UINTN  OutputByteLen,
+  IN CONST VOID   *Customization,
+  IN       UINTN  CustomByteLen
+  )
+{
+  UINT8    EncBufB[sizeof (UINTN)+1];
+  UINTN    EncSizeB;
+  UINT8    EncBufN[sizeof (UINTN)+1];
+  UINTN    EncSizeN;
+  UINT8    EncBufL[sizeof (UINTN)+1];
+  UINTN    EncSizeL;
+  UINTN    Index;
+  UINT8    *CombinedInput;
+  UINTN    CombinedInputSize;
+  BOOLEAN  AllCompleted;
+  UINTN    Offset;
+  BOOLEAN  ReturnValue;
+
+  if ((InputByteLen == 0) || (OutputByteLen == 0) || (BlockSize == 0)) {
+    return FALSE;
+  }
+
+  if ((Input == NULL) || (Output == NULL)) {
+    return FALSE;
+  }
+
+  if ((CustomByteLen != 0) && (Customization == NULL)) {
+    return FALSE;
+  }
+
+  mBlockSize = BlockSize;
+
+  //
+  // Calculate block number n.
+  //
+  mBlockNum = InputByteLen % mBlockSize == 0 ? InputByteLen / mBlockSize : InputByteLen / mBlockSize + 1;
+
+  //
+  // Set hash result size of each block in bytes.
+  //
+  mBlockResultSize = OutputByteLen;
+
+  //
+  // Encode B, n, L to string and record size.
+  //
+  EncSizeB = LeftEncode (EncBufB, mBlockSize);
+  EncSizeN = RightEncode (EncBufN, mBlockNum);
+  EncSizeL = RightEncode (EncBufL, OutputByteLen * CHAR_BIT);
+
+  //
+  // Allocate buffer for combined input (newX), Block completed flag and SpinLock.
+  //
+  CombinedInputSize = EncSizeB + EncSizeN + EncSizeL + mBlockNum * mBlockResultSize;
+  CombinedInput     = AllocateZeroPool (CombinedInputSize);
+  mBlockIsCompleted = AllocateZeroPool (mBlockNum * sizeof (BOOLEAN));
+  mSpinLockList     = AllocatePool (mBlockNum * sizeof (SPIN_LOCK));
+  if ((CombinedInput == NULL) || (mBlockIsCompleted == NULL) || (mSpinLockList == NULL)) {
+    ReturnValue = FALSE;
+    goto Exit;
+  }
+
+  //
+  // Fill LeftEncode(B).
+  //
+  CopyMem (CombinedInput, EncBufB, EncSizeB);
+
+  //
+  // Prepare for parallel hash.
+  //
+  mBlockHashResult = CombinedInput + EncSizeB;
+  mInput           = (UINT8 *)Input;
+  mLastBlockSize   = InputByteLen % mBlockSize == 0 ? mBlockSize : InputByteLen % mBlockSize;
+
+  //
+  // Initialize SpinLock for each result block.
+  //
+  for (Index = 0; Index < mBlockNum; Index++) {
+    InitializeSpinLock (&mSpinLockList[Index]);
+  }
+
+  //
+  // Dispatch blocklist to each AP.
+  //
+  if (gMmst != NULL) {
+    MmDispatchBlockToAP ();
+  }
+
+  //
+  // Wait until all block hash completed.
+  //
+  do {
+    AllCompleted = TRUE;
+    for (Index = 0; Index < mBlockNum; Index++) {
+      if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
+        if (!mBlockIsCompleted[Index]) {
+          AllCompleted = FALSE;
+          ReturnValue  = CShake256HashAll (
+                           mInput + Index * mBlockSize,
+                           (Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
+                           mBlockResultSize,
+                           NULL,
+                           0,
+                           NULL,
+                           0,
+                           mBlockHashResult + Index * mBlockResultSize
+                           );
+          if (ReturnValue) {
+            mBlockIsCompleted[Index] = TRUE;
+          }
+
+          ReleaseSpinLock (&mSpinLockList[Index]);
+          break;
+        }
+
+        ReleaseSpinLock (&mSpinLockList[Index]);
+      } else {
+        AllCompleted = FALSE;
+        break;
+      }
+    }
+  } while (!AllCompleted);
+
+  //
+  // Fill LeftEncode(n).
+  //
+  Offset = EncSizeB + mBlockNum * mBlockResultSize;
+  CopyMem (CombinedInput + Offset, EncBufN, EncSizeN);
+
+  //
+  // Fill LeftEncode(L).
+  //
+  Offset += EncSizeN;
+  CopyMem (CombinedInput + Offset, EncBufL, EncSizeL);
+
+  ReturnValue = CShake256HashAll (
+                  CombinedInput,
+                  CombinedInputSize,
+                  OutputByteLen,
+                  PARALLELHASH_CUSTOMIZATION,
+                  AsciiStrLen (PARALLELHASH_CUSTOMIZATION),
+                  Customization,
+                  CustomByteLen,
+                  Output
+                  );
+
+Exit:
+  ZeroMem (CombinedInput, CombinedInputSize);
+
+  if (CombinedInput != NULL) {
+    FreePool (CombinedInput);
+  }
+
+  if (mSpinLockList != NULL) {
+    FreePool ((VOID *)mSpinLockList);
+  }
+
+  if (mBlockIsCompleted != NULL) {
+    FreePool (mBlockIsCompleted);
+  }
+
+  return ReturnValue;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
new file mode 100644
index 000000000000..2bf89594def5
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
@@ -0,0 +1,40 @@
+/** @file
+  ParallelHash Implementation which does not provide real capabilities.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+
+/**
+  Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
+  published December 2016.
+
+  @param[in]   Input            Pointer to the input message (X).
+  @param[in]   InputByteLen     The number(>0) of input bytes provided for the input data.
+  @param[in]   BlockSize        The size of each block (B).
+  @param[out]  Output           Pointer to the output buffer.
+  @param[in]   OutputByteLen    The desired number of output bytes (L).
+  @param[in]   Customization    Pointer to the customization string (S).
+  @param[in]   CustomByteLen    The length of the customization string in bytes.
+
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ParallelHash256HashAll (
+  IN CONST VOID   *Input,
+  IN       UINTN  InputByteLen,
+  IN       UINTN  BlockSize,
+  OUT      VOID   *Output,
+  IN       UINTN  OutputByteLen,
+  IN CONST VOID   *Customization,
+  IN       UINTN  CustomByteLen
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
new file mode 100644
index 000000000000..6abafc3c00e6
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
@@ -0,0 +1,166 @@
+/** @file
+  SHA3 realted functions from OpenSSL.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+Licensed under the OpenSSL license (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+https://www.openssl.org/source/license.html
+**/
+
+#include "CryptParallelHash.h"
+
+/**
+  Keccak initial fuction.
+
+  Set up state with specified capacity.
+
+  @param[out] Context           Pointer to the context being initialized.
+  @param[in]  Pad               Delimited Suffix.
+  @param[in]  BlockSize         Size of context block.
+  @param[in]  MessageDigestLen  Size of message digest in bytes.
+
+  @retval 1  Initialize successfully.
+  @retval 0  Fail to initialize.
+**/
+UINT8
+EFIAPI
+KeccakInit (
+  OUT Keccak1600_Ctx  *Context,
+  IN  UINT8           Pad,
+  IN  UINTN           BlockSize,
+  IN  UINTN           MessageDigestLen
+  )
+{
+  if (BlockSize <= sizeof (Context->buf)) {
+    memset (Context->A, 0, sizeof (Context->A));
+
+    Context->num        = 0;
+    Context->block_size = BlockSize;
+    Context->md_size    = MessageDigestLen;
+    Context->pad        = Pad;
+
+    return 1;
+  }
+
+  return 0;
+}
+
+/**
+  Sha3 update fuction.
+
+  This function performs Sha3 digest on a data buffer of the specified size.
+  It can be called multiple times to compute the digest of long or discontinuous data streams.
+
+  @param[in,out] Context   Pointer to the Keccak context.
+  @param[in]     Data      Pointer to the buffer containing the data to be hashed.
+  @param[in]     DataSize  Size of Data buffer in bytes.
+
+  @retval 1  Update successfully.
+**/
+UINT8
+EFIAPI
+Sha3Update (
+  IN OUT Keccak1600_Ctx  *Context,
+  IN const VOID          *Data,
+  IN UINTN               DataSize
+  )
+{
+  const UINT8  *DataCopy;
+  UINTN        BlockSize;
+  UINTN        Num;
+  UINTN        Rem;
+
+  DataCopy  = Data;
+  BlockSize = (UINT8)(Context->block_size);
+
+  if (DataSize == 0) {
+    return 1;
+  }
+
+  if ((Num = Context->num) != 0) {
+    //
+    // process intermediate buffer
+    //
+    Rem = BlockSize - Num;
+
+    if (DataSize < Rem) {
+      memcpy (Context->buf + Num, DataCopy, DataSize);
+      Context->num += DataSize;
+      return 1;
+    }
+
+    //
+    // We have enough data to fill or overflow the intermediate
+    // buffer. So we append |Rem| bytes and process the block,
+    // leaving the rest for later processing.
+    //
+    memcpy (Context->buf + Num, DataCopy, Rem);
+    DataCopy += Rem;
+    DataSize -= Rem;
+    (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
+    Context->num = 0;
+    // Context->buf is processed, Context->num is guaranteed to be zero.
+  }
+
+  if (DataSize >= BlockSize) {
+    Rem = SHA3_absorb (Context->A, DataCopy, DataSize, BlockSize);
+  } else {
+    Rem = DataSize;
+  }
+
+  if (Rem > 0) {
+    memcpy (Context->buf, DataCopy + DataSize - Rem, Rem);
+    Context->num = Rem;
+  }
+
+  return 1;
+}
+
+/**
+  Completes computation of Sha3 message digest.
+
+  This function completes sha3 hash computation and retrieves the digest value into
+  the specified memory. After this function has been called, the keccak context cannot
+  be used again.
+
+  @param[in, out]  Context        Pointer to the keccak context.
+  @param[out]      MessageDigest  Pointer to a buffer that receives the message digest.
+
+  @retval 1   Meaasge digest computation succeeded.
+**/
+UINT8
+EFIAPI
+Sha3Final (
+  IN OUT Keccak1600_Ctx  *Context,
+  OUT    UINT8           *MessageDigest
+  )
+{
+  UINTN  BlockSize;
+  UINTN  Num;
+
+  BlockSize = Context->block_size;
+  Num       = Context->num;
+
+  if (Context->md_size == 0) {
+    return 1;
+  }
+
+  //
+  // Pad the data with 10*1. Note that |Num| can be |BlockSize - 1|
+  // in which case both byte operations below are performed on
+  // same byte.
+  //
+  memset (Context->buf + Num, 0, BlockSize - Num);
+  Context->buf[Num]            = Context->pad;
+  Context->buf[BlockSize - 1] |= 0x80;
+
+  (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
+
+  SHA3_squeeze (Context->A, MessageDigest, Context->md_size, BlockSize);
+
+  return 1;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
new file mode 100644
index 000000000000..12c46cfbcd59
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
@@ -0,0 +1,107 @@
+/** @file
+  Encode realted functions from Xkcp.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Copyright 2022 The eXtended Keccak Code Package (XKCP)
+https://github.com/XKCP/XKCP
+Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles Van Assche.
+Implementation by the designers, hereby denoted as "the implementer".
+For more information, feedback or questions, please refer to the Keccak Team website:
+https://keccak.team/
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+
+**/
+
+#include "CryptParallelHash.h"
+
+/**
+  Encode function from XKCP.
+
+  Encodes the input as a byte string in a way that can be unambiguously parsed
+  from the beginning of the string by inserting the length of the byte string
+  before the byte string representation of input.
+
+  @param[out] EncBuf  Result of left encode.
+  @param[in]  Value   Input of left encode.
+
+  @retval EncLen  Size of encode result in bytes.
+**/
+UINTN
+EFIAPI
+LeftEncode (
+  OUT UINT8  *EncBuf,
+  IN  UINTN  Value
+  )
+{
+  UINT32  BlockNum;
+  UINT32  EncLen;
+  UINT32  Index;
+  UINTN   ValueCopy;
+
+  for ( ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof (UINTN)); ++BlockNum, ValueCopy >>= 8 ) {
+    //
+    // Empty
+    //
+  }
+
+  if (BlockNum == 0) {
+    BlockNum = 1;
+  }
+
+  for (Index = 1; Index <= BlockNum; ++Index) {
+    EncBuf[Index] = (UINT8)(Value >> (8 * (BlockNum - Index)));
+  }
+
+  EncBuf[0] = (UINT8)BlockNum;
+  EncLen    = BlockNum + 1;
+
+  return EncLen;
+}
+
+/**
+  Encode function from XKCP.
+
+  Encodes the input as a byte string in a way that can be unambiguously parsed
+  from the end of the string by inserting the length of the byte string after
+  the byte string representation of input.
+
+  @param[out] EncBuf  Result of right encode.
+  @param[in]  Value   Input of right encode.
+
+  @retval EncLen  Size of encode result in bytes.
+**/
+UINTN
+EFIAPI
+RightEncode (
+  OUT UINT8  *EncBuf,
+  IN  UINTN  Value
+  )
+{
+  UINT32  BlockNum;
+  UINT32  EncLen;
+  UINT32  Index;
+  UINTN   ValueCopy;
+
+  for (ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof (UINTN)); ++BlockNum, ValueCopy >>= 8) {
+    //
+    // Empty
+    //
+  }
+
+  if (BlockNum == 0) {
+    BlockNum = 1;
+  }
+
+  for (Index = 1; Index <= BlockNum; ++Index) {
+    EncBuf[Index-1] = (UINT8)(Value >> (8 * (BlockNum-Index)));
+  }
+
+  EncBuf[BlockNum] = (UINT8)BlockNum;
+  EncLen           = BlockNum + 1;
+
+  return EncLen;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c b/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
new file mode 100644
index 000000000000..2bf89594def5
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
@@ -0,0 +1,40 @@
+/** @file
+  ParallelHash Implementation which does not provide real capabilities.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+
+/**
+  Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
+  published December 2016.
+
+  @param[in]   Input            Pointer to the input message (X).
+  @param[in]   InputByteLen     The number(>0) of input bytes provided for the input data.
+  @param[in]   BlockSize        The size of each block (B).
+  @param[out]  Output           Pointer to the output buffer.
+  @param[in]   OutputByteLen    The desired number of output bytes (L).
+  @param[in]   Customization    Pointer to the customization string (S).
+  @param[in]   CustomByteLen    The length of the customization string in bytes.
+
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ParallelHash256HashAll (
+  IN CONST VOID   *Input,
+  IN       UINTN  InputByteLen,
+  IN       UINTN  BlockSize,
+  OUT      VOID   *Output,
+  IN       UINTN  OutputByteLen,
+  IN CONST VOID   *Customization,
+  IN       UINTN  CustomByteLen
+  )
+{
+  ASSERT (FALSE);
+  return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
index c8df259ea963..8ee1b53cf957 100644
--- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
+++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
@@ -3,7 +3,7 @@
   Protocol/PPI.
 
   Copyright (C) Microsoft Corporation. All rights reserved.
-  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -870,6 +870,38 @@ Sha512HashAll (
   CALL_CRYPTO_SERVICE (Sha512HashAll, (Data, DataSize, HashValue), FALSE);
 }
 
+/**
+  Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
+  published December 2016.
+
+  @param[in]   Input            Pointer to the input message (X).
+  @param[in]   InputByteLen     The number(>0) of input bytes provided for the input data.
+  @param[in]   BlockSize        The size of each block (B).
+  @param[out]  Output           Pointer to the output buffer.
+  @param[in]   OutputByteLen    The desired number of output bytes (L).
+  @param[in]   Customization    Pointer to the customization string (S).
+  @param[in]   CustomByteLen    The length of the customization string in bytes.
+
+  @retval TRUE   ParallelHash256 digest computation succeeded.
+  @retval FALSE  ParallelHash256 digest computation failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ParallelHash256HashAll (
+  IN CONST VOID   *Input,
+  IN       UINTN  InputByteLen,
+  IN       UINTN  BlockSize,
+  OUT      VOID   *Output,
+  IN       UINTN  OutputByteLen,
+  IN CONST VOID   *Customization,
+  IN       UINTN  CustomByteLen
+  )
+{
+  CALL_CRYPTO_SERVICE (ParallelHash256HashAll, (Input, InputByteLen, BlockSize, Output, OutputByteLen, Customization, CustomByteLen), FALSE);
+}
+
 /**
   Retrieves the size, in bytes, of the context buffer required for SM3 hash operations.
 
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
new file mode 100644
index 000000000000..fb57e91a9f16
--- /dev/null
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
@@ -0,0 +1,145 @@
+/** @file
+  Application for Parallelhash Function Validation.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "TestBaseCryptLib.h"
+
+//
+// Parallelhash Test Sample common parameters.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN  OutputByteLen = 64;
+
+//
+// Parallelhash Test Sample #1 from NIST Special Publication 800-185.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  InputSample1[] = {
+  // input data of sample1.
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
+};
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample1ByteLen   = 24;        // Length of sample1 input data in bytes.
+GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID   *CustomizationSample1 = "";        // Customization string (S) of sample1.
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample1ByteLen  = 0;         // Customization string length of sample1 in bytes.
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample1      = 8;         // Block size of sample1.
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  ExpectOutputSample1[] = {
+  // Expected output data of sample1.
+  0xbc, 0x1e, 0xf1, 0x24, 0xda, 0x34, 0x49, 0x5e, 0x94, 0x8e, 0xad, 0x20, 0x7d, 0xd9, 0x84, 0x22,
+  0x35, 0xda, 0x43, 0x2d, 0x2b, 0xbc, 0x54, 0xb4, 0xc1, 0x10, 0xe6, 0x4c, 0x45, 0x11, 0x05, 0x53,
+  0x1b, 0x7f, 0x2a, 0x3e, 0x0c, 0xe0, 0x55, 0xc0, 0x28, 0x05, 0xe7, 0xc2, 0xde, 0x1f, 0xb7, 0x46,
+  0xaf, 0x97, 0xa1, 0xd0, 0x01, 0xf4, 0x3b, 0x82, 0x4e, 0x31, 0xb8, 0x76, 0x12, 0x41, 0x04, 0x29
+};
+
+//
+// Parallelhash Test Sample #2 from NIST Special Publication 800-185.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  *InputSample2         = InputSample1;               // Input of sample2 is same as sample1.
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample2ByteLen   = 24;                         // Length of sample2 input data in bytes.
+GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID   *CustomizationSample2 = "Parallel Data";            // Customization string (S) of sample2.
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample2ByteLen  = 13;                         // Customization string length of sample2 in bytes.
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample2      = 8;                          // Block size of sample2.
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  ExpectOutputSample2[] = {
+  // Expected output data of sample2.
+  0xcd, 0xf1, 0x52, 0x89, 0xb5, 0x4f, 0x62, 0x12, 0xb4, 0xbc, 0x27, 0x05, 0x28, 0xb4, 0x95, 0x26,
+  0x00, 0x6d, 0xd9, 0xb5, 0x4e, 0x2b, 0x6a, 0xdd, 0x1e, 0xf6, 0x90, 0x0d, 0xda, 0x39, 0x63, 0xbb,
+  0x33, 0xa7, 0x24, 0x91, 0xf2, 0x36, 0x96, 0x9c, 0xa8, 0xaf, 0xae, 0xa2, 0x9c, 0x68, 0x2d, 0x47,
+  0xa3, 0x93, 0xc0, 0x65, 0xb3, 0x8e, 0x29, 0xfa, 0xe6, 0x51, 0xa2, 0x09, 0x1c, 0x83, 0x31, 0x10
+};
+
+//
+// Parallelhash Test Sample #3 from NIST Special Publication 800-185.
+//
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  InputSample3[] = {
+  // input data of sample3.
+  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x11, 0x12, 0x13,
+  0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+  0x28, 0x29, 0x2a, 0x2b, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b,
+  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x50, 0x51, 0x52, 0x53,
+  0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b
+};
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample3ByteLen   = 72;                         // Length of sample3 input data in bytes.
+GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID   *CustomizationSample3 = "Parallel Data";            // Customization string (S) of sample3.
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample3ByteLen  = 13;                         // Customization string length of sample3 in bytes.
+GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample3      = 12;                         // Block size of sample3.
+GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  ExpectOutputSample3[] = {
+  // Expected output data of sample3.
+  0x69, 0xd0, 0xfc, 0xb7, 0x64, 0xea, 0x05, 0x5d, 0xd0, 0x93, 0x34, 0xbc, 0x60, 0x21, 0xcb, 0x7e,
+  0x4b, 0x61, 0x34, 0x8d, 0xff, 0x37, 0x5d, 0xa2, 0x62, 0x67, 0x1c, 0xde, 0xc3, 0xef, 0xfa, 0x8d,
+  0x1b, 0x45, 0x68, 0xa6, 0xcc, 0xe1, 0x6b, 0x1c, 0xad, 0x94, 0x6d, 0xdd, 0xe2, 0x7f, 0x6c, 0xe2,
+  0xb8, 0xde, 0xe4, 0xcd, 0x1b, 0x24, 0x85, 0x1e, 0xbf, 0x00, 0xeb, 0x90, 0xd4, 0x38, 0x13, 0xe9
+};
+
+UNIT_TEST_STATUS
+EFIAPI
+TestVerifyParallelHash256HashAll (
+  IN UNIT_TEST_CONTEXT  Context
+  )
+{
+  BOOLEAN  Status;
+  UINT8    Output[64];
+
+  //
+  // Test #1 using sample1.
+  //
+  Status = ParallelHash256HashAll (
+             InputSample1,
+             InputSample1ByteLen,
+             BlockSizeSample1,
+             Output,
+             OutputByteLen,
+             CustomizationSample1,
+             CustomSample1ByteLen
+             );
+  UT_ASSERT_TRUE (Status);
+
+  // Check the output with the expected output.
+  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample1, OutputByteLen);
+
+  //
+  // Test #2 using sample2.
+  //
+  Status = ParallelHash256HashAll (
+             InputSample2,
+             InputSample2ByteLen,
+             BlockSizeSample2,
+             Output,
+             OutputByteLen,
+             CustomizationSample2,
+             CustomSample2ByteLen
+             );
+  UT_ASSERT_TRUE (Status);
+
+  // Check the output with the expected output.
+  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample2, OutputByteLen);
+
+  //
+  // Test #3 using sample3.
+  //
+  Status = ParallelHash256HashAll (
+             InputSample3,
+             InputSample3ByteLen,
+             BlockSizeSample3,
+             Output,
+             OutputByteLen,
+             CustomizationSample3,
+             CustomSample3ByteLen
+             );
+  UT_ASSERT_TRUE (Status);
+
+  // Check the output with the expected output.
+  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3, OutputByteLen);
+
+  return EFI_SUCCESS;
+}
+
+TEST_DESC  mParallelhashTest[] = {
+  //
+  // -----Description------------------------------Class----------------------Function-----------------Pre---Post--Context
+  //
+  { "TestVerifyParallelHash256HashAll()", "CryptoPkg.BaseCryptLib.ParallelHash256HashAll", TestVerifyParallelHash256HashAll, NULL, NULL, NULL },
+};
+
+UINTN  mParallelhashTestNum = ARRAY_SIZE (mParallelhashTest);
diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml
index eeb388ae71c5..e21fafac1efe 100644
--- a/CryptoPkg/CryptoPkg.ci.yaml
+++ b/CryptoPkg/CryptoPkg.ci.yaml
@@ -2,7 +2,7 @@
 # CI configuration for CryptoPkg
 #
 # Copyright (c) Microsoft Corporation
-# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+# Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 ##
 {
@@ -34,6 +34,8 @@
             "Library/OpensslLib/rand_pool.c",
             # This has OpenSSL interfaces that aren't UEFI spec compliant
             "Library/Include/CrtLibSupport.h",
+            # This has OpenSSL interfaces that aren't UEFI spec compliant
+            "Library/BaseCryptLib/Hash/CryptParallelHash.h",
             # These directories contain auto-generated OpenSSL content
             "Library/OpensslLib",
             "Library/IntrinsicLib",
diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
index f4bc7c0d73d9..7d1499350a49 100644
--- a/CryptoPkg/Include/Library/BaseCryptLib.h
+++ b/CryptoPkg/Include/Library/BaseCryptLib.h
@@ -4,7 +4,7 @@
   primitives (Hash Serials, HMAC, RSA, Diffie-Hellman, etc) for UEFI security
   functionality enabling.
 
-Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -753,6 +753,35 @@ Sha512HashAll (
   OUT  UINT8       *HashValue
   );
 
+/**
+  Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
+  published December 2016.
+
+  @param[in]   Input            Pointer to the input message (X).
+  @param[in]   InputByteLen     The number(>0) of input bytes provided for the input data.
+  @param[in]   BlockSize        The size of each block (B).
+  @param[out]  Output           Pointer to the output buffer.
+  @param[in]   OutputByteLen    The desired number of output bytes (L).
+  @param[in]   Customization    Pointer to the customization string (S).
+  @param[in]   CustomByteLen    The length of the customization string in bytes.
+
+  @retval TRUE   ParallelHash256 digest computation succeeded.
+  @retval FALSE  ParallelHash256 digest computation failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+ParallelHash256HashAll (
+  IN CONST VOID   *Input,
+  IN       UINTN  InputByteLen,
+  IN       UINTN  BlockSize,
+  OUT      VOID   *Output,
+  IN       UINTN  OutputByteLen,
+  IN CONST VOID   *Customization,
+  IN       UINTN  CustomByteLen
+  );
+
 /**
   Retrieves the size, in bytes, of the context buffer required for SM3 hash operations.
 
diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
index 5186a54759ae..0b30a821bc16 100644
--- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
+++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
@@ -2,7 +2,7 @@
   Defines the PCD_CRYPTO_SERVICE_FAMILY_ENABLE structure associated with
   gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.
 
-  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
+  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
   SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -172,6 +172,12 @@ typedef struct {
     } Services;
     UINT32    Family;
   } Sha512;
+  union {
+    struct {
+      UINT8    HashAll : 1;
+    } Services;
+    UINT32    Family;
+  } ParallelHash;
   union {
     struct {
       UINT8    GetSubjectName             : 1;
diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
index 49703fa4c963..15cf3dab105c 100644
--- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
@@ -6,7 +6,7 @@
 #  This external input must be validated carefully to avoid security issues such as
 #  buffer overflow or integer overflow.
 #
-#  Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -34,6 +34,7 @@
   Hash/CryptSha256.c
   Hash/CryptSha512.c
   Hash/CryptSm3.c
+  Hash/CryptParallelHashNull.c
   Hmac/CryptHmacSha256.c
   Kdf/CryptHkdf.c
   Cipher/CryptAes.c
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
new file mode 100644
index 000000000000..fe08d4928e8d
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
@@ -0,0 +1,201 @@
+/** @file
+  ParallelHash related function and type declaration.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
+Licensed under the OpenSSL license (the "License").  You may not use
+this file except in compliance with the License.  You can obtain a copy
+in the file LICENSE in the source distribution or at
+https://www.openssl.org/source/license.html
+
+Copyright 2022 The eXtended Keccak Code Package (XKCP)
+https://github.com/XKCP/XKCP
+Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles Van Assche.
+Implementation by the designers, hereby denoted as "the implementer".
+For more information, feedback or questions, please refer to the Keccak Team website:
+https://keccak.team/
+To the extent possible under law, the implementer has waived all copyright
+and related or neighboring rights to the source code in this file.
+http://creativecommons.org/publicdomain/zero/1.0/
+**/
+
+#include "InternalCryptLib.h"
+
+#define KECCAK1600_WIDTH  1600
+
+//
+// This struct referring to m_sha3.c from opessl and modified its type name.
+//
+typedef struct {
+  uint64_t         A[5][5];
+  size_t           block_size;  /* cached ctx->digest->block_size */
+  size_t           md_size;     /* output length, variable in XOF */
+  size_t           num;         /* used bytes in below buffer */
+  unsigned char    buf[KECCAK1600_WIDTH / 8 - 32];
+  unsigned char    pad;
+} Keccak1600_Ctx;
+
+/**
+  SHA3_absorb can be called multiple times, but at each invocation
+  largest multiple of |r| out of |len| bytes are processed. Then
+  remaining amount of bytes is returned. This is done to spare caller
+  trouble of calculating the largest multiple of |r|. |r| can be viewed
+  as blocksize. It is commonly (1600 - 256*n)/8, e.g. 168, 136, 104,
+  72, but can also be (1600 - 448)/8 = 144. All this means that message
+  padding and intermediate sub-block buffering, byte- or bitwise, is
+  caller's responsibility.
+**/
+size_t
+SHA3_absorb (
+  uint64_t             A[5][5],
+  const unsigned char  *inp,
+  size_t               len,
+  size_t               r
+  );
+
+/**
+  SHA3_squeeze is called once at the end to generate |out| hash value
+  of |len| bytes.
+**/
+void
+SHA3_squeeze (
+  uint64_t       A[5][5],
+  unsigned char  *out,
+  size_t         len,
+  size_t         r
+  );
+
+/**
+  Encode function from XKCP.
+
+  Encodes the input as a byte string in a way that can be unambiguously parsed
+  from the beginning of the string by inserting the length of the byte string
+  before the byte string representation of input.
+
+  @param[out] EncBuf  Result of left encode.
+  @param[in]  Value   Input of left encode.
+
+  @retval EncLen  Size of encode result in bytes.
+**/
+UINTN
+EFIAPI
+LeftEncode (
+  OUT UINT8  *EncBuf,
+  IN  UINTN  Value
+  );
+
+/**
+  Encode function from XKCP.
+
+  Encodes the input as a byte string in a way that can be unambiguously parsed
+  from the end of the string by inserting the length of the byte string after
+  the byte string representation of input.
+
+  @param[out] EncBuf  Result of right encode.
+  @param[in]  Value   Input of right encode.
+
+  @retval EncLen  Size of encode result in bytes.
+**/
+UINTN
+EFIAPI
+RightEncode (
+  OUT UINT8  *EncBuf,
+  IN  UINTN  Value
+  );
+
+/**
+  Keccak initial fuction.
+
+  Set up state with specified capacity.
+
+  @param[out] Context           Pointer to the context being initialized.
+  @param[in]  Pad               Delimited Suffix.
+  @param[in]  BlockSize         Size of context block.
+  @param[in]  MessageDigestLen  Size of message digest in bytes.
+
+  @retval 1  Initialize successfully.
+  @retval 0  Fail to initialize.
+**/
+UINT8
+EFIAPI
+KeccakInit (
+  OUT Keccak1600_Ctx  *Context,
+  IN  UINT8           Pad,
+  IN  UINTN           BlockSize,
+  IN  UINTN           MessageDigstLen
+  );
+
+/**
+  Sha3 update fuction.
+
+  This function performs Sha3 digest on a data buffer of the specified size.
+  It can be called multiple times to compute the digest of long or discontinuous data streams.
+
+  @param[in,out] Context   Pointer to the Keccak context.
+  @param[in]     Data      Pointer to the buffer containing the data to be hashed.
+  @param[in]     DataSize  Size of Data buffer in bytes.
+
+  @retval 1  Update successfully.
+**/
+UINT8
+EFIAPI
+Sha3Update (
+  IN OUT Keccak1600_Ctx  *Context,
+  IN const VOID          *Data,
+  IN UINTN               DataSize
+  );
+
+/**
+  Completes computation of Sha3 message digest.
+
+  This function completes sha3 hash computation and retrieves the digest value into
+  the specified memory. After this function has been called, the keccak context cannot
+  be used again.
+
+  @param[in, out]  Context        Pointer to the keccak context.
+  @param[out]      MessageDigest  Pointer to a buffer that receives the message digest.
+
+  @retval 1   Meaasge digest computation succeeded.
+**/
+UINT8
+EFIAPI
+Sha3Final (
+  IN OUT Keccak1600_Ctx  *Context,
+  OUT    UINT8           *MessageDigest
+  );
+
+/**
+  Computes the CSHAKE-256 message digest of a input data buffer.
+
+  This function performs the CSHAKE-256 message digest of a given data buffer, and places
+  the digest value into the specified memory.
+
+  @param[in]   Data               Pointer to the buffer containing the data to be hashed.
+  @param[in]   DataSize           Size of Data buffer in bytes.
+  @param[in]   OutputLen          Size of output in bytes.
+  @param[in]   Name               Pointer to the function name string.
+  @param[in]   NameLen            Size of the function name in bytes.
+  @param[in]   Customization      Pointer to the customization string.
+  @param[in]   CustomizationLen   Size of the customization string in bytes.
+  @param[out]  HashValue          Pointer to a buffer that receives the CSHAKE-256 digest
+                                  value.
+
+  @retval TRUE   CSHAKE-256 digest computation succeeded.
+  @retval FALSE  CSHAKE-256 digest computation failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+CShake256HashAll (
+  IN   CONST VOID  *Data,
+  IN   UINTN       DataSize,
+  IN   UINTN       OutputLen,
+  IN   CONST VOID  *Name,
+  IN   UINTN       NameLen,
+  IN   CONST VOID  *Customization,
+  IN   UINTN       CustomizationLen,
+  OUT  UINT8       *HashValue
+  );
diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
index 0cab5f3ce36c..bf1563b06407 100644
--- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
@@ -13,7 +13,7 @@
 #  PEM handler functions, and pseudorandom number generator functions are not
 #  supported in this instance.
 #
-#  Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -40,6 +40,7 @@
   Hash/CryptSha256.c
   Hash/CryptSm3.c
   Hash/CryptSha512.c
+  Hash/CryptParallelHashNull.c
   Hmac/CryptHmacSha256.c
   Kdf/CryptHkdf.c
   Cipher/CryptAesNull.c
diff --git a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
index fdbb6edfd23e..6742da0be4fe 100644
--- a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
@@ -11,7 +11,7 @@
 #  functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, and
 #  authenticode signature verification functions are not supported in this instance.
 #
-#  Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -40,6 +40,7 @@
   Hash/CryptSha256.c
   Hash/CryptSm3.c
   Hash/CryptSha512.c
+  Hash/CryptParallelHashNull.c
   Hmac/CryptHmacSha256.c
   Kdf/CryptHkdf.c
   Cipher/CryptAes.c
diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
index e6470d7a2127..8f39517f78b7 100644
--- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
@@ -10,7 +10,7 @@
 #  RSA external functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, and
 #  authenticode signature verification functions are not supported in this instance.
 #
-#  Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
 ##
@@ -38,6 +38,10 @@
   Hash/CryptSha256.c
   Hash/CryptSm3.c
   Hash/CryptSha512.c
+  Hash/CryptSha3.c
+  Hash/CryptXkcp.c
+  Hash/CryptCShake256.c
+  Hash/CryptParallelHash.c
   Hmac/CryptHmacSha256.c
   Kdf/CryptHkdfNull.c
   Cipher/CryptAes.c
@@ -85,6 +89,8 @@
   OpensslLib
   IntrinsicLib
   PrintLib
+  MmServicesTableLib
+  SynchronizationLib
 
 #
 # Remove these [BuildOptions] after this library is cleaned up
diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
index faf959827b90..63d1d82d1914 100644
--- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
+++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
@@ -6,7 +6,7 @@
 #  This external input must be validated carefully to avoid security issues such as
 #  buffer overflow or integer overflow.
 #
-#  Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
 #  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
 #  SPDX-License-Identifier: BSD-2-Clause-Patent
 #
@@ -34,6 +34,7 @@
   Hash/CryptSha256Null.c
   Hash/CryptSha512Null.c
   Hash/CryptSm3Null.c
+  Hash/CryptParallelHashNull.c
   Hmac/CryptHmacSha256Null.c
   Kdf/CryptHkdfNull.c
   Cipher/CryptAesNull.c
diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h b/CryptoPkg/Library/Include/CrtLibSupport.h
index d257dca8fa9b..b76b140a7acf 100644
--- a/CryptoPkg/Library/Include/CrtLibSupport.h
+++ b/CryptoPkg/Library/Include/CrtLibSupport.h
@@ -2,7 +2,7 @@
   Root include file of C runtime library to support building the third-party
   cryptographic library.
 
-Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
 Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
@@ -111,6 +111,7 @@ typedef UINT8   u_char;
 typedef UINT32  uid_t;
 typedef UINT32  gid_t;
 typedef CHAR16  wchar_t;
+typedef UINT64  uint64_t;
 
 //
 // File operations are not required for EFI building,
diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h
index e378a8a8c60e..d51fc4a0e2cc 100644
--- a/CryptoPkg/Private/Protocol/Crypto.h
+++ b/CryptoPkg/Private/Protocol/Crypto.h
@@ -1905,6 +1905,35 @@ BOOLEAN
   OUT  UINT8       *HashValue
   );
 
+/**
+  Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
+  published December 2016.
+
+  @param[in]   Input            Pointer to the input message (X).
+  @param[in]   InputByteLen     The number(>0) of input bytes provided for the input data.
+  @param[in]   BlockSize        The size of each block (B).
+  @param[out]  Output           Pointer to the output buffer.
+  @param[in]   OutputByteLen    The desired number of output bytes (L).
+  @param[in]   Customization    Pointer to the customization string (S).
+  @param[in]   CustomByteLen    The length of the customization string in bytes.
+
+  @retval TRUE   ParallelHash256 digest computation succeeded.
+  @retval FALSE  ParallelHash256 digest computation failed.
+  @retval FALSE  This interface is not supported.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EDKII_CRYPTO_PARALLEL_HASH_ALL)(
+  IN CONST VOID   *Input,
+  IN       UINTN  InputByteLen,
+  IN       UINTN  BlockSize,
+  OUT      VOID   *Output,
+  IN       UINTN  OutputByteLen,
+  IN CONST VOID   *Customization,
+  IN       UINTN  CustomByteLen
+  );
+
 // ----------------------------------------------------------------------------
 // X509
 // ----------------------------------------------------------------------------
@@ -3560,6 +3589,8 @@ struct _EDKII_CRYPTO_PROTOCOL {
   EDKII_CRYPTO_SHA512_UPDATE                         Sha512Update;
   EDKII_CRYPTO_SHA512_FINAL                          Sha512Final;
   EDKII_CRYPTO_SHA512_HASH_ALL                       Sha512HashAll;
+  /// Parallel hash
+  EDKII_CRYPTO_PARALLEL_HASH_ALL                     ParallelHash256HashAll;
   /// X509
   EDKII_CRYPTO_X509_GET_SUBJECT_NAME                 X509GetSubjectName;
   EDKII_CRYPTO_X509_GET_COMMON_NAME                  X509GetCommonName;
diff --git a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
index ff0af36bcc80..ba6e1edb6015 100644
--- a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
+++ b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
@@ -21,6 +21,9 @@
 [LibraryClasses]
   OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
   BaseCryptLib|CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
+  MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib.inf
+  SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizationLib.inf
+  TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
 
 [LibraryClasses.AARCH64, LibraryClasses.ARM]
   RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
index 00c869265080..399db596c2d1 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
@@ -2,6 +2,7 @@
 # Host-based UnitTest for BaseCryptLib
 #
 # Copyright (c) Microsoft Corporation.<BR>
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 ##
 
@@ -35,6 +36,7 @@
   Pkcs7EkuTests.c
   OaepEncryptTests.c
   RsaPssTests.c
+  ParallelhashTests.c
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -45,3 +47,5 @@
   DebugLib
   BaseCryptLib
   UnitTestLib
+  MmServicesTableLib
+  SynchronizationLib
-- 
2.26.2.windows.1


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [edk2-devel] [PATCH v5 1/1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
  2022-03-09  8:44 [PATCH v5 1/1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib Li, Zhihao
@ 2022-03-14  5:50 ` Yao, Jiewen
  2022-03-17  2:43   ` Li, Zhihao
  0 siblings, 1 reply; 4+ messages in thread
From: Yao, Jiewen @ 2022-03-14  5:50 UTC (permalink / raw)
  To: devel@edk2.groups.io, Li, Zhihao
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Fu, Siyuan

Thanks. It is close to final version, but there are some compatibility issue need to be address.

1) Whenever you add a new field in the data structure, please add it at the end. Don't add them in the middle.
E.g. PCD_CRYPTO_SERVICE_FAMILY_ENABLE, _EDKII_CRYPTO_PROTOCOL

2) Whenever you add a new field for a data structure, please remember to increase the version.
E.g. EDKII_CRYPTO_VERSION


3) Please clarify if you have tested the CrytoLibOnProtocol version code.

Thank you
Yao Jiewen


> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Li, Zhihao
> Sent: Wednesday, March 9, 2022 4:44 PM
> To: devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>;
> Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>;
> Fu, Siyuan <siyuan.fu@intel.com>
> Subject: [edk2-devel] [PATCH v5 1/1] CryptoPkg: Add new hash algorithm
> ParallelHash256HashAll in BaseCryptLib.
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3596
> 
> Parallel hash function ParallelHash256HashAll, as defined in NIST's
> Special Publication 800-185, published December 2016. It utilizes
> multi-process to calculate the digest.
> 
> Some modifications to pass CI test.
> 
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> Cc: Guomin Jiang <guomin.jiang@intel.com>
> Cc: Siyuan Fu <siyuan.fu@intel.com>
> Cc: Zhihao Li <zhihao.li@intel.com>
> 
> Signed-off-by: Zhihao Li <zhihao.li@intel.com>
> ---
>  CryptoPkg/Driver/Crypto.c                                             |  36 ++-
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                  | 282
> ++++++++++++++++++++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c               | 278
> +++++++++++++++++++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c           |  40 +++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                       | 166
> ++++++++++++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                       | 107 ++++++++
>  CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c       |  40 +++
>  CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c                |  34 ++-
>  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c      | 145
> ++++++++++
>  CryptoPkg/CryptoPkg.ci.yaml                                           |   4 +-
>  CryptoPkg/Include/Library/BaseCryptLib.h                              |  31 ++-
>  CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h                  |   8 +-
>  CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf                       |   3 +-
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h               | 201
> ++++++++++++++
>  CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf                        |   3 +-
>  CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf                    |   3 +-
>  CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                        |   8 +-
>  CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf               |   3 +-
>  CryptoPkg/Library/Include/CrtLibSupport.h                             |   3 +-
>  CryptoPkg/Private/Protocol/Crypto.h                                   |  31 +++
>  CryptoPkg/Test/CryptoPkgHostUnitTest.dsc                              |   3 +
>  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf |   4 +
>  22 files changed, 1422 insertions(+), 11 deletions(-)
> 
> diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
> index d5d6aa8e5820..35312e0818a0 100644
> --- a/CryptoPkg/Driver/Crypto.c
> +++ b/CryptoPkg/Driver/Crypto.c
> @@ -3,7 +3,7 @@
>    from BaseCryptLib and TlsLib.
> 
> 
> 
>    Copyright (C) Microsoft Corporation. All rights reserved.
> 
> -  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -1314,6 +1314,38 @@ CryptoServiceSha512HashAll (
>    return CALL_BASECRYPTLIB (Sha512.Services.HashAll, Sha512HashAll, (Data,
> DataSize, HashValue), FALSE);
> 
>  }
> 
> 
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CryptoServiceParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  return CALL_BASECRYPTLIB (ParallelHash.Services.HashAll,
> ParallelHash256HashAll, (Input, InputByteLen, BlockSize, Output, OutputByteLen,
> Customization, CustomByteLen), FALSE);
> 
> +}
> 
> +
> 
>  /**
> 
>    Retrieves the size, in bytes, of the context buffer required for SM3 hash
> operations.
> 
> 
> 
> @@ -4590,6 +4622,8 @@ const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
>    CryptoServiceSha512Update,
> 
>    CryptoServiceSha512Final,
> 
>    CryptoServiceSha512HashAll,
> 
> +  /// Parallel hash
> 
> +  CryptoServiceParallelHash256HashAll,
> 
>    /// X509
> 
>    CryptoServiceX509GetSubjectName,
> 
>    CryptoServiceX509GetCommonName,
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> new file mode 100644
> index 000000000000..96e3c8eb02e1
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> @@ -0,0 +1,282 @@
> +/** @file
> 
> +  cSHAKE-256 Digest Wrapper Implementations.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "CryptParallelHash.h"
> 
> +
> 
> +#define  CSHAKE256_SECURITY_STRENGTH  256
> 
> +#define  CSHAKE256_RATE_IN_BYTES      136
> 
> +
> 
> +const CHAR8  mZeroPadding[CSHAKE256_RATE_IN_BYTES] = { 0 };
> 
> +
> 
> +/**
> 
> +  CShake256 initial function.
> 
> +
> 
> +  Initializes user-supplied memory pointed by CShake256Context as cSHAKE-256
> hash context for
> 
> +  subsequent use.
> 
> +
> 
> +  @param[out] CShake256Context  Pointer to cSHAKE-256 context being
> initialized.
> 
> +  @param[in]  OutputLen         The desired number of output length in bytes.
> 
> +  @param[in]  Name              Pointer to the function name string.
> 
> +  @param[in]  NameLen           The length of the function name in bytes.
> 
> +  @param[in]  Customization     Pointer to the customization string.
> 
> +  @param[in]  CustomizationLen  The length of the customization string in
> bytes.
> 
> +
> 
> +  @retval TRUE   cSHAKE-256 context initialization succeeded.
> 
> +  @retval FALSE  cSHAKE-256 context initialization failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256Init (
> 
> +  OUT  VOID        *CShake256Context,
> 
> +  IN   UINTN       OutputLen,
> 
> +  IN   CONST VOID  *Name,
> 
> +  IN   UINTN       NameLen,
> 
> +  IN   CONST VOID  *Customization,
> 
> +  IN   UINTN       CustomizationLen
> 
> +  )
> 
> +{
> 
> +  BOOLEAN  Status;
> 
> +  UINT8    EncBuf[sizeof (UINTN) + 1];
> 
> +  UINTN    EncLen;
> 
> +  UINTN    AbsorbLen;
> 
> +  UINTN    PadLen;
> 
> +
> 
> +  //
> 
> +  // Check input parameters.
> 
> +  //
> 
> +  if ((CShake256Context == NULL) || (OutputLen == 0) || ((NameLen != 0) &&
> (Name == NULL)) || ((CustomizationLen != 0) && (Customization == NULL))) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Initialize KECCAK context with pad value and block size.
> 
> +  //
> 
> +  if ((NameLen == 0) && (CustomizationLen == 0)) {
> 
> +    //
> 
> +    // When N and S are both empty strings, cSHAKE(X, L, N, S) is equivalent to
> 
> +    // SHAKE as defined in FIPS 202.
> 
> +    //
> 
> +    Status = (BOOLEAN)KeccakInit (
> 
> +                        (Keccak1600_Ctx *)CShake256Context,
> 
> +                        '\x1f',
> 
> +                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
> 
> +                        OutputLen
> 
> +                        );
> 
> +
> 
> +    return Status;
> 
> +  } else {
> 
> +    Status = (BOOLEAN)KeccakInit (
> 
> +                        (Keccak1600_Ctx *)CShake256Context,
> 
> +                        '\x04',
> 
> +                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
> 
> +                        OutputLen
> 
> +                        );
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen = 0;
> 
> +    //
> 
> +    // Absorb Absorb bytepad(.., rate).
> 
> +    //
> 
> +    EncLen = LeftEncode (EncBuf, CSHAKE256_RATE_IN_BYTES);
> 
> +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> EncBuf, EncLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += EncLen;
> 
> +
> 
> +    //
> 
> +    // Absorb encode_string(N).
> 
> +    //
> 
> +    EncLen = LeftEncode (EncBuf, NameLen * 8);
> 
> +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> EncBuf, EncLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += EncLen;
> 
> +    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> Name, NameLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += NameLen;
> 
> +
> 
> +    //
> 
> +    // Absorb encode_string(S).
> 
> +    //
> 
> +    EncLen = LeftEncode (EncBuf, CustomizationLen * 8);
> 
> +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> EncBuf, EncLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += EncLen;
> 
> +    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> Customization, CustomizationLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += CustomizationLen;
> 
> +
> 
> +    //
> 
> +    // Absorb zero padding up to rate.
> 
> +    //
> 
> +    PadLen = CSHAKE256_RATE_IN_BYTES - AbsorbLen %
> CSHAKE256_RATE_IN_BYTES;
> 
> +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> mZeroPadding, PadLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    return TRUE;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Digests the input data and updates cSHAKE-256 context.
> 
> +
> 
> +  This function performs cSHAKE-256 digest on a data buffer of the specified
> size.
> 
> +  It can be called multiple times to compute the digest of long or discontinuous
> data streams.
> 
> +  cSHAKE-256 context should be already correctly initialized by CShake256Init(),
> and should not be finalized
> 
> +  by CShake256Final(). Behavior with invalid context is undefined.
> 
> +
> 
> +  @param[in, out]  CShake256Context   Pointer to the cSHAKE-256 context.
> 
> +  @param[in]       Data               Pointer to the buffer containing the data to be
> hashed.
> 
> +  @param[in]       DataSize           Size of Data buffer in bytes.
> 
> +
> 
> +  @retval TRUE   cSHAKE-256 data digest succeeded.
> 
> +  @retval FALSE  cSHAKE-256 data digest failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256Update (
> 
> +  IN OUT  VOID        *CShake256Context,
> 
> +  IN      CONST VOID  *Data,
> 
> +  IN      UINTN       DataSize
> 
> +  )
> 
> +{
> 
> +  //
> 
> +  // Check input parameters.
> 
> +  //
> 
> +  if (CShake256Context == NULL) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Check invalid parameters, in case that only DataLength was checked in
> OpenSSL.
> 
> +  //
> 
> +  if ((Data == NULL) && (DataSize != 0)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  return (BOOLEAN)(Sha3Update ((Keccak1600_Ctx *)CShake256Context, Data,
> DataSize));
> 
> +}
> 
> +
> 
> +/**
> 
> +  Completes computation of the cSHAKE-256 digest value.
> 
> +
> 
> +  This function completes cSHAKE-256 hash computation and retrieves the
> digest value into
> 
> +  the specified memory. After this function has been called, the cSHAKE-256
> context cannot
> 
> +  be used again.
> 
> +  cSHAKE-256 context should be already correctly initialized by CShake256Init(),
> and should not be
> 
> +  finalized by CShake256Final(). Behavior with invalid cSHAKE-256 context is
> undefined.
> 
> +
> 
> +  @param[in, out]  CShake256Context  Pointer to the cSHAKE-256 context.
> 
> +  @param[out]      HashValue         Pointer to a buffer that receives the cSHAKE-
> 256 digest
> 
> +                                     value.
> 
> +
> 
> +  @retval TRUE   cSHAKE-256 digest computation succeeded.
> 
> +  @retval FALSE  cSHAKE-256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256Final (
> 
> +  IN OUT  VOID   *CShake256Context,
> 
> +  OUT     UINT8  *HashValue
> 
> +  )
> 
> +{
> 
> +  //
> 
> +  // Check input parameters.
> 
> +  //
> 
> +  if ((CShake256Context == NULL) || (HashValue == NULL)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // cSHAKE-256 Hash Finalization.
> 
> +  //
> 
> +  return (BOOLEAN)(Sha3Final ((Keccak1600_Ctx *)CShake256Context,
> HashValue));
> 
> +}
> 
> +
> 
> +/**
> 
> +  Computes the CSHAKE-256 message digest of a input data buffer.
> 
> +
> 
> +  This function performs the CSHAKE-256 message digest of a given data buffer,
> and places
> 
> +  the digest value into the specified memory.
> 
> +
> 
> +  @param[in]   Data               Pointer to the buffer containing the data to be
> hashed.
> 
> +  @param[in]   DataSize           Size of Data buffer in bytes.
> 
> +  @param[in]   OutputLen          Size of output in bytes.
> 
> +  @param[in]   Name               Pointer to the function name string.
> 
> +  @param[in]   NameLen            Size of the function name in bytes.
> 
> +  @param[in]   Customization      Pointer to the customization string.
> 
> +  @param[in]   CustomizationLen   Size of the customization string in bytes.
> 
> +  @param[out]  HashValue          Pointer to a buffer that receives the CSHAKE-
> 256 digest
> 
> +                                  value.
> 
> +
> 
> +  @retval TRUE   CSHAKE-256 digest computation succeeded.
> 
> +  @retval FALSE  CSHAKE-256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256HashAll (
> 
> +  IN   CONST VOID  *Data,
> 
> +  IN   UINTN       DataSize,
> 
> +  IN   UINTN       OutputLen,
> 
> +  IN   CONST VOID  *Name,
> 
> +  IN   UINTN       NameLen,
> 
> +  IN   CONST VOID  *Customization,
> 
> +  IN   UINTN       CustomizationLen,
> 
> +  OUT  UINT8       *HashValue
> 
> +  )
> 
> +{
> 
> +  BOOLEAN         Status;
> 
> +  Keccak1600_Ctx  Ctx;
> 
> +
> 
> +  //
> 
> +  // Check input parameters.
> 
> +  //
> 
> +  if (HashValue == NULL) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  if ((Data == NULL) && (DataSize != 0)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  Status = CShake256Init (&Ctx, OutputLen, Name, NameLen, Customization,
> CustomizationLen);
> 
> +  if (!Status) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  Status = CShake256Update (&Ctx, Data, DataSize);
> 
> +  if (!Status) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  return CShake256Final (&Ctx, HashValue);
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> new file mode 100644
> index 000000000000..f7ce9dbf523e
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> @@ -0,0 +1,278 @@
> +/** @file
> 
> +  ParallelHash Implementation.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "CryptParallelHash.h"
> 
> +#include <Library/MmServicesTableLib.h>
> 
> +#include <Library/SynchronizationLib.h>
> 
> +
> 
> +#define PARALLELHASH_CUSTOMIZATION  "ParallelHash"
> 
> +
> 
> +UINTN      mBlockNum;
> 
> +UINTN      mBlockSize;
> 
> +UINTN      mLastBlockSize;
> 
> +UINT8      *mInput;
> 
> +UINTN      mBlockResultSize;
> 
> +UINT8      *mBlockHashResult;
> 
> +BOOLEAN    *mBlockIsCompleted;
> 
> +SPIN_LOCK  *mSpinLockList;
> 
> +
> 
> +/**
> 
> +  Complete computation of digest of each block.
> 
> +
> 
> +  Each AP perform the function called by BSP.
> 
> +
> 
> +  @param[in] ProcedureArgument Argument of the procedure.
> 
> +**/
> 
> +VOID
> 
> +EFIAPI
> 
> +ParallelHashApExecute (
> 
> +  IN VOID  *ProcedureArgument
> 
> +  )
> 
> +{
> 
> +  UINTN    Index;
> 
> +  BOOLEAN  Status;
> 
> +
> 
> +  for (Index = 0; Index < mBlockNum; Index++) {
> 
> +    if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
> 
> +      //
> 
> +      // Completed, try next one.
> 
> +      //
> 
> +      if (mBlockIsCompleted[Index]) {
> 
> +        ReleaseSpinLock (&mSpinLockList[Index]);
> 
> +        continue;
> 
> +      }
> 
> +
> 
> +      //
> 
> +      // Calculate CShake256 for this block.
> 
> +      //
> 
> +      Status = CShake256HashAll (
> 
> +                 mInput + Index * mBlockSize,
> 
> +                 (Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
> 
> +                 mBlockResultSize,
> 
> +                 NULL,
> 
> +                 0,
> 
> +                 NULL,
> 
> +                 0,
> 
> +                 mBlockHashResult + Index * mBlockResultSize
> 
> +                 );
> 
> +      if (!EFI_ERROR (Status)) {
> 
> +        mBlockIsCompleted[Index] = TRUE;
> 
> +      }
> 
> +
> 
> +      ReleaseSpinLock (&mSpinLockList[Index]);
> 
> +    }
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Dispatch the block task to each AP in SMM mode.
> 
> +
> 
> +**/
> 
> +VOID
> 
> +EFIAPI
> 
> +MmDispatchBlockToAP (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  UINTN  Index;
> 
> +
> 
> +  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
> 
> +    if (Index != gMmst->CurrentlyExecutingCpu) {
> 
> +      gMmst->MmStartupThisAp (ParallelHashApExecute, Index, NULL);
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  UINT8    EncBufB[sizeof (UINTN)+1];
> 
> +  UINTN    EncSizeB;
> 
> +  UINT8    EncBufN[sizeof (UINTN)+1];
> 
> +  UINTN    EncSizeN;
> 
> +  UINT8    EncBufL[sizeof (UINTN)+1];
> 
> +  UINTN    EncSizeL;
> 
> +  UINTN    Index;
> 
> +  UINT8    *CombinedInput;
> 
> +  UINTN    CombinedInputSize;
> 
> +  BOOLEAN  AllCompleted;
> 
> +  UINTN    Offset;
> 
> +  BOOLEAN  ReturnValue;
> 
> +
> 
> +  if ((InputByteLen == 0) || (OutputByteLen == 0) || (BlockSize == 0)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  if ((Input == NULL) || (Output == NULL)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  if ((CustomByteLen != 0) && (Customization == NULL)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  mBlockSize = BlockSize;
> 
> +
> 
> +  //
> 
> +  // Calculate block number n.
> 
> +  //
> 
> +  mBlockNum = InputByteLen % mBlockSize == 0 ? InputByteLen / mBlockSize :
> InputByteLen / mBlockSize + 1;
> 
> +
> 
> +  //
> 
> +  // Set hash result size of each block in bytes.
> 
> +  //
> 
> +  mBlockResultSize = OutputByteLen;
> 
> +
> 
> +  //
> 
> +  // Encode B, n, L to string and record size.
> 
> +  //
> 
> +  EncSizeB = LeftEncode (EncBufB, mBlockSize);
> 
> +  EncSizeN = RightEncode (EncBufN, mBlockNum);
> 
> +  EncSizeL = RightEncode (EncBufL, OutputByteLen * CHAR_BIT);
> 
> +
> 
> +  //
> 
> +  // Allocate buffer for combined input (newX), Block completed flag and
> SpinLock.
> 
> +  //
> 
> +  CombinedInputSize = EncSizeB + EncSizeN + EncSizeL + mBlockNum *
> mBlockResultSize;
> 
> +  CombinedInput     = AllocateZeroPool (CombinedInputSize);
> 
> +  mBlockIsCompleted = AllocateZeroPool (mBlockNum * sizeof (BOOLEAN));
> 
> +  mSpinLockList     = AllocatePool (mBlockNum * sizeof (SPIN_LOCK));
> 
> +  if ((CombinedInput == NULL) || (mBlockIsCompleted == NULL) ||
> (mSpinLockList == NULL)) {
> 
> +    ReturnValue = FALSE;
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Fill LeftEncode(B).
> 
> +  //
> 
> +  CopyMem (CombinedInput, EncBufB, EncSizeB);
> 
> +
> 
> +  //
> 
> +  // Prepare for parallel hash.
> 
> +  //
> 
> +  mBlockHashResult = CombinedInput + EncSizeB;
> 
> +  mInput           = (UINT8 *)Input;
> 
> +  mLastBlockSize   = InputByteLen % mBlockSize == 0 ? mBlockSize :
> InputByteLen % mBlockSize;
> 
> +
> 
> +  //
> 
> +  // Initialize SpinLock for each result block.
> 
> +  //
> 
> +  for (Index = 0; Index < mBlockNum; Index++) {
> 
> +    InitializeSpinLock (&mSpinLockList[Index]);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Dispatch blocklist to each AP.
> 
> +  //
> 
> +  if (gMmst != NULL) {
> 
> +    MmDispatchBlockToAP ();
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Wait until all block hash completed.
> 
> +  //
> 
> +  do {
> 
> +    AllCompleted = TRUE;
> 
> +    for (Index = 0; Index < mBlockNum; Index++) {
> 
> +      if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
> 
> +        if (!mBlockIsCompleted[Index]) {
> 
> +          AllCompleted = FALSE;
> 
> +          ReturnValue  = CShake256HashAll (
> 
> +                           mInput + Index * mBlockSize,
> 
> +                           (Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
> 
> +                           mBlockResultSize,
> 
> +                           NULL,
> 
> +                           0,
> 
> +                           NULL,
> 
> +                           0,
> 
> +                           mBlockHashResult + Index * mBlockResultSize
> 
> +                           );
> 
> +          if (ReturnValue) {
> 
> +            mBlockIsCompleted[Index] = TRUE;
> 
> +          }
> 
> +
> 
> +          ReleaseSpinLock (&mSpinLockList[Index]);
> 
> +          break;
> 
> +        }
> 
> +
> 
> +        ReleaseSpinLock (&mSpinLockList[Index]);
> 
> +      } else {
> 
> +        AllCompleted = FALSE;
> 
> +        break;
> 
> +      }
> 
> +    }
> 
> +  } while (!AllCompleted);
> 
> +
> 
> +  //
> 
> +  // Fill LeftEncode(n).
> 
> +  //
> 
> +  Offset = EncSizeB + mBlockNum * mBlockResultSize;
> 
> +  CopyMem (CombinedInput + Offset, EncBufN, EncSizeN);
> 
> +
> 
> +  //
> 
> +  // Fill LeftEncode(L).
> 
> +  //
> 
> +  Offset += EncSizeN;
> 
> +  CopyMem (CombinedInput + Offset, EncBufL, EncSizeL);
> 
> +
> 
> +  ReturnValue = CShake256HashAll (
> 
> +                  CombinedInput,
> 
> +                  CombinedInputSize,
> 
> +                  OutputByteLen,
> 
> +                  PARALLELHASH_CUSTOMIZATION,
> 
> +                  AsciiStrLen (PARALLELHASH_CUSTOMIZATION),
> 
> +                  Customization,
> 
> +                  CustomByteLen,
> 
> +                  Output
> 
> +                  );
> 
> +
> 
> +Exit:
> 
> +  ZeroMem (CombinedInput, CombinedInputSize);
> 
> +
> 
> +  if (CombinedInput != NULL) {
> 
> +    FreePool (CombinedInput);
> 
> +  }
> 
> +
> 
> +  if (mSpinLockList != NULL) {
> 
> +    FreePool ((VOID *)mSpinLockList);
> 
> +  }
> 
> +
> 
> +  if (mBlockIsCompleted != NULL) {
> 
> +    FreePool (mBlockIsCompleted);
> 
> +  }
> 
> +
> 
> +  return ReturnValue;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
> new file mode 100644
> index 000000000000..2bf89594def5
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
> @@ -0,0 +1,40 @@
> +/** @file
> 
> +  ParallelHash Implementation which does not provide real capabilities.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "InternalCryptLib.h"
> 
> +
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  ASSERT (FALSE);
> 
> +  return FALSE;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> new file mode 100644
> index 000000000000..6abafc3c00e6
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> @@ -0,0 +1,166 @@
> +/** @file
> 
> +  SHA3 realted functions from OpenSSL.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
> 
> +Licensed under the OpenSSL license (the "License").  You may not use
> 
> +this file except in compliance with the License.  You can obtain a copy
> 
> +in the file LICENSE in the source distribution or at
> 
> +https://www.openssl.org/source/license.html
> 
> +**/
> 
> +
> 
> +#include "CryptParallelHash.h"
> 
> +
> 
> +/**
> 
> +  Keccak initial fuction.
> 
> +
> 
> +  Set up state with specified capacity.
> 
> +
> 
> +  @param[out] Context           Pointer to the context being initialized.
> 
> +  @param[in]  Pad               Delimited Suffix.
> 
> +  @param[in]  BlockSize         Size of context block.
> 
> +  @param[in]  MessageDigestLen  Size of message digest in bytes.
> 
> +
> 
> +  @retval 1  Initialize successfully.
> 
> +  @retval 0  Fail to initialize.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +KeccakInit (
> 
> +  OUT Keccak1600_Ctx  *Context,
> 
> +  IN  UINT8           Pad,
> 
> +  IN  UINTN           BlockSize,
> 
> +  IN  UINTN           MessageDigestLen
> 
> +  )
> 
> +{
> 
> +  if (BlockSize <= sizeof (Context->buf)) {
> 
> +    memset (Context->A, 0, sizeof (Context->A));
> 
> +
> 
> +    Context->num        = 0;
> 
> +    Context->block_size = BlockSize;
> 
> +    Context->md_size    = MessageDigestLen;
> 
> +    Context->pad        = Pad;
> 
> +
> 
> +    return 1;
> 
> +  }
> 
> +
> 
> +  return 0;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Sha3 update fuction.
> 
> +
> 
> +  This function performs Sha3 digest on a data buffer of the specified size.
> 
> +  It can be called multiple times to compute the digest of long or discontinuous
> data streams.
> 
> +
> 
> +  @param[in,out] Context   Pointer to the Keccak context.
> 
> +  @param[in]     Data      Pointer to the buffer containing the data to be hashed.
> 
> +  @param[in]     DataSize  Size of Data buffer in bytes.
> 
> +
> 
> +  @retval 1  Update successfully.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +Sha3Update (
> 
> +  IN OUT Keccak1600_Ctx  *Context,
> 
> +  IN const VOID          *Data,
> 
> +  IN UINTN               DataSize
> 
> +  )
> 
> +{
> 
> +  const UINT8  *DataCopy;
> 
> +  UINTN        BlockSize;
> 
> +  UINTN        Num;
> 
> +  UINTN        Rem;
> 
> +
> 
> +  DataCopy  = Data;
> 
> +  BlockSize = (UINT8)(Context->block_size);
> 
> +
> 
> +  if (DataSize == 0) {
> 
> +    return 1;
> 
> +  }
> 
> +
> 
> +  if ((Num = Context->num) != 0) {
> 
> +    //
> 
> +    // process intermediate buffer
> 
> +    //
> 
> +    Rem = BlockSize - Num;
> 
> +
> 
> +    if (DataSize < Rem) {
> 
> +      memcpy (Context->buf + Num, DataCopy, DataSize);
> 
> +      Context->num += DataSize;
> 
> +      return 1;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // We have enough data to fill or overflow the intermediate
> 
> +    // buffer. So we append |Rem| bytes and process the block,
> 
> +    // leaving the rest for later processing.
> 
> +    //
> 
> +    memcpy (Context->buf + Num, DataCopy, Rem);
> 
> +    DataCopy += Rem;
> 
> +    DataSize -= Rem;
> 
> +    (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
> 
> +    Context->num = 0;
> 
> +    // Context->buf is processed, Context->num is guaranteed to be zero.
> 
> +  }
> 
> +
> 
> +  if (DataSize >= BlockSize) {
> 
> +    Rem = SHA3_absorb (Context->A, DataCopy, DataSize, BlockSize);
> 
> +  } else {
> 
> +    Rem = DataSize;
> 
> +  }
> 
> +
> 
> +  if (Rem > 0) {
> 
> +    memcpy (Context->buf, DataCopy + DataSize - Rem, Rem);
> 
> +    Context->num = Rem;
> 
> +  }
> 
> +
> 
> +  return 1;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Completes computation of Sha3 message digest.
> 
> +
> 
> +  This function completes sha3 hash computation and retrieves the digest value
> into
> 
> +  the specified memory. After this function has been called, the keccak context
> cannot
> 
> +  be used again.
> 
> +
> 
> +  @param[in, out]  Context        Pointer to the keccak context.
> 
> +  @param[out]      MessageDigest  Pointer to a buffer that receives the
> message digest.
> 
> +
> 
> +  @retval 1   Meaasge digest computation succeeded.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +Sha3Final (
> 
> +  IN OUT Keccak1600_Ctx  *Context,
> 
> +  OUT    UINT8           *MessageDigest
> 
> +  )
> 
> +{
> 
> +  UINTN  BlockSize;
> 
> +  UINTN  Num;
> 
> +
> 
> +  BlockSize = Context->block_size;
> 
> +  Num       = Context->num;
> 
> +
> 
> +  if (Context->md_size == 0) {
> 
> +    return 1;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Pad the data with 10*1. Note that |Num| can be |BlockSize - 1|
> 
> +  // in which case both byte operations below are performed on
> 
> +  // same byte.
> 
> +  //
> 
> +  memset (Context->buf + Num, 0, BlockSize - Num);
> 
> +  Context->buf[Num]            = Context->pad;
> 
> +  Context->buf[BlockSize - 1] |= 0x80;
> 
> +
> 
> +  (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
> 
> +
> 
> +  SHA3_squeeze (Context->A, MessageDigest, Context->md_size, BlockSize);
> 
> +
> 
> +  return 1;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> new file mode 100644
> index 000000000000..12c46cfbcd59
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> @@ -0,0 +1,107 @@
> +/** @file
> 
> +  Encode realted functions from Xkcp.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +Copyright 2022 The eXtended Keccak Code Package (XKCP)
> 
> +https://github.com/XKCP/XKCP
> 
> +Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles
> Van Assche.
> 
> +Implementation by the designers, hereby denoted as "the implementer".
> 
> +For more information, feedback or questions, please refer to the Keccak Team
> website:
> 
> +https://keccak.team/
> 
> +To the extent possible under law, the implementer has waived all copyright
> 
> +and related or neighboring rights to the source code in this file.
> 
> +http://creativecommons.org/publicdomain/zero/1.0/
> 
> +
> 
> +**/
> 
> +
> 
> +#include "CryptParallelHash.h"
> 
> +
> 
> +/**
> 
> +  Encode function from XKCP.
> 
> +
> 
> +  Encodes the input as a byte string in a way that can be unambiguously parsed
> 
> +  from the beginning of the string by inserting the length of the byte string
> 
> +  before the byte string representation of input.
> 
> +
> 
> +  @param[out] EncBuf  Result of left encode.
> 
> +  @param[in]  Value   Input of left encode.
> 
> +
> 
> +  @retval EncLen  Size of encode result in bytes.
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +LeftEncode (
> 
> +  OUT UINT8  *EncBuf,
> 
> +  IN  UINTN  Value
> 
> +  )
> 
> +{
> 
> +  UINT32  BlockNum;
> 
> +  UINT32  EncLen;
> 
> +  UINT32  Index;
> 
> +  UINTN   ValueCopy;
> 
> +
> 
> +  for ( ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof
> (UINTN)); ++BlockNum, ValueCopy >>= 8 ) {
> 
> +    //
> 
> +    // Empty
> 
> +    //
> 
> +  }
> 
> +
> 
> +  if (BlockNum == 0) {
> 
> +    BlockNum = 1;
> 
> +  }
> 
> +
> 
> +  for (Index = 1; Index <= BlockNum; ++Index) {
> 
> +    EncBuf[Index] = (UINT8)(Value >> (8 * (BlockNum - Index)));
> 
> +  }
> 
> +
> 
> +  EncBuf[0] = (UINT8)BlockNum;
> 
> +  EncLen    = BlockNum + 1;
> 
> +
> 
> +  return EncLen;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Encode function from XKCP.
> 
> +
> 
> +  Encodes the input as a byte string in a way that can be unambiguously parsed
> 
> +  from the end of the string by inserting the length of the byte string after
> 
> +  the byte string representation of input.
> 
> +
> 
> +  @param[out] EncBuf  Result of right encode.
> 
> +  @param[in]  Value   Input of right encode.
> 
> +
> 
> +  @retval EncLen  Size of encode result in bytes.
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +RightEncode (
> 
> +  OUT UINT8  *EncBuf,
> 
> +  IN  UINTN  Value
> 
> +  )
> 
> +{
> 
> +  UINT32  BlockNum;
> 
> +  UINT32  EncLen;
> 
> +  UINT32  Index;
> 
> +  UINTN   ValueCopy;
> 
> +
> 
> +  for (ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof
> (UINTN)); ++BlockNum, ValueCopy >>= 8) {
> 
> +    //
> 
> +    // Empty
> 
> +    //
> 
> +  }
> 
> +
> 
> +  if (BlockNum == 0) {
> 
> +    BlockNum = 1;
> 
> +  }
> 
> +
> 
> +  for (Index = 1; Index <= BlockNum; ++Index) {
> 
> +    EncBuf[Index-1] = (UINT8)(Value >> (8 * (BlockNum-Index)));
> 
> +  }
> 
> +
> 
> +  EncBuf[BlockNum] = (UINT8)BlockNum;
> 
> +  EncLen           = BlockNum + 1;
> 
> +
> 
> +  return EncLen;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
> b/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
> new file mode 100644
> index 000000000000..2bf89594def5
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
> @@ -0,0 +1,40 @@
> +/** @file
> 
> +  ParallelHash Implementation which does not provide real capabilities.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "InternalCryptLib.h"
> 
> +
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  ASSERT (FALSE);
> 
> +  return FALSE;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> index c8df259ea963..8ee1b53cf957 100644
> --- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> +++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> @@ -3,7 +3,7 @@
>    Protocol/PPI.
> 
> 
> 
>    Copyright (C) Microsoft Corporation. All rights reserved.
> 
> -  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -870,6 +870,38 @@ Sha512HashAll (
>    CALL_CRYPTO_SERVICE (Sha512HashAll, (Data, DataSize, HashValue), FALSE);
> 
>  }
> 
> 
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  CALL_CRYPTO_SERVICE (ParallelHash256HashAll, (Input, InputByteLen,
> BlockSize, Output, OutputByteLen, Customization, CustomByteLen), FALSE);
> 
> +}
> 
> +
> 
>  /**
> 
>    Retrieves the size, in bytes, of the context buffer required for SM3 hash
> operations.
> 
> 
> 
> diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> new file mode 100644
> index 000000000000..fb57e91a9f16
> --- /dev/null
> +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> @@ -0,0 +1,145 @@
> +/** @file
> 
> +  Application for Parallelhash Function Validation.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "TestBaseCryptLib.h"
> 
> +
> 
> +//
> 
> +// Parallelhash Test Sample common parameters.
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN  OutputByteLen = 64;
> 
> +
> 
> +//
> 
> +// Parallelhash Test Sample #1 from NIST Special Publication 800-185.
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  InputSample1[] = {
> 
> +  // input data of sample1.
> 
> +  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14,
> 0x15, 0x16, 0x17,
> 
> +  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
> 
> +};
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample1ByteLen   = 24;
> // Length of sample1 input data in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID   *CustomizationSample1
> = "";        // Customization string (S) of sample1.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample1ByteLen  = 0;
> // Customization string length of sample1 in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample1      = 8;
> // Block size of sample1.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  ExpectOutputSample1[]
> = {
> 
> +  // Expected output data of sample1.
> 
> +  0xbc, 0x1e, 0xf1, 0x24, 0xda, 0x34, 0x49, 0x5e, 0x94, 0x8e, 0xad, 0x20, 0x7d,
> 0xd9, 0x84, 0x22,
> 
> +  0x35, 0xda, 0x43, 0x2d, 0x2b, 0xbc, 0x54, 0xb4, 0xc1, 0x10, 0xe6, 0x4c, 0x45,
> 0x11, 0x05, 0x53,
> 
> +  0x1b, 0x7f, 0x2a, 0x3e, 0x0c, 0xe0, 0x55, 0xc0, 0x28, 0x05, 0xe7, 0xc2, 0xde,
> 0x1f, 0xb7, 0x46,
> 
> +  0xaf, 0x97, 0xa1, 0xd0, 0x01, 0xf4, 0x3b, 0x82, 0x4e, 0x31, 0xb8, 0x76, 0x12,
> 0x41, 0x04, 0x29
> 
> +};
> 
> +
> 
> +//
> 
> +// Parallelhash Test Sample #2 from NIST Special Publication 800-185.
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  *InputSample2         =
> InputSample1;               // Input of sample2 is same as sample1.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample2ByteLen   = 24;
> // Length of sample2 input data in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID   *CustomizationSample2
> = "Parallel Data";            // Customization string (S) of sample2.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample2ByteLen  =
> 13;                         // Customization string length of sample2 in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample2      = 8;
> // Block size of sample2.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  ExpectOutputSample2[]
> = {
> 
> +  // Expected output data of sample2.
> 
> +  0xcd, 0xf1, 0x52, 0x89, 0xb5, 0x4f, 0x62, 0x12, 0xb4, 0xbc, 0x27, 0x05, 0x28,
> 0xb4, 0x95, 0x26,
> 
> +  0x00, 0x6d, 0xd9, 0xb5, 0x4e, 0x2b, 0x6a, 0xdd, 0x1e, 0xf6, 0x90, 0x0d, 0xda,
> 0x39, 0x63, 0xbb,
> 
> +  0x33, 0xa7, 0x24, 0x91, 0xf2, 0x36, 0x96, 0x9c, 0xa8, 0xaf, 0xae, 0xa2, 0x9c,
> 0x68, 0x2d, 0x47,
> 
> +  0xa3, 0x93, 0xc0, 0x65, 0xb3, 0x8e, 0x29, 0xfa, 0xe6, 0x51, 0xa2, 0x09, 0x1c,
> 0x83, 0x31, 0x10
> 
> +};
> 
> +
> 
> +//
> 
> +// Parallelhash Test Sample #3 from NIST Special Publication 800-185.
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  InputSample3[] = {
> 
> +  // input data of sample3.
> 
> +  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10,
> 0x11, 0x12, 0x13,
> 
> +  0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x20, 0x21, 0x22, 0x23, 0x24,
> 0x25, 0x26, 0x27,
> 
> +  0x28, 0x29, 0x2a, 0x2b, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
> 0x39, 0x3a, 0x3b,
> 
> +  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x50,
> 0x51, 0x52, 0x53,
> 
> +  0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b
> 
> +};
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample3ByteLen   = 72;
> // Length of sample3 input data in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID   *CustomizationSample3
> = "Parallel Data";            // Customization string (S) of sample3.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample3ByteLen  =
> 13;                         // Customization string length of sample3 in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample3      = 12;
> // Block size of sample3.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  ExpectOutputSample3[]
> = {
> 
> +  // Expected output data of sample3.
> 
> +  0x69, 0xd0, 0xfc, 0xb7, 0x64, 0xea, 0x05, 0x5d, 0xd0, 0x93, 0x34, 0xbc, 0x60,
> 0x21, 0xcb, 0x7e,
> 
> +  0x4b, 0x61, 0x34, 0x8d, 0xff, 0x37, 0x5d, 0xa2, 0x62, 0x67, 0x1c, 0xde, 0xc3,
> 0xef, 0xfa, 0x8d,
> 
> +  0x1b, 0x45, 0x68, 0xa6, 0xcc, 0xe1, 0x6b, 0x1c, 0xad, 0x94, 0x6d, 0xdd, 0xe2,
> 0x7f, 0x6c, 0xe2,
> 
> +  0xb8, 0xde, 0xe4, 0xcd, 0x1b, 0x24, 0x85, 0x1e, 0xbf, 0x00, 0xeb, 0x90, 0xd4,
> 0x38, 0x13, 0xe9
> 
> +};
> 
> +
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +TestVerifyParallelHash256HashAll (
> 
> +  IN UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
> 
> +  BOOLEAN  Status;
> 
> +  UINT8    Output[64];
> 
> +
> 
> +  //
> 
> +  // Test #1 using sample1.
> 
> +  //
> 
> +  Status = ParallelHash256HashAll (
> 
> +             InputSample1,
> 
> +             InputSample1ByteLen,
> 
> +             BlockSizeSample1,
> 
> +             Output,
> 
> +             OutputByteLen,
> 
> +             CustomizationSample1,
> 
> +             CustomSample1ByteLen
> 
> +             );
> 
> +  UT_ASSERT_TRUE (Status);
> 
> +
> 
> +  // Check the output with the expected output.
> 
> +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample1, OutputByteLen);
> 
> +
> 
> +  //
> 
> +  // Test #2 using sample2.
> 
> +  //
> 
> +  Status = ParallelHash256HashAll (
> 
> +             InputSample2,
> 
> +             InputSample2ByteLen,
> 
> +             BlockSizeSample2,
> 
> +             Output,
> 
> +             OutputByteLen,
> 
> +             CustomizationSample2,
> 
> +             CustomSample2ByteLen
> 
> +             );
> 
> +  UT_ASSERT_TRUE (Status);
> 
> +
> 
> +  // Check the output with the expected output.
> 
> +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample2, OutputByteLen);
> 
> +
> 
> +  //
> 
> +  // Test #3 using sample3.
> 
> +  //
> 
> +  Status = ParallelHash256HashAll (
> 
> +             InputSample3,
> 
> +             InputSample3ByteLen,
> 
> +             BlockSizeSample3,
> 
> +             Output,
> 
> +             OutputByteLen,
> 
> +             CustomizationSample3,
> 
> +             CustomSample3ByteLen
> 
> +             );
> 
> +  UT_ASSERT_TRUE (Status);
> 
> +
> 
> +  // Check the output with the expected output.
> 
> +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3, OutputByteLen);
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +TEST_DESC  mParallelhashTest[] = {
> 
> +  //
> 
> +  // -----Description------------------------------Class----------------------Function----
> -------------Pre---Post--Context
> 
> +  //
> 
> +  { "TestVerifyParallelHash256HashAll()",
> "CryptoPkg.BaseCryptLib.ParallelHash256HashAll",
> TestVerifyParallelHash256HashAll, NULL, NULL, NULL },
> 
> +};
> 
> +
> 
> +UINTN  mParallelhashTestNum = ARRAY_SIZE (mParallelhashTest);
> 
> diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml
> index eeb388ae71c5..e21fafac1efe 100644
> --- a/CryptoPkg/CryptoPkg.ci.yaml
> +++ b/CryptoPkg/CryptoPkg.ci.yaml
> @@ -2,7 +2,7 @@
>  # CI configuration for CryptoPkg
> 
>  #
> 
>  # Copyright (c) Microsoft Corporation
> 
> -# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +# Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  ##
> 
>  {
> 
> @@ -34,6 +34,8 @@
>              "Library/OpensslLib/rand_pool.c",
> 
>              # This has OpenSSL interfaces that aren't UEFI spec compliant
> 
>              "Library/Include/CrtLibSupport.h",
> 
> +            # This has OpenSSL interfaces that aren't UEFI spec compliant
> 
> +            "Library/BaseCryptLib/Hash/CryptParallelHash.h",
> 
>              # These directories contain auto-generated OpenSSL content
> 
>              "Library/OpensslLib",
> 
>              "Library/IntrinsicLib",
> 
> diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> b/CryptoPkg/Include/Library/BaseCryptLib.h
> index f4bc7c0d73d9..7d1499350a49 100644
> --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> @@ -4,7 +4,7 @@
>    primitives (Hash Serials, HMAC, RSA, Diffie-Hellman, etc) for UEFI security
> 
>    functionality enabling.
> 
> 
> 
> -Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -753,6 +753,35 @@ Sha512HashAll (
>    OUT  UINT8       *HashValue
> 
>    );
> 
> 
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  );
> 
> +
> 
>  /**
> 
>    Retrieves the size, in bytes, of the context buffer required for SM3 hash
> operations.
> 
> 
> 
> diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> index 5186a54759ae..0b30a821bc16 100644
> --- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> +++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> @@ -2,7 +2,7 @@
>    Defines the PCD_CRYPTO_SERVICE_FAMILY_ENABLE structure associated with
> 
>    gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.
> 
> 
> 
> -  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -172,6 +172,12 @@ typedef struct {
>      } Services;
> 
>      UINT32    Family;
> 
>    } Sha512;
> 
> +  union {
> 
> +    struct {
> 
> +      UINT8    HashAll : 1;
> 
> +    } Services;
> 
> +    UINT32    Family;
> 
> +  } ParallelHash;
> 
>    union {
> 
>      struct {
> 
>        UINT8    GetSubjectName             : 1;
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> index 49703fa4c963..15cf3dab105c 100644
> --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> @@ -6,7 +6,7 @@
>  #  This external input must be validated carefully to avoid security issues such as
> 
>  #  buffer overflow or integer overflow.
> 
>  #
> 
> -#  Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
> @@ -34,6 +34,7 @@
>    Hash/CryptSha256.c
> 
>    Hash/CryptSha512.c
> 
>    Hash/CryptSm3.c
> 
> +  Hash/CryptParallelHashNull.c
> 
>    Hmac/CryptHmacSha256.c
> 
>    Kdf/CryptHkdf.c
> 
>    Cipher/CryptAes.c
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
> new file mode 100644
> index 000000000000..fe08d4928e8d
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
> @@ -0,0 +1,201 @@
> +/** @file
> 
> +  ParallelHash related function and type declaration.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
> 
> +Licensed under the OpenSSL license (the "License").  You may not use
> 
> +this file except in compliance with the License.  You can obtain a copy
> 
> +in the file LICENSE in the source distribution or at
> 
> +https://www.openssl.org/source/license.html
> 
> +
> 
> +Copyright 2022 The eXtended Keccak Code Package (XKCP)
> 
> +https://github.com/XKCP/XKCP
> 
> +Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles
> Van Assche.
> 
> +Implementation by the designers, hereby denoted as "the implementer".
> 
> +For more information, feedback or questions, please refer to the Keccak Team
> website:
> 
> +https://keccak.team/
> 
> +To the extent possible under law, the implementer has waived all copyright
> 
> +and related or neighboring rights to the source code in this file.
> 
> +http://creativecommons.org/publicdomain/zero/1.0/
> 
> +**/
> 
> +
> 
> +#include "InternalCryptLib.h"
> 
> +
> 
> +#define KECCAK1600_WIDTH  1600
> 
> +
> 
> +//
> 
> +// This struct referring to m_sha3.c from opessl and modified its type name.
> 
> +//
> 
> +typedef struct {
> 
> +  uint64_t         A[5][5];
> 
> +  size_t           block_size;  /* cached ctx->digest->block_size */
> 
> +  size_t           md_size;     /* output length, variable in XOF */
> 
> +  size_t           num;         /* used bytes in below buffer */
> 
> +  unsigned char    buf[KECCAK1600_WIDTH / 8 - 32];
> 
> +  unsigned char    pad;
> 
> +} Keccak1600_Ctx;
> 
> +
> 
> +/**
> 
> +  SHA3_absorb can be called multiple times, but at each invocation
> 
> +  largest multiple of |r| out of |len| bytes are processed. Then
> 
> +  remaining amount of bytes is returned. This is done to spare caller
> 
> +  trouble of calculating the largest multiple of |r|. |r| can be viewed
> 
> +  as blocksize. It is commonly (1600 - 256*n)/8, e.g. 168, 136, 104,
> 
> +  72, but can also be (1600 - 448)/8 = 144. All this means that message
> 
> +  padding and intermediate sub-block buffering, byte- or bitwise, is
> 
> +  caller's responsibility.
> 
> +**/
> 
> +size_t
> 
> +SHA3_absorb (
> 
> +  uint64_t             A[5][5],
> 
> +  const unsigned char  *inp,
> 
> +  size_t               len,
> 
> +  size_t               r
> 
> +  );
> 
> +
> 
> +/**
> 
> +  SHA3_squeeze is called once at the end to generate |out| hash value
> 
> +  of |len| bytes.
> 
> +**/
> 
> +void
> 
> +SHA3_squeeze (
> 
> +  uint64_t       A[5][5],
> 
> +  unsigned char  *out,
> 
> +  size_t         len,
> 
> +  size_t         r
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Encode function from XKCP.
> 
> +
> 
> +  Encodes the input as a byte string in a way that can be unambiguously parsed
> 
> +  from the beginning of the string by inserting the length of the byte string
> 
> +  before the byte string representation of input.
> 
> +
> 
> +  @param[out] EncBuf  Result of left encode.
> 
> +  @param[in]  Value   Input of left encode.
> 
> +
> 
> +  @retval EncLen  Size of encode result in bytes.
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +LeftEncode (
> 
> +  OUT UINT8  *EncBuf,
> 
> +  IN  UINTN  Value
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Encode function from XKCP.
> 
> +
> 
> +  Encodes the input as a byte string in a way that can be unambiguously parsed
> 
> +  from the end of the string by inserting the length of the byte string after
> 
> +  the byte string representation of input.
> 
> +
> 
> +  @param[out] EncBuf  Result of right encode.
> 
> +  @param[in]  Value   Input of right encode.
> 
> +
> 
> +  @retval EncLen  Size of encode result in bytes.
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +RightEncode (
> 
> +  OUT UINT8  *EncBuf,
> 
> +  IN  UINTN  Value
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Keccak initial fuction.
> 
> +
> 
> +  Set up state with specified capacity.
> 
> +
> 
> +  @param[out] Context           Pointer to the context being initialized.
> 
> +  @param[in]  Pad               Delimited Suffix.
> 
> +  @param[in]  BlockSize         Size of context block.
> 
> +  @param[in]  MessageDigestLen  Size of message digest in bytes.
> 
> +
> 
> +  @retval 1  Initialize successfully.
> 
> +  @retval 0  Fail to initialize.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +KeccakInit (
> 
> +  OUT Keccak1600_Ctx  *Context,
> 
> +  IN  UINT8           Pad,
> 
> +  IN  UINTN           BlockSize,
> 
> +  IN  UINTN           MessageDigstLen
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Sha3 update fuction.
> 
> +
> 
> +  This function performs Sha3 digest on a data buffer of the specified size.
> 
> +  It can be called multiple times to compute the digest of long or discontinuous
> data streams.
> 
> +
> 
> +  @param[in,out] Context   Pointer to the Keccak context.
> 
> +  @param[in]     Data      Pointer to the buffer containing the data to be hashed.
> 
> +  @param[in]     DataSize  Size of Data buffer in bytes.
> 
> +
> 
> +  @retval 1  Update successfully.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +Sha3Update (
> 
> +  IN OUT Keccak1600_Ctx  *Context,
> 
> +  IN const VOID          *Data,
> 
> +  IN UINTN               DataSize
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Completes computation of Sha3 message digest.
> 
> +
> 
> +  This function completes sha3 hash computation and retrieves the digest value
> into
> 
> +  the specified memory. After this function has been called, the keccak context
> cannot
> 
> +  be used again.
> 
> +
> 
> +  @param[in, out]  Context        Pointer to the keccak context.
> 
> +  @param[out]      MessageDigest  Pointer to a buffer that receives the
> message digest.
> 
> +
> 
> +  @retval 1   Meaasge digest computation succeeded.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +Sha3Final (
> 
> +  IN OUT Keccak1600_Ctx  *Context,
> 
> +  OUT    UINT8           *MessageDigest
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Computes the CSHAKE-256 message digest of a input data buffer.
> 
> +
> 
> +  This function performs the CSHAKE-256 message digest of a given data buffer,
> and places
> 
> +  the digest value into the specified memory.
> 
> +
> 
> +  @param[in]   Data               Pointer to the buffer containing the data to be
> hashed.
> 
> +  @param[in]   DataSize           Size of Data buffer in bytes.
> 
> +  @param[in]   OutputLen          Size of output in bytes.
> 
> +  @param[in]   Name               Pointer to the function name string.
> 
> +  @param[in]   NameLen            Size of the function name in bytes.
> 
> +  @param[in]   Customization      Pointer to the customization string.
> 
> +  @param[in]   CustomizationLen   Size of the customization string in bytes.
> 
> +  @param[out]  HashValue          Pointer to a buffer that receives the CSHAKE-
> 256 digest
> 
> +                                  value.
> 
> +
> 
> +  @retval TRUE   CSHAKE-256 digest computation succeeded.
> 
> +  @retval FALSE  CSHAKE-256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256HashAll (
> 
> +  IN   CONST VOID  *Data,
> 
> +  IN   UINTN       DataSize,
> 
> +  IN   UINTN       OutputLen,
> 
> +  IN   CONST VOID  *Name,
> 
> +  IN   UINTN       NameLen,
> 
> +  IN   CONST VOID  *Customization,
> 
> +  IN   UINTN       CustomizationLen,
> 
> +  OUT  UINT8       *HashValue
> 
> +  );
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> index 0cab5f3ce36c..bf1563b06407 100644
> --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> @@ -13,7 +13,7 @@
>  #  PEM handler functions, and pseudorandom number generator functions are
> not
> 
>  #  supported in this instance.
> 
>  #
> 
> -#  Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
>  ##
> 
> @@ -40,6 +40,7 @@
>    Hash/CryptSha256.c
> 
>    Hash/CryptSm3.c
> 
>    Hash/CryptSha512.c
> 
> +  Hash/CryptParallelHashNull.c
> 
>    Hmac/CryptHmacSha256.c
> 
>    Kdf/CryptHkdf.c
> 
>    Cipher/CryptAesNull.c
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> index fdbb6edfd23e..6742da0be4fe 100644
> --- a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> @@ -11,7 +11,7 @@
>  #  functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, and
> 
>  #  authenticode signature verification functions are not supported in this
> instance.
> 
>  #
> 
> -#  Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights
> reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
> @@ -40,6 +40,7 @@
>    Hash/CryptSha256.c
> 
>    Hash/CryptSm3.c
> 
>    Hash/CryptSha512.c
> 
> +  Hash/CryptParallelHashNull.c
> 
>    Hmac/CryptHmacSha256.c
> 
>    Kdf/CryptHkdf.c
> 
>    Cipher/CryptAes.c
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> index e6470d7a2127..8f39517f78b7 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> @@ -10,7 +10,7 @@
>  #  RSA external functions, PKCS#7 SignedData sign functions, Diffie-Hellman
> functions, and
> 
>  #  authenticode signature verification functions are not supported in this
> instance.
> 
>  #
> 
> -#  Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
>  ##
> 
> @@ -38,6 +38,10 @@
>    Hash/CryptSha256.c
> 
>    Hash/CryptSm3.c
> 
>    Hash/CryptSha512.c
> 
> +  Hash/CryptSha3.c
> 
> +  Hash/CryptXkcp.c
> 
> +  Hash/CryptCShake256.c
> 
> +  Hash/CryptParallelHash.c
> 
>    Hmac/CryptHmacSha256.c
> 
>    Kdf/CryptHkdfNull.c
> 
>    Cipher/CryptAes.c
> 
> @@ -85,6 +89,8 @@
>    OpensslLib
> 
>    IntrinsicLib
> 
>    PrintLib
> 
> +  MmServicesTableLib
> 
> +  SynchronizationLib
> 
> 
> 
>  #
> 
>  # Remove these [BuildOptions] after this library is cleaned up
> 
> diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> index faf959827b90..63d1d82d1914 100644
> --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> @@ -6,7 +6,7 @@
>  #  This external input must be validated carefully to avoid security issues such as
> 
>  #  buffer overflow or integer overflow.
> 
>  #
> 
> -#  Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
> @@ -34,6 +34,7 @@
>    Hash/CryptSha256Null.c
> 
>    Hash/CryptSha512Null.c
> 
>    Hash/CryptSm3Null.c
> 
> +  Hash/CryptParallelHashNull.c
> 
>    Hmac/CryptHmacSha256Null.c
> 
>    Kdf/CryptHkdfNull.c
> 
>    Cipher/CryptAesNull.c
> 
> diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h
> b/CryptoPkg/Library/Include/CrtLibSupport.h
> index d257dca8fa9b..b76b140a7acf 100644
> --- a/CryptoPkg/Library/Include/CrtLibSupport.h
> +++ b/CryptoPkg/Library/Include/CrtLibSupport.h
> @@ -2,7 +2,7 @@
>    Root include file of C runtime library to support building the third-party
> 
>    cryptographic library.
> 
> 
> 
> -Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
> 
> +Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> reserved.<BR>
> 
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
> @@ -111,6 +111,7 @@ typedef UINT8   u_char;
>  typedef UINT32  uid_t;
> 
>  typedef UINT32  gid_t;
> 
>  typedef CHAR16  wchar_t;
> 
> +typedef UINT64  uint64_t;
> 
> 
> 
>  //
> 
>  // File operations are not required for EFI building,
> 
> diff --git a/CryptoPkg/Private/Protocol/Crypto.h
> b/CryptoPkg/Private/Protocol/Crypto.h
> index e378a8a8c60e..d51fc4a0e2cc 100644
> --- a/CryptoPkg/Private/Protocol/Crypto.h
> +++ b/CryptoPkg/Private/Protocol/Crypto.h
> @@ -1905,6 +1905,35 @@ BOOLEAN
>    OUT  UINT8       *HashValue
> 
>    );
> 
> 
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +typedef
> 
> +BOOLEAN
> 
> +(EFIAPI *EDKII_CRYPTO_PARALLEL_HASH_ALL)(
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  );
> 
> +
> 
>  // ----------------------------------------------------------------------------
> 
>  // X509
> 
>  // ----------------------------------------------------------------------------
> 
> @@ -3560,6 +3589,8 @@ struct _EDKII_CRYPTO_PROTOCOL {
>    EDKII_CRYPTO_SHA512_UPDATE                         Sha512Update;
> 
>    EDKII_CRYPTO_SHA512_FINAL                          Sha512Final;
> 
>    EDKII_CRYPTO_SHA512_HASH_ALL                       Sha512HashAll;
> 
> +  /// Parallel hash
> 
> +  EDKII_CRYPTO_PARALLEL_HASH_ALL                     ParallelHash256HashAll;
> 
>    /// X509
> 
>    EDKII_CRYPTO_X509_GET_SUBJECT_NAME                 X509GetSubjectName;
> 
>    EDKII_CRYPTO_X509_GET_COMMON_NAME                  X509GetCommonName;
> 
> diff --git a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> index ff0af36bcc80..ba6e1edb6015 100644
> --- a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> +++ b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> @@ -21,6 +21,9 @@
>  [LibraryClasses]
> 
>    OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
> 
>    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
> 
> +
> MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib
> .inf
> 
> +
> SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizati
> onLib.inf
> 
> +
> TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplat
> e.inf
> 
> 
> 
>  [LibraryClasses.AARCH64, LibraryClasses.ARM]
> 
>    RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf
> 
> diff --git
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> index 00c869265080..399db596c2d1 100644
> --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> @@ -2,6 +2,7 @@
>  # Host-based UnitTest for BaseCryptLib
> 
>  #
> 
>  # Copyright (c) Microsoft Corporation.<BR>
> 
> +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  ##
> 
> 
> 
> @@ -35,6 +36,7 @@
>    Pkcs7EkuTests.c
> 
>    OaepEncryptTests.c
> 
>    RsaPssTests.c
> 
> +  ParallelhashTests.c
> 
> 
> 
>  [Packages]
> 
>    MdePkg/MdePkg.dec
> 
> @@ -45,3 +47,5 @@
>    DebugLib
> 
>    BaseCryptLib
> 
>    UnitTestLib
> 
> +  MmServicesTableLib
> 
> +  SynchronizationLib
> 
> --
> 2.26.2.windows.1
> 
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> View/Reply Online (#87382): https://edk2.groups.io/g/devel/message/87382
> Mute This Topic: https://groups.io/mt/89658124/1772286
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub [jiewen.yao@intel.com]
> -=-=-=-=-=-=
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [edk2-devel] [PATCH v5 1/1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
  2022-03-14  5:50 ` [edk2-devel] " Yao, Jiewen
@ 2022-03-17  2:43   ` Li, Zhihao
  2022-03-17  3:24     ` Yao, Jiewen
  0 siblings, 1 reply; 4+ messages in thread
From: Li, Zhihao @ 2022-03-17  2:43 UTC (permalink / raw)
  To: Yao, Jiewen, devel@edk2.groups.io
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Fu, Siyuan

Will send patch_v6 with following update soon.
1. adjust the position of new field in the data structure.
2.update the version of data structure if it existing.
3.With the usability test, the CrytoLibOnProtocol version code can be used normally as static version.

Best Regard
Zhihao


-----Original Message-----
From: Yao, Jiewen <jiewen.yao@intel.com> 
Sent: Monday, March 14, 2022 1:50 PM
To: devel@edk2.groups.io; Li, Zhihao <zhihao.li@intel.com>
Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>
Subject: RE: [edk2-devel] [PATCH v5 1/1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.

Thanks. It is close to final version, but there are some compatibility issue need to be address.

1) Whenever you add a new field in the data structure, please add it at the end. Don't add them in the middle.
E.g. PCD_CRYPTO_SERVICE_FAMILY_ENABLE, _EDKII_CRYPTO_PROTOCOL

2) Whenever you add a new field for a data structure, please remember to increase the version.
E.g. EDKII_CRYPTO_VERSION


3) Please clarify if you have tested the CrytoLibOnProtocol version code.

Thank you
Yao Jiewen


> -----Original Message-----
> From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Li, Zhihao
> Sent: Wednesday, March 9, 2022 4:44 PM
> To: devel@edk2.groups.io
> Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J <jian.j.wang@intel.com>;
> Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin <guomin.jiang@intel.com>;
> Fu, Siyuan <siyuan.fu@intel.com>
> Subject: [edk2-devel] [PATCH v5 1/1] CryptoPkg: Add new hash algorithm
> ParallelHash256HashAll in BaseCryptLib.
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3596
> 
> Parallel hash function ParallelHash256HashAll, as defined in NIST's
> Special Publication 800-185, published December 2016. It utilizes
> multi-process to calculate the digest.
> 
> Some modifications to pass CI test.
> 
> Cc: Jiewen Yao <jiewen.yao@intel.com>
> Cc: Jian J Wang <jian.j.wang@intel.com>
> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> Cc: Guomin Jiang <guomin.jiang@intel.com>
> Cc: Siyuan Fu <siyuan.fu@intel.com>
> Cc: Zhihao Li <zhihao.li@intel.com>
> 
> Signed-off-by: Zhihao Li <zhihao.li@intel.com>
> ---
>  CryptoPkg/Driver/Crypto.c                                             |  36 ++-
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                  | 282
> ++++++++++++++++++++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c               | 278
> +++++++++++++++++++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c           |  40 +++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                       | 166
> ++++++++++++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                       | 107 ++++++++
>  CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c       |  40 +++
>  CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c                |  34 ++-
>  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c      | 145
> ++++++++++
>  CryptoPkg/CryptoPkg.ci.yaml                                           |   4 +-
>  CryptoPkg/Include/Library/BaseCryptLib.h                              |  31 ++-
>  CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h                  |   8 +-
>  CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf                       |   3 +-
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h               | 201
> ++++++++++++++
>  CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf                        |   3 +-
>  CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf                    |   3 +-
>  CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                        |   8 +-
>  CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf               |   3 +-
>  CryptoPkg/Library/Include/CrtLibSupport.h                             |   3 +-
>  CryptoPkg/Private/Protocol/Crypto.h                                   |  31 +++
>  CryptoPkg/Test/CryptoPkgHostUnitTest.dsc                              |   3 +
>  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf |   4 +
>  22 files changed, 1422 insertions(+), 11 deletions(-)
> 
> diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
> index d5d6aa8e5820..35312e0818a0 100644
> --- a/CryptoPkg/Driver/Crypto.c
> +++ b/CryptoPkg/Driver/Crypto.c
> @@ -3,7 +3,7 @@
>    from BaseCryptLib and TlsLib.
> 
> 
> 
>    Copyright (C) Microsoft Corporation. All rights reserved.
> 
> -  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -1314,6 +1314,38 @@ CryptoServiceSha512HashAll (
>    return CALL_BASECRYPTLIB (Sha512.Services.HashAll, Sha512HashAll, (Data,
> DataSize, HashValue), FALSE);
> 
>  }
> 
> 
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CryptoServiceParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  return CALL_BASECRYPTLIB (ParallelHash.Services.HashAll,
> ParallelHash256HashAll, (Input, InputByteLen, BlockSize, Output, OutputByteLen,
> Customization, CustomByteLen), FALSE);
> 
> +}
> 
> +
> 
>  /**
> 
>    Retrieves the size, in bytes, of the context buffer required for SM3 hash
> operations.
> 
> 
> 
> @@ -4590,6 +4622,8 @@ const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
>    CryptoServiceSha512Update,
> 
>    CryptoServiceSha512Final,
> 
>    CryptoServiceSha512HashAll,
> 
> +  /// Parallel hash
> 
> +  CryptoServiceParallelHash256HashAll,
> 
>    /// X509
> 
>    CryptoServiceX509GetSubjectName,
> 
>    CryptoServiceX509GetCommonName,
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> new file mode 100644
> index 000000000000..96e3c8eb02e1
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> @@ -0,0 +1,282 @@
> +/** @file
> 
> +  cSHAKE-256 Digest Wrapper Implementations.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "CryptParallelHash.h"
> 
> +
> 
> +#define  CSHAKE256_SECURITY_STRENGTH  256
> 
> +#define  CSHAKE256_RATE_IN_BYTES      136
> 
> +
> 
> +const CHAR8  mZeroPadding[CSHAKE256_RATE_IN_BYTES] = { 0 };
> 
> +
> 
> +/**
> 
> +  CShake256 initial function.
> 
> +
> 
> +  Initializes user-supplied memory pointed by CShake256Context as cSHAKE-256
> hash context for
> 
> +  subsequent use.
> 
> +
> 
> +  @param[out] CShake256Context  Pointer to cSHAKE-256 context being
> initialized.
> 
> +  @param[in]  OutputLen         The desired number of output length in bytes.
> 
> +  @param[in]  Name              Pointer to the function name string.
> 
> +  @param[in]  NameLen           The length of the function name in bytes.
> 
> +  @param[in]  Customization     Pointer to the customization string.
> 
> +  @param[in]  CustomizationLen  The length of the customization string in
> bytes.
> 
> +
> 
> +  @retval TRUE   cSHAKE-256 context initialization succeeded.
> 
> +  @retval FALSE  cSHAKE-256 context initialization failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256Init (
> 
> +  OUT  VOID        *CShake256Context,
> 
> +  IN   UINTN       OutputLen,
> 
> +  IN   CONST VOID  *Name,
> 
> +  IN   UINTN       NameLen,
> 
> +  IN   CONST VOID  *Customization,
> 
> +  IN   UINTN       CustomizationLen
> 
> +  )
> 
> +{
> 
> +  BOOLEAN  Status;
> 
> +  UINT8    EncBuf[sizeof (UINTN) + 1];
> 
> +  UINTN    EncLen;
> 
> +  UINTN    AbsorbLen;
> 
> +  UINTN    PadLen;
> 
> +
> 
> +  //
> 
> +  // Check input parameters.
> 
> +  //
> 
> +  if ((CShake256Context == NULL) || (OutputLen == 0) || ((NameLen != 0) &&
> (Name == NULL)) || ((CustomizationLen != 0) && (Customization == NULL))) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Initialize KECCAK context with pad value and block size.
> 
> +  //
> 
> +  if ((NameLen == 0) && (CustomizationLen == 0)) {
> 
> +    //
> 
> +    // When N and S are both empty strings, cSHAKE(X, L, N, S) is equivalent to
> 
> +    // SHAKE as defined in FIPS 202.
> 
> +    //
> 
> +    Status = (BOOLEAN)KeccakInit (
> 
> +                        (Keccak1600_Ctx *)CShake256Context,
> 
> +                        '\x1f',
> 
> +                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
> 
> +                        OutputLen
> 
> +                        );
> 
> +
> 
> +    return Status;
> 
> +  } else {
> 
> +    Status = (BOOLEAN)KeccakInit (
> 
> +                        (Keccak1600_Ctx *)CShake256Context,
> 
> +                        '\x04',
> 
> +                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
> 
> +                        OutputLen
> 
> +                        );
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen = 0;
> 
> +    //
> 
> +    // Absorb Absorb bytepad(.., rate).
> 
> +    //
> 
> +    EncLen = LeftEncode (EncBuf, CSHAKE256_RATE_IN_BYTES);
> 
> +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> EncBuf, EncLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += EncLen;
> 
> +
> 
> +    //
> 
> +    // Absorb encode_string(N).
> 
> +    //
> 
> +    EncLen = LeftEncode (EncBuf, NameLen * 8);
> 
> +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> EncBuf, EncLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += EncLen;
> 
> +    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> Name, NameLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += NameLen;
> 
> +
> 
> +    //
> 
> +    // Absorb encode_string(S).
> 
> +    //
> 
> +    EncLen = LeftEncode (EncBuf, CustomizationLen * 8);
> 
> +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> EncBuf, EncLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += EncLen;
> 
> +    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> Customization, CustomizationLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    AbsorbLen += CustomizationLen;
> 
> +
> 
> +    //
> 
> +    // Absorb zero padding up to rate.
> 
> +    //
> 
> +    PadLen = CSHAKE256_RATE_IN_BYTES - AbsorbLen %
> CSHAKE256_RATE_IN_BYTES;
> 
> +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> mZeroPadding, PadLen);
> 
> +    if (!Status) {
> 
> +      return FALSE;
> 
> +    }
> 
> +
> 
> +    return TRUE;
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Digests the input data and updates cSHAKE-256 context.
> 
> +
> 
> +  This function performs cSHAKE-256 digest on a data buffer of the specified
> size.
> 
> +  It can be called multiple times to compute the digest of long or discontinuous
> data streams.
> 
> +  cSHAKE-256 context should be already correctly initialized by CShake256Init(),
> and should not be finalized
> 
> +  by CShake256Final(). Behavior with invalid context is undefined.
> 
> +
> 
> +  @param[in, out]  CShake256Context   Pointer to the cSHAKE-256 context.
> 
> +  @param[in]       Data               Pointer to the buffer containing the data to be
> hashed.
> 
> +  @param[in]       DataSize           Size of Data buffer in bytes.
> 
> +
> 
> +  @retval TRUE   cSHAKE-256 data digest succeeded.
> 
> +  @retval FALSE  cSHAKE-256 data digest failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256Update (
> 
> +  IN OUT  VOID        *CShake256Context,
> 
> +  IN      CONST VOID  *Data,
> 
> +  IN      UINTN       DataSize
> 
> +  )
> 
> +{
> 
> +  //
> 
> +  // Check input parameters.
> 
> +  //
> 
> +  if (CShake256Context == NULL) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Check invalid parameters, in case that only DataLength was checked in
> OpenSSL.
> 
> +  //
> 
> +  if ((Data == NULL) && (DataSize != 0)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  return (BOOLEAN)(Sha3Update ((Keccak1600_Ctx *)CShake256Context, Data,
> DataSize));
> 
> +}
> 
> +
> 
> +/**
> 
> +  Completes computation of the cSHAKE-256 digest value.
> 
> +
> 
> +  This function completes cSHAKE-256 hash computation and retrieves the
> digest value into
> 
> +  the specified memory. After this function has been called, the cSHAKE-256
> context cannot
> 
> +  be used again.
> 
> +  cSHAKE-256 context should be already correctly initialized by CShake256Init(),
> and should not be
> 
> +  finalized by CShake256Final(). Behavior with invalid cSHAKE-256 context is
> undefined.
> 
> +
> 
> +  @param[in, out]  CShake256Context  Pointer to the cSHAKE-256 context.
> 
> +  @param[out]      HashValue         Pointer to a buffer that receives the cSHAKE-
> 256 digest
> 
> +                                     value.
> 
> +
> 
> +  @retval TRUE   cSHAKE-256 digest computation succeeded.
> 
> +  @retval FALSE  cSHAKE-256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256Final (
> 
> +  IN OUT  VOID   *CShake256Context,
> 
> +  OUT     UINT8  *HashValue
> 
> +  )
> 
> +{
> 
> +  //
> 
> +  // Check input parameters.
> 
> +  //
> 
> +  if ((CShake256Context == NULL) || (HashValue == NULL)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // cSHAKE-256 Hash Finalization.
> 
> +  //
> 
> +  return (BOOLEAN)(Sha3Final ((Keccak1600_Ctx *)CShake256Context,
> HashValue));
> 
> +}
> 
> +
> 
> +/**
> 
> +  Computes the CSHAKE-256 message digest of a input data buffer.
> 
> +
> 
> +  This function performs the CSHAKE-256 message digest of a given data buffer,
> and places
> 
> +  the digest value into the specified memory.
> 
> +
> 
> +  @param[in]   Data               Pointer to the buffer containing the data to be
> hashed.
> 
> +  @param[in]   DataSize           Size of Data buffer in bytes.
> 
> +  @param[in]   OutputLen          Size of output in bytes.
> 
> +  @param[in]   Name               Pointer to the function name string.
> 
> +  @param[in]   NameLen            Size of the function name in bytes.
> 
> +  @param[in]   Customization      Pointer to the customization string.
> 
> +  @param[in]   CustomizationLen   Size of the customization string in bytes.
> 
> +  @param[out]  HashValue          Pointer to a buffer that receives the CSHAKE-
> 256 digest
> 
> +                                  value.
> 
> +
> 
> +  @retval TRUE   CSHAKE-256 digest computation succeeded.
> 
> +  @retval FALSE  CSHAKE-256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256HashAll (
> 
> +  IN   CONST VOID  *Data,
> 
> +  IN   UINTN       DataSize,
> 
> +  IN   UINTN       OutputLen,
> 
> +  IN   CONST VOID  *Name,
> 
> +  IN   UINTN       NameLen,
> 
> +  IN   CONST VOID  *Customization,
> 
> +  IN   UINTN       CustomizationLen,
> 
> +  OUT  UINT8       *HashValue
> 
> +  )
> 
> +{
> 
> +  BOOLEAN         Status;
> 
> +  Keccak1600_Ctx  Ctx;
> 
> +
> 
> +  //
> 
> +  // Check input parameters.
> 
> +  //
> 
> +  if (HashValue == NULL) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  if ((Data == NULL) && (DataSize != 0)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  Status = CShake256Init (&Ctx, OutputLen, Name, NameLen, Customization,
> CustomizationLen);
> 
> +  if (!Status) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  Status = CShake256Update (&Ctx, Data, DataSize);
> 
> +  if (!Status) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  return CShake256Final (&Ctx, HashValue);
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> new file mode 100644
> index 000000000000..f7ce9dbf523e
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> @@ -0,0 +1,278 @@
> +/** @file
> 
> +  ParallelHash Implementation.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "CryptParallelHash.h"
> 
> +#include <Library/MmServicesTableLib.h>
> 
> +#include <Library/SynchronizationLib.h>
> 
> +
> 
> +#define PARALLELHASH_CUSTOMIZATION  "ParallelHash"
> 
> +
> 
> +UINTN      mBlockNum;
> 
> +UINTN      mBlockSize;
> 
> +UINTN      mLastBlockSize;
> 
> +UINT8      *mInput;
> 
> +UINTN      mBlockResultSize;
> 
> +UINT8      *mBlockHashResult;
> 
> +BOOLEAN    *mBlockIsCompleted;
> 
> +SPIN_LOCK  *mSpinLockList;
> 
> +
> 
> +/**
> 
> +  Complete computation of digest of each block.
> 
> +
> 
> +  Each AP perform the function called by BSP.
> 
> +
> 
> +  @param[in] ProcedureArgument Argument of the procedure.
> 
> +**/
> 
> +VOID
> 
> +EFIAPI
> 
> +ParallelHashApExecute (
> 
> +  IN VOID  *ProcedureArgument
> 
> +  )
> 
> +{
> 
> +  UINTN    Index;
> 
> +  BOOLEAN  Status;
> 
> +
> 
> +  for (Index = 0; Index < mBlockNum; Index++) {
> 
> +    if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
> 
> +      //
> 
> +      // Completed, try next one.
> 
> +      //
> 
> +      if (mBlockIsCompleted[Index]) {
> 
> +        ReleaseSpinLock (&mSpinLockList[Index]);
> 
> +        continue;
> 
> +      }
> 
> +
> 
> +      //
> 
> +      // Calculate CShake256 for this block.
> 
> +      //
> 
> +      Status = CShake256HashAll (
> 
> +                 mInput + Index * mBlockSize,
> 
> +                 (Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
> 
> +                 mBlockResultSize,
> 
> +                 NULL,
> 
> +                 0,
> 
> +                 NULL,
> 
> +                 0,
> 
> +                 mBlockHashResult + Index * mBlockResultSize
> 
> +                 );
> 
> +      if (!EFI_ERROR (Status)) {
> 
> +        mBlockIsCompleted[Index] = TRUE;
> 
> +      }
> 
> +
> 
> +      ReleaseSpinLock (&mSpinLockList[Index]);
> 
> +    }
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Dispatch the block task to each AP in SMM mode.
> 
> +
> 
> +**/
> 
> +VOID
> 
> +EFIAPI
> 
> +MmDispatchBlockToAP (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  UINTN  Index;
> 
> +
> 
> +  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
> 
> +    if (Index != gMmst->CurrentlyExecutingCpu) {
> 
> +      gMmst->MmStartupThisAp (ParallelHashApExecute, Index, NULL);
> 
> +    }
> 
> +  }
> 
> +
> 
> +  return;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  UINT8    EncBufB[sizeof (UINTN)+1];
> 
> +  UINTN    EncSizeB;
> 
> +  UINT8    EncBufN[sizeof (UINTN)+1];
> 
> +  UINTN    EncSizeN;
> 
> +  UINT8    EncBufL[sizeof (UINTN)+1];
> 
> +  UINTN    EncSizeL;
> 
> +  UINTN    Index;
> 
> +  UINT8    *CombinedInput;
> 
> +  UINTN    CombinedInputSize;
> 
> +  BOOLEAN  AllCompleted;
> 
> +  UINTN    Offset;
> 
> +  BOOLEAN  ReturnValue;
> 
> +
> 
> +  if ((InputByteLen == 0) || (OutputByteLen == 0) || (BlockSize == 0)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  if ((Input == NULL) || (Output == NULL)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  if ((CustomByteLen != 0) && (Customization == NULL)) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  mBlockSize = BlockSize;
> 
> +
> 
> +  //
> 
> +  // Calculate block number n.
> 
> +  //
> 
> +  mBlockNum = InputByteLen % mBlockSize == 0 ? InputByteLen / mBlockSize :
> InputByteLen / mBlockSize + 1;
> 
> +
> 
> +  //
> 
> +  // Set hash result size of each block in bytes.
> 
> +  //
> 
> +  mBlockResultSize = OutputByteLen;
> 
> +
> 
> +  //
> 
> +  // Encode B, n, L to string and record size.
> 
> +  //
> 
> +  EncSizeB = LeftEncode (EncBufB, mBlockSize);
> 
> +  EncSizeN = RightEncode (EncBufN, mBlockNum);
> 
> +  EncSizeL = RightEncode (EncBufL, OutputByteLen * CHAR_BIT);
> 
> +
> 
> +  //
> 
> +  // Allocate buffer for combined input (newX), Block completed flag and
> SpinLock.
> 
> +  //
> 
> +  CombinedInputSize = EncSizeB + EncSizeN + EncSizeL + mBlockNum *
> mBlockResultSize;
> 
> +  CombinedInput     = AllocateZeroPool (CombinedInputSize);
> 
> +  mBlockIsCompleted = AllocateZeroPool (mBlockNum * sizeof (BOOLEAN));
> 
> +  mSpinLockList     = AllocatePool (mBlockNum * sizeof (SPIN_LOCK));
> 
> +  if ((CombinedInput == NULL) || (mBlockIsCompleted == NULL) ||
> (mSpinLockList == NULL)) {
> 
> +    ReturnValue = FALSE;
> 
> +    goto Exit;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Fill LeftEncode(B).
> 
> +  //
> 
> +  CopyMem (CombinedInput, EncBufB, EncSizeB);
> 
> +
> 
> +  //
> 
> +  // Prepare for parallel hash.
> 
> +  //
> 
> +  mBlockHashResult = CombinedInput + EncSizeB;
> 
> +  mInput           = (UINT8 *)Input;
> 
> +  mLastBlockSize   = InputByteLen % mBlockSize == 0 ? mBlockSize :
> InputByteLen % mBlockSize;
> 
> +
> 
> +  //
> 
> +  // Initialize SpinLock for each result block.
> 
> +  //
> 
> +  for (Index = 0; Index < mBlockNum; Index++) {
> 
> +    InitializeSpinLock (&mSpinLockList[Index]);
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Dispatch blocklist to each AP.
> 
> +  //
> 
> +  if (gMmst != NULL) {
> 
> +    MmDispatchBlockToAP ();
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Wait until all block hash completed.
> 
> +  //
> 
> +  do {
> 
> +    AllCompleted = TRUE;
> 
> +    for (Index = 0; Index < mBlockNum; Index++) {
> 
> +      if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
> 
> +        if (!mBlockIsCompleted[Index]) {
> 
> +          AllCompleted = FALSE;
> 
> +          ReturnValue  = CShake256HashAll (
> 
> +                           mInput + Index * mBlockSize,
> 
> +                           (Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
> 
> +                           mBlockResultSize,
> 
> +                           NULL,
> 
> +                           0,
> 
> +                           NULL,
> 
> +                           0,
> 
> +                           mBlockHashResult + Index * mBlockResultSize
> 
> +                           );
> 
> +          if (ReturnValue) {
> 
> +            mBlockIsCompleted[Index] = TRUE;
> 
> +          }
> 
> +
> 
> +          ReleaseSpinLock (&mSpinLockList[Index]);
> 
> +          break;
> 
> +        }
> 
> +
> 
> +        ReleaseSpinLock (&mSpinLockList[Index]);
> 
> +      } else {
> 
> +        AllCompleted = FALSE;
> 
> +        break;
> 
> +      }
> 
> +    }
> 
> +  } while (!AllCompleted);
> 
> +
> 
> +  //
> 
> +  // Fill LeftEncode(n).
> 
> +  //
> 
> +  Offset = EncSizeB + mBlockNum * mBlockResultSize;
> 
> +  CopyMem (CombinedInput + Offset, EncBufN, EncSizeN);
> 
> +
> 
> +  //
> 
> +  // Fill LeftEncode(L).
> 
> +  //
> 
> +  Offset += EncSizeN;
> 
> +  CopyMem (CombinedInput + Offset, EncBufL, EncSizeL);
> 
> +
> 
> +  ReturnValue = CShake256HashAll (
> 
> +                  CombinedInput,
> 
> +                  CombinedInputSize,
> 
> +                  OutputByteLen,
> 
> +                  PARALLELHASH_CUSTOMIZATION,
> 
> +                  AsciiStrLen (PARALLELHASH_CUSTOMIZATION),
> 
> +                  Customization,
> 
> +                  CustomByteLen,
> 
> +                  Output
> 
> +                  );
> 
> +
> 
> +Exit:
> 
> +  ZeroMem (CombinedInput, CombinedInputSize);
> 
> +
> 
> +  if (CombinedInput != NULL) {
> 
> +    FreePool (CombinedInput);
> 
> +  }
> 
> +
> 
> +  if (mSpinLockList != NULL) {
> 
> +    FreePool ((VOID *)mSpinLockList);
> 
> +  }
> 
> +
> 
> +  if (mBlockIsCompleted != NULL) {
> 
> +    FreePool (mBlockIsCompleted);
> 
> +  }
> 
> +
> 
> +  return ReturnValue;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
> new file mode 100644
> index 000000000000..2bf89594def5
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
> @@ -0,0 +1,40 @@
> +/** @file
> 
> +  ParallelHash Implementation which does not provide real capabilities.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "InternalCryptLib.h"
> 
> +
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  ASSERT (FALSE);
> 
> +  return FALSE;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> new file mode 100644
> index 000000000000..6abafc3c00e6
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> @@ -0,0 +1,166 @@
> +/** @file
> 
> +  SHA3 realted functions from OpenSSL.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
> 
> +Licensed under the OpenSSL license (the "License").  You may not use
> 
> +this file except in compliance with the License.  You can obtain a copy
> 
> +in the file LICENSE in the source distribution or at
> 
> +https://www.openssl.org/source/license.html
> 
> +**/
> 
> +
> 
> +#include "CryptParallelHash.h"
> 
> +
> 
> +/**
> 
> +  Keccak initial fuction.
> 
> +
> 
> +  Set up state with specified capacity.
> 
> +
> 
> +  @param[out] Context           Pointer to the context being initialized.
> 
> +  @param[in]  Pad               Delimited Suffix.
> 
> +  @param[in]  BlockSize         Size of context block.
> 
> +  @param[in]  MessageDigestLen  Size of message digest in bytes.
> 
> +
> 
> +  @retval 1  Initialize successfully.
> 
> +  @retval 0  Fail to initialize.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +KeccakInit (
> 
> +  OUT Keccak1600_Ctx  *Context,
> 
> +  IN  UINT8           Pad,
> 
> +  IN  UINTN           BlockSize,
> 
> +  IN  UINTN           MessageDigestLen
> 
> +  )
> 
> +{
> 
> +  if (BlockSize <= sizeof (Context->buf)) {
> 
> +    memset (Context->A, 0, sizeof (Context->A));
> 
> +
> 
> +    Context->num        = 0;
> 
> +    Context->block_size = BlockSize;
> 
> +    Context->md_size    = MessageDigestLen;
> 
> +    Context->pad        = Pad;
> 
> +
> 
> +    return 1;
> 
> +  }
> 
> +
> 
> +  return 0;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Sha3 update fuction.
> 
> +
> 
> +  This function performs Sha3 digest on a data buffer of the specified size.
> 
> +  It can be called multiple times to compute the digest of long or discontinuous
> data streams.
> 
> +
> 
> +  @param[in,out] Context   Pointer to the Keccak context.
> 
> +  @param[in]     Data      Pointer to the buffer containing the data to be hashed.
> 
> +  @param[in]     DataSize  Size of Data buffer in bytes.
> 
> +
> 
> +  @retval 1  Update successfully.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +Sha3Update (
> 
> +  IN OUT Keccak1600_Ctx  *Context,
> 
> +  IN const VOID          *Data,
> 
> +  IN UINTN               DataSize
> 
> +  )
> 
> +{
> 
> +  const UINT8  *DataCopy;
> 
> +  UINTN        BlockSize;
> 
> +  UINTN        Num;
> 
> +  UINTN        Rem;
> 
> +
> 
> +  DataCopy  = Data;
> 
> +  BlockSize = (UINT8)(Context->block_size);
> 
> +
> 
> +  if (DataSize == 0) {
> 
> +    return 1;
> 
> +  }
> 
> +
> 
> +  if ((Num = Context->num) != 0) {
> 
> +    //
> 
> +    // process intermediate buffer
> 
> +    //
> 
> +    Rem = BlockSize - Num;
> 
> +
> 
> +    if (DataSize < Rem) {
> 
> +      memcpy (Context->buf + Num, DataCopy, DataSize);
> 
> +      Context->num += DataSize;
> 
> +      return 1;
> 
> +    }
> 
> +
> 
> +    //
> 
> +    // We have enough data to fill or overflow the intermediate
> 
> +    // buffer. So we append |Rem| bytes and process the block,
> 
> +    // leaving the rest for later processing.
> 
> +    //
> 
> +    memcpy (Context->buf + Num, DataCopy, Rem);
> 
> +    DataCopy += Rem;
> 
> +    DataSize -= Rem;
> 
> +    (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
> 
> +    Context->num = 0;
> 
> +    // Context->buf is processed, Context->num is guaranteed to be zero.
> 
> +  }
> 
> +
> 
> +  if (DataSize >= BlockSize) {
> 
> +    Rem = SHA3_absorb (Context->A, DataCopy, DataSize, BlockSize);
> 
> +  } else {
> 
> +    Rem = DataSize;
> 
> +  }
> 
> +
> 
> +  if (Rem > 0) {
> 
> +    memcpy (Context->buf, DataCopy + DataSize - Rem, Rem);
> 
> +    Context->num = Rem;
> 
> +  }
> 
> +
> 
> +  return 1;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Completes computation of Sha3 message digest.
> 
> +
> 
> +  This function completes sha3 hash computation and retrieves the digest value
> into
> 
> +  the specified memory. After this function has been called, the keccak context
> cannot
> 
> +  be used again.
> 
> +
> 
> +  @param[in, out]  Context        Pointer to the keccak context.
> 
> +  @param[out]      MessageDigest  Pointer to a buffer that receives the
> message digest.
> 
> +
> 
> +  @retval 1   Meaasge digest computation succeeded.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +Sha3Final (
> 
> +  IN OUT Keccak1600_Ctx  *Context,
> 
> +  OUT    UINT8           *MessageDigest
> 
> +  )
> 
> +{
> 
> +  UINTN  BlockSize;
> 
> +  UINTN  Num;
> 
> +
> 
> +  BlockSize = Context->block_size;
> 
> +  Num       = Context->num;
> 
> +
> 
> +  if (Context->md_size == 0) {
> 
> +    return 1;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Pad the data with 10*1. Note that |Num| can be |BlockSize - 1|
> 
> +  // in which case both byte operations below are performed on
> 
> +  // same byte.
> 
> +  //
> 
> +  memset (Context->buf + Num, 0, BlockSize - Num);
> 
> +  Context->buf[Num]            = Context->pad;
> 
> +  Context->buf[BlockSize - 1] |= 0x80;
> 
> +
> 
> +  (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
> 
> +
> 
> +  SHA3_squeeze (Context->A, MessageDigest, Context->md_size, BlockSize);
> 
> +
> 
> +  return 1;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> new file mode 100644
> index 000000000000..12c46cfbcd59
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> @@ -0,0 +1,107 @@
> +/** @file
> 
> +  Encode realted functions from Xkcp.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +Copyright 2022 The eXtended Keccak Code Package (XKCP)
> 
> +https://github.com/XKCP/XKCP
> 
> +Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles
> Van Assche.
> 
> +Implementation by the designers, hereby denoted as "the implementer".
> 
> +For more information, feedback or questions, please refer to the Keccak Team
> website:
> 
> +https://keccak.team/
> 
> +To the extent possible under law, the implementer has waived all copyright
> 
> +and related or neighboring rights to the source code in this file.
> 
> +http://creativecommons.org/publicdomain/zero/1.0/
> 
> +
> 
> +**/
> 
> +
> 
> +#include "CryptParallelHash.h"
> 
> +
> 
> +/**
> 
> +  Encode function from XKCP.
> 
> +
> 
> +  Encodes the input as a byte string in a way that can be unambiguously parsed
> 
> +  from the beginning of the string by inserting the length of the byte string
> 
> +  before the byte string representation of input.
> 
> +
> 
> +  @param[out] EncBuf  Result of left encode.
> 
> +  @param[in]  Value   Input of left encode.
> 
> +
> 
> +  @retval EncLen  Size of encode result in bytes.
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +LeftEncode (
> 
> +  OUT UINT8  *EncBuf,
> 
> +  IN  UINTN  Value
> 
> +  )
> 
> +{
> 
> +  UINT32  BlockNum;
> 
> +  UINT32  EncLen;
> 
> +  UINT32  Index;
> 
> +  UINTN   ValueCopy;
> 
> +
> 
> +  for ( ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof
> (UINTN)); ++BlockNum, ValueCopy >>= 8 ) {
> 
> +    //
> 
> +    // Empty
> 
> +    //
> 
> +  }
> 
> +
> 
> +  if (BlockNum == 0) {
> 
> +    BlockNum = 1;
> 
> +  }
> 
> +
> 
> +  for (Index = 1; Index <= BlockNum; ++Index) {
> 
> +    EncBuf[Index] = (UINT8)(Value >> (8 * (BlockNum - Index)));
> 
> +  }
> 
> +
> 
> +  EncBuf[0] = (UINT8)BlockNum;
> 
> +  EncLen    = BlockNum + 1;
> 
> +
> 
> +  return EncLen;
> 
> +}
> 
> +
> 
> +/**
> 
> +  Encode function from XKCP.
> 
> +
> 
> +  Encodes the input as a byte string in a way that can be unambiguously parsed
> 
> +  from the end of the string by inserting the length of the byte string after
> 
> +  the byte string representation of input.
> 
> +
> 
> +  @param[out] EncBuf  Result of right encode.
> 
> +  @param[in]  Value   Input of right encode.
> 
> +
> 
> +  @retval EncLen  Size of encode result in bytes.
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +RightEncode (
> 
> +  OUT UINT8  *EncBuf,
> 
> +  IN  UINTN  Value
> 
> +  )
> 
> +{
> 
> +  UINT32  BlockNum;
> 
> +  UINT32  EncLen;
> 
> +  UINT32  Index;
> 
> +  UINTN   ValueCopy;
> 
> +
> 
> +  for (ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof
> (UINTN)); ++BlockNum, ValueCopy >>= 8) {
> 
> +    //
> 
> +    // Empty
> 
> +    //
> 
> +  }
> 
> +
> 
> +  if (BlockNum == 0) {
> 
> +    BlockNum = 1;
> 
> +  }
> 
> +
> 
> +  for (Index = 1; Index <= BlockNum; ++Index) {
> 
> +    EncBuf[Index-1] = (UINT8)(Value >> (8 * (BlockNum-Index)));
> 
> +  }
> 
> +
> 
> +  EncBuf[BlockNum] = (UINT8)BlockNum;
> 
> +  EncLen           = BlockNum + 1;
> 
> +
> 
> +  return EncLen;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
> b/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
> new file mode 100644
> index 000000000000..2bf89594def5
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
> @@ -0,0 +1,40 @@
> +/** @file
> 
> +  ParallelHash Implementation which does not provide real capabilities.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "InternalCryptLib.h"
> 
> +
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  ASSERT (FALSE);
> 
> +  return FALSE;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> index c8df259ea963..8ee1b53cf957 100644
> --- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> +++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> @@ -3,7 +3,7 @@
>    Protocol/PPI.
> 
> 
> 
>    Copyright (C) Microsoft Corporation. All rights reserved.
> 
> -  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -870,6 +870,38 @@ Sha512HashAll (
>    CALL_CRYPTO_SERVICE (Sha512HashAll, (Data, DataSize, HashValue), FALSE);
> 
>  }
> 
> 
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  )
> 
> +{
> 
> +  CALL_CRYPTO_SERVICE (ParallelHash256HashAll, (Input, InputByteLen,
> BlockSize, Output, OutputByteLen, Customization, CustomByteLen), FALSE);
> 
> +}
> 
> +
> 
>  /**
> 
>    Retrieves the size, in bytes, of the context buffer required for SM3 hash
> operations.
> 
> 
> 
> diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> new file mode 100644
> index 000000000000..fb57e91a9f16
> --- /dev/null
> +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> @@ -0,0 +1,145 @@
> +/** @file
> 
> +  Application for Parallelhash Function Validation.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "TestBaseCryptLib.h"
> 
> +
> 
> +//
> 
> +// Parallelhash Test Sample common parameters.
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN  OutputByteLen = 64;
> 
> +
> 
> +//
> 
> +// Parallelhash Test Sample #1 from NIST Special Publication 800-185.
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  InputSample1[] = {
> 
> +  // input data of sample1.
> 
> +  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, 0x14,
> 0x15, 0x16, 0x17,
> 
> +  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
> 
> +};
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample1ByteLen   = 24;
> // Length of sample1 input data in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID   *CustomizationSample1
> = "";        // Customization string (S) of sample1.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample1ByteLen  = 0;
> // Customization string length of sample1 in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample1      = 8;
> // Block size of sample1.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  ExpectOutputSample1[]
> = {
> 
> +  // Expected output data of sample1.
> 
> +  0xbc, 0x1e, 0xf1, 0x24, 0xda, 0x34, 0x49, 0x5e, 0x94, 0x8e, 0xad, 0x20, 0x7d,
> 0xd9, 0x84, 0x22,
> 
> +  0x35, 0xda, 0x43, 0x2d, 0x2b, 0xbc, 0x54, 0xb4, 0xc1, 0x10, 0xe6, 0x4c, 0x45,
> 0x11, 0x05, 0x53,
> 
> +  0x1b, 0x7f, 0x2a, 0x3e, 0x0c, 0xe0, 0x55, 0xc0, 0x28, 0x05, 0xe7, 0xc2, 0xde,
> 0x1f, 0xb7, 0x46,
> 
> +  0xaf, 0x97, 0xa1, 0xd0, 0x01, 0xf4, 0x3b, 0x82, 0x4e, 0x31, 0xb8, 0x76, 0x12,
> 0x41, 0x04, 0x29
> 
> +};
> 
> +
> 
> +//
> 
> +// Parallelhash Test Sample #2 from NIST Special Publication 800-185.
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  *InputSample2         =
> InputSample1;               // Input of sample2 is same as sample1.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample2ByteLen   = 24;
> // Length of sample2 input data in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID   *CustomizationSample2
> = "Parallel Data";            // Customization string (S) of sample2.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample2ByteLen  =
> 13;                         // Customization string length of sample2 in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample2      = 8;
> // Block size of sample2.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  ExpectOutputSample2[]
> = {
> 
> +  // Expected output data of sample2.
> 
> +  0xcd, 0xf1, 0x52, 0x89, 0xb5, 0x4f, 0x62, 0x12, 0xb4, 0xbc, 0x27, 0x05, 0x28,
> 0xb4, 0x95, 0x26,
> 
> +  0x00, 0x6d, 0xd9, 0xb5, 0x4e, 0x2b, 0x6a, 0xdd, 0x1e, 0xf6, 0x90, 0x0d, 0xda,
> 0x39, 0x63, 0xbb,
> 
> +  0x33, 0xa7, 0x24, 0x91, 0xf2, 0x36, 0x96, 0x9c, 0xa8, 0xaf, 0xae, 0xa2, 0x9c,
> 0x68, 0x2d, 0x47,
> 
> +  0xa3, 0x93, 0xc0, 0x65, 0xb3, 0x8e, 0x29, 0xfa, 0xe6, 0x51, 0xa2, 0x09, 0x1c,
> 0x83, 0x31, 0x10
> 
> +};
> 
> +
> 
> +//
> 
> +// Parallelhash Test Sample #3 from NIST Special Publication 800-185.
> 
> +//
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  InputSample3[] = {
> 
> +  // input data of sample3.
> 
> +  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10,
> 0x11, 0x12, 0x13,
> 
> +  0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x20, 0x21, 0x22, 0x23, 0x24,
> 0x25, 0x26, 0x27,
> 
> +  0x28, 0x29, 0x2a, 0x2b, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
> 0x39, 0x3a, 0x3b,
> 
> +  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x50,
> 0x51, 0x52, 0x53,
> 
> +  0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b
> 
> +};
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample3ByteLen   = 72;
> // Length of sample3 input data in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID   *CustomizationSample3
> = "Parallel Data";            // Customization string (S) of sample3.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample3ByteLen  =
> 13;                         // Customization string length of sample3 in bytes.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample3      = 12;
> // Block size of sample3.
> 
> +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  ExpectOutputSample3[]
> = {
> 
> +  // Expected output data of sample3.
> 
> +  0x69, 0xd0, 0xfc, 0xb7, 0x64, 0xea, 0x05, 0x5d, 0xd0, 0x93, 0x34, 0xbc, 0x60,
> 0x21, 0xcb, 0x7e,
> 
> +  0x4b, 0x61, 0x34, 0x8d, 0xff, 0x37, 0x5d, 0xa2, 0x62, 0x67, 0x1c, 0xde, 0xc3,
> 0xef, 0xfa, 0x8d,
> 
> +  0x1b, 0x45, 0x68, 0xa6, 0xcc, 0xe1, 0x6b, 0x1c, 0xad, 0x94, 0x6d, 0xdd, 0xe2,
> 0x7f, 0x6c, 0xe2,
> 
> +  0xb8, 0xde, 0xe4, 0xcd, 0x1b, 0x24, 0x85, 0x1e, 0xbf, 0x00, 0xeb, 0x90, 0xd4,
> 0x38, 0x13, 0xe9
> 
> +};
> 
> +
> 
> +UNIT_TEST_STATUS
> 
> +EFIAPI
> 
> +TestVerifyParallelHash256HashAll (
> 
> +  IN UNIT_TEST_CONTEXT  Context
> 
> +  )
> 
> +{
> 
> +  BOOLEAN  Status;
> 
> +  UINT8    Output[64];
> 
> +
> 
> +  //
> 
> +  // Test #1 using sample1.
> 
> +  //
> 
> +  Status = ParallelHash256HashAll (
> 
> +             InputSample1,
> 
> +             InputSample1ByteLen,
> 
> +             BlockSizeSample1,
> 
> +             Output,
> 
> +             OutputByteLen,
> 
> +             CustomizationSample1,
> 
> +             CustomSample1ByteLen
> 
> +             );
> 
> +  UT_ASSERT_TRUE (Status);
> 
> +
> 
> +  // Check the output with the expected output.
> 
> +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample1, OutputByteLen);
> 
> +
> 
> +  //
> 
> +  // Test #2 using sample2.
> 
> +  //
> 
> +  Status = ParallelHash256HashAll (
> 
> +             InputSample2,
> 
> +             InputSample2ByteLen,
> 
> +             BlockSizeSample2,
> 
> +             Output,
> 
> +             OutputByteLen,
> 
> +             CustomizationSample2,
> 
> +             CustomSample2ByteLen
> 
> +             );
> 
> +  UT_ASSERT_TRUE (Status);
> 
> +
> 
> +  // Check the output with the expected output.
> 
> +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample2, OutputByteLen);
> 
> +
> 
> +  //
> 
> +  // Test #3 using sample3.
> 
> +  //
> 
> +  Status = ParallelHash256HashAll (
> 
> +             InputSample3,
> 
> +             InputSample3ByteLen,
> 
> +             BlockSizeSample3,
> 
> +             Output,
> 
> +             OutputByteLen,
> 
> +             CustomizationSample3,
> 
> +             CustomSample3ByteLen
> 
> +             );
> 
> +  UT_ASSERT_TRUE (Status);
> 
> +
> 
> +  // Check the output with the expected output.
> 
> +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3, OutputByteLen);
> 
> +
> 
> +  return EFI_SUCCESS;
> 
> +}
> 
> +
> 
> +TEST_DESC  mParallelhashTest[] = {
> 
> +  //
> 
> +  // -----Description------------------------------Class----------------------Function----
> -------------Pre---Post--Context
> 
> +  //
> 
> +  { "TestVerifyParallelHash256HashAll()",
> "CryptoPkg.BaseCryptLib.ParallelHash256HashAll",
> TestVerifyParallelHash256HashAll, NULL, NULL, NULL },
> 
> +};
> 
> +
> 
> +UINTN  mParallelhashTestNum = ARRAY_SIZE (mParallelhashTest);
> 
> diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml
> index eeb388ae71c5..e21fafac1efe 100644
> --- a/CryptoPkg/CryptoPkg.ci.yaml
> +++ b/CryptoPkg/CryptoPkg.ci.yaml
> @@ -2,7 +2,7 @@
>  # CI configuration for CryptoPkg
> 
>  #
> 
>  # Copyright (c) Microsoft Corporation
> 
> -# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> 
> +# Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  ##
> 
>  {
> 
> @@ -34,6 +34,8 @@
>              "Library/OpensslLib/rand_pool.c",
> 
>              # This has OpenSSL interfaces that aren't UEFI spec compliant
> 
>              "Library/Include/CrtLibSupport.h",
> 
> +            # This has OpenSSL interfaces that aren't UEFI spec compliant
> 
> +            "Library/BaseCryptLib/Hash/CryptParallelHash.h",
> 
>              # These directories contain auto-generated OpenSSL content
> 
>              "Library/OpensslLib",
> 
>              "Library/IntrinsicLib",
> 
> diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> b/CryptoPkg/Include/Library/BaseCryptLib.h
> index f4bc7c0d73d9..7d1499350a49 100644
> --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> @@ -4,7 +4,7 @@
>    primitives (Hash Serials, HMAC, RSA, Diffie-Hellman, etc) for UEFI security
> 
>    functionality enabling.
> 
> 
> 
> -Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -753,6 +753,35 @@ Sha512HashAll (
>    OUT  UINT8       *HashValue
> 
>    );
> 
> 
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +ParallelHash256HashAll (
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  );
> 
> +
> 
>  /**
> 
>    Retrieves the size, in bytes, of the context buffer required for SM3 hash
> operations.
> 
> 
> 
> diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> index 5186a54759ae..0b30a821bc16 100644
> --- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> +++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> @@ -2,7 +2,7 @@
>    Defines the PCD_CRYPTO_SERVICE_FAMILY_ENABLE structure associated with
> 
>    gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.
> 
> 
> 
> -  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>    SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -172,6 +172,12 @@ typedef struct {
>      } Services;
> 
>      UINT32    Family;
> 
>    } Sha512;
> 
> +  union {
> 
> +    struct {
> 
> +      UINT8    HashAll : 1;
> 
> +    } Services;
> 
> +    UINT32    Family;
> 
> +  } ParallelHash;
> 
>    union {
> 
>      struct {
> 
>        UINT8    GetSubjectName             : 1;
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> index 49703fa4c963..15cf3dab105c 100644
> --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> @@ -6,7 +6,7 @@
>  #  This external input must be validated carefully to avoid security issues such as
> 
>  #  buffer overflow or integer overflow.
> 
>  #
> 
> -#  Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
> @@ -34,6 +34,7 @@
>    Hash/CryptSha256.c
> 
>    Hash/CryptSha512.c
> 
>    Hash/CryptSm3.c
> 
> +  Hash/CryptParallelHashNull.c
> 
>    Hmac/CryptHmacSha256.c
> 
>    Kdf/CryptHkdf.c
> 
>    Cipher/CryptAes.c
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
> new file mode 100644
> index 000000000000..fe08d4928e8d
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
> @@ -0,0 +1,201 @@
> +/** @file
> 
> +  ParallelHash related function and type declaration.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
> 
> +Licensed under the OpenSSL license (the "License").  You may not use
> 
> +this file except in compliance with the License.  You can obtain a copy
> 
> +in the file LICENSE in the source distribution or at
> 
> +https://www.openssl.org/source/license.html
> 
> +
> 
> +Copyright 2022 The eXtended Keccak Code Package (XKCP)
> 
> +https://github.com/XKCP/XKCP
> 
> +Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles
> Van Assche.
> 
> +Implementation by the designers, hereby denoted as "the implementer".
> 
> +For more information, feedback or questions, please refer to the Keccak Team
> website:
> 
> +https://keccak.team/
> 
> +To the extent possible under law, the implementer has waived all copyright
> 
> +and related or neighboring rights to the source code in this file.
> 
> +http://creativecommons.org/publicdomain/zero/1.0/
> 
> +**/
> 
> +
> 
> +#include "InternalCryptLib.h"
> 
> +
> 
> +#define KECCAK1600_WIDTH  1600
> 
> +
> 
> +//
> 
> +// This struct referring to m_sha3.c from opessl and modified its type name.
> 
> +//
> 
> +typedef struct {
> 
> +  uint64_t         A[5][5];
> 
> +  size_t           block_size;  /* cached ctx->digest->block_size */
> 
> +  size_t           md_size;     /* output length, variable in XOF */
> 
> +  size_t           num;         /* used bytes in below buffer */
> 
> +  unsigned char    buf[KECCAK1600_WIDTH / 8 - 32];
> 
> +  unsigned char    pad;
> 
> +} Keccak1600_Ctx;
> 
> +
> 
> +/**
> 
> +  SHA3_absorb can be called multiple times, but at each invocation
> 
> +  largest multiple of |r| out of |len| bytes are processed. Then
> 
> +  remaining amount of bytes is returned. This is done to spare caller
> 
> +  trouble of calculating the largest multiple of |r|. |r| can be viewed
> 
> +  as blocksize. It is commonly (1600 - 256*n)/8, e.g. 168, 136, 104,
> 
> +  72, but can also be (1600 - 448)/8 = 144. All this means that message
> 
> +  padding and intermediate sub-block buffering, byte- or bitwise, is
> 
> +  caller's responsibility.
> 
> +**/
> 
> +size_t
> 
> +SHA3_absorb (
> 
> +  uint64_t             A[5][5],
> 
> +  const unsigned char  *inp,
> 
> +  size_t               len,
> 
> +  size_t               r
> 
> +  );
> 
> +
> 
> +/**
> 
> +  SHA3_squeeze is called once at the end to generate |out| hash value
> 
> +  of |len| bytes.
> 
> +**/
> 
> +void
> 
> +SHA3_squeeze (
> 
> +  uint64_t       A[5][5],
> 
> +  unsigned char  *out,
> 
> +  size_t         len,
> 
> +  size_t         r
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Encode function from XKCP.
> 
> +
> 
> +  Encodes the input as a byte string in a way that can be unambiguously parsed
> 
> +  from the beginning of the string by inserting the length of the byte string
> 
> +  before the byte string representation of input.
> 
> +
> 
> +  @param[out] EncBuf  Result of left encode.
> 
> +  @param[in]  Value   Input of left encode.
> 
> +
> 
> +  @retval EncLen  Size of encode result in bytes.
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +LeftEncode (
> 
> +  OUT UINT8  *EncBuf,
> 
> +  IN  UINTN  Value
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Encode function from XKCP.
> 
> +
> 
> +  Encodes the input as a byte string in a way that can be unambiguously parsed
> 
> +  from the end of the string by inserting the length of the byte string after
> 
> +  the byte string representation of input.
> 
> +
> 
> +  @param[out] EncBuf  Result of right encode.
> 
> +  @param[in]  Value   Input of right encode.
> 
> +
> 
> +  @retval EncLen  Size of encode result in bytes.
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +RightEncode (
> 
> +  OUT UINT8  *EncBuf,
> 
> +  IN  UINTN  Value
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Keccak initial fuction.
> 
> +
> 
> +  Set up state with specified capacity.
> 
> +
> 
> +  @param[out] Context           Pointer to the context being initialized.
> 
> +  @param[in]  Pad               Delimited Suffix.
> 
> +  @param[in]  BlockSize         Size of context block.
> 
> +  @param[in]  MessageDigestLen  Size of message digest in bytes.
> 
> +
> 
> +  @retval 1  Initialize successfully.
> 
> +  @retval 0  Fail to initialize.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +KeccakInit (
> 
> +  OUT Keccak1600_Ctx  *Context,
> 
> +  IN  UINT8           Pad,
> 
> +  IN  UINTN           BlockSize,
> 
> +  IN  UINTN           MessageDigstLen
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Sha3 update fuction.
> 
> +
> 
> +  This function performs Sha3 digest on a data buffer of the specified size.
> 
> +  It can be called multiple times to compute the digest of long or discontinuous
> data streams.
> 
> +
> 
> +  @param[in,out] Context   Pointer to the Keccak context.
> 
> +  @param[in]     Data      Pointer to the buffer containing the data to be hashed.
> 
> +  @param[in]     DataSize  Size of Data buffer in bytes.
> 
> +
> 
> +  @retval 1  Update successfully.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +Sha3Update (
> 
> +  IN OUT Keccak1600_Ctx  *Context,
> 
> +  IN const VOID          *Data,
> 
> +  IN UINTN               DataSize
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Completes computation of Sha3 message digest.
> 
> +
> 
> +  This function completes sha3 hash computation and retrieves the digest value
> into
> 
> +  the specified memory. After this function has been called, the keccak context
> cannot
> 
> +  be used again.
> 
> +
> 
> +  @param[in, out]  Context        Pointer to the keccak context.
> 
> +  @param[out]      MessageDigest  Pointer to a buffer that receives the
> message digest.
> 
> +
> 
> +  @retval 1   Meaasge digest computation succeeded.
> 
> +**/
> 
> +UINT8
> 
> +EFIAPI
> 
> +Sha3Final (
> 
> +  IN OUT Keccak1600_Ctx  *Context,
> 
> +  OUT    UINT8           *MessageDigest
> 
> +  );
> 
> +
> 
> +/**
> 
> +  Computes the CSHAKE-256 message digest of a input data buffer.
> 
> +
> 
> +  This function performs the CSHAKE-256 message digest of a given data buffer,
> and places
> 
> +  the digest value into the specified memory.
> 
> +
> 
> +  @param[in]   Data               Pointer to the buffer containing the data to be
> hashed.
> 
> +  @param[in]   DataSize           Size of Data buffer in bytes.
> 
> +  @param[in]   OutputLen          Size of output in bytes.
> 
> +  @param[in]   Name               Pointer to the function name string.
> 
> +  @param[in]   NameLen            Size of the function name in bytes.
> 
> +  @param[in]   Customization      Pointer to the customization string.
> 
> +  @param[in]   CustomizationLen   Size of the customization string in bytes.
> 
> +  @param[out]  HashValue          Pointer to a buffer that receives the CSHAKE-
> 256 digest
> 
> +                                  value.
> 
> +
> 
> +  @retval TRUE   CSHAKE-256 digest computation succeeded.
> 
> +  @retval FALSE  CSHAKE-256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +BOOLEAN
> 
> +EFIAPI
> 
> +CShake256HashAll (
> 
> +  IN   CONST VOID  *Data,
> 
> +  IN   UINTN       DataSize,
> 
> +  IN   UINTN       OutputLen,
> 
> +  IN   CONST VOID  *Name,
> 
> +  IN   UINTN       NameLen,
> 
> +  IN   CONST VOID  *Customization,
> 
> +  IN   UINTN       CustomizationLen,
> 
> +  OUT  UINT8       *HashValue
> 
> +  );
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> index 0cab5f3ce36c..bf1563b06407 100644
> --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> @@ -13,7 +13,7 @@
>  #  PEM handler functions, and pseudorandom number generator functions are
> not
> 
>  #  supported in this instance.
> 
>  #
> 
> -#  Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
>  ##
> 
> @@ -40,6 +40,7 @@
>    Hash/CryptSha256.c
> 
>    Hash/CryptSm3.c
> 
>    Hash/CryptSha512.c
> 
> +  Hash/CryptParallelHashNull.c
> 
>    Hmac/CryptHmacSha256.c
> 
>    Kdf/CryptHkdf.c
> 
>    Cipher/CryptAesNull.c
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> index fdbb6edfd23e..6742da0be4fe 100644
> --- a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> @@ -11,7 +11,7 @@
>  #  functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, and
> 
>  #  authenticode signature verification functions are not supported in this
> instance.
> 
>  #
> 
> -#  Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights
> reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
> @@ -40,6 +40,7 @@
>    Hash/CryptSha256.c
> 
>    Hash/CryptSm3.c
> 
>    Hash/CryptSha512.c
> 
> +  Hash/CryptParallelHashNull.c
> 
>    Hmac/CryptHmacSha256.c
> 
>    Kdf/CryptHkdf.c
> 
>    Cipher/CryptAes.c
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> index e6470d7a2127..8f39517f78b7 100644
> --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> @@ -10,7 +10,7 @@
>  #  RSA external functions, PKCS#7 SignedData sign functions, Diffie-Hellman
> functions, and
> 
>  #  authenticode signature verification functions are not supported in this
> instance.
> 
>  #
> 
> -#  Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
>  ##
> 
> @@ -38,6 +38,10 @@
>    Hash/CryptSha256.c
> 
>    Hash/CryptSm3.c
> 
>    Hash/CryptSha512.c
> 
> +  Hash/CryptSha3.c
> 
> +  Hash/CryptXkcp.c
> 
> +  Hash/CryptCShake256.c
> 
> +  Hash/CryptParallelHash.c
> 
>    Hmac/CryptHmacSha256.c
> 
>    Kdf/CryptHkdfNull.c
> 
>    Cipher/CryptAes.c
> 
> @@ -85,6 +89,8 @@
>    OpensslLib
> 
>    IntrinsicLib
> 
>    PrintLib
> 
> +  MmServicesTableLib
> 
> +  SynchronizationLib
> 
> 
> 
>  #
> 
>  # Remove these [BuildOptions] after this library is cleaned up
> 
> diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> index faf959827b90..63d1d82d1914 100644
> --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> @@ -6,7 +6,7 @@
>  #  This external input must be validated carefully to avoid security issues such as
> 
>  #  buffer overflow or integer overflow.
> 
>  #
> 
> -#  Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
> 
> +#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  #  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> reserved.<BR>
> 
>  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  #
> 
> @@ -34,6 +34,7 @@
>    Hash/CryptSha256Null.c
> 
>    Hash/CryptSha512Null.c
> 
>    Hash/CryptSm3Null.c
> 
> +  Hash/CryptParallelHashNull.c
> 
>    Hmac/CryptHmacSha256Null.c
> 
>    Kdf/CryptHkdfNull.c
> 
>    Cipher/CryptAesNull.c
> 
> diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h
> b/CryptoPkg/Library/Include/CrtLibSupport.h
> index d257dca8fa9b..b76b140a7acf 100644
> --- a/CryptoPkg/Library/Include/CrtLibSupport.h
> +++ b/CryptoPkg/Library/Include/CrtLibSupport.h
> @@ -2,7 +2,7 @@
>    Root include file of C runtime library to support building the third-party
> 
>    cryptographic library.
> 
> 
> 
> -Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
> 
> +Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> reserved.<BR>
> 
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
> @@ -111,6 +111,7 @@ typedef UINT8   u_char;
>  typedef UINT32  uid_t;
> 
>  typedef UINT32  gid_t;
> 
>  typedef CHAR16  wchar_t;
> 
> +typedef UINT64  uint64_t;
> 
> 
> 
>  //
> 
>  // File operations are not required for EFI building,
> 
> diff --git a/CryptoPkg/Private/Protocol/Crypto.h
> b/CryptoPkg/Private/Protocol/Crypto.h
> index e378a8a8c60e..d51fc4a0e2cc 100644
> --- a/CryptoPkg/Private/Protocol/Crypto.h
> +++ b/CryptoPkg/Private/Protocol/Crypto.h
> @@ -1905,6 +1905,35 @@ BOOLEAN
>    OUT  UINT8       *HashValue
> 
>    );
> 
> 
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param[in]   Input            Pointer to the input message (X).
> 
> +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param[in]   BlockSize        The size of each block (B).
> 
> +  @param[out]  Output           Pointer to the output buffer.
> 
> +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> 
> +  @param[in]   Customization    Pointer to the customization string (S).
> 
> +  @param[in]   CustomByteLen    The length of the customization string in bytes.
> 
> +
> 
> +  @retval TRUE   ParallelHash256 digest computation succeeded.
> 
> +  @retval FALSE  ParallelHash256 digest computation failed.
> 
> +  @retval FALSE  This interface is not supported.
> 
> +
> 
> +**/
> 
> +typedef
> 
> +BOOLEAN
> 
> +(EFIAPI *EDKII_CRYPTO_PARALLEL_HASH_ALL)(
> 
> +  IN CONST VOID   *Input,
> 
> +  IN       UINTN  InputByteLen,
> 
> +  IN       UINTN  BlockSize,
> 
> +  OUT      VOID   *Output,
> 
> +  IN       UINTN  OutputByteLen,
> 
> +  IN CONST VOID   *Customization,
> 
> +  IN       UINTN  CustomByteLen
> 
> +  );
> 
> +
> 
>  // ----------------------------------------------------------------------------
> 
>  // X509
> 
>  // ----------------------------------------------------------------------------
> 
> @@ -3560,6 +3589,8 @@ struct _EDKII_CRYPTO_PROTOCOL {
>    EDKII_CRYPTO_SHA512_UPDATE                         Sha512Update;
> 
>    EDKII_CRYPTO_SHA512_FINAL                          Sha512Final;
> 
>    EDKII_CRYPTO_SHA512_HASH_ALL                       Sha512HashAll;
> 
> +  /// Parallel hash
> 
> +  EDKII_CRYPTO_PARALLEL_HASH_ALL                     ParallelHash256HashAll;
> 
>    /// X509
> 
>    EDKII_CRYPTO_X509_GET_SUBJECT_NAME                 X509GetSubjectName;
> 
>    EDKII_CRYPTO_X509_GET_COMMON_NAME                  X509GetCommonName;
> 
> diff --git a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> index ff0af36bcc80..ba6e1edb6015 100644
> --- a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> +++ b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> @@ -21,6 +21,9 @@
>  [LibraryClasses]
> 
>    OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
> 
>    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
> 
> +
> MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib
> .inf
> 
> +
> SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizati
> onLib.inf
> 
> +
> TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplat
> e.inf
> 
> 
> 
>  [LibraryClasses.AARCH64, LibraryClasses.ARM]
> 
>    RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf
> 
> diff --git
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> index 00c869265080..399db596c2d1 100644
> --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> @@ -2,6 +2,7 @@
>  # Host-based UnitTest for BaseCryptLib
> 
>  #
> 
>  # Copyright (c) Microsoft Corporation.<BR>
> 
> +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  ##
> 
> 
> 
> @@ -35,6 +36,7 @@
>    Pkcs7EkuTests.c
> 
>    OaepEncryptTests.c
> 
>    RsaPssTests.c
> 
> +  ParallelhashTests.c
> 
> 
> 
>  [Packages]
> 
>    MdePkg/MdePkg.dec
> 
> @@ -45,3 +47,5 @@
>    DebugLib
> 
>    BaseCryptLib
> 
>    UnitTestLib
> 
> +  MmServicesTableLib
> 
> +  SynchronizationLib
> 
> --
> 2.26.2.windows.1
> 
> 
> 
> -=-=-=-=-=-=
> Groups.io Links: You receive all messages sent to this group.
> View/Reply Online (#87382): https://edk2.groups.io/g/devel/message/87382
> Mute This Topic: https://groups.io/mt/89658124/1772286
> Group Owner: devel+owner@edk2.groups.io
> Unsubscribe: https://edk2.groups.io/g/devel/unsub [jiewen.yao@intel.com]
> -=-=-=-=-=-=
> 


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [edk2-devel] [PATCH v5 1/1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
  2022-03-17  2:43   ` Li, Zhihao
@ 2022-03-17  3:24     ` Yao, Jiewen
  0 siblings, 0 replies; 4+ messages in thread
From: Yao, Jiewen @ 2022-03-17  3:24 UTC (permalink / raw)
  To: Li, Zhihao, devel@edk2.groups.io
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Fu, Siyuan

Sounds good. Thanks for the update.

> -----Original Message-----
> From: Li, Zhihao <zhihao.li@intel.com>
> Sent: Thursday, March 17, 2022 10:43 AM
> To: Yao, Jiewen <jiewen.yao@intel.com>; devel@edk2.groups.io
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>;
> Jiang, Guomin <guomin.jiang@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>
> Subject: RE: [edk2-devel] [PATCH v5 1/1] CryptoPkg: Add new hash algorithm
> ParallelHash256HashAll in BaseCryptLib.
> 
> Will send patch_v6 with following update soon.
> 1. adjust the position of new field in the data structure.
> 2.update the version of data structure if it existing.
> 3.With the usability test, the CrytoLibOnProtocol version code can be used
> normally as static version.
> 
> Best Regard
> Zhihao
> 
> 
> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: Monday, March 14, 2022 1:50 PM
> To: devel@edk2.groups.io; Li, Zhihao <zhihao.li@intel.com>
> Cc: Wang, Jian J <jian.j.wang@intel.com>; Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>;
> Jiang, Guomin <guomin.jiang@intel.com>; Fu, Siyuan <siyuan.fu@intel.com>
> Subject: RE: [edk2-devel] [PATCH v5 1/1] CryptoPkg: Add new hash algorithm
> ParallelHash256HashAll in BaseCryptLib.
> 
> Thanks. It is close to final version, but there are some compatibility issue need to
> be address.
> 
> 1) Whenever you add a new field in the data structure, please add it at the end.
> Don't add them in the middle.
> E.g. PCD_CRYPTO_SERVICE_FAMILY_ENABLE, _EDKII_CRYPTO_PROTOCOL
> 
> 2) Whenever you add a new field for a data structure, please remember to
> increase the version.
> E.g. EDKII_CRYPTO_VERSION
> 
> 
> 3) Please clarify if you have tested the CrytoLibOnProtocol version code.
> 
> Thank you
> Yao Jiewen
> 
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Li, Zhihao
> > Sent: Wednesday, March 9, 2022 4:44 PM
> > To: devel@edk2.groups.io
> > Cc: Yao, Jiewen <jiewen.yao@intel.com>; Wang, Jian J
> <jian.j.wang@intel.com>;
> > Lu, Xiaoyu1 <xiaoyu1.lu@intel.com>; Jiang, Guomin
> <guomin.jiang@intel.com>;
> > Fu, Siyuan <siyuan.fu@intel.com>
> > Subject: [edk2-devel] [PATCH v5 1/1] CryptoPkg: Add new hash algorithm
> > ParallelHash256HashAll in BaseCryptLib.
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3596
> >
> > Parallel hash function ParallelHash256HashAll, as defined in NIST's
> > Special Publication 800-185, published December 2016. It utilizes
> > multi-process to calculate the digest.
> >
> > Some modifications to pass CI test.
> >
> > Cc: Jiewen Yao <jiewen.yao@intel.com>
> > Cc: Jian J Wang <jian.j.wang@intel.com>
> > Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
> > Cc: Guomin Jiang <guomin.jiang@intel.com>
> > Cc: Siyuan Fu <siyuan.fu@intel.com>
> > Cc: Zhihao Li <zhihao.li@intel.com>
> >
> > Signed-off-by: Zhihao Li <zhihao.li@intel.com>
> > ---
> >  CryptoPkg/Driver/Crypto.c                                             |  36 ++-
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                  | 282
> > ++++++++++++++++++++
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c               | 278
> > +++++++++++++++++++
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c           |  40 +++
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                       | 166
> > ++++++++++++
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                       | 107
> ++++++++
> >  CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c       |  40
> +++
> >  CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c                |  34 ++-
> >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c      | 145
> > ++++++++++
> >  CryptoPkg/CryptoPkg.ci.yaml                                           |   4 +-
> >  CryptoPkg/Include/Library/BaseCryptLib.h                              |  31 ++-
> >  CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h                  |   8 +-
> >  CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf                       |   3 +-
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h               | 201
> > ++++++++++++++
> >  CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf                        |   3 +-
> >  CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf                    |   3 +-
> >  CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                        |   8 +-
> >  CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf               |   3 +-
> >  CryptoPkg/Library/Include/CrtLibSupport.h                             |   3 +-
> >  CryptoPkg/Private/Protocol/Crypto.h                                   |  31 +++
> >  CryptoPkg/Test/CryptoPkgHostUnitTest.dsc                              |   3 +
> >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf |   4
> +
> >  22 files changed, 1422 insertions(+), 11 deletions(-)
> >
> > diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
> > index d5d6aa8e5820..35312e0818a0 100644
> > --- a/CryptoPkg/Driver/Crypto.c
> > +++ b/CryptoPkg/Driver/Crypto.c
> > @@ -3,7 +3,7 @@
> >    from BaseCryptLib and TlsLib.
> >
> >
> >
> >    Copyright (C) Microsoft Corporation. All rights reserved.
> >
> > -  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> >
> > +  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >    SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> >
> >  **/
> >
> > @@ -1314,6 +1314,38 @@ CryptoServiceSha512HashAll (
> >    return CALL_BASECRYPTLIB (Sha512.Services.HashAll, Sha512HashAll, (Data,
> > DataSize, HashValue), FALSE);
> >
> >  }
> >
> >
> >
> > +/**
> >
> > +  Parallel hash function ParallelHash256, as defined in NIST's Special
> Publication
> > 800-185,
> >
> > +  published December 2016.
> >
> > +
> >
> > +  @param[in]   Input            Pointer to the input message (X).
> >
> > +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> > input data.
> >
> > +  @param[in]   BlockSize        The size of each block (B).
> >
> > +  @param[out]  Output           Pointer to the output buffer.
> >
> > +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> >
> > +  @param[in]   Customization    Pointer to the customization string (S).
> >
> > +  @param[in]   CustomByteLen    The length of the customization string in
> bytes.
> >
> > +
> >
> > +  @retval TRUE   ParallelHash256 digest computation succeeded.
> >
> > +  @retval FALSE  ParallelHash256 digest computation failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +CryptoServiceParallelHash256HashAll (
> >
> > +  IN CONST VOID   *Input,
> >
> > +  IN       UINTN  InputByteLen,
> >
> > +  IN       UINTN  BlockSize,
> >
> > +  OUT      VOID   *Output,
> >
> > +  IN       UINTN  OutputByteLen,
> >
> > +  IN CONST VOID   *Customization,
> >
> > +  IN       UINTN  CustomByteLen
> >
> > +  )
> >
> > +{
> >
> > +  return CALL_BASECRYPTLIB (ParallelHash.Services.HashAll,
> > ParallelHash256HashAll, (Input, InputByteLen, BlockSize, Output,
> OutputByteLen,
> > Customization, CustomByteLen), FALSE);
> >
> > +}
> >
> > +
> >
> >  /**
> >
> >    Retrieves the size, in bytes, of the context buffer required for SM3 hash
> > operations.
> >
> >
> >
> > @@ -4590,6 +4622,8 @@ const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
> >    CryptoServiceSha512Update,
> >
> >    CryptoServiceSha512Final,
> >
> >    CryptoServiceSha512HashAll,
> >
> > +  /// Parallel hash
> >
> > +  CryptoServiceParallelHash256HashAll,
> >
> >    /// X509
> >
> >    CryptoServiceX509GetSubjectName,
> >
> >    CryptoServiceX509GetCommonName,
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > new file mode 100644
> > index 000000000000..96e3c8eb02e1
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > @@ -0,0 +1,282 @@
> > +/** @file
> >
> > +  cSHAKE-256 Digest Wrapper Implementations.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "CryptParallelHash.h"
> >
> > +
> >
> > +#define  CSHAKE256_SECURITY_STRENGTH  256
> >
> > +#define  CSHAKE256_RATE_IN_BYTES      136
> >
> > +
> >
> > +const CHAR8  mZeroPadding[CSHAKE256_RATE_IN_BYTES] = { 0 };
> >
> > +
> >
> > +/**
> >
> > +  CShake256 initial function.
> >
> > +
> >
> > +  Initializes user-supplied memory pointed by CShake256Context as cSHAKE-
> 256
> > hash context for
> >
> > +  subsequent use.
> >
> > +
> >
> > +  @param[out] CShake256Context  Pointer to cSHAKE-256 context being
> > initialized.
> >
> > +  @param[in]  OutputLen         The desired number of output length in bytes.
> >
> > +  @param[in]  Name              Pointer to the function name string.
> >
> > +  @param[in]  NameLen           The length of the function name in bytes.
> >
> > +  @param[in]  Customization     Pointer to the customization string.
> >
> > +  @param[in]  CustomizationLen  The length of the customization string in
> > bytes.
> >
> > +
> >
> > +  @retval TRUE   cSHAKE-256 context initialization succeeded.
> >
> > +  @retval FALSE  cSHAKE-256 context initialization failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +CShake256Init (
> >
> > +  OUT  VOID        *CShake256Context,
> >
> > +  IN   UINTN       OutputLen,
> >
> > +  IN   CONST VOID  *Name,
> >
> > +  IN   UINTN       NameLen,
> >
> > +  IN   CONST VOID  *Customization,
> >
> > +  IN   UINTN       CustomizationLen
> >
> > +  )
> >
> > +{
> >
> > +  BOOLEAN  Status;
> >
> > +  UINT8    EncBuf[sizeof (UINTN) + 1];
> >
> > +  UINTN    EncLen;
> >
> > +  UINTN    AbsorbLen;
> >
> > +  UINTN    PadLen;
> >
> > +
> >
> > +  //
> >
> > +  // Check input parameters.
> >
> > +  //
> >
> > +  if ((CShake256Context == NULL) || (OutputLen == 0) || ((NameLen != 0) &&
> > (Name == NULL)) || ((CustomizationLen != 0) && (Customization == NULL))) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Initialize KECCAK context with pad value and block size.
> >
> > +  //
> >
> > +  if ((NameLen == 0) && (CustomizationLen == 0)) {
> >
> > +    //
> >
> > +    // When N and S are both empty strings, cSHAKE(X, L, N, S) is equivalent to
> >
> > +    // SHAKE as defined in FIPS 202.
> >
> > +    //
> >
> > +    Status = (BOOLEAN)KeccakInit (
> >
> > +                        (Keccak1600_Ctx *)CShake256Context,
> >
> > +                        '\x1f',
> >
> > +                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) /
> 8,
> >
> > +                        OutputLen
> >
> > +                        );
> >
> > +
> >
> > +    return Status;
> >
> > +  } else {
> >
> > +    Status = (BOOLEAN)KeccakInit (
> >
> > +                        (Keccak1600_Ctx *)CShake256Context,
> >
> > +                        '\x04',
> >
> > +                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) /
> 8,
> >
> > +                        OutputLen
> >
> > +                        );
> >
> > +    if (!Status) {
> >
> > +      return FALSE;
> >
> > +    }
> >
> > +
> >
> > +    AbsorbLen = 0;
> >
> > +    //
> >
> > +    // Absorb Absorb bytepad(.., rate).
> >
> > +    //
> >
> > +    EncLen = LeftEncode (EncBuf, CSHAKE256_RATE_IN_BYTES);
> >
> > +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> > EncBuf, EncLen);
> >
> > +    if (!Status) {
> >
> > +      return FALSE;
> >
> > +    }
> >
> > +
> >
> > +    AbsorbLen += EncLen;
> >
> > +
> >
> > +    //
> >
> > +    // Absorb encode_string(N).
> >
> > +    //
> >
> > +    EncLen = LeftEncode (EncBuf, NameLen * 8);
> >
> > +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> > EncBuf, EncLen);
> >
> > +    if (!Status) {
> >
> > +      return FALSE;
> >
> > +    }
> >
> > +
> >
> > +    AbsorbLen += EncLen;
> >
> > +    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> > Name, NameLen);
> >
> > +    if (!Status) {
> >
> > +      return FALSE;
> >
> > +    }
> >
> > +
> >
> > +    AbsorbLen += NameLen;
> >
> > +
> >
> > +    //
> >
> > +    // Absorb encode_string(S).
> >
> > +    //
> >
> > +    EncLen = LeftEncode (EncBuf, CustomizationLen * 8);
> >
> > +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> > EncBuf, EncLen);
> >
> > +    if (!Status) {
> >
> > +      return FALSE;
> >
> > +    }
> >
> > +
> >
> > +    AbsorbLen += EncLen;
> >
> > +    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> > Customization, CustomizationLen);
> >
> > +    if (!Status) {
> >
> > +      return FALSE;
> >
> > +    }
> >
> > +
> >
> > +    AbsorbLen += CustomizationLen;
> >
> > +
> >
> > +    //
> >
> > +    // Absorb zero padding up to rate.
> >
> > +    //
> >
> > +    PadLen = CSHAKE256_RATE_IN_BYTES - AbsorbLen %
> > CSHAKE256_RATE_IN_BYTES;
> >
> > +    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> > mZeroPadding, PadLen);
> >
> > +    if (!Status) {
> >
> > +      return FALSE;
> >
> > +    }
> >
> > +
> >
> > +    return TRUE;
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Digests the input data and updates cSHAKE-256 context.
> >
> > +
> >
> > +  This function performs cSHAKE-256 digest on a data buffer of the specified
> > size.
> >
> > +  It can be called multiple times to compute the digest of long or
> discontinuous
> > data streams.
> >
> > +  cSHAKE-256 context should be already correctly initialized by
> CShake256Init(),
> > and should not be finalized
> >
> > +  by CShake256Final(). Behavior with invalid context is undefined.
> >
> > +
> >
> > +  @param[in, out]  CShake256Context   Pointer to the cSHAKE-256 context.
> >
> > +  @param[in]       Data               Pointer to the buffer containing the data to be
> > hashed.
> >
> > +  @param[in]       DataSize           Size of Data buffer in bytes.
> >
> > +
> >
> > +  @retval TRUE   cSHAKE-256 data digest succeeded.
> >
> > +  @retval FALSE  cSHAKE-256 data digest failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +CShake256Update (
> >
> > +  IN OUT  VOID        *CShake256Context,
> >
> > +  IN      CONST VOID  *Data,
> >
> > +  IN      UINTN       DataSize
> >
> > +  )
> >
> > +{
> >
> > +  //
> >
> > +  // Check input parameters.
> >
> > +  //
> >
> > +  if (CShake256Context == NULL) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Check invalid parameters, in case that only DataLength was checked in
> > OpenSSL.
> >
> > +  //
> >
> > +  if ((Data == NULL) && (DataSize != 0)) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  return (BOOLEAN)(Sha3Update ((Keccak1600_Ctx *)CShake256Context,
> Data,
> > DataSize));
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Completes computation of the cSHAKE-256 digest value.
> >
> > +
> >
> > +  This function completes cSHAKE-256 hash computation and retrieves the
> > digest value into
> >
> > +  the specified memory. After this function has been called, the cSHAKE-256
> > context cannot
> >
> > +  be used again.
> >
> > +  cSHAKE-256 context should be already correctly initialized by
> CShake256Init(),
> > and should not be
> >
> > +  finalized by CShake256Final(). Behavior with invalid cSHAKE-256 context is
> > undefined.
> >
> > +
> >
> > +  @param[in, out]  CShake256Context  Pointer to the cSHAKE-256 context.
> >
> > +  @param[out]      HashValue         Pointer to a buffer that receives the
> cSHAKE-
> > 256 digest
> >
> > +                                     value.
> >
> > +
> >
> > +  @retval TRUE   cSHAKE-256 digest computation succeeded.
> >
> > +  @retval FALSE  cSHAKE-256 digest computation failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +CShake256Final (
> >
> > +  IN OUT  VOID   *CShake256Context,
> >
> > +  OUT     UINT8  *HashValue
> >
> > +  )
> >
> > +{
> >
> > +  //
> >
> > +  // Check input parameters.
> >
> > +  //
> >
> > +  if ((CShake256Context == NULL) || (HashValue == NULL)) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // cSHAKE-256 Hash Finalization.
> >
> > +  //
> >
> > +  return (BOOLEAN)(Sha3Final ((Keccak1600_Ctx *)CShake256Context,
> > HashValue));
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Computes the CSHAKE-256 message digest of a input data buffer.
> >
> > +
> >
> > +  This function performs the CSHAKE-256 message digest of a given data
> buffer,
> > and places
> >
> > +  the digest value into the specified memory.
> >
> > +
> >
> > +  @param[in]   Data               Pointer to the buffer containing the data to be
> > hashed.
> >
> > +  @param[in]   DataSize           Size of Data buffer in bytes.
> >
> > +  @param[in]   OutputLen          Size of output in bytes.
> >
> > +  @param[in]   Name               Pointer to the function name string.
> >
> > +  @param[in]   NameLen            Size of the function name in bytes.
> >
> > +  @param[in]   Customization      Pointer to the customization string.
> >
> > +  @param[in]   CustomizationLen   Size of the customization string in bytes.
> >
> > +  @param[out]  HashValue          Pointer to a buffer that receives the CSHAKE-
> > 256 digest
> >
> > +                                  value.
> >
> > +
> >
> > +  @retval TRUE   CSHAKE-256 digest computation succeeded.
> >
> > +  @retval FALSE  CSHAKE-256 digest computation failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +CShake256HashAll (
> >
> > +  IN   CONST VOID  *Data,
> >
> > +  IN   UINTN       DataSize,
> >
> > +  IN   UINTN       OutputLen,
> >
> > +  IN   CONST VOID  *Name,
> >
> > +  IN   UINTN       NameLen,
> >
> > +  IN   CONST VOID  *Customization,
> >
> > +  IN   UINTN       CustomizationLen,
> >
> > +  OUT  UINT8       *HashValue
> >
> > +  )
> >
> > +{
> >
> > +  BOOLEAN         Status;
> >
> > +  Keccak1600_Ctx  Ctx;
> >
> > +
> >
> > +  //
> >
> > +  // Check input parameters.
> >
> > +  //
> >
> > +  if (HashValue == NULL) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  if ((Data == NULL) && (DataSize != 0)) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  Status = CShake256Init (&Ctx, OutputLen, Name, NameLen, Customization,
> > CustomizationLen);
> >
> > +  if (!Status) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  Status = CShake256Update (&Ctx, Data, DataSize);
> >
> > +  if (!Status) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  return CShake256Final (&Ctx, HashValue);
> >
> > +}
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> > new file mode 100644
> > index 000000000000..f7ce9dbf523e
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> > @@ -0,0 +1,278 @@
> > +/** @file
> >
> > +  ParallelHash Implementation.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "CryptParallelHash.h"
> >
> > +#include <Library/MmServicesTableLib.h>
> >
> > +#include <Library/SynchronizationLib.h>
> >
> > +
> >
> > +#define PARALLELHASH_CUSTOMIZATION  "ParallelHash"
> >
> > +
> >
> > +UINTN      mBlockNum;
> >
> > +UINTN      mBlockSize;
> >
> > +UINTN      mLastBlockSize;
> >
> > +UINT8      *mInput;
> >
> > +UINTN      mBlockResultSize;
> >
> > +UINT8      *mBlockHashResult;
> >
> > +BOOLEAN    *mBlockIsCompleted;
> >
> > +SPIN_LOCK  *mSpinLockList;
> >
> > +
> >
> > +/**
> >
> > +  Complete computation of digest of each block.
> >
> > +
> >
> > +  Each AP perform the function called by BSP.
> >
> > +
> >
> > +  @param[in] ProcedureArgument Argument of the procedure.
> >
> > +**/
> >
> > +VOID
> >
> > +EFIAPI
> >
> > +ParallelHashApExecute (
> >
> > +  IN VOID  *ProcedureArgument
> >
> > +  )
> >
> > +{
> >
> > +  UINTN    Index;
> >
> > +  BOOLEAN  Status;
> >
> > +
> >
> > +  for (Index = 0; Index < mBlockNum; Index++) {
> >
> > +    if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
> >
> > +      //
> >
> > +      // Completed, try next one.
> >
> > +      //
> >
> > +      if (mBlockIsCompleted[Index]) {
> >
> > +        ReleaseSpinLock (&mSpinLockList[Index]);
> >
> > +        continue;
> >
> > +      }
> >
> > +
> >
> > +      //
> >
> > +      // Calculate CShake256 for this block.
> >
> > +      //
> >
> > +      Status = CShake256HashAll (
> >
> > +                 mInput + Index * mBlockSize,
> >
> > +                 (Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
> >
> > +                 mBlockResultSize,
> >
> > +                 NULL,
> >
> > +                 0,
> >
> > +                 NULL,
> >
> > +                 0,
> >
> > +                 mBlockHashResult + Index * mBlockResultSize
> >
> > +                 );
> >
> > +      if (!EFI_ERROR (Status)) {
> >
> > +        mBlockIsCompleted[Index] = TRUE;
> >
> > +      }
> >
> > +
> >
> > +      ReleaseSpinLock (&mSpinLockList[Index]);
> >
> > +    }
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Dispatch the block task to each AP in SMM mode.
> >
> > +
> >
> > +**/
> >
> > +VOID
> >
> > +EFIAPI
> >
> > +MmDispatchBlockToAP (
> >
> > +  VOID
> >
> > +  )
> >
> > +{
> >
> > +  UINTN  Index;
> >
> > +
> >
> > +  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
> >
> > +    if (Index != gMmst->CurrentlyExecutingCpu) {
> >
> > +      gMmst->MmStartupThisAp (ParallelHashApExecute, Index, NULL);
> >
> > +    }
> >
> > +  }
> >
> > +
> >
> > +  return;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Parallel hash function ParallelHash256, as defined in NIST's Special
> Publication
> > 800-185,
> >
> > +  published December 2016.
> >
> > +
> >
> > +  @param[in]   Input            Pointer to the input message (X).
> >
> > +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> > input data.
> >
> > +  @param[in]   BlockSize        The size of each block (B).
> >
> > +  @param[out]  Output           Pointer to the output buffer.
> >
> > +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> >
> > +  @param[in]   Customization    Pointer to the customization string (S).
> >
> > +  @param[in]   CustomByteLen    The length of the customization string in
> bytes.
> >
> > +
> >
> > +  @retval TRUE   ParallelHash256 digest computation succeeded.
> >
> > +  @retval FALSE  ParallelHash256 digest computation failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +ParallelHash256HashAll (
> >
> > +  IN CONST VOID   *Input,
> >
> > +  IN       UINTN  InputByteLen,
> >
> > +  IN       UINTN  BlockSize,
> >
> > +  OUT      VOID   *Output,
> >
> > +  IN       UINTN  OutputByteLen,
> >
> > +  IN CONST VOID   *Customization,
> >
> > +  IN       UINTN  CustomByteLen
> >
> > +  )
> >
> > +{
> >
> > +  UINT8    EncBufB[sizeof (UINTN)+1];
> >
> > +  UINTN    EncSizeB;
> >
> > +  UINT8    EncBufN[sizeof (UINTN)+1];
> >
> > +  UINTN    EncSizeN;
> >
> > +  UINT8    EncBufL[sizeof (UINTN)+1];
> >
> > +  UINTN    EncSizeL;
> >
> > +  UINTN    Index;
> >
> > +  UINT8    *CombinedInput;
> >
> > +  UINTN    CombinedInputSize;
> >
> > +  BOOLEAN  AllCompleted;
> >
> > +  UINTN    Offset;
> >
> > +  BOOLEAN  ReturnValue;
> >
> > +
> >
> > +  if ((InputByteLen == 0) || (OutputByteLen == 0) || (BlockSize == 0)) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  if ((Input == NULL) || (Output == NULL)) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  if ((CustomByteLen != 0) && (Customization == NULL)) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  mBlockSize = BlockSize;
> >
> > +
> >
> > +  //
> >
> > +  // Calculate block number n.
> >
> > +  //
> >
> > +  mBlockNum = InputByteLen % mBlockSize == 0 ? InputByteLen / mBlockSize :
> > InputByteLen / mBlockSize + 1;
> >
> > +
> >
> > +  //
> >
> > +  // Set hash result size of each block in bytes.
> >
> > +  //
> >
> > +  mBlockResultSize = OutputByteLen;
> >
> > +
> >
> > +  //
> >
> > +  // Encode B, n, L to string and record size.
> >
> > +  //
> >
> > +  EncSizeB = LeftEncode (EncBufB, mBlockSize);
> >
> > +  EncSizeN = RightEncode (EncBufN, mBlockNum);
> >
> > +  EncSizeL = RightEncode (EncBufL, OutputByteLen * CHAR_BIT);
> >
> > +
> >
> > +  //
> >
> > +  // Allocate buffer for combined input (newX), Block completed flag and
> > SpinLock.
> >
> > +  //
> >
> > +  CombinedInputSize = EncSizeB + EncSizeN + EncSizeL + mBlockNum *
> > mBlockResultSize;
> >
> > +  CombinedInput     = AllocateZeroPool (CombinedInputSize);
> >
> > +  mBlockIsCompleted = AllocateZeroPool (mBlockNum * sizeof (BOOLEAN));
> >
> > +  mSpinLockList     = AllocatePool (mBlockNum * sizeof (SPIN_LOCK));
> >
> > +  if ((CombinedInput == NULL) || (mBlockIsCompleted == NULL) ||
> > (mSpinLockList == NULL)) {
> >
> > +    ReturnValue = FALSE;
> >
> > +    goto Exit;
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Fill LeftEncode(B).
> >
> > +  //
> >
> > +  CopyMem (CombinedInput, EncBufB, EncSizeB);
> >
> > +
> >
> > +  //
> >
> > +  // Prepare for parallel hash.
> >
> > +  //
> >
> > +  mBlockHashResult = CombinedInput + EncSizeB;
> >
> > +  mInput           = (UINT8 *)Input;
> >
> > +  mLastBlockSize   = InputByteLen % mBlockSize == 0 ? mBlockSize :
> > InputByteLen % mBlockSize;
> >
> > +
> >
> > +  //
> >
> > +  // Initialize SpinLock for each result block.
> >
> > +  //
> >
> > +  for (Index = 0; Index < mBlockNum; Index++) {
> >
> > +    InitializeSpinLock (&mSpinLockList[Index]);
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Dispatch blocklist to each AP.
> >
> > +  //
> >
> > +  if (gMmst != NULL) {
> >
> > +    MmDispatchBlockToAP ();
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Wait until all block hash completed.
> >
> > +  //
> >
> > +  do {
> >
> > +    AllCompleted = TRUE;
> >
> > +    for (Index = 0; Index < mBlockNum; Index++) {
> >
> > +      if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
> >
> > +        if (!mBlockIsCompleted[Index]) {
> >
> > +          AllCompleted = FALSE;
> >
> > +          ReturnValue  = CShake256HashAll (
> >
> > +                           mInput + Index * mBlockSize,
> >
> > +                           (Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
> >
> > +                           mBlockResultSize,
> >
> > +                           NULL,
> >
> > +                           0,
> >
> > +                           NULL,
> >
> > +                           0,
> >
> > +                           mBlockHashResult + Index * mBlockResultSize
> >
> > +                           );
> >
> > +          if (ReturnValue) {
> >
> > +            mBlockIsCompleted[Index] = TRUE;
> >
> > +          }
> >
> > +
> >
> > +          ReleaseSpinLock (&mSpinLockList[Index]);
> >
> > +          break;
> >
> > +        }
> >
> > +
> >
> > +        ReleaseSpinLock (&mSpinLockList[Index]);
> >
> > +      } else {
> >
> > +        AllCompleted = FALSE;
> >
> > +        break;
> >
> > +      }
> >
> > +    }
> >
> > +  } while (!AllCompleted);
> >
> > +
> >
> > +  //
> >
> > +  // Fill LeftEncode(n).
> >
> > +  //
> >
> > +  Offset = EncSizeB + mBlockNum * mBlockResultSize;
> >
> > +  CopyMem (CombinedInput + Offset, EncBufN, EncSizeN);
> >
> > +
> >
> > +  //
> >
> > +  // Fill LeftEncode(L).
> >
> > +  //
> >
> > +  Offset += EncSizeN;
> >
> > +  CopyMem (CombinedInput + Offset, EncBufL, EncSizeL);
> >
> > +
> >
> > +  ReturnValue = CShake256HashAll (
> >
> > +                  CombinedInput,
> >
> > +                  CombinedInputSize,
> >
> > +                  OutputByteLen,
> >
> > +                  PARALLELHASH_CUSTOMIZATION,
> >
> > +                  AsciiStrLen (PARALLELHASH_CUSTOMIZATION),
> >
> > +                  Customization,
> >
> > +                  CustomByteLen,
> >
> > +                  Output
> >
> > +                  );
> >
> > +
> >
> > +Exit:
> >
> > +  ZeroMem (CombinedInput, CombinedInputSize);
> >
> > +
> >
> > +  if (CombinedInput != NULL) {
> >
> > +    FreePool (CombinedInput);
> >
> > +  }
> >
> > +
> >
> > +  if (mSpinLockList != NULL) {
> >
> > +    FreePool ((VOID *)mSpinLockList);
> >
> > +  }
> >
> > +
> >
> > +  if (mBlockIsCompleted != NULL) {
> >
> > +    FreePool (mBlockIsCompleted);
> >
> > +  }
> >
> > +
> >
> > +  return ReturnValue;
> >
> > +}
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
> > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
> > new file mode 100644
> > index 000000000000..2bf89594def5
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
> > @@ -0,0 +1,40 @@
> > +/** @file
> >
> > +  ParallelHash Implementation which does not provide real capabilities.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "InternalCryptLib.h"
> >
> > +
> >
> > +/**
> >
> > +  Parallel hash function ParallelHash256, as defined in NIST's Special
> Publication
> > 800-185,
> >
> > +  published December 2016.
> >
> > +
> >
> > +  @param[in]   Input            Pointer to the input message (X).
> >
> > +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> > input data.
> >
> > +  @param[in]   BlockSize        The size of each block (B).
> >
> > +  @param[out]  Output           Pointer to the output buffer.
> >
> > +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> >
> > +  @param[in]   Customization    Pointer to the customization string (S).
> >
> > +  @param[in]   CustomByteLen    The length of the customization string in
> bytes.
> >
> > +
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +ParallelHash256HashAll (
> >
> > +  IN CONST VOID   *Input,
> >
> > +  IN       UINTN  InputByteLen,
> >
> > +  IN       UINTN  BlockSize,
> >
> > +  OUT      VOID   *Output,
> >
> > +  IN       UINTN  OutputByteLen,
> >
> > +  IN CONST VOID   *Customization,
> >
> > +  IN       UINTN  CustomByteLen
> >
> > +  )
> >
> > +{
> >
> > +  ASSERT (FALSE);
> >
> > +  return FALSE;
> >
> > +}
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > new file mode 100644
> > index 000000000000..6abafc3c00e6
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > @@ -0,0 +1,166 @@
> > +/** @file
> >
> > +  SHA3 realted functions from OpenSSL.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
> >
> > +Licensed under the OpenSSL license (the "License").  You may not use
> >
> > +this file except in compliance with the License.  You can obtain a copy
> >
> > +in the file LICENSE in the source distribution or at
> >
> > +https://www.openssl.org/source/license.html
> >
> > +**/
> >
> > +
> >
> > +#include "CryptParallelHash.h"
> >
> > +
> >
> > +/**
> >
> > +  Keccak initial fuction.
> >
> > +
> >
> > +  Set up state with specified capacity.
> >
> > +
> >
> > +  @param[out] Context           Pointer to the context being initialized.
> >
> > +  @param[in]  Pad               Delimited Suffix.
> >
> > +  @param[in]  BlockSize         Size of context block.
> >
> > +  @param[in]  MessageDigestLen  Size of message digest in bytes.
> >
> > +
> >
> > +  @retval 1  Initialize successfully.
> >
> > +  @retval 0  Fail to initialize.
> >
> > +**/
> >
> > +UINT8
> >
> > +EFIAPI
> >
> > +KeccakInit (
> >
> > +  OUT Keccak1600_Ctx  *Context,
> >
> > +  IN  UINT8           Pad,
> >
> > +  IN  UINTN           BlockSize,
> >
> > +  IN  UINTN           MessageDigestLen
> >
> > +  )
> >
> > +{
> >
> > +  if (BlockSize <= sizeof (Context->buf)) {
> >
> > +    memset (Context->A, 0, sizeof (Context->A));
> >
> > +
> >
> > +    Context->num        = 0;
> >
> > +    Context->block_size = BlockSize;
> >
> > +    Context->md_size    = MessageDigestLen;
> >
> > +    Context->pad        = Pad;
> >
> > +
> >
> > +    return 1;
> >
> > +  }
> >
> > +
> >
> > +  return 0;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Sha3 update fuction.
> >
> > +
> >
> > +  This function performs Sha3 digest on a data buffer of the specified size.
> >
> > +  It can be called multiple times to compute the digest of long or
> discontinuous
> > data streams.
> >
> > +
> >
> > +  @param[in,out] Context   Pointer to the Keccak context.
> >
> > +  @param[in]     Data      Pointer to the buffer containing the data to be
> hashed.
> >
> > +  @param[in]     DataSize  Size of Data buffer in bytes.
> >
> > +
> >
> > +  @retval 1  Update successfully.
> >
> > +**/
> >
> > +UINT8
> >
> > +EFIAPI
> >
> > +Sha3Update (
> >
> > +  IN OUT Keccak1600_Ctx  *Context,
> >
> > +  IN const VOID          *Data,
> >
> > +  IN UINTN               DataSize
> >
> > +  )
> >
> > +{
> >
> > +  const UINT8  *DataCopy;
> >
> > +  UINTN        BlockSize;
> >
> > +  UINTN        Num;
> >
> > +  UINTN        Rem;
> >
> > +
> >
> > +  DataCopy  = Data;
> >
> > +  BlockSize = (UINT8)(Context->block_size);
> >
> > +
> >
> > +  if (DataSize == 0) {
> >
> > +    return 1;
> >
> > +  }
> >
> > +
> >
> > +  if ((Num = Context->num) != 0) {
> >
> > +    //
> >
> > +    // process intermediate buffer
> >
> > +    //
> >
> > +    Rem = BlockSize - Num;
> >
> > +
> >
> > +    if (DataSize < Rem) {
> >
> > +      memcpy (Context->buf + Num, DataCopy, DataSize);
> >
> > +      Context->num += DataSize;
> >
> > +      return 1;
> >
> > +    }
> >
> > +
> >
> > +    //
> >
> > +    // We have enough data to fill or overflow the intermediate
> >
> > +    // buffer. So we append |Rem| bytes and process the block,
> >
> > +    // leaving the rest for later processing.
> >
> > +    //
> >
> > +    memcpy (Context->buf + Num, DataCopy, Rem);
> >
> > +    DataCopy += Rem;
> >
> > +    DataSize -= Rem;
> >
> > +    (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
> >
> > +    Context->num = 0;
> >
> > +    // Context->buf is processed, Context->num is guaranteed to be zero.
> >
> > +  }
> >
> > +
> >
> > +  if (DataSize >= BlockSize) {
> >
> > +    Rem = SHA3_absorb (Context->A, DataCopy, DataSize, BlockSize);
> >
> > +  } else {
> >
> > +    Rem = DataSize;
> >
> > +  }
> >
> > +
> >
> > +  if (Rem > 0) {
> >
> > +    memcpy (Context->buf, DataCopy + DataSize - Rem, Rem);
> >
> > +    Context->num = Rem;
> >
> > +  }
> >
> > +
> >
> > +  return 1;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Completes computation of Sha3 message digest.
> >
> > +
> >
> > +  This function completes sha3 hash computation and retrieves the digest
> value
> > into
> >
> > +  the specified memory. After this function has been called, the keccak
> context
> > cannot
> >
> > +  be used again.
> >
> > +
> >
> > +  @param[in, out]  Context        Pointer to the keccak context.
> >
> > +  @param[out]      MessageDigest  Pointer to a buffer that receives the
> > message digest.
> >
> > +
> >
> > +  @retval 1   Meaasge digest computation succeeded.
> >
> > +**/
> >
> > +UINT8
> >
> > +EFIAPI
> >
> > +Sha3Final (
> >
> > +  IN OUT Keccak1600_Ctx  *Context,
> >
> > +  OUT    UINT8           *MessageDigest
> >
> > +  )
> >
> > +{
> >
> > +  UINTN  BlockSize;
> >
> > +  UINTN  Num;
> >
> > +
> >
> > +  BlockSize = Context->block_size;
> >
> > +  Num       = Context->num;
> >
> > +
> >
> > +  if (Context->md_size == 0) {
> >
> > +    return 1;
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Pad the data with 10*1. Note that |Num| can be |BlockSize - 1|
> >
> > +  // in which case both byte operations below are performed on
> >
> > +  // same byte.
> >
> > +  //
> >
> > +  memset (Context->buf + Num, 0, BlockSize - Num);
> >
> > +  Context->buf[Num]            = Context->pad;
> >
> > +  Context->buf[BlockSize - 1] |= 0x80;
> >
> > +
> >
> > +  (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
> >
> > +
> >
> > +  SHA3_squeeze (Context->A, MessageDigest, Context->md_size, BlockSize);
> >
> > +
> >
> > +  return 1;
> >
> > +}
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > new file mode 100644
> > index 000000000000..12c46cfbcd59
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > @@ -0,0 +1,107 @@
> > +/** @file
> >
> > +  Encode realted functions from Xkcp.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +Copyright 2022 The eXtended Keccak Code Package (XKCP)
> >
> > +https://github.com/XKCP/XKCP
> >
> > +Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles
> > Van Assche.
> >
> > +Implementation by the designers, hereby denoted as "the implementer".
> >
> > +For more information, feedback or questions, please refer to the Keccak
> Team
> > website:
> >
> > +https://keccak.team/
> >
> > +To the extent possible under law, the implementer has waived all copyright
> >
> > +and related or neighboring rights to the source code in this file.
> >
> > +http://creativecommons.org/publicdomain/zero/1.0/
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "CryptParallelHash.h"
> >
> > +
> >
> > +/**
> >
> > +  Encode function from XKCP.
> >
> > +
> >
> > +  Encodes the input as a byte string in a way that can be unambiguously
> parsed
> >
> > +  from the beginning of the string by inserting the length of the byte string
> >
> > +  before the byte string representation of input.
> >
> > +
> >
> > +  @param[out] EncBuf  Result of left encode.
> >
> > +  @param[in]  Value   Input of left encode.
> >
> > +
> >
> > +  @retval EncLen  Size of encode result in bytes.
> >
> > +**/
> >
> > +UINTN
> >
> > +EFIAPI
> >
> > +LeftEncode (
> >
> > +  OUT UINT8  *EncBuf,
> >
> > +  IN  UINTN  Value
> >
> > +  )
> >
> > +{
> >
> > +  UINT32  BlockNum;
> >
> > +  UINT32  EncLen;
> >
> > +  UINT32  Index;
> >
> > +  UINTN   ValueCopy;
> >
> > +
> >
> > +  for ( ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof
> > (UINTN)); ++BlockNum, ValueCopy >>= 8 ) {
> >
> > +    //
> >
> > +    // Empty
> >
> > +    //
> >
> > +  }
> >
> > +
> >
> > +  if (BlockNum == 0) {
> >
> > +    BlockNum = 1;
> >
> > +  }
> >
> > +
> >
> > +  for (Index = 1; Index <= BlockNum; ++Index) {
> >
> > +    EncBuf[Index] = (UINT8)(Value >> (8 * (BlockNum - Index)));
> >
> > +  }
> >
> > +
> >
> > +  EncBuf[0] = (UINT8)BlockNum;
> >
> > +  EncLen    = BlockNum + 1;
> >
> > +
> >
> > +  return EncLen;
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Encode function from XKCP.
> >
> > +
> >
> > +  Encodes the input as a byte string in a way that can be unambiguously
> parsed
> >
> > +  from the end of the string by inserting the length of the byte string after
> >
> > +  the byte string representation of input.
> >
> > +
> >
> > +  @param[out] EncBuf  Result of right encode.
> >
> > +  @param[in]  Value   Input of right encode.
> >
> > +
> >
> > +  @retval EncLen  Size of encode result in bytes.
> >
> > +**/
> >
> > +UINTN
> >
> > +EFIAPI
> >
> > +RightEncode (
> >
> > +  OUT UINT8  *EncBuf,
> >
> > +  IN  UINTN  Value
> >
> > +  )
> >
> > +{
> >
> > +  UINT32  BlockNum;
> >
> > +  UINT32  EncLen;
> >
> > +  UINT32  Index;
> >
> > +  UINTN   ValueCopy;
> >
> > +
> >
> > +  for (ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof
> > (UINTN)); ++BlockNum, ValueCopy >>= 8) {
> >
> > +    //
> >
> > +    // Empty
> >
> > +    //
> >
> > +  }
> >
> > +
> >
> > +  if (BlockNum == 0) {
> >
> > +    BlockNum = 1;
> >
> > +  }
> >
> > +
> >
> > +  for (Index = 1; Index <= BlockNum; ++Index) {
> >
> > +    EncBuf[Index-1] = (UINT8)(Value >> (8 * (BlockNum-Index)));
> >
> > +  }
> >
> > +
> >
> > +  EncBuf[BlockNum] = (UINT8)BlockNum;
> >
> > +  EncLen           = BlockNum + 1;
> >
> > +
> >
> > +  return EncLen;
> >
> > +}
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
> > b/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
> > new file mode 100644
> > index 000000000000..2bf89594def5
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/Hash/CryptParallelHashNull.c
> > @@ -0,0 +1,40 @@
> > +/** @file
> >
> > +  ParallelHash Implementation which does not provide real capabilities.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "InternalCryptLib.h"
> >
> > +
> >
> > +/**
> >
> > +  Parallel hash function ParallelHash256, as defined in NIST's Special
> Publication
> > 800-185,
> >
> > +  published December 2016.
> >
> > +
> >
> > +  @param[in]   Input            Pointer to the input message (X).
> >
> > +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> > input data.
> >
> > +  @param[in]   BlockSize        The size of each block (B).
> >
> > +  @param[out]  Output           Pointer to the output buffer.
> >
> > +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> >
> > +  @param[in]   Customization    Pointer to the customization string (S).
> >
> > +  @param[in]   CustomByteLen    The length of the customization string in
> bytes.
> >
> > +
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +ParallelHash256HashAll (
> >
> > +  IN CONST VOID   *Input,
> >
> > +  IN       UINTN  InputByteLen,
> >
> > +  IN       UINTN  BlockSize,
> >
> > +  OUT      VOID   *Output,
> >
> > +  IN       UINTN  OutputByteLen,
> >
> > +  IN CONST VOID   *Customization,
> >
> > +  IN       UINTN  CustomByteLen
> >
> > +  )
> >
> > +{
> >
> > +  ASSERT (FALSE);
> >
> > +  return FALSE;
> >
> > +}
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> > b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> > index c8df259ea963..8ee1b53cf957 100644
> > --- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> > +++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c
> > @@ -3,7 +3,7 @@
> >    Protocol/PPI.
> >
> >
> >
> >    Copyright (C) Microsoft Corporation. All rights reserved.
> >
> > -  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> >
> > +  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >    SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> >
> >  **/
> >
> > @@ -870,6 +870,38 @@ Sha512HashAll (
> >    CALL_CRYPTO_SERVICE (Sha512HashAll, (Data, DataSize, HashValue), FALSE);
> >
> >  }
> >
> >
> >
> > +/**
> >
> > +  Parallel hash function ParallelHash256, as defined in NIST's Special
> Publication
> > 800-185,
> >
> > +  published December 2016.
> >
> > +
> >
> > +  @param[in]   Input            Pointer to the input message (X).
> >
> > +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> > input data.
> >
> > +  @param[in]   BlockSize        The size of each block (B).
> >
> > +  @param[out]  Output           Pointer to the output buffer.
> >
> > +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> >
> > +  @param[in]   Customization    Pointer to the customization string (S).
> >
> > +  @param[in]   CustomByteLen    The length of the customization string in
> bytes.
> >
> > +
> >
> > +  @retval TRUE   ParallelHash256 digest computation succeeded.
> >
> > +  @retval FALSE  ParallelHash256 digest computation failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +ParallelHash256HashAll (
> >
> > +  IN CONST VOID   *Input,
> >
> > +  IN       UINTN  InputByteLen,
> >
> > +  IN       UINTN  BlockSize,
> >
> > +  OUT      VOID   *Output,
> >
> > +  IN       UINTN  OutputByteLen,
> >
> > +  IN CONST VOID   *Customization,
> >
> > +  IN       UINTN  CustomByteLen
> >
> > +  )
> >
> > +{
> >
> > +  CALL_CRYPTO_SERVICE (ParallelHash256HashAll, (Input, InputByteLen,
> > BlockSize, Output, OutputByteLen, Customization, CustomByteLen), FALSE);
> >
> > +}
> >
> > +
> >
> >  /**
> >
> >    Retrieves the size, in bytes, of the context buffer required for SM3 hash
> > operations.
> >
> >
> >
> > diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > new file mode 100644
> > index 000000000000..fb57e91a9f16
> > --- /dev/null
> > +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > @@ -0,0 +1,145 @@
> > +/** @file
> >
> > +  Application for Parallelhash Function Validation.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "TestBaseCryptLib.h"
> >
> > +
> >
> > +//
> >
> > +// Parallelhash Test Sample common parameters.
> >
> > +//
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINTN  OutputByteLen = 64;
> >
> > +
> >
> > +//
> >
> > +// Parallelhash Test Sample #1 from NIST Special Publication 800-185.
> >
> > +//
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  InputSample1[] = {
> >
> > +  // input data of sample1.
> >
> > +  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13,
> 0x14,
> > 0x15, 0x16, 0x17,
> >
> > +  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27
> >
> > +};
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample1ByteLen   =
> 24;
> > // Length of sample1 input data in bytes.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID
> *CustomizationSample1
> > = "";        // Customization string (S) of sample1.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample1ByteLen  =
> 0;
> > // Customization string length of sample1 in bytes.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample1      = 8;
> > // Block size of sample1.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8
> ExpectOutputSample1[]
> > = {
> >
> > +  // Expected output data of sample1.
> >
> > +  0xbc, 0x1e, 0xf1, 0x24, 0xda, 0x34, 0x49, 0x5e, 0x94, 0x8e, 0xad, 0x20,
> 0x7d,
> > 0xd9, 0x84, 0x22,
> >
> > +  0x35, 0xda, 0x43, 0x2d, 0x2b, 0xbc, 0x54, 0xb4, 0xc1, 0x10, 0xe6, 0x4c,
> 0x45,
> > 0x11, 0x05, 0x53,
> >
> > +  0x1b, 0x7f, 0x2a, 0x3e, 0x0c, 0xe0, 0x55, 0xc0, 0x28, 0x05, 0xe7, 0xc2, 0xde,
> > 0x1f, 0xb7, 0x46,
> >
> > +  0xaf, 0x97, 0xa1, 0xd0, 0x01, 0xf4, 0x3b, 0x82, 0x4e, 0x31, 0xb8, 0x76, 0x12,
> > 0x41, 0x04, 0x29
> >
> > +};
> >
> > +
> >
> > +//
> >
> > +// Parallelhash Test Sample #2 from NIST Special Publication 800-185.
> >
> > +//
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  *InputSample2         =
> > InputSample1;               // Input of sample2 is same as sample1.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample2ByteLen   =
> 24;
> > // Length of sample2 input data in bytes.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID
> *CustomizationSample2
> > = "Parallel Data";            // Customization string (S) of sample2.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample2ByteLen  =
> > 13;                         // Customization string length of sample2 in bytes.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample2      = 8;
> > // Block size of sample2.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8
> ExpectOutputSample2[]
> > = {
> >
> > +  // Expected output data of sample2.
> >
> > +  0xcd, 0xf1, 0x52, 0x89, 0xb5, 0x4f, 0x62, 0x12, 0xb4, 0xbc, 0x27, 0x05, 0x28,
> > 0xb4, 0x95, 0x26,
> >
> > +  0x00, 0x6d, 0xd9, 0xb5, 0x4e, 0x2b, 0x6a, 0xdd, 0x1e, 0xf6, 0x90, 0x0d,
> 0xda,
> > 0x39, 0x63, 0xbb,
> >
> > +  0x33, 0xa7, 0x24, 0x91, 0xf2, 0x36, 0x96, 0x9c, 0xa8, 0xaf, 0xae, 0xa2, 0x9c,
> > 0x68, 0x2d, 0x47,
> >
> > +  0xa3, 0x93, 0xc0, 0x65, 0xb3, 0x8e, 0x29, 0xfa, 0xe6, 0x51, 0xa2, 0x09, 0x1c,
> > 0x83, 0x31, 0x10
> >
> > +};
> >
> > +
> >
> > +//
> >
> > +// Parallelhash Test Sample #3 from NIST Special Publication 800-185.
> >
> > +//
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8  InputSample3[] = {
> >
> > +  // input data of sample3.
> >
> > +  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
> 0x10,
> > 0x11, 0x12, 0x13,
> >
> > +  0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x20, 0x21, 0x22, 0x23,
> 0x24,
> > 0x25, 0x26, 0x27,
> >
> > +  0x28, 0x29, 0x2a, 0x2b, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
> 0x38,
> > 0x39, 0x3a, 0x3b,
> >
> > +  0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b,
> 0x50,
> > 0x51, 0x52, 0x53,
> >
> > +  0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x5b
> >
> > +};
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        InputSample3ByteLen   =
> 72;
> > // Length of sample3 input data in bytes.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST VOID
> *CustomizationSample3
> > = "Parallel Data";            // Customization string (S) of sample3.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        CustomSample3ByteLen  =
> > 13;                         // Customization string length of sample3 in bytes.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED UINTN        BlockSizeSample3      = 12;
> > // Block size of sample3.
> >
> > +GLOBAL_REMOVE_IF_UNREFERENCED CONST UINT8
> ExpectOutputSample3[]
> > = {
> >
> > +  // Expected output data of sample3.
> >
> > +  0x69, 0xd0, 0xfc, 0xb7, 0x64, 0xea, 0x05, 0x5d, 0xd0, 0x93, 0x34, 0xbc, 0x60,
> > 0x21, 0xcb, 0x7e,
> >
> > +  0x4b, 0x61, 0x34, 0x8d, 0xff, 0x37, 0x5d, 0xa2, 0x62, 0x67, 0x1c, 0xde, 0xc3,
> > 0xef, 0xfa, 0x8d,
> >
> > +  0x1b, 0x45, 0x68, 0xa6, 0xcc, 0xe1, 0x6b, 0x1c, 0xad, 0x94, 0x6d, 0xdd,
> 0xe2,
> > 0x7f, 0x6c, 0xe2,
> >
> > +  0xb8, 0xde, 0xe4, 0xcd, 0x1b, 0x24, 0x85, 0x1e, 0xbf, 0x00, 0xeb, 0x90,
> 0xd4,
> > 0x38, 0x13, 0xe9
> >
> > +};
> >
> > +
> >
> > +UNIT_TEST_STATUS
> >
> > +EFIAPI
> >
> > +TestVerifyParallelHash256HashAll (
> >
> > +  IN UNIT_TEST_CONTEXT  Context
> >
> > +  )
> >
> > +{
> >
> > +  BOOLEAN  Status;
> >
> > +  UINT8    Output[64];
> >
> > +
> >
> > +  //
> >
> > +  // Test #1 using sample1.
> >
> > +  //
> >
> > +  Status = ParallelHash256HashAll (
> >
> > +             InputSample1,
> >
> > +             InputSample1ByteLen,
> >
> > +             BlockSizeSample1,
> >
> > +             Output,
> >
> > +             OutputByteLen,
> >
> > +             CustomizationSample1,
> >
> > +             CustomSample1ByteLen
> >
> > +             );
> >
> > +  UT_ASSERT_TRUE (Status);
> >
> > +
> >
> > +  // Check the output with the expected output.
> >
> > +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample1, OutputByteLen);
> >
> > +
> >
> > +  //
> >
> > +  // Test #2 using sample2.
> >
> > +  //
> >
> > +  Status = ParallelHash256HashAll (
> >
> > +             InputSample2,
> >
> > +             InputSample2ByteLen,
> >
> > +             BlockSizeSample2,
> >
> > +             Output,
> >
> > +             OutputByteLen,
> >
> > +             CustomizationSample2,
> >
> > +             CustomSample2ByteLen
> >
> > +             );
> >
> > +  UT_ASSERT_TRUE (Status);
> >
> > +
> >
> > +  // Check the output with the expected output.
> >
> > +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample2, OutputByteLen);
> >
> > +
> >
> > +  //
> >
> > +  // Test #3 using sample3.
> >
> > +  //
> >
> > +  Status = ParallelHash256HashAll (
> >
> > +             InputSample3,
> >
> > +             InputSample3ByteLen,
> >
> > +             BlockSizeSample3,
> >
> > +             Output,
> >
> > +             OutputByteLen,
> >
> > +             CustomizationSample3,
> >
> > +             CustomSample3ByteLen
> >
> > +             );
> >
> > +  UT_ASSERT_TRUE (Status);
> >
> > +
> >
> > +  // Check the output with the expected output.
> >
> > +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3, OutputByteLen);
> >
> > +
> >
> > +  return EFI_SUCCESS;
> >
> > +}
> >
> > +
> >
> > +TEST_DESC  mParallelhashTest[] = {
> >
> > +  //
> >
> > +  // -----Description------------------------------Class----------------------Function--
> --
> > -------------Pre---Post--Context
> >
> > +  //
> >
> > +  { "TestVerifyParallelHash256HashAll()",
> > "CryptoPkg.BaseCryptLib.ParallelHash256HashAll",
> > TestVerifyParallelHash256HashAll, NULL, NULL, NULL },
> >
> > +};
> >
> > +
> >
> > +UINTN  mParallelhashTestNum = ARRAY_SIZE (mParallelhashTest);
> >
> > diff --git a/CryptoPkg/CryptoPkg.ci.yaml b/CryptoPkg/CryptoPkg.ci.yaml
> > index eeb388ae71c5..e21fafac1efe 100644
> > --- a/CryptoPkg/CryptoPkg.ci.yaml
> > +++ b/CryptoPkg/CryptoPkg.ci.yaml
> > @@ -2,7 +2,7 @@
> >  # CI configuration for CryptoPkg
> >
> >  #
> >
> >  # Copyright (c) Microsoft Corporation
> >
> > -# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> >
> > +# Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  # SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  ##
> >
> >  {
> >
> > @@ -34,6 +34,8 @@
> >              "Library/OpensslLib/rand_pool.c",
> >
> >              # This has OpenSSL interfaces that aren't UEFI spec compliant
> >
> >              "Library/Include/CrtLibSupport.h",
> >
> > +            # This has OpenSSL interfaces that aren't UEFI spec compliant
> >
> > +            "Library/BaseCryptLib/Hash/CryptParallelHash.h",
> >
> >              # These directories contain auto-generated OpenSSL content
> >
> >              "Library/OpensslLib",
> >
> >              "Library/IntrinsicLib",
> >
> > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > index f4bc7c0d73d9..7d1499350a49 100644
> > --- a/CryptoPkg/Include/Library/BaseCryptLib.h
> > +++ b/CryptoPkg/Include/Library/BaseCryptLib.h
> > @@ -4,7 +4,7 @@
> >    primitives (Hash Serials, HMAC, RSA, Diffie-Hellman, etc) for UEFI security
> >
> >    functionality enabling.
> >
> >
> >
> > -Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
> >
> > +Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> >
> >  **/
> >
> > @@ -753,6 +753,35 @@ Sha512HashAll (
> >    OUT  UINT8       *HashValue
> >
> >    );
> >
> >
> >
> > +/**
> >
> > +  Parallel hash function ParallelHash256, as defined in NIST's Special
> Publication
> > 800-185,
> >
> > +  published December 2016.
> >
> > +
> >
> > +  @param[in]   Input            Pointer to the input message (X).
> >
> > +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> > input data.
> >
> > +  @param[in]   BlockSize        The size of each block (B).
> >
> > +  @param[out]  Output           Pointer to the output buffer.
> >
> > +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> >
> > +  @param[in]   Customization    Pointer to the customization string (S).
> >
> > +  @param[in]   CustomByteLen    The length of the customization string in
> bytes.
> >
> > +
> >
> > +  @retval TRUE   ParallelHash256 digest computation succeeded.
> >
> > +  @retval FALSE  ParallelHash256 digest computation failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +ParallelHash256HashAll (
> >
> > +  IN CONST VOID   *Input,
> >
> > +  IN       UINTN  InputByteLen,
> >
> > +  IN       UINTN  BlockSize,
> >
> > +  OUT      VOID   *Output,
> >
> > +  IN       UINTN  OutputByteLen,
> >
> > +  IN CONST VOID   *Customization,
> >
> > +  IN       UINTN  CustomByteLen
> >
> > +  );
> >
> > +
> >
> >  /**
> >
> >    Retrieves the size, in bytes, of the context buffer required for SM3 hash
> > operations.
> >
> >
> >
> > diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> > b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> > index 5186a54759ae..0b30a821bc16 100644
> > --- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> > +++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h
> > @@ -2,7 +2,7 @@
> >    Defines the PCD_CRYPTO_SERVICE_FAMILY_ENABLE structure associated
> with
> >
> >    gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.
> >
> >
> >
> > -  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> >
> > +  Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >    SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> >
> >  **/
> >
> > @@ -172,6 +172,12 @@ typedef struct {
> >      } Services;
> >
> >      UINT32    Family;
> >
> >    } Sha512;
> >
> > +  union {
> >
> > +    struct {
> >
> > +      UINT8    HashAll : 1;
> >
> > +    } Services;
> >
> > +    UINT32    Family;
> >
> > +  } ParallelHash;
> >
> >    union {
> >
> >      struct {
> >
> >        UINT8    GetSubjectName             : 1;
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > index 49703fa4c963..15cf3dab105c 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
> > @@ -6,7 +6,7 @@
> >  #  This external input must be validated carefully to avoid security issues such
> as
> >
> >  #  buffer overflow or integer overflow.
> >
> >  #
> >
> > -#  Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
> >
> > +#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  #  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> > reserved.<BR>
> >
> >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  #
> >
> > @@ -34,6 +34,7 @@
> >    Hash/CryptSha256.c
> >
> >    Hash/CryptSha512.c
> >
> >    Hash/CryptSm3.c
> >
> > +  Hash/CryptParallelHashNull.c
> >
> >    Hmac/CryptHmacSha256.c
> >
> >    Kdf/CryptHkdf.c
> >
> >    Cipher/CryptAes.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
> > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
> > new file mode 100644
> > index 000000000000..fe08d4928e8d
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
> > @@ -0,0 +1,201 @@
> > +/** @file
> >
> > +  ParallelHash related function and type declaration.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
> >
> > +Licensed under the OpenSSL license (the "License").  You may not use
> >
> > +this file except in compliance with the License.  You can obtain a copy
> >
> > +in the file LICENSE in the source distribution or at
> >
> > +https://www.openssl.org/source/license.html
> >
> > +
> >
> > +Copyright 2022 The eXtended Keccak Code Package (XKCP)
> >
> > +https://github.com/XKCP/XKCP
> >
> > +Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles
> > Van Assche.
> >
> > +Implementation by the designers, hereby denoted as "the implementer".
> >
> > +For more information, feedback or questions, please refer to the Keccak
> Team
> > website:
> >
> > +https://keccak.team/
> >
> > +To the extent possible under law, the implementer has waived all copyright
> >
> > +and related or neighboring rights to the source code in this file.
> >
> > +http://creativecommons.org/publicdomain/zero/1.0/
> >
> > +**/
> >
> > +
> >
> > +#include "InternalCryptLib.h"
> >
> > +
> >
> > +#define KECCAK1600_WIDTH  1600
> >
> > +
> >
> > +//
> >
> > +// This struct referring to m_sha3.c from opessl and modified its type name.
> >
> > +//
> >
> > +typedef struct {
> >
> > +  uint64_t         A[5][5];
> >
> > +  size_t           block_size;  /* cached ctx->digest->block_size */
> >
> > +  size_t           md_size;     /* output length, variable in XOF */
> >
> > +  size_t           num;         /* used bytes in below buffer */
> >
> > +  unsigned char    buf[KECCAK1600_WIDTH / 8 - 32];
> >
> > +  unsigned char    pad;
> >
> > +} Keccak1600_Ctx;
> >
> > +
> >
> > +/**
> >
> > +  SHA3_absorb can be called multiple times, but at each invocation
> >
> > +  largest multiple of |r| out of |len| bytes are processed. Then
> >
> > +  remaining amount of bytes is returned. This is done to spare caller
> >
> > +  trouble of calculating the largest multiple of |r|. |r| can be viewed
> >
> > +  as blocksize. It is commonly (1600 - 256*n)/8, e.g. 168, 136, 104,
> >
> > +  72, but can also be (1600 - 448)/8 = 144. All this means that message
> >
> > +  padding and intermediate sub-block buffering, byte- or bitwise, is
> >
> > +  caller's responsibility.
> >
> > +**/
> >
> > +size_t
> >
> > +SHA3_absorb (
> >
> > +  uint64_t             A[5][5],
> >
> > +  const unsigned char  *inp,
> >
> > +  size_t               len,
> >
> > +  size_t               r
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  SHA3_squeeze is called once at the end to generate |out| hash value
> >
> > +  of |len| bytes.
> >
> > +**/
> >
> > +void
> >
> > +SHA3_squeeze (
> >
> > +  uint64_t       A[5][5],
> >
> > +  unsigned char  *out,
> >
> > +  size_t         len,
> >
> > +  size_t         r
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  Encode function from XKCP.
> >
> > +
> >
> > +  Encodes the input as a byte string in a way that can be unambiguously
> parsed
> >
> > +  from the beginning of the string by inserting the length of the byte string
> >
> > +  before the byte string representation of input.
> >
> > +
> >
> > +  @param[out] EncBuf  Result of left encode.
> >
> > +  @param[in]  Value   Input of left encode.
> >
> > +
> >
> > +  @retval EncLen  Size of encode result in bytes.
> >
> > +**/
> >
> > +UINTN
> >
> > +EFIAPI
> >
> > +LeftEncode (
> >
> > +  OUT UINT8  *EncBuf,
> >
> > +  IN  UINTN  Value
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  Encode function from XKCP.
> >
> > +
> >
> > +  Encodes the input as a byte string in a way that can be unambiguously
> parsed
> >
> > +  from the end of the string by inserting the length of the byte string after
> >
> > +  the byte string representation of input.
> >
> > +
> >
> > +  @param[out] EncBuf  Result of right encode.
> >
> > +  @param[in]  Value   Input of right encode.
> >
> > +
> >
> > +  @retval EncLen  Size of encode result in bytes.
> >
> > +**/
> >
> > +UINTN
> >
> > +EFIAPI
> >
> > +RightEncode (
> >
> > +  OUT UINT8  *EncBuf,
> >
> > +  IN  UINTN  Value
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  Keccak initial fuction.
> >
> > +
> >
> > +  Set up state with specified capacity.
> >
> > +
> >
> > +  @param[out] Context           Pointer to the context being initialized.
> >
> > +  @param[in]  Pad               Delimited Suffix.
> >
> > +  @param[in]  BlockSize         Size of context block.
> >
> > +  @param[in]  MessageDigestLen  Size of message digest in bytes.
> >
> > +
> >
> > +  @retval 1  Initialize successfully.
> >
> > +  @retval 0  Fail to initialize.
> >
> > +**/
> >
> > +UINT8
> >
> > +EFIAPI
> >
> > +KeccakInit (
> >
> > +  OUT Keccak1600_Ctx  *Context,
> >
> > +  IN  UINT8           Pad,
> >
> > +  IN  UINTN           BlockSize,
> >
> > +  IN  UINTN           MessageDigstLen
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  Sha3 update fuction.
> >
> > +
> >
> > +  This function performs Sha3 digest on a data buffer of the specified size.
> >
> > +  It can be called multiple times to compute the digest of long or
> discontinuous
> > data streams.
> >
> > +
> >
> > +  @param[in,out] Context   Pointer to the Keccak context.
> >
> > +  @param[in]     Data      Pointer to the buffer containing the data to be
> hashed.
> >
> > +  @param[in]     DataSize  Size of Data buffer in bytes.
> >
> > +
> >
> > +  @retval 1  Update successfully.
> >
> > +**/
> >
> > +UINT8
> >
> > +EFIAPI
> >
> > +Sha3Update (
> >
> > +  IN OUT Keccak1600_Ctx  *Context,
> >
> > +  IN const VOID          *Data,
> >
> > +  IN UINTN               DataSize
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  Completes computation of Sha3 message digest.
> >
> > +
> >
> > +  This function completes sha3 hash computation and retrieves the digest
> value
> > into
> >
> > +  the specified memory. After this function has been called, the keccak
> context
> > cannot
> >
> > +  be used again.
> >
> > +
> >
> > +  @param[in, out]  Context        Pointer to the keccak context.
> >
> > +  @param[out]      MessageDigest  Pointer to a buffer that receives the
> > message digest.
> >
> > +
> >
> > +  @retval 1   Meaasge digest computation succeeded.
> >
> > +**/
> >
> > +UINT8
> >
> > +EFIAPI
> >
> > +Sha3Final (
> >
> > +  IN OUT Keccak1600_Ctx  *Context,
> >
> > +  OUT    UINT8           *MessageDigest
> >
> > +  );
> >
> > +
> >
> > +/**
> >
> > +  Computes the CSHAKE-256 message digest of a input data buffer.
> >
> > +
> >
> > +  This function performs the CSHAKE-256 message digest of a given data
> buffer,
> > and places
> >
> > +  the digest value into the specified memory.
> >
> > +
> >
> > +  @param[in]   Data               Pointer to the buffer containing the data to be
> > hashed.
> >
> > +  @param[in]   DataSize           Size of Data buffer in bytes.
> >
> > +  @param[in]   OutputLen          Size of output in bytes.
> >
> > +  @param[in]   Name               Pointer to the function name string.
> >
> > +  @param[in]   NameLen            Size of the function name in bytes.
> >
> > +  @param[in]   Customization      Pointer to the customization string.
> >
> > +  @param[in]   CustomizationLen   Size of the customization string in bytes.
> >
> > +  @param[out]  HashValue          Pointer to a buffer that receives the CSHAKE-
> > 256 digest
> >
> > +                                  value.
> >
> > +
> >
> > +  @retval TRUE   CSHAKE-256 digest computation succeeded.
> >
> > +  @retval FALSE  CSHAKE-256 digest computation failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +BOOLEAN
> >
> > +EFIAPI
> >
> > +CShake256HashAll (
> >
> > +  IN   CONST VOID  *Data,
> >
> > +  IN   UINTN       DataSize,
> >
> > +  IN   UINTN       OutputLen,
> >
> > +  IN   CONST VOID  *Name,
> >
> > +  IN   UINTN       NameLen,
> >
> > +  IN   CONST VOID  *Customization,
> >
> > +  IN   UINTN       CustomizationLen,
> >
> > +  OUT  UINT8       *HashValue
> >
> > +  );
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > index 0cab5f3ce36c..bf1563b06407 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
> > @@ -13,7 +13,7 @@
> >  #  PEM handler functions, and pseudorandom number generator functions are
> > not
> >
> >  #  supported in this instance.
> >
> >  #
> >
> > -#  Copyright (c) 2010 - 2020, Intel Corporation. All rights reserved.<BR>
> >
> > +#  Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  #
> >
> >  ##
> >
> > @@ -40,6 +40,7 @@
> >    Hash/CryptSha256.c
> >
> >    Hash/CryptSm3.c
> >
> >    Hash/CryptSha512.c
> >
> > +  Hash/CryptParallelHashNull.c
> >
> >    Hmac/CryptHmacSha256.c
> >
> >    Kdf/CryptHkdf.c
> >
> >    Cipher/CryptAesNull.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> > index fdbb6edfd23e..6742da0be4fe 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
> > @@ -11,7 +11,7 @@
> >  #  functions, PKCS#7 SignedData sign functions, Diffie-Hellman functions, and
> >
> >  #  authenticode signature verification functions are not supported in this
> > instance.
> >
> >  #
> >
> > -#  Copyright (c) 2009 - 2021, Intel Corporation. All rights reserved.<BR>
> >
> > +#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  #  Copyright (c) 2021, Hewlett Packard Enterprise Development LP. All rights
> > reserved.<BR>
> >
> >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  #
> >
> > @@ -40,6 +40,7 @@
> >    Hash/CryptSha256.c
> >
> >    Hash/CryptSm3.c
> >
> >    Hash/CryptSha512.c
> >
> > +  Hash/CryptParallelHashNull.c
> >
> >    Hmac/CryptHmacSha256.c
> >
> >    Kdf/CryptHkdf.c
> >
> >    Cipher/CryptAes.c
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > index e6470d7a2127..8f39517f78b7 100644
> > --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > @@ -10,7 +10,7 @@
> >  #  RSA external functions, PKCS#7 SignedData sign functions, Diffie-Hellman
> > functions, and
> >
> >  #  authenticode signature verification functions are not supported in this
> > instance.
> >
> >  #
> >
> > -#  Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
> >
> > +#  Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  #
> >
> >  ##
> >
> > @@ -38,6 +38,10 @@
> >    Hash/CryptSha256.c
> >
> >    Hash/CryptSm3.c
> >
> >    Hash/CryptSha512.c
> >
> > +  Hash/CryptSha3.c
> >
> > +  Hash/CryptXkcp.c
> >
> > +  Hash/CryptCShake256.c
> >
> > +  Hash/CryptParallelHash.c
> >
> >    Hmac/CryptHmacSha256.c
> >
> >    Kdf/CryptHkdfNull.c
> >
> >    Cipher/CryptAes.c
> >
> > @@ -85,6 +89,8 @@
> >    OpensslLib
> >
> >    IntrinsicLib
> >
> >    PrintLib
> >
> > +  MmServicesTableLib
> >
> > +  SynchronizationLib
> >
> >
> >
> >  #
> >
> >  # Remove these [BuildOptions] after this library is cleaned up
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > index faf959827b90..63d1d82d1914 100644
> > --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf
> > @@ -6,7 +6,7 @@
> >  #  This external input must be validated carefully to avoid security issues such
> as
> >
> >  #  buffer overflow or integer overflow.
> >
> >  #
> >
> > -#  Copyright (c) 2009 - 2020, Intel Corporation. All rights reserved.<BR>
> >
> > +#  Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  #  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> > reserved.<BR>
> >
> >  #  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  #
> >
> > @@ -34,6 +34,7 @@
> >    Hash/CryptSha256Null.c
> >
> >    Hash/CryptSha512Null.c
> >
> >    Hash/CryptSm3Null.c
> >
> > +  Hash/CryptParallelHashNull.c
> >
> >    Hmac/CryptHmacSha256Null.c
> >
> >    Kdf/CryptHkdfNull.c
> >
> >    Cipher/CryptAesNull.c
> >
> > diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h
> > b/CryptoPkg/Library/Include/CrtLibSupport.h
> > index d257dca8fa9b..b76b140a7acf 100644
> > --- a/CryptoPkg/Library/Include/CrtLibSupport.h
> > +++ b/CryptoPkg/Library/Include/CrtLibSupport.h
> > @@ -2,7 +2,7 @@
> >    Root include file of C runtime library to support building the third-party
> >
> >    cryptographic library.
> >
> >
> >
> > -Copyright (c) 2010 - 2021, Intel Corporation. All rights reserved.<BR>
> >
> > +Copyright (c) 2010 - 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  Copyright (c) 2020, Hewlett Packard Enterprise Development LP. All rights
> > reserved.<BR>
> >
> >  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> >
> > @@ -111,6 +111,7 @@ typedef UINT8   u_char;
> >  typedef UINT32  uid_t;
> >
> >  typedef UINT32  gid_t;
> >
> >  typedef CHAR16  wchar_t;
> >
> > +typedef UINT64  uint64_t;
> >
> >
> >
> >  //
> >
> >  // File operations are not required for EFI building,
> >
> > diff --git a/CryptoPkg/Private/Protocol/Crypto.h
> > b/CryptoPkg/Private/Protocol/Crypto.h
> > index e378a8a8c60e..d51fc4a0e2cc 100644
> > --- a/CryptoPkg/Private/Protocol/Crypto.h
> > +++ b/CryptoPkg/Private/Protocol/Crypto.h
> > @@ -1905,6 +1905,35 @@ BOOLEAN
> >    OUT  UINT8       *HashValue
> >
> >    );
> >
> >
> >
> > +/**
> >
> > +  Parallel hash function ParallelHash256, as defined in NIST's Special
> Publication
> > 800-185,
> >
> > +  published December 2016.
> >
> > +
> >
> > +  @param[in]   Input            Pointer to the input message (X).
> >
> > +  @param[in]   InputByteLen     The number(>0) of input bytes provided for the
> > input data.
> >
> > +  @param[in]   BlockSize        The size of each block (B).
> >
> > +  @param[out]  Output           Pointer to the output buffer.
> >
> > +  @param[in]   OutputByteLen    The desired number of output bytes (L).
> >
> > +  @param[in]   Customization    Pointer to the customization string (S).
> >
> > +  @param[in]   CustomByteLen    The length of the customization string in
> bytes.
> >
> > +
> >
> > +  @retval TRUE   ParallelHash256 digest computation succeeded.
> >
> > +  @retval FALSE  ParallelHash256 digest computation failed.
> >
> > +  @retval FALSE  This interface is not supported.
> >
> > +
> >
> > +**/
> >
> > +typedef
> >
> > +BOOLEAN
> >
> > +(EFIAPI *EDKII_CRYPTO_PARALLEL_HASH_ALL)(
> >
> > +  IN CONST VOID   *Input,
> >
> > +  IN       UINTN  InputByteLen,
> >
> > +  IN       UINTN  BlockSize,
> >
> > +  OUT      VOID   *Output,
> >
> > +  IN       UINTN  OutputByteLen,
> >
> > +  IN CONST VOID   *Customization,
> >
> > +  IN       UINTN  CustomByteLen
> >
> > +  );
> >
> > +
> >
> >  // ----------------------------------------------------------------------------
> >
> >  // X509
> >
> >  // ----------------------------------------------------------------------------
> >
> > @@ -3560,6 +3589,8 @@ struct _EDKII_CRYPTO_PROTOCOL {
> >    EDKII_CRYPTO_SHA512_UPDATE                         Sha512Update;
> >
> >    EDKII_CRYPTO_SHA512_FINAL                          Sha512Final;
> >
> >    EDKII_CRYPTO_SHA512_HASH_ALL                       Sha512HashAll;
> >
> > +  /// Parallel hash
> >
> > +  EDKII_CRYPTO_PARALLEL_HASH_ALL                     ParallelHash256HashAll;
> >
> >    /// X509
> >
> >    EDKII_CRYPTO_X509_GET_SUBJECT_NAME                 X509GetSubjectName;
> >
> >    EDKII_CRYPTO_X509_GET_COMMON_NAME
> X509GetCommonName;
> >
> > diff --git a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> > b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> > index ff0af36bcc80..ba6e1edb6015 100644
> > --- a/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> > +++ b/CryptoPkg/Test/CryptoPkgHostUnitTest.dsc
> > @@ -21,6 +21,9 @@
> >  [LibraryClasses]
> >
> >    OpensslLib|CryptoPkg/Library/OpensslLib/OpensslLib.inf
> >
> >    BaseCryptLib|CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf
> >
> > +
> >
> MmServicesTableLib|MdePkg/Library/MmServicesTableLib/MmServicesTableLib
> > .inf
> >
> > +
> >
> SynchronizationLib|MdePkg/Library/BaseSynchronizationLib/BaseSynchronizati
> > onLib.inf
> >
> > +
> >
> TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplat
> > e.inf
> >
> >
> >
> >  [LibraryClasses.AARCH64, LibraryClasses.ARM]
> >
> >    RngLib|MdePkg/Library/BaseRngLibNull/BaseRngLibNull.inf
> >
> > diff --git
> > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> > index 00c869265080..399db596c2d1 100644
> > --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> > +++
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> > @@ -2,6 +2,7 @@
> >  # Host-based UnitTest for BaseCryptLib
> >
> >  #
> >
> >  # Copyright (c) Microsoft Corporation.<BR>
> >
> > +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  # SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  ##
> >
> >
> >
> > @@ -35,6 +36,7 @@
> >    Pkcs7EkuTests.c
> >
> >    OaepEncryptTests.c
> >
> >    RsaPssTests.c
> >
> > +  ParallelhashTests.c
> >
> >
> >
> >  [Packages]
> >
> >    MdePkg/MdePkg.dec
> >
> > @@ -45,3 +47,5 @@
> >    DebugLib
> >
> >    BaseCryptLib
> >
> >    UnitTestLib
> >
> > +  MmServicesTableLib
> >
> > +  SynchronizationLib
> >
> > --
> > 2.26.2.windows.1
> >
> >
> >
> > -=-=-=-=-=-=
> > Groups.io Links: You receive all messages sent to this group.
> > View/Reply Online (#87382): https://edk2.groups.io/g/devel/message/87382
> > Mute This Topic: https://groups.io/mt/89658124/1772286
> > Group Owner: devel+owner@edk2.groups.io
> > Unsubscribe: https://edk2.groups.io/g/devel/unsub [jiewen.yao@intel.com]
> > -=-=-=-=-=-=
> >


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-03-17  3:24 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-03-09  8:44 [PATCH v5 1/1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib Li, Zhihao
2022-03-14  5:50 ` [edk2-devel] " Yao, Jiewen
2022-03-17  2:43   ` Li, Zhihao
2022-03-17  3:24     ` Yao, Jiewen

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox