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