--- /dev/null
+/** @file\r
+ SHA3 realted functions from OpenSSL.\r
+\r
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.\r
+Licensed under the OpenSSL license (the "License"). You may not use\r
+this file except in compliance with the License. You can obtain a copy\r
+in the file LICENSE in the source distribution or at\r
+https://www.openssl.org/source/license.html\r
+**/\r
+\r
+#include "CryptParallelHash.h"\r
+\r
+/**\r
+ Keccak initial fuction.\r
+\r
+ Set up state with specified capacity.\r
+\r
+ @param[out] Context Pointer to the context being initialized.\r
+ @param[in] Pad Delimited Suffix.\r
+ @param[in] BlockSize Size of context block.\r
+ @param[in] MessageDigestLen Size of message digest in bytes.\r
+\r
+ @retval 1 Initialize successfully.\r
+ @retval 0 Fail to initialize.\r
+**/\r
+UINT8\r
+EFIAPI\r
+KeccakInit (\r
+ OUT Keccak1600_Ctx *Context,\r
+ IN UINT8 Pad,\r
+ IN UINTN BlockSize,\r
+ IN UINTN MessageDigestLen\r
+ )\r
+{\r
+ if (BlockSize <= sizeof (Context->buf)) {\r
+ memset (Context->A, 0, sizeof (Context->A));\r
+\r
+ Context->num = 0;\r
+ Context->block_size = BlockSize;\r
+ Context->md_size = MessageDigestLen;\r
+ Context->pad = Pad;\r
+\r
+ return 1;\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+/**\r
+ Sha3 update fuction.\r
+\r
+ This function performs Sha3 digest on a data buffer of the specified size.\r
+ It can be called multiple times to compute the digest of long or discontinuous data streams.\r
+\r
+ @param[in,out] Context Pointer to the Keccak context.\r
+ @param[in] Data Pointer to the buffer containing the data to be hashed.\r
+ @param[in] DataSize Size of Data buffer in bytes.\r
+\r
+ @retval 1 Update successfully.\r
+**/\r
+UINT8\r
+EFIAPI\r
+Sha3Update (\r
+ IN OUT Keccak1600_Ctx *Context,\r
+ IN const VOID *Data,\r
+ IN UINTN DataSize\r
+ )\r
+{\r
+ const UINT8 *DataCopy;\r
+ UINTN BlockSize;\r
+ UINTN Num;\r
+ UINTN Rem;\r
+\r
+ DataCopy = Data;\r
+ BlockSize = (UINT8)(Context->block_size);\r
+\r
+ if (DataSize == 0) {\r
+ return 1;\r
+ }\r
+\r
+ if ((Num = Context->num) != 0) {\r
+ //\r
+ // process intermediate buffer\r
+ //\r
+ Rem = BlockSize - Num;\r
+\r
+ if (DataSize < Rem) {\r
+ memcpy (Context->buf + Num, DataCopy, DataSize);\r
+ Context->num += DataSize;\r
+ return 1;\r
+ }\r
+\r
+ //\r
+ // We have enough data to fill or overflow the intermediate\r
+ // buffer. So we append |Rem| bytes and process the block,\r
+ // leaving the rest for later processing.\r
+ //\r
+ memcpy (Context->buf + Num, DataCopy, Rem);\r
+ DataCopy += Rem;\r
+ DataSize -= Rem;\r
+ (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);\r
+ Context->num = 0;\r
+ // Context->buf is processed, Context->num is guaranteed to be zero.\r
+ }\r
+\r
+ if (DataSize >= BlockSize) {\r
+ Rem = SHA3_absorb (Context->A, DataCopy, DataSize, BlockSize);\r
+ } else {\r
+ Rem = DataSize;\r
+ }\r
+\r
+ if (Rem > 0) {\r
+ memcpy (Context->buf, DataCopy + DataSize - Rem, Rem);\r
+ Context->num = Rem;\r
+ }\r
+\r
+ return 1;\r
+}\r
+\r
+/**\r
+ Completes computation of Sha3 message digest.\r
+\r
+ This function completes sha3 hash computation and retrieves the digest value into\r
+ the specified memory. After this function has been called, the keccak context cannot\r
+ be used again.\r
+\r
+ @param[in, out] Context Pointer to the keccak context.\r
+ @param[out] MessageDigest Pointer to a buffer that receives the message digest.\r
+\r
+ @retval 1 Meaasge digest computation succeeded.\r
+**/\r
+UINT8\r
+EFIAPI\r
+Sha3Final (\r
+ IN OUT Keccak1600_Ctx *Context,\r
+ OUT UINT8 *MessageDigest\r
+ )\r
+{\r
+ UINTN BlockSize;\r
+ UINTN Num;\r
+\r
+ BlockSize = Context->block_size;\r
+ Num = Context->num;\r
+\r
+ if (Context->md_size == 0) {\r
+ return 1;\r
+ }\r
+\r
+ //\r
+ // Pad the data with 10*1. Note that |Num| can be |BlockSize - 1|\r
+ // in which case both byte operations below are performed on\r
+ // same byte.\r
+ //\r
+ memset (Context->buf + Num, 0, BlockSize - Num);\r
+ Context->buf[Num] = Context->pad;\r
+ Context->buf[BlockSize - 1] |= 0x80;\r
+\r
+ (void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);\r
+\r
+ SHA3_squeeze (Context->A, MessageDigest, Context->md_size, BlockSize);\r
+\r
+ return 1;\r
+}\r