From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga06.intel.com (mga06.intel.com [134.134.136.31]) by mx.groups.io with SMTP id smtpd.web11.3159.1600131479614931624 for ; Mon, 14 Sep 2020 17:57:59 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.31, mailfrom: christopher.j.zurcher@intel.com) IronPort-SDR: wH2U6iuv0mB4gn7ygpoVZgeaj0JyS05sXAbRJHcy7MZlUAJxZvFH2LuLsWow5FRBe1SHE+6bep JPJRaLKjNYlg== X-IronPort-AV: E=McAfee;i="6000,8403,9744"; a="220738220" X-IronPort-AV: E=Sophos;i="5.76,427,1592895600"; d="scan'208";a="220738220" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga003.jf.intel.com ([10.7.209.27]) by orsmga104.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Sep 2020 17:57:58 -0700 IronPort-SDR: J2fOjEuWRcNI/SdAvw+CkXpbeX+EOHofDnf8dC9ZbLDnC5ZT9r3NawfWaWPeVex3OmhBpeQV8/ APnINtxaGRTg== X-IronPort-AV: E=Sophos;i="5.76,427,1592895600"; d="scan'208";a="301949618" Received: from cjzurch-desk.amr.corp.intel.com ([10.9.70.181]) by orsmga003-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 14 Sep 2020 17:57:58 -0700 From: "Zurcher, Christopher J" To: devel@edk2.groups.io Cc: Laszlo Ersek , Jiewen Yao , Jian J Wang , Xiaoyu Lu Subject: [PATCH v2 1/3] CryptoPkg/BaseCryptLib: Add EVP (Envelope) Digest interface Date: Mon, 14 Sep 2020 17:57:47 -0700 Message-Id: <20200915005749.5331-2-christopher.j.zurcher@intel.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200915005749.5331-1-christopher.j.zurcher@intel.com> References: <20200915005749.5331-1-christopher.j.zurcher@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2545 The EVP interface should be used in place of discrete digest function calls. Cc: Laszlo Ersek Cc: Jiewen Yao Cc: Jian J Wang Cc: Xiaoyu Lu Signed-off-by: Christopher J Zurcher --- 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/Library/BaseCryptLibNull/BaseCryptLibNull.inf | 1 + CryptoPkg/Include/Library/BaseCryptLib.h | 125 ++++++++++ CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMd.c | 253 ++++++++++++++++++++ CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMdNull.c | 124 ++++++++++ 8 files changed, 507 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/Library/BaseCryptLibNull/BaseCryptLibNull.inf b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf index 689af4fedd..542ac2e2e1 100644 --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf @@ -50,6 +50,7 @@ Pk/CryptTsNull.c Pem/CryptPemNull.c Rand/CryptRandNull.c + Evp/CryptEvpMdNull.c [Packages] MdePkg/MdePkg.dec diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h index ae9bde9e37..a92e5e5766 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -1012,6 +1012,131 @@ HmacSha256Final ( OUT UINT8 *HmacValue ); +//===================================================================================== +// EVP (Envelope) Primitive +//===================================================================================== + +/** + Allocates and initializes one EVP_MD_CTX context for subsequent EVP_MD use. + + If DigestName is NULL, then return FALSE. + + @param[in] DigestName Pointer to the digest name. + + @return Pointer to the EVP_MD_CTX context that has been allocated and initialized. + If DigestName is invalid, returns NULL. + If the allocations fails, returns NULL. + If initialization fails, returns NULL. + +**/ +VOID * +EFIAPI +EvpMdInit ( + 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. + If Data is NULL and DataSize is not zero, 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. + Releases the specified EVP_MD_CTX context. + + 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 DigestValue is NULL, free the Context 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 + ); + +/** + Computes the message digest of an input data buffer. + + This function performs the message digest of a given data buffer, and places + the digest value into the specified memory. + + If DigestName is NULL, return FALSE. + If Data is NULL and DataSize is not zero, return FALSE. + If HashValue is NULL, return FALSE. + + @param[in] DigestName Pointer to the digest name. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the digest value. + + @retval TRUE Digest computation succeeded. + @retval FALSE Digest computation failed. + +**/ +BOOLEAN +EFIAPI +EvpMdHashAll ( + IN CONST CHAR8 *DigestName, + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ); + //===================================================================================== // 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..3ec7b33b67 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMd.c @@ -0,0 +1,253 @@ +/** @file + EVP MD Wrapper Implementation for OpenSSL. + +Copyright (c) 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include + +/** + Allocates and initializes one EVP_MD_CTX context for subsequent EVP_MD use. + + If DigestName is NULL, then return FALSE. + + @param[in] DigestName Pointer to the digest name. + + @return Pointer to the EVP_MD_CTX context that has been allocated and initialized. + If DigestName is invalid, returns NULL. + If the allocations fails, returns NULL. + If initialization fails, returns NULL. + +**/ +VOID * +EFIAPI +EvpMdInit ( + IN CONST CHAR8 *DigestName + ) +{ + EVP_MD *Digest; + VOID *EvpMdContext; + + // + // Check input parameters. + // + if (DigestName == NULL) { + return NULL; + } + + // + // Allocate EVP_MD_CTX Context + // + EvpMdContext = EVP_MD_CTX_new (); + if (EvpMdContext == NULL) { + return NULL; + } + + Digest = EVP_get_digestbyname (DigestName); + if (Digest == NULL) { + return NULL; + } + + // + // Initialize Context + // + if (EVP_DigestInit_ex (EvpMdContext, Digest, NULL) != 1) { + EVP_MD_CTX_free (EvpMdContext); + return NULL; + } + + return EvpMdContext; +} + +/** + 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 (NewEvpMdContext, 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. + If Data is NULL and DataSize is not zero, 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 (EvpMdContext, Data, DataSize) != 1) { + return FALSE; + } + + return TRUE; +} + +/** + Completes computation of the EVP digest value. + Releases the specified EVP_MD_CTX context. + + 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 DigestValue is NULL, free the Context 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; + BOOLEAN ReturnValue; + + ReturnValue = TRUE; + + // + // Check input parameters. + // + if (EvpMdContext == NULL) { + return FALSE; + } + if (DigestValue == NULL) { + EVP_MD_CTX_free (EvpMdContext); + return FALSE; + } + + // + // OpenSSL EVP digest finalization + // + if (EVP_DigestFinal_ex (EvpMdContext, DigestValue, &Length) != 1) { + ReturnValue = FALSE; + } + + // + // Free OpenSSL EVP_MD_CTX Context + // + EVP_MD_CTX_free (EvpMdContext); + + return ReturnValue; +} + +/** + Computes the message digest of an input data buffer. + + This function performs the message digest of a given data buffer, and places + the digest value into the specified memory. + + If DigestName is NULL, return FALSE. + If Data is NULL and DataSize is not zero, return FALSE. + If HashValue is NULL, return FALSE. + + @param[in] DigestName Pointer to the digest name. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the digest value. + + @retval TRUE Digest computation succeeded. + @retval FALSE Digest computation failed. + +**/ +BOOLEAN +EFIAPI +EvpMdHashAll ( + IN CONST CHAR8 *DigestName, + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + BOOLEAN Result; + VOID *EvpMdContext; + + EvpMdContext = EvpMdInit (DigestName); + if (EvpMdContext == NULL) { + return FALSE; + } + + Result = EvpMdUpdate (EvpMdContext, Data, DataSize); + if (Result == FALSE) { + EvpMdFinal (EvpMdContext, NULL); + return FALSE; + } + + Result = EvpMdFinal (EvpMdContext, HashValue); + + return Result; +} diff --git a/CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMdNull.c b/CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMdNull.c new file mode 100644 index 0000000000..b9b0bd1572 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Evp/CryptEvpMdNull.c @@ -0,0 +1,124 @@ +/** @file + EVP MD Wrapper Null Library. + +Copyright (c) 2020, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +/** + Allocates and initializes one EVP_MD_CTX context for subsequent EVP_MD use. + + Return FALSE to indicate this interface is not supported. + + @param[in] DigestName Pointer to the digest name. + + @return NULL This interface is not supported. + +**/ +VOID * +EFIAPI +EvpMdInit ( + IN CONST CHAR8 *DigestName + ) +{ + ASSERT (FALSE); + return NULL; +} + +/** + Makes a copy of an existing EVP_MD context. + + Return FALSE to indicate this interface is not supported. + + @param[in] EvpMdContext Pointer to EVP_MD context being copied. + @param[out] NewEvpMdContext Pointer to new EVP_MD context. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +EvpMdDuplicate ( + IN CONST VOID *EvpMdContext, + OUT VOID *NewEvpMdContext + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Digests the input data and updates EVP_MD context. + + Return FALSE to indicate this interface is not supported. + + @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 FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +EvpMdUpdate ( + IN OUT VOID *EvpMdContext, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Completes computation of the EVP digest value. + Releases the specified EVP_MD_CTX context. + + Return FALSE to indicate this interface is not supported. + + @param[in, out] EvpMdContext Pointer to the EVP context. + @param[out] Digest Pointer to a buffer that receives the EVP digest value. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +EvpMdFinal ( + IN OUT VOID *EvpMdContext, + OUT UINT8 *DigestValue + ) +{ + ASSERT (FALSE); + return FALSE; +} + +/** + Computes the message digest of an input data buffer. + + Return FALSE to indicate this interface is not supported. + + @param[in] DigestName Pointer to the digest name. + @param[in] Data Pointer to the buffer containing the data to be hashed. + @param[in] DataSize Size of Data buffer in bytes. + @param[out] HashValue Pointer to a buffer that receives the digest value. + + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +EvpMdHashAll ( + IN CONST CHAR8 *DigestName, + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + ASSERT (FALSE); + return FALSE; +} -- 2.28.0.windows.1