From: Tam Chi Nguyen <tamnguyen...@os.amperecomputing.com> This patch adds a new Pkcs7GetSignature API to support extracting the signature data from PKCS7 Certificate.
Cc: Jiewen Yao <jiewen....@intel.com> Cc: Jian J Wang <jian.j.w...@intel.com> Cc: Xiaoyu Lu <xiaoyu1...@intel.com> Cc: Guomin Jiang <guomin.ji...@intel.com> Signed-off-by: Minh Nguyen <minhnguy...@os.amperecomputing.com> --- CryptoPkg/Include/Library/BaseCryptLib.h | 29 +++++ CryptoPkg/Private/Protocol/Crypto.h | 30 +++++ CryptoPkg/Driver/Crypto.c | 33 ++++++ CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c | 120 ++++++++++++++++++++ CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c | 33 ++++++ CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c | 32 ++++++ 6 files changed, 277 insertions(+) diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h index a52bd91ad664..e277ea188de8 100644 --- a/CryptoPkg/Include/Library/BaseCryptLib.h +++ b/CryptoPkg/Include/Library/BaseCryptLib.h @@ -5,6 +5,7 @@ functionality enabling. Copyright (c) 2009 - 2022, Intel Corporation. All rights reserved.<BR> +Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -2471,6 +2472,34 @@ ImageTimestampVerify ( OUT EFI_TIME *SigningTime ); +/** + Get the data signature from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, Signature, SignatureLength is NULL, then return FALSE. + If P7Length overflow, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] Signature Pointer to Signature data + @param[out] SignatureLength Length of signature in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetSignature ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **Signature, + OUT UINTN *SignatureLength + ); + /** Retrieve the version from one X.509 certificate. diff --git a/CryptoPkg/Private/Protocol/Crypto.h b/CryptoPkg/Private/Protocol/Crypto.h index 0e0b1d94018d..25cd03fb08a3 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.<BR> + Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -1036,6 +1037,34 @@ BOOLEAN OUT EFI_TIME *SigningTime ); +/** + Get the data signature from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, Signature, SignatureLength is NULL, then return FALSE. + If P7Length overflow, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] Signature Pointer to Signature data + @param[out] SignatureLength Length of signature in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + @retval FALSE This interface is not supported. + +**/ +typedef +BOOLEAN +(EFIAPI *EDKII_CRYPTO_PKCS7_GET_SIGNATURE) ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **Signature, + OUT UINTN *SignatureLength + ); + // ===================================================================================== // DH Key Exchange Primitive // ===================================================================================== @@ -5371,6 +5400,7 @@ struct _EDKII_CRYPTO_PROTOCOL { EDKII_CRYPTO_PKCS7_SIGN Pkcs7Sign; EDKII_CRYPTO_PKCS7_GET_ATTACHED_CONTENT Pkcs7GetAttachedContent; EDKII_CRYPTO_PKCS7_GET_CERTIFICATES_LIST Pkcs7GetCertificatesList; + EDKII_CRYPTO_PKCS7_GET_SIGNATURE Pkcs7GetSignature; EDKII_CRYPTO_AUTHENTICODE_VERIFY AuthenticodeVerify; EDKII_CRYPTO_IMAGE_TIMESTAMP_VERIFY ImageTimestampVerify; /// DH diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c index bdbb4863a97e..9b55b70f1c48 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.<BR> + Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -3910,6 +3911,37 @@ CryptoServiceImageTimestampVerify ( return CALL_BASECRYPTLIB (Pkcs.Services.ImageTimestampVerify, ImageTimestampVerify, (AuthData, DataSize, TsaCert, CertSize, SigningTime), FALSE); } +/** + Get the data signature from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, Signature, SignatureLength is NULL, then return FALSE. + If P7Length overflow, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] Signature Pointer to Signature data + @param[out] SignatureLength Length of signature in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +CryptoServicePkcs7GetSignature ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **Signature, + OUT UINTN *SignatureLength + ) +{ + return CALL_BASECRYPTLIB (Pkcs.Services.Pkcs7GetSignature, Pkcs7GetSignature, (P7Data, P7Length, Signature, SignatureLength), FALSE); +} + // ===================================================================================== // DH Key Exchange Primitive // ===================================================================================== @@ -6746,6 +6778,7 @@ const EDKII_CRYPTO_PROTOCOL mEdkiiCrypto = { CryptoServicePkcs7Sign, CryptoServicePkcs7GetAttachedContent, CryptoServicePkcs7GetCertificatesList, + CryptoServicePkcs7GetSignature, CryptoServiceAuthenticodeVerify, CryptoServiceImageTimestampVerify, /// DH diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c index 4e5a14e35210..cb3e647c56c9 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c @@ -11,6 +11,7 @@ Variable and will do basic check for data structure. Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR> +Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -926,3 +927,122 @@ Pkcs7Verify ( return Status; } + +/** + Get the data signature from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, Signature, SignatureLength is NULL, then return FALSE. + If P7Length overflow, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] Signature Pointer to Signature data + @param[out] SignatureLength Length of signature in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetSignature ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **Signature, + OUT UINTN *SignatureLength + ) +{ + PKCS7 *Pkcs7; + BOOLEAN Wrapped; + BOOLEAN Status; + UINT8 *SignedData; + UINT8 *Temp; + UINTN SignedDataSize; + STACK_OF (PKCS7_SIGNER_INFO) *SignerInfos; + PKCS7_SIGNER_INFO *SignInfo; + ASN1_OCTET_STRING *EncDigest; + + if ((P7Data == NULL) || (P7Length > INT_MAX) || + (Signature == NULL && SignatureLength == NULL)) { + return FALSE; + } + + Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize); + if (!Status) { + return Status; + } + + Status = FALSE; + Pkcs7 = NULL; + // + // Retrieve PKCS#7 Data (DER encoding) + // + if (SignedDataSize > INT_MAX) { + goto _Exit; + } + + Temp = SignedData; + Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **) &Temp, (int) SignedDataSize); + if (Pkcs7 == NULL) { + goto _Exit; + } + + // + // Check if it's PKCS#7 Signed Data (for Authenticode Scenario) + // + if (!PKCS7_type_is_signed (Pkcs7)) { + goto _Exit; + } + + // + // Check if there is one and only one signer. + // + SignerInfos = PKCS7_get_signer_info (Pkcs7); + if (!SignerInfos || (sk_PKCS7_SIGNER_INFO_num (SignerInfos) != 1)) { + goto _Exit; + } + + // + // Locate the TimeStamp CounterSignature. + // + SignInfo = sk_PKCS7_SIGNER_INFO_value (SignerInfos, 0); + if (SignInfo == NULL) { + goto _Exit; + } + + // + // Locate Message Digest which will be the data to be time-stamped. + // + EncDigest = SignInfo->enc_digest; + if (EncDigest == NULL) { + goto _Exit; + } + + *SignatureLength = EncDigest->length; + if (Signature != NULL) + { + if (*Signature == NULL) { + Status = FALSE; + goto _Exit; + } + CopyMem ((VOID *)*Signature, EncDigest->data, EncDigest->length); + Status = TRUE; + } + +_Exit: + // + // Release Resources + // + if (!Wrapped) { + free (SignedData); + } + if (Pkcs7 != NULL) { + PKCS7_free (Pkcs7); + } + + return Status; +} diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c index b9b7960126de..1b093d509694 100644 --- a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c +++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyNull.c @@ -3,6 +3,7 @@ real capabilities. Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR> +Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -161,3 +162,35 @@ Pkcs7GetAttachedContent ( ASSERT (FALSE); return FALSE; } + +/** + Get the data signature from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, Signature, SignatureLength is NULL, then return FALSE. + If P7Length overflow, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] Signature Pointer to Signature data + @param[out] SignatureLength Length of signature in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetSignature ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **Signature, + OUT UINTN *SignatureLength + ) +{ + ASSERT (FALSE); + return FALSE; +} diff --git a/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c b/CryptoPkg/Library/BaseCryptLibOnProtocolPpi/CryptLib.c index 4e31bc278e0f..dcac864cc358 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.<BR> + Copyright (c) 2023, Ampere Computing LLC. All rights reserved.<BR> SPDX-License-Identifier: BSD-2-Clause-Patent **/ @@ -3146,6 +3147,37 @@ ImageTimestampVerify ( CALL_CRYPTO_SERVICE (ImageTimestampVerify, (AuthData, DataSize, TsaCert, CertSize, SigningTime), FALSE); } +/** + Get the data signature from PKCS#7 signed data as described in "PKCS #7: + Cryptographic Message Syntax Standard". The input signed data could be wrapped + in a ContentInfo structure. + + If P7Data, Signature, SignatureLength is NULL, then return FALSE. + If P7Length overflow, then return FALSE. + If this interface is not supported, then return FALSE. + + @param[in] P7Data Pointer to the PKCS#7 message to verify. + @param[in] P7Length Length of the PKCS#7 message in bytes. + @param[out] Signature Pointer to Signature data + @param[out] SignatureLength Length of signature in bytes. + + @retval TRUE The operation is finished successfully. + @retval FALSE Error occurs during the operation. + @retval FALSE This interface is not supported. + +**/ +BOOLEAN +EFIAPI +Pkcs7GetSignature ( + IN CONST UINT8 *P7Data, + IN UINTN P7Length, + OUT UINT8 **Signature, + OUT UINTN *SignatureLength + ) +{ + CALL_CRYPTO_SERVICE (Pkcs7GetSignature, (P7Data, P7Length, Signature, SignatureLength), FALSE); +} + // ===================================================================================== // DH Key Exchange Primitive // ===================================================================================== -- 2.39.0 -=-=-=-=-=-=-=-=-=-=-=- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#104978): https://edk2.groups.io/g/devel/message/104978 Mute This Topic: https://groups.io/mt/98948705/21656 Group Owner: devel+ow...@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [arch...@mail-archive.com] -=-=-=-=-=-=-=-=-=-=-=-