From nobody Thu Mar 28 20:01:37 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+74566+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+74566+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=intel.com ARC-Seal: i=1; a=rsa-sha256; t=1619628241; cv=none; d=zohomail.com; s=zohoarc; b=ntyX0bIEdmy9V4a9D9q29oXDPbhJLzI/aKwCn/IDnGEkp+f2ofeEsAoU6l8KeN4p65RtY2jya857rEg5de7D6rhtnlnsKTwK7EQ2MDKMQDkkX2G6vQ2wDOwi8rfBlRYL9ED2nTEEppGd39rr0XiqFAfBjVhe+I9U4vTBtbhFfqE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1619628241; h=Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:Message-ID:Reply-To:References:Sender:Subject:To; bh=D9cAXYHFeE/w57Fq2LkudwafuTE3TkAqBImEwr8sUdg=; b=WSzto5WwqvASIZ0FKrqdmrwW9OtgpmoiZK2/YVUV0P9AQl33eh09aIJ43mIMDsDaF0BltPONA/WcijOQOX41geBQiQMJpxgp0ewXwfvHT0RpPDlv9n13MOhjIG3B3usIuxQqNE9qEGTyS1I2cVyMgpihcojLT2zhXGvYeDNrY4c= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+74566+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) header.from= Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1619628241205393.8025093405806; Wed, 28 Apr 2021 09:44:01 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id rvDiYY1788612xBfuFJ7cprp; Wed, 28 Apr 2021 09:44:00 -0700 X-Received: from mga04.intel.com (mga04.intel.com []) by mx.groups.io with SMTP id smtpd.web09.78.1619626522610477311 for ; Wed, 28 Apr 2021 09:15:23 -0700 IronPort-SDR: 24mOAv698Loch0zx7Xd2b896zuevYKYspCOvaAVlH50WcjBppSA17SKqcn00yj5yU24ZIzSWSH Kmz/QHyv1+gw== X-IronPort-AV: E=McAfee;i="6200,9189,9968"; a="194668042" X-IronPort-AV: E=Sophos;i="5.82,258,1613462400"; d="scan'208";a="194668042" X-Received: from fmsmga003.fm.intel.com ([10.253.24.29]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 28 Apr 2021 09:15:22 -0700 IronPort-SDR: YL1/mJMTGQXvd2HHJ/EYc9biC4Uitw0/go/6IOp5s5/1pLE9xMKvOSKpNQIxC8QEIrPNasrZR7 k1BAfEQI9tZw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.82,258,1613462400"; d="scan'208";a="455124993" X-Received: from sagraw2-desk1.amr.corp.intel.com ([10.72.4.190]) by FMSMGA003.fm.intel.com with ESMTP; 28 Apr 2021 09:15:21 -0700 From: "Agrawal, Sachin" To: devel@edk2.groups.io Cc: Jiewen Yao , Jian J Wang , Xiaoyu Lu , Guomin Jiang , Sachin Agrawal Subject: [edk2-devel] [PATCH v2 1/1] CryptoPkg: BaseCryptLib: Add RSA PSS verify support Date: Wed, 28 Apr 2021 09:15:20 -0700 Message-Id: <20210428161520.16876-2-sachin.agrawal@intel.com> In-Reply-To: <20210428161520.16876-1-sachin.agrawal@intel.com> References: <20210428161520.16876-1-sachin.agrawal@intel.com> Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,sachin.agrawal@intel.com X-Gm-Message-State: QVi7IINsMVOW1SfTOXTW85rIx1787277AA= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1619628240; bh=38+jsAABGe9n7omniqc2vMrnPwrmO4TbgpmYeOyiBTM=; h=Cc:Date:From:Reply-To:Subject:To; b=B1tAJPWauFdTZ4p6ft8aD/vsotQkzH2nhz3FugvP3Njj/wB7JmNiPt0FKN43gaazwbd m+DxQMMBO2yU4wlFz1XPflIsxTWEv/sbxI8re5ca09hjBAGXKj5dq5r0+A75Qh4tTula8 WJB7d/i0tdGm6OzXwCgwoMQ9vFh5zSJ4Kuk= X-ZohoMail-DKIM: pass (identity @groups.io) Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D3314 This patch uses Openssl's EVP API's to perform RSASSA-PSS verification of a binary blob. Cc: Jiewen Yao Cc: Jian J Wang Cc: Xiaoyu Lu Cc: Guomin Jiang Signed-off-by: Sachin Agrawal --- Notes: v2: - Added SaltLen as argument (Jiewen) - Added RsaPssSign support (Jiewen) - Added Unit test (Jiewen) - Added RSA PSS API in EDK2 Crypto Protocol (Missed in v1) CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c | 1= 45 +++++++++++++++ CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c | = 46 +++++ CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c | 1= 68 +++++++++++++++++ CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c | = 60 ++++++ CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c | = 46 +++++ CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c | = 60 ++++++ CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c | = 66 +++++++ CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c | = 1 + CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c | 1= 91 ++++++++++++++++++++ CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaTests.c | = 2 + CryptoPkg/Include/Library/BaseCryptLib.h | = 74 ++++++++ CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf | = 2 + CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf | = 2 + CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf | = 2 + CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf | = 2 + CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf | = 2 + CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf | = 2 + CryptoPkg/Private/Protocol/Crypto.h | = 78 ++++++++ CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h | = 3 + CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf | = 1 + CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf | = 1 + 21 files changed, 954 insertions(+) diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c b/CryptoPkg/Li= brary/BaseCryptLib/Pk/CryptRsaPss.c new file mode 100644 index 000000000000..023f64ba214b --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPss.c @@ -0,0 +1,145 @@ +/** @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.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include +#include + + +/** + 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 R= FC 8017. + Implementation determines salt length automatically from the signature e= ncoding. + 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 verific= ation. + @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 verifi= ed. + @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 *pEvpRsaKey =3D NULL; + EVP_MD_CTX *pEvpVerifyCtx =3D NULL; + EVP_PKEY_CTX *pKeyCtx =3D NULL; + CONST EVP_MD *HashAlg =3D NULL; + + if (RsaContext =3D=3D NULL) { + return FALSE; + } + if (Message =3D=3D NULL || MsgSize =3D=3D 0 || MsgSize > INT_MAX) { + return FALSE; + } + if (Signature =3D=3D NULL || SigSize =3D=3D 0 || SigSize > INT_MAX) { + return FALSE; + } + if (SaltLen < DigestLen) { + return FALSE; + } + + HashAlg =3D GetEvpMD(DigestLen); + + if (HashAlg =3D=3D NULL) { + return FALSE; + } + + pEvpRsaKey =3D EVP_PKEY_new(); + if (pEvpRsaKey =3D=3D NULL) { + goto _Exit; + } + + EVP_PKEY_set1_RSA(pEvpRsaKey, RsaContext); + + pEvpVerifyCtx =3D EVP_MD_CTX_create(); + if (pEvpVerifyCtx =3D=3D NULL) { + goto _Exit; + } + + Result =3D EVP_DigestVerifyInit(pEvpVerifyCtx, &pKeyCtx, HashAlg, NULL, = pEvpRsaKey) > 0; + if (pKeyCtx =3D=3D NULL) { + goto _Exit; + } + + if (Result) { + Result =3D EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING= ) > 0; + } + if (Result) { + Result =3D EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, SaltLen) > 0; + } + if (Result) { + Result =3D EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, HashAlg) > 0; + } + if (Result) { + Result =3D EVP_DigestVerifyUpdate(pEvpVerifyCtx, Message, (UINT32)MsgS= ize) > 0; + } + if (Result) { + Result =3D EVP_DigestVerifyFinal(pEvpVerifyCtx, Signature, (UINT32)Sig= Size) > 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/CryptoPk= g/Library/BaseCryptLib/Pk/CryptRsaPssNull.c new file mode 100644 index 000000000000..69c6889fbc4b --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssNull.c @@ -0,0 +1,46 @@ +/** @file + RSA-PSS Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file does not provide real capabilities for following APIs in RSA h= andling: + 1) RsaPssVerify + +Copyright (c) 2021, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +/** + Verifies the RSA signature with RSASSA-PSS signature scheme defined in R= FC 8017. + Implementation determines salt length automatically from the signature e= ncoding. + 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 verific= ation. + @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 verifi= ed. + @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 + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c b/CryptoPk= g/Library/BaseCryptLib/Pk/CryptRsaPssSign.c new file mode 100644 index 000000000000..7f798e82215a --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSign.c @@ -0,0 +1,168 @@ +/** @file + RSA PSS Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file implements following APIs which provide basic capabilities for= RSA: + 1) RsaPssSign + +Copyright (c) 2021, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +#include +#include +#include +#include + + +/** + 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; + } +} + + +/** + Carries out the RSA-SSA signature generation with EMSA-PSS encoding sche= me. + + 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 < 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 genera= tion. + @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 fo= r 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 signat= ure. + @param[in, out] SigSize On input, the size of Signature buffer in b= ytes. + On output, the size of data returned in Sig= nature 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 + ) +{ + BOOLEAN Result; + UINTN RsaSigSize; + EVP_PKEY *pEvpRsaKey =3D NULL; + EVP_MD_CTX *pEvpVerifyCtx =3D NULL; + EVP_PKEY_CTX *pKeyCtx =3D NULL; + CONST EVP_MD *HashAlg =3D NULL; + + if (RsaContext =3D=3D NULL) { + return FALSE; + } + if (Message =3D=3D NULL || MsgSize =3D=3D 0 || MsgSize > INT_MAX) { + return FALSE; + } + + RsaSigSize =3D RSA_size (RsaContext); + if (*SigSize < RsaSigSize) { + *SigSize =3D RsaSigSize; + return FALSE; + } + + if (Signature =3D=3D NULL) { + return FALSE; + } + + if (SaltLen < DigestLen) { + return FALSE; + } + + HashAlg =3D GetEvpMD(DigestLen); + + if (HashAlg =3D=3D NULL) { + return FALSE; + } + + pEvpRsaKey =3D EVP_PKEY_new(); + if (pEvpRsaKey =3D=3D NULL) { + goto _Exit; + } + + EVP_PKEY_set1_RSA(pEvpRsaKey, RsaContext); + + pEvpVerifyCtx =3D EVP_MD_CTX_create(); + if (pEvpVerifyCtx =3D=3D NULL) { + goto _Exit; + } + + Result =3D EVP_DigestSignInit(pEvpVerifyCtx, &pKeyCtx, HashAlg, NULL, pE= vpRsaKey) > 0; + if (pKeyCtx =3D=3D NULL) { + goto _Exit; + } + + if (Result) { + Result =3D EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING= ) > 0; + } + if (Result) { + Result =3D EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, SaltLen) > 0; + } + if (Result) { + Result =3D EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, HashAlg) > 0; + } + if (Result) { + Result =3D EVP_DigestSignUpdate(pEvpVerifyCtx, Message, (UINT32)MsgSiz= e) > 0; + } + if (Result) { + Result =3D EVP_DigestSignFinal(pEvpVerifyCtx, Signature, 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/CryptRsaPssSignNull.c b/Cryp= toPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c new file mode 100644 index 000000000000..4ed2dfce992a --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptRsaPssSignNull.c @@ -0,0 +1,60 @@ +/** @file + RSA-PSS Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file does not provide real capabilities for following APIs in RSA h= andling: + 1) RsaPssSign + +Copyright (c) 2021, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +/** + Carries out the RSA-SSA signature generation with EMSA-PSS encoding sche= me. + + 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 < 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 genera= tion. + @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 fo= r 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 signat= ure. + @param[in, out] SigSize On input, the size of Signature buffer in b= ytes. + On output, the size of data returned in Sig= nature 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 + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c b/Cryp= toPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c new file mode 100644 index 000000000000..69c6889fbc4b --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssNull.c @@ -0,0 +1,46 @@ +/** @file + RSA-PSS Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file does not provide real capabilities for following APIs in RSA h= andling: + 1) RsaPssVerify + +Copyright (c) 2021, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +/** + Verifies the RSA signature with RSASSA-PSS signature scheme defined in R= FC 8017. + Implementation determines salt length automatically from the signature e= ncoding. + 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 verific= ation. + @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 verifi= ed. + @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 + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c b/= CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c new file mode 100644 index 000000000000..4ed2dfce992a --- /dev/null +++ b/CryptoPkg/Library/BaseCryptLibNull/Pk/CryptRsaPssSignNull.c @@ -0,0 +1,60 @@ +/** @file + RSA-PSS Asymmetric Cipher Wrapper Implementation over OpenSSL. + + This file does not provide real capabilities for following APIs in RSA h= andling: + 1) RsaPssSign + +Copyright (c) 2021, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "InternalCryptLib.h" + +/** + Carries out the RSA-SSA signature generation with EMSA-PSS encoding sche= me. + + 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 < 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 genera= tion. + @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 fo= r 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 signat= ure. + @param[in, out] SigSize On input, the size of Signature buffer in b= ytes. + On output, the size of data returned in Sig= nature 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 + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/Crypt= oPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c index 8b43d1363cb9..412fbdbff52c 100644 --- a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c +++ b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c @@ -1552,6 +1552,72 @@ RsaPkcs1Verify ( CALL_CRYPTO_SERVICE (RsaPkcs1Verify, (RsaContext, MessageHash, HashSize,= Signature, SigSize), FALSE); } =20 +/** + Verifies the RSA signature with RSASSA-PSS signature scheme defined in R= FC 8017. + Implementation determines salt length automatically from the signature e= ncoding. + 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 verific= ation. + @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 verifi= ed. + @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, Signat= ure, SigSize, DigestLen, SaltLen), FALSE); +} + +/** + Verifies the RSA signature with RSASSA-PSS signature scheme defined in R= FC 8017. + Implementation determines salt length automatically from the signature e= ncoding. + 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 verific= ation. + @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 verifi= ed. + @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 +RsaPssSign ( + IN VOID *RsaContext, + IN CONST UINT8 *Message, + IN UINTN MsgSize, + IN UINT16 DigestLen, + IN UINT16 SaltLen, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ) +{ + CALL_CRYPTO_SERVICE (RsaPssSign, (RsaContext, Message, MsgSize, DigestLe= n, SaltLen, Signature, SigSize), FALSE); +} + /** Retrieve the RSA Private Key from the password-protected PEM key data. =20 diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitT= ests.c b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests= .c index b7fcea3ff7e4..3873de973064 100644 --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/BaseCryptLibUnitTests.c @@ -16,6 +16,7 @@ SUITE_DESC mSuiteDesc[] =3D { {"HMAC verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, = &mHmacTestNum, mHmacTest}, {"BlockCipher verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, = &mBlockCipherTestNum, mBlockCipherTest}, {"RSA verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, = &mRsaTestNum, mRsaTest}, + {"RSA PSS verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, = &mRsaPssTestNum, mRsaPssTest}, {"RSACert verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, = &mRsaCertTestNum, mRsaCertTest}, {"PKCS7 verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, = &mPkcs7TestNum, mPkcs7Test}, {"PKCS5 verify tests", "CryptoPkg.BaseCryptLib", NULL, NULL, = &mPkcs5TestNum, mPkcs5Test}, diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c b/C= ryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c new file mode 100644 index 000000000000..5ac2f325fbdd --- /dev/null +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaPssTests.c @@ -0,0 +1,191 @@ +/** @file + Application for RSA PSS Primitives Validation. + +Copyright (c) 2021, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "TestBaseCryptLib.h" + +// +// RSA PSS test vectors from NIST FIPS 186-3 RSA files +// + +// +// Public Modulus of RSA Key +// +UINT8 RsaPssN[]=3D{ + 0xa4, 0x7d, 0x04, 0xe7, 0xca, 0xcd, 0xba, 0x4e, 0xa2, 0x6e, 0xca, 0x8a= , 0x4c, 0x6e, 0x14, 0x56, + 0x3c, 0x2c, 0xe0, 0x3b, 0x62, 0x3b, 0x76, 0x8c, 0x0d, 0x49, 0x86, 0x8a= , 0x57, 0x12, 0x13, 0x01, + 0xdb, 0xf7, 0x83, 0xd8, 0x2f, 0x4c, 0x05, 0x5e, 0x73, 0x96, 0x0e, 0x70= , 0x55, 0x01, 0x87, 0xd0, + 0xaf, 0x62, 0xac, 0x34, 0x96, 0xf0, 0xa3, 0xd9, 0x10, 0x3c, 0x2e, 0xb7= , 0x91, 0x9a, 0x72, 0x75, + 0x2f, 0xa7, 0xce, 0x8c, 0x68, 0x8d, 0x81, 0xe3, 0xae, 0xe9, 0x94, 0x68= , 0x88, 0x7a, 0x15, 0x28, + 0x8a, 0xfb, 0xb7, 0xac, 0xb8, 0x45, 0xb7, 0xc5, 0x22, 0xb5, 0xc6, 0x4e= , 0x67, 0x8f, 0xcd, 0x3d, + 0x22, 0xfe, 0xb8, 0x4b, 0x44, 0x27, 0x27, 0x00, 0xbe, 0x52, 0x7d, 0x2b= , 0x20, 0x25, 0xa3, 0xf8, + 0x3c, 0x23, 0x83, 0xbf, 0x6a, 0x39, 0xcf, 0x5b, 0x4e, 0x48, 0xb3, 0xcf= , 0x2f, 0x56, 0xee, 0xf0, + 0xdf, 0xff, 0x18, 0x55, 0x5e, 0x31, 0x03, 0x7b, 0x91, 0x52, 0x48, 0x69= , 0x48, 0x76, 0xf3, 0x04, + 0x78, 0x14, 0x41, 0x51, 0x64, 0xf2, 0xc6, 0x60, 0x88, 0x1e, 0x69, 0x4b= , 0x58, 0xc2, 0x80, 0x38, + 0xa0, 0x32, 0xad, 0x25, 0x63, 0x4a, 0xad, 0x7b, 0x39, 0x17, 0x1d, 0xee= , 0x36, 0x8e, 0x3d, 0x59, + 0xbf, 0xb7, 0x29, 0x9e, 0x46, 0x01, 0xd4, 0x58, 0x7e, 0x68, 0xca, 0xaf= , 0x8d, 0xb4, 0x57, 0xb7, + 0x5a, 0xf4, 0x2f, 0xc0, 0xcf, 0x1a, 0xe7, 0xca, 0xce, 0xd2, 0x86, 0xd7= , 0x7f, 0xac, 0x6c, 0xed, + 0xb0, 0x3a, 0xd9, 0x4f, 0x14, 0x33, 0xd2, 0xc9, 0x4d, 0x08, 0xe6, 0x0b= , 0xc1, 0xfd, 0xef, 0x05, + 0x43, 0xcd, 0x29, 0x51, 0xe7, 0x65, 0xb3, 0x82, 0x30, 0xfd, 0xd1, 0x8d= , 0xe5, 0xd2, 0xca, 0x62, + 0x7d, 0xdc, 0x03, 0x2f, 0xe0, 0x5b, 0xbd, 0x2f, 0xf2, 0x1e, 0x2d, 0xb1= , 0xc2, 0xf9, 0x4d, 0x8b, + }; + +// +// Public Exponent of RSA Key +// +UINT8 RsaPssE[]=3D{ 0x10, 0xe4, 0x3f }; + +// +// Private Exponent of RSA Key +// +UINT8 RsaPssD[]=3D{ + 0x11, 0xa0, 0xdd, 0x28, 0x5f, 0x66, 0x47, 0x1a, 0x8d, 0xa3, 0x0b, 0xcb= , 0x8c, 0x24, 0xa1, 0xd5, + 0xc8, 0xdb, 0x94, 0x2f, 0xc9, 0x92, 0x07, 0x97, 0xca, 0x44, 0x24, 0x60= , 0xa8, 0x00, 0xb7, 0x5b, + 0xbc, 0x73, 0x8b, 0xeb, 0x8e, 0xe0, 0xe8, 0x74, 0xb0, 0x53, 0xe6, 0x47= , 0x07, 0xdf, 0x4c, 0xfc, + 0x78, 0x37, 0xc4, 0x0e, 0x5b, 0xe6, 0x8b, 0x8a, 0x8e, 0x1d, 0x01, 0x45= , 0x16, 0x9c, 0xa6, 0x27, + 0x1d, 0x81, 0x88, 0x7e, 0x19, 0xa1, 0xcd, 0x95, 0xb2, 0xfd, 0x0d, 0xe0= , 0xdb, 0xa3, 0x47, 0xfe, + 0x63, 0x7b, 0xcc, 0x6c, 0xdc, 0x24, 0xee, 0xbe, 0x03, 0xc2, 0x4d, 0x4c= , 0xf3, 0xa5, 0xc6, 0x15, + 0x4d, 0x78, 0xf1, 0x41, 0xfe, 0x34, 0x16, 0x99, 0x24, 0xd0, 0xf8, 0x95= , 0x33, 0x65, 0x8e, 0xac, + 0xfd, 0xea, 0xe9, 0x9c, 0xe1, 0xa8, 0x80, 0x27, 0xc1, 0x8f, 0xf9, 0x26= , 0x53, 0xa8, 0x35, 0xaa, + 0x38, 0x91, 0xbf, 0xff, 0xcd, 0x38, 0x8f, 0xfc, 0x23, 0x88, 0xce, 0x2b= , 0x10, 0x56, 0x85, 0x43, + 0x75, 0x05, 0x02, 0xcc, 0xbc, 0x69, 0xc0, 0x08, 0x8f, 0x1d, 0x69, 0x0e= , 0x97, 0xa5, 0xf5, 0xbd, + 0xd1, 0x88, 0x8c, 0xd2, 0xfa, 0xa4, 0x3c, 0x04, 0xae, 0x24, 0x53, 0x95= , 0x22, 0xdd, 0xe2, 0xd9, + 0xc2, 0x02, 0xf6, 0x55, 0xfc, 0x55, 0x75, 0x44, 0x40, 0xb5, 0x3a, 0x15= , 0x32, 0xaa, 0xb4, 0x78, + 0x51, 0xf6, 0x0b, 0x7a, 0x06, 0x7e, 0x24, 0x0b, 0x73, 0x8e, 0x1b, 0x1d= , 0xaa, 0xe6, 0xca, 0x0d, + 0x59, 0xee, 0xae, 0x27, 0x68, 0x6c, 0xd8, 0x88, 0x57, 0xe9, 0xad, 0xad= , 0xc2, 0xd4, 0xb8, 0x2b, + 0x07, 0xa6, 0x1a, 0x35, 0x84, 0x56, 0xaa, 0xf8, 0x07, 0x66, 0x96, 0x93= , 0xff, 0xb1, 0x3c, 0x99, + 0x64, 0xa6, 0x36, 0x54, 0xca, 0xdc, 0x81, 0xee, 0x59, 0xdf, 0x51, 0x1c= , 0xa3, 0xa4, 0xbd, 0x67, + }; + +// +// Binary message to be signed and verified +// +UINT8 PssMessage[]=3D{ + 0xe0, 0x02, 0x37, 0x7a, 0xff, 0xb0, 0x4f, 0x0f, 0xe4, 0x59, 0x8d, 0xe9= , 0xd9, 0x2d, 0x31, 0xd6, + 0xc7, 0x86, 0x04, 0x0d, 0x57, 0x76, 0x97, 0x65, 0x56, 0xa2, 0xcf, 0xc5= , 0x5e, 0x54, 0xa1, 0xdc, + 0xb3, 0xcb, 0x1b, 0x12, 0x6b, 0xd6, 0xa4, 0xbe, 0xd2, 0xa1, 0x84, 0x99= , 0x0c, 0xce, 0xa7, 0x73, + 0xfc, 0xc7, 0x9d, 0x24, 0x65, 0x53, 0xe6, 0xc6, 0x4f, 0x68, 0x6d, 0x21= , 0xad, 0x41, 0x52, 0x67, + 0x3c, 0xaf, 0xec, 0x22, 0xae, 0xb4, 0x0f, 0x6a, 0x08, 0x4e, 0x8a, 0x5b= , 0x49, 0x91, 0xf4, 0xc6, + 0x4c, 0xf8, 0xa9, 0x27, 0xef, 0xfd, 0x0f, 0xd7, 0x75, 0xe7, 0x1e, 0x83= , 0x29, 0xe4, 0x1f, 0xdd, + 0x44, 0x57, 0xb3, 0x91, 0x11, 0x73, 0x18, 0x7b, 0x4f, 0x09, 0xa8, 0x17= , 0xd7, 0x9e, 0xa2, 0x39, + 0x7f, 0xc1, 0x2d, 0xfe, 0x3d, 0x9c, 0x9a, 0x02, 0x90, 0xc8, 0xea, 0xd3= , 0x1b, 0x66, 0x90, 0xa6, + }; + +// +// Binary message to be signed and verified +// +UINT8 PssSalt[]=3D{ + 0xd6, 0x6f, 0x72, 0xf1, 0x0b, 0x69, 0x00, 0x1a, 0x5b, 0x59, 0xcf, 0x10= , 0x92, 0xad, 0x27, 0x4d, + 0x50, 0x56, 0xc4, 0xe9, 0x5c, 0xcc, 0xcf, 0xbe, 0x3b, 0x53, 0x0d, 0xcb= , 0x02, 0x7e, 0x57, 0xd6 + }; + +// +// RSASSA-PSS Signature over above message using above keys, salt and SHA2= 56 digest(and MGF1) algo. +// +UINT8 TestVectorSignature[]=3D{ + 0x4f, 0x9b, 0x42, 0x5c, 0x20, 0x58, 0x46, 0x0e, 0x4a, 0xb2, 0xf5, 0xc9= , 0x63, 0x84, 0xda, 0x23, + 0x27, 0xfd, 0x29, 0x15, 0x0f, 0x01, 0x95, 0x5a, 0x76, 0xb4, 0xef, 0xe9= , 0x56, 0xaf, 0x06, 0xdc, + 0x08, 0x77, 0x9a, 0x37, 0x4e, 0xe4, 0x60, 0x7e, 0xab, 0x61, 0xa9, 0x3a= , 0xdc, 0x56, 0x08, 0xf4, + 0xec, 0x36, 0xe4, 0x7f, 0x2a, 0x0f, 0x75, 0x4e, 0x8f, 0xf8, 0x39, 0xa8= , 0xa1, 0x9b, 0x1d, 0xb1, + 0xe8, 0x84, 0xea, 0x4c, 0xf3, 0x48, 0xcd, 0x45, 0x50, 0x69, 0xeb, 0x87= , 0xaf, 0xd5, 0x36, 0x45, + 0xb4, 0x4e, 0x28, 0xa0, 0xa5, 0x68, 0x08, 0xf5, 0x03, 0x1d, 0xa5, 0xba= , 0x91, 0x12, 0x76, 0x8d, + 0xfb, 0xfc, 0xa4, 0x4e, 0xbe, 0x63, 0xa0, 0xc0, 0x57, 0x2b, 0x73, 0x1d= , 0x66, 0x12, 0x2f, 0xb7, + 0x16, 0x09, 0xbe, 0x14, 0x80, 0xfa, 0xa4, 0xe4, 0xf7, 0x5e, 0x43, 0x95= , 0x51, 0x59, 0xd7, 0x0f, + 0x08, 0x1e, 0x2a, 0x32, 0xfb, 0xb1, 0x9a, 0x48, 0xb9, 0xf1, 0x62, 0xcf= , 0x6b, 0x2f, 0xb4, 0x45, + 0xd2, 0xd6, 0x99, 0x4b, 0xc5, 0x89, 0x10, 0xa2, 0x6b, 0x59, 0x43, 0x47= , 0x78, 0x03, 0xcd, 0xaa, + 0xa1, 0xbd, 0x74, 0xb0, 0xda, 0x0a, 0x5d, 0x05, 0x3d, 0x8b, 0x1d, 0xc5= , 0x93, 0x09, 0x1d, 0xb5, + 0x38, 0x83, 0x83, 0xc2, 0x60, 0x79, 0xf3, 0x44, 0xe2, 0xae, 0xa6, 0x00= , 0xd0, 0xe3, 0x24, 0x16, + 0x4b, 0x45, 0x0f, 0x7b, 0x9b, 0x46, 0x51, 0x11, 0xb7, 0x26, 0x5f, 0x3b= , 0x1b, 0x06, 0x30, 0x89, + 0xae, 0x7e, 0x26, 0x23, 0xfc, 0x0f, 0xda, 0x80, 0x52, 0xcf, 0x4b, 0xf3= , 0x37, 0x91, 0x02, 0xfb, + 0xf7, 0x1d, 0x7c, 0x98, 0xe8, 0x25, 0x86, 0x64, 0xce, 0xed, 0x63, 0x7d= , 0x20, 0xf9, 0x5f, 0xf0, + 0x11, 0x18, 0x81, 0xe6, 0x50, 0xce, 0x61, 0xf2, 0x51, 0xd9, 0xc3, 0xa6= , 0x29, 0xef, 0x22, 0x2d, + }; + + +VOID *mRsa; + +UNIT_TEST_STATUS +EFIAPI +TestVerifyRsaPssPreReq ( + UNIT_TEST_CONTEXT Context + ) +{ + mRsa =3D RsaNew (); + + if (mRsa =3D=3D NULL) { + return UNIT_TEST_ERROR_TEST_FAILED; + } + + return UNIT_TEST_PASSED; +} + +VOID +EFIAPI +TestVerifyRsaPssCleanUp ( + UNIT_TEST_CONTEXT Context + ) +{ + if (mRsa !=3D NULL) { + RsaFree (mRsa); + mRsa =3D NULL; + } +} + + +UNIT_TEST_STATUS +EFIAPI +TestVerifyRsaPssSignVerify ( + IN UNIT_TEST_CONTEXT Context + ) +{ + UINT8 *Signature; + UINTN SigSize; + BOOLEAN Status; + + Status =3D RsaSetKey (mRsa, RsaKeyN, RsaPssN, sizeof (RsaPssN)); + UT_ASSERT_TRUE (Status); + + Status =3D RsaSetKey (mRsa, RsaKeyE, RsaPssE, sizeof (RsaPssE)); + UT_ASSERT_TRUE (Status); + + Status =3D RsaSetKey (mRsa, RsaKeyD, RsaPssD, sizeof (RsaPssD)); + UT_ASSERT_TRUE (Status); + + SigSize =3D 0; + Status =3D RsaPssSign (mRsa, PssMessage, sizeof(PssMessage), SHA256_DIGE= ST_SIZE, SHA256_DIGEST_SIZE, NULL, &SigSize); + UT_ASSERT_FALSE (Status); + UT_ASSERT_NOT_EQUAL (SigSize, 0); + + Signature =3D AllocatePool (SigSize); + Status =3D RsaPssSign (mRsa, PssMessage, sizeof(PssMessage), SHA256_DIGE= ST_SIZE, SHA256_DIGEST_SIZE, Signature, &SigSize); + UT_ASSERT_TRUE (Status); + + // + // Verify RSA PSS encoded Signature generated in above step + // + Status =3D RsaPssVerify (mRsa, PssMessage, sizeof(PssMessage), Signature= , SigSize, SHA256_DIGEST_SIZE, SHA256_DIGEST_SIZE); + UT_ASSERT_TRUE (Status); + + // + // Verify NIST FIPS 186-3 RSA test vector signature + // + Status =3D RsaPssVerify (mRsa, PssMessage, sizeof(PssMessage), TestVecto= rSignature, sizeof(TestVectorSignature), SHA256_DIGEST_SIZE, SHA256_DIGEST_= SIZE); + UT_ASSERT_TRUE (Status); + + FreePool(Signature); + return UNIT_TEST_PASSED; +} + + +TEST_DESC mRsaPssTest[] =3D { + // + // -----Description--------------------------------------Class--------= --------------Function---------------------------------Pre-----------------= ----Post---------Context + // + {"TestVerifyRsaPssSignVerify()", "CryptoPkg.BaseCryptLib.Rsa= ", TestVerifyRsaPssSignVerify, TestVerifyRsaPssPreReq, TestVeri= fyRsaPssCleanUp, NULL}, +}; + +UINTN mRsaPssTestNum =3D ARRAY_SIZE(mRsaPssTest); diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaTests.c b/Cryp= toPkg/Test/UnitTest/Library/BaseCryptLib/RsaTests.c index 7ce20d2e778f..0969b6aea660 100644 --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaTests.c +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/RsaTests.c @@ -295,6 +295,8 @@ TestVerifyRsaPkcs1SignVerify ( Status =3D RsaPkcs1Verify (mRsa, HashValue, HashSize, Signature, SigSize= ); UT_ASSERT_TRUE (Status); =20 + FreePool(Signature); + return UNIT_TEST_PASSED; } =20 diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/L= ibrary/BaseCryptLib.h index 496121e6a4ed..8c7d5922ef96 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -1363,6 +1363,80 @@ RsaPkcs1Verify ( IN UINTN SigSize ); =20 +/** + Carries out the RSA-SSA signature generation with EMSA-PSS encoding sche= me. + + 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 < 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 genera= tion. + @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 fo= r 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 signat= ure. + @param[in, out] SigSize On input, the size of Signature buffer in b= ytes. + On output, the size of data returned in Sig= nature 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 + ); + +/** + Verifies the RSA signature with RSASSA-PSS signature scheme defined in R= FC 8017. + Implementation determines salt length automatically from the signature e= ncoding. + 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 verific= ation. + @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 verifi= ed. + @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 + ); + /** Retrieve the RSA Private Key from the password-protected PEM key data. =20 diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Li= brary/BaseCryptLib/BaseCryptLib.inf index 4aae2aba95d6..49703fa4c963 100644 --- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf @@ -49,6 +49,8 @@ Pk/CryptX509.c Pk/CryptAuthenticode.c Pk/CryptTs.c + Pk/CryptRsaPss.c + Pk/CryptRsaPssSign.c Pem/CryptPem.c =20 SysCall/CrtWrapper.c diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Lib= rary/BaseCryptLib/PeiCryptLib.inf index 7509e4273028..0cab5f3ce36c 100644 --- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf @@ -55,6 +55,8 @@ Pk/CryptX509Null.c Pk/CryptAuthenticodeNull.c Pk/CryptTsNull.c + Pk/CryptRsaPss.c + Pk/CryptRsaPssSignNull.c Pem/CryptPemNull.c Rand/CryptRandNull.c =20 diff --git a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf b/CryptoPkg= /Library/BaseCryptLib/RuntimeCryptLib.inf index 70c985ec93dc..3d3a6fb94a77 100644 --- a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf @@ -55,6 +55,8 @@ Pk/CryptX509.c Pk/CryptAuthenticodeNull.c Pk/CryptTsNull.c + Pk/CryptRsaPssNull.c + Pk/CryptRsaPssSignNull.c Pem/CryptPem.c =20 SysCall/CrtWrapper.c diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Lib= rary/BaseCryptLib/SmmCryptLib.inf index 91ec3e03bf5e..07c376ce04bb 100644 --- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf @@ -53,6 +53,8 @@ Pk/CryptX509.c Pk/CryptAuthenticodeNull.c Pk/CryptTsNull.c + Pk/CryptRsaPss.c + Pk/CryptRsaPssSignNull.c Pem/CryptPem.c =20 SysCall/CrtWrapper.c diff --git a/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf b/= CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf index db506c32f724..b98f9635b27b 100644 --- a/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf +++ b/CryptoPkg/Library/BaseCryptLib/UnitTestHostBaseCryptLib.inf @@ -44,6 +44,8 @@ Pk/CryptAuthenticode.c Pk/CryptTs.c Pem/CryptPem.c + Pk/CryptRsaPss.c + Pk/CryptRsaPssSign.c =20 SysCall/UnitTestHostCrtWrapper.c =20 diff --git a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf b/Cryp= toPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf index 689af4fedd68..faf959827b90 100644 --- a/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf +++ b/CryptoPkg/Library/BaseCryptLibNull/BaseCryptLibNull.inf @@ -50,6 +50,8 @@ Pk/CryptTsNull.c Pem/CryptPemNull.c Rand/CryptRandNull.c + Pk/CryptRsaPssNull.c + Pk/CryptRsaPssSignNull.c =20 [Packages] MdePkg/MdePkg.dec diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protoc= ol/Crypto.h index 17930a77a60e..e304302c9445 100644 --- a/CryptoPkg/Private/Protocol/Crypto.h +++ b/CryptoPkg/Private/Protocol/Crypto.h @@ -3408,6 +3408,81 @@ EFI_STATUS IN OUT UINTN *DataSize ); =20 +/** + Carries out the RSA-SSA signature generation with EMSA-PSS encoding sche= me. + + 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 < 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 genera= tion. + @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 fo= r 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 signat= ure. + @param[in, out] SigSize On input, the size of Signature buffer in b= ytes. + On output, the size of data returned in Sig= nature 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)( + IN VOID *RsaContext, + IN CONST UINT8 *Message, + IN UINTN MsgSize, + IN UINT16 DigestLen, + IN UINT16 SaltLen, + OUT UINT8 *Signature, + IN OUT UINTN *SigSize + ); + +/** + Verifies the RSA signature with RSASSA-PSS signature scheme defined in R= FC 8017. + Implementation determines salt length automatically from the signature e= ncoding. + 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 verific= ation. + @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 verifi= ed. + @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. + +**/ +typedef +BOOLEAN +(EFIAPI* EDKII_CRYPTO_RSA_PSS_VERIFY)( + IN VOID *RsaContext, + IN CONST UINT8 *Message, + IN UINTN MsgSize, + IN CONST UINT8 *Signature, + IN UINTN SigSize, + IN UINT16 DigestLen, + IN UINT16 SaltLen + ); + + =20 /// /// EDK II Crypto Protocol @@ -3593,6 +3668,9 @@ struct _EDKII_CRYPTO_PROTOCOL { EDKII_CRYPTO_TLS_GET_HOST_PUBLIC_CERT TlsGetHostPublicCert; EDKII_CRYPTO_TLS_GET_HOST_PRIVATE_KEY TlsGetHostPrivateKey; EDKII_CRYPTO_TLS_GET_CERT_REVOCATION_LIST TlsGetCertRevocationList; + /// RSA PSS + EDKII_CRYPTO_RSA_PSS_SIGN RsaPssSign; + EDKII_CRYPTO_RSA_PSS_VERIFY RsaPssVerify; }; =20 extern GUID gEdkiiCryptoProtocolGuid; diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.= h b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h index 9d1cb150a113..25c1379f1a77 100644 --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLib.h @@ -83,6 +83,9 @@ extern TEST_DESC mPrngTest[]; extern UINTN mOaepTestNum; extern TEST_DESC mOaepTest[]; =20 +extern UINTN mRsaPssTestNum; +extern TEST_DESC mRsaPssTest[]; + /** Creates a framework you can use */ EFI_STATUS EFIAPI diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibH= ost.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost= .inf index 300b98e40b33..00c869265080 100644 --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibHost.inf @@ -34,6 +34,7 @@ RandTests.c Pkcs7EkuTests.c OaepEncryptTests.c + RsaPssTests.c =20 [Packages] MdePkg/MdePkg.dec diff --git a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibS= hell.inf b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShe= ll.inf index d5e7e0d01446..ca789aa6ada3 100644 --- a/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf +++ b/CryptoPkg/Test/UnitTest/Library/BaseCryptLib/TestBaseCryptLibShell.inf @@ -35,6 +35,7 @@ RandTests.c Pkcs7EkuTests.c OaepEncryptTests.c + RsaPssTests.c =20 [Packages] MdePkg/MdePkg.dec --=20 2.14.3.windows.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#74566): https://edk2.groups.io/g/devel/message/74566 Mute This Topic: https://groups.io/mt/82434092/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-