]> git.proxmox.com Git - mirror_edk2.git/blobdiff - CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
[mirror_edk2.git] / CryptoPkg / Library / BaseCryptLib / Hash / CryptCShake256.c
diff --git a/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c b/CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
new file mode 100644 (file)
index 0000000..2a9eaf9
--- /dev/null
@@ -0,0 +1,282 @@
+/** @file\r
+  cSHAKE-256 Digest Wrapper Implementations.\r
+\r
+Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
+\r
+**/\r
+\r
+#include "CryptParallelHash.h"\r
+\r
+#define  CSHAKE256_SECURITY_STRENGTH  256\r
+#define  CSHAKE256_RATE_IN_BYTES      136\r
+\r
+CONST CHAR8  mZeroPadding[CSHAKE256_RATE_IN_BYTES] = { 0 };\r
+\r
+/**\r
+  CShake256 initial function.\r
+\r
+  Initializes user-supplied memory pointed by CShake256Context as cSHAKE-256 hash context for\r
+  subsequent use.\r
+\r
+  @param[out] CShake256Context  Pointer to cSHAKE-256 context being initialized.\r
+  @param[in]  OutputLen         The desired number of output length in bytes.\r
+  @param[in]  Name              Pointer to the function name string.\r
+  @param[in]  NameLen           The length of the function name in bytes.\r
+  @param[in]  Customization     Pointer to the customization string.\r
+  @param[in]  CustomizationLen  The length of the customization string in bytes.\r
+\r
+  @retval TRUE   cSHAKE-256 context initialization succeeded.\r
+  @retval FALSE  cSHAKE-256 context initialization failed.\r
+  @retval FALSE  This interface is not supported.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+CShake256Init (\r
+  OUT  VOID        *CShake256Context,\r
+  IN   UINTN       OutputLen,\r
+  IN   CONST VOID  *Name,\r
+  IN   UINTN       NameLen,\r
+  IN   CONST VOID  *Customization,\r
+  IN   UINTN       CustomizationLen\r
+  )\r
+{\r
+  BOOLEAN  Status;\r
+  UINT8    EncBuf[sizeof (UINTN) + 1];\r
+  UINTN    EncLen;\r
+  UINTN    AbsorbLen;\r
+  UINTN    PadLen;\r
+\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if ((CShake256Context == NULL) || (OutputLen == 0) || ((NameLen != 0) && (Name == NULL)) || ((CustomizationLen != 0) && (Customization == NULL))) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Initialize KECCAK context with pad value and block size.\r
+  //\r
+  if ((NameLen == 0) && (CustomizationLen == 0)) {\r
+    //\r
+    // When N and S are both empty strings, cSHAKE(X, L, N, S) is equivalent to\r
+    // SHAKE as defined in FIPS 202.\r
+    //\r
+    Status = (BOOLEAN)KeccakInit (\r
+                        (Keccak1600_Ctx *)CShake256Context,\r
+                        '\x1f',\r
+                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,\r
+                        OutputLen\r
+                        );\r
+\r
+    return Status;\r
+  } else {\r
+    Status = (BOOLEAN)KeccakInit (\r
+                        (Keccak1600_Ctx *)CShake256Context,\r
+                        '\x04',\r
+                        (KECCAK1600_WIDTH - CSHAKE256_SECURITY_STRENGTH * 2) / 8,\r
+                        OutputLen\r
+                        );\r
+    if (!Status) {\r
+      return FALSE;\r
+    }\r
+\r
+    AbsorbLen = 0;\r
+    //\r
+    // Absorb Absorb bytepad(.., rate).\r
+    //\r
+    EncLen = LeftEncode (EncBuf, CSHAKE256_RATE_IN_BYTES);\r
+    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, EncBuf, EncLen);\r
+    if (!Status) {\r
+      return FALSE;\r
+    }\r
+\r
+    AbsorbLen += EncLen;\r
+\r
+    //\r
+    // Absorb encode_string(N).\r
+    //\r
+    EncLen = LeftEncode (EncBuf, NameLen * 8);\r
+    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, EncBuf, EncLen);\r
+    if (!Status) {\r
+      return FALSE;\r
+    }\r
+\r
+    AbsorbLen += EncLen;\r
+    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, Name, NameLen);\r
+    if (!Status) {\r
+      return FALSE;\r
+    }\r
+\r
+    AbsorbLen += NameLen;\r
+\r
+    //\r
+    // Absorb encode_string(S).\r
+    //\r
+    EncLen = LeftEncode (EncBuf, CustomizationLen * 8);\r
+    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, EncBuf, EncLen);\r
+    if (!Status) {\r
+      return FALSE;\r
+    }\r
+\r
+    AbsorbLen += EncLen;\r
+    Status     = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, Customization, CustomizationLen);\r
+    if (!Status) {\r
+      return FALSE;\r
+    }\r
+\r
+    AbsorbLen += CustomizationLen;\r
+\r
+    //\r
+    // Absorb zero padding up to rate.\r
+    //\r
+    PadLen = CSHAKE256_RATE_IN_BYTES - AbsorbLen % CSHAKE256_RATE_IN_BYTES;\r
+    Status = (BOOLEAN)Sha3Update ((Keccak1600_Ctx *)CShake256Context, mZeroPadding, PadLen);\r
+    if (!Status) {\r
+      return FALSE;\r
+    }\r
+\r
+    return TRUE;\r
+  }\r
+}\r
+\r
+/**\r
+  Digests the input data and updates cSHAKE-256 context.\r
+\r
+  This function performs cSHAKE-256 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
+  cSHAKE-256 context should be already correctly initialized by CShake256Init(), and should not be finalized\r
+  by CShake256Final(). Behavior with invalid context is undefined.\r
+\r
+  @param[in, out]  CShake256Context   Pointer to the cSHAKE-256 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 TRUE   cSHAKE-256 data digest succeeded.\r
+  @retval FALSE  cSHAKE-256 data digest failed.\r
+  @retval FALSE  This interface is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+CShake256Update (\r
+  IN OUT  VOID        *CShake256Context,\r
+  IN      CONST VOID  *Data,\r
+  IN      UINTN       DataSize\r
+  )\r
+{\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if (CShake256Context == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Check invalid parameters, in case that only DataLength was checked in OpenSSL.\r
+  //\r
+  if ((Data == NULL) && (DataSize != 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  return (BOOLEAN)(Sha3Update ((Keccak1600_Ctx *)CShake256Context, Data, DataSize));\r
+}\r
+\r
+/**\r
+  Completes computation of the cSHAKE-256 digest value.\r
+\r
+  This function completes cSHAKE-256 hash computation and retrieves the digest value into\r
+  the specified memory. After this function has been called, the cSHAKE-256 context cannot\r
+  be used again.\r
+  cSHAKE-256 context should be already correctly initialized by CShake256Init(), and should not be\r
+  finalized by CShake256Final(). Behavior with invalid cSHAKE-256 context is undefined.\r
+\r
+  @param[in, out]  CShake256Context  Pointer to the cSHAKE-256 context.\r
+  @param[out]      HashValue         Pointer to a buffer that receives the cSHAKE-256 digest\r
+                                     value.\r
+\r
+  @retval TRUE   cSHAKE-256 digest computation succeeded.\r
+  @retval FALSE  cSHAKE-256 digest computation failed.\r
+  @retval FALSE  This interface is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+CShake256Final (\r
+  IN OUT  VOID   *CShake256Context,\r
+  OUT     UINT8  *HashValue\r
+  )\r
+{\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if ((CShake256Context == NULL) || (HashValue == NULL)) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // cSHAKE-256 Hash Finalization.\r
+  //\r
+  return (BOOLEAN)(Sha3Final ((Keccak1600_Ctx *)CShake256Context, HashValue));\r
+}\r
+\r
+/**\r
+  Computes the CSHAKE-256 message digest of a input data buffer.\r
+\r
+  This function performs the CSHAKE-256 message digest of a given data buffer, and places\r
+  the digest value into the specified memory.\r
+\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
+  @param[in]   OutputLen          Size of output in bytes.\r
+  @param[in]   Name               Pointer to the function name string.\r
+  @param[in]   NameLen            Size of the function name in bytes.\r
+  @param[in]   Customization      Pointer to the customization string.\r
+  @param[in]   CustomizationLen   Size of the customization string in bytes.\r
+  @param[out]  HashValue          Pointer to a buffer that receives the CSHAKE-256 digest\r
+                                  value.\r
+\r
+  @retval TRUE   CSHAKE-256 digest computation succeeded.\r
+  @retval FALSE  CSHAKE-256 digest computation failed.\r
+  @retval FALSE  This interface is not supported.\r
+\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+CShake256HashAll (\r
+  IN   CONST VOID  *Data,\r
+  IN   UINTN       DataSize,\r
+  IN   UINTN       OutputLen,\r
+  IN   CONST VOID  *Name,\r
+  IN   UINTN       NameLen,\r
+  IN   CONST VOID  *Customization,\r
+  IN   UINTN       CustomizationLen,\r
+  OUT  UINT8       *HashValue\r
+  )\r
+{\r
+  BOOLEAN         Status;\r
+  Keccak1600_Ctx  Ctx;\r
+\r
+  //\r
+  // Check input parameters.\r
+  //\r
+  if (HashValue == NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  if ((Data == NULL) && (DataSize != 0)) {\r
+    return FALSE;\r
+  }\r
+\r
+  Status = CShake256Init (&Ctx, OutputLen, Name, NameLen, Customization, CustomizationLen);\r
+  if (!Status) {\r
+    return FALSE;\r
+  }\r
+\r
+  Status = CShake256Update (&Ctx, Data, DataSize);\r
+  if (!Status) {\r
+    return FALSE;\r
+  }\r
+\r
+  return CShake256Final (&Ctx, HashValue);\r
+}\r