| /** @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 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; | |
| } |