diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c index fbaad52457..24ef6c159f 100644 --- a/CryptoPkg/Driver/Crypto.c +++ b/CryptoPkg/Driver/Crypto.c @@ -4,6 +4,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.
+ (c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -5809,6 +5810,61 @@ CryptoServiceRsaPssVerify ( return CALL_BASECRYPTLIB (RsaPss.Services.Verify, RsaPssVerify, (RsaContext, Message, MsgSize, Signature, SigSize, DigestLen, SaltLen), FALSE); } +/** + Carries out the RSA-PSS signature generation over a precomputed message digest. + + @param[in] RsaContext Pointer to RSA context for signature generation. + @param[in] Digest Pointer to the precomputed message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @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 +CryptoServiceRsaPssSignDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + return CALL_BASECRYPTLIB (RsaPss.Services.SignDigest, RsaPssSignDigest, (RsaContext, Digest, DigestSize, Signature, SigSize), FALSE); +} + +/** + Verifies an RSA-PSS signature over a precomputed message digest. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Digest Pointer to the message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. + +**/ +BOOLEAN +EFIAPI +CryptoServiceRsaPssVerifyDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ) +{ + return CALL_BASECRYPTLIB (RsaPss.Services.VerifyDigest, RsaPssVerifyDigest, (RsaContext, Digest, DigestSize, Signature, SigSize), FALSE); +} + /** Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185, published December 2016. @@ -7583,4 +7639,7 @@ const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = { CryptoServiceEcGroupSetGenerator, CryptoServiceEcPointMul2, CryptoServiceEcPointsMul, + /// RSA PSS (Continued) + CryptoServiceRsaPssSignDigest, + CryptoServiceRsaPssVerifyDigest, }; diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h index 88147c1ed6..f31b7d6160 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -6,6 +6,7 @@ Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.
Copyright (c) Microsoft Corporation. All rights reserved. +(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -1915,6 +1916,73 @@ RsaPssVerify ( IN UINT16 SaltLen ); +/** + Carries out the RSA-PSS signature generation with EMSA-PSS encoding scheme + over a precomputed message digest. + + This function carries out the RSA-PSS 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 Digest is NULL, then return FALSE. + If DigestSize is not one of SHA-256, SHA-384 or SHA-512 digest sizes, 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] Digest Pointer to the precomputed message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @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 +RsaPssSignDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ); + +/** + Verifies an RSA-PSS signature over a precomputed message digest. + + If RsaContext is NULL, then return FALSE. + If Digest is NULL, then return FALSE. + If Signature is NULL, then return FALSE. + If DigestSize is not one of SHA-256, SHA-384 or SHA-512 digest sizes, + then return FALSE. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Digest Pointer to the message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. +**/ +BOOLEAN +EFIAPI +RsaPssVerifyDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ); + /** Retrieve the RSA Private Key from the password-protected PEM key data. diff --git a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h index 7585849027..7c5173f180 100644 --- a/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h +++ b/CryptoPkg/Include/Pcd/PcdCryptoServiceFamilyEnable.h @@ -24,6 +24,7 @@ Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.
Copyright (c) Microsoft Corporation. All rights reserved. + (c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -354,8 +355,10 @@ typedef struct { } TlsGet; union { struct { - UINT8 Sign : 1; - UINT8 Verify : 1; + UINT8 Sign : 1; + UINT8 Verify : 1; + UINT8 SignDigest : 1; + UINT8 VerifyDigest : 1; } Services; UINT32 Family; } RsaPss; diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c index bdc9155e1f..cd4d22ae85 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c @@ -3,8 +3,10 @@ This file implements following APIs which provide basic capabilities for RSA: 1) RsaPssVerify + 2) RsaPssVerifyDigest Copyright (c) 2021, Intel Corporation. All rights reserved.
+(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -156,3 +158,115 @@ _Exit: return Result; } + +/** + Verifies an RSA-PSS signature over a precomputed message digest. + Mask generation function is the same as the message digest algorithm. + + If RsaContext is NULL, then return FALSE. + If Digest is NULL, then return FALSE. + If Signature is NULL, then return FALSE. + If DigestSize is not one of SHA-256, SHA-384 or SHA-512 digest sizes, + then return FALSE. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Digest Pointer to the message digest. + @param[in] DigestSize Digest size in bytes + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. +**/ +BOOLEAN +EFIAPI +RsaPssVerifyDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ) +{ + BOOLEAN Result; + EVP_PKEY *EvpRsaKey; + EVP_PKEY_CTX *EvpVerifyCtx; + CONST EVP_MD *HashAlg; + + Result = FALSE; + EvpRsaKey = NULL; + EvpVerifyCtx = NULL; + HashAlg = NULL; + + if (RsaContext == NULL) { + return FALSE; + } + + if ((Digest == NULL) || (DigestSize == 0) || (DigestSize > INT_MAX) || (DigestSize > MAX_UINT16)) { + return FALSE; + } + + if ((Signature == NULL) || (SigSize == 0) || (SigSize > INT_MAX)) { + return FALSE; + } + + HashAlg = GetEvpMD ((UINT16)DigestSize); + + if (HashAlg == NULL) { + return FALSE; + } + + EvpRsaKey = EVP_PKEY_new (); + if (EvpRsaKey == NULL) { + goto _Exit; + } + + EVP_PKEY_set1_RSA (EvpRsaKey, RsaContext); + + EvpVerifyCtx = EVP_PKEY_CTX_new (EvpRsaKey, NULL); + if (EvpVerifyCtx == NULL) { + goto _Exit; + } + + Result = EVP_PKEY_verify_init (EvpVerifyCtx) > 0; + + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_padding (EvpVerifyCtx, RSA_PKCS1_PSS_PADDING) > 0; + } + + if (Result) { + Result = EVP_PKEY_CTX_set_signature_md (EvpVerifyCtx, HashAlg) > 0; + } + + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_mgf1_md (EvpVerifyCtx, HashAlg) > 0; + } + + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_pss_saltlen (EvpVerifyCtx, (INT32)DigestSize) > 0; + } + + if (Result) { + Result = EVP_PKEY_verify ( + EvpVerifyCtx, + Signature, + (UINT32)SigSize, + Digest, + (UINT32)DigestSize + ) > 0; + } + +_Exit: + if (EvpVerifyCtx != NULL) { + EVP_PKEY_CTX_free (EvpVerifyCtx); + } + + if (EvpRsaKey != NULL) { + EVP_PKEY_free (EvpRsaKey); + } + + return Result; +} diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c index 07c24f6e8d..4835f81168 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c @@ -3,8 +3,10 @@ This file implements following APIs which provide basic capabilities for RSA: 1) RsaPssSign + 2) RsaPssSignDigest Copyright (c) 2021, Intel Corporation. All rights reserved.
+(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -177,3 +179,128 @@ _Exit: return Result; } + +/** + Carries out the RSA-PSS signature generation with EMSA-PSS encoding scheme + over a precomputed message digest. + + This function carries out the RSA-PSS 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 Digest is NULL, then return FALSE. + If DigestSize is not one of SHA-256, SHA-384 or SHA-512 digest sizes, 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] Digest Pointer to the precomputed message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @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 +RsaPssSignDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + BOOLEAN Result; + UINTN RsaSigSize; + EVP_PKEY *EvpRsaKey; + EVP_PKEY_CTX *EvpSignCtx; + CONST EVP_MD *HashAlg; + + Result = FALSE; + EvpRsaKey = NULL; + EvpSignCtx = NULL; + HashAlg = NULL; + + if (RsaContext == NULL) { + return FALSE; + } + + if ((Digest == NULL) || (DigestSize == 0) || (DigestSize > INT_MAX) || (DigestSize > MAX_UINT16)) { + return FALSE; + } + + RsaSigSize = RSA_size (RsaContext); + if (*SigSize < RsaSigSize) { + *SigSize = RsaSigSize; + return FALSE; + } + + if (Signature == NULL) { + return FALSE; + } + + HashAlg = GetEvpMD ((UINT16)DigestSize); + if (HashAlg == NULL) { + return FALSE; + } + + EvpRsaKey = EVP_PKEY_new (); + if (EvpRsaKey == NULL) { + goto _Exit; + } + + EVP_PKEY_set1_RSA (EvpRsaKey, RsaContext); + + EvpSignCtx = EVP_PKEY_CTX_new (EvpRsaKey, NULL); + if (EvpSignCtx == NULL) { + goto _Exit; + } + + Result = EVP_PKEY_sign_init (EvpSignCtx) > 0; + + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_padding (EvpSignCtx, RSA_PKCS1_PSS_PADDING) > 0; + } + + if (Result) { + Result = EVP_PKEY_CTX_set_signature_md (EvpSignCtx, HashAlg) > 0; + } + + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_mgf1_md (EvpSignCtx, HashAlg) > 0; + } + + if (Result) { + Result = EVP_PKEY_CTX_set_rsa_pss_saltlen (EvpSignCtx, (INT32)DigestSize) > 0; + } + + if (Result) { + Result = EVP_PKEY_sign ( + EvpSignCtx, + Signature, + SigSize, + Digest, + (UINT32)DigestSize + ) > 0; + } + +_Exit: + if (EvpSignCtx != NULL) { + EVP_PKEY_CTX_free (EvpSignCtx); + } + + if (EvpRsaKey != NULL) { + EVP_PKEY_free (EvpRsaKey); + } + + return Result; +} diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c index 911b972521..66ae8a7855 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c @@ -3,8 +3,10 @@ This file does not provide real capabilities for following APIs in RSA handling: 1) RsaPssSign + 2) RsaPssSignDigest Copyright (c) 2021, Intel Corporation. All rights reserved.
+(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -58,3 +60,46 @@ RsaPssSign ( ASSERT (FALSE); return FALSE; } + +/** + Carries out the RSA-PSS signature generation with EMSA-PSS encoding scheme + over a precomputed message digest. + + This function carries out the RSA-PSS 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 Digest is NULL, then return FALSE. + If DigestSize is not one of SHA-256, SHA-384 or SHA-512 digest sizes, 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] Digest Pointer to the precomputed message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @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 +RsaPssSignDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPss.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPss.c index ecd1bd1a41..452727a5e2 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPss.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPss.c @@ -3,8 +3,10 @@ This file implements following APIs which provide basic capabilities for RSA: 1) RsaPssVerify + 2) RsaPssVerifyDigest Copyright (c) 2023, Intel Corporation. All rights reserved.
+(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -120,3 +122,93 @@ RsaPssVerify ( return TRUE; } + +/** + Verifies an RSA-PSS signature over a precomputed message digest. + Mask generation function is the same as the message digest algorithm. + + If RsaContext is NULL, then return FALSE. + If Digest is NULL, then return FALSE. + If Signature is NULL, then return FALSE. + If DigestSize is not one of SHA-256, SHA-384 or SHA-512 digest sizes, + then return FALSE. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Digest Pointer to the message digest. + @param[in] DigestSize Digest size in bytes + SHA256_DIGEST_SIZE + SHA384_DIGEST_SIZE + SHA512_DIGEST_SIZE + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. +**/ +BOOLEAN +EFIAPI +RsaPssVerifyDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ) +{ + INT32 Ret; + mbedtls_md_type_t MdAlg; + mbedtls_rsa_context *RsaKey; + + if (RsaContext == NULL) { + return FALSE; + } + + if ((Digest == NULL) || (DigestSize == 0) || (DigestSize > INT_MAX) || (DigestSize > MAX_UINT16)) { + return FALSE; + } + + if ((Signature == NULL) || (SigSize == 0) || (SigSize > INT_MAX)) { + return FALSE; + } + + RsaKey = (mbedtls_rsa_context *)RsaContext; + if (mbedtls_rsa_complete (RsaKey) != 0) { + return FALSE; + } + + switch (DigestSize) { + 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) { + return FALSE; + } + + mbedtls_rsa_set_padding (RsaContext, MBEDTLS_RSA_PKCS_V21, MdAlg); + + Ret = mbedtls_rsa_rsassa_pss_verify ( + RsaContext, + MdAlg, + (UINT32)DigestSize, + Digest, + Signature + ); + if (Ret != 0) { + return FALSE; + } + + return TRUE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c index 5555f9261e..5baf6c35ca 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSign.c @@ -3,8 +3,10 @@ This file implements following APIs which provide basic capabilities for RSA: 1) RsaPssSign + 2) RsaPssSignDigest Copyright (c) 2024, Intel Corporation. All rights reserved.
+(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -138,3 +140,95 @@ RsaPssSign ( *SigSize = ((mbedtls_rsa_context *)RsaContext)->len; return TRUE; } + +/** + Carries out the RSA-PSS signature generation with EMSA-PSS encoding scheme + over a precomputed message digest. + + If RsaContext is NULL, then return FALSE. + If Digest is NULL, then return FALSE. + If DigestSize is not one of SHA-256, SHA-384 or SHA-512 digest sizes, 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] Digest Pointer to the precomputed message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @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 +RsaPssSignDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + INT32 Ret; + mbedtls_md_type_t MdAlg; + + if (RsaContext == NULL) { + return FALSE; + } + + if (mbedtls_rsa_complete ((mbedtls_rsa_context *)RsaContext) != 0) { + return FALSE; + } + + if ((Digest == NULL) || (DigestSize == 0) || (DigestSize > INT_MAX) || (DigestSize > MAX_UINT16)) { + return FALSE; + } + + switch (DigestSize) { + 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 (Signature == NULL) { + *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)DigestSize, + Digest, + Signature + ); + if (Ret != 0) { + return FALSE; + } + + *SigSize = ((mbedtls_rsa_context *)RsaContext)->len; + return TRUE; +} diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSignNull.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSignNull.c index 10687bd38e..b2c667cc34 100644 --- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSignNull.c +++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptRsaPssSignNull.c @@ -3,8 +3,10 @@ This file does not provide real capabilities for following APIs in RSA handling: 1) RsaPssSign + 2) RsaPssSignDigest Copyright (c) 2023, Intel Corporation. All rights reserved.
+(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -58,3 +60,46 @@ RsaPssSign ( ASSERT (FALSE); return FALSE; } + +/** + Carries out the RSA-PSS signature generation with EMSA-PSS encoding scheme + over a precomputed message digest. + + This function carries out the RSA-PSS 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 Digest is NULL, then return FALSE. + If DigestSize is not one of SHA-256, SHA-384 or SHA-512 digest sizes, 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] Digest Pointer to the precomputed message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @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 +RsaPssSignDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c index cc325c9291..ac4647351f 100644 --- a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c @@ -3,8 +3,10 @@ This file does not provide real capabilities for following APIs in RSA handling: 1) RsaPssVerify + 2) RsaPssVerifyDigest Copyright (c) 2021, Intel Corporation. All rights reserved.
+(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -44,3 +46,30 @@ RsaPssVerify ( ASSERT (FALSE); return FALSE; } + +/** + Verifies an RSA-PSS signature over a precomputed message digest. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Digest Pointer to the message digest. + @param[in] DigestSize Digest size in bytes. + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. + +**/ +BOOLEAN +EFIAPI +RsaPssVerifyDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c index 911b972521..4da5a6fba7 100644 --- a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c @@ -3,8 +3,10 @@ This file does not provide real capabilities for following APIs in RSA handling: 1) RsaPssSign + 2) RsaPssSignDigest Copyright (c) 2021, Intel Corporation. All rights reserved.
+(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -58,3 +60,32 @@ RsaPssSign ( ASSERT (FALSE); return FALSE; } + +/** + Carries out the RSA-PSS signature generation over a precomputed message digest. + + @param[in] RsaContext Pointer to RSA context for signature generation. + @param[in] Digest Pointer to the precomputed message digest. + @param[in] DigestSize Digest size in bytes. + @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 This interface is not supported. + +**/ +BOOLEAN +EFIAPI +RsaPssSignDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c index 37f5d6ad6e..21b93883a5 100644 --- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c +++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c @@ -4,6 +4,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. Copyright (c) 2019 - 2022, Intel Corporation. All rights reserved.
+ (c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -2068,39 +2069,6 @@ RsaPkcs1Verify ( CALL_CRYPTO_SERVICE (RsaPkcs1Verify, (RsaContext, MessageHash, HashSize, Signature, SigSize), FALSE); } -/** - 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 - ) -{ - CALL_CRYPTO_SERVICE (RsaPssVerify, (RsaContext, Message, MsgSize, Signature, SigSize, DigestLen, SaltLen), FALSE); -} - /** This function carries out the RSA-SSA signature generation with EMSA-PSS encoding scheme defined in RFC 8017. @@ -2146,6 +2114,94 @@ RsaPssSign ( CALL_CRYPTO_SERVICE (RsaPssSign, (RsaContext, Message, MsgSize, DigestLen, SaltLen, Signature, SigSize), FALSE); } +/** + 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 + ) +{ + CALL_CRYPTO_SERVICE (RsaPssVerify, (RsaContext, Message, MsgSize, Signature, SigSize, DigestLen, SaltLen), FALSE); +} + +/** + Carries out the RSA-PSS signature generation over a precomputed message digest. + + @param[in] RsaContext Pointer to RSA context for signature generation. + @param[in] Digest Pointer to the precomputed message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @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 +RsaPssSignDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + CALL_CRYPTO_SERVICE (RsaPssSignDigest, (RsaContext, Digest, DigestSize, Signature, SigSize), FALSE); +} + +/** + Verifies an RSA-PSS signature over a precomputed message digest. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Digest Pointer to the message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. + +**/ +BOOLEAN +EFIAPI +RsaPssVerifyDigest ( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ) +{ + CALL_CRYPTO_SERVICE (RsaPssVerifyDigest, (RsaContext, Digest, DigestSize, Signature, SigSize), FALSE); +} + /** Retrieve the RSA Private Key from the password-protected PEM key data. diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h index 3afd272fd4..e5635bc070 100644 --- a/CryptoPkg/Private/Protocol/Crypto.h +++ b/CryptoPkg/Private/Protocol/Crypto.h @@ -3,6 +3,7 @@ Copyright (C) Microsoft Corporation. All rights reserved. Copyright (c) 2020 - 2022, Intel Corporation. All rights reserved.
+ (c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -20,7 +21,7 @@ /// the EDK II Crypto Protocol is extended, this version define must be /// increased. /// -#define EDKII_CRYPTO_VERSION 23 +#define EDKII_CRYPTO_VERSION 24 /// /// EDK II Crypto Protocol forward declaration @@ -4472,6 +4473,55 @@ BOOLEAN IN UINT16 SaltLen ); +/** + Carries out the RSA-PSS signature generation over a precomputed message digest. + + @param[in] RsaContext Pointer to RSA context for signature generation. + @param[in] Digest Pointer to the precomputed message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @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. + +**/ +typedef +BOOLEAN +(EFIAPI *EDKII_CRYPTO_RSA_PSS_SIGN_DIGEST)( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ); + +/** + Verifies an RSA-PSS signature over a precomputed message digest. + + @param[in] RsaContext Pointer to RSA context for signature verification. + @param[in] Digest Pointer to the message digest. + @param[in] DigestSize Digest size in bytes (32=SHA-256, 48=SHA-384, 64=SHA-512). + @param[in] Signature Pointer to RSASSA-PSS signature to be verified. + @param[in] SigSize Size of signature in bytes. + + @retval TRUE Valid signature encoded in RSASSA-PSS. + @retval FALSE Invalid signature or invalid RSA context. + +**/ +typedef +BOOLEAN +(EFIAPI *EDKII_CRYPTO_RSA_PSS_VERIFY_DIGEST)( + IN VOID *RsaContext, + IN CONST UINT8 *Digest, + IN UINTN DigestSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize + ); + /** Parallel hash function ParallelHash256, as defined in NIST's Special Publication 800-185, published December 2016. @@ -6121,6 +6171,9 @@ struct _EDKII_CRYPTO_PROTOCOL { EDKII_CRYPTO_EC_GROUP_SET_GENERATOR EcGroupSetGenerator; EDKII_CRYPTO_EC_POINT_MUL2 EcPointMul2; EDKII_CRYPTO_EC_POINTS_MUL EcPointsMul; + /// RSA PSS (Continued) + EDKII_CRYPTO_RSA_PSS_SIGN_DIGEST RsaPssSignDigest; + EDKII_CRYPTO_RSA_PSS_VERIFY_DIGEST RsaPssVerifyDigest; }; extern GUID gEdkiiCryptoProtocolGuid; diff --git a/CryptoPkg/Readme.md b/CryptoPkg/Readme.md index 9cd7850c0a..c29a9117d9 100644 --- a/CryptoPkg/Readme.md +++ b/CryptoPkg/Readme.md @@ -227,6 +227,8 @@ also configured. | TlsGet | N | N | | | C-Tls | | | | RsaPss.Sign | N | N | | | C | | | | RsaPss.Verify | N | N | | C | C | C | | +| RsaPss.SignDigest | N | N | | | C | | | +| RsaPss.VerifyDigest | N | N | | C | C | C | | | ParallelHash | N | N | | | | C | | | AeadAesGcm | N | N | | | C | | | | Bn | N | N | | | C | C | | diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c index 48c1b7a450..a6ac8ea5e3 100644 --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c @@ -2,6 +2,7 @@ Application for RSA PSS Primitives Validation. Copyright (c) 2021, Intel Corporation. All rights reserved.
+(c) Copyright 2026 HP Development Company, L.P. SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -183,11 +184,79 @@ TestVerifyRsaPssSignVerify ( return UNIT_TEST_PASSED; } +UNIT_TEST_STATUS +EFIAPI +TestVerifyRsaPssSignVerifyDigest ( + IN UNIT_TEST_CONTEXT Context + ) +{ + UINT8 HashValue[SHA256_DIGEST_SIZE]; + UINT8 *Signature; + UINTN SigSize; + BOOLEAN Status; + + Status = RsaSetKey (mRsa, RsaKeyN, RsaPssN, sizeof (RsaPssN)); + UT_ASSERT_TRUE (Status); + + Status = RsaSetKey (mRsa, RsaKeyE, RsaPssE, sizeof (RsaPssE)); + UT_ASSERT_TRUE (Status); + + Status = RsaSetKey (mRsa, RsaKeyD, RsaPssD, sizeof (RsaPssD)); + UT_ASSERT_TRUE (Status); + + Status = Sha256HashAll (PssMessage, sizeof (PssMessage), HashValue); + UT_ASSERT_TRUE (Status); + + // + // Query required signature buffer size + // + SigSize = 0; + Status = RsaPssSignDigest (mRsa, HashValue, sizeof (HashValue), NULL, &SigSize); + UT_ASSERT_FALSE (Status); + UT_ASSERT_NOT_EQUAL (SigSize, 0); + + Signature = AllocatePool (SigSize); + if (Signature == NULL) { + UT_LOG_ERROR ("Failed to allocate memory for Signature"); + return UNIT_TEST_ERROR_TEST_FAILED; + } + + // + // Sign the precomputed digest + // + Status = RsaPssSignDigest (mRsa, HashValue, sizeof (HashValue), Signature, &SigSize); + UT_ASSERT_TRUE (Status); + + // + // Verify the signature using the digest-based verify API + // + Status = RsaPssVerifyDigest (mRsa, HashValue, sizeof (HashValue), Signature, SigSize); + UT_ASSERT_TRUE (Status); + + // + // Corrupting one byte should fail digest-based verification + // + Signature[0] ^= 0xFF; + Status = RsaPssVerifyDigest (mRsa, HashValue, sizeof (HashValue), Signature, SigSize); + UT_ASSERT_FALSE (Status); + + FreePool (Signature); + + // + // Verify NIST FIPS 186-3 RSA test vector signature with precomputed digest + // + Status = RsaPssVerifyDigest (mRsa, HashValue, sizeof (HashValue), TestVectorSignature, sizeof (TestVectorSignature)); + UT_ASSERT_TRUE (Status); + + return UNIT_TEST_PASSED; +} + TEST_DESC mRsaPssTest[] = { // // -----Description--------------------------------------Class----------------------Function---------------------------------Pre---------------------Post---------Context // - { "TestVerifyRsaPssSignVerify()", "CryptoPkg.BaseCryptLib.Rsa", TestVerifyRsaPssSignVerify, TestVerifyRsaPssPreReq, TestVerifyRsaPssCleanUp, NULL }, + { "TestVerifyRsaPssSignVerify()", "CryptoPkg.BaseCryptLib.Rsa", TestVerifyRsaPssSignVerify, TestVerifyRsaPssPreReq, TestVerifyRsaPssCleanUp, NULL }, + { "TestVerifyRsaPssSignVerifyDigest()", "CryptoPkg.BaseCryptLib.Rsa", TestVerifyRsaPssSignVerifyDigest, TestVerifyRsaPssPreReq, TestVerifyRsaPssCleanUp, NULL }, }; UINTN mRsaPssTestNum = ARRAY_SIZE (mRsaPssTest);