CryptoPkg: Add new hash algorithm ParallelHash256HashAll in BaseCryptLib.
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3596 Parallel hash function ParallelHash256HashAll, as defined in NIST's Special Publication 800-185, published December 2016. It utilizes multi-process to calculate the digest. Passed CI test. Onprotocol version code passed test. Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Jian J Wang <jian.j.wang@intel.com> Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com> Cc: Guomin Jiang <guomin.jiang@intel.com> Cc: Siyuan Fu <siyuan.fu@intel.com> Signed-off-by: Zhihao Li <zhihao.li@intel.com> Reviewed-by: Jiewen Yao <jiewen.yao@intel.com>
This commit is contained in:
282
CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
Normal file
282
CryptoPkg/Library/BaseCryptLib/Hash/CryptCShake256.c
Normal file
@@ -0,0 +1,282 @@
|
||||
/** @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);
|
||||
}
|
278
CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
Normal file
278
CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.c
Normal file
@@ -0,0 +1,278 @@
|
||||
/** @file
|
||||
ParallelHash Implementation.
|
||||
|
||||
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "CryptParallelHash.h"
|
||||
#include <Library/MmServicesTableLib.h>
|
||||
#include <Library/SynchronizationLib.h>
|
||||
|
||||
#define PARALLELHASH_CUSTOMIZATION "ParallelHash"
|
||||
|
||||
UINTN mBlockNum;
|
||||
UINTN mBlockSize;
|
||||
UINTN mLastBlockSize;
|
||||
UINT8 *mInput;
|
||||
UINTN mBlockResultSize;
|
||||
UINT8 *mBlockHashResult;
|
||||
BOOLEAN *mBlockIsCompleted;
|
||||
SPIN_LOCK *mSpinLockList;
|
||||
|
||||
/**
|
||||
Complete computation of digest of each block.
|
||||
|
||||
Each AP perform the function called by BSP.
|
||||
|
||||
@param[in] ProcedureArgument Argument of the procedure.
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
ParallelHashApExecute (
|
||||
IN VOID *ProcedureArgument
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
BOOLEAN Status;
|
||||
|
||||
for (Index = 0; Index < mBlockNum; Index++) {
|
||||
if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
|
||||
//
|
||||
// Completed, try next one.
|
||||
//
|
||||
if (mBlockIsCompleted[Index]) {
|
||||
ReleaseSpinLock (&mSpinLockList[Index]);
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Calculate CShake256 for this block.
|
||||
//
|
||||
Status = CShake256HashAll (
|
||||
mInput + Index * mBlockSize,
|
||||
(Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
|
||||
mBlockResultSize,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
mBlockHashResult + Index * mBlockResultSize
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
mBlockIsCompleted[Index] = TRUE;
|
||||
}
|
||||
|
||||
ReleaseSpinLock (&mSpinLockList[Index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Dispatch the block task to each AP in SMM mode.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
MmDispatchBlockToAP (
|
||||
VOID
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
for (Index = 0; Index < gMmst->NumberOfCpus; Index++) {
|
||||
if (Index != gMmst->CurrentlyExecutingCpu) {
|
||||
gMmst->MmStartupThisAp (ParallelHashApExecute, Index, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
|
||||
published December 2016.
|
||||
|
||||
@param[in] Input Pointer to the input message (X).
|
||||
@param[in] InputByteLen The number(>0) of input bytes provided for the input data.
|
||||
@param[in] BlockSize The size of each block (B).
|
||||
@param[out] Output Pointer to the output buffer.
|
||||
@param[in] OutputByteLen The desired number of output bytes (L).
|
||||
@param[in] Customization Pointer to the customization string (S).
|
||||
@param[in] CustomByteLen The length of the customization string in bytes.
|
||||
|
||||
@retval TRUE ParallelHash256 digest computation succeeded.
|
||||
@retval FALSE ParallelHash256 digest computation failed.
|
||||
@retval FALSE This interface is not supported.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ParallelHash256HashAll (
|
||||
IN CONST VOID *Input,
|
||||
IN UINTN InputByteLen,
|
||||
IN UINTN BlockSize,
|
||||
OUT VOID *Output,
|
||||
IN UINTN OutputByteLen,
|
||||
IN CONST VOID *Customization,
|
||||
IN UINTN CustomByteLen
|
||||
)
|
||||
{
|
||||
UINT8 EncBufB[sizeof (UINTN)+1];
|
||||
UINTN EncSizeB;
|
||||
UINT8 EncBufN[sizeof (UINTN)+1];
|
||||
UINTN EncSizeN;
|
||||
UINT8 EncBufL[sizeof (UINTN)+1];
|
||||
UINTN EncSizeL;
|
||||
UINTN Index;
|
||||
UINT8 *CombinedInput;
|
||||
UINTN CombinedInputSize;
|
||||
BOOLEAN AllCompleted;
|
||||
UINTN Offset;
|
||||
BOOLEAN ReturnValue;
|
||||
|
||||
if ((InputByteLen == 0) || (OutputByteLen == 0) || (BlockSize == 0)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((Input == NULL) || (Output == NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((CustomByteLen != 0) && (Customization == NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
mBlockSize = BlockSize;
|
||||
|
||||
//
|
||||
// Calculate block number n.
|
||||
//
|
||||
mBlockNum = InputByteLen % mBlockSize == 0 ? InputByteLen / mBlockSize : InputByteLen / mBlockSize + 1;
|
||||
|
||||
//
|
||||
// Set hash result size of each block in bytes.
|
||||
//
|
||||
mBlockResultSize = OutputByteLen;
|
||||
|
||||
//
|
||||
// Encode B, n, L to string and record size.
|
||||
//
|
||||
EncSizeB = LeftEncode (EncBufB, mBlockSize);
|
||||
EncSizeN = RightEncode (EncBufN, mBlockNum);
|
||||
EncSizeL = RightEncode (EncBufL, OutputByteLen * CHAR_BIT);
|
||||
|
||||
//
|
||||
// Allocate buffer for combined input (newX), Block completed flag and SpinLock.
|
||||
//
|
||||
CombinedInputSize = EncSizeB + EncSizeN + EncSizeL + mBlockNum * mBlockResultSize;
|
||||
CombinedInput = AllocateZeroPool (CombinedInputSize);
|
||||
mBlockIsCompleted = AllocateZeroPool (mBlockNum * sizeof (BOOLEAN));
|
||||
mSpinLockList = AllocatePool (mBlockNum * sizeof (SPIN_LOCK));
|
||||
if ((CombinedInput == NULL) || (mBlockIsCompleted == NULL) || (mSpinLockList == NULL)) {
|
||||
ReturnValue = FALSE;
|
||||
goto Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Fill LeftEncode(B).
|
||||
//
|
||||
CopyMem (CombinedInput, EncBufB, EncSizeB);
|
||||
|
||||
//
|
||||
// Prepare for parallel hash.
|
||||
//
|
||||
mBlockHashResult = CombinedInput + EncSizeB;
|
||||
mInput = (UINT8 *)Input;
|
||||
mLastBlockSize = InputByteLen % mBlockSize == 0 ? mBlockSize : InputByteLen % mBlockSize;
|
||||
|
||||
//
|
||||
// Initialize SpinLock for each result block.
|
||||
//
|
||||
for (Index = 0; Index < mBlockNum; Index++) {
|
||||
InitializeSpinLock (&mSpinLockList[Index]);
|
||||
}
|
||||
|
||||
//
|
||||
// Dispatch blocklist to each AP.
|
||||
//
|
||||
if (gMmst != NULL) {
|
||||
MmDispatchBlockToAP ();
|
||||
}
|
||||
|
||||
//
|
||||
// Wait until all block hash completed.
|
||||
//
|
||||
do {
|
||||
AllCompleted = TRUE;
|
||||
for (Index = 0; Index < mBlockNum; Index++) {
|
||||
if (AcquireSpinLockOrFail (&mSpinLockList[Index])) {
|
||||
if (!mBlockIsCompleted[Index]) {
|
||||
AllCompleted = FALSE;
|
||||
ReturnValue = CShake256HashAll (
|
||||
mInput + Index * mBlockSize,
|
||||
(Index == (mBlockNum - 1)) ? mLastBlockSize : mBlockSize,
|
||||
mBlockResultSize,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
mBlockHashResult + Index * mBlockResultSize
|
||||
);
|
||||
if (ReturnValue) {
|
||||
mBlockIsCompleted[Index] = TRUE;
|
||||
}
|
||||
|
||||
ReleaseSpinLock (&mSpinLockList[Index]);
|
||||
break;
|
||||
}
|
||||
|
||||
ReleaseSpinLock (&mSpinLockList[Index]);
|
||||
} else {
|
||||
AllCompleted = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (!AllCompleted);
|
||||
|
||||
//
|
||||
// Fill LeftEncode(n).
|
||||
//
|
||||
Offset = EncSizeB + mBlockNum * mBlockResultSize;
|
||||
CopyMem (CombinedInput + Offset, EncBufN, EncSizeN);
|
||||
|
||||
//
|
||||
// Fill LeftEncode(L).
|
||||
//
|
||||
Offset += EncSizeN;
|
||||
CopyMem (CombinedInput + Offset, EncBufL, EncSizeL);
|
||||
|
||||
ReturnValue = CShake256HashAll (
|
||||
CombinedInput,
|
||||
CombinedInputSize,
|
||||
OutputByteLen,
|
||||
PARALLELHASH_CUSTOMIZATION,
|
||||
AsciiStrLen (PARALLELHASH_CUSTOMIZATION),
|
||||
Customization,
|
||||
CustomByteLen,
|
||||
Output
|
||||
);
|
||||
|
||||
Exit:
|
||||
ZeroMem (CombinedInput, CombinedInputSize);
|
||||
|
||||
if (CombinedInput != NULL) {
|
||||
FreePool (CombinedInput);
|
||||
}
|
||||
|
||||
if (mSpinLockList != NULL) {
|
||||
FreePool ((VOID *)mSpinLockList);
|
||||
}
|
||||
|
||||
if (mBlockIsCompleted != NULL) {
|
||||
FreePool (mBlockIsCompleted);
|
||||
}
|
||||
|
||||
return ReturnValue;
|
||||
}
|
201
CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
Normal file
201
CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHash.h
Normal file
@@ -0,0 +1,201 @@
|
||||
/** @file
|
||||
ParallelHash related function and type declaration.
|
||||
|
||||
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
Licensed under the OpenSSL license (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
in the file LICENSE in the source distribution or at
|
||||
https://www.openssl.org/source/license.html
|
||||
|
||||
Copyright 2022 The eXtended Keccak Code Package (XKCP)
|
||||
https://github.com/XKCP/XKCP
|
||||
Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles Van Assche.
|
||||
Implementation by the designers, hereby denoted as "the implementer".
|
||||
For more information, feedback or questions, please refer to the Keccak Team website:
|
||||
https://keccak.team/
|
||||
To the extent possible under law, the implementer has waived all copyright
|
||||
and related or neighboring rights to the source code in this file.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
**/
|
||||
|
||||
#include "InternalCryptLib.h"
|
||||
|
||||
#define KECCAK1600_WIDTH 1600
|
||||
|
||||
//
|
||||
// This struct referring to m_sha3.c from opessl and modified its type name.
|
||||
//
|
||||
typedef struct {
|
||||
uint64_t A[5][5];
|
||||
size_t block_size; /* cached ctx->digest->block_size */
|
||||
size_t md_size; /* output length, variable in XOF */
|
||||
size_t num; /* used bytes in below buffer */
|
||||
unsigned char buf[KECCAK1600_WIDTH / 8 - 32];
|
||||
unsigned char pad;
|
||||
} Keccak1600_Ctx;
|
||||
|
||||
/**
|
||||
SHA3_absorb can be called multiple times, but at each invocation
|
||||
largest multiple of |r| out of |len| bytes are processed. Then
|
||||
remaining amount of bytes is returned. This is done to spare caller
|
||||
trouble of calculating the largest multiple of |r|. |r| can be viewed
|
||||
as blocksize. It is commonly (1600 - 256*n)/8, e.g. 168, 136, 104,
|
||||
72, but can also be (1600 - 448)/8 = 144. All this means that message
|
||||
padding and intermediate sub-block buffering, byte- or bitwise, is
|
||||
caller's responsibility.
|
||||
**/
|
||||
size_t
|
||||
SHA3_absorb (
|
||||
uint64_t A[5][5],
|
||||
const unsigned char *inp,
|
||||
size_t len,
|
||||
size_t r
|
||||
);
|
||||
|
||||
/**
|
||||
SHA3_squeeze is called once at the end to generate |out| hash value
|
||||
of |len| bytes.
|
||||
**/
|
||||
void
|
||||
SHA3_squeeze (
|
||||
uint64_t A[5][5],
|
||||
unsigned char *out,
|
||||
size_t len,
|
||||
size_t r
|
||||
);
|
||||
|
||||
/**
|
||||
Encode function from XKCP.
|
||||
|
||||
Encodes the input as a byte string in a way that can be unambiguously parsed
|
||||
from the beginning of the string by inserting the length of the byte string
|
||||
before the byte string representation of input.
|
||||
|
||||
@param[out] EncBuf Result of left encode.
|
||||
@param[in] Value Input of left encode.
|
||||
|
||||
@retval EncLen Size of encode result in bytes.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
LeftEncode (
|
||||
OUT UINT8 *EncBuf,
|
||||
IN UINTN Value
|
||||
);
|
||||
|
||||
/**
|
||||
Encode function from XKCP.
|
||||
|
||||
Encodes the input as a byte string in a way that can be unambiguously parsed
|
||||
from the end of the string by inserting the length of the byte string after
|
||||
the byte string representation of input.
|
||||
|
||||
@param[out] EncBuf Result of right encode.
|
||||
@param[in] Value Input of right encode.
|
||||
|
||||
@retval EncLen Size of encode result in bytes.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
RightEncode (
|
||||
OUT UINT8 *EncBuf,
|
||||
IN UINTN Value
|
||||
);
|
||||
|
||||
/**
|
||||
Keccak initial fuction.
|
||||
|
||||
Set up state with specified capacity.
|
||||
|
||||
@param[out] Context Pointer to the context being initialized.
|
||||
@param[in] Pad Delimited Suffix.
|
||||
@param[in] BlockSize Size of context block.
|
||||
@param[in] MessageDigestLen Size of message digest in bytes.
|
||||
|
||||
@retval 1 Initialize successfully.
|
||||
@retval 0 Fail to initialize.
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
KeccakInit (
|
||||
OUT Keccak1600_Ctx *Context,
|
||||
IN UINT8 Pad,
|
||||
IN UINTN BlockSize,
|
||||
IN UINTN MessageDigstLen
|
||||
);
|
||||
|
||||
/**
|
||||
Sha3 update fuction.
|
||||
|
||||
This function performs Sha3 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.
|
||||
|
||||
@param[in,out] Context Pointer to the Keccak context.
|
||||
@param[in] Data Pointer to the buffer containing the data to be hashed.
|
||||
@param[in] DataSize Size of Data buffer in bytes.
|
||||
|
||||
@retval 1 Update successfully.
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
Sha3Update (
|
||||
IN OUT Keccak1600_Ctx *Context,
|
||||
IN const VOID *Data,
|
||||
IN UINTN DataSize
|
||||
);
|
||||
|
||||
/**
|
||||
Completes computation of Sha3 message digest.
|
||||
|
||||
This function completes sha3 hash computation and retrieves the digest value into
|
||||
the specified memory. After this function has been called, the keccak context cannot
|
||||
be used again.
|
||||
|
||||
@param[in, out] Context Pointer to the keccak context.
|
||||
@param[out] MessageDigest Pointer to a buffer that receives the message digest.
|
||||
|
||||
@retval 1 Meaasge digest computation succeeded.
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
Sha3Final (
|
||||
IN OUT Keccak1600_Ctx *Context,
|
||||
OUT UINT8 *MessageDigest
|
||||
);
|
||||
|
||||
/**
|
||||
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
|
||||
);
|
40
CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
Normal file
40
CryptoPkg/Library/BaseCryptLib/Hash/CryptParallelHashNull.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/** @file
|
||||
ParallelHash Implementation which does not provide real capabilities.
|
||||
|
||||
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
**/
|
||||
|
||||
#include "InternalCryptLib.h"
|
||||
|
||||
/**
|
||||
Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185,
|
||||
published December 2016.
|
||||
|
||||
@param[in] Input Pointer to the input message (X).
|
||||
@param[in] InputByteLen The number(>0) of input bytes provided for the input data.
|
||||
@param[in] BlockSize The size of each block (B).
|
||||
@param[out] Output Pointer to the output buffer.
|
||||
@param[in] OutputByteLen The desired number of output bytes (L).
|
||||
@param[in] Customization Pointer to the customization string (S).
|
||||
@param[in] CustomByteLen The length of the customization string in bytes.
|
||||
|
||||
@retval FALSE This interface is not supported.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
ParallelHash256HashAll (
|
||||
IN CONST VOID *Input,
|
||||
IN UINTN InputByteLen,
|
||||
IN UINTN BlockSize,
|
||||
OUT VOID *Output,
|
||||
IN UINTN OutputByteLen,
|
||||
IN CONST VOID *Customization,
|
||||
IN UINTN CustomByteLen
|
||||
)
|
||||
{
|
||||
ASSERT (FALSE);
|
||||
return FALSE;
|
||||
}
|
166
CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
Normal file
166
CryptoPkg/Library/BaseCryptLib/Hash/CryptSha3.c
Normal file
@@ -0,0 +1,166 @@
|
||||
/** @file
|
||||
SHA3 realted functions from OpenSSL.
|
||||
|
||||
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
|
||||
Licensed under the OpenSSL license (the "License"). You may not use
|
||||
this file except in compliance with the License. You can obtain a copy
|
||||
in the file LICENSE in the source distribution or at
|
||||
https://www.openssl.org/source/license.html
|
||||
**/
|
||||
|
||||
#include "CryptParallelHash.h"
|
||||
|
||||
/**
|
||||
Keccak initial fuction.
|
||||
|
||||
Set up state with specified capacity.
|
||||
|
||||
@param[out] Context Pointer to the context being initialized.
|
||||
@param[in] Pad Delimited Suffix.
|
||||
@param[in] BlockSize Size of context block.
|
||||
@param[in] MessageDigestLen Size of message digest in bytes.
|
||||
|
||||
@retval 1 Initialize successfully.
|
||||
@retval 0 Fail to initialize.
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
KeccakInit (
|
||||
OUT Keccak1600_Ctx *Context,
|
||||
IN UINT8 Pad,
|
||||
IN UINTN BlockSize,
|
||||
IN UINTN MessageDigestLen
|
||||
)
|
||||
{
|
||||
if (BlockSize <= sizeof (Context->buf)) {
|
||||
memset (Context->A, 0, sizeof (Context->A));
|
||||
|
||||
Context->num = 0;
|
||||
Context->block_size = BlockSize;
|
||||
Context->md_size = MessageDigestLen;
|
||||
Context->pad = Pad;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Sha3 update fuction.
|
||||
|
||||
This function performs Sha3 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.
|
||||
|
||||
@param[in,out] Context Pointer to the Keccak context.
|
||||
@param[in] Data Pointer to the buffer containing the data to be hashed.
|
||||
@param[in] DataSize Size of Data buffer in bytes.
|
||||
|
||||
@retval 1 Update successfully.
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
Sha3Update (
|
||||
IN OUT Keccak1600_Ctx *Context,
|
||||
IN const VOID *Data,
|
||||
IN UINTN DataSize
|
||||
)
|
||||
{
|
||||
const UINT8 *DataCopy;
|
||||
UINTN BlockSize;
|
||||
UINTN Num;
|
||||
UINTN Rem;
|
||||
|
||||
DataCopy = Data;
|
||||
BlockSize = (UINT8)(Context->block_size);
|
||||
|
||||
if (DataSize == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((Num = Context->num) != 0) {
|
||||
//
|
||||
// process intermediate buffer
|
||||
//
|
||||
Rem = BlockSize - Num;
|
||||
|
||||
if (DataSize < Rem) {
|
||||
memcpy (Context->buf + Num, DataCopy, DataSize);
|
||||
Context->num += DataSize;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// We have enough data to fill or overflow the intermediate
|
||||
// buffer. So we append |Rem| bytes and process the block,
|
||||
// leaving the rest for later processing.
|
||||
//
|
||||
memcpy (Context->buf + Num, DataCopy, Rem);
|
||||
DataCopy += Rem;
|
||||
DataSize -= Rem;
|
||||
(void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
|
||||
Context->num = 0;
|
||||
// Context->buf is processed, Context->num is guaranteed to be zero.
|
||||
}
|
||||
|
||||
if (DataSize >= BlockSize) {
|
||||
Rem = SHA3_absorb (Context->A, DataCopy, DataSize, BlockSize);
|
||||
} else {
|
||||
Rem = DataSize;
|
||||
}
|
||||
|
||||
if (Rem > 0) {
|
||||
memcpy (Context->buf, DataCopy + DataSize - Rem, Rem);
|
||||
Context->num = Rem;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
Completes computation of Sha3 message digest.
|
||||
|
||||
This function completes sha3 hash computation and retrieves the digest value into
|
||||
the specified memory. After this function has been called, the keccak context cannot
|
||||
be used again.
|
||||
|
||||
@param[in, out] Context Pointer to the keccak context.
|
||||
@param[out] MessageDigest Pointer to a buffer that receives the message digest.
|
||||
|
||||
@retval 1 Meaasge digest computation succeeded.
|
||||
**/
|
||||
UINT8
|
||||
EFIAPI
|
||||
Sha3Final (
|
||||
IN OUT Keccak1600_Ctx *Context,
|
||||
OUT UINT8 *MessageDigest
|
||||
)
|
||||
{
|
||||
UINTN BlockSize;
|
||||
UINTN Num;
|
||||
|
||||
BlockSize = Context->block_size;
|
||||
Num = Context->num;
|
||||
|
||||
if (Context->md_size == 0) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Pad the data with 10*1. Note that |Num| can be |BlockSize - 1|
|
||||
// in which case both byte operations below are performed on
|
||||
// same byte.
|
||||
//
|
||||
memset (Context->buf + Num, 0, BlockSize - Num);
|
||||
Context->buf[Num] = Context->pad;
|
||||
Context->buf[BlockSize - 1] |= 0x80;
|
||||
|
||||
(void)SHA3_absorb (Context->A, Context->buf, BlockSize, BlockSize);
|
||||
|
||||
SHA3_squeeze (Context->A, MessageDigest, Context->md_size, BlockSize);
|
||||
|
||||
return 1;
|
||||
}
|
107
CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
Normal file
107
CryptoPkg/Library/BaseCryptLib/Hash/CryptXkcp.c
Normal file
@@ -0,0 +1,107 @@
|
||||
/** @file
|
||||
Encode realted functions from Xkcp.
|
||||
|
||||
Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
|
||||
SPDX-License-Identifier: BSD-2-Clause-Patent
|
||||
|
||||
Copyright 2022 The eXtended Keccak Code Package (XKCP)
|
||||
https://github.com/XKCP/XKCP
|
||||
Keccak, designed by Guido Bertoni, Joan Daemen, Michael Peeters and Gilles Van Assche.
|
||||
Implementation by the designers, hereby denoted as "the implementer".
|
||||
For more information, feedback or questions, please refer to the Keccak Team website:
|
||||
https://keccak.team/
|
||||
To the extent possible under law, the implementer has waived all copyright
|
||||
and related or neighboring rights to the source code in this file.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/
|
||||
|
||||
**/
|
||||
|
||||
#include "CryptParallelHash.h"
|
||||
|
||||
/**
|
||||
Encode function from XKCP.
|
||||
|
||||
Encodes the input as a byte string in a way that can be unambiguously parsed
|
||||
from the beginning of the string by inserting the length of the byte string
|
||||
before the byte string representation of input.
|
||||
|
||||
@param[out] EncBuf Result of left encode.
|
||||
@param[in] Value Input of left encode.
|
||||
|
||||
@retval EncLen Size of encode result in bytes.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
LeftEncode (
|
||||
OUT UINT8 *EncBuf,
|
||||
IN UINTN Value
|
||||
)
|
||||
{
|
||||
UINT32 BlockNum;
|
||||
UINT32 EncLen;
|
||||
UINT32 Index;
|
||||
UINTN ValueCopy;
|
||||
|
||||
for ( ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof (UINTN)); ++BlockNum, ValueCopy >>= 8 ) {
|
||||
//
|
||||
// Empty
|
||||
//
|
||||
}
|
||||
|
||||
if (BlockNum == 0) {
|
||||
BlockNum = 1;
|
||||
}
|
||||
|
||||
for (Index = 1; Index <= BlockNum; ++Index) {
|
||||
EncBuf[Index] = (UINT8)(Value >> (8 * (BlockNum - Index)));
|
||||
}
|
||||
|
||||
EncBuf[0] = (UINT8)BlockNum;
|
||||
EncLen = BlockNum + 1;
|
||||
|
||||
return EncLen;
|
||||
}
|
||||
|
||||
/**
|
||||
Encode function from XKCP.
|
||||
|
||||
Encodes the input as a byte string in a way that can be unambiguously parsed
|
||||
from the end of the string by inserting the length of the byte string after
|
||||
the byte string representation of input.
|
||||
|
||||
@param[out] EncBuf Result of right encode.
|
||||
@param[in] Value Input of right encode.
|
||||
|
||||
@retval EncLen Size of encode result in bytes.
|
||||
**/
|
||||
UINTN
|
||||
EFIAPI
|
||||
RightEncode (
|
||||
OUT UINT8 *EncBuf,
|
||||
IN UINTN Value
|
||||
)
|
||||
{
|
||||
UINT32 BlockNum;
|
||||
UINT32 EncLen;
|
||||
UINT32 Index;
|
||||
UINTN ValueCopy;
|
||||
|
||||
for (ValueCopy = Value, BlockNum = 0; ValueCopy && (BlockNum < sizeof (UINTN)); ++BlockNum, ValueCopy >>= 8) {
|
||||
//
|
||||
// Empty
|
||||
//
|
||||
}
|
||||
|
||||
if (BlockNum == 0) {
|
||||
BlockNum = 1;
|
||||
}
|
||||
|
||||
for (Index = 1; Index <= BlockNum; ++Index) {
|
||||
EncBuf[Index-1] = (UINT8)(Value >> (8 * (BlockNum-Index)));
|
||||
}
|
||||
|
||||
EncBuf[BlockNum] = (UINT8)BlockNum;
|
||||
EncLen = BlockNum + 1;
|
||||
|
||||
return EncLen;
|
||||
}
|
Reference in New Issue
Block a user