]> git.proxmox.com Git - mirror_edk2.git/blobdiff - CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Hash / CryptSha3.c
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
new file mode 100644 (file)
index 0000000..6abafc3
--- /dev/null
@@ -0,0 +1,166 @@
+/** @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