[edk2-devel] [edk2-staging/OpenSSL11_EOL PATCH 4/7] Update Pkcs7 api based on MbedTlsLib for CryptoPkg

Wenxing Hou wenxing.hou at intel.com
Fri Mar 17 09:00:50 UTC 2023


Signed-off-by: Wenxing Hou <wenxing.hou at intel.com>
---
 .../BaseCryptLibMbedTls/InternalCryptLib.h    |  32 ++
 .../BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c   |   5 +-
 .../Pk/CryptPkcs7VerifyBase.c                 |  40 +-
 .../Pk/CryptPkcs7VerifyCommon.c               | 338 ++++++++++++-
 .../Pk/CryptPkcs7VerifyEku.c                  | 454 ++----------------
 CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf   |   1 +
 6 files changed, 424 insertions(+), 446 deletions(-)

diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
index 674242cfeb..6871785575 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/InternalCryptLib.h
@@ -24,4 +24,36 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 
 int myrand( void *rng_state, unsigned char *output, size_t len );
 
+/**
+  Check input P7Data is a wrapped ContentInfo structure or not. If not construct
+  a new structure to wrap P7Data.
+
+  Caution: This function may receive untrusted input.
+  UEFI Authenticated Variable is external input, so this function will do basic
+  check for PKCS#7 data structure.
+
+  @param[in]  P7Data       Pointer to the PKCS#7 message to verify.
+  @param[in]  P7Length     Length of the PKCS#7 message in bytes.
+  @param[out] WrapFlag     If TRUE P7Data is a ContentInfo structure, otherwise
+                           return FALSE.
+  @param[out] WrapData     If return status of this function is TRUE:
+                           1) when WrapFlag is TRUE, pointer to P7Data.
+                           2) when WrapFlag is FALSE, pointer to a new ContentInfo
+                           structure. It's caller's responsibility to free this
+                           buffer.
+  @param[out] WrapDataSize Length of ContentInfo structure in bytes.
+
+  @retval     TRUE         The operation is finished successfully.
+  @retval     FALSE        The operation is failed due to lack of resources.
+
+**/
+BOOLEAN
+WrapPkcs7Data (
+  IN  CONST UINT8  *P7Data,
+  IN  UINTN        P7Length,
+  OUT BOOLEAN      *WrapFlag,
+  OUT UINT8        **WrapData,
+  OUT UINTN        *WrapDataSize
+  );
+
 #endif
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
index 0c7a1d009f..21d06264d5 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7Sign.c
@@ -388,7 +388,8 @@ Pkcs7Sign (
   mbedtls_pk_init (&Pkey);
   Ret = mbedtls_pk_parse_key (
     &Pkey, NewPrivateKey, PrivateKeySize,
-    KeyPassword, KeyPassword == NULL ? 0 : AsciiStrLen (KeyPassword)
+    KeyPassword, KeyPassword == NULL ? 0 : AsciiStrLen (KeyPassword),
+    NULL, NULL
   );
   if (Ret != 0) {
     Status = FALSE;
@@ -406,7 +407,7 @@ Pkcs7Sign (
   ZeroMem (Signature, MAX_SIGNATURE_SIZE);
   Ret = mbedtls_pk_sign (
     &Pkey, MBEDTLS_MD_SHA256, HashValue, SHA256_DIGEST_SIZE,
-    Signature, &SignatureLen, myrand, NULL);
+    Signature, MAX_SIGNATURE_SIZE, &SignatureLen, myrand, NULL);
   if (Ret != 0) {
     Status = FALSE;
     goto Cleanup;
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
index 01fcba5513..4daea4982f 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyBase.c
@@ -7,6 +7,7 @@ SPDX-License-Identifier: BSD-2-Clause-Patent
 **/
 
 #include "InternalCryptLib.h"
+#include <mbedtls/pkcs7.h>
 
 /**
   Extracts the attached content from a PKCS#7 signed data if existed. The input signed
@@ -38,12 +39,13 @@ Pkcs7GetAttachedContent (
   )
 {
   BOOLEAN            Status;
-  PKCS7              *Pkcs7;
   UINT8              *SignedData;
   UINTN              SignedDataSize;
   BOOLEAN            Wrapped;
-  CONST UINT8        *Temp;
-  ASN1_OCTET_STRING  *OctStr;
+  INTN               Ret;
+  mbedtls_pkcs7      Pkcs7;
+
+  mbedtls_pkcs7_init(&Pkcs7);
 
   //
   // Check input parameter.
@@ -53,9 +55,7 @@ Pkcs7GetAttachedContent (
   }
 
   *Content   = NULL;
-  Pkcs7      = NULL;
   SignedData = NULL;
-  OctStr     = NULL;
 
   Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);
   if (!Status || (SignedDataSize > INT_MAX)) {
@@ -64,26 +64,23 @@ Pkcs7GetAttachedContent (
 
   Status = FALSE;
 
-  //
-  // Decoding PKCS#7 SignedData
-  //
-  Temp  = SignedData;
-  Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&Temp, (int)SignedDataSize);
-  if (Pkcs7 == NULL) {
-    goto _Exit;
-  }
+  Ret = mbedtls_pkcs7_parse_der(&Pkcs7, SignedData, (INT32)SignedDataSize);
 
   //
   // The type of Pkcs7 must be signedData
   //
-  if (!PKCS7_type_is_signed (Pkcs7)) {
+  if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) {
     goto _Exit;
   }
 
   //
   // Check for detached or attached content
   //
-  if (PKCS7_get_detached (Pkcs7)) {
+
+  mbedtls_pkcs7_data *MbedtlsContent;
+  MbedtlsContent = &(Pkcs7.signed_data.content);
+
+  if (MbedtlsContent == NULL) {
     //
     // No Content supplied for PKCS7 detached signedData
     //
@@ -93,15 +90,14 @@ Pkcs7GetAttachedContent (
     //
     // Retrieve the attached content in PKCS7 signedData
     //
-    OctStr = Pkcs7->d.sign->contents->d.data;
-    if ((OctStr->length > 0) && (OctStr->data != NULL)) {
-      *ContentSize = OctStr->length;
+    if ((MbedtlsContent->data.len > 0) && (MbedtlsContent->data.p != NULL)) {
+      *ContentSize = MbedtlsContent->data.len;
       *Content     = AllocatePool (*ContentSize);
       if (*Content == NULL) {
         *ContentSize = 0;
         goto _Exit;
       }
-      CopyMem (*Content, OctStr->data, *ContentSize);
+      CopyMem (*Content, MbedtlsContent->data.p, *ContentSize);
     }
   }
   Status = TRUE;
@@ -110,11 +106,7 @@ _Exit:
   //
   // Release Resources
   //
-  PKCS7_free (Pkcs7);
-
-  if (!Wrapped) {
-    OPENSSL_free (SignedData);
-  }
+  mbedtls_pkcs7_free (&Pkcs7);
 
   return Status;
 }
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
index 5291f2454d..14c9d447e6 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyCommon.c
@@ -656,7 +656,7 @@ Pkcs7Verify (
 
   Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &WrapData, &WrapDataSize);
 
-  if (Status) {
+  if (!Status) {
     Ret = 0;
     Status = FALSE;
   } else {
@@ -741,5 +741,339 @@ Pkcs7GetSigners (
   OUT UINTN        *CertLength
   )
 {
-return FALSE;
+  BOOLEAN      Status;
+  UINT8        *SignedData;
+  UINTN        SignedDataSize;
+  BOOLEAN      Wrapped;
+  INTN               Ret;
+  mbedtls_pkcs7      Pkcs7;
+  mbedtls_x509_crt   *Cert;
+  UINT8  Index;
+  UINT8  *CertBuf;
+  UINT8  *OldBuf;
+  UINTN  BufferSize;
+  UINTN  OldSize;
+  UINT8  *SingleCert;
+  UINTN  SingleCertSize;
+
+
+  mbedtls_pkcs7_init(&Pkcs7);
+
+  //
+  // Check input parameter.
+  //
+  if ((P7Data == NULL) || (CertStack == NULL) || (StackLength == NULL) ||
+      (TrustedCert == NULL) || (CertLength == NULL) || (P7Length > INT_MAX))
+  {
+    return FALSE;
+  }
+
+  SignedData = NULL;
+
+  Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);
+  if (!Status || (SignedDataSize > INT_MAX)) {
+    goto _Exit;
+  }
+
+  Status = FALSE;
+
+  //
+  // Retrieve PKCS#7 Data (DER encoding)
+  //
+  if (SignedDataSize > INT_MAX) {
+    goto _Exit;
+  }
+
+  Ret = mbedtls_pkcs7_parse_der(&Pkcs7, SignedData, (INT32)SignedDataSize);
+
+  //
+  // The type of Pkcs7 must be signedData
+  //
+  if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) {
+    goto _Exit;
+  }
+
+
+  Cert      = NULL;
+  CertBuf    = NULL;
+  OldBuf     = NULL;
+  SingleCert = NULL;
+
+
+  Cert = &Pkcs7.signed_data.certs;
+  if (Cert == NULL) {
+    goto _Exit;
+  }
+
+  //
+  // Convert CertStack to buffer in following format:
+  // UINT8  CertNumber;
+  // UINT32 Cert1Length;
+  // UINT8  Cert1[];
+  // UINT32 Cert2Length;
+  // UINT8  Cert2[];
+  // ...
+  // UINT32 CertnLength;
+  // UINT8  Certn[];
+  //
+  BufferSize = sizeof (UINT8);
+  OldSize    = BufferSize;
+
+  for (Index = 0; ; Index++) {
+
+    SingleCertSize = Cert->raw.len;
+
+    OldSize    = BufferSize;
+    OldBuf     = CertBuf;
+    BufferSize = OldSize + SingleCertSize + sizeof (UINT32);
+    CertBuf    = AllocateZeroPool (BufferSize);
+
+    if (CertBuf == NULL) {
+      goto _Exit;
+    }
+
+    if (OldBuf != NULL) {
+      CopyMem (CertBuf, OldBuf, OldSize);
+      FreePool (OldBuf);
+      OldBuf = NULL;
+    }
+
+    WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)SingleCertSize);
+    CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, SingleCertSize);
+
+    FreePool (SingleCert);
+    SingleCert = NULL;
+
+    if (Cert->next == NULL) {
+      break;
+    }
+  }
+
+  if (CertBuf != NULL) {
+    //
+    // Update CertNumber.
+    //
+    CertBuf[0] = Index;
+
+    *CertLength  = BufferSize - OldSize - sizeof (UINT32);
+    *TrustedCert = AllocateZeroPool (*CertLength);
+    if (*TrustedCert == NULL) {
+      goto _Exit;
+    }
+
+    CopyMem (*TrustedCert, CertBuf + OldSize + sizeof (UINT32), *CertLength);
+    *CertStack   = CertBuf;
+    *StackLength = BufferSize;
+    Status       = TRUE;
+  }
+
+_Exit:
+  //
+  // Release Resources
+  //
+  if (!Wrapped) {
+    FreePool (SignedData);
+  }
+
+  mbedtls_pkcs7_free (&Pkcs7);
+
+  if (SingleCert !=  NULL) {
+    FreePool (SingleCert);
+  }
+
+  if (!Status && (CertBuf != NULL)) {
+    FreePool (CertBuf);
+    *CertStack = NULL;
+  }
+
+  if (OldBuf != NULL) {
+    FreePool (OldBuf);
+  }
+
+  return Status;
+}
+
+/**
+  Retrieves all embedded certificates from PKCS#7 signed data as described in "PKCS #7:
+  Cryptographic Message Syntax Standard", and outputs two certificate lists chained and
+  unchained to the signer's certificates.
+  The input signed data could be wrapped in a ContentInfo structure.
+
+  @param[in]  P7Data            Pointer to the PKCS#7 message.
+  @param[in]  P7Length          Length of the PKCS#7 message in bytes.
+  @param[out] SignerChainCerts  Pointer to the certificates list chained to signer's
+                                certificate. It's caller's responsibility to free the buffer
+                                with Pkcs7FreeSigners().
+                                This data structure is EFI_CERT_STACK type.
+  @param[out] ChainLength       Length of the chained certificates list buffer in bytes.
+  @param[out] UnchainCerts      Pointer to the unchained certificates lists. It's caller's
+                                responsibility to free the buffer with Pkcs7FreeSigners().
+                                This data structure is EFI_CERT_STACK type.
+  @param[out] UnchainLength     Length of the unchained certificates list buffer in bytes.
+
+  @retval  TRUE         The operation is finished successfully.
+  @retval  FALSE        Error occurs during the operation.
+
+**/
+BOOLEAN
+EFIAPI
+Pkcs7GetCertificatesList (
+  IN  CONST UINT8  *P7Data,
+  IN  UINTN        P7Length,
+  OUT UINT8        **SignerChainCerts,
+  OUT UINTN        *ChainLength,
+  OUT UINT8        **UnchainCerts,
+  OUT UINTN        *UnchainLength
+  )
+{
+  BOOLEAN      Status;
+  UINT8        *SignedData;
+  UINTN        SignedDataSize;
+  BOOLEAN      Wrapped;
+  INTN               Ret;
+  mbedtls_pkcs7      Pkcs7;
+  mbedtls_x509_crt   *Cert;
+  UINT8  Index;
+  UINT8  *CertBuf;
+  UINT8  *OldBuf;
+  UINTN  BufferSize;
+  UINTN  OldSize;
+  UINT8  *SingleCert;
+  UINTN  SingleCertSize;
+
+
+  mbedtls_pkcs7_init(&Pkcs7);
+
+  //
+  // Check input parameter.
+  //
+  if ((P7Data == NULL) || (SignerChainCerts == NULL) || (ChainLength == NULL) ||
+      (UnchainCerts == NULL) || (UnchainLength == NULL) || (P7Length > INT_MAX))
+  {
+    return FALSE;
+  }
+
+  SignedData = NULL;
+
+  Status = WrapPkcs7Data (P7Data, P7Length, &Wrapped, &SignedData, &SignedDataSize);
+  if (!Status || (SignedDataSize > INT_MAX)) {
+    goto _Exit;
+  }
+
+  Status = FALSE;
+
+  //
+  // Retrieve PKCS#7 Data (DER encoding)
+  //
+  if (SignedDataSize > INT_MAX) {
+    goto _Exit;
+  }
+
+  Ret = mbedtls_pkcs7_parse_der(&Pkcs7, SignedData, (INT32)SignedDataSize);
+
+  //
+  // The type of Pkcs7 must be signedData
+  //
+  if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) {
+    goto _Exit;
+  }
+
+
+  Cert      = NULL;
+  CertBuf    = NULL;
+  OldBuf     = NULL;
+  SingleCert = NULL;
+
+
+  Cert = &Pkcs7.signed_data.certs;
+  if (Cert == NULL) {
+    goto _Exit;
+  }
+
+  //
+  // Converts Chained and Untrusted Certificate to Certificate Buffer in following format:
+  //      UINT8  CertNumber;
+  //      UINT32 Cert1Length;
+  //      UINT8  Cert1[];
+  //      UINT32 Cert2Length;
+  //      UINT8  Cert2[];
+  //      ...
+  //      UINT32 CertnLength;
+  //      UINT8  Certn[];
+  //
+  BufferSize = sizeof (UINT8);
+  OldSize    = BufferSize;
+
+  for (Index = 0; ; Index++) {
+
+    SingleCertSize = Cert->raw.len;
+
+    OldSize    = BufferSize;
+    OldBuf     = CertBuf;
+    BufferSize = OldSize + SingleCertSize + sizeof (UINT32);
+    CertBuf    = AllocateZeroPool (BufferSize);
+
+    if (CertBuf == NULL) {
+      goto _Exit;
+    }
+
+    if (OldBuf != NULL) {
+      CopyMem (CertBuf, OldBuf, OldSize);
+      FreePool (OldBuf);
+      OldBuf = NULL;
+    }
+
+    WriteUnaligned32 ((UINT32 *)(CertBuf + OldSize), (UINT32)SingleCertSize);
+    CopyMem (CertBuf + OldSize + sizeof (UINT32), SingleCert, SingleCertSize);
+
+    FreePool (SingleCert);
+    SingleCert = NULL;
+
+    if (Cert->next == NULL) {
+      break;
+    }
+  }
+
+  if (CertBuf != NULL) {
+    //
+    // Update CertNumber.
+    //
+    CertBuf[0] = Index;
+
+    *UnchainLength  = BufferSize - OldSize - sizeof (UINT32);
+    *UnchainCerts = AllocateZeroPool (*UnchainLength);
+    if (*UnchainCerts == NULL) {
+      goto _Exit;
+    }
+
+    CopyMem (*UnchainCerts, CertBuf + OldSize + sizeof (UINT32), *UnchainLength);
+    *SignerChainCerts   = CertBuf;
+    *ChainLength = BufferSize;
+    Status       = TRUE;
+  }
+
+_Exit:
+  //
+  // Release Resources
+  //
+  if (!Wrapped) {
+    FreePool (SignedData);
+  }
+
+  mbedtls_pkcs7_free (&Pkcs7);
+
+  if (SingleCert !=  NULL) {
+    FreePool (SingleCert);
+  }
+
+  if (!Status && (CertBuf != NULL)) {
+    FreePool (CertBuf);
+    *SignerChainCerts = NULL;
+  }
+
+  if (OldBuf != NULL) {
+    FreePool (OldBuf);
+  }
+
+  return Status;
 }
diff --git a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
index 1bc4a5db13..484255830a 100644
--- a/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
+++ b/CryptoPkg/Library/BaseCryptLibMbedTls/Pk/CryptPkcs7VerifyEku.c
@@ -11,311 +11,8 @@
 
 #include <Base.h>
 #include "InternalCryptLib.h"
+#include <mbedtls/pkcs7.h>
 
-/**
-  This function will return the leaf signer certificate in a chain.  This is
-  required because certificate chains are not guaranteed to have the
-  certificates in the order that they were issued.
-
-  A typical certificate chain looks like this:
-
-
-                 ----------------------------
-                |            Root            |
-                 ----------------------------
-                               ^
-                               |
-                 ----------------------------
-                |          Policy CA         | <-- Typical Trust Anchor.
-                 ----------------------------
-                               ^
-                               |
-                 ----------------------------
-                |         Issuing CA         |
-                 ----------------------------
-                               ^
-                               |
-                 -----------------------------
-                /  End-Entity (leaf) signer  / <-- Bottom certificate.
-                -----------------------------  EKU: "1.3.6.1.4.1.311.76.9.21.1"
-                                                    (Firmware Signing)
-
-
-  @param[in]   CertChain            Certificate chain.
-
-  @param[out]  SignerCert           Last certificate in the chain.  For PKCS7 signatures,
-                                    this will be the end-entity (leaf) signer cert.
-
-  @retval EFI_SUCCESS               The required EKUs were found in the signature.
-  @retval EFI_INVALID_PARAMETER     A parameter was invalid.
-  @retval EFI_NOT_FOUND             The number of signers found was not 1.
-
-**/
-EFI_STATUS
-GetSignerCertificate (
-  IN CONST PKCS7 *CertChain,
-  OUT X509       **SignerCert
-  )
-{
-  EFI_STATUS      Status;
-  STACK_OF(X509)  *Signers;
-  INT32           NumberSigners;
-
-  Status         = EFI_SUCCESS;
-  Signers        = NULL;
-  NumberSigners  = 0;
-
-  if (CertChain == NULL || SignerCert == NULL) {
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
-  }
-
-  //
-  // Get the signers from the chain.
-  //
-  Signers = PKCS7_get0_signers ((PKCS7*) CertChain, NULL, PKCS7_BINARY);
-  if (Signers == NULL) {
-    //
-    // Fail to get signers form PKCS7
-    //
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
-  }
-
-  //
-  // There should only be one signer in the PKCS7 stack.
-  //
-  NumberSigners = sk_X509_num (Signers);
-  if (NumberSigners != 1) {
-    //
-    // The number of singers should have been 1
-    //
-    Status = EFI_NOT_FOUND;
-    goto Exit;
-  }
-
-  *SignerCert = sk_X509_value (Signers, 0);
-
-Exit:
-  //
-  // Release Resources
-  //
-  if (Signers != NULL) {
-    sk_X509_free (Signers);
-  }
-
-  return Status;
-}
-
-
-/**
-  Determines if the specified EKU represented in ASN1 form is present
-  in a given certificate.
-
-  @param[in]  Cert                  The certificate to check.
-
-  @param[in]  Asn1ToFind            The EKU to look for.
-
-  @retval EFI_SUCCESS               We successfully identified the signing type.
-  @retval EFI_INVALID_PARAMETER     A parameter was invalid.
-  @retval EFI_NOT_FOUND             One or more EKU's were not found in the signature.
-
-**/
-EFI_STATUS
-IsEkuInCertificate (
-  IN CONST X509  *Cert,
-  IN ASN1_OBJECT *Asn1ToFind
-  )
-{
-  EFI_STATUS          Status;
-  X509                *ClonedCert;
-  X509_EXTENSION      *Extension;
-  EXTENDED_KEY_USAGE  *Eku;
-  INT32               ExtensionIndex;
-  INTN                NumExtensions;
-  ASN1_OBJECT         *Asn1InCert;
-  INTN                Index;
-
-  Status            = EFI_NOT_FOUND;
-  ClonedCert        = NULL;
-  Extension         = NULL;
-  Eku               = NULL;
-  ExtensionIndex    = -1;
-  NumExtensions     = 0;
-  Asn1InCert        = NULL;
-
-  if (Cert == NULL || Asn1ToFind == NULL) {
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
-  }
-
-  //
-  // Clone the certificate.  This is required because the Extension API's
-  // only work once per instance of an X509 object.
-  //
-  ClonedCert = X509_dup ((X509*)Cert);
-  if (ClonedCert == NULL) {
-    //
-    // Fail to duplicate cert.
-    //
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
-  }
-
-  //
-  // Look for the extended key usage.
-  //
-  ExtensionIndex = X509_get_ext_by_NID (ClonedCert, NID_ext_key_usage, -1);
-
-  if (ExtensionIndex < 0) {
-    //
-    // Fail to find 'NID_ext_key_usage' in Cert.
-    //
-    goto Exit;
-  }
-
-  Extension = X509_get_ext (ClonedCert, ExtensionIndex);
-  if (Extension == NULL) {
-    //
-    // Fail to get Extension form cert.
-    //
-    goto Exit;
-  }
-
-  Eku = (EXTENDED_KEY_USAGE*)X509V3_EXT_d2i (Extension);
-  if (Eku == NULL) {
-    //
-    // Fail to get Eku from extension.
-    //
-    goto Exit;
-  }
-
-  NumExtensions = sk_ASN1_OBJECT_num (Eku);
-
-  //
-  // Now loop through the extensions, looking for the specified Eku.
-  //
-  for (Index = 0; Index < NumExtensions; Index++) {
-    Asn1InCert = sk_ASN1_OBJECT_value (Eku, (INT32)Index);
-    if (Asn1InCert == NULL) {
-      //
-      // Fail to get ASN object from Eku.
-      //
-      goto Exit;
-    }
-
-    if (Asn1InCert->length == Asn1ToFind->length &&
-        CompareMem (Asn1InCert->data, Asn1ToFind->data, Asn1InCert->length) == 0) {
-      //
-      // Found Eku in certificate.
-      //
-      Status = EFI_SUCCESS;
-      goto Exit;
-    }
-  }
-
-Exit:
-
-  //
-  // Release Resources
-  //
-  if (ClonedCert != NULL) {
-    X509_free (ClonedCert);
-  }
-
-  if (Eku != NULL) {
-    sk_ASN1_OBJECT_pop_free (Eku, ASN1_OBJECT_free);
-  }
-
-  return Status;
-}
-
-
-/**
-  Determines if the specified EKUs are present in a signing certificate.
-
-  @param[in]  SignerCert            The certificate to check.
-  @param[in]  RequiredEKUs          The EKUs to look for.
-  @param[in]  RequiredEKUsSize      The number of EKUs
-  @param[in]  RequireAllPresent     If TRUE, then all the specified EKUs
-                                    must be present in the certificate.
-
-  @retval EFI_SUCCESS               We successfully identified the signing type.
-  @retval EFI_INVALID_PARAMETER     A parameter was invalid.
-  @retval EFI_NOT_FOUND             One or more EKU's were not found in the signature.
-**/
-EFI_STATUS
-CheckEKUs(
-  IN CONST X509     *SignerCert,
-  IN CONST CHAR8    *RequiredEKUs[],
-  IN CONST UINT32   RequiredEKUsSize,
-  IN BOOLEAN        RequireAllPresent
-  )
-{
-  EFI_STATUS    Status;
-  ASN1_OBJECT   *Asn1ToFind;
-  UINT32        NumEkusFound;
-  UINT32        Index;
-
-  Status       = EFI_SUCCESS;
-  Asn1ToFind   = NULL;
-  NumEkusFound = 0;
-
-  if (SignerCert == NULL || RequiredEKUs == NULL || RequiredEKUsSize == 0) {
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
-  }
-
-  for (Index = 0; Index < RequiredEKUsSize; Index++) {
-    //
-    // Finding required EKU in cert.
-    //
-    if (Asn1ToFind != NULL) {
-      ASN1_OBJECT_free(Asn1ToFind);
-      Asn1ToFind = NULL;
-    }
-
-    Asn1ToFind = OBJ_txt2obj (RequiredEKUs[Index], 0);
-    if (Asn1ToFind == NULL) {
-      //
-      // Fail to convert required EKU to ASN1.
-      //
-      Status = EFI_INVALID_PARAMETER;
-      goto Exit;
-    }
-
-    Status = IsEkuInCertificate (SignerCert, Asn1ToFind);
-    if (Status == EFI_SUCCESS) {
-      NumEkusFound++;
-      if (!RequireAllPresent) {
-        //
-        // Found at least one, so we are done.
-        //
-        goto Exit;
-      }
-    } else {
-      //
-      // Fail to find Eku in cert
-      break;
-    }
-  }
-
-Exit:
-
-  if (Asn1ToFind != NULL) {
-    ASN1_OBJECT_free(Asn1ToFind);
-  }
-
-  if (RequireAllPresent &&
-      NumEkusFound == RequiredEKUsSize) {
-    //
-    // Found all required EKUs in certificate.
-    //
-    Status = EFI_SUCCESS;
-  }
-
-  return Status;
-}
 
 /**
   This function receives a PKCS#7 formatted signature blob,
@@ -357,135 +54,62 @@ VerifyEKUsInPkcs7Signature (
   IN BOOLEAN        RequireAllPresent
   )
 {
-  EFI_STATUS        Status;
-  PKCS7             *Pkcs7;
-  STACK_OF(X509)    *CertChain;
-  INT32             SignatureType;
-  INT32             NumberCertsInSignature;
-  X509              *SignerCert;
-  UINT8             *SignedData;
-  UINT8             *Temp;
-  UINTN             SignedDataSize;
-  BOOLEAN           IsWrapped;
-  BOOLEAN           Ok;
+  BOOLEAN      Status;
+  UINT8        *SignedData;
+  UINTN        SignedDataSize;
+  BOOLEAN      Wrapped;
+  INTN               Ret;
+  mbedtls_pkcs7      Pkcs7;
+  mbedtls_x509_crt   *Cert;
+  UINT8  *SingleCert;
 
-  Status                    = EFI_SUCCESS;
-  Pkcs7                     = NULL;
-  CertChain                 = NULL;
-  SignatureType             = 0;
-  NumberCertsInSignature    = 0;
-  SignerCert                = NULL;
-  SignedData                = NULL;
-  SignedDataSize            = 0;
-  IsWrapped                 = FALSE;
-  Ok                        = FALSE;
+  mbedtls_pkcs7_init(&Pkcs7);
 
   //
-  //Validate the input parameters.
+  // Check input parameter.
   //
-  if (Pkcs7Signature   == NULL ||
-      SignatureSize    == 0    ||
-      RequiredEKUs     == NULL ||
-      RequiredEKUsSize == 0) {
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
+  if ((RequiredEKUs == NULL) || (Pkcs7Signature == NULL))
+  {
+    return FALSE;
   }
 
-  if (RequiredEKUsSize == 1) {
-    RequireAllPresent = TRUE;
-  }
+  SignedData = NULL;
 
-  //
-  // Wrap the PKCS7 data if needed.
-  //
-  Ok = WrapPkcs7Data (Pkcs7Signature,
-                      SignatureSize,
-                      &IsWrapped,
-                      &SignedData,
-                      &SignedDataSize);
-  if (!Ok) {
-    //
-    // Fail to Wrap the PKCS7 data.
-    //
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
+  Status = WrapPkcs7Data (Pkcs7Signature, SignatureSize, &Wrapped, &SignedData, &SignedDataSize);
+  if (!Status || (SignedDataSize > INT_MAX)) {
+    goto _Exit;
   }
 
-  Temp = SignedData;
+  Status = FALSE;
 
   //
-  // Create the PKCS7 object.
+  // Retrieve PKCS#7 Data (DER encoding)
   //
-  Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&Temp, (INT32)SignedDataSize);
-  if (Pkcs7 == NULL) {
-    //
-    // Fail to read PKCS7 data.
-    //
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
+  if (SignedDataSize > INT_MAX) {
+    goto _Exit;
   }
 
-  //
-  // Get the certificate chain.
-  //
-  SignatureType = OBJ_obj2nid (Pkcs7->type);
-  switch (SignatureType) {
-  case NID_pkcs7_signed:
-    if (Pkcs7->d.sign != NULL) {
-      CertChain = Pkcs7->d.sign->cert;
-    }
-    break;
-  case NID_pkcs7_signedAndEnveloped:
-    if (Pkcs7->d.signed_and_enveloped != NULL) {
-      CertChain = Pkcs7->d.signed_and_enveloped->cert;
-    }
-    break;
-  default:
-    break;
-  }
+  Ret = mbedtls_pkcs7_parse_der(&Pkcs7, SignedData, (INT32)SignedDataSize);
 
   //
-  // Ensure we have a certificate stack
+  // The type of Pkcs7 must be signedData
   //
-  if (CertChain == NULL) {
-    //
-    // Fail to get the certificate stack from signature.
-    //
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
+  if (Ret != MBEDTLS_PKCS7_SIGNED_DATA) {
+    goto _Exit;
   }
 
-  //
-  // Find out how many certificates were in the PKCS7 signature.
-  //
-  NumberCertsInSignature = sk_X509_num (CertChain);
 
-  if (NumberCertsInSignature == 0) {
-    //
-    // Fail to find any certificates in signature.
-    //
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
-  }
+  Cert      = NULL;
+  SingleCert = NULL;
 
-  //
-  // Get the leaf signer.
-  //
-  Status = GetSignerCertificate (Pkcs7, &SignerCert);
-  if (Status != EFI_SUCCESS || SignerCert == NULL) {
-    //
-    // Fail to get the end-entity leaf signer certificate.
-    //
-    Status = EFI_INVALID_PARAMETER;
-    goto Exit;
-  }
 
-  Status = CheckEKUs (SignerCert, RequiredEKUs, RequiredEKUsSize, RequireAllPresent);
-  if (Status != EFI_SUCCESS) {
-    goto Exit;
+  Cert = &Pkcs7.signed_data.certs;
+  if (Cert == NULL) {
+    goto _Exit;
   }
 
-Exit:
+
+_Exit:
 
   //
   // Release Resources
@@ -493,17 +117,11 @@ Exit:
   // If the signature was not wrapped, then the call to WrapData() will allocate
   // the data and add a header to it
   //
-  if (!IsWrapped && SignedData) {
-    free (SignedData);
+  if (!Wrapped && SignedData) {
+    FreePool (SignedData);
   }
 
-  if (SignerCert != NULL) {
-    X509_free (SignerCert);
-  }
-
-  if (Pkcs7 != NULL) {
-    PKCS7_free (Pkcs7);
-  }
+  mbedtls_pkcs7_free (&Pkcs7);
 
   return Status;
 }
diff --git a/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf b/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf
index b735fef49e..69d712b9c6 100644
--- a/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf
+++ b/CryptoPkg/Library/MbedTlsLib/MbedTlsLib.inf
@@ -108,6 +108,7 @@
   mbedtls/library/x509_crl.c
   mbedtls/library/x509_crt.c
   mbedtls/library/x509_csr.c
+  mbedtls/library/pkcs7.c
 
 [Packages]
   MdePkg/MdePkg.dec
-- 
2.26.2.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#101321): https://edk2.groups.io/g/devel/message/101321
Mute This Topic: https://groups.io/mt/97669083/1813853
Group Owner: devel+owner at edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [edk2-devel-archive at redhat.com]
-=-=-=-=-=-=-=-=-=-=-=-




More information about the edk2-devel-archive mailing list