| /** @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, 0); | |
| return 1; | |
| } |