public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
@ 2022-02-11  9:05 Li, Zhihao
  2022-02-15  6:08 ` Yao, Jiewen
  0 siblings, 1 reply; 6+ messages in thread
From: Li, Zhihao @ 2022-02-11  9:05 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.

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>

Signed-off-by: Zhihao Li <zhihao.li@intel.com>
---
 CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                   | 313 ++++++++++++++++++++
 CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c                | 275 +++++++++++++++++
 CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                        | 102 +++++++
 CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                        |  53 ++++
 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c       | 152 ++++++++++
 CryptoPkg/CryptoPkg.dec                                                |   9 +-
 CryptoPkg/Include/Library/BaseCryptLib.h                               |  29 +-
 CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                         |  12 +-
 CryptoPkg/Library/Include/CrtLibSupport.h                              |   5 +-
 CryptoPkg/Library/Include/sha3.h                                       |  32 ++
 CryptoPkg/Library/Include/xkcp.h                                       |  23 ++
 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h        |   3 +-
 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf  |   7 +
 CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf |   6 +
 14 files changed, 1016 insertions(+), 5 deletions(-)

diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
new file mode 100644
index 0000000000..5efced3f46
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
@@ -0,0 +1,313 @@
+/** @file
+  cSHAKE-256 Digest Wrapper Implementations.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include "sha3.h"
+#include "xkcp.h"
+
+#define  CSHAKE256_SECURITY_STRENGTH    256
+#define  CSHAKE256_RATE_IN_BYTES        136
+
+const CHAR8 mZeroPadding[CSHAKE256_RATE_IN_BYTES] = {0};
+
+UINTN
+EFIAPI
+LeftEncode (
+  OUT UINT8     *Encbuf,
+  IN  UINTN     Value
+  )
+{
+  return left_encode (Encbuf, Value);
+}
+
+UINTN
+EFIAPI
+RightEncode (
+  OUT UINT8     *Encbuf,
+  IN  UINTN     Value
+  )
+{
+  return right_encode (Encbuf, Value);
+}
+
+/**
+  Retrieves the size, in bytes, of the context buffer required for cSHAKE-256 hash operations.
+
+  @return  The size, in bytes, of the context buffer required for cSHAKE-256 hash operations.
+
+**/
+UINTN
+EFIAPI
+CShake256GetContextSize (
+  VOID
+  )
+{
+  return (UINTN) (sizeof (KECCAK1600_CTX));
+}
+
+/**
+  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;
+  unsigned char EncBuf[sizeof(size_t)+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.
+    //
+    return (BOOLEAN) init (
+                      (KECCAK1600_CTX *) CShake256Context,
+                      '\x1f',
+                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
+                      OutputLen
+                      );
+  }
+
+  Status = (BOOLEAN) init (
+                      (KECCAK1600_CTX *) CShake256Context,
+                      '\x04',
+                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
+                      OutputLen
+                      );
+  if (!Status) {
+    return FALSE;
+  }
+
+  AbsorbLen = 0;
+  //
+  // Absorb Absorb bytepad(.., rate).
+  //
+  EncLen = left_encode (EncBuf, CSHAKE256_RATE_IN_BYTES);
+  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *) CShake256Context, EncBuf, EncLen);
+  if (!Status) {
+    return FALSE;
+  }
+  AbsorbLen += EncLen;
+
+  //
+  // Absorb encode_string(N).
+  //
+  EncLen = left_encode (EncBuf, NameLen * 8);
+  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *) CShake256Context, EncBuf, EncLen);
+  if (!Status) {
+    return FALSE;
+  }
+  AbsorbLen += EncLen;
+  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *) CShake256Context, Name, NameLen);
+  if (!Status) {
+    return FALSE;
+  }
+  AbsorbLen += NameLen;
+
+  //
+  // Absorb encode_string(S).
+  //
+  EncLen = left_encode (EncBuf, CustomizationLen * 8);
+  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *) CShake256Context, EncBuf, EncLen);
+  if (!Status) {
+    return FALSE;
+  }
+  AbsorbLen += EncLen;
+  Status = (BOOLEAN) sha3_update ((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) sha3_update ((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)(sha3_update ((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) (sha3_final ((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 0000000000..3eaa7c2ceb
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
@@ -0,0 +1,275 @@
+/** @file
+  ParallelHash Implementation.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <Library\PcdLib.h>
+#include <Library\SynchronizationLib.h>
+#include <Library\MmServicesTableLib.h>
+
+
+UINT16        mBlockNum;
+UINTN        mBlockSize;
+UINTN        mLastBlockSize;
+UINT8        *mInput;
+UINTN        mBlockResultSize;
+UINT8        *mBlockHashResult;
+BOOLEAN      *mBlockIsCompleted;
+SPIN_LOCK    *mSpinLockList;
+
+UINTN LeftEncode (OUT UINT8 *Encbuf, IN UINTN Value);
+UINTN RightEncode (OUT UINT8 *Encbuf, IN UINTN Value);
+
+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
+  );
+
+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]);
+    }
+  }
+}
+
+/**
+  Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
+  published December 2016.
+
+  @param  Input[in]            Pointer to the input message (X).
+  @param  InputByteLen[in]     The number(>0) of input bytes provided for the input data.
+  @param  Output[out]          Pointer to the output buffer.
+  @param  OutputByteLen[in]    The desired number of output bytes (L).
+  @param  Customization[in]    Pointer to the customization string (S).
+  @param  CustomByteLen[in]    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,
+  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;
+  EFI_STATUS   Status;
+  UINTN        StartedApNum;
+  BOOLEAN      AllCompleted;
+  UINTN        Offset;
+  BOOLEAN      ReturnValue;
+
+  if (InputByteLen == 0 || OutputByteLen == 0) {
+    return FALSE;
+  }
+
+  if (Input == NULL || Output == NULL){
+    return FALSE;
+  }
+
+  if (CustomByteLen != 0 && Customization == NULL){
+    return FALSE;
+  }
+
+  //
+  // Get Block number n.
+  //
+  mBlockNum = PcdGet16 (PcdParallelHashBlockNumber);
+
+  if (mBlockNum < 1 || InputByteLen < mBlockNum - 1){
+    return FALSE;
+  }
+
+  //
+  // Set hash result size of each block in bytes.
+  //
+  mBlockResultSize = OutputByteLen;
+
+  //
+  // calculate the block byte length B.
+  //
+  mBlockSize = InputByteLen % mBlockNum == 0 ? InputByteLen / mBlockNum : InputByteLen / (mBlockNum - 1);
+
+  //
+  // 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 = 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.
+  //
+  StartedApNum = 0;
+  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
+    if (Index != gMmst->CurrentlyExecutingCpu) {
+      Status = gMmst->MmStartupThisAp (ParallelHashApExecute, Index, NULL);
+      if (!EFI_ERROR (Status)) {
+        StartedApNum++;
+      }
+    }
+  }
+
+  //
+  // 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 (mSpinLockList);
+  }
+  if (mBlockIsCompleted != NULL){
+    FreePool (mBlockIsCompleted);
+  }
+
+  return ReturnValue;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
new file mode 100644
index 0000000000..b170c463de
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
@@ -0,0 +1,102 @@
+/** @file
+  SHA3 realted functions from OpenSSL.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Copyright 2017-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 "sha3.h"
+
+size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
+                   size_t r);
+void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r);
+
+int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t md_size)
+{
+    if (bsz <= sizeof(ctx->buf)) {
+        memset(ctx->A, 0, sizeof(ctx->A));
+
+        ctx->num = 0;
+        ctx->block_size = bsz;
+        ctx->md_size = md_size;
+        ctx->pad = pad;
+
+        return 1;
+    }
+
+    return 0;
+}
+
+
+int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
+{
+    const unsigned char *inp = _inp;
+    size_t bsz = ctx->block_size;
+    size_t num, rem;
+
+    if (len == 0)
+        return 1;
+
+    if ((num = ctx->num) != 0) {      /* process intermediate buffer? */
+        rem = bsz - num;
+
+        if (len < rem) {
+            memcpy(ctx->buf + num, inp, len);
+            ctx->num += len;
+            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(ctx->buf + num, inp, rem);
+        inp += rem, len -= rem;
+        (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
+        ctx->num = 0;
+        /* ctx->buf is processed, ctx->num is guaranteed to be zero */
+    }
+
+    if (len >= bsz)
+        rem = SHA3_absorb(ctx->A, inp, len, bsz);
+    else
+        rem = len;
+
+    if (rem) {
+        memcpy(ctx->buf, inp + len - rem, rem);
+        ctx->num = rem;
+    }
+
+    return 1;
+}
+
+int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md)
+{
+    size_t bsz = ctx->block_size;
+    size_t num = ctx->num;
+
+    if (ctx->md_size == 0)
+        return 1;
+
+    /*
+     * Pad the data with 10*1. Note that |num| can be |bsz - 1|
+     * in which case both byte operations below are performed on
+     * same byte...
+     */
+    memset(ctx->buf + num, 0, bsz - num);
+    ctx->buf[num] = ctx->pad;
+    ctx->buf[bsz - 1] |= 0x80;
+
+    (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
+
+    SHA3_squeeze(ctx->A, md, ctx->md_size, bsz);
+
+    return 1;
+}
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
new file mode 100644
index 0000000000..b2a40ee044
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
@@ -0,0 +1,53 @@
+/** @file
+  Encode realted functions from Xkcp.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+The eXtended Keccak Code Package (XKCP)
+https://github.com/XKCP/XKCP
+Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 "xkcp.h"
+
+unsigned int left_encode(unsigned char * encbuf, size_t value)
+{
+    unsigned int n, i;
+    size_t v;
+
+    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
+        ; /* empty */
+    if (n == 0)
+        n = 1;
+    for ( i = 1; i <= n; ++i )
+    {
+        encbuf[i] = (unsigned char)(value >> (8 * (n-i)));
+    }
+    encbuf[0] = (unsigned char)n;
+    return n + 1;
+}
+
+unsigned int right_encode(unsigned char * encbuf, size_t value)
+{
+    unsigned int n, i;
+    size_t v;
+
+    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
+        ; /* empty */
+    if (n == 0)
+        n = 1;
+    for ( i = 1; i <= n; ++i )
+    {
+        encbuf[i-1] = (unsigned char)(value >> (8 * (n-i)));
+    }
+    encbuf[n] = (unsigned char)n;
+    return n + 1;
+}
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
new file mode 100644
index 0000000000..052ab3a0d6
--- /dev/null
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
@@ -0,0 +1,152 @@
+/** @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;
+  UINT16   OriginalParallelHashBlockNumber;
+  UINT8    Output[64];
+
+  // Restore original PcdParallelHashBlockNumber.
+  OriginalParallelHashBlockNumber = PcdGet16 (PcdParallelHashBlockNumber);
+
+  //
+  // Test #1 using sample1.
+  //
+  PcdSet16S (PcdParallelHashBlockNumber, InputSample1ByteLen / BlockSizeSample1);
+  Status = ParallelHash256HashAll (
+             InputSample1,
+             InputSample1ByteLen,
+             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.
+  //
+  PcdSet16S (PcdParallelHashBlockNumber, InputSample2ByteLen / BlockSizeSample2);
+  Status = ParallelHash256HashAll (
+             InputSample2,
+             InputSample2ByteLen,
+             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.
+  //
+  PcdSet16S (PcdParallelHashBlockNumber, InputSample3ByteLen / BlockSizeSample3);
+  Status = ParallelHash256HashAll (
+             InputSample3,
+             InputSample3ByteLen,
+             Output,
+             OutputByteLen,
+             CustomizationSample3,
+             CustomSample3ByteLen
+             );
+  UT_ASSERT_TRUE (Status);
+
+  // Check the output with the expected output.
+  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3, OutputByteLen);
+
+  // Recover original PcdParallelHashBlockNumber.
+  PcdSet16S (PcdParallelHashBlockNumber, OriginalParallelHashBlockNumber);
+
+  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.dec b/CryptoPkg/CryptoPkg.dec
index 5888941bab..3af55d9c10 100644
--- a/CryptoPkg/CryptoPkg.dec
+++ b/CryptoPkg/CryptoPkg.dec
@@ -4,7 +4,7 @@
 #  This Package provides cryptographic-related libraries for UEFI security modules.
 #  It also provides a test application to test libraries.
 #
-#  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
 #
 ##
@@ -81,5 +81,12 @@
   # @ValidList 0x80000001 | 0x00000001, 0x00000002, 0x00000004, 0x00000008, 0x00000010
   gEfiCryptoPkgTokenSpaceGuid.PcdHashApiLibPolicy|0x00000002|UINT32|0x00000001
 
+[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
+  ## This PCD indicates the block number of parallel hash
+  #  Based on the value set, parallel hash can chose the block
+  #  number to calculate specific hash.<BR>
+  #  The number can be set by platform team according to the core number.
+  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber|0x0100|UINT16|0x00000003
+
 [UserExtensions.TianoCore."ExtraFiles"]
   CryptoPkgExtra.uni
diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
index f4bc7c0d73..0b274b1257 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,33 @@ 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[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,
+  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/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
index e6470d7a21..70159163d4 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,9 @@
   OpensslLib
   IntrinsicLib
   PrintLib
+  MmServicesTableLib
+  SynchronizationLib
+  PcdLib
 
 #
 # Remove these [BuildOptions] after this library is cleaned up
@@ -101,3 +108,6 @@
   GCC:*_CLANG35_*_CC_FLAGS = -std=c99
   GCC:*_CLANG38_*_CC_FLAGS = -std=c99
   GCC:*_CLANGPDB_*_CC_FLAGS = -std=c99 -Wno-error=incompatible-pointer-types
+
+[Pcd]
+  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h b/CryptoPkg/Library/Include/CrtLibSupport.h
index d257dca8fa..35d9c62a0b 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
 
@@ -21,6 +21,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 #define MAX_STRING_SIZE  0x1000
 
+#define PARALLELHASH_CUSTOMIZATION "ParallelHash"
+
 //
 // We already have "no-ui" in out Configure invocation.
 // but the code still fails to compile.
@@ -111,6 +113,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/Library/Include/sha3.h b/CryptoPkg/Library/Include/sha3.h
new file mode 100644
index 0000000000..71b4c75548
--- /dev/null
+++ b/CryptoPkg/Library/Include/sha3.h
@@ -0,0 +1,32 @@
+/** @file
+  SHA3 realted functions from OpenSSL.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+Copyright 2017-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 <CrtLibSupport.h>
+
+#define KECCAK1600_WIDTH 1600
+
+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;
+
+int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t md_size);
+
+int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
+
+int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md);
diff --git a/CryptoPkg/Library/Include/xkcp.h b/CryptoPkg/Library/Include/xkcp.h
new file mode 100644
index 0000000000..b328d672e4
--- /dev/null
+++ b/CryptoPkg/Library/Include/xkcp.h
@@ -0,0 +1,23 @@
+/** @file
+  Encode realted functions from Xkcp.
+
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+The eXtended Keccak Code Package (XKCP)
+https://github.com/XKCP/XKCP
+Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 <CrtLibSupport.h>
+
+unsigned int left_encode(unsigned char * encbuf, size_t value);
+
+unsigned int right_encode(unsigned char * encbuf, size_t value);
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
index a6b3482742..0bffd687c2 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
@@ -1,7 +1,7 @@
 /** @file
   Application for Cryptographic Primitives Validation.
 
-Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -19,6 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 #include <Library/BaseLib.h>
 #include <Library/BaseMemoryLib.h>
 #include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
 // #include <UnitTestTypes.h>
 #include <Library/UnitTestLib.h>
 // #include <Library/UnitTestAssertLib.h>
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
index 00c8692650..61a59d6a47 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,8 @@
   DebugLib
   BaseCryptLib
   UnitTestLib
+  PcdLib
+
+[Pcd]
+  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
+
diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
index ca789aa6ad..682f25a754 100644
--- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
+++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
@@ -2,6 +2,7 @@
 # BaseCryptLib UnitTest built for execution in UEFI Shell.
 #
 # Copyright (c) Microsoft Corporation.<BR>
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
 # SPDX-License-Identifier: BSD-2-Clause-Patent
 ##
 
@@ -36,6 +37,7 @@
   Pkcs7EkuTests.c
   OaepEncryptTests.c
   RsaPssTests.c
+  ParallelhashTests.c
 
 [Packages]
   MdePkg/MdePkg.dec
@@ -48,3 +50,7 @@
   UnitTestLib
   PrintLib
   BaseCryptLib
+  PcdLib
+
+[Pcd]
+  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
-- 
2.26.2.windows.1


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

* Re: [PATCH v1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
  2022-02-11  9:05 [PATCH v1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib Li, Zhihao
@ 2022-02-15  6:08 ` Yao, Jiewen
  2022-02-16  7:43   ` Li, Zhihao
  0 siblings, 1 reply; 6+ messages in thread
From: Yao, Jiewen @ 2022-02-15  6:08 UTC (permalink / raw)
  To: Li, Zhihao, devel@edk2.groups.io
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Fu, Siyuan

Thanks for the update.

Feedback below:

1) How block size is determined for below API?

BOOLEAN
EFIAPI
ParallelHash256HashAll (
  IN CONST VOID            *Input,
  IN       UINTN           InputByteLen,
  OUT      VOID            *Output,
  IN       UINTN           OutputByteLen,
  IN CONST VOID            *Customization,
  IN       UINTN           CustomByteLen
  );

Is that determined by PcdParallelHashBlockNumber ?

I don’t think it is good idea to let a crypto library determine a platform PCD.
For example, how do you support binary crypto module ?

2) Why we need "sha3.h" and "xkcp.h" ?
These are openssl specific structure. It shall not be put to EDKII file header.

CryptoPkg\Library\Include shall only contain generic dependency header.




Thank you
Yao, Jiewen

> -----Original Message-----
> From: Li, Zhihao <zhihao.li@intel.com>
> Sent: Friday, February 11, 2022 5:05 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: [PATCH v1] 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.
> 
> 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>
> 
> Signed-off-by: Zhihao Li <zhihao.li@intel.com>
> ---
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                   | 313
> ++++++++++++++++++++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c                | 275
> +++++++++++++++++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                        | 102 +++++++
>  CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                        |  53 ++++
>  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c       | 152
> ++++++++++
>  CryptoPkg/CryptoPkg.dec                                                |   9 +-
>  CryptoPkg/Include/Library/BaseCryptLib.h                               |  29 +-
>  CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                         |  12 +-
>  CryptoPkg/Library/Include/CrtLibSupport.h                              |   5 +-
>  CryptoPkg/Library/Include/sha3.h                                       |  32 ++
>  CryptoPkg/Library/Include/xkcp.h                                       |  23 ++
>  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h        |   3 +-
>  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf  |   7 +
>  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf |   6 +
>  14 files changed, 1016 insertions(+), 5 deletions(-)
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> new file mode 100644
> index 0000000000..5efced3f46
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> @@ -0,0 +1,313 @@
> +/** @file
> 
> +  cSHAKE-256 Digest Wrapper Implementations.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "InternalCryptLib.h"
> 
> +#include "sha3.h"
> 
> +#include "xkcp.h"
> 
> +
> 
> +#define  CSHAKE256_SECURITY_STRENGTH    256
> 
> +#define  CSHAKE256_RATE_IN_BYTES        136
> 
> +
> 
> +const CHAR8 mZeroPadding[CSHAKE256_RATE_IN_BYTES] = {0};
> 
> +
> 
> +UINTN
> 
> +EFIAPI
> 
> +LeftEncode (
> 
> +  OUT UINT8     *Encbuf,
> 
> +  IN  UINTN     Value
> 
> +  )
> 
> +{
> 
> +  return left_encode (Encbuf, Value);
> 
> +}
> 
> +
> 
> +UINTN
> 
> +EFIAPI
> 
> +RightEncode (
> 
> +  OUT UINT8     *Encbuf,
> 
> +  IN  UINTN     Value
> 
> +  )
> 
> +{
> 
> +  return right_encode (Encbuf, Value);
> 
> +}
> 
> +
> 
> +/**
> 
> +  Retrieves the size, in bytes, of the context buffer required for cSHAKE-256
> hash operations.
> 
> +
> 
> +  @return  The size, in bytes, of the context buffer required for cSHAKE-256
> hash operations.
> 
> +
> 
> +**/
> 
> +UINTN
> 
> +EFIAPI
> 
> +CShake256GetContextSize (
> 
> +  VOID
> 
> +  )
> 
> +{
> 
> +  return (UINTN) (sizeof (KECCAK1600_CTX));
> 
> +}
> 
> +
> 
> +/**
> 
> +  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;
> 
> +  unsigned char EncBuf[sizeof(size_t)+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.
> 
> +    //
> 
> +    return (BOOLEAN) init (
> 
> +                      (KECCAK1600_CTX *) CShake256Context,
> 
> +                      '\x1f',
> 
> +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
> 
> +                      OutputLen
> 
> +                      );
> 
> +  }
> 
> +
> 
> +  Status = (BOOLEAN) init (
> 
> +                      (KECCAK1600_CTX *) CShake256Context,
> 
> +                      '\x04',
> 
> +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,
> 
> +                      OutputLen
> 
> +                      );
> 
> +  if (!Status) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  AbsorbLen = 0;
> 
> +  //
> 
> +  // Absorb Absorb bytepad(.., rate).
> 
> +  //
> 
> +  EncLen = left_encode (EncBuf, CSHAKE256_RATE_IN_BYTES);
> 
> +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *) CShake256Context,
> EncBuf, EncLen);
> 
> +  if (!Status) {
> 
> +    return FALSE;
> 
> +  }
> 
> +  AbsorbLen += EncLen;
> 
> +
> 
> +  //
> 
> +  // Absorb encode_string(N).
> 
> +  //
> 
> +  EncLen = left_encode (EncBuf, NameLen * 8);
> 
> +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *) CShake256Context,
> EncBuf, EncLen);
> 
> +  if (!Status) {
> 
> +    return FALSE;
> 
> +  }
> 
> +  AbsorbLen += EncLen;
> 
> +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *) CShake256Context,
> Name, NameLen);
> 
> +  if (!Status) {
> 
> +    return FALSE;
> 
> +  }
> 
> +  AbsorbLen += NameLen;
> 
> +
> 
> +  //
> 
> +  // Absorb encode_string(S).
> 
> +  //
> 
> +  EncLen = left_encode (EncBuf, CustomizationLen * 8);
> 
> +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *) CShake256Context,
> EncBuf, EncLen);
> 
> +  if (!Status) {
> 
> +    return FALSE;
> 
> +  }
> 
> +  AbsorbLen += EncLen;
> 
> +  Status = (BOOLEAN) sha3_update ((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) sha3_update ((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)(sha3_update ((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) (sha3_final ((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 0000000000..3eaa7c2ceb
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> @@ -0,0 +1,275 @@
> +/** @file
> 
> +  ParallelHash Implementation.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +**/
> 
> +
> 
> +#include "InternalCryptLib.h"
> 
> +#include <Library\PcdLib.h>
> 
> +#include <Library\SynchronizationLib.h>
> 
> +#include <Library\MmServicesTableLib.h>
> 
> +
> 
> +
> 
> +UINT16        mBlockNum;
> 
> +UINTN        mBlockSize;
> 
> +UINTN        mLastBlockSize;
> 
> +UINT8        *mInput;
> 
> +UINTN        mBlockResultSize;
> 
> +UINT8        *mBlockHashResult;
> 
> +BOOLEAN      *mBlockIsCompleted;
> 
> +SPIN_LOCK    *mSpinLockList;
> 
> +
> 
> +UINTN LeftEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> 
> +UINTN RightEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> 
> +
> 
> +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
> 
> +  );
> 
> +
> 
> +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]);
> 
> +    }
> 
> +  }
> 
> +}
> 
> +
> 
> +/**
> 
> +  Parallel hash function ParallelHash256, as defined in NIST's Special Publication
> 800-185,
> 
> +  published December 2016.
> 
> +
> 
> +  @param  Input[in]            Pointer to the input message (X).
> 
> +  @param  InputByteLen[in]     The number(>0) of input bytes provided for the
> input data.
> 
> +  @param  Output[out]          Pointer to the output buffer.
> 
> +  @param  OutputByteLen[in]    The desired number of output bytes (L).
> 
> +  @param  Customization[in]    Pointer to the customization string (S).
> 
> +  @param  CustomByteLen[in]    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,
> 
> +  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;
> 
> +  EFI_STATUS   Status;
> 
> +  UINTN        StartedApNum;
> 
> +  BOOLEAN      AllCompleted;
> 
> +  UINTN        Offset;
> 
> +  BOOLEAN      ReturnValue;
> 
> +
> 
> +  if (InputByteLen == 0 || OutputByteLen == 0) {
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  if (Input == NULL || Output == NULL){
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  if (CustomByteLen != 0 && Customization == NULL){
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Get Block number n.
> 
> +  //
> 
> +  mBlockNum = PcdGet16 (PcdParallelHashBlockNumber);
> 
> +
> 
> +  if (mBlockNum < 1 || InputByteLen < mBlockNum - 1){
> 
> +    return FALSE;
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // Set hash result size of each block in bytes.
> 
> +  //
> 
> +  mBlockResultSize = OutputByteLen;
> 
> +
> 
> +  //
> 
> +  // calculate the block byte length B.
> 
> +  //
> 
> +  mBlockSize = InputByteLen % mBlockNum == 0 ? InputByteLen / mBlockNum :
> InputByteLen / (mBlockNum - 1);
> 
> +
> 
> +  //
> 
> +  // 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 = 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.
> 
> +  //
> 
> +  StartedApNum = 0;
> 
> +  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
> 
> +    if (Index != gMmst->CurrentlyExecutingCpu) {
> 
> +      Status = gMmst->MmStartupThisAp (ParallelHashApExecute, Index, NULL);
> 
> +      if (!EFI_ERROR (Status)) {
> 
> +        StartedApNum++;
> 
> +      }
> 
> +    }
> 
> +  }
> 
> +
> 
> +  //
> 
> +  // 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 (mSpinLockList);
> 
> +  }
> 
> +  if (mBlockIsCompleted != NULL){
> 
> +    FreePool (mBlockIsCompleted);
> 
> +  }
> 
> +
> 
> +  return ReturnValue;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> new file mode 100644
> index 0000000000..b170c463de
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> @@ -0,0 +1,102 @@
> +/** @file
> 
> +  SHA3 realted functions from OpenSSL.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +Copyright 2017-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 "sha3.h"
> 
> +
> 
> +size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t len,
> 
> +                   size_t r);
> 
> +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len, size_t r);
> 
> +
> 
> +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t md_size)
> 
> +{
> 
> +    if (bsz <= sizeof(ctx->buf)) {
> 
> +        memset(ctx->A, 0, sizeof(ctx->A));
> 
> +
> 
> +        ctx->num = 0;
> 
> +        ctx->block_size = bsz;
> 
> +        ctx->md_size = md_size;
> 
> +        ctx->pad = pad;
> 
> +
> 
> +        return 1;
> 
> +    }
> 
> +
> 
> +    return 0;
> 
> +}
> 
> +
> 
> +
> 
> +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
> 
> +{
> 
> +    const unsigned char *inp = _inp;
> 
> +    size_t bsz = ctx->block_size;
> 
> +    size_t num, rem;
> 
> +
> 
> +    if (len == 0)
> 
> +        return 1;
> 
> +
> 
> +    if ((num = ctx->num) != 0) {      /* process intermediate buffer? */
> 
> +        rem = bsz - num;
> 
> +
> 
> +        if (len < rem) {
> 
> +            memcpy(ctx->buf + num, inp, len);
> 
> +            ctx->num += len;
> 
> +            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(ctx->buf + num, inp, rem);
> 
> +        inp += rem, len -= rem;
> 
> +        (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> 
> +        ctx->num = 0;
> 
> +        /* ctx->buf is processed, ctx->num is guaranteed to be zero */
> 
> +    }
> 
> +
> 
> +    if (len >= bsz)
> 
> +        rem = SHA3_absorb(ctx->A, inp, len, bsz);
> 
> +    else
> 
> +        rem = len;
> 
> +
> 
> +    if (rem) {
> 
> +        memcpy(ctx->buf, inp + len - rem, rem);
> 
> +        ctx->num = rem;
> 
> +    }
> 
> +
> 
> +    return 1;
> 
> +}
> 
> +
> 
> +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md)
> 
> +{
> 
> +    size_t bsz = ctx->block_size;
> 
> +    size_t num = ctx->num;
> 
> +
> 
> +    if (ctx->md_size == 0)
> 
> +        return 1;
> 
> +
> 
> +    /*
> 
> +     * Pad the data with 10*1. Note that |num| can be |bsz - 1|
> 
> +     * in which case both byte operations below are performed on
> 
> +     * same byte...
> 
> +     */
> 
> +    memset(ctx->buf + num, 0, bsz - num);
> 
> +    ctx->buf[num] = ctx->pad;
> 
> +    ctx->buf[bsz - 1] |= 0x80;
> 
> +
> 
> +    (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> 
> +
> 
> +    SHA3_squeeze(ctx->A, md, ctx->md_size, bsz);
> 
> +
> 
> +    return 1;
> 
> +}
> 
> diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> new file mode 100644
> index 0000000000..b2a40ee044
> --- /dev/null
> +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> @@ -0,0 +1,53 @@
> +/** @file
> 
> +  Encode realted functions from Xkcp.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +The eXtended Keccak Code Package (XKCP)
> 
> +https://github.com/XKCP/XKCP
> 
> +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 "xkcp.h"
> 
> +
> 
> +unsigned int left_encode(unsigned char * encbuf, size_t value)
> 
> +{
> 
> +    unsigned int n, i;
> 
> +    size_t v;
> 
> +
> 
> +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> 
> +        ; /* empty */
> 
> +    if (n == 0)
> 
> +        n = 1;
> 
> +    for ( i = 1; i <= n; ++i )
> 
> +    {
> 
> +        encbuf[i] = (unsigned char)(value >> (8 * (n-i)));
> 
> +    }
> 
> +    encbuf[0] = (unsigned char)n;
> 
> +    return n + 1;
> 
> +}
> 
> +
> 
> +unsigned int right_encode(unsigned char * encbuf, size_t value)
> 
> +{
> 
> +    unsigned int n, i;
> 
> +    size_t v;
> 
> +
> 
> +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> 
> +        ; /* empty */
> 
> +    if (n == 0)
> 
> +        n = 1;
> 
> +    for ( i = 1; i <= n; ++i )
> 
> +    {
> 
> +        encbuf[i-1] = (unsigned char)(value >> (8 * (n-i)));
> 
> +    }
> 
> +    encbuf[n] = (unsigned char)n;
> 
> +    return n + 1;
> 
> +}
> 
> diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> new file mode 100644
> index 0000000000..052ab3a0d6
> --- /dev/null
> +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> @@ -0,0 +1,152 @@
> +/** @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;
> 
> +  UINT16   OriginalParallelHashBlockNumber;
> 
> +  UINT8    Output[64];
> 
> +
> 
> +  // Restore original PcdParallelHashBlockNumber.
> 
> +  OriginalParallelHashBlockNumber = PcdGet16 (PcdParallelHashBlockNumber);
> 
> +
> 
> +  //
> 
> +  // Test #1 using sample1.
> 
> +  //
> 
> +  PcdSet16S (PcdParallelHashBlockNumber, InputSample1ByteLen /
> BlockSizeSample1);
> 
> +  Status = ParallelHash256HashAll (
> 
> +             InputSample1,
> 
> +             InputSample1ByteLen,
> 
> +             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.
> 
> +  //
> 
> +  PcdSet16S (PcdParallelHashBlockNumber, InputSample2ByteLen /
> BlockSizeSample2);
> 
> +  Status = ParallelHash256HashAll (
> 
> +             InputSample2,
> 
> +             InputSample2ByteLen,
> 
> +             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.
> 
> +  //
> 
> +  PcdSet16S (PcdParallelHashBlockNumber, InputSample3ByteLen /
> BlockSizeSample3);
> 
> +  Status = ParallelHash256HashAll (
> 
> +             InputSample3,
> 
> +             InputSample3ByteLen,
> 
> +             Output,
> 
> +             OutputByteLen,
> 
> +             CustomizationSample3,
> 
> +             CustomSample3ByteLen
> 
> +             );
> 
> +  UT_ASSERT_TRUE (Status);
> 
> +
> 
> +  // Check the output with the expected output.
> 
> +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3, OutputByteLen);
> 
> +
> 
> +  // Recover original PcdParallelHashBlockNumber.
> 
> +  PcdSet16S (PcdParallelHashBlockNumber, OriginalParallelHashBlockNumber);
> 
> +
> 
> +  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.dec b/CryptoPkg/CryptoPkg.dec
> index 5888941bab..3af55d9c10 100644
> --- a/CryptoPkg/CryptoPkg.dec
> +++ b/CryptoPkg/CryptoPkg.dec
> @@ -4,7 +4,7 @@
>  #  This Package provides cryptographic-related libraries for UEFI security
> modules.
> 
>  #  It also provides a test application to test libraries.
> 
>  #
> 
> -#  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
> 
>  #
> 
>  ##
> 
> @@ -81,5 +81,12 @@
>    # @ValidList 0x80000001 | 0x00000001, 0x00000002, 0x00000004,
> 0x00000008, 0x00000010
> 
> 
> gEfiCryptoPkgTokenSpaceGuid.PcdHashApiLibPolicy|0x00000002|UINT32|0x00
> 000001
> 
> 
> 
> +[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
> 
> +  ## This PCD indicates the block number of parallel hash
> 
> +  #  Based on the value set, parallel hash can chose the block
> 
> +  #  number to calculate specific hash.<BR>
> 
> +  #  The number can be set by platform team according to the core number.
> 
> +
> gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber|0x0100|UINT16|0
> x00000003
> 
> +
> 
>  [UserExtensions.TianoCore."ExtraFiles"]
> 
>    CryptoPkgExtra.uni
> 
> diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> b/CryptoPkg/Include/Library/BaseCryptLib.h
> index f4bc7c0d73..0b274b1257 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,33 @@ 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[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,
> 
> +  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/Library/BaseCryptLib/SmmCryptLib.inf
> b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> index e6470d7a21..70159163d4 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,9 @@
>    OpensslLib
> 
>    IntrinsicLib
> 
>    PrintLib
> 
> +  MmServicesTableLib
> 
> +  SynchronizationLib
> 
> +  PcdLib
> 
> 
> 
>  #
> 
>  # Remove these [BuildOptions] after this library is cleaned up
> 
> @@ -101,3 +108,6 @@
>    GCC:*_CLANG35_*_CC_FLAGS = -std=c99
> 
>    GCC:*_CLANG38_*_CC_FLAGS = -std=c99
> 
>    GCC:*_CLANGPDB_*_CC_FLAGS = -std=c99 -Wno-error=incompatible-pointer-
> types
> 
> +
> 
> +[Pcd]
> 
> +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> 
> diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h
> b/CryptoPkg/Library/Include/CrtLibSupport.h
> index d257dca8fa..35d9c62a0b 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
> 
> 
> 
> @@ -21,6 +21,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
>  #define MAX_STRING_SIZE  0x1000
> 
> 
> 
> +#define PARALLELHASH_CUSTOMIZATION "ParallelHash"
> 
> +
> 
>  //
> 
>  // We already have "no-ui" in out Configure invocation.
> 
>  // but the code still fails to compile.
> 
> @@ -111,6 +113,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/Library/Include/sha3.h
> b/CryptoPkg/Library/Include/sha3.h
> new file mode 100644
> index 0000000000..71b4c75548
> --- /dev/null
> +++ b/CryptoPkg/Library/Include/sha3.h
> @@ -0,0 +1,32 @@
> +/** @file
> 
> +  SHA3 realted functions from OpenSSL.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +Copyright 2017-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 <CrtLibSupport.h>
> 
> +
> 
> +#define KECCAK1600_WIDTH 1600
> 
> +
> 
> +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;
> 
> +
> 
> +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t md_size);
> 
> +
> 
> +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
> 
> +
> 
> +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md);
> 
> diff --git a/CryptoPkg/Library/Include/xkcp.h
> b/CryptoPkg/Library/Include/xkcp.h
> new file mode 100644
> index 0000000000..b328d672e4
> --- /dev/null
> +++ b/CryptoPkg/Library/Include/xkcp.h
> @@ -0,0 +1,23 @@
> +/** @file
> 
> +  Encode realted functions from Xkcp.
> 
> +
> 
> +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
> +SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> +
> 
> +The eXtended Keccak Code Package (XKCP)
> 
> +https://github.com/XKCP/XKCP
> 
> +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 <CrtLibSupport.h>
> 
> +
> 
> +unsigned int left_encode(unsigned char * encbuf, size_t value);
> 
> +
> 
> +unsigned int right_encode(unsigned char * encbuf, size_t value);
> 
> diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> index a6b3482742..0bffd687c2 100644
> --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> @@ -1,7 +1,7 @@
>  /** @file
> 
>    Application for Cryptographic Primitives Validation.
> 
> 
> 
> -Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
> 
> +Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR>
> 
>  SPDX-License-Identifier: BSD-2-Clause-Patent
> 
> 
> 
>  **/
> 
> @@ -19,6 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
>  #include <Library/BaseLib.h>
> 
>  #include <Library/BaseMemoryLib.h>
> 
>  #include <Library/MemoryAllocationLib.h>
> 
> +#include <Library/PcdLib.h>
> 
>  // #include <UnitTestTypes.h>
> 
>  #include <Library/UnitTestLib.h>
> 
>  // #include <Library/UnitTestAssertLib.h>
> 
> diff --git
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> index 00c8692650..61a59d6a47 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,8 @@
>    DebugLib
> 
>    BaseCryptLib
> 
>    UnitTestLib
> 
> +  PcdLib
> 
> +
> 
> +[Pcd]
> 
> +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> 
> +
> 
> diff --git
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
> index ca789aa6ad..682f25a754 100644
> --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
> +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf
> @@ -2,6 +2,7 @@
>  # BaseCryptLib UnitTest built for execution in UEFI Shell.
> 
>  #
> 
>  # Copyright (c) Microsoft Corporation.<BR>
> 
> +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> 
>  # SPDX-License-Identifier: BSD-2-Clause-Patent
> 
>  ##
> 
> 
> 
> @@ -36,6 +37,7 @@
>    Pkcs7EkuTests.c
> 
>    OaepEncryptTests.c
> 
>    RsaPssTests.c
> 
> +  ParallelhashTests.c
> 
> 
> 
>  [Packages]
> 
>    MdePkg/MdePkg.dec
> 
> @@ -48,3 +50,7 @@
>    UnitTestLib
> 
>    PrintLib
> 
>    BaseCryptLib
> 
> +  PcdLib
> 
> +
> 
> +[Pcd]
> 
> +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> 
> --
> 2.26.2.windows.1


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

* Re: [PATCH v1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
  2022-02-15  6:08 ` Yao, Jiewen
@ 2022-02-16  7:43   ` Li, Zhihao
  2022-02-16  7:51     ` Yao, Jiewen
  0 siblings, 1 reply; 6+ messages in thread
From: Li, Zhihao @ 2022-02-16  7:43 UTC (permalink / raw)
  To: Yao, Jiewen, devel@edk2.groups.io
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Fu, Siyuan

With your comment, we plan do some modification for parallelhash.
1. Plan to add  a parameter (BlockSize) on  ParallelHash256HashAll  function to replace PcdParallelHashBlockNumber.
2. Plan to move sha3.h and xkcp.h to CryptoPkg\Library\BaseCryptLib\Hash folder.


> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: Tuesday, February 15, 2022 2:09 PM
> To: Li, Zhihao <zhihao.li@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: [PATCH v1] CryptoPkg: Add new hash algorithm
> ParallelHash256HashAll in BaseCryptLib.
> 
> Thanks for the update.
> 
> Feedback below:
> 
> 1) How block size is determined for below API?
> 
> BOOLEAN
> EFIAPI
> ParallelHash256HashAll (
>   IN CONST VOID            *Input,
>   IN       UINTN           InputByteLen,
>   OUT      VOID            *Output,
>   IN       UINTN           OutputByteLen,
>   IN CONST VOID            *Customization,
>   IN       UINTN           CustomByteLen
>   );
> 
> Is that determined by PcdParallelHashBlockNumber ?
> 
> I don’t think it is good idea to let a crypto library determine a platform PCD.
> For example, how do you support binary crypto module ?
Plan to add  a parameter (BlockSize) to replace PcdParallelHashBlockNumber.
> 
> 2) Why we need "sha3.h" and "xkcp.h" ?
> These are openssl specific structure. It shall not be put to EDKII file header.
> 
> CryptoPkg\Library\Include shall only contain generic dependency header.
Plan to move sha3.h and xkcp.h to CryptoPkg\Library\BaseCryptLib\Hash folder.
> 
> 
> 
> 
> Thank you
> Yao, Jiewen
> 
> > -----Original Message-----
> > From: Li, Zhihao <zhihao.li@intel.com>
> > Sent: Friday, February 11, 2022 5:05 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: [PATCH v1] 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.
> >
> > 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>
> >
> > Signed-off-by: Zhihao Li <zhihao.li@intel.com>
> > ---
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                   | 313
> > ++++++++++++++++++++
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c                | 275
> > +++++++++++++++++
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                        | 102
> +++++++
> >  CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                        |  53 ++++
> >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c       |
> 152
> > ++++++++++
> >  CryptoPkg/CryptoPkg.dec                                                |   9 +-
> >  CryptoPkg/Include/Library/BaseCryptLib.h                               |  29 +-
> >  CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                         |  12 +-
> >  CryptoPkg/Library/Include/CrtLibSupport.h                              |   5 +-
> >  CryptoPkg/Library/Include/sha3.h                                       |  32 ++
> >  CryptoPkg/Library/Include/xkcp.h                                       |  23 ++
> >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h        |   3
> +-
> >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> |   7 +
> >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf |
> 6 +
> >  14 files changed, 1016 insertions(+), 5 deletions(-)
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > new file mode 100644
> > index 0000000000..5efced3f46
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > @@ -0,0 +1,313 @@
> > +/** @file
> >
> > +  cSHAKE-256 Digest Wrapper Implementations.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "InternalCryptLib.h"
> >
> > +#include "sha3.h"
> >
> > +#include "xkcp.h"
> >
> > +
> >
> > +#define  CSHAKE256_SECURITY_STRENGTH    256
> >
> > +#define  CSHAKE256_RATE_IN_BYTES        136
> >
> > +
> >
> > +const CHAR8 mZeroPadding[CSHAKE256_RATE_IN_BYTES] = {0};
> >
> > +
> >
> > +UINTN
> >
> > +EFIAPI
> >
> > +LeftEncode (
> >
> > +  OUT UINT8     *Encbuf,
> >
> > +  IN  UINTN     Value
> >
> > +  )
> >
> > +{
> >
> > +  return left_encode (Encbuf, Value);
> >
> > +}
> >
> > +
> >
> > +UINTN
> >
> > +EFIAPI
> >
> > +RightEncode (
> >
> > +  OUT UINT8     *Encbuf,
> >
> > +  IN  UINTN     Value
> >
> > +  )
> >
> > +{
> >
> > +  return right_encode (Encbuf, Value);
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Retrieves the size, in bytes, of the context buffer required for
> > + cSHAKE-256
> > hash operations.
> >
> > +
> >
> > +  @return  The size, in bytes, of the context buffer required for
> > + cSHAKE-256
> > hash operations.
> >
> > +
> >
> > +**/
> >
> > +UINTN
> >
> > +EFIAPI
> >
> > +CShake256GetContextSize (
> >
> > +  VOID
> >
> > +  )
> >
> > +{
> >
> > +  return (UINTN) (sizeof (KECCAK1600_CTX));
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  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;
> >
> > +  unsigned char EncBuf[sizeof(size_t)+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.
> >
> > +    //
> >
> > +    return (BOOLEAN) init (
> >
> > +                      (KECCAK1600_CTX *) CShake256Context,
> >
> > +                      '\x1f',
> >
> > +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH
> > + * 2) / 8,
> >
> > +                      OutputLen
> >
> > +                      );
> >
> > +  }
> >
> > +
> >
> > +  Status = (BOOLEAN) init (
> >
> > +                      (KECCAK1600_CTX *) CShake256Context,
> >
> > +                      '\x04',
> >
> > +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH
> > + * 2) / 8,
> >
> > +                      OutputLen
> >
> > +                      );
> >
> > +  if (!Status) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  AbsorbLen = 0;
> >
> > +  //
> >
> > +  // Absorb Absorb bytepad(.., rate).
> >
> > +  //
> >
> > +  EncLen = left_encode (EncBuf, CSHAKE256_RATE_IN_BYTES);
> >
> > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > + CShake256Context,
> > EncBuf, EncLen);
> >
> > +  if (!Status) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +  AbsorbLen += EncLen;
> >
> > +
> >
> > +  //
> >
> > +  // Absorb encode_string(N).
> >
> > +  //
> >
> > +  EncLen = left_encode (EncBuf, NameLen * 8);
> >
> > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > + CShake256Context,
> > EncBuf, EncLen);
> >
> > +  if (!Status) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +  AbsorbLen += EncLen;
> >
> > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > + CShake256Context,
> > Name, NameLen);
> >
> > +  if (!Status) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +  AbsorbLen += NameLen;
> >
> > +
> >
> > +  //
> >
> > +  // Absorb encode_string(S).
> >
> > +  //
> >
> > +  EncLen = left_encode (EncBuf, CustomizationLen * 8);
> >
> > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > + CShake256Context,
> > EncBuf, EncLen);
> >
> > +  if (!Status) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +  AbsorbLen += EncLen;
> >
> > +  Status = (BOOLEAN) sha3_update ((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) sha3_update ((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)(sha3_update ((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) (sha3_final ((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 0000000000..3eaa7c2ceb
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> > @@ -0,0 +1,275 @@
> > +/** @file
> >
> > +  ParallelHash Implementation.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +**/
> >
> > +
> >
> > +#include "InternalCryptLib.h"
> >
> > +#include <Library\PcdLib.h>
> >
> > +#include <Library\SynchronizationLib.h>
> >
> > +#include <Library\MmServicesTableLib.h>
> >
> > +
> >
> > +
> >
> > +UINT16        mBlockNum;
> >
> > +UINTN        mBlockSize;
> >
> > +UINTN        mLastBlockSize;
> >
> > +UINT8        *mInput;
> >
> > +UINTN        mBlockResultSize;
> >
> > +UINT8        *mBlockHashResult;
> >
> > +BOOLEAN      *mBlockIsCompleted;
> >
> > +SPIN_LOCK    *mSpinLockList;
> >
> > +
> >
> > +UINTN LeftEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> >
> > +UINTN RightEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> >
> > +
> >
> > +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
> >
> > +  );
> >
> > +
> >
> > +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]);
> >
> > +    }
> >
> > +  }
> >
> > +}
> >
> > +
> >
> > +/**
> >
> > +  Parallel hash function ParallelHash256, as defined in NIST's
> > + Special Publication
> > 800-185,
> >
> > +  published December 2016.
> >
> > +
> >
> > +  @param  Input[in]            Pointer to the input message (X).
> >
> > +  @param  InputByteLen[in]     The number(>0) of input bytes provided for
> the
> > input data.
> >
> > +  @param  Output[out]          Pointer to the output buffer.
> >
> > +  @param  OutputByteLen[in]    The desired number of output bytes (L).
> >
> > +  @param  Customization[in]    Pointer to the customization string (S).
> >
> > +  @param  CustomByteLen[in]    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,
> >
> > +  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;
> >
> > +  EFI_STATUS   Status;
> >
> > +  UINTN        StartedApNum;
> >
> > +  BOOLEAN      AllCompleted;
> >
> > +  UINTN        Offset;
> >
> > +  BOOLEAN      ReturnValue;
> >
> > +
> >
> > +  if (InputByteLen == 0 || OutputByteLen == 0) {
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  if (Input == NULL || Output == NULL){
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  if (CustomByteLen != 0 && Customization == NULL){
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Get Block number n.
> >
> > +  //
> >
> > +  mBlockNum = PcdGet16 (PcdParallelHashBlockNumber);
> >
> > +
> >
> > +  if (mBlockNum < 1 || InputByteLen < mBlockNum - 1){
> >
> > +    return FALSE;
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // Set hash result size of each block in bytes.
> >
> > +  //
> >
> > +  mBlockResultSize = OutputByteLen;
> >
> > +
> >
> > +  //
> >
> > +  // calculate the block byte length B.
> >
> > +  //
> >
> > +  mBlockSize = InputByteLen % mBlockNum == 0 ? InputByteLen /
> mBlockNum :
> > InputByteLen / (mBlockNum - 1);
> >
> > +
> >
> > +  //
> >
> > +  // 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 = 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.
> >
> > +  //
> >
> > +  StartedApNum = 0;
> >
> > +  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
> >
> > +    if (Index != gMmst->CurrentlyExecutingCpu) {
> >
> > +      Status = gMmst->MmStartupThisAp (ParallelHashApExecute, Index,
> > + NULL);
> >
> > +      if (!EFI_ERROR (Status)) {
> >
> > +        StartedApNum++;
> >
> > +      }
> >
> > +    }
> >
> > +  }
> >
> > +
> >
> > +  //
> >
> > +  // 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 (mSpinLockList);
> >
> > +  }
> >
> > +  if (mBlockIsCompleted != NULL){
> >
> > +    FreePool (mBlockIsCompleted);
> >
> > +  }
> >
> > +
> >
> > +  return ReturnValue;
> >
> > +}
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > new file mode 100644
> > index 0000000000..b170c463de
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > @@ -0,0 +1,102 @@
> > +/** @file
> >
> > +  SHA3 realted functions from OpenSSL.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +Copyright 2017-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 "sha3.h"
> >
> > +
> >
> > +size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t
> > +len,
> >
> > +                   size_t r);
> >
> > +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len,
> > +size_t r);
> >
> > +
> >
> > +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t
> > +md_size)
> >
> > +{
> >
> > +    if (bsz <= sizeof(ctx->buf)) {
> >
> > +        memset(ctx->A, 0, sizeof(ctx->A));
> >
> > +
> >
> > +        ctx->num = 0;
> >
> > +        ctx->block_size = bsz;
> >
> > +        ctx->md_size = md_size;
> >
> > +        ctx->pad = pad;
> >
> > +
> >
> > +        return 1;
> >
> > +    }
> >
> > +
> >
> > +    return 0;
> >
> > +}
> >
> > +
> >
> > +
> >
> > +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
> >
> > +{
> >
> > +    const unsigned char *inp = _inp;
> >
> > +    size_t bsz = ctx->block_size;
> >
> > +    size_t num, rem;
> >
> > +
> >
> > +    if (len == 0)
> >
> > +        return 1;
> >
> > +
> >
> > +    if ((num = ctx->num) != 0) {      /* process intermediate buffer? */
> >
> > +        rem = bsz - num;
> >
> > +
> >
> > +        if (len < rem) {
> >
> > +            memcpy(ctx->buf + num, inp, len);
> >
> > +            ctx->num += len;
> >
> > +            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(ctx->buf + num, inp, rem);
> >
> > +        inp += rem, len -= rem;
> >
> > +        (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> >
> > +        ctx->num = 0;
> >
> > +        /* ctx->buf is processed, ctx->num is guaranteed to be zero
> > + */
> >
> > +    }
> >
> > +
> >
> > +    if (len >= bsz)
> >
> > +        rem = SHA3_absorb(ctx->A, inp, len, bsz);
> >
> > +    else
> >
> > +        rem = len;
> >
> > +
> >
> > +    if (rem) {
> >
> > +        memcpy(ctx->buf, inp + len - rem, rem);
> >
> > +        ctx->num = rem;
> >
> > +    }
> >
> > +
> >
> > +    return 1;
> >
> > +}
> >
> > +
> >
> > +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md)
> >
> > +{
> >
> > +    size_t bsz = ctx->block_size;
> >
> > +    size_t num = ctx->num;
> >
> > +
> >
> > +    if (ctx->md_size == 0)
> >
> > +        return 1;
> >
> > +
> >
> > +    /*
> >
> > +     * Pad the data with 10*1. Note that |num| can be |bsz - 1|
> >
> > +     * in which case both byte operations below are performed on
> >
> > +     * same byte...
> >
> > +     */
> >
> > +    memset(ctx->buf + num, 0, bsz - num);
> >
> > +    ctx->buf[num] = ctx->pad;
> >
> > +    ctx->buf[bsz - 1] |= 0x80;
> >
> > +
> >
> > +    (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> >
> > +
> >
> > +    SHA3_squeeze(ctx->A, md, ctx->md_size, bsz);
> >
> > +
> >
> > +    return 1;
> >
> > +}
> >
> > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > new file mode 100644
> > index 0000000000..b2a40ee044
> > --- /dev/null
> > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > @@ -0,0 +1,53 @@
> > +/** @file
> >
> > +  Encode realted functions from Xkcp.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +The eXtended Keccak Code Package (XKCP)
> >
> > +https://github.com/XKCP/XKCP
> >
> > +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 "xkcp.h"
> >
> > +
> >
> > +unsigned int left_encode(unsigned char * encbuf, size_t value)
> >
> > +{
> >
> > +    unsigned int n, i;
> >
> > +    size_t v;
> >
> > +
> >
> > +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> >
> > +        ; /* empty */
> >
> > +    if (n == 0)
> >
> > +        n = 1;
> >
> > +    for ( i = 1; i <= n; ++i )
> >
> > +    {
> >
> > +        encbuf[i] = (unsigned char)(value >> (8 * (n-i)));
> >
> > +    }
> >
> > +    encbuf[0] = (unsigned char)n;
> >
> > +    return n + 1;
> >
> > +}
> >
> > +
> >
> > +unsigned int right_encode(unsigned char * encbuf, size_t value)
> >
> > +{
> >
> > +    unsigned int n, i;
> >
> > +    size_t v;
> >
> > +
> >
> > +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> >
> > +        ; /* empty */
> >
> > +    if (n == 0)
> >
> > +        n = 1;
> >
> > +    for ( i = 1; i <= n; ++i )
> >
> > +    {
> >
> > +        encbuf[i-1] = (unsigned char)(value >> (8 * (n-i)));
> >
> > +    }
> >
> > +    encbuf[n] = (unsigned char)n;
> >
> > +    return n + 1;
> >
> > +}
> >
> > diff --git
> > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > new file mode 100644
> > index 0000000000..052ab3a0d6
> > --- /dev/null
> > +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > @@ -0,0 +1,152 @@
> > +/** @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;
> >
> > +  UINT16   OriginalParallelHashBlockNumber;
> >
> > +  UINT8    Output[64];
> >
> > +
> >
> > +  // Restore original PcdParallelHashBlockNumber.
> >
> > +  OriginalParallelHashBlockNumber = PcdGet16
> > + (PcdParallelHashBlockNumber);
> >
> > +
> >
> > +  //
> >
> > +  // Test #1 using sample1.
> >
> > +  //
> >
> > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample1ByteLen /
> > BlockSizeSample1);
> >
> > +  Status = ParallelHash256HashAll (
> >
> > +             InputSample1,
> >
> > +             InputSample1ByteLen,
> >
> > +             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.
> >
> > +  //
> >
> > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample2ByteLen /
> > BlockSizeSample2);
> >
> > +  Status = ParallelHash256HashAll (
> >
> > +             InputSample2,
> >
> > +             InputSample2ByteLen,
> >
> > +             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.
> >
> > +  //
> >
> > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample3ByteLen /
> > BlockSizeSample3);
> >
> > +  Status = ParallelHash256HashAll (
> >
> > +             InputSample3,
> >
> > +             InputSample3ByteLen,
> >
> > +             Output,
> >
> > +             OutputByteLen,
> >
> > +             CustomizationSample3,
> >
> > +             CustomSample3ByteLen
> >
> > +             );
> >
> > +  UT_ASSERT_TRUE (Status);
> >
> > +
> >
> > +  // Check the output with the expected output.
> >
> > +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3,
> OutputByteLen);
> >
> > +
> >
> > +  // Recover original PcdParallelHashBlockNumber.
> >
> > +  PcdSet16S (PcdParallelHashBlockNumber,
> > + OriginalParallelHashBlockNumber);
> >
> > +
> >
> > +  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.dec b/CryptoPkg/CryptoPkg.dec index
> > 5888941bab..3af55d9c10 100644
> > --- a/CryptoPkg/CryptoPkg.dec
> > +++ b/CryptoPkg/CryptoPkg.dec
> > @@ -4,7 +4,7 @@
> >  #  This Package provides cryptographic-related libraries for UEFI
> > security modules.
> >
> >  #  It also provides a test application to test libraries.
> >
> >  #
> >
> > -#  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
> >
> >  #
> >
> >  ##
> >
> > @@ -81,5 +81,12 @@
> >    # @ValidList 0x80000001 | 0x00000001, 0x00000002, 0x00000004,
> > 0x00000008, 0x00000010
> >
> >
> >
> gEfiCryptoPkgTokenSpaceGuid.PcdHashApiLibPolicy|0x00000002|UINT32|0x
> 00
> > 000001
> >
> >
> >
> > +[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic,
> PcdsDynamicEx]
> >
> > +  ## This PCD indicates the block number of parallel hash
> >
> > +  #  Based on the value set, parallel hash can chose the block
> >
> > +  #  number to calculate specific hash.<BR>
> >
> > +  #  The number can be set by platform team according to the core
> number.
> >
> > +
> >
> gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber|0x0100|UINT1
> 6|0
> > x00000003
> >
> > +
> >
> >  [UserExtensions.TianoCore."ExtraFiles"]
> >
> >    CryptoPkgExtra.uni
> >
> > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > index f4bc7c0d73..0b274b1257 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,33 @@ 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[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,
> >
> > +  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/Library/BaseCryptLib/SmmCryptLib.inf
> > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > index e6470d7a21..70159163d4 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,9 @@
> >    OpensslLib
> >
> >    IntrinsicLib
> >
> >    PrintLib
> >
> > +  MmServicesTableLib
> >
> > +  SynchronizationLib
> >
> > +  PcdLib
> >
> >
> >
> >  #
> >
> >  # Remove these [BuildOptions] after this library is cleaned up
> >
> > @@ -101,3 +108,6 @@
> >    GCC:*_CLANG35_*_CC_FLAGS = -std=c99
> >
> >    GCC:*_CLANG38_*_CC_FLAGS = -std=c99
> >
> >    GCC:*_CLANGPDB_*_CC_FLAGS = -std=c99
> > -Wno-error=incompatible-pointer- types
> >
> > +
> >
> > +[Pcd]
> >
> > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> >
> > diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h
> > b/CryptoPkg/Library/Include/CrtLibSupport.h
> > index d257dca8fa..35d9c62a0b 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
> >
> >
> >
> > @@ -21,6 +21,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> >  #define MAX_STRING_SIZE  0x1000
> >
> >
> >
> > +#define PARALLELHASH_CUSTOMIZATION "ParallelHash"
> >
> > +
> >
> >  //
> >
> >  // We already have "no-ui" in out Configure invocation.
> >
> >  // but the code still fails to compile.
> >
> > @@ -111,6 +113,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/Library/Include/sha3.h
> > b/CryptoPkg/Library/Include/sha3.h
> > new file mode 100644
> > index 0000000000..71b4c75548
> > --- /dev/null
> > +++ b/CryptoPkg/Library/Include/sha3.h
> > @@ -0,0 +1,32 @@
> > +/** @file
> >
> > +  SHA3 realted functions from OpenSSL.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +Copyright 2017-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 <CrtLibSupport.h>
> >
> > +
> >
> > +#define KECCAK1600_WIDTH 1600
> >
> > +
> >
> > +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;
> >
> > +
> >
> > +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t
> > +md_size);
> >
> > +
> >
> > +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
> >
> > +
> >
> > +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md);
> >
> > diff --git a/CryptoPkg/Library/Include/xkcp.h
> > b/CryptoPkg/Library/Include/xkcp.h
> > new file mode 100644
> > index 0000000000..b328d672e4
> > --- /dev/null
> > +++ b/CryptoPkg/Library/Include/xkcp.h
> > @@ -0,0 +1,23 @@
> > +/** @file
> >
> > +  Encode realted functions from Xkcp.
> >
> > +
> >
> > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> > +SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> > +
> >
> > +The eXtended Keccak Code Package (XKCP)
> >
> > +https://github.com/XKCP/XKCP
> >
> > +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 <CrtLibSupport.h>
> >
> > +
> >
> > +unsigned int left_encode(unsigned char * encbuf, size_t value);
> >
> > +
> >
> > +unsigned int right_encode(unsigned char * encbuf, size_t value);
> >
> > diff --git
> > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > index a6b3482742..0bffd687c2 100644
> > --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > @@ -1,7 +1,7 @@
> >  /** @file
> >
> >    Application for Cryptographic Primitives Validation.
> >
> >
> >
> > -Copyright (c) 2009 - 2016, Intel Corporation. All rights
> > reserved.<BR>
> >
> > +Copyright (c) 2009 - 2022, Intel Corporation. All rights
> > +reserved.<BR>
> >
> >  SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >
> >
> >  **/
> >
> > @@ -19,6 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > #include <Library/BaseLib.h>
> >
> >  #include <Library/BaseMemoryLib.h>
> >
> >  #include <Library/MemoryAllocationLib.h>
> >
> > +#include <Library/PcdLib.h>
> >
> >  // #include <UnitTestTypes.h>
> >
> >  #include <Library/UnitTestLib.h>
> >
> >  // #include <Library/UnitTestAssertLib.h>
> >
> > diff --git
> > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > f
> > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > f
> > index 00c8692650..61a59d6a47 100644
> > ---
> > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > f
> > +++
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHos
> > +++ t.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,8 @@
> >    DebugLib
> >
> >    BaseCryptLib
> >
> >    UnitTestLib
> >
> > +  PcdLib
> >
> > +
> >
> > +[Pcd]
> >
> > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> >
> > +
> >
> > diff --git
> > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > nf
> > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > nf
> > index ca789aa6ad..682f25a754 100644
> > ---
> > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > nf
> > +++
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShe
> > +++ ll.inf
> > @@ -2,6 +2,7 @@
> >  # BaseCryptLib UnitTest built for execution in UEFI Shell.
> >
> >  #
> >
> >  # Copyright (c) Microsoft Corporation.<BR>
> >
> > +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> >
> >  # SPDX-License-Identifier: BSD-2-Clause-Patent
> >
> >  ##
> >
> >
> >
> > @@ -36,6 +37,7 @@
> >    Pkcs7EkuTests.c
> >
> >    OaepEncryptTests.c
> >
> >    RsaPssTests.c
> >
> > +  ParallelhashTests.c
> >
> >
> >
> >  [Packages]
> >
> >    MdePkg/MdePkg.dec
> >
> > @@ -48,3 +50,7 @@
> >    UnitTestLib
> >
> >    PrintLib
> >
> >    BaseCryptLib
> >
> > +  PcdLib
> >
> > +
> >
> > +[Pcd]
> >
> > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> >
> > --
> > 2.26.2.windows.1


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

* Re: [PATCH v1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
  2022-02-16  7:43   ` Li, Zhihao
@ 2022-02-16  7:51     ` Yao, Jiewen
  2022-02-16  8:23       ` Li, Zhihao
  2022-02-17  5:28       ` Li, Zhihao
  0 siblings, 2 replies; 6+ messages in thread
From: Yao, Jiewen @ 2022-02-16  7:51 UTC (permalink / raw)
  To: Li, Zhihao, devel@edk2.groups.io
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Fu, Siyuan

But I don’t understand why we need sha3.h and xkcp.h at all.


> -----Original Message-----
> From: Li, Zhihao <zhihao.li@intel.com>
> Sent: Wednesday, February 16, 2022 3:43 PM
> 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: [PATCH v1] CryptoPkg: Add new hash algorithm
> ParallelHash256HashAll in BaseCryptLib.
> 
> With your comment, we plan do some modification for parallelhash.
> 1. Plan to add  a parameter (BlockSize) on  ParallelHash256HashAll  function to
> replace PcdParallelHashBlockNumber.
> 2. Plan to move sha3.h and xkcp.h to CryptoPkg\Library\BaseCryptLib\Hash
> folder.
> 
> 
> > -----Original Message-----
> > From: Yao, Jiewen <jiewen.yao@intel.com>
> > Sent: Tuesday, February 15, 2022 2:09 PM
> > To: Li, Zhihao <zhihao.li@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: [PATCH v1] CryptoPkg: Add new hash algorithm
> > ParallelHash256HashAll in BaseCryptLib.
> >
> > Thanks for the update.
> >
> > Feedback below:
> >
> > 1) How block size is determined for below API?
> >
> > BOOLEAN
> > EFIAPI
> > ParallelHash256HashAll (
> >   IN CONST VOID            *Input,
> >   IN       UINTN           InputByteLen,
> >   OUT      VOID            *Output,
> >   IN       UINTN           OutputByteLen,
> >   IN CONST VOID            *Customization,
> >   IN       UINTN           CustomByteLen
> >   );
> >
> > Is that determined by PcdParallelHashBlockNumber ?
> >
> > I don’t think it is good idea to let a crypto library determine a platform PCD.
> > For example, how do you support binary crypto module ?
> Plan to add  a parameter (BlockSize) to replace PcdParallelHashBlockNumber.
> >
> > 2) Why we need "sha3.h" and "xkcp.h" ?
> > These are openssl specific structure. It shall not be put to EDKII file header.
> >
> > CryptoPkg\Library\Include shall only contain generic dependency header.
> Plan to move sha3.h and xkcp.h to CryptoPkg\Library\BaseCryptLib\Hash folder.
> >
> >
> >
> >
> > Thank you
> > Yao, Jiewen
> >
> > > -----Original Message-----
> > > From: Li, Zhihao <zhihao.li@intel.com>
> > > Sent: Friday, February 11, 2022 5:05 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: [PATCH v1] 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.
> > >
> > > 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>
> > >
> > > Signed-off-by: Zhihao Li <zhihao.li@intel.com>
> > > ---
> > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                   | 313
> > > ++++++++++++++++++++
> > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c                | 275
> > > +++++++++++++++++
> > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                        | 102
> > +++++++
> > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                        |  53 ++++
> > >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c       |
> > 152
> > > ++++++++++
> > >  CryptoPkg/CryptoPkg.dec                                                |   9 +-
> > >  CryptoPkg/Include/Library/BaseCryptLib.h                               |  29 +-
> > >  CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                         |  12 +-
> > >  CryptoPkg/Library/Include/CrtLibSupport.h                              |   5 +-
> > >  CryptoPkg/Library/Include/sha3.h                                       |  32 ++
> > >  CryptoPkg/Library/Include/xkcp.h                                       |  23 ++
> > >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h        |   3
> > +-
> > >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> > |   7 +
> > >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf |
> > 6 +
> > >  14 files changed, 1016 insertions(+), 5 deletions(-)
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > > new file mode 100644
> > > index 0000000000..5efced3f46
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > > @@ -0,0 +1,313 @@
> > > +/** @file
> > >
> > > +  cSHAKE-256 Digest Wrapper Implementations.
> > >
> > > +
> > >
> > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +**/
> > >
> > > +
> > >
> > > +#include "InternalCryptLib.h"
> > >
> > > +#include "sha3.h"
> > >
> > > +#include "xkcp.h"
> > >
> > > +
> > >
> > > +#define  CSHAKE256_SECURITY_STRENGTH    256
> > >
> > > +#define  CSHAKE256_RATE_IN_BYTES        136
> > >
> > > +
> > >
> > > +const CHAR8 mZeroPadding[CSHAKE256_RATE_IN_BYTES] = {0};
> > >
> > > +
> > >
> > > +UINTN
> > >
> > > +EFIAPI
> > >
> > > +LeftEncode (
> > >
> > > +  OUT UINT8     *Encbuf,
> > >
> > > +  IN  UINTN     Value
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  return left_encode (Encbuf, Value);
> > >
> > > +}
> > >
> > > +
> > >
> > > +UINTN
> > >
> > > +EFIAPI
> > >
> > > +RightEncode (
> > >
> > > +  OUT UINT8     *Encbuf,
> > >
> > > +  IN  UINTN     Value
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  return right_encode (Encbuf, Value);
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Retrieves the size, in bytes, of the context buffer required for
> > > + cSHAKE-256
> > > hash operations.
> > >
> > > +
> > >
> > > +  @return  The size, in bytes, of the context buffer required for
> > > + cSHAKE-256
> > > hash operations.
> > >
> > > +
> > >
> > > +**/
> > >
> > > +UINTN
> > >
> > > +EFIAPI
> > >
> > > +CShake256GetContextSize (
> > >
> > > +  VOID
> > >
> > > +  )
> > >
> > > +{
> > >
> > > +  return (UINTN) (sizeof (KECCAK1600_CTX));
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  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;
> > >
> > > +  unsigned char EncBuf[sizeof(size_t)+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.
> > >
> > > +    //
> > >
> > > +    return (BOOLEAN) init (
> > >
> > > +                      (KECCAK1600_CTX *) CShake256Context,
> > >
> > > +                      '\x1f',
> > >
> > > +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH
> > > + * 2) / 8,
> > >
> > > +                      OutputLen
> > >
> > > +                      );
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  Status = (BOOLEAN) init (
> > >
> > > +                      (KECCAK1600_CTX *) CShake256Context,
> > >
> > > +                      '\x04',
> > >
> > > +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH
> > > + * 2) / 8,
> > >
> > > +                      OutputLen
> > >
> > > +                      );
> > >
> > > +  if (!Status) {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  AbsorbLen = 0;
> > >
> > > +  //
> > >
> > > +  // Absorb Absorb bytepad(.., rate).
> > >
> > > +  //
> > >
> > > +  EncLen = left_encode (EncBuf, CSHAKE256_RATE_IN_BYTES);
> > >
> > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > + CShake256Context,
> > > EncBuf, EncLen);
> > >
> > > +  if (!Status) {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +  AbsorbLen += EncLen;
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // Absorb encode_string(N).
> > >
> > > +  //
> > >
> > > +  EncLen = left_encode (EncBuf, NameLen * 8);
> > >
> > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > + CShake256Context,
> > > EncBuf, EncLen);
> > >
> > > +  if (!Status) {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +  AbsorbLen += EncLen;
> > >
> > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > + CShake256Context,
> > > Name, NameLen);
> > >
> > > +  if (!Status) {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +  AbsorbLen += NameLen;
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // Absorb encode_string(S).
> > >
> > > +  //
> > >
> > > +  EncLen = left_encode (EncBuf, CustomizationLen * 8);
> > >
> > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > + CShake256Context,
> > > EncBuf, EncLen);
> > >
> > > +  if (!Status) {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +  AbsorbLen += EncLen;
> > >
> > > +  Status = (BOOLEAN) sha3_update ((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) sha3_update ((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)(sha3_update ((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) (sha3_final ((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 0000000000..3eaa7c2ceb
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> > > @@ -0,0 +1,275 @@
> > > +/** @file
> > >
> > > +  ParallelHash Implementation.
> > >
> > > +
> > >
> > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +**/
> > >
> > > +
> > >
> > > +#include "InternalCryptLib.h"
> > >
> > > +#include <Library\PcdLib.h>
> > >
> > > +#include <Library\SynchronizationLib.h>
> > >
> > > +#include <Library\MmServicesTableLib.h>
> > >
> > > +
> > >
> > > +
> > >
> > > +UINT16        mBlockNum;
> > >
> > > +UINTN        mBlockSize;
> > >
> > > +UINTN        mLastBlockSize;
> > >
> > > +UINT8        *mInput;
> > >
> > > +UINTN        mBlockResultSize;
> > >
> > > +UINT8        *mBlockHashResult;
> > >
> > > +BOOLEAN      *mBlockIsCompleted;
> > >
> > > +SPIN_LOCK    *mSpinLockList;
> > >
> > > +
> > >
> > > +UINTN LeftEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> > >
> > > +UINTN RightEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> > >
> > > +
> > >
> > > +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
> > >
> > > +  );
> > >
> > > +
> > >
> > > +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]);
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +}
> > >
> > > +
> > >
> > > +/**
> > >
> > > +  Parallel hash function ParallelHash256, as defined in NIST's
> > > + Special Publication
> > > 800-185,
> > >
> > > +  published December 2016.
> > >
> > > +
> > >
> > > +  @param  Input[in]            Pointer to the input message (X).
> > >
> > > +  @param  InputByteLen[in]     The number(>0) of input bytes provided for
> > the
> > > input data.
> > >
> > > +  @param  Output[out]          Pointer to the output buffer.
> > >
> > > +  @param  OutputByteLen[in]    The desired number of output bytes (L).
> > >
> > > +  @param  Customization[in]    Pointer to the customization string (S).
> > >
> > > +  @param  CustomByteLen[in]    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,
> > >
> > > +  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;
> > >
> > > +  EFI_STATUS   Status;
> > >
> > > +  UINTN        StartedApNum;
> > >
> > > +  BOOLEAN      AllCompleted;
> > >
> > > +  UINTN        Offset;
> > >
> > > +  BOOLEAN      ReturnValue;
> > >
> > > +
> > >
> > > +  if (InputByteLen == 0 || OutputByteLen == 0) {
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if (Input == NULL || Output == NULL){
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  if (CustomByteLen != 0 && Customization == NULL){
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // Get Block number n.
> > >
> > > +  //
> > >
> > > +  mBlockNum = PcdGet16 (PcdParallelHashBlockNumber);
> > >
> > > +
> > >
> > > +  if (mBlockNum < 1 || InputByteLen < mBlockNum - 1){
> > >
> > > +    return FALSE;
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // Set hash result size of each block in bytes.
> > >
> > > +  //
> > >
> > > +  mBlockResultSize = OutputByteLen;
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // calculate the block byte length B.
> > >
> > > +  //
> > >
> > > +  mBlockSize = InputByteLen % mBlockNum == 0 ? InputByteLen /
> > mBlockNum :
> > > InputByteLen / (mBlockNum - 1);
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // 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 = 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.
> > >
> > > +  //
> > >
> > > +  StartedApNum = 0;
> > >
> > > +  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
> > >
> > > +    if (Index != gMmst->CurrentlyExecutingCpu) {
> > >
> > > +      Status = gMmst->MmStartupThisAp (ParallelHashApExecute, Index,
> > > + NULL);
> > >
> > > +      if (!EFI_ERROR (Status)) {
> > >
> > > +        StartedApNum++;
> > >
> > > +      }
> > >
> > > +    }
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // 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 (mSpinLockList);
> > >
> > > +  }
> > >
> > > +  if (mBlockIsCompleted != NULL){
> > >
> > > +    FreePool (mBlockIsCompleted);
> > >
> > > +  }
> > >
> > > +
> > >
> > > +  return ReturnValue;
> > >
> > > +}
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > > new file mode 100644
> > > index 0000000000..b170c463de
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > > @@ -0,0 +1,102 @@
> > > +/** @file
> > >
> > > +  SHA3 realted functions from OpenSSL.
> > >
> > > +
> > >
> > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +Copyright 2017-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 "sha3.h"
> > >
> > > +
> > >
> > > +size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t
> > > +len,
> > >
> > > +                   size_t r);
> > >
> > > +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len,
> > > +size_t r);
> > >
> > > +
> > >
> > > +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t
> > > +md_size)
> > >
> > > +{
> > >
> > > +    if (bsz <= sizeof(ctx->buf)) {
> > >
> > > +        memset(ctx->A, 0, sizeof(ctx->A));
> > >
> > > +
> > >
> > > +        ctx->num = 0;
> > >
> > > +        ctx->block_size = bsz;
> > >
> > > +        ctx->md_size = md_size;
> > >
> > > +        ctx->pad = pad;
> > >
> > > +
> > >
> > > +        return 1;
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    return 0;
> > >
> > > +}
> > >
> > > +
> > >
> > > +
> > >
> > > +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
> > >
> > > +{
> > >
> > > +    const unsigned char *inp = _inp;
> > >
> > > +    size_t bsz = ctx->block_size;
> > >
> > > +    size_t num, rem;
> > >
> > > +
> > >
> > > +    if (len == 0)
> > >
> > > +        return 1;
> > >
> > > +
> > >
> > > +    if ((num = ctx->num) != 0) {      /* process intermediate buffer? */
> > >
> > > +        rem = bsz - num;
> > >
> > > +
> > >
> > > +        if (len < rem) {
> > >
> > > +            memcpy(ctx->buf + num, inp, len);
> > >
> > > +            ctx->num += len;
> > >
> > > +            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(ctx->buf + num, inp, rem);
> > >
> > > +        inp += rem, len -= rem;
> > >
> > > +        (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> > >
> > > +        ctx->num = 0;
> > >
> > > +        /* ctx->buf is processed, ctx->num is guaranteed to be zero
> > > + */
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    if (len >= bsz)
> > >
> > > +        rem = SHA3_absorb(ctx->A, inp, len, bsz);
> > >
> > > +    else
> > >
> > > +        rem = len;
> > >
> > > +
> > >
> > > +    if (rem) {
> > >
> > > +        memcpy(ctx->buf, inp + len - rem, rem);
> > >
> > > +        ctx->num = rem;
> > >
> > > +    }
> > >
> > > +
> > >
> > > +    return 1;
> > >
> > > +}
> > >
> > > +
> > >
> > > +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md)
> > >
> > > +{
> > >
> > > +    size_t bsz = ctx->block_size;
> > >
> > > +    size_t num = ctx->num;
> > >
> > > +
> > >
> > > +    if (ctx->md_size == 0)
> > >
> > > +        return 1;
> > >
> > > +
> > >
> > > +    /*
> > >
> > > +     * Pad the data with 10*1. Note that |num| can be |bsz - 1|
> > >
> > > +     * in which case both byte operations below are performed on
> > >
> > > +     * same byte...
> > >
> > > +     */
> > >
> > > +    memset(ctx->buf + num, 0, bsz - num);
> > >
> > > +    ctx->buf[num] = ctx->pad;
> > >
> > > +    ctx->buf[bsz - 1] |= 0x80;
> > >
> > > +
> > >
> > > +    (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> > >
> > > +
> > >
> > > +    SHA3_squeeze(ctx->A, md, ctx->md_size, bsz);
> > >
> > > +
> > >
> > > +    return 1;
> > >
> > > +}
> > >
> > > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > > new file mode 100644
> > > index 0000000000..b2a40ee044
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > > @@ -0,0 +1,53 @@
> > > +/** @file
> > >
> > > +  Encode realted functions from Xkcp.
> > >
> > > +
> > >
> > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +The eXtended Keccak Code Package (XKCP)
> > >
> > > +https://github.com/XKCP/XKCP
> > >
> > > +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 "xkcp.h"
> > >
> > > +
> > >
> > > +unsigned int left_encode(unsigned char * encbuf, size_t value)
> > >
> > > +{
> > >
> > > +    unsigned int n, i;
> > >
> > > +    size_t v;
> > >
> > > +
> > >
> > > +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> > >
> > > +        ; /* empty */
> > >
> > > +    if (n == 0)
> > >
> > > +        n = 1;
> > >
> > > +    for ( i = 1; i <= n; ++i )
> > >
> > > +    {
> > >
> > > +        encbuf[i] = (unsigned char)(value >> (8 * (n-i)));
> > >
> > > +    }
> > >
> > > +    encbuf[0] = (unsigned char)n;
> > >
> > > +    return n + 1;
> > >
> > > +}
> > >
> > > +
> > >
> > > +unsigned int right_encode(unsigned char * encbuf, size_t value)
> > >
> > > +{
> > >
> > > +    unsigned int n, i;
> > >
> > > +    size_t v;
> > >
> > > +
> > >
> > > +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> > >
> > > +        ; /* empty */
> > >
> > > +    if (n == 0)
> > >
> > > +        n = 1;
> > >
> > > +    for ( i = 1; i <= n; ++i )
> > >
> > > +    {
> > >
> > > +        encbuf[i-1] = (unsigned char)(value >> (8 * (n-i)));
> > >
> > > +    }
> > >
> > > +    encbuf[n] = (unsigned char)n;
> > >
> > > +    return n + 1;
> > >
> > > +}
> > >
> > > diff --git
> > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > > new file mode 100644
> > > index 0000000000..052ab3a0d6
> > > --- /dev/null
> > > +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > > @@ -0,0 +1,152 @@
> > > +/** @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;
> > >
> > > +  UINT16   OriginalParallelHashBlockNumber;
> > >
> > > +  UINT8    Output[64];
> > >
> > > +
> > >
> > > +  // Restore original PcdParallelHashBlockNumber.
> > >
> > > +  OriginalParallelHashBlockNumber = PcdGet16
> > > + (PcdParallelHashBlockNumber);
> > >
> > > +
> > >
> > > +  //
> > >
> > > +  // Test #1 using sample1.
> > >
> > > +  //
> > >
> > > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample1ByteLen /
> > > BlockSizeSample1);
> > >
> > > +  Status = ParallelHash256HashAll (
> > >
> > > +             InputSample1,
> > >
> > > +             InputSample1ByteLen,
> > >
> > > +             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.
> > >
> > > +  //
> > >
> > > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample2ByteLen /
> > > BlockSizeSample2);
> > >
> > > +  Status = ParallelHash256HashAll (
> > >
> > > +             InputSample2,
> > >
> > > +             InputSample2ByteLen,
> > >
> > > +             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.
> > >
> > > +  //
> > >
> > > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample3ByteLen /
> > > BlockSizeSample3);
> > >
> > > +  Status = ParallelHash256HashAll (
> > >
> > > +             InputSample3,
> > >
> > > +             InputSample3ByteLen,
> > >
> > > +             Output,
> > >
> > > +             OutputByteLen,
> > >
> > > +             CustomizationSample3,
> > >
> > > +             CustomSample3ByteLen
> > >
> > > +             );
> > >
> > > +  UT_ASSERT_TRUE (Status);
> > >
> > > +
> > >
> > > +  // Check the output with the expected output.
> > >
> > > +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3,
> > OutputByteLen);
> > >
> > > +
> > >
> > > +  // Recover original PcdParallelHashBlockNumber.
> > >
> > > +  PcdSet16S (PcdParallelHashBlockNumber,
> > > + OriginalParallelHashBlockNumber);
> > >
> > > +
> > >
> > > +  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.dec b/CryptoPkg/CryptoPkg.dec index
> > > 5888941bab..3af55d9c10 100644
> > > --- a/CryptoPkg/CryptoPkg.dec
> > > +++ b/CryptoPkg/CryptoPkg.dec
> > > @@ -4,7 +4,7 @@
> > >  #  This Package provides cryptographic-related libraries for UEFI
> > > security modules.
> > >
> > >  #  It also provides a test application to test libraries.
> > >
> > >  #
> > >
> > > -#  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
> > >
> > >  #
> > >
> > >  ##
> > >
> > > @@ -81,5 +81,12 @@
> > >    # @ValidList 0x80000001 | 0x00000001, 0x00000002, 0x00000004,
> > > 0x00000008, 0x00000010
> > >
> > >
> > >
> > gEfiCryptoPkgTokenSpaceGuid.PcdHashApiLibPolicy|0x00000002|UINT32|0x
> > 00
> > > 000001
> > >
> > >
> > >
> > > +[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic,
> > PcdsDynamicEx]
> > >
> > > +  ## This PCD indicates the block number of parallel hash
> > >
> > > +  #  Based on the value set, parallel hash can chose the block
> > >
> > > +  #  number to calculate specific hash.<BR>
> > >
> > > +  #  The number can be set by platform team according to the core
> > number.
> > >
> > > +
> > >
> > gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber|0x0100|UINT1
> > 6|0
> > > x00000003
> > >
> > > +
> > >
> > >  [UserExtensions.TianoCore."ExtraFiles"]
> > >
> > >    CryptoPkgExtra.uni
> > >
> > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > index f4bc7c0d73..0b274b1257 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,33 @@ 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[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,
> > >
> > > +  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/Library/BaseCryptLib/SmmCryptLib.inf
> > > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > index e6470d7a21..70159163d4 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,9 @@
> > >    OpensslLib
> > >
> > >    IntrinsicLib
> > >
> > >    PrintLib
> > >
> > > +  MmServicesTableLib
> > >
> > > +  SynchronizationLib
> > >
> > > +  PcdLib
> > >
> > >
> > >
> > >  #
> > >
> > >  # Remove these [BuildOptions] after this library is cleaned up
> > >
> > > @@ -101,3 +108,6 @@
> > >    GCC:*_CLANG35_*_CC_FLAGS = -std=c99
> > >
> > >    GCC:*_CLANG38_*_CC_FLAGS = -std=c99
> > >
> > >    GCC:*_CLANGPDB_*_CC_FLAGS = -std=c99
> > > -Wno-error=incompatible-pointer- types
> > >
> > > +
> > >
> > > +[Pcd]
> > >
> > > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> > >
> > > diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h
> > > b/CryptoPkg/Library/Include/CrtLibSupport.h
> > > index d257dca8fa..35d9c62a0b 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
> > >
> > >
> > >
> > > @@ -21,6 +21,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >
> > >  #define MAX_STRING_SIZE  0x1000
> > >
> > >
> > >
> > > +#define PARALLELHASH_CUSTOMIZATION "ParallelHash"
> > >
> > > +
> > >
> > >  //
> > >
> > >  // We already have "no-ui" in out Configure invocation.
> > >
> > >  // but the code still fails to compile.
> > >
> > > @@ -111,6 +113,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/Library/Include/sha3.h
> > > b/CryptoPkg/Library/Include/sha3.h
> > > new file mode 100644
> > > index 0000000000..71b4c75548
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/Include/sha3.h
> > > @@ -0,0 +1,32 @@
> > > +/** @file
> > >
> > > +  SHA3 realted functions from OpenSSL.
> > >
> > > +
> > >
> > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +Copyright 2017-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 <CrtLibSupport.h>
> > >
> > > +
> > >
> > > +#define KECCAK1600_WIDTH 1600
> > >
> > > +
> > >
> > > +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;
> > >
> > > +
> > >
> > > +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t
> > > +md_size);
> > >
> > > +
> > >
> > > +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
> > >
> > > +
> > >
> > > +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md);
> > >
> > > diff --git a/CryptoPkg/Library/Include/xkcp.h
> > > b/CryptoPkg/Library/Include/xkcp.h
> > > new file mode 100644
> > > index 0000000000..b328d672e4
> > > --- /dev/null
> > > +++ b/CryptoPkg/Library/Include/xkcp.h
> > > @@ -0,0 +1,23 @@
> > > +/** @file
> > >
> > > +  Encode realted functions from Xkcp.
> > >
> > > +
> > >
> > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > >
> > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > > +
> > >
> > > +The eXtended Keccak Code Package (XKCP)
> > >
> > > +https://github.com/XKCP/XKCP
> > >
> > > +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 <CrtLibSupport.h>
> > >
> > > +
> > >
> > > +unsigned int left_encode(unsigned char * encbuf, size_t value);
> > >
> > > +
> > >
> > > +unsigned int right_encode(unsigned char * encbuf, size_t value);
> > >
> > > diff --git
> > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > index a6b3482742..0bffd687c2 100644
> > > --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > @@ -1,7 +1,7 @@
> > >  /** @file
> > >
> > >    Application for Cryptographic Primitives Validation.
> > >
> > >
> > >
> > > -Copyright (c) 2009 - 2016, Intel Corporation. All rights
> > > reserved.<BR>
> > >
> > > +Copyright (c) 2009 - 2022, Intel Corporation. All rights
> > > +reserved.<BR>
> > >
> > >  SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >
> > >
> > >  **/
> > >
> > > @@ -19,6 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > #include <Library/BaseLib.h>
> > >
> > >  #include <Library/BaseMemoryLib.h>
> > >
> > >  #include <Library/MemoryAllocationLib.h>
> > >
> > > +#include <Library/PcdLib.h>
> > >
> > >  // #include <UnitTestTypes.h>
> > >
> > >  #include <Library/UnitTestLib.h>
> > >
> > >  // #include <Library/UnitTestAssertLib.h>
> > >
> > > diff --git
> > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > > f
> > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > > f
> > > index 00c8692650..61a59d6a47 100644
> > > ---
> > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > > f
> > > +++
> > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHos
> > > +++ t.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,8 @@
> > >    DebugLib
> > >
> > >    BaseCryptLib
> > >
> > >    UnitTestLib
> > >
> > > +  PcdLib
> > >
> > > +
> > >
> > > +[Pcd]
> > >
> > > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> > >
> > > +
> > >
> > > diff --git
> > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > > nf
> > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > > nf
> > > index ca789aa6ad..682f25a754 100644
> > > ---
> > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > > nf
> > > +++
> > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShe
> > > +++ ll.inf
> > > @@ -2,6 +2,7 @@
> > >  # BaseCryptLib UnitTest built for execution in UEFI Shell.
> > >
> > >  #
> > >
> > >  # Copyright (c) Microsoft Corporation.<BR>
> > >
> > > +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > >
> > >  # SPDX-License-Identifier: BSD-2-Clause-Patent
> > >
> > >  ##
> > >
> > >
> > >
> > > @@ -36,6 +37,7 @@
> > >    Pkcs7EkuTests.c
> > >
> > >    OaepEncryptTests.c
> > >
> > >    RsaPssTests.c
> > >
> > > +  ParallelhashTests.c
> > >
> > >
> > >
> > >  [Packages]
> > >
> > >    MdePkg/MdePkg.dec
> > >
> > > @@ -48,3 +50,7 @@
> > >    UnitTestLib
> > >
> > >    PrintLib
> > >
> > >    BaseCryptLib
> > >
> > > +  PcdLib
> > >
> > > +
> > >
> > > +[Pcd]
> > >
> > > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> > >
> > > --
> > > 2.26.2.windows.1


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

* Re: [PATCH v1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
  2022-02-16  7:51     ` Yao, Jiewen
@ 2022-02-16  8:23       ` Li, Zhihao
  2022-02-17  5:28       ` Li, Zhihao
  1 sibling, 0 replies; 6+ messages in thread
From: Li, Zhihao @ 2022-02-16  8:23 UTC (permalink / raw)
  To: Yao, Jiewen, devel@edk2.groups.io
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Fu, Siyuan

In CT 46 review result, it require that the code in openssl_sha3 and in xkcp need to be made proper attribution.
We separated their implementation into CryptSha3.c and CryptXkcp.c, separated their header files into sha3.h and xkcp.h.

Now we plan to delete these header files and put the declaration and structure define into CryptCshake256.c if head file not within the scope of CT46 suggestion.

> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: Wednesday, February 16, 2022 3:52 PM
> To: Li, Zhihao <zhihao.li@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: [PATCH v1] CryptoPkg: Add new hash algorithm
> ParallelHash256HashAll in BaseCryptLib.
> 
> But I don’t understand why we need sha3.h and xkcp.h at all.
> 
> 
> > -----Original Message-----
> > From: Li, Zhihao <zhihao.li@intel.com>
> > Sent: Wednesday, February 16, 2022 3:43 PM
> > 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: [PATCH v1] CryptoPkg: Add new hash algorithm
> > ParallelHash256HashAll in BaseCryptLib.
> >
> > With your comment, we plan do some modification for parallelhash.
> > 1. Plan to add  a parameter (BlockSize) on  ParallelHash256HashAll  function
> to
> > replace PcdParallelHashBlockNumber.
> > 2. Plan to move sha3.h and xkcp.h to CryptoPkg\Library\BaseCryptLib\Hash
> > folder.
> >
> >
> > > -----Original Message-----
> > > From: Yao, Jiewen <jiewen.yao@intel.com>
> > > Sent: Tuesday, February 15, 2022 2:09 PM
> > > To: Li, Zhihao <zhihao.li@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: [PATCH v1] CryptoPkg: Add new hash algorithm
> > > ParallelHash256HashAll in BaseCryptLib.
> > >
> > > Thanks for the update.
> > >
> > > Feedback below:
> > >
> > > 1) How block size is determined for below API?
> > >
> > > BOOLEAN
> > > EFIAPI
> > > ParallelHash256HashAll (
> > >   IN CONST VOID            *Input,
> > >   IN       UINTN           InputByteLen,
> > >   OUT      VOID            *Output,
> > >   IN       UINTN           OutputByteLen,
> > >   IN CONST VOID            *Customization,
> > >   IN       UINTN           CustomByteLen
> > >   );
> > >
> > > Is that determined by PcdParallelHashBlockNumber ?
> > >
> > > I don’t think it is good idea to let a crypto library determine a platform
> PCD.
> > > For example, how do you support binary crypto module ?
> > Plan to add  a parameter (BlockSize) to replace
> PcdParallelHashBlockNumber.
> > >
> > > 2) Why we need "sha3.h" and "xkcp.h" ?
> > > These are openssl specific structure. It shall not be put to EDKII file
> header.
> > >
> > > CryptoPkg\Library\Include shall only contain generic dependency header.
> > Plan to move sha3.h and xkcp.h to CryptoPkg\Library\BaseCryptLib\Hash
> folder.
> > >
> > >
> > >
> > >
> > > Thank you
> > > Yao, Jiewen
> > >
> > > > -----Original Message-----
> > > > From: Li, Zhihao <zhihao.li@intel.com>
> > > > Sent: Friday, February 11, 2022 5:05 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: [PATCH v1] 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.
> > > >
> > > > 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>
> > > >
> > > > Signed-off-by: Zhihao Li <zhihao.li@intel.com>
> > > > ---
> > > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                   | 313
> > > > ++++++++++++++++++++
> > > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c                | 275
> > > > +++++++++++++++++
> > > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                        | 102
> > > +++++++
> > > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                        |  53
> ++++
> > > >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c       |
> > > 152
> > > > ++++++++++
> > > >  CryptoPkg/CryptoPkg.dec                                                |   9 +-
> > > >  CryptoPkg/Include/Library/BaseCryptLib.h                               |  29 +-
> > > >  CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                         |  12 +-
> > > >  CryptoPkg/Library/Include/CrtLibSupport.h                              |   5 +-
> > > >  CryptoPkg/Library/Include/sha3.h                                       |  32 ++
> > > >  CryptoPkg/Library/Include/xkcp.h                                       |  23 ++
> > > >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> |   3
> > > +-
> > > >
> CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> > > |   7 +
> > > >
> CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf |
> > > 6 +
> > > >  14 files changed, 1016 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > > > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > > > new file mode 100644
> > > > index 0000000000..5efced3f46
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > > > @@ -0,0 +1,313 @@
> > > > +/** @file
> > > >
> > > > +  cSHAKE-256 Digest Wrapper Implementations.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +
> > > >
> > > > +#include "InternalCryptLib.h"
> > > >
> > > > +#include "sha3.h"
> > > >
> > > > +#include "xkcp.h"
> > > >
> > > > +
> > > >
> > > > +#define  CSHAKE256_SECURITY_STRENGTH    256
> > > >
> > > > +#define  CSHAKE256_RATE_IN_BYTES        136
> > > >
> > > > +
> > > >
> > > > +const CHAR8 mZeroPadding[CSHAKE256_RATE_IN_BYTES] = {0};
> > > >
> > > > +
> > > >
> > > > +UINTN
> > > >
> > > > +EFIAPI
> > > >
> > > > +LeftEncode (
> > > >
> > > > +  OUT UINT8     *Encbuf,
> > > >
> > > > +  IN  UINTN     Value
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  return left_encode (Encbuf, Value);
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +UINTN
> > > >
> > > > +EFIAPI
> > > >
> > > > +RightEncode (
> > > >
> > > > +  OUT UINT8     *Encbuf,
> > > >
> > > > +  IN  UINTN     Value
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  return right_encode (Encbuf, Value);
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Retrieves the size, in bytes, of the context buffer required for
> > > > + cSHAKE-256
> > > > hash operations.
> > > >
> > > > +
> > > >
> > > > +  @return  The size, in bytes, of the context buffer required for
> > > > + cSHAKE-256
> > > > hash operations.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +UINTN
> > > >
> > > > +EFIAPI
> > > >
> > > > +CShake256GetContextSize (
> > > >
> > > > +  VOID
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  return (UINTN) (sizeof (KECCAK1600_CTX));
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  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;
> > > >
> > > > +  unsigned char EncBuf[sizeof(size_t)+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.
> > > >
> > > > +    //
> > > >
> > > > +    return (BOOLEAN) init (
> > > >
> > > > +                      (KECCAK1600_CTX *) CShake256Context,
> > > >
> > > > +                      '\x1f',
> > > >
> > > > +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH
> > > > + * 2) / 8,
> > > >
> > > > +                      OutputLen
> > > >
> > > > +                      );
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  Status = (BOOLEAN) init (
> > > >
> > > > +                      (KECCAK1600_CTX *) CShake256Context,
> > > >
> > > > +                      '\x04',
> > > >
> > > > +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH
> > > > + * 2) / 8,
> > > >
> > > > +                      OutputLen
> > > >
> > > > +                      );
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  AbsorbLen = 0;
> > > >
> > > > +  //
> > > >
> > > > +  // Absorb Absorb bytepad(.., rate).
> > > >
> > > > +  //
> > > >
> > > > +  EncLen = left_encode (EncBuf, CSHAKE256_RATE_IN_BYTES);
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > > + CShake256Context,
> > > > EncBuf, EncLen);
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  AbsorbLen += EncLen;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Absorb encode_string(N).
> > > >
> > > > +  //
> > > >
> > > > +  EncLen = left_encode (EncBuf, NameLen * 8);
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > > + CShake256Context,
> > > > EncBuf, EncLen);
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  AbsorbLen += EncLen;
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > > + CShake256Context,
> > > > Name, NameLen);
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  AbsorbLen += NameLen;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Absorb encode_string(S).
> > > >
> > > > +  //
> > > >
> > > > +  EncLen = left_encode (EncBuf, CustomizationLen * 8);
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > > + CShake256Context,
> > > > EncBuf, EncLen);
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  AbsorbLen += EncLen;
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((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) sha3_update ((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)(sha3_update ((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) (sha3_final ((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 0000000000..3eaa7c2ceb
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> > > > @@ -0,0 +1,275 @@
> > > > +/** @file
> > > >
> > > > +  ParallelHash Implementation.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +
> > > >
> > > > +#include "InternalCryptLib.h"
> > > >
> > > > +#include <Library\PcdLib.h>
> > > >
> > > > +#include <Library\SynchronizationLib.h>
> > > >
> > > > +#include <Library\MmServicesTableLib.h>
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +UINT16        mBlockNum;
> > > >
> > > > +UINTN        mBlockSize;
> > > >
> > > > +UINTN        mLastBlockSize;
> > > >
> > > > +UINT8        *mInput;
> > > >
> > > > +UINTN        mBlockResultSize;
> > > >
> > > > +UINT8        *mBlockHashResult;
> > > >
> > > > +BOOLEAN      *mBlockIsCompleted;
> > > >
> > > > +SPIN_LOCK    *mSpinLockList;
> > > >
> > > > +
> > > >
> > > > +UINTN LeftEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> > > >
> > > > +UINTN RightEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> > > >
> > > > +
> > > >
> > > > +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
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +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]);
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Parallel hash function ParallelHash256, as defined in NIST's
> > > > + Special Publication
> > > > 800-185,
> > > >
> > > > +  published December 2016.
> > > >
> > > > +
> > > >
> > > > +  @param  Input[in]            Pointer to the input message (X).
> > > >
> > > > +  @param  InputByteLen[in]     The number(>0) of input bytes provided
> for
> > > the
> > > > input data.
> > > >
> > > > +  @param  Output[out]          Pointer to the output buffer.
> > > >
> > > > +  @param  OutputByteLen[in]    The desired number of output bytes
> (L).
> > > >
> > > > +  @param  Customization[in]    Pointer to the customization string (S).
> > > >
> > > > +  @param  CustomByteLen[in]    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,
> > > >
> > > > +  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;
> > > >
> > > > +  EFI_STATUS   Status;
> > > >
> > > > +  UINTN        StartedApNum;
> > > >
> > > > +  BOOLEAN      AllCompleted;
> > > >
> > > > +  UINTN        Offset;
> > > >
> > > > +  BOOLEAN      ReturnValue;
> > > >
> > > > +
> > > >
> > > > +  if (InputByteLen == 0 || OutputByteLen == 0) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if (Input == NULL || Output == NULL){
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if (CustomByteLen != 0 && Customization == NULL){
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Get Block number n.
> > > >
> > > > +  //
> > > >
> > > > +  mBlockNum = PcdGet16 (PcdParallelHashBlockNumber);
> > > >
> > > > +
> > > >
> > > > +  if (mBlockNum < 1 || InputByteLen < mBlockNum - 1){
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Set hash result size of each block in bytes.
> > > >
> > > > +  //
> > > >
> > > > +  mBlockResultSize = OutputByteLen;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // calculate the block byte length B.
> > > >
> > > > +  //
> > > >
> > > > +  mBlockSize = InputByteLen % mBlockNum == 0 ? InputByteLen /
> > > mBlockNum :
> > > > InputByteLen / (mBlockNum - 1);
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // 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 = 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.
> > > >
> > > > +  //
> > > >
> > > > +  StartedApNum = 0;
> > > >
> > > > +  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
> > > >
> > > > +    if (Index != gMmst->CurrentlyExecutingCpu) {
> > > >
> > > > +      Status = gMmst->MmStartupThisAp (ParallelHashApExecute, Index,
> > > > + NULL);
> > > >
> > > > +      if (!EFI_ERROR (Status)) {
> > > >
> > > > +        StartedApNum++;
> > > >
> > > > +      }
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // 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 (mSpinLockList);
> > > >
> > > > +  }
> > > >
> > > > +  if (mBlockIsCompleted != NULL){
> > > >
> > > > +    FreePool (mBlockIsCompleted);
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  return ReturnValue;
> > > >
> > > > +}
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > > > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > > > new file mode 100644
> > > > index 0000000000..b170c463de
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > > > @@ -0,0 +1,102 @@
> > > > +/** @file
> > > >
> > > > +  SHA3 realted functions from OpenSSL.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +Copyright 2017-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 "sha3.h"
> > > >
> > > > +
> > > >
> > > > +size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t
> > > > +len,
> > > >
> > > > +                   size_t r);
> > > >
> > > > +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len,
> > > > +size_t r);
> > > >
> > > > +
> > > >
> > > > +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t
> > > > +md_size)
> > > >
> > > > +{
> > > >
> > > > +    if (bsz <= sizeof(ctx->buf)) {
> > > >
> > > > +        memset(ctx->A, 0, sizeof(ctx->A));
> > > >
> > > > +
> > > >
> > > > +        ctx->num = 0;
> > > >
> > > > +        ctx->block_size = bsz;
> > > >
> > > > +        ctx->md_size = md_size;
> > > >
> > > > +        ctx->pad = pad;
> > > >
> > > > +
> > > >
> > > > +        return 1;
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    return 0;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
> > > >
> > > > +{
> > > >
> > > > +    const unsigned char *inp = _inp;
> > > >
> > > > +    size_t bsz = ctx->block_size;
> > > >
> > > > +    size_t num, rem;
> > > >
> > > > +
> > > >
> > > > +    if (len == 0)
> > > >
> > > > +        return 1;
> > > >
> > > > +
> > > >
> > > > +    if ((num = ctx->num) != 0) {      /* process intermediate buffer? */
> > > >
> > > > +        rem = bsz - num;
> > > >
> > > > +
> > > >
> > > > +        if (len < rem) {
> > > >
> > > > +            memcpy(ctx->buf + num, inp, len);
> > > >
> > > > +            ctx->num += len;
> > > >
> > > > +            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(ctx->buf + num, inp, rem);
> > > >
> > > > +        inp += rem, len -= rem;
> > > >
> > > > +        (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> > > >
> > > > +        ctx->num = 0;
> > > >
> > > > +        /* ctx->buf is processed, ctx->num is guaranteed to be zero
> > > > + */
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    if (len >= bsz)
> > > >
> > > > +        rem = SHA3_absorb(ctx->A, inp, len, bsz);
> > > >
> > > > +    else
> > > >
> > > > +        rem = len;
> > > >
> > > > +
> > > >
> > > > +    if (rem) {
> > > >
> > > > +        memcpy(ctx->buf, inp + len - rem, rem);
> > > >
> > > > +        ctx->num = rem;
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    return 1;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md)
> > > >
> > > > +{
> > > >
> > > > +    size_t bsz = ctx->block_size;
> > > >
> > > > +    size_t num = ctx->num;
> > > >
> > > > +
> > > >
> > > > +    if (ctx->md_size == 0)
> > > >
> > > > +        return 1;
> > > >
> > > > +
> > > >
> > > > +    /*
> > > >
> > > > +     * Pad the data with 10*1. Note that |num| can be |bsz - 1|
> > > >
> > > > +     * in which case both byte operations below are performed on
> > > >
> > > > +     * same byte...
> > > >
> > > > +     */
> > > >
> > > > +    memset(ctx->buf + num, 0, bsz - num);
> > > >
> > > > +    ctx->buf[num] = ctx->pad;
> > > >
> > > > +    ctx->buf[bsz - 1] |= 0x80;
> > > >
> > > > +
> > > >
> > > > +    (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> > > >
> > > > +
> > > >
> > > > +    SHA3_squeeze(ctx->A, md, ctx->md_size, bsz);
> > > >
> > > > +
> > > >
> > > > +    return 1;
> > > >
> > > > +}
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > > > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > > > new file mode 100644
> > > > index 0000000000..b2a40ee044
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > > > @@ -0,0 +1,53 @@
> > > > +/** @file
> > > >
> > > > +  Encode realted functions from Xkcp.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +The eXtended Keccak Code Package (XKCP)
> > > >
> > > > +https://github.com/XKCP/XKCP
> > > >
> > > > +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 "xkcp.h"
> > > >
> > > > +
> > > >
> > > > +unsigned int left_encode(unsigned char * encbuf, size_t value)
> > > >
> > > > +{
> > > >
> > > > +    unsigned int n, i;
> > > >
> > > > +    size_t v;
> > > >
> > > > +
> > > >
> > > > +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> > > >
> > > > +        ; /* empty */
> > > >
> > > > +    if (n == 0)
> > > >
> > > > +        n = 1;
> > > >
> > > > +    for ( i = 1; i <= n; ++i )
> > > >
> > > > +    {
> > > >
> > > > +        encbuf[i] = (unsigned char)(value >> (8 * (n-i)));
> > > >
> > > > +    }
> > > >
> > > > +    encbuf[0] = (unsigned char)n;
> > > >
> > > > +    return n + 1;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +unsigned int right_encode(unsigned char * encbuf, size_t value)
> > > >
> > > > +{
> > > >
> > > > +    unsigned int n, i;
> > > >
> > > > +    size_t v;
> > > >
> > > > +
> > > >
> > > > +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> > > >
> > > > +        ; /* empty */
> > > >
> > > > +    if (n == 0)
> > > >
> > > > +        n = 1;
> > > >
> > > > +    for ( i = 1; i <= n; ++i )
> > > >
> > > > +    {
> > > >
> > > > +        encbuf[i-1] = (unsigned char)(value >> (8 * (n-i)));
> > > >
> > > > +    }
> > > >
> > > > +    encbuf[n] = (unsigned char)n;
> > > >
> > > > +    return n + 1;
> > > >
> > > > +}
> > > >
> > > > diff --git
> > > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > > > new file mode 100644
> > > > index 0000000000..052ab3a0d6
> > > > --- /dev/null
> > > > +++
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > > > @@ -0,0 +1,152 @@
> > > > +/** @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;
> > > >
> > > > +  UINT16   OriginalParallelHashBlockNumber;
> > > >
> > > > +  UINT8    Output[64];
> > > >
> > > > +
> > > >
> > > > +  // Restore original PcdParallelHashBlockNumber.
> > > >
> > > > +  OriginalParallelHashBlockNumber = PcdGet16
> > > > + (PcdParallelHashBlockNumber);
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Test #1 using sample1.
> > > >
> > > > +  //
> > > >
> > > > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample1ByteLen /
> > > > BlockSizeSample1);
> > > >
> > > > +  Status = ParallelHash256HashAll (
> > > >
> > > > +             InputSample1,
> > > >
> > > > +             InputSample1ByteLen,
> > > >
> > > > +             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.
> > > >
> > > > +  //
> > > >
> > > > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample2ByteLen /
> > > > BlockSizeSample2);
> > > >
> > > > +  Status = ParallelHash256HashAll (
> > > >
> > > > +             InputSample2,
> > > >
> > > > +             InputSample2ByteLen,
> > > >
> > > > +             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.
> > > >
> > > > +  //
> > > >
> > > > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample3ByteLen /
> > > > BlockSizeSample3);
> > > >
> > > > +  Status = ParallelHash256HashAll (
> > > >
> > > > +             InputSample3,
> > > >
> > > > +             InputSample3ByteLen,
> > > >
> > > > +             Output,
> > > >
> > > > +             OutputByteLen,
> > > >
> > > > +             CustomizationSample3,
> > > >
> > > > +             CustomSample3ByteLen
> > > >
> > > > +             );
> > > >
> > > > +  UT_ASSERT_TRUE (Status);
> > > >
> > > > +
> > > >
> > > > +  // Check the output with the expected output.
> > > >
> > > > +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3,
> > > OutputByteLen);
> > > >
> > > > +
> > > >
> > > > +  // Recover original PcdParallelHashBlockNumber.
> > > >
> > > > +  PcdSet16S (PcdParallelHashBlockNumber,
> > > > + OriginalParallelHashBlockNumber);
> > > >
> > > > +
> > > >
> > > > +  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.dec b/CryptoPkg/CryptoPkg.dec index
> > > > 5888941bab..3af55d9c10 100644
> > > > --- a/CryptoPkg/CryptoPkg.dec
> > > > +++ b/CryptoPkg/CryptoPkg.dec
> > > > @@ -4,7 +4,7 @@
> > > >  #  This Package provides cryptographic-related libraries for UEFI
> > > > security modules.
> > > >
> > > >  #  It also provides a test application to test libraries.
> > > >
> > > >  #
> > > >
> > > > -#  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
> > > >
> > > >  #
> > > >
> > > >  ##
> > > >
> > > > @@ -81,5 +81,12 @@
> > > >    # @ValidList 0x80000001 | 0x00000001, 0x00000002, 0x00000004,
> > > > 0x00000008, 0x00000010
> > > >
> > > >
> > > >
> > >
> gEfiCryptoPkgTokenSpaceGuid.PcdHashApiLibPolicy|0x00000002|UINT32|0x
> > > 00
> > > > 000001
> > > >
> > > >
> > > >
> > > > +[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic,
> > > PcdsDynamicEx]
> > > >
> > > > +  ## This PCD indicates the block number of parallel hash
> > > >
> > > > +  #  Based on the value set, parallel hash can chose the block
> > > >
> > > > +  #  number to calculate specific hash.<BR>
> > > >
> > > > +  #  The number can be set by platform team according to the core
> > > number.
> > > >
> > > > +
> > > >
> > >
> gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber|0x0100|UINT1
> > > 6|0
> > > > x00000003
> > > >
> > > > +
> > > >
> > > >  [UserExtensions.TianoCore."ExtraFiles"]
> > > >
> > > >    CryptoPkgExtra.uni
> > > >
> > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > index f4bc7c0d73..0b274b1257 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,33 @@ 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[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,
> > > >
> > > > +  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/Library/BaseCryptLib/SmmCryptLib.inf
> > > > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > index e6470d7a21..70159163d4 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,9 @@
> > > >    OpensslLib
> > > >
> > > >    IntrinsicLib
> > > >
> > > >    PrintLib
> > > >
> > > > +  MmServicesTableLib
> > > >
> > > > +  SynchronizationLib
> > > >
> > > > +  PcdLib
> > > >
> > > >
> > > >
> > > >  #
> > > >
> > > >  # Remove these [BuildOptions] after this library is cleaned up
> > > >
> > > > @@ -101,3 +108,6 @@
> > > >    GCC:*_CLANG35_*_CC_FLAGS = -std=c99
> > > >
> > > >    GCC:*_CLANG38_*_CC_FLAGS = -std=c99
> > > >
> > > >    GCC:*_CLANGPDB_*_CC_FLAGS = -std=c99
> > > > -Wno-error=incompatible-pointer- types
> > > >
> > > > +
> > > >
> > > > +[Pcd]
> > > >
> > > > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> > > >
> > > > diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h
> > > > b/CryptoPkg/Library/Include/CrtLibSupport.h
> > > > index d257dca8fa..35d9c62a0b 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
> > > >
> > > >
> > > >
> > > > @@ -21,6 +21,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >
> > > >  #define MAX_STRING_SIZE  0x1000
> > > >
> > > >
> > > >
> > > > +#define PARALLELHASH_CUSTOMIZATION "ParallelHash"
> > > >
> > > > +
> > > >
> > > >  //
> > > >
> > > >  // We already have "no-ui" in out Configure invocation.
> > > >
> > > >  // but the code still fails to compile.
> > > >
> > > > @@ -111,6 +113,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/Library/Include/sha3.h
> > > > b/CryptoPkg/Library/Include/sha3.h
> > > > new file mode 100644
> > > > index 0000000000..71b4c75548
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/Include/sha3.h
> > > > @@ -0,0 +1,32 @@
> > > > +/** @file
> > > >
> > > > +  SHA3 realted functions from OpenSSL.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +Copyright 2017-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 <CrtLibSupport.h>
> > > >
> > > > +
> > > >
> > > > +#define KECCAK1600_WIDTH 1600
> > > >
> > > > +
> > > >
> > > > +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;
> > > >
> > > > +
> > > >
> > > > +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t
> > > > +md_size);
> > > >
> > > > +
> > > >
> > > > +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
> > > >
> > > > +
> > > >
> > > > +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md);
> > > >
> > > > diff --git a/CryptoPkg/Library/Include/xkcp.h
> > > > b/CryptoPkg/Library/Include/xkcp.h
> > > > new file mode 100644
> > > > index 0000000000..b328d672e4
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/Include/xkcp.h
> > > > @@ -0,0 +1,23 @@
> > > > +/** @file
> > > >
> > > > +  Encode realted functions from Xkcp.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +The eXtended Keccak Code Package (XKCP)
> > > >
> > > > +https://github.com/XKCP/XKCP
> > > >
> > > > +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 <CrtLibSupport.h>
> > > >
> > > > +
> > > >
> > > > +unsigned int left_encode(unsigned char * encbuf, size_t value);
> > > >
> > > > +
> > > >
> > > > +unsigned int right_encode(unsigned char * encbuf, size_t value);
> > > >
> > > > diff --git
> > > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > > index a6b3482742..0bffd687c2 100644
> > > > ---
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > > +++
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > > @@ -1,7 +1,7 @@
> > > >  /** @file
> > > >
> > > >    Application for Cryptographic Primitives Validation.
> > > >
> > > >
> > > >
> > > > -Copyright (c) 2009 - 2016, Intel Corporation. All rights
> > > > reserved.<BR>
> > > >
> > > > +Copyright (c) 2009 - 2022, Intel Corporation. All rights
> > > > +reserved.<BR>
> > > >
> > > >  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >
> > > >
> > > >  **/
> > > >
> > > > @@ -19,6 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > #include <Library/BaseLib.h>
> > > >
> > > >  #include <Library/BaseMemoryLib.h>
> > > >
> > > >  #include <Library/MemoryAllocationLib.h>
> > > >
> > > > +#include <Library/PcdLib.h>
> > > >
> > > >  // #include <UnitTestTypes.h>
> > > >
> > > >  #include <Library/UnitTestLib.h>
> > > >
> > > >  // #include <Library/UnitTestAssertLib.h>
> > > >
> > > > diff --git
> > > >
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > > > f
> > > >
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > > > f
> > > > index 00c8692650..61a59d6a47 100644
> > > > ---
> > > >
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > > > f
> > > > +++
> > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHos
> > > > +++ t.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,8 @@
> > > >    DebugLib
> > > >
> > > >    BaseCryptLib
> > > >
> > > >    UnitTestLib
> > > >
> > > > +  PcdLib
> > > >
> > > > +
> > > >
> > > > +[Pcd]
> > > >
> > > > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> > > >
> > > > +
> > > >
> > > > diff --git
> > > >
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > > > nf
> > > >
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > > > nf
> > > > index ca789aa6ad..682f25a754 100644
> > > > ---
> > > >
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > > > nf
> > > > +++
> > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShe
> > > > +++ ll.inf
> > > > @@ -2,6 +2,7 @@
> > > >  # BaseCryptLib UnitTest built for execution in UEFI Shell.
> > > >
> > > >  #
> > > >
> > > >  # Copyright (c) Microsoft Corporation.<BR>
> > > >
> > > > +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > >  # SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >  ##
> > > >
> > > >
> > > >
> > > > @@ -36,6 +37,7 @@
> > > >    Pkcs7EkuTests.c
> > > >
> > > >    OaepEncryptTests.c
> > > >
> > > >    RsaPssTests.c
> > > >
> > > > +  ParallelhashTests.c
> > > >
> > > >
> > > >
> > > >  [Packages]
> > > >
> > > >    MdePkg/MdePkg.dec
> > > >
> > > > @@ -48,3 +50,7 @@
> > > >    UnitTestLib
> > > >
> > > >    PrintLib
> > > >
> > > >    BaseCryptLib
> > > >
> > > > +  PcdLib
> > > >
> > > > +
> > > >
> > > > +[Pcd]
> > > >
> > > > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> > > >
> > > > --
> > > > 2.26.2.windows.1


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

* Re: [PATCH v1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
  2022-02-16  7:51     ` Yao, Jiewen
  2022-02-16  8:23       ` Li, Zhihao
@ 2022-02-17  5:28       ` Li, Zhihao
  1 sibling, 0 replies; 6+ messages in thread
From: Li, Zhihao @ 2022-02-17  5:28 UTC (permalink / raw)
  To: Yao, Jiewen, devel@edk2.groups.io
  Cc: Wang, Jian J, Lu, Xiaoyu1, Jiang, Guomin, Fu, Siyuan

We try to make proper attribution for the code in  openssl_sha3 and in xkcp.
We separated their implementation into CryptSha3.c and CryptXkcp.c, 
Separated their declaration into sha3.h and xkcp.h.

With the comment, we plan to delete these header files and put the declaration and 
Structure define into CryptCshake256.c.

> -----Original Message-----
> From: Yao, Jiewen <jiewen.yao@intel.com>
> Sent: Wednesday, February 16, 2022 3:52 PM
> To: Li, Zhihao <zhihao.li@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: [PATCH v1] CryptoPkg: Add new hash algorithm
> ParallelHash256HashAll in BaseCryptLib.
> 
> But I don’t understand why we need sha3.h and xkcp.h at all.
> 
> 
> > -----Original Message-----
> > From: Li, Zhihao <zhihao.li@intel.com>
> > Sent: Wednesday, February 16, 2022 3:43 PM
> > 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: [PATCH v1] CryptoPkg: Add new hash algorithm
> > ParallelHash256HashAll in BaseCryptLib.
> >
> > With your comment, we plan do some modification for parallelhash.
> > 1. Plan to add  a parameter (BlockSize) on  ParallelHash256HashAll  function
> to
> > replace PcdParallelHashBlockNumber.
> > 2. Plan to move sha3.h and xkcp.h to CryptoPkg\Library\BaseCryptLib\Hash
> > folder.
> >
> >
> > > -----Original Message-----
> > > From: Yao, Jiewen <jiewen.yao@intel.com>
> > > Sent: Tuesday, February 15, 2022 2:09 PM
> > > To: Li, Zhihao <zhihao.li@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: [PATCH v1] CryptoPkg: Add new hash algorithm
> > > ParallelHash256HashAll in BaseCryptLib.
> > >
> > > Thanks for the update.
> > >
> > > Feedback below:
> > >
> > > 1) How block size is determined for below API?
> > >
> > > BOOLEAN
> > > EFIAPI
> > > ParallelHash256HashAll (
> > >   IN CONST VOID            *Input,
> > >   IN       UINTN           InputByteLen,
> > >   OUT      VOID            *Output,
> > >   IN       UINTN           OutputByteLen,
> > >   IN CONST VOID            *Customization,
> > >   IN       UINTN           CustomByteLen
> > >   );
> > >
> > > Is that determined by PcdParallelHashBlockNumber ?
> > >
> > > I don’t think it is good idea to let a crypto library determine a platform
> PCD.
> > > For example, how do you support binary crypto module ?
> > Plan to add  a parameter (BlockSize) to replace
> PcdParallelHashBlockNumber.
> > >
> > > 2) Why we need "sha3.h" and "xkcp.h" ?
> > > These are openssl specific structure. It shall not be put to EDKII file
> header.
> > >
> > > CryptoPkg\Library\Include shall only contain generic dependency header.
> > Plan to move sha3.h and xkcp.h to CryptoPkg\Library\BaseCryptLib\Hash
> folder.
> > >
> > >
> > >
> > >
> > > Thank you
> > > Yao, Jiewen
> > >
> > > > -----Original Message-----
> > > > From: Li, Zhihao <zhihao.li@intel.com>
> > > > Sent: Friday, February 11, 2022 5:05 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: [PATCH v1] 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.
> > > >
> > > > 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>
> > > >
> > > > Signed-off-by: Zhihao Li <zhihao.li@intel.com>
> > > > ---
> > > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c                   | 313
> > > > ++++++++++++++++++++
> > > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c                | 275
> > > > +++++++++++++++++
> > > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c                        | 102
> > > +++++++
> > > >  CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c                        |  53
> ++++
> > > >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c       |
> > > 152
> > > > ++++++++++
> > > >  CryptoPkg/CryptoPkg.dec                                                |   9 +-
> > > >  CryptoPkg/Include/Library/BaseCryptLib.h                               |  29 +-
> > > >  CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf                         |  12 +-
> > > >  CryptoPkg/Library/Include/CrtLibSupport.h                              |   5 +-
> > > >  CryptoPkg/Library/Include/sha3.h                                       |  32 ++
> > > >  CryptoPkg/Library/Include/xkcp.h                                       |  23 ++
> > > >  CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> |   3
> > > +-
> > > >
> CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf
> > > |   7 +
> > > >
> CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf |
> > > 6 +
> > > >  14 files changed, 1016 insertions(+), 5 deletions(-)
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > > > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > > > new file mode 100644
> > > > index 0000000000..5efced3f46
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
> > > > @@ -0,0 +1,313 @@
> > > > +/** @file
> > > >
> > > > +  cSHAKE-256 Digest Wrapper Implementations.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +
> > > >
> > > > +#include "InternalCryptLib.h"
> > > >
> > > > +#include "sha3.h"
> > > >
> > > > +#include "xkcp.h"
> > > >
> > > > +
> > > >
> > > > +#define  CSHAKE256_SECURITY_STRENGTH    256
> > > >
> > > > +#define  CSHAKE256_RATE_IN_BYTES        136
> > > >
> > > > +
> > > >
> > > > +const CHAR8 mZeroPadding[CSHAKE256_RATE_IN_BYTES] = {0};
> > > >
> > > > +
> > > >
> > > > +UINTN
> > > >
> > > > +EFIAPI
> > > >
> > > > +LeftEncode (
> > > >
> > > > +  OUT UINT8     *Encbuf,
> > > >
> > > > +  IN  UINTN     Value
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  return left_encode (Encbuf, Value);
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +UINTN
> > > >
> > > > +EFIAPI
> > > >
> > > > +RightEncode (
> > > >
> > > > +  OUT UINT8     *Encbuf,
> > > >
> > > > +  IN  UINTN     Value
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  return right_encode (Encbuf, Value);
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Retrieves the size, in bytes, of the context buffer required for
> > > > + cSHAKE-256
> > > > hash operations.
> > > >
> > > > +
> > > >
> > > > +  @return  The size, in bytes, of the context buffer required for
> > > > + cSHAKE-256
> > > > hash operations.
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +UINTN
> > > >
> > > > +EFIAPI
> > > >
> > > > +CShake256GetContextSize (
> > > >
> > > > +  VOID
> > > >
> > > > +  )
> > > >
> > > > +{
> > > >
> > > > +  return (UINTN) (sizeof (KECCAK1600_CTX));
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  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;
> > > >
> > > > +  unsigned char EncBuf[sizeof(size_t)+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.
> > > >
> > > > +    //
> > > >
> > > > +    return (BOOLEAN) init (
> > > >
> > > > +                      (KECCAK1600_CTX *) CShake256Context,
> > > >
> > > > +                      '\x1f',
> > > >
> > > > +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH
> > > > + * 2) / 8,
> > > >
> > > > +                      OutputLen
> > > >
> > > > +                      );
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  Status = (BOOLEAN) init (
> > > >
> > > > +                      (KECCAK1600_CTX *) CShake256Context,
> > > >
> > > > +                      '\x04',
> > > >
> > > > +                      (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH
> > > > + * 2) / 8,
> > > >
> > > > +                      OutputLen
> > > >
> > > > +                      );
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  AbsorbLen = 0;
> > > >
> > > > +  //
> > > >
> > > > +  // Absorb Absorb bytepad(.., rate).
> > > >
> > > > +  //
> > > >
> > > > +  EncLen = left_encode (EncBuf, CSHAKE256_RATE_IN_BYTES);
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > > + CShake256Context,
> > > > EncBuf, EncLen);
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  AbsorbLen += EncLen;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Absorb encode_string(N).
> > > >
> > > > +  //
> > > >
> > > > +  EncLen = left_encode (EncBuf, NameLen * 8);
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > > + CShake256Context,
> > > > EncBuf, EncLen);
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  AbsorbLen += EncLen;
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > > + CShake256Context,
> > > > Name, NameLen);
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  AbsorbLen += NameLen;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Absorb encode_string(S).
> > > >
> > > > +  //
> > > >
> > > > +  EncLen = left_encode (EncBuf, CustomizationLen * 8);
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((KECCAK1600_CTX *)
> > > > + CShake256Context,
> > > > EncBuf, EncLen);
> > > >
> > > > +  if (!Status) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +  AbsorbLen += EncLen;
> > > >
> > > > +  Status = (BOOLEAN) sha3_update ((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) sha3_update ((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)(sha3_update ((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) (sha3_final ((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 0000000000..3eaa7c2ceb
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
> > > > @@ -0,0 +1,275 @@
> > > > +/** @file
> > > >
> > > > +  ParallelHash Implementation.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +**/
> > > >
> > > > +
> > > >
> > > > +#include "InternalCryptLib.h"
> > > >
> > > > +#include <Library\PcdLib.h>
> > > >
> > > > +#include <Library\SynchronizationLib.h>
> > > >
> > > > +#include <Library\MmServicesTableLib.h>
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +UINT16        mBlockNum;
> > > >
> > > > +UINTN        mBlockSize;
> > > >
> > > > +UINTN        mLastBlockSize;
> > > >
> > > > +UINT8        *mInput;
> > > >
> > > > +UINTN        mBlockResultSize;
> > > >
> > > > +UINT8        *mBlockHashResult;
> > > >
> > > > +BOOLEAN      *mBlockIsCompleted;
> > > >
> > > > +SPIN_LOCK    *mSpinLockList;
> > > >
> > > > +
> > > >
> > > > +UINTN LeftEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> > > >
> > > > +UINTN RightEncode (OUT UINT8 *Encbuf, IN UINTN Value);
> > > >
> > > > +
> > > >
> > > > +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
> > > >
> > > > +  );
> > > >
> > > > +
> > > >
> > > > +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]);
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +/**
> > > >
> > > > +  Parallel hash function ParallelHash256, as defined in NIST's
> > > > + Special Publication
> > > > 800-185,
> > > >
> > > > +  published December 2016.
> > > >
> > > > +
> > > >
> > > > +  @param  Input[in]            Pointer to the input message (X).
> > > >
> > > > +  @param  InputByteLen[in]     The number(>0) of input bytes provided
> for
> > > the
> > > > input data.
> > > >
> > > > +  @param  Output[out]          Pointer to the output buffer.
> > > >
> > > > +  @param  OutputByteLen[in]    The desired number of output bytes
> (L).
> > > >
> > > > +  @param  Customization[in]    Pointer to the customization string (S).
> > > >
> > > > +  @param  CustomByteLen[in]    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,
> > > >
> > > > +  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;
> > > >
> > > > +  EFI_STATUS   Status;
> > > >
> > > > +  UINTN        StartedApNum;
> > > >
> > > > +  BOOLEAN      AllCompleted;
> > > >
> > > > +  UINTN        Offset;
> > > >
> > > > +  BOOLEAN      ReturnValue;
> > > >
> > > > +
> > > >
> > > > +  if (InputByteLen == 0 || OutputByteLen == 0) {
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if (Input == NULL || Output == NULL){
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  if (CustomByteLen != 0 && Customization == NULL){
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Get Block number n.
> > > >
> > > > +  //
> > > >
> > > > +  mBlockNum = PcdGet16 (PcdParallelHashBlockNumber);
> > > >
> > > > +
> > > >
> > > > +  if (mBlockNum < 1 || InputByteLen < mBlockNum - 1){
> > > >
> > > > +    return FALSE;
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Set hash result size of each block in bytes.
> > > >
> > > > +  //
> > > >
> > > > +  mBlockResultSize = OutputByteLen;
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // calculate the block byte length B.
> > > >
> > > > +  //
> > > >
> > > > +  mBlockSize = InputByteLen % mBlockNum == 0 ? InputByteLen /
> > > mBlockNum :
> > > > InputByteLen / (mBlockNum - 1);
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // 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 = 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.
> > > >
> > > > +  //
> > > >
> > > > +  StartedApNum = 0;
> > > >
> > > > +  for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
> > > >
> > > > +    if (Index != gMmst->CurrentlyExecutingCpu) {
> > > >
> > > > +      Status = gMmst->MmStartupThisAp (ParallelHashApExecute, Index,
> > > > + NULL);
> > > >
> > > > +      if (!EFI_ERROR (Status)) {
> > > >
> > > > +        StartedApNum++;
> > > >
> > > > +      }
> > > >
> > > > +    }
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // 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 (mSpinLockList);
> > > >
> > > > +  }
> > > >
> > > > +  if (mBlockIsCompleted != NULL){
> > > >
> > > > +    FreePool (mBlockIsCompleted);
> > > >
> > > > +  }
> > > >
> > > > +
> > > >
> > > > +  return ReturnValue;
> > > >
> > > > +}
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > > > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > > > new file mode 100644
> > > > index 0000000000..b170c463de
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
> > > > @@ -0,0 +1,102 @@
> > > > +/** @file
> > > >
> > > > +  SHA3 realted functions from OpenSSL.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +Copyright 2017-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 "sha3.h"
> > > >
> > > > +
> > > >
> > > > +size_t SHA3_absorb(uint64_t A[5][5], const unsigned char *inp, size_t
> > > > +len,
> > > >
> > > > +                   size_t r);
> > > >
> > > > +void SHA3_squeeze(uint64_t A[5][5], unsigned char *out, size_t len,
> > > > +size_t r);
> > > >
> > > > +
> > > >
> > > > +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t
> > > > +md_size)
> > > >
> > > > +{
> > > >
> > > > +    if (bsz <= sizeof(ctx->buf)) {
> > > >
> > > > +        memset(ctx->A, 0, sizeof(ctx->A));
> > > >
> > > > +
> > > >
> > > > +        ctx->num = 0;
> > > >
> > > > +        ctx->block_size = bsz;
> > > >
> > > > +        ctx->md_size = md_size;
> > > >
> > > > +        ctx->pad = pad;
> > > >
> > > > +
> > > >
> > > > +        return 1;
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    return 0;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +
> > > >
> > > > +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len)
> > > >
> > > > +{
> > > >
> > > > +    const unsigned char *inp = _inp;
> > > >
> > > > +    size_t bsz = ctx->block_size;
> > > >
> > > > +    size_t num, rem;
> > > >
> > > > +
> > > >
> > > > +    if (len == 0)
> > > >
> > > > +        return 1;
> > > >
> > > > +
> > > >
> > > > +    if ((num = ctx->num) != 0) {      /* process intermediate buffer? */
> > > >
> > > > +        rem = bsz - num;
> > > >
> > > > +
> > > >
> > > > +        if (len < rem) {
> > > >
> > > > +            memcpy(ctx->buf + num, inp, len);
> > > >
> > > > +            ctx->num += len;
> > > >
> > > > +            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(ctx->buf + num, inp, rem);
> > > >
> > > > +        inp += rem, len -= rem;
> > > >
> > > > +        (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> > > >
> > > > +        ctx->num = 0;
> > > >
> > > > +        /* ctx->buf is processed, ctx->num is guaranteed to be zero
> > > > + */
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    if (len >= bsz)
> > > >
> > > > +        rem = SHA3_absorb(ctx->A, inp, len, bsz);
> > > >
> > > > +    else
> > > >
> > > > +        rem = len;
> > > >
> > > > +
> > > >
> > > > +    if (rem) {
> > > >
> > > > +        memcpy(ctx->buf, inp + len - rem, rem);
> > > >
> > > > +        ctx->num = rem;
> > > >
> > > > +    }
> > > >
> > > > +
> > > >
> > > > +    return 1;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md)
> > > >
> > > > +{
> > > >
> > > > +    size_t bsz = ctx->block_size;
> > > >
> > > > +    size_t num = ctx->num;
> > > >
> > > > +
> > > >
> > > > +    if (ctx->md_size == 0)
> > > >
> > > > +        return 1;
> > > >
> > > > +
> > > >
> > > > +    /*
> > > >
> > > > +     * Pad the data with 10*1. Note that |num| can be |bsz - 1|
> > > >
> > > > +     * in which case both byte operations below are performed on
> > > >
> > > > +     * same byte...
> > > >
> > > > +     */
> > > >
> > > > +    memset(ctx->buf + num, 0, bsz - num);
> > > >
> > > > +    ctx->buf[num] = ctx->pad;
> > > >
> > > > +    ctx->buf[bsz - 1] |= 0x80;
> > > >
> > > > +
> > > >
> > > > +    (void)SHA3_absorb(ctx->A, ctx->buf, bsz, bsz);
> > > >
> > > > +
> > > >
> > > > +    SHA3_squeeze(ctx->A, md, ctx->md_size, bsz);
> > > >
> > > > +
> > > >
> > > > +    return 1;
> > > >
> > > > +}
> > > >
> > > > diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > > > b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > > > new file mode 100644
> > > > index 0000000000..b2a40ee044
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
> > > > @@ -0,0 +1,53 @@
> > > > +/** @file
> > > >
> > > > +  Encode realted functions from Xkcp.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +The eXtended Keccak Code Package (XKCP)
> > > >
> > > > +https://github.com/XKCP/XKCP
> > > >
> > > > +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 "xkcp.h"
> > > >
> > > > +
> > > >
> > > > +unsigned int left_encode(unsigned char * encbuf, size_t value)
> > > >
> > > > +{
> > > >
> > > > +    unsigned int n, i;
> > > >
> > > > +    size_t v;
> > > >
> > > > +
> > > >
> > > > +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> > > >
> > > > +        ; /* empty */
> > > >
> > > > +    if (n == 0)
> > > >
> > > > +        n = 1;
> > > >
> > > > +    for ( i = 1; i <= n; ++i )
> > > >
> > > > +    {
> > > >
> > > > +        encbuf[i] = (unsigned char)(value >> (8 * (n-i)));
> > > >
> > > > +    }
> > > >
> > > > +    encbuf[0] = (unsigned char)n;
> > > >
> > > > +    return n + 1;
> > > >
> > > > +}
> > > >
> > > > +
> > > >
> > > > +unsigned int right_encode(unsigned char * encbuf, size_t value)
> > > >
> > > > +{
> > > >
> > > > +    unsigned int n, i;
> > > >
> > > > +    size_t v;
> > > >
> > > > +
> > > >
> > > > +    for ( v = value, n = 0; v && (n < sizeof(size_t)); ++n, v >>= 8 )
> > > >
> > > > +        ; /* empty */
> > > >
> > > > +    if (n == 0)
> > > >
> > > > +        n = 1;
> > > >
> > > > +    for ( i = 1; i <= n; ++i )
> > > >
> > > > +    {
> > > >
> > > > +        encbuf[i-1] = (unsigned char)(value >> (8 * (n-i)));
> > > >
> > > > +    }
> > > >
> > > > +    encbuf[n] = (unsigned char)n;
> > > >
> > > > +    return n + 1;
> > > >
> > > > +}
> > > >
> > > > diff --git
> > > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > > > new file mode 100644
> > > > index 0000000000..052ab3a0d6
> > > > --- /dev/null
> > > > +++
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/ParallelhashTests.c
> > > > @@ -0,0 +1,152 @@
> > > > +/** @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;
> > > >
> > > > +  UINT16   OriginalParallelHashBlockNumber;
> > > >
> > > > +  UINT8    Output[64];
> > > >
> > > > +
> > > >
> > > > +  // Restore original PcdParallelHashBlockNumber.
> > > >
> > > > +  OriginalParallelHashBlockNumber = PcdGet16
> > > > + (PcdParallelHashBlockNumber);
> > > >
> > > > +
> > > >
> > > > +  //
> > > >
> > > > +  // Test #1 using sample1.
> > > >
> > > > +  //
> > > >
> > > > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample1ByteLen /
> > > > BlockSizeSample1);
> > > >
> > > > +  Status = ParallelHash256HashAll (
> > > >
> > > > +             InputSample1,
> > > >
> > > > +             InputSample1ByteLen,
> > > >
> > > > +             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.
> > > >
> > > > +  //
> > > >
> > > > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample2ByteLen /
> > > > BlockSizeSample2);
> > > >
> > > > +  Status = ParallelHash256HashAll (
> > > >
> > > > +             InputSample2,
> > > >
> > > > +             InputSample2ByteLen,
> > > >
> > > > +             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.
> > > >
> > > > +  //
> > > >
> > > > +  PcdSet16S (PcdParallelHashBlockNumber, InputSample3ByteLen /
> > > > BlockSizeSample3);
> > > >
> > > > +  Status = ParallelHash256HashAll (
> > > >
> > > > +             InputSample3,
> > > >
> > > > +             InputSample3ByteLen,
> > > >
> > > > +             Output,
> > > >
> > > > +             OutputByteLen,
> > > >
> > > > +             CustomizationSample3,
> > > >
> > > > +             CustomSample3ByteLen
> > > >
> > > > +             );
> > > >
> > > > +  UT_ASSERT_TRUE (Status);
> > > >
> > > > +
> > > >
> > > > +  // Check the output with the expected output.
> > > >
> > > > +  UT_ASSERT_MEM_EQUAL (Output, ExpectOutputSample3,
> > > OutputByteLen);
> > > >
> > > > +
> > > >
> > > > +  // Recover original PcdParallelHashBlockNumber.
> > > >
> > > > +  PcdSet16S (PcdParallelHashBlockNumber,
> > > > + OriginalParallelHashBlockNumber);
> > > >
> > > > +
> > > >
> > > > +  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.dec b/CryptoPkg/CryptoPkg.dec index
> > > > 5888941bab..3af55d9c10 100644
> > > > --- a/CryptoPkg/CryptoPkg.dec
> > > > +++ b/CryptoPkg/CryptoPkg.dec
> > > > @@ -4,7 +4,7 @@
> > > >  #  This Package provides cryptographic-related libraries for UEFI
> > > > security modules.
> > > >
> > > >  #  It also provides a test application to test libraries.
> > > >
> > > >  #
> > > >
> > > > -#  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
> > > >
> > > >  #
> > > >
> > > >  ##
> > > >
> > > > @@ -81,5 +81,12 @@
> > > >    # @ValidList 0x80000001 | 0x00000001, 0x00000002, 0x00000004,
> > > > 0x00000008, 0x00000010
> > > >
> > > >
> > > >
> > >
> gEfiCryptoPkgTokenSpaceGuid.PcdHashApiLibPolicy|0x00000002|UINT32|0x
> > > 00
> > > > 000001
> > > >
> > > >
> > > >
> > > > +[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic,
> > > PcdsDynamicEx]
> > > >
> > > > +  ## This PCD indicates the block number of parallel hash
> > > >
> > > > +  #  Based on the value set, parallel hash can chose the block
> > > >
> > > > +  #  number to calculate specific hash.<BR>
> > > >
> > > > +  #  The number can be set by platform team according to the core
> > > number.
> > > >
> > > > +
> > > >
> > >
> gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber|0x0100|UINT1
> > > 6|0
> > > > x00000003
> > > >
> > > > +
> > > >
> > > >  [UserExtensions.TianoCore."ExtraFiles"]
> > > >
> > > >    CryptoPkgExtra.uni
> > > >
> > > > diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > b/CryptoPkg/Include/Library/BaseCryptLib.h
> > > > index f4bc7c0d73..0b274b1257 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,33 @@ 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[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,
> > > >
> > > > +  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/Library/BaseCryptLib/SmmCryptLib.inf
> > > > b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
> > > > index e6470d7a21..70159163d4 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,9 @@
> > > >    OpensslLib
> > > >
> > > >    IntrinsicLib
> > > >
> > > >    PrintLib
> > > >
> > > > +  MmServicesTableLib
> > > >
> > > > +  SynchronizationLib
> > > >
> > > > +  PcdLib
> > > >
> > > >
> > > >
> > > >  #
> > > >
> > > >  # Remove these [BuildOptions] after this library is cleaned up
> > > >
> > > > @@ -101,3 +108,6 @@
> > > >    GCC:*_CLANG35_*_CC_FLAGS = -std=c99
> > > >
> > > >    GCC:*_CLANG38_*_CC_FLAGS = -std=c99
> > > >
> > > >    GCC:*_CLANGPDB_*_CC_FLAGS = -std=c99
> > > > -Wno-error=incompatible-pointer- types
> > > >
> > > > +
> > > >
> > > > +[Pcd]
> > > >
> > > > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> > > >
> > > > diff --git a/CryptoPkg/Library/Include/CrtLibSupport.h
> > > > b/CryptoPkg/Library/Include/CrtLibSupport.h
> > > > index d257dca8fa..35d9c62a0b 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
> > > >
> > > >
> > > >
> > > > @@ -21,6 +21,8 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >
> > > >  #define MAX_STRING_SIZE  0x1000
> > > >
> > > >
> > > >
> > > > +#define PARALLELHASH_CUSTOMIZATION "ParallelHash"
> > > >
> > > > +
> > > >
> > > >  //
> > > >
> > > >  // We already have "no-ui" in out Configure invocation.
> > > >
> > > >  // but the code still fails to compile.
> > > >
> > > > @@ -111,6 +113,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/Library/Include/sha3.h
> > > > b/CryptoPkg/Library/Include/sha3.h
> > > > new file mode 100644
> > > > index 0000000000..71b4c75548
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/Include/sha3.h
> > > > @@ -0,0 +1,32 @@
> > > > +/** @file
> > > >
> > > > +  SHA3 realted functions from OpenSSL.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +Copyright 2017-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 <CrtLibSupport.h>
> > > >
> > > > +
> > > >
> > > > +#define KECCAK1600_WIDTH 1600
> > > >
> > > > +
> > > >
> > > > +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;
> > > >
> > > > +
> > > >
> > > > +int init(KECCAK1600_CTX *ctx, unsigned char pad, size_t bsz, size_t
> > > > +md_size);
> > > >
> > > > +
> > > >
> > > > +int sha3_update(KECCAK1600_CTX *ctx, const void *_inp, size_t len);
> > > >
> > > > +
> > > >
> > > > +int sha3_final(KECCAK1600_CTX *ctx, unsigned char *md);
> > > >
> > > > diff --git a/CryptoPkg/Library/Include/xkcp.h
> > > > b/CryptoPkg/Library/Include/xkcp.h
> > > > new file mode 100644
> > > > index 0000000000..b328d672e4
> > > > --- /dev/null
> > > > +++ b/CryptoPkg/Library/Include/xkcp.h
> > > > @@ -0,0 +1,23 @@
> > > > +/** @file
> > > >
> > > > +  Encode realted functions from Xkcp.
> > > >
> > > > +
> > > >
> > > > +Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > > +SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > > +
> > > >
> > > > +The eXtended Keccak Code Package (XKCP)
> > > >
> > > > +https://github.com/XKCP/XKCP
> > > >
> > > > +Keccak, designed by Guido Bertoni, Joan Daemen, Michaël 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 <CrtLibSupport.h>
> > > >
> > > > +
> > > >
> > > > +unsigned int left_encode(unsigned char * encbuf, size_t value);
> > > >
> > > > +
> > > >
> > > > +unsigned int right_encode(unsigned char * encbuf, size_t value);
> > > >
> > > > diff --git
> > > > a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > > index a6b3482742..0bffd687c2 100644
> > > > ---
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > > +++
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h
> > > > @@ -1,7 +1,7 @@
> > > >  /** @file
> > > >
> > > >    Application for Cryptographic Primitives Validation.
> > > >
> > > >
> > > >
> > > > -Copyright (c) 2009 - 2016, Intel Corporation. All rights
> > > > reserved.<BR>
> > > >
> > > > +Copyright (c) 2009 - 2022, Intel Corporation. All rights
> > > > +reserved.<BR>
> > > >
> > > >  SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >
> > > >
> > > >  **/
> > > >
> > > > @@ -19,6 +19,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
> > > > #include <Library/BaseLib.h>
> > > >
> > > >  #include <Library/BaseMemoryLib.h>
> > > >
> > > >  #include <Library/MemoryAllocationLib.h>
> > > >
> > > > +#include <Library/PcdLib.h>
> > > >
> > > >  // #include <UnitTestTypes.h>
> > > >
> > > >  #include <Library/UnitTestLib.h>
> > > >
> > > >  // #include <Library/UnitTestAssertLib.h>
> > > >
> > > > diff --git
> > > >
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > > > f
> > > >
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > > > f
> > > > index 00c8692650..61a59d6a47 100644
> > > > ---
> > > >
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.in
> > > > f
> > > > +++
> > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHos
> > > > +++ t.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,8 @@
> > > >    DebugLib
> > > >
> > > >    BaseCryptLib
> > > >
> > > >    UnitTestLib
> > > >
> > > > +  PcdLib
> > > >
> > > > +
> > > >
> > > > +[Pcd]
> > > >
> > > > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> > > >
> > > > +
> > > >
> > > > diff --git
> > > >
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > > > nf
> > > >
> b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > > > nf
> > > > index ca789aa6ad..682f25a754 100644
> > > > ---
> > > >
> a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.i
> > > > nf
> > > > +++
> > > b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShe
> > > > +++ ll.inf
> > > > @@ -2,6 +2,7 @@
> > > >  # BaseCryptLib UnitTest built for execution in UEFI Shell.
> > > >
> > > >  #
> > > >
> > > >  # Copyright (c) Microsoft Corporation.<BR>
> > > >
> > > > +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > > >
> > > >  # SPDX-License-Identifier: BSD-2-Clause-Patent
> > > >
> > > >  ##
> > > >
> > > >
> > > >
> > > > @@ -36,6 +37,7 @@
> > > >    Pkcs7EkuTests.c
> > > >
> > > >    OaepEncryptTests.c
> > > >
> > > >    RsaPssTests.c
> > > >
> > > > +  ParallelhashTests.c
> > > >
> > > >
> > > >
> > > >  [Packages]
> > > >
> > > >    MdePkg/MdePkg.dec
> > > >
> > > > @@ -48,3 +50,7 @@
> > > >    UnitTestLib
> > > >
> > > >    PrintLib
> > > >
> > > >    BaseCryptLib
> > > >
> > > > +  PcdLib
> > > >
> > > > +
> > > >
> > > > +[Pcd]
> > > >
> > > > +  gEfiCryptoPkgTokenSpaceGuid.PcdParallelHashBlockNumber
> > > >
> > > > --
> > > > 2.26.2.windows.1


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

end of thread, other threads:[~2022-02-17  5:28 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-02-11  9:05 [PATCH v1] CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib Li, Zhihao
2022-02-15  6:08 ` Yao, Jiewen
2022-02-16  7:43   ` Li, Zhihao
2022-02-16  7:51     ` Yao, Jiewen
2022-02-16  8:23       ` Li, Zhihao
2022-02-17  5:28       ` Li, Zhihao

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