From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mga18.intel.com (mga18.intel.com [134.134.136.126]) by mx.groups.io with SMTP id smtpd.web10.12116.1600217946492239432 for ; Tue, 15 Sep 2020 17:59:06 -0700 Authentication-Results: mx.groups.io; dkim=missing; spf=pass (domain: intel.com, ip: 134.134.136.126, mailfrom: christopher.j.zurcher@intel.com) IronPort-SDR: Ufhe0pK4FNjN8qlvGfGZ/C8sapODMFoQ01Zj2Ux8EKyT3U5gxoLgLJx2xx0rWASQLxcxMevKbq gVev8sbJ79tQ== X-IronPort-AV: E=McAfee;i="6000,8403,9745"; a="147129206" X-IronPort-AV: E=Sophos;i="5.76,430,1592895600"; d="scan'208";a="147129206" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by orsmga106.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 15 Sep 2020 17:59:05 -0700 IronPort-SDR: mskvcnYflbwqnlmU3SDEzWNeHDzGp786+hufJnBDQmRt8DkeJH7m3qvkib56yFXqHnVM8UCepS K3lzwKH1Zz7Q== X-IronPort-AV: E=Sophos;i="5.76,430,1592895600"; d="scan'208";a="483077548" 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; 15 Sep 2020 17:59:05 -0700 From: "Zurcher, Christopher J" To: devel@edk2.groups.io Cc: Laszlo Ersek , Jiewen Yao , Jian J Wang , Xiaoyu Lu Subject: [PATCH v3 2/3] CryptoPkg: Add EVP to Crypto Service driver interface Date: Tue, 15 Sep 2020 17:59:01 -0700 Message-Id: <20200916005902.6114-3-christopher.j.zurcher@intel.com> X-Mailer: git-send-email 2.28.0.windows.1 In-Reply-To: <20200916005902.6114-1-christopher.j.zurcher@intel.com> References: <20200916005902.6114-1-christopher.j.zurcher@intel.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2545 Cc: Laszlo Ersek Cc: Jiewen Yao Cc: Jian J Wang Cc: Xiaoyu Lu Signed-off-by: Christopher J Zurcher --- CryptoPkg/CryptoPkg.dsc | 3 + CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h | 10 ++ CryptoPkg/Private/Protocol/Crypto.h | 131 +++++++++++++++++ CryptoPkg/Driver/Crypto.c | 152 +++++++++++++++++++- CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c | 144 +++++++++++++++++++ 5 files changed, 439 insertions(+), 1 deletion(-) diff --git a/CryptoPkg/CryptoPkg.dsc b/CryptoPkg/CryptoPkg.dsc index 1af78468a1..af3fceb99f 100644 --- a/CryptoPkg/CryptoPkg.dsc +++ b/CryptoPkg/CryptoPkg.dsc @@ -159,6 +159,7 @@ gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Tls.Family | PCD_CRYPTO_SERVICE_ENABLE_FAMILY gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsSet.Family | PCD_CRYPTO_SERVICE_ENABLE_FAMILY gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.TlsGet.Family | PCD_CRYPTO_SERVICE_ENABLE_FAMILY + gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.EvpMd.Family | PCD_CRYPTO_SERVICE_ENABLE_FAMILY !endif !if $(CRYPTO_SERVICES) == MIN_PEI @@ -173,6 +174,7 @@ gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Rsa.Services.Free | TRUE gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Rsa.Services.SetKey | TRUE gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Pkcs.Services.Pkcs5HashPassword | TRUE + gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.EvpMd.Family | PCD_CRYPTO_SERVICE_ENABLE_FAMILY !endif !if $(CRYPTO_SERVICES) == MIN_DXE_MIN_SMM @@ -203,6 +205,7 @@ gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Aes.Services.Init | TRUE gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Aes.Services.CbcEncrypt | TRUE gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.Aes.Services.CbcDecrypt | TRUE + gEfiCryptoPkgTokenSpaceGuid.PcdCryptoServiceFamilyEnable.EvpMd.Family | PCD_CRYPTO_SERVICE_ENABLE_FAMILY !endif ################################################################################################### diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h index 44fb0262f4..b79c98d679 100644 --- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h +++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h @@ -288,6 +288,16 @@ typedef struct { } Services; UINT32 Family; } TlsGet; + union { + struct { + UINT8 Init:1; + UINT8 Duplicate:1; + UINT8 Update:1; + UINT8 Final:1; + UINT8 HashAll:1; + } Services; + UINT32 Family; + } EvpMd; } PCD_CRYPTO_SERVICE_FAMILY_ENABLE; #endif diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h index c399e0d67a..a3dffc0ce0 100644 --- a/CryptoPkg/Private/Protocol/Crypto.h +++ b/CryptoPkg/Private/Protocol/Crypto.h @@ -3434,6 +3434,131 @@ EFI_STATUS IN OUT UINTN *DataSize ); +/** + 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 as a NULL-terminated ASCII string. + Valid digest names are: + MD5, SHA1, SHA224, SHA256, SHA384, SHA512 + SHA3-224, SHA3-256, SHA3-384, SHA3-512 + SM3 + + @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. + +**/ +typedef +VOID * +(EFIAPI* EDKII_CRYPTO_EVPMD_INIT)( + 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. + +**/ +typedef +BOOLEAN +(EFIAPI* EDKII_CRYPTO_EVPMD_DUPLICATE)( + 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. + +**/ +typedef +BOOLEAN +(EFIAPI* EDKII_CRYPTO_EVPMD_UPDATE)( + 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. + +**/ +typedef +BOOLEAN +(EFIAPI* EDKII_CRYPTO_EVPMD_FINAL)( + 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. + +**/ +typedef +BOOLEAN +(EFIAPI* EDKII_CRYPTO_EVPMD_HASH_ALL)( + IN CONST CHAR8 *DigestName, + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ); + /// /// EDK II Crypto Protocol @@ -3619,6 +3744,12 @@ struct _EDKII_CRYPTO_PROTOCOL { EDKII_CRYPTO_TLS_GET_HOST_PUBLIC_CERT TlsGetHostPublicCert; EDKII_CRYPTO_TLS_GET_HOST_PRIVATE_KEY TlsGetHostPrivateKey; EDKII_CRYPTO_TLS_GET_CERT_REVOCATION_LIST TlsGetCertRevocationList; + /// Digest Envelope (EVP MD) + EDKII_CRYPTO_EVPMD_INIT EvpMdInit; + EDKII_CRYPTO_EVPMD_DUPLICATE EvpMdDuplicate; + EDKII_CRYPTO_EVPMD_UPDATE EvpMdUpdate; + EDKII_CRYPTO_EVPMD_FINAL EvpMdFinal; + EDKII_CRYPTO_EVPMD_HASH_ALL EvpMdHashAll; }; extern GUID gEdkiiCryptoProtocolGuid; diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c index d9096ea603..c50ac4a6da 100644 --- a/CryptoPkg/Driver/Crypto.c +++ b/CryptoPkg/Driver/Crypto.c @@ -4463,6 +4463,150 @@ CryptoServiceTlsGetCertRevocationList ( return CALL_BASECRYPTLIB (TlsGet.Services.CertRevocationList, TlsGetCertRevocationList, (Data, DataSize), EFI_UNSUPPORTED); } +//===================================================================================== +// 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 as a NULL-terminated ASCII string. + Valid digest names are: + MD5, SHA1, SHA224, SHA256, SHA384, SHA512 + SHA3-224, SHA3-256, SHA3-384, SHA3-512 + SM3 + + @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 +CryptoServiceEvpMdInit ( + IN CONST CHAR8 *DigestName + ) +{ + return CALL_BASECRYPTLIB (EvpMd.Services.Init, EvpMdInit, (DigestName), NULL); +} + +/** + 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 +CryptoServiceEvpMdDuplicate ( + IN CONST VOID *EvpMdContext, + OUT VOID *NewEvpMdContext + ) +{ + return CALL_BASECRYPTLIB (EvpMd.Services.Duplicate, EvpMdDuplicate, (EvpMdContext, NewEvpMdContext), FALSE); +} + +/** + 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 +CryptoServiceEvpMdUpdate ( + IN OUT VOID *EvpMdContext, + IN CONST VOID *Data, + IN UINTN DataSize + ) +{ + return CALL_BASECRYPTLIB (EvpMd.Services.Update, EvpMdUpdate, (EvpMdContext, Data, DataSize), FALSE); +} + +/** + 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 +CryptoServiceEvpMdFinal ( + IN OUT VOID *EvpMdContext, + OUT UINT8 *DigestValue + ) +{ + return CALL_BASECRYPTLIB (EvpMd.Services.Final, EvpMdFinal, (EvpMdContext, DigestValue), FALSE); +} + +/** + 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 +CryptoServiceEvpMdHashAll ( + IN CONST CHAR8 *DigestName, + IN CONST VOID *Data, + IN UINTN DataSize, + OUT UINT8 *HashValue + ) +{ + return CALL_BASECRYPTLIB (EvpMd.Services.HashAll, EvpMdHashAll, (DigestName, Data, DataSize, HashValue), FALSE); +} + const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = { /// Version CryptoServiceGetCryptoVersion, @@ -4663,5 +4807,11 @@ const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = { CryptoServiceTlsGetCaCertificate, CryptoServiceTlsGetHostPublicCert, CryptoServiceTlsGetHostPrivateKey, - CryptoServiceTlsGetCertRevocationList + CryptoServiceTlsGetCertRevocationList, + /// Digest Envelope (EVP MD) + CryptoServiceEvpMdInit, + CryptoServiceEvpMdDuplicate, + CryptoServiceEvpMdUpdate, + CryptoServiceEvpMdFinal, + CryptoServiceEvpMdHashAll }; diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c index 3f14c6d262..0a68d0682e 100644 --- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c +++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c @@ -3499,3 +3499,147 @@ TlsGetCertRevocationList ( { CALL_CRYPTO_SERVICE (TlsGetCertRevocationList, (Data, DataSize), EFI_UNSUPPORTED); } + +//===================================================================================== +// 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 as a NULL-terminated ASCII string. + Valid digest names are: + MD5, SHA1, SHA224, SHA256, SHA384, SHA512 + SHA3-224, SHA3-256, SHA3-384, SHA3-512 + SM3 + + @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 + ) +{ + CALL_CRYPTO_SERVICE (EvpMdInit, (DigestName), NULL); +} + +/** + 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 + ) +{ + CALL_CRYPTO_SERVICE (EvpMdDuplicate, (EvpMdContext, NewEvpMdContext), FALSE); +} + +/** + 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 + ) +{ + CALL_CRYPTO_SERVICE (EvpMdUpdate, (EvpMdContext, Data, DataSize), FALSE); +} + +/** + 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 + ) +{ + CALL_CRYPTO_SERVICE (EvpMdFinal, (EvpMdContext, DigestValue), FALSE); +} + +/** + 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 + ) +{ + CALL_CRYPTO_SERVICE (EvpMdHashAll, (DigestName, Data, DataSize, HashValue), FALSE); +} -- 2.28.0.windows.1