summaryrefslogtreecommitdiff
path: root/CryptoPkg
diff options
context:
space:
mode:
authorWenxing Hou <wenxing.hou@intel.com>2024-04-07 15:21:48 +0800
committerLiming Gao <gaoliming@byosoft.com.cn>2024-05-27 17:24:30 +0800
commitb5412646db76cfc95b562699cb905befff7311d0 (patch)
tree57baa08e2e0745d66cd296be4c8b212ad9fde0bc /CryptoPkg
parente065735b1b5e7e0fede376c1b21240a950ae74ef (diff)
downloadedk2-b5412646db76cfc95b562699cb905befff7311d0.zip
edk2-b5412646db76cfc95b562699cb905befff7311d0.tar.gz
edk2-b5412646db76cfc95b562699cb905befff7311d0.tar.bz2
CryptoPkg: Add more RSA related functions based on Mbedtls
REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4177 Implement more RSA functions such as RsaPkcs1Sign based Mbedlts. Cc: Jiewen Yao <jiewen.yao@intel.com> Cc: Yi Li <yi1.li@intel.com> Signed-off-by: Wenxing Hou <wenxing.hou@intel.com> Reviewed-by: Yi Li <yi1.li@intel.com> Acked-by: Jiewen Yao <Jiewen.yao@intel.com>
Diffstat (limited to 'CryptoPkg')
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c278
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c352
-rw-r--r--CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c140
3 files changed, 770 insertions, 0 deletions
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c
new file mode 100644
index 0000000..61ccdd7
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs1Oaep.c
@@ -0,0 +1,278 @@
+/** @file
+ This file contains UEFI wrapper functions for RSA PKCS1v2 OAEP encryption routines.
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+ Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+#include <mbedtls/x509_crt.h>
+#include <Library/MemoryAllocationLib.h>
+
+/**
+ Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+ encrypted message in a newly allocated buffer.
+
+ Things that can cause a failure include:
+ - X509 key size does not match any known key size.
+ - Fail to parse X509 certificate.
+ - Fail to allocate an intermediate buffer.
+ - Null pointer provided for a non-optional parameter.
+ - Data size is too large for the provided key size (max size is a function of key size
+ and hash digest size).
+
+ @param[in] PublicKey A pointer to the DER-encoded X509 certificate that
+ will be used to encrypt the data.
+ @param[in] PublicKeySize Size of the X509 cert buffer.
+ @param[in] InData Data to be encrypted.
+ @param[in] InDataSize Size of the data buffer.
+ @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer
+ to be used when initializing the PRNG. NULL otherwise.
+ @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer.
+ 0 otherwise.
+ @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted
+ message.
+ @param[out] EncryptedDataSize Size of the encrypted message buffer.
+
+ @retval TRUE Encryption was successful.
+ @retval FALSE Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs1v2Encrypt (
+ IN CONST UINT8 *PublicKey,
+ IN UINTN PublicKeySize,
+ IN UINT8 *InData,
+ IN UINTN InDataSize,
+ IN CONST UINT8 *PrngSeed OPTIONAL,
+ IN UINTN PrngSeedSize OPTIONAL,
+ OUT UINT8 **EncryptedData,
+ OUT UINTN *EncryptedDataSize
+ )
+{
+ BOOLEAN Result;
+ UINT32 Ret;
+ UINT8 *OutData;
+ mbedtls_x509_crt CertContext;
+ mbedtls_rsa_context RsaContext;
+
+ //
+ // Check input parameters.
+ //
+ if ((PublicKey == NULL) || (InData == NULL) ||
+ (EncryptedData == NULL) || (EncryptedDataSize == NULL))
+ {
+ return FALSE;
+ }
+
+ //
+ // Check public key size.
+ //
+ if (PublicKeySize > UINT_MAX) {
+ //
+ // Public key size is too large for implementation.
+ //
+ return FALSE;
+ }
+
+ *EncryptedData = NULL;
+ *EncryptedDataSize = 0;
+ Result = FALSE;
+ OutData = NULL;
+
+ mbedtls_x509_crt_init (&CertContext);
+
+ if (mbedtls_x509_crt_parse_der (&CertContext, PublicKey, (UINT32)PublicKeySize) != 0) {
+ goto _Exit;
+ }
+
+ if (mbedtls_pk_get_type (&CertContext.pk) != MBEDTLS_PK_RSA) {
+ goto _Exit;
+ }
+
+ mbedtls_rsa_init (&RsaContext);
+ if (mbedtls_rsa_set_padding (&RsaContext, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_NONE) != 0) {
+ goto _Exit;
+ }
+
+ Ret = mbedtls_rsa_copy (&RsaContext, mbedtls_pk_rsa (CertContext.pk));
+ if (Ret != 0) {
+ goto _Exit;
+ }
+
+ *EncryptedDataSize = RsaContext.len;
+
+ //
+ // Allocate a buffer for the output data.
+ //
+ OutData = AllocateZeroPool (*EncryptedDataSize);
+ if (OutData == NULL) {
+ //
+ // Fail to allocate the output buffer.
+ //
+ goto _Exit;
+ }
+
+ Ret = mbedtls_rsa_pkcs1_encrypt (
+ &RsaContext,
+ MbedtlsRand,
+ NULL,
+ InDataSize,
+ InData,
+ OutData
+ );
+ if (Ret != 0) {
+ FreePool (OutData);
+ OutData = NULL;
+ goto _Exit;
+ }
+
+ *EncryptedData = OutData;
+ Result = TRUE;
+
+_Exit:
+ //
+ // Release Resources
+ //
+ if (&CertContext != NULL) {
+ mbedtls_x509_crt_free (&CertContext);
+ }
+
+ if (&RsaContext != NULL) {
+ mbedtls_rsa_free (&RsaContext);
+ }
+
+ return Result;
+}
+
+/**
+ Encrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+ encrypted message in a newly allocated buffer.
+
+ Things that can cause a failure include:
+ - X509 key size does not match any known key size.
+ - Fail to allocate an intermediate buffer.
+ - Null pointer provided for a non-optional parameter.
+ - Data size is too large for the provided key size (max size is a function of key size
+ and hash digest size).
+
+ @param[in] RsaContext A pointer to an RSA context created by RsaNew() and
+ provisioned with a public key using RsaSetKey().
+ @param[in] InData Data to be encrypted.
+ @param[in] InDataSize Size of the data buffer.
+ @param[in] PrngSeed [Optional] If provided, a pointer to a random seed buffer
+ to be used when initializing the PRNG. NULL otherwise.
+ @param[in] PrngSeedSize [Optional] If provided, size of the random seed buffer.
+ 0 otherwise.
+ @param[in] DigestLen [Optional] If provided, size of the hash used:
+ SHA1_DIGEST_SIZE
+ SHA256_DIGEST_SIZE
+ SHA384_DIGEST_SIZE
+ SHA512_DIGEST_SIZE
+ 0 to use default (SHA1)
+ @param[out] EncryptedData Pointer to an allocated buffer containing the encrypted
+ message.
+ @param[out] EncryptedDataSize Size of the encrypted message buffer.
+
+ @retval TRUE Encryption was successful.
+ @retval FALSE Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+RsaOaepEncrypt (
+ IN VOID *RsaContext,
+ IN UINT8 *InData,
+ IN UINTN InDataSize,
+ IN CONST UINT8 *PrngSeed OPTIONAL,
+ IN UINTN PrngSeedSize OPTIONAL,
+ IN UINT16 DigestLen OPTIONAL,
+ OUT UINT8 **EncryptedData,
+ OUT UINTN *EncryptedDataSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+ decrypted message in a newly allocated buffer.
+
+ Things that can cause a failure include:
+ - Fail to parse private key.
+ - Fail to allocate an intermediate buffer.
+ - Null pointer provided for a non-optional parameter.
+
+ @param[in] PrivateKey A pointer to the DER-encoded private key.
+ @param[in] PrivateKeySize Size of the private key buffer.
+ @param[in] EncryptedData Data to be decrypted.
+ @param[in] EncryptedDataSize Size of the encrypted buffer.
+ @param[out] OutData Pointer to an allocated buffer containing the encrypted
+ message.
+ @param[out] OutDataSize Size of the encrypted message buffer.
+
+ @retval TRUE Encryption was successful.
+ @retval FALSE Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs1v2Decrypt (
+ IN CONST UINT8 *PrivateKey,
+ IN UINTN PrivateKeySize,
+ IN UINT8 *EncryptedData,
+ IN UINTN EncryptedDataSize,
+ OUT UINT8 **OutData,
+ OUT UINTN *OutDataSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
+
+/**
+ Decrypts a blob using PKCS1v2 (RSAES-OAEP) schema. On success, will return the
+ decrypted message in a newly allocated buffer.
+
+ Things that can cause a failure include:
+ - Fail to parse private key.
+ - Fail to allocate an intermediate buffer.
+ - Null pointer provided for a non-optional parameter.
+
+ @param[in] RsaContext A pointer to an RSA context created by RsaNew() and
+ provisioned with a private key using RsaSetKey().
+ @param[in] EncryptedData Data to be decrypted.
+ @param[in] EncryptedDataSize Size of the encrypted buffer.
+ @param[in] DigestLen [Optional] If provided, size of the hash used:
+ SHA1_DIGEST_SIZE
+ SHA256_DIGEST_SIZE
+ SHA384_DIGEST_SIZE
+ SHA512_DIGEST_SIZE
+ 0 to use default (SHA1)
+ @param[out] OutData Pointer to an allocated buffer containing the encrypted
+ message.
+ @param[out] OutDataSize Size of the encrypted message buffer.
+
+ @retval TRUE Encryption was successful.
+ @retval FALSE Encryption failed.
+
+**/
+BOOLEAN
+EFIAPI
+RsaOaepDecrypt (
+ IN VOID *RsaContext,
+ IN UINT8 *EncryptedData,
+ IN UINTN EncryptedDataSize,
+ IN UINT16 DigestLen OPTIONAL,
+ OUT UINT8 **OutData,
+ OUT UINTN *OutDataSize
+ )
+{
+ ASSERT (FALSE);
+ return FALSE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
new file mode 100644
index 0000000..5fe76f1
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaExt.c
@@ -0,0 +1,352 @@
+/** @file
+ RSA Asymmetric Cipher Wrapper Implementation over MbedTLS.
+
+ This file implements following APIs which provide more capabilities for RSA:
+ 1) RsaGetKey
+ 2) RsaGenerateKey
+ 3) RsaCheckKey
+ 4) RsaPkcs1Sign
+
+ RFC 8017 - PKCS #1: RSA Cryptography Specifications Version 2.2
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+
+/**
+ Gets the tag-designated RSA key component from the established RSA context.
+
+ This function retrieves the tag-designated RSA key component from the
+ established RSA context as a non-negative integer (octet string format
+ represented in RSA PKCS#1).
+ If specified key component has not been set or has been cleared, then returned
+ BnSize is set to 0.
+ If the BigNumber buffer is too small to hold the contents of the key, FALSE
+ is returned and BnSize is set to the required buffer size to obtain the key.
+
+ If RsaContext is NULL, then return FALSE.
+ If BnSize is NULL, then return FALSE.
+ If BnSize is large enough but BigNumber is NULL, then return FALSE.
+
+ @param[in, out] RsaContext Pointer to RSA context being set.
+ @param[in] KeyTag Tag of RSA key component being set.
+ @param[out] BigNumber Pointer to octet integer buffer.
+ @param[in, out] BnSize On input, the size of big number buffer in bytes.
+ On output, the size of data returned in big number buffer in bytes.
+
+ @retval TRUE RSA key component was retrieved successfully.
+ @retval FALSE Invalid RSA key component tag.
+ @retval FALSE BnSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGetKey (
+ IN OUT VOID *RsaContext,
+ IN RSA_KEY_TAG KeyTag,
+ OUT UINT8 *BigNumber,
+ IN OUT UINTN *BnSize
+ )
+{
+ mbedtls_rsa_context *RsaKey;
+ INT32 Ret;
+ mbedtls_mpi Value;
+ UINTN Size;
+
+ //
+ // Check input parameters.
+ //
+ if ((RsaContext == NULL) || (*BnSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ //
+ // Init mbedtls_mpi
+ //
+ mbedtls_mpi_init (&Value);
+ Size = *BnSize;
+ *BnSize = 0;
+
+ RsaKey = (mbedtls_rsa_context *)RsaContext;
+
+ switch (KeyTag) {
+ case RsaKeyN:
+ Ret = mbedtls_rsa_export (RsaKey, &Value, NULL, NULL, NULL, NULL);
+ break;
+ case RsaKeyE:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, NULL, &Value);
+ break;
+ case RsaKeyD:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, NULL, &Value, NULL);
+ break;
+ case RsaKeyQ:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, NULL, &Value, NULL, NULL);
+ break;
+ case RsaKeyP:
+ Ret = mbedtls_rsa_export (RsaKey, NULL, &Value, NULL, NULL, NULL);
+ break;
+ case RsaKeyDp:
+ case RsaKeyDq:
+ case RsaKeyQInv:
+ default:
+ Ret = -1;
+ break;
+ }
+
+ if (Ret != 0) {
+ goto End;
+ }
+
+ if (mbedtls_mpi_size (&Value) == 0) {
+ Ret = 0;
+ goto End;
+ }
+
+ *BnSize = Size;
+
+ Size = mbedtls_mpi_size (&Value);
+ if (*BnSize < Size) {
+ Ret = 1;
+ *BnSize = Size;
+ goto End;
+ }
+
+ if (BigNumber == NULL) {
+ Ret = 0;
+ *BnSize = Size;
+ goto End;
+ }
+
+ if ((BigNumber != NULL) && (Ret == 0)) {
+ Ret = mbedtls_mpi_write_binary (&Value, BigNumber, Size);
+ *BnSize = Size;
+ }
+
+End:
+ mbedtls_mpi_free (&Value);
+ return Ret == 0;
+}
+
+/**
+ Generates RSA key components.
+
+ This function generates RSA key components. It takes RSA public exponent Pe and
+ length in bits of RSA modulus N as input, and generates all key components.
+ If PublicExponent is NULL, the default RSA public exponent (0x10001) will be used.
+
+ Before this function can be invoked, pseudorandom number generator must be correctly
+ initialized by RandomSeed().
+
+ If RsaContext is NULL, then return FALSE.
+
+ @param[in, out] RsaContext Pointer to RSA context being set.
+ @param[in] ModulusLength Length of RSA modulus N in bits.
+ @param[in] PublicExponent Pointer to RSA public exponent.
+ @param[in] PublicExponentSize Size of RSA public exponent buffer in bytes.
+
+ @retval TRUE RSA key component was generated successfully.
+ @retval FALSE Invalid RSA key component tag.
+
+**/
+BOOLEAN
+EFIAPI
+RsaGenerateKey (
+ IN OUT VOID *RsaContext,
+ IN UINTN ModulusLength,
+ IN CONST UINT8 *PublicExponent,
+ IN UINTN PublicExponentSize
+ )
+{
+ INT32 Ret;
+ mbedtls_rsa_context *Rsa;
+ INT32 Pe;
+
+ //
+ // Check input parameters.
+ //
+ if ((RsaContext == NULL) || (ModulusLength > INT_MAX) || (PublicExponentSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ Rsa = (mbedtls_rsa_context *)RsaContext;
+
+ if (PublicExponent == NULL) {
+ Pe = 0x10001;
+ } else {
+ if (PublicExponentSize == 0) {
+ return FALSE;
+ }
+
+ switch (PublicExponentSize) {
+ case 1:
+ Pe = PublicExponent[0];
+ break;
+ case 2:
+ Pe = PublicExponent[0] << 8 | PublicExponent[1];
+ break;
+ case 3:
+ Pe = PublicExponent[0] << 16 | PublicExponent[1] << 8 |
+ PublicExponent[2];
+ break;
+ case 4:
+ Pe = PublicExponent[0] << 24 | PublicExponent[1] << 16 |
+ PublicExponent[2] << 8 | PublicExponent[3];
+ break;
+ default:
+ return FALSE;
+ }
+ }
+
+ Ret = mbedtls_rsa_gen_key (
+ Rsa,
+ MbedtlsRand,
+ NULL,
+ (UINT32)ModulusLength,
+ Pe
+ );
+
+ return Ret == 0;
+}
+
+/**
+ Validates key components of RSA context.
+ NOTE: This function performs integrity checks on all the RSA key material, so
+ the RSA key structure must contain all the private key data.
+
+ This function validates key components of RSA context in following aspects:
+ - Whether p is a prime
+ - Whether q is a prime
+ - Whether n = p * q
+ - Whether d*e = 1 mod lcm(p-1,q-1)
+
+ If RsaContext is NULL, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context to check.
+
+ @retval TRUE RSA key components are valid.
+ @retval FALSE RSA key components are not valid.
+
+**/
+BOOLEAN
+EFIAPI
+RsaCheckKey (
+ IN VOID *RsaContext
+ )
+{
+ if (RsaContext == NULL) {
+ return FALSE;
+ }
+
+ UINT32 Ret;
+
+ Ret = mbedtls_rsa_complete (RsaContext);
+ if (Ret == 0) {
+ Ret = mbedtls_rsa_check_privkey (RsaContext);
+ }
+
+ return Ret == 0;
+}
+
+/**
+ Carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme.
+
+ This function carries out the RSA-SSA signature generation with EMSA-PKCS1-v1_5 encoding scheme defined in
+ RSA PKCS#1.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If RsaContext is NULL, then return FALSE.
+ If MessageHash is NULL, then return FALSE.
+ If HashSize is not equal to the size of MD5, SHA-1, SHA-256, SHA-384 or SHA-512 digest, then return FALSE.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] MessageHash Pointer to octet message hash to be signed.
+ @param[in] HashSize Size of the message hash in bytes.
+ @param[out] Signature Pointer to buffer to receive RSA PKCS1-v1_5 signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in PKCS1-v1_5.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPkcs1Sign (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *MessageHash,
+ IN UINTN HashSize,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ INT32 Ret;
+ mbedtls_md_type_t MdAlg;
+
+ if ((RsaContext == NULL) || (MessageHash == NULL)) {
+ return FALSE;
+ }
+
+ if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) {
+ return FALSE;
+ }
+
+ switch (HashSize) {
+ #ifndef DISABLE_SHA1_DEPRECATED_INTERFACES
+ case SHA1_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA1;
+ break;
+ #endif
+
+ case SHA256_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA256;
+ break;
+
+ case SHA384_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA384;
+ break;
+
+ case SHA512_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA512;
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (mbedtls_rsa_get_len (RsaContext) > *SigSize) {
+ *SigSize = mbedtls_rsa_get_len (RsaContext);
+ return FALSE;
+ }
+
+ if (Signature == NULL) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V15, MdAlg);
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_pkcs1_sign (
+ RsaContext,
+ MbedtlsRand,
+ NULL,
+ MdAlg,
+ (UINT32)HashSize,
+ MessageHash,
+ Signature
+ );
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ *SigSize = mbedtls_rsa_get_len (RsaContext);
+ return TRUE;
+}
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c
new file mode 100644
index 0000000..5555f92
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c
@@ -0,0 +1,140 @@
+/** @file
+ RSA PSS Asymmetric Cipher Wrapper Implementation over MbedTLS.
+
+ This file implements following APIs which provide basic capabilities for RSA:
+ 1) RsaPssSign
+
+Copyright (c) 2024, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "InternalCryptLib.h"
+#include <mbedtls/rsa.h>
+#include <mbedtls/sha256.h>
+#include <mbedtls/sha512.h>
+
+/**
+ Carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme.
+
+ This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in
+ RFC 8017.
+ Mask generation function is the same as the message digest algorithm.
+ If the Signature buffer is too small to hold the contents of signature, FALSE
+ is returned and SigSize is set to the required buffer size to obtain the signature.
+
+ If RsaContext is NULL, then return FALSE.
+ If Message is NULL, then return FALSE.
+ If MsgSize is zero or > INT_MAX, then return FALSE.
+ If DigestLen is NOT 32, 48 or 64, return FALSE.
+ If SaltLen is not equal to DigestLen, then return FALSE.
+ If SigSize is large enough but Signature is NULL, then return FALSE.
+ If this interface is not supported, then return FALSE.
+
+ @param[in] RsaContext Pointer to RSA context for signature generation.
+ @param[in] Message Pointer to octet message to be signed.
+ @param[in] MsgSize Size of the message in bytes.
+ @param[in] DigestLen Length of the digest in bytes to be used for RSA signature operation.
+ @param[in] SaltLen Length of the salt in bytes to be used for PSS encoding.
+ @param[out] Signature Pointer to buffer to receive RSA PSS signature.
+ @param[in, out] SigSize On input, the size of Signature buffer in bytes.
+ On output, the size of data returned in Signature buffer in bytes.
+
+ @retval TRUE Signature successfully generated in RSASSA-PSS.
+ @retval FALSE Signature generation failed.
+ @retval FALSE SigSize is too small.
+ @retval FALSE This interface is not supported.
+
+**/
+BOOLEAN
+EFIAPI
+RsaPssSign (
+ IN VOID *RsaContext,
+ IN CONST UINT8 *Message,
+ IN UINTN MsgSize,
+ IN UINT16 DigestLen,
+ IN UINT16 SaltLen,
+ OUT UINT8 *Signature,
+ IN OUT UINTN *SigSize
+ )
+{
+ INT32 Ret;
+ mbedtls_md_type_t MdAlg;
+ UINT8 HashValue[SHA512_DIGEST_SIZE];
+
+ if (RsaContext == NULL) {
+ return FALSE;
+ }
+
+ if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) {
+ return FALSE;
+ }
+
+ if ((Message == NULL) || (MsgSize == 0) || (MsgSize > INT_MAX)) {
+ return FALSE;
+ }
+
+ if (SaltLen != DigestLen) {
+ return FALSE;
+ }
+
+ ZeroMem (HashValue, DigestLen);
+
+ switch (DigestLen) {
+ case SHA256_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA256;
+ if (mbedtls_sha256 (Message, MsgSize, HashValue, FALSE) != 0) {
+ return FALSE;
+ }
+
+ break;
+
+ case SHA384_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA384;
+ if (mbedtls_sha512 (Message, MsgSize, HashValue, TRUE) != 0) {
+ return FALSE;
+ }
+
+ break;
+
+ case SHA512_DIGEST_SIZE:
+ MdAlg = MBEDTLS_MD_SHA512;
+ if (mbedtls_sha512 (Message, MsgSize, HashValue, FALSE) != 0) {
+ return FALSE;
+ }
+
+ break;
+
+ default:
+ return FALSE;
+ }
+
+ if (Signature == NULL) {
+ //
+ // If Signature is NULL, return safe SignatureSize
+ //
+ *SigSize = MBEDTLS_MPI_MAX_SIZE;
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V21, MdAlg);
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ Ret = mbedtls_rsa_rsassa_pss_sign (
+ RsaContext,
+ MbedtlsRand,
+ NULL,
+ MdAlg,
+ (UINT32)DigestLen,
+ HashValue,
+ Signature
+ );
+ if (Ret != 0) {
+ return FALSE;
+ }
+
+ *SigSize = ((mbedtls_rsa_context *)RsaContext)->len;
+ return TRUE;
+}