From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga09.intel.com (mga09.intel.com []) by mx.groups.io with SMTP id smtpd.web12.1156.1597281655421476218 for ; Wed, 12 Aug 2020 18:20:56 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=fail (domain: intel.com, ip: , mailfrom: christopher.j.zurcher@intel.com) IronPort-SDR: k8vCIa7ovcp0i7o0jR6WnzcVBxBQRm63Oe6Yzx8bj2kxZn/qt6ux9mWBolADY2dl+47WTybhQ1 F+7GCt/pfvdg== X-IronPort-AV: E=McAfee;i="6000,8403,9711"; a="155266567" X-IronPort-AV: E=Sophos;i="5.76,306,1592895600"; d="scan'208";a="155266567" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Aug 2020 18:20:53 -0700 IronPort-SDR: nI18eHByjMVPTyIVpkUrMWs0N2Iy0T7m7NjCfVRb9DGrXgzpIAtqap5NUfUpsYPFkk9Dl5RxXN Le0rS81zXo2Q== X-IronPort-AV: E=Sophos;i="5.76,306,1592895600"; d="scan'208";a="470035745" Received: from cjzurch-desk.amr.corp.intel.com ([10.9.70.181]) by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Aug 2020 18:20:52 -0700 From: "Zurcher, Christopher J" To: devel@edk2.groups.io Cc: Jiewen Yao , Jian J Wang , Xiaoyu Lu Subject: [PATCH 1/1] CryptoPkg/BaseCryptLib: Add EVP (Envelope) Digest interface Date: Wed, 12 Aug 2020 18:20:49 -0700 Message-Id: <20200813012049.7402-2-christopher.j.zurcher@intel.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200813012049.7402-1-christopher.j.zurcher@intel.com> References: <20200813012049.7402-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: 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/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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" +#include + +/** + 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