public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
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