diff options
Diffstat (limited to 'src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c')
-rw-r--r-- | src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c | 152 |
1 files changed, 152 insertions, 0 deletions
diff --git a/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c new file mode 100644 index 00000000..4c25404c --- /dev/null +++ b/src/VBox/Devices/EFI/Firmware/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c @@ -0,0 +1,152 @@ +/** @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 +const +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. + Salt length should atleast be equal to digest length. + + @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. + @param[in] SaltLen Salt length for PSS encoding. + + @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, + IN UINT16 SaltLen + ) +{ + BOOLEAN Result; + EVP_PKEY *EvpRsaKey; + EVP_MD_CTX *EvpVerifyCtx; + EVP_PKEY_CTX *KeyCtx; + CONST EVP_MD *HashAlg; + + Result = FALSE; + EvpRsaKey = NULL; + EvpVerifyCtx = NULL; + KeyCtx = NULL; + 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; + } + if (SaltLen < DigestLen) { + return FALSE; + } + + HashAlg = GetEvpMD(DigestLen); + + if (HashAlg == NULL) { + return FALSE; + } + + EvpRsaKey = EVP_PKEY_new(); + if (EvpRsaKey == NULL) { + goto _Exit; + } + + EVP_PKEY_set1_RSA(EvpRsaKey, RsaContext); + + EvpVerifyCtx = EVP_MD_CTX_create(); + if (EvpVerifyCtx == NULL) { + goto _Exit; + } + + Result = EVP_DigestVerifyInit(EvpVerifyCtx, &KeyCtx, HashAlg, NULL, EvpRsaKey) > 0; + if (KeyCtx == NULL) { + goto _Exit; + } + + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_padding(KeyCtx, RSA_PKCS1_PSS_PADDING) > 0; + } + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_pss_saltlen(KeyCtx, SaltLen) > 0; + } + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_mgf1_md(KeyCtx, HashAlg) > 0; + } + if (Result) { + Result = EVP_DigestVerifyUpdate(EvpVerifyCtx, Message, (UINT32)MsgSize) > 0; + } + if (Result) { + Result = EVP_DigestVerifyFinal(EvpVerifyCtx, Signature, (UINT32)SigSize) > 0; + } + +_Exit : + if (EvpRsaKey != NULL) { + EVP_PKEY_free(EvpRsaKey); + } + if (EvpVerifyCtx != NULL) { + EVP_MD_CTX_destroy(EvpVerifyCtx); + } + + return Result; +} |