public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: Zhichao Gao <zhichao.gao@intel.com>
To: edk2-devel@lists.01.org
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>,
	Ting Ye <ting.ye@intel.com>, Gang Wei <gang.wei@intel.com>,
	Wang Jian J <jian.j.wang@intel.com>,
	Liming Gao <liming.gao@intel.com>,
	Sean Brogan <sean.brogan@microsoft.com>,
	Michael Turner <Michael.Turner@microsoft.com>
Subject: [PATCH 4/6] CryptoPkg/BaseCryptLib: Add new API VerifyEKUsInPkcs7Signature
Date: Mon, 25 Mar 2019 12:01:11 +0800	[thread overview]
Message-ID: <20190325040113.18848-5-zhichao.gao@intel.com> (raw)
In-Reply-To: <20190325040113.18848-1-zhichao.gao@intel.com>

From: Bret Barkelew <Bret.Barkelew@microsoft.com>

REF:https://bugzilla.tianocore.org/show_bug.cgi?id=1402

Add the API VerifyEKUsInPkcs7Signature to check if x509 cert
has any or all EKUs.

Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Zhichao Gao <zhichao.gao@intel.com>
Cc: Ting Ye <ting.ye@intel.com>
Cc: Gang Wei <gang.wei@intel.com>
Cc: Wang Jian J <jian.j.wang@intel.com>
Cc: Liming Gao <liming.gao@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Michael Turner <Michael.Turner@microsoft.com>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
---
 CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf    |   1 +
 CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf     |   3 +-
 .../Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c  | 539 +++++++++++++++++++++
 .../BaseCryptLib/Pk/CryptPkcs7VerifyEkuRuntime.c   |  75 +++
 CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf |   1 +
 CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf     |   1 +
 6 files changed, 619 insertions(+), 1 deletion(-)
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c
 create mode 100644 CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEkuRuntime.c

diff --git a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
index 5988c103c6..dbddd98c59 100644
--- a/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/BaseCryptLib.inf
@@ -51,6 +51,7 @@
   Pk/CryptPkcs7Sign.c
   Pk/CryptPkcs7VerifyCommon.c
   Pk/CryptPkcs7VerifyBase.c
+  Pk/CryptPkcs7VerifyEku.c
   Pk/CryptDh.c
   Pk/CryptX509.c
   Pk/CryptAuthenticode.c
diff --git a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
index e84d7f91e4..5dbb115734 100644
--- a/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/PeiCryptLib.inf
@@ -13,7 +13,7 @@
 #  PEM handler functions, and pseudorandom number generator functions are not
 #  supported in this instance.
 #
-#  Copyright (c) 2010 - 2018, Intel Corporation. All rights reserved.<BR>
+#  Copyright (c) 2010 - 2019, Intel Corporation. All rights reserved.<BR>
 #  This program and the accompanying materials
 #  are licensed and made available under the terms and conditions of the BSD License
 #  which accompanies this distribution.  The full text of the license may be found at
@@ -58,6 +58,7 @@
   Pk/CryptPkcs7SignNull.c
   Pk/CryptPkcs7VerifyCommon.c
   Pk/CryptPkcs7VerifyBase.c
+  Pk/CryptPkcs7VerifyEku.c
 
   Pk/CryptDhNull.c
   Pk/CryptX509Null.c
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c
new file mode 100644
index 0000000000..0384b53476
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEku.c
@@ -0,0 +1,539 @@
+/** @file
+  This module verifies that Enhanced Key Usages (EKU's) are present within
+  a PKCS7 signature blob using OpenSSL.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+  THE POSSIBILITY OF SUCH DAMAGE.
+
+  Copyright (C) Microsoft Corporation. All Rights Reserved.
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+  1. Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+**/
+
+#include <Base.h>
+#include "InternalCryptLib.h"
+#include <openssl/x509v3.h>
+#include <openssl/asn1.h>
+#include <openssl/x509.h>
+#include <openssl/bio.h>
+#include <internal/x509_int.h>
+#include <openssl/pkcs7.h>
+#include <openssl/bn.h>
+#include <openssl/x509_vfy.h>
+#include <openssl/pem.h>
+#include <openssl/evp.h>
+#include <internal/asn1_int.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) {
+    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) {
+    X509_free (ClonedCert);
+  }
+
+  if (Eku) {
+    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) {
+      ASN1_OBJECT_free(Asn1ToFind);
+      Asn1ToFind = NULL;
+    }
+
+    Asn1ToFind = OBJ_txt2obj (RequiredEKUs[Index], 0);
+    if (!Asn1ToFind) {
+      //
+      // 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) {
+    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,
+  looks for the EKU SEQUENCE blob, and if found then looks
+  for all the required EKUs. This function was created so that
+  the Surface team can cut down on the number of Certificate
+  Authorities (CA's) by checking EKU's on leaf signers for
+  a specific product. This prevents one product's certificate
+  from signing another product's firmware or unlock blobs.
+
+  Note that this function does not validate the certificate chain.
+  That needs to be done before using this function.
+
+  @param[in]  Pkcs7Signature       The PKCS#7 signed information content block. An array
+                                   containing the content block with both the signature,
+                                   the signer's certificate, and any necessary intermediate
+                                   certificates.
+  @param[in]  Pkcs7SignatureSize   Number of bytes in Pkcs7Signature.
+  @param[in]  RequiredEKUs         Array of null-terminated strings listing OIDs of
+                                   required EKUs that must be present in the signature.
+  @param[in]  RequiredEKUsSize     Number of elements in the RequiredEKUs string array.
+  @param[in]  RequireAllPresent    If this is TRUE, then all of the specified EKU's
+                                   must be present in the leaf signer.  If it is
+                                   FALSE, then we will succeed if we find any
+                                   of the specified EKU's.
+
+  @retval EFI_SUCCESS              The required EKUs were found in the signature.
+  @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
+EFIAPI
+VerifyEKUsInPkcs7Signature (
+  IN CONST UINT8    *Pkcs7Signature,
+  IN CONST UINT32   SignatureSize,
+  IN CONST CHAR8    *RequiredEKUs[],
+  IN CONST UINT32   RequiredEKUsSize,
+  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;
+
+  Status                    = EFI_SUCCESS;
+  Pkcs7                     = NULL;
+  CertChain                 = NULL;
+  SignatureType             = 0;
+  NumberCertsInSignature    = 0;
+  SignerCert                = NULL;
+  SignedData                = NULL;
+  SignedDataSize            = 0;
+  IsWrapped                 = FALSE;
+  Ok                        = FALSE;
+
+  //
+  //Validate the input parameters.
+  //
+  if (Pkcs7Signature   == NULL ||
+      SignatureSize    == 0    ||
+      RequiredEKUs     == NULL ||
+      RequiredEKUsSize == 0) {
+    Status = EFI_INVALID_PARAMETER;
+    goto Exit;
+  }
+
+  if (RequiredEKUsSize == 1) {
+    RequireAllPresent = TRUE;
+  }
+
+  //
+  // 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;
+  }
+
+  Temp = SignedData;
+
+  //
+  // Create the PKCS7 object.
+  //
+  Pkcs7 = d2i_PKCS7 (NULL, (const unsigned char **)&Temp, (INT32)SignedDataSize);
+  if (Pkcs7 == NULL) {
+    //
+    // Fail to read PKCS7 data.
+    //
+    Status = EFI_INVALID_PARAMETER;
+    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;
+  }
+
+  //
+  // Ensure we have a certificate stack
+  //
+  if (CertChain == NULL) {
+    //
+    // Fail to get the certificate stack from signature.
+    //
+    Status = EFI_INVALID_PARAMETER;
+    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;
+  }
+
+  //
+  // 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;
+  }
+
+Exit:
+
+  //
+  // Release Resources
+  //
+  // 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 (SignerCert) {
+    X509_free (SignerCert);
+  }
+
+  if (Pkcs7) {
+    PKCS7_free (Pkcs7);
+  }
+
+  return Status;
+}
+
diff --git a/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEkuRuntime.c b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEkuRuntime.c
new file mode 100644
index 0000000000..4133975162
--- /dev/null
+++ b/CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyEkuRuntime.c
@@ -0,0 +1,75 @@
+/** @file
+  This module verifies that Enhanced Key Usages (EKU's) are present within
+  a PKCS7 signature blob using OpenSSL.
+
+  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+  THE POSSIBILITY OF SUCH DAMAGE.
+
+  Copyright (C) Microsoft Corporation. All Rights Reserved.
+  Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
+
+  Redistribution and use in source and binary forms, with or without
+  modification, are permitted provided that the following conditions are met:
+  1. Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+  2. Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+
+**/
+
+#include "InternalCryptLib.h"
+
+/**
+  This function receives a PKCS#7 formatted signature blob,
+  looks for the EKU SEQUENCE blob, and if found then looks
+  for all the required EKUs.  This function was created so that
+  the Surface team can cut down on the number of Certificate
+  Authorities (CA's) by checking EKU's on leaf signers for
+  a specific product.  This prevents one product's certificate
+  from signing another product's firmware or unlock blobs.
+
+  Return RETURN_UNSUPPORTED to indicate this interface is not supported.
+
+  @param[in]  Pkcs7Signature        The PKCS#7 signed information content block. An array
+                                    containing the content block with both the signature,
+                                    the signer's certificate, and any necessary intermediate
+                                    certificates.
+  @param[in]  Pkcs7SignatureSize    Number of bytes in pPkcs7Signature.
+  @param[in]  RequiredEKUs          Array of null-terminated strings listing OIDs of
+                                    required EKUs that must be present in the signature.
+                                    All specified EKU's must be present in order to
+                                    succeed.
+  @param[in]  RequiredEKUsSize      Number of elements in the rgRequiredEKUs string.
+                                    This parameter has a maximum of MAX_EKU_SEARCH.
+  @param[in]  RequireAllPresent     If this is TRUE, then all of the specified EKU's
+                                    must be present in the leaf signer.  If it is
+                                    FALSE, then we will succeed if we find any
+                                    of the specified EKU's.
+
+  @retval RETURN_UNSUPPORTED        The operation is not supported.
+
+**/
+EFI_STATUS
+EFIAPI
+VerifyEKUsInPkcs7Signature (
+  IN CONST UINT8    *Pkcs7Signature,
+  IN CONST UINT32   SignatureSize,
+  IN CONST CHAR8    *RequiredEKUs[],
+  IN CONST UINT32   RequiredEKUsSize,
+  IN BOOLEAN        RequireAllPresent
+  )
+{
+  ASSERT (FALSE);
+  return RETURN_UNSUPPORTED;
+}
+
diff --git a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
index 95d4278090..f24cb91f33 100644
--- a/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/RuntimeCryptLib.inf
@@ -56,6 +56,7 @@
   Pk/CryptPkcs7SignNull.c
   Pk/CryptPkcs7VerifyCommon.c
   Pk/CryptPkcs7VerifyRuntime.c
+  Pk/CryptPkcs7VerifyEkuRuntime.c
   Pk/CryptDhNull.c
   Pk/CryptX509.c
   Pk/CryptAuthenticodeNull.c
diff --git a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
index c3aa9c9eab..81d4bbe463 100644
--- a/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
+++ b/CryptoPkg/Library/BaseCryptLib/SmmCryptLib.inf
@@ -56,6 +56,7 @@
   Pk/CryptPkcs7SignNull.c
   Pk/CryptPkcs7VerifyCommon.c
   Pk/CryptPkcs7VerifyBase.c
+  Pk/CryptPkcs7VerifyEku.c
   Pk/CryptDhNull.c
   Pk/CryptX509.c
   Pk/CryptAuthenticodeNull.c
-- 
2.16.2.windows.1



  parent reply	other threads:[~2019-03-25  4:01 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-03-25  4:01 [PATCH 0/6] Add new APIs for BaseCryptLib Zhichao Gao
2019-03-25  4:01 ` [PATCH 1/6] CryptoPkg/BaseCryptLib.h: Add new API to get organization name Zhichao Gao
2019-03-25  4:01 ` [PATCH 2/6] CryptoPkg/BaseCryptLib: " Zhichao Gao
2019-03-25  4:01 ` [PATCH 3/6] CryptoPkg/BaseCryptLib.h: Add new API VerifyEKUsInPkcs7Signature Zhichao Gao
2019-03-25  4:01 ` Zhichao Gao [this message]
2019-03-25  4:01 ` [PATCH 5/6] CryptoPkg/BaseCryptLib.h: Add PKCS1v2 (RSAES-OAEP) support Zhichao Gao
2019-03-25  4:01 ` [PATCH 6/6] CryptoPkg/BaseCryptLib: " Zhichao Gao
2019-03-25  8:22 ` [PATCH 0/6] Add new APIs for BaseCryptLib Yao, Jiewen
2019-03-28  4:04   ` Gao, Zhichao
2019-04-17  5:57     ` [edk2] " Gao, Zhichao
2019-04-17  6:09       ` Wang, Jian J

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=20190325040113.18848-5-zhichao.gao@intel.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