REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3314
This patch uses Openssl's EVP API's to perform RSASSA-PSS verification of a binary blob. Cc: Jiewen Yao <jiewen....@intel.com> Cc: Jian J Wang <jian.j.w...@intel.com> Cc: Xiaoyu Lu <xiaoyux...@intel.com> Cc: Guomin Jiang <guomin.ji...@intel.com> Signed-off-by: Sachin Agrawal <sachin.agra...@intel.com> --- CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c | 139 ++++++++++++++++++++ CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c | 43 ++++++ CryptoPkg/Include/Library/BaseCryptLib.h | 27 ++++ CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf | 1 + CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf | 1 + CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf | 1 + CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf | 1 + 7 files changed, 213 insertions(+) diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c new file mode 100644 index 000000000000..acf5eb689cd8 --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c @@ -0,0 +1,139 @@ +/** @file + RSA Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file implements following APIs which provide basic capabilities for RSA: + 1) RsaPssVerify + +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +#include <openssl/bn.h> +#include <openssl/rsa.h> +#include <openssl/objects.h> +#include <openssl/evp.h> + + +/** + Retrieve a pointer to EVP message digest object. + + @param[in] DigestLen Length of the message digest. + +**/ +static +EVP_MD* +GetEvpMD ( + IN UINT16 DigestLen + ) +{ + switch (DigestLen){ + case SHA256_DIGEST_SIZE: + return EVP_sha256(); + break; + case SHA384_DIGEST_SIZE: + return EVP_sha384(); + break; + case SHA512_DIGEST_SIZE: + return EVP_sha512(); + break; + default: + return NULL; + } +} + + +/** + Verifies the RSA signature with RSASSA-PSS signature scheme defined in RFC 8017. + Implementation determines salt length automatically from the signature encoding. + Mask generation function is the same as the message digest algorithm. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Message Pointer to octet message to be verified. + @param[in] MsgSize Size of the message in bytes. + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + @param[in] DigestLen Length of digest for RSA operation. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. + +**/ +BOOLEAN +EFIAPI +RsaPssVerify ( + IN VOID *RsaContext, + IN CONST UINT8 *Message, + IN UINTN MsgSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize, + IN UINT16 DigestLen + ) +{ + BOOLEAN Result; + EVP_PKEY *pEvpRsaKey = NULL; + EVP_MD_CTX *pEvpVerifyCtx = NULL; + EVP_PKEY_CTX *pKeyCtx = NULL; + CONST EVP_MD *HashAlg = NULL; + + if (RsaContext == NULL) { + return FALSE; + } + if (Message == NULL || MsgSize == 0 || MsgSize > INT_MAX) { + return FALSE; + } + if (Signature == NULL || SigSize == 0 || SigSize > INT_MAX) { + return FALSE; + } + + HashAlg = GetEvpMD(DigestLen); + + if (HashAlg == NULL) { + return FALSE; + } + + pEvpRsaKey = EVP_PKEY_new(); + if (pEvpRsaKey == NULL) { + goto _Exit; + } + + EVP_PKEY_set1_RSA(pEvpRsaKey, RsaContext); + + pEvpVerifyCtx = EVP_MD_CTX_create(); + if (pEvpVerifyCtx == NULL) { + goto _Exit; + } + + Result = EVP_DigestVerifyInit(pEvpVerifyCtx, &pKeyCtx, HashAlg, NULL, pEvpRsaKey) > 0; + if (pKeyCtx == NULL) { + goto _Exit; + } + + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING) > 0; + } + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_PSS_SALTLEN_AUTO) > 0; + } + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, HashAlg) > 0; + } + if (Result) { + Result = EVP_DigestVerifyUpdate(pEvpVerifyCtx, Message, (UINT32)MsgSize) > 0; + } + if (Result) { + Result = EVP_DigestVerifyFinal(pEvpVerifyCtx, Signature, (UINT32)SigSize) > 0; + } + +_Exit : + if (pEvpRsaKey) { + EVP_PKEY_free(pEvpRsaKey); + } + if (pEvpVerifyCtx) { + EVP_MD_CTX_destroy(pEvpVerifyCtx); + } + + return Result; +} diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c new file mode 100644 index 000000000000..8d84b4c1426c --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c @@ -0,0 +1,43 @@ +/** @file + RSA-PSS Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file does not provide real capabilities for following APIs in RSA handling: + 1) RsaPssVerify + +Copyright (c) 2021, Intel Corporation. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +/** + Verifies the RSA signature with RSASSA-PSS signature scheme defined in RFC 8017. + Implementation determines salt length automatically from the signature encoding. + Mask generation function is the same as the message digest algorithm. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Message Pointer to octet message to be verified. + @param[in] MsgSize Size of the message in bytes. + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + @param[in] DigestLen Length of digest for RSA operation. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. + +**/ +BOOLEAN +EFIAPI +RsaPssVerify ( + IN VOID *RsaContext, + IN CONST UINT8 *Message, + IN UINTN MsgSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize, + IN UINT16 DigestLen + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h index 496121e6a4ed..36d560b8d691 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -1363,6 +1363,33 @@ RsaPkcs1Verify ( IN UINTN SigSize ); +/** + Verifies the RSA signature with RSASSA-PSS signature scheme defined in RFC 8017. + Implementation determines salt length automatically from the signature encoding. + Mask generation function is the same as the message digest algorithm. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Message Pointer to octet message to be verified. + @param[in] MsgSize Size of the message in bytes. + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + @param[in] DigestLen Length of digest for RSA operation. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. + +**/ +BOOLEAN +EFIAPI +RsaPssVerify ( + IN VOID *RsaContext, + IN CONST UINT8 *Message, + IN UINTN MsgSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize, + IN UINT16 DigestLen + ); + /** Retrieve the RSA Private Key from the password-protected PEM key data. -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#74287): https://edk2.groups.io/g/devel/message/74287 Mute This Topic: https://groups.io/mt/82225508/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-