BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2545
The EVP interface should be used in place of discrete digest function calls. Cc: Jiewen Yao <jiewen....@intel.com> Cc: Jian J Wang <jian.j.w...@intel.com> Cc: Xiaoyu Lu <xiaoyux...@intel.com> Signed-off-by: Christopher J Zurcher <christopher.j.zurc...@intel.com> --- CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf | 1 + CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf | 1 + CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf | 1 + CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf | 1 + CryptoPkg/Include/Library/BaseCryptLib.h | 122 +++++++++++ CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMd.c | 228 ++++++++++++++++++++ 6 files changed, 354 insertions(+) diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf index 4aae2aba95..3968f29412 100644 --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf @@ -50,6 +50,7 @@ Pk/CryptAuthenticode.c Pk/CryptTs.c Pem/CryptPem.c + Evp/CryptEvpMd.c SysCall/CrtWrapper.c SysCall/TimerWrapper.c diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf index dc28e3a11d..d0b91716d0 100644 --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf @@ -57,6 +57,7 @@ Pk/CryptTsNull.c Pem/CryptPemNull.c Rand/CryptRandNull.c + Evp/CryptEvpMd.c SysCall/CrtWrapper.c SysCall/ConstantTimeClock.c diff --git a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf index 5005beed02..9f3accd35b 100644 --- a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf @@ -56,6 +56,7 @@ Pk/CryptAuthenticodeNull.c Pk/CryptTsNull.c Pem/CryptPem.c + Evp/CryptEvpMd.c SysCall/CrtWrapper.c SysCall/TimerWrapper.c diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf index 91ec3e03bf..420623cdc6 100644 --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf @@ -54,6 +54,7 @@ Pk/CryptAuthenticodeNull.c Pk/CryptTsNull.c Pem/CryptPem.c + Evp/CryptEvpMd.c SysCall/CrtWrapper.c SysCall/ConstantTimeClock.c diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h index ae9bde9e37..f3bf8aac0c 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -1012,6 +1012,128 @@ HmacSha256Final ( OUT UINT8 *HmacValue ); +//===================================================================================== +// EVP (Envelope) Primitive +//===================================================================================== + +/** + Allocates and initializes one EVP_MD_CTX context for subsequent EVP_MD use. + + @return Pointer to the EVP_MD_CTX context that has been initialized. + If the allocations fails, EvpMdNew() returns NULL. + +**/ +VOID * +EFIAPI +EvpMdNew ( + VOID + ); + +/** + Release the specified EVP_MD_CTX context. + + @param[in] EvpMdContext Pointer to the EVP_MD_CTX context to be released. + +**/ +VOID +EFIAPI +EvpMdFree ( + IN VOID *EvpMdContext + ); + +/** + Initializes user-supplied memory pointed to by EvpMdContext as EVP_MD_CTX + context for subsequent use. + + If EvpMdContext is NULL, then return FALSE. + If DigestName is NULL, then return FALSE. + + @param[out] EvpMdContext Pointer to EVP_MD_CTX context being initialized. + @param[in] DigestName Pointer to the digest name. + + @retval TRUE EVP_MD_CTX context initialization succeeded. + @retval FALSE EVP_MD_CTX context initialization failed. + +**/ +BOOLEAN +EFIAPI +EvpMdInit ( + OUT VOID *EvpMdContext, + IN CONST CHAR8 *DigestName + ); + +/** + Makes a copy of an existing EVP_MD context. + + If EvpMdContext is NULL, then return FALSE. + If NewEvpMdContext is NULL, then return FALSE. + + @param[in] EvpMdContext Pointer to EVP_MD context being copied. + @param[out] NewEvpMdContext Pointer to new EVP_MD context. + + @retval TRUE EVP_MD context copy succeeded. + @retval FALSE EVP_MD context copy failed. + +**/ +BOOLEAN +EFIAPI +EvpMdDuplicate ( + IN CONST VOID *EvpMdContext, + OUT VOID *NewEvpMdContext + ); + +/** + Digests the input data and updates EVP_MD context. + + This function performs EVP 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. + EVP_MD context should be already correctly initialized by EvpMdInit(), and should not + be finalized by EvpMdFinal(). Behavior with invalid context is undefined. + + If EvpMdContext is NULL, then return FALSE. + + @param[in, out] EvpMdContext Pointer to the EVP_MD context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE EVP data digest succeeded. + @retval FALSE EVP data digest failed. + +**/ +BOOLEAN +EFIAPI +EvpMdUpdate ( + IN OUT VOID *EvpMdContext, + IN CONST VOID *Data, + IN UINTN DataSize + ); + +/** + Completes computation of the EVP digest value. + + This function completes EVP hash computation and retrieves the digest value into + the specified memory. After this function has been called, the EVP context cannot + be used again. + EVP context should be already correctly initialized by EvpMdInit(), and should + not be finalized by EvpMdFinal(). Behavior with invalid EVP context is undefined. + + If EvpMdContext is NULL, then return FALSE. + If Digest is NULL, then return FALSE. + + @param[in, out] EvpMdContext Pointer to the EVP context. + @param[out] Digest Pointer to a buffer that receives the EVP digest value. + + @retval TRUE EVP digest computation succeeded. + @retval FALSE EVP digest computation failed. + +**/ +BOOLEAN +EFIAPI +EvpMdFinal ( + IN OUT VOID *EvpMdContext, + OUT UINT8 *DigestValue + ); + //===================================================================================== // Symmetric Cryptography Primitive //===================================================================================== diff --git a/CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMd.c b/CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMd.c new file mode 100644 index 0000000000..a38c300eb8 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMd.c @@ -0,0 +1,228 @@ +/** @file + EVP MD Wrapper Implementation for OpenSSL. + +Copyright (c) 2020, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include <openssl/evp.h> + +/** + Allocates and initializes one EVP_MD_CTX context for subsequent EVP_MD use. + + @return Pointer to the EVP_MD_CTX context that has been initialized. + If the allocations fails, EvpMdNew() returns NULL. + +**/ +VOID * +EFIAPI +EvpMdNew ( + VOID + ) +{ + // + // Allocates & Initializes EVP_MD_CTX Context by OpenSSL EVP_MD_CTX_new() + // + return (VOID *) EVP_MD_CTX_new (); +} + +/** + Release the specified EVP_MD_CTX context. + + @param[in] EvpMdContext Pointer to the EVP_MD_CTX context to be released. + +**/ +VOID +EFIAPI +EvpMdFree ( + IN VOID *EvpMdContext + ) +{ + // + // Free OpenSSL EVP_MD_CTX Context + // + EVP_MD_CTX_free ((EVP_MD_CTX *)EvpMdContext); +} + +/** + Initializes user-supplied memory pointed to by EvpMdContext as EVP_MD_CTX + context for subsequent use. + + If EvpMdContext is NULL, then return FALSE. + If DigestName is NULL, then return FALSE. + + @param[out] EvpMdContext Pointer to EVP_MD_CTX context being initialized. + @param[in] DigestName Pointer to the digest name. + + @retval TRUE EVP_MD_CTX context initialization succeeded. + @retval FALSE EVP_MD_CTX context initialization failed. + +**/ +BOOLEAN +EFIAPI +EvpMdInit ( + OUT VOID *EvpMdContext, + IN CONST CHAR8 *DigestName + ) +{ + CONST EVP_MD *Digest; + + // + // Check input parameters. + // + if (EvpMdContext == NULL || DigestName == NULL) { + return FALSE; + } + + // + // OpenSSL EVP_MD Context Initialization + // + if (EVP_MD_CTX_reset ((EVP_MD_CTX *)EvpMdContext) != 1) { + return FALSE; + } + + Digest = EVP_get_digestbyname (DigestName); + if (Digest == NULL) { + return FALSE; + } + + if (EVP_DigestInit_ex ((EVP_MD_CTX *)EvpMdContext, Digest, NULL) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Makes a copy of an existing EVP_MD context. + + If EvpMdContext is NULL, then return FALSE. + If NewEvpMdContext is NULL, then return FALSE. + + @param[in] EvpMdContext Pointer to EVP_MD context being copied. + @param[out] NewEvpMdContext Pointer to new EVP_MD context. + + @retval TRUE EVP_MD context copy succeeded. + @retval FALSE EVP_MD context copy failed. + +**/ +BOOLEAN +EFIAPI +EvpMdDuplicate ( + IN CONST VOID *EvpMdContext, + OUT VOID *NewEvpMdContext + ) +{ + // + // Check input parameters. + // + if (EvpMdContext == NULL || NewEvpMdContext == NULL) { + return FALSE; + } + + if (EVP_MD_CTX_copy ((EVP_MD_CTX *)NewEvpMdContext, (EVP_MD_CTX *)EvpMdContext) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Digests the input data and updates EVP_MD context. + + This function performs EVP 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. + EVP_MD context should be already correctly initialized by EvpMdInit(), and should not + be finalized by EvpMdFinal(). Behavior with invalid context is undefined. + + If EvpMdContext is NULL, then return FALSE. + + @param[in, out] EvpMdContext Pointer to the EVP_MD context. + @param[in] Data Pointer to the buffer containing the data to be digested. + @param[in] DataSize Size of Data buffer in bytes. + + @retval TRUE EVP data digest succeeded. + @retval FALSE EVP data digest failed. + +**/ +BOOLEAN +EFIAPI +EvpMdUpdate ( + IN OUT VOID *EvpMdContext, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + // + // Check input parameters. + // + if (EvpMdContext == NULL) { + return FALSE; + } + + // + // Check invalid parameters, in case only DataLength was checked in OpenSSL + // + if (Data == NULL && DataSize != 0) { + return FALSE; + } + + // + // OpenSSL EVP digest update + // + if (EVP_DigestUpdate ((EVP_MD_CTX *)EvpMdContext, Data, DataSize) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Completes computation of the EVP digest value. + + This function completes EVP hash computation and retrieves the digest value into + the specified memory. After this function has been called, the EVP context cannot + be used again. + EVP context should be already correctly initialized by EvpMdInit(), and should + not be finalized by EvpMdFinal(). Behavior with invalid EVP context is undefined. + + If EvpMdContext is NULL, then return FALSE. + If Digest is NULL, then return FALSE. + + @param[in, out] EvpMdContext Pointer to the EVP context. + @param[out] Digest Pointer to a buffer that receives the EVP digest value. + + @retval TRUE EVP digest computation succeeded. + @retval FALSE EVP digest computation failed. + +**/ +BOOLEAN +EFIAPI +EvpMdFinal ( + IN OUT VOID *EvpMdContext, + OUT UINT8 *DigestValue + ) +{ + UINT32 Length; + + // + // Check input parameters. + // + if (EvpMdContext == NULL || DigestValue == NULL) { + return FALSE; + } + + // + // OpenSSL EVP digest finalization + // + if (EVP_DigestFinal_ex ((EVP_MD_CTX *)EvpMdContext, DigestValue, &Length) != 1) { + return FALSE; + } + if (EVP_MD_CTX_reset ((EVP_MD_CTX *)EvpMdContext) != 1) { + return FALSE; + } + + return TRUE; +} -- 2.28.0.windows.1 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#64135): https://edk2.groups.io/g/devel/message/64135 Mute This Topic: https://groups.io/mt/76159838/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-