/** @file | |
cSHAKE-256 Digest Wrapper Implementations. | |
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR> | |
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); | |
} |