From: Minh Nguyen <minhnguyen1@os.amperecomputing.com>
To: devel@edk2.groups.io
Cc: tamnguyenchi@os.amperecomputing.com, nhi@os.amperecomputing.com,
Jiewen Yao <jiewen.yao@intel.com>,
Jian J Wang <jian.j.wang@intel.com>,
Xiaoyu Lu <xiaoyu1.lu@intel.com>,
Guomin Jiang <guomin.jiang@intel.com>,
Minh Nguyen <minhnguyen1@os.amperecomputing.com>
Subject: [PATCH 1/1] CryptoPkg: Add new API to get PKCS7 Signature
Date: Tue, 16 May 2023 13:53:35 +0700 [thread overview]
Message-ID: <20230516065335.3603101-1-minhnguyen1@os.amperecomputing.com> (raw)
From: Tam Chi Nguyen <tamnguyenchi@os.amperecomputing.com>
This patch adds a new Pkcs7GetSignature API to support
extracting the signature data from PKCS7 Certificate.
Cc: Jiewen Yao <jiewen.yao@intel.com>
Cc: Jian J Wang <jian.j.wang@intel.com>
Cc: Xiaoyu Lu <xiaoyu1.lu@intel.com>
Cc: Guomin Jiang <guomin.jiang@intel.com>
Signed-off-by: Minh Nguyen <minhnguyen1@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
reply other threads:[~2023-05-16 6:54 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230516065335.3603101-1-minhnguyen1@os.amperecomputing.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox