public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [edk2-devel] [PATCH 1/1] CryptoPkg: Add new API to get PKCS7 Signature
@ 2024-01-30  5:44 Nhi Pham via groups.io
  2024-01-30  9:46 ` Wenxing Hou
  0 siblings, 1 reply; 5+ messages in thread
From: Nhi Pham via groups.io @ 2024-01-30  5:44 UTC (permalink / raw)
  To: devel; +Cc: Tam Chi Nguyen, Jiewen Yao, Wenxing Hou, Yi Li, Nhi Pham

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: Wenxing Hou <wenxing.hou@intel.com>
Cc: Yi Li <yi1.li@intel.com>
Signed-off-by: Nhi Pham <nhi@os.amperecomputing.com>
---
 CryptoPkg/Include/Library/BaseCryptLib.h                   |  29 +++++
 CryptoPkg/Private/Protocol/Crypto.h                        |  29 +++++
 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, 276 insertions(+)

diff --git a/CryptoPkg/Include/Library/BaseCryptLib.h b/CryptoPkg/Include/Library/BaseCryptLib.h
index a52bd91ad664..d52a91244482 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) 2024, 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..d228cea0453b 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) 2024, 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
 // =====================================================================================
diff --git a/CryptoPkg/Driver/Crypto.c b/CryptoPkg/Driver/Crypto.c
index bdbb4863a97e..83094e73c33a 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) 2024, 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
 // =====================================================================================
@@ -6748,6 +6780,7 @@ const EDKII_CRYPTO_PROTOCOL  mEdkiiCrypto = {
   CryptoServicePkcs7GetCertificatesList,
   CryptoServiceAuthenticodeVerify,
   CryptoServiceImageTimestampVerify,
+  CryptoServicePkcs7GetSignature,
   /// DH
   CryptoServiceDhNew,
   CryptoServiceDhFree,
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c
index 4e5a14e35210..9e3fccf1bb4e 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) 2024, Ampere Computing LLC. All rights reserved.<BR>
 SPDX-License-Identifier: BSD-2-Clause-Patent
 
 **/
@@ -926,3 +927,122 @@ _Exit:
 
   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..a080bbfc4237 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) 2024, 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..55d7b17688a0 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) 2024, 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.25.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#114759): https://edk2.groups.io/g/devel/message/114759
Mute This Topic: https://groups.io/mt/104048629/7686176
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [rebecca@openfw.io]
-=-=-=-=-=-=-=-=-=-=-=-



^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-02-19  3:31 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-01-30  5:44 [edk2-devel] [PATCH 1/1] CryptoPkg: Add new API to get PKCS7 Signature Nhi Pham via groups.io
2024-01-30  9:46 ` Wenxing Hou
2024-01-30  9:48   ` Nhi Pham via groups.io
2024-02-01  2:09     ` Yao, Jiewen
2024-02-19  3:31       ` Nhi Pham via groups.io

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox