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]
-=-=-=-=-=-=-=-=-=-=-=-


Reply via email to