/** @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; | |
} |