예제 #1
1
int main(int argc, char const *argv[])
{
	PKCS7 *p7;
	FILE *fp = NULL;
	PKCS7_SIGNER_INFO *si;
	STACK_OF(PKCS7_SIGNER_INFO) *sk;
	X509_STORE_CTX cert_ctx;
	X509_STORE *cert_store;
	BIO *mybio;
	int ret, len, i;
	unsigned char *errordesc;
	unsigned long errorno;

	unsigned char data[2028], *p, *buf;
	OpenSSL_add_all_algorithms();

	fp = fopen("p7signed.cer", "rb");
	if(fp == NULL)
		return 0;
	len = fread(data, 1, 2048, fp);
	fclose(fp);
	p = data;
	p7 = d2i_PKCS7(NULL, (const unsigned char **)&p, len);

	mybio = PKCS7_dataInit(p7, NULL);
	sk = PKCS7_get_signer_info(p7);
	if(sk == NULL)
	{
		printf("no signer in p7\n");
		return 0;
	}

cert_store=X509_STORE_new(); 
X509_STORE_set_verify_cb_func(cert_store,verify_callback);//必须要有回调设置 
for(i = 0; i < sk_PKCS7_SIGNER_INFO_num(sk); i++) 
{ 
si = sk_PKCS7_SIGNER_INFO_value(sk, i); 
ret = PKCS7_dataVerify(cert_store, &cert_ctx, mybio, p7, si); 
if(ret == 1) 
printf("succ in pkcs7 signed data verify\n"); 
else 
printf("fail in pkcs7 signed data verify\n"); 
} 

X509_STORE_free(cert_store); 
PKCS7_free(p7); 
return 1; 
} 
예제 #2
0
void openssl_pkcs7_sign()
{
	int len;
	BIO *in;
	X509 *x;
	FILE *fp;
	PKCS7 *p7;
	X509_ALGOR *md;
	PKCS7_SIGNER_INFO *si;
	char name[MAX1_LEN], tmp[MAX1_LEN];
	unsigned char *der, *p, buf[SHA_DIGEST_LENGTH] = "pkcs7 sign";

	p7 = PKCS7_new();
	PKCS7_set_type(p7, NID_pkcs7_data);
	ASN1_OCTET_STRING_set(p7->d.data, buf, SHA_DIGEST_LENGTH);
	len = i2d_PKCS7(p7, NULL);
	der = (unsigned char *)malloc(len);
	p = der;
	len = i2d_PKCS7(p7, &p);
	fp = fopen("/tmp/test.cer", "wb");
	fwrite(der, 1, len, fp);
	fclose(fp);
	free(der);
	PKCS7_free(p7);

	p7 = PKCS7_new();
	PKCS7_set_type(p7, NID_pkcs7_signed);
	p7->d.sign->cert = sk_X509_new_null();
	in = BIO_new_file("/tmp/test.cer", "r");
	x = PEM_read_bio_X509(in, NULL, NULL, NULL);
	sk_X509_push(p7->d.sign->cert, x);
	BIO_free(in);

	md = X509_ALGOR_new();
	md->algorithm = OBJ_nid2obj(NID_md5);
	sk_X509_ALGOR_push(p7->d.sign->md_algs, md);

	si = PKCS7_SIGNER_INFO_new();
	ASN1_INTEGER_set(si->version, 2);
	ASN1_INTEGER_set(si->issuer_and_serial->serial, 333);
	sk_PKCS7_SIGNER_INFO_push(p7->d.sign->signer_info, si);

	len = i2d_PKCS7(p7, NULL);
	der = (unsigned char *)malloc(len);
	p = der;
	len = i2d_PKCS7(p7, &p);
	fp = fopen("/tmp/test.cer", "wb");
	fwrite(der, 1, len, fp);
	fclose(fp);
	free(der);

	fp = fopen("/tmp/test.cer", "rb");
	len = fread(tmp, 1, MAX1_LEN, fp);
	fclose(fp);
	p = (unsigned char *)&tmp;
	d2i_PKCS7(&p7, (const unsigned char **)&p, len);
	OBJ_obj2txt(name, MAX1_LEN, p7->type, 0);

	PKCS7_free(p7);
}
예제 #3
0
// Verify the signed block, the first 32 bytes of the data must be the certificate hash to work.
int __fastcall util_verify(char* signature, int signlen, struct util_cert* cert, char** data)
{
	unsigned int size, r;
	BIO *out = NULL;
	PKCS7 *message = NULL;
	char* data2 = NULL;
	char hash[UTIL_HASHSIZE];
	STACK_OF(X509) *st = NULL;

	cert->x509 = NULL;
	cert->pkey = NULL;
	*data = NULL;
	message = d2i_PKCS7(NULL, (const unsigned char**)&signature, signlen);
	if (message == NULL) goto error;
	out = BIO_new(BIO_s_mem());

	// Lets rebuild the original message and check the size
	size = i2d_PKCS7(message, NULL);
	if (size < (unsigned int)signlen) goto error;

	// Check the PKCS7 signature, but not the certificate chain.
	r = PKCS7_verify(message, NULL, NULL, NULL, out, PKCS7_NOVERIFY);
	if (r == 0) goto error;

	// If data block contains less than 32 bytes, fail.
	size = BIO_get_mem_data(out, &data2);
	if (size <= UTIL_HASHSIZE) goto error;

	// Copy the data block
	*data = (char*)malloc(size + 1);
	if (*data == NULL) goto error;
	memcpy(*data, data2, size);
	(*data)[size] = 0;

	// Get the certificate signer
	st = PKCS7_get0_signers(message, NULL, PKCS7_NOVERIFY);
	cert->x509 = X509_dup(sk_X509_value(st, 0));
	sk_X509_free(st);

	// Get a full certificate hash of the signer
	r = UTIL_HASHSIZE;
	X509_digest(cert->x509, EVP_sha256(), (unsigned char*)hash, &r);

	// Check certificate hash with first 32 bytes of data.
	if (memcmp(hash, *data, UTIL_HASHSIZE) != 0) goto error;

	// Approved, cleanup and return.
	BIO_free(out);
	PKCS7_free(message);

	return size;

error:
	if (out != NULL) BIO_free(out);
	if (message != NULL) PKCS7_free(message);
	if (*data != NULL) free(*data);
	if (cert->x509 != NULL) { X509_free(cert->x509); cert->x509 = NULL; }

	return 0;
}
예제 #4
0
PKCS7* CryptoNative_DecodePkcs7(const uint8_t* buf, int32_t len)
{
    if (!buf || !len)
    {
        return NULL;
    }

    return d2i_PKCS7(NULL, &buf, len);
}
예제 #5
0
extern "C" PKCS7* CryptoNative_DecodePkcs7(const uint8_t* buf, int32_t len)
{
    if (!buf || !len)
    {
        return nullptr;
    }

    return d2i_PKCS7(nullptr, &buf, len);
}
예제 #6
0
extern "C" PKCS7* DecodePkcs7(const unsigned char* buf, int32_t len)
{
    if (!buf || !len)
    {
        return nullptr;
    }

    return d2i_PKCS7(nullptr, &buf, len);
}
예제 #7
0
/*
 * Internal static function for decoding of the signature of the published
 * file.
 */
static int decodeSignature(GTPublicationsFile *pubfile)
{
	const unsigned char *p;

	assert(pubfile->signature == NULL);

	p = pubfile->data + pubfile->signature_block_begin;
	ERR_clear_error();
	pubfile->signature = d2i_PKCS7(
			NULL, &p, pubfile->data_length - pubfile->signature_block_begin);
	if (pubfile->signature == NULL) {
		return GT_isMallocFailure() ? GT_OUT_OF_MEMORY : GT_INVALID_FORMAT;
	}

	return GT_OK;
}
예제 #8
0
static int attach_sig(struct image *image, const char *image_filename,
		const char *sig_filename)
{
	const uint8_t *tmp_buf;
	uint8_t *sigbuf;
	size_t size;
	PKCS7 *p7;
	int rc;

	rc = fileio_read_file(image, sig_filename, &sigbuf, &size);
	if (rc)
		goto out;

	image_add_signature(image, sigbuf, size);

	rc = -1;
	tmp_buf = sigbuf;
	p7 = d2i_PKCS7(NULL, &tmp_buf, size);
	if (!p7) {
		fprintf(stderr, "Unable to parse signature data in file: %s\n",
				sig_filename);
		ERR_print_errors_fp(stderr);
		goto out;
	}
	rc = PKCS7_verify(p7, NULL, NULL, NULL, NULL,
				PKCS7_BINARY | PKCS7_NOVERIFY | PKCS7_NOSIGS);
	if (!rc) {
		fprintf(stderr, "PKCS7 verification failed for file %s\n",
				sig_filename);
		ERR_print_errors_fp(stderr);
		goto out;
	}

	rc = image_write(image, image_filename);
	if (rc)
		fprintf(stderr, "Error writing %s: %s\n", image_filename,
				strerror(errno));

out:
	talloc_free(sigbuf);
	return rc;
}
예제 #9
0
int
EAC_CTX_init_ef_cardsecurity(const unsigned char *ef_cardsecurity,
            size_t ef_cardsecurity_len, EAC_CTX *ctx)
{
	PKCS7 *p7 = NULL, *signed_data;
    ASN1_OCTET_STRING *os;
    int r = 0;

    check(ef_cardsecurity, "Invalid arguments");

    if (!d2i_PKCS7(&p7, &ef_cardsecurity, ef_cardsecurity_len)
            || !PKCS7_type_is_signed(p7))
        goto err;

    if (ctx && ctx->ca_ctx &&
            !(ctx->ca_ctx->flags & CA_FLAG_DISABLE_PASSIVE_AUTH))
        check((CA_passive_authentication(ctx, p7) == 1),
                "Failed to perform passive authentication");

    signed_data = p7->d.sign->contents;
    if (OBJ_obj2nid(signed_data->type) != NID_id_SecurityObject
            || ASN1_TYPE_get(signed_data->d.other) != V_ASN1_OCTET_STRING)
        goto err;
    os = signed_data->d.other->value.octet_string;

    if (!EAC_CTX_init_ef_cardaccess(os->data, os->length, ctx)
            || !ctx || !ctx->ca_ctx || !ctx->ca_ctx->ka_ctx)
        goto err;

    r = 1;

err:
    if (p7)
        PKCS7_free(p7);

    return r;
}
예제 #10
0
파일: est.c 프로젝트: janetuk/mech_eap
static int pkcs7_to_cert(struct hs20_osu_client *ctx, const u8 *pkcs7,
			 size_t len, char *pem_file, char *der_file)
{
#ifdef OPENSSL_IS_BORINGSSL
	CBS pkcs7_cbs;
#else /* OPENSSL_IS_BORINGSSL */
	PKCS7 *p7 = NULL;
	const unsigned char *p = pkcs7;
#endif /* OPENSSL_IS_BORINGSSL */
	STACK_OF(X509) *certs;
	int i, num, ret = -1;
	BIO *out = NULL;

#ifdef OPENSSL_IS_BORINGSSL
	certs = sk_X509_new_null();
	if (!certs)
		goto fail;
	CBS_init(&pkcs7_cbs, pkcs7, len);
	if (!PKCS7_get_certificates(certs, &pkcs7_cbs)) {
		wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
			   ERR_error_string(ERR_get_error(), NULL));
		write_result(ctx, "Could not parse PKCS#7 object from EST");
		goto fail;
	}
#else /* OPENSSL_IS_BORINGSSL */
	p7 = d2i_PKCS7(NULL, &p, len);
	if (p7 == NULL) {
		wpa_printf(MSG_INFO, "Could not parse PKCS#7 object: %s",
			   ERR_error_string(ERR_get_error(), NULL));
		write_result(ctx, "Could not parse PKCS#7 object from EST");
		goto fail;
	}

	switch (OBJ_obj2nid(p7->type)) {
	case NID_pkcs7_signed:
		certs = p7->d.sign->cert;
		break;
	case NID_pkcs7_signedAndEnveloped:
		certs = p7->d.signed_and_enveloped->cert;
		break;
	default:
		certs = NULL;
		break;
	}
#endif /* OPENSSL_IS_BORINGSSL */

	if (!certs || ((num = sk_X509_num(certs)) == 0)) {
		wpa_printf(MSG_INFO, "No certificates found in PKCS#7 object");
		write_result(ctx, "No certificates found in PKCS#7 object");
		goto fail;
	}

	if (der_file) {
		FILE *f = fopen(der_file, "wb");
		if (f == NULL)
			goto fail;
		i2d_X509_fp(f, sk_X509_value(certs, 0));
		fclose(f);
	}

	if (pem_file) {
		out = BIO_new(BIO_s_file());
		if (out == NULL ||
		    BIO_write_filename(out, pem_file) <= 0)
			goto fail;

		for (i = 0; i < num; i++) {
			X509 *cert = sk_X509_value(certs, i);
			X509_print(out, cert);
			PEM_write_bio_X509(out, cert);
			BIO_puts(out, "\n");
		}
	}

	ret = 0;

fail:
#ifdef OPENSSL_IS_BORINGSSL
	if (certs)
		sk_X509_pop_free(certs, X509_free);
#else /* OPENSSL_IS_BORINGSSL */
	PKCS7_free(p7);
#endif /* OPENSSL_IS_BORINGSSL */
	if (out)
		BIO_free_all(out);

	return ret;
}
예제 #11
0
/**
  Verifies the validility of a PE/COFF Authenticode Signature as described in "Windows
  Authenticode Portable Executable Signature Format".

  If AuthData is NULL, then return FALSE.
  If ImageHash is NULL, then return FALSE.

  Caution: This function may receive untrusted input.
  PE/COFF Authenticode is external input, so this function will do basic check for
  Authenticode data structure.

  @param[in]  AuthData     Pointer to the Authenticode Signature retrieved from signed
                           PE/COFF image to be verified.
  @param[in]  DataSize     Size of the Authenticode Signature in bytes.
  @param[in]  TrustedCert  Pointer to a trusted/root certificate encoded in DER, which
                           is used for certificate chain verification.
  @param[in]  CertSize     Size of the trusted certificate in bytes.
  @param[in]  ImageHash    Pointer to the original image file hash value. The procudure
                           for calculating the image hash value is described in Authenticode
                           specification.
  @param[in]  HashSize     Size of Image hash value in bytes.

  @retval  TRUE   The specified Authenticode Signature is valid.
  @retval  FALSE  Invalid Authenticode Signature.

**/
BOOLEAN
EFIAPI
AuthenticodeVerify (
  IN  CONST UINT8  *AuthData,
  IN  UINTN        DataSize,
  IN  CONST UINT8  *TrustedCert,
  IN  UINTN        CertSize,
  IN  CONST UINT8  *ImageHash,
  IN  UINTN        HashSize
  )
{
  BOOLEAN      Status;
  PKCS7        *Pkcs7;
  CONST UINT8  *OrigAuthData;
  UINT8        *SpcIndirectDataContent;
  UINT8        Asn1Byte;
  UINTN        ContentSize;
  UINT8        *SpcIndirectDataOid;

  //
  // Check input parameters.
  //
  if ((AuthData == NULL) || (TrustedCert == NULL) || (ImageHash == NULL)) {
    return FALSE;
  }

  if ((DataSize > INT_MAX) || (CertSize > INT_MAX) || (HashSize > INT_MAX)) {
    return FALSE;
  }

  Status       = FALSE;
  Pkcs7        = NULL;
  OrigAuthData = AuthData;

  //
  // Retrieve & Parse PKCS#7 Data (DER encoding) from Authenticode Signature
  //
  Pkcs7 = d2i_PKCS7 (NULL, &AuthData, (int)DataSize);
  if (Pkcs7 == NULL) {
    goto _Exit;
  }

  //
  // Check if it's PKCS#7 Signed Data (for Authenticode Scenario)
  //
  if (!PKCS7_type_is_signed (Pkcs7)) {
    goto _Exit;
  }

  //
  // NOTE: OpenSSL PKCS7 Decoder didn't work for Authenticode-format signed data due to
  //       some authenticode-specific structure. Use opaque ASN.1 string to retrieve
  //       PKCS#7 ContentInfo here.
  //
  SpcIndirectDataOid = (UINT8 *)(Pkcs7->d.sign->contents->type->data);
  if (CompareMem (
        SpcIndirectDataOid,
        mSpcIndirectOidValue,
        sizeof (mSpcIndirectOidValue)
        ) != 0) {
    //
    // Un-matched SPC_INDIRECT_DATA_OBJID.
    //
    goto _Exit;
  }  


  SpcIndirectDataContent = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data);

  //
  // Retrieve the SEQUENCE data size from ASN.1-encoded SpcIndirectDataContent.
  //
  Asn1Byte = *(SpcIndirectDataContent + 1);

  if ((Asn1Byte & 0x80) == 0) {
    //
    // Short Form of Length Encoding
    //
    ContentSize = (UINTN) (Asn1Byte & 0x7F);
    //
    // Skip the SEQUENCE Tag;
    //
    SpcIndirectDataContent += 2;
  } else if ((Asn1Byte & 0x82) == 0x82) {
    //
    // Long Form of Length Encoding, only support two bytes.
    //
    ContentSize = (UINTN) (*(UINT8 *)(SpcIndirectDataContent + 2));
    ContentSize = (ContentSize << 8) + (UINTN)(*(UINT8 *)(SpcIndirectDataContent + 3));
    //
    // Skip the SEQUENCE Tag;
    //
    SpcIndirectDataContent += 4;
  } else {
    goto _Exit;
  }

  //
  // Compare the original file hash value to the digest retrieve from SpcIndirectDataContent
  // defined in Authenticode
  // NOTE: Need to double-check HashLength here!
  //
  if (CompareMem (SpcIndirectDataContent + ContentSize - HashSize, ImageHash, HashSize) != 0) {
    //
    // Un-matched PE/COFF Hash Value
    //
    goto _Exit;
  }

  //
  // Verifies the PKCS#7 Signed Data in PE/COFF Authenticode Signature
  //
  Status = (BOOLEAN) Pkcs7Verify (OrigAuthData, DataSize, TrustedCert, CertSize, SpcIndirectDataContent, ContentSize);

_Exit:
  //
  // Release Resources
  //
  PKCS7_free (Pkcs7);

  return Status;
}
예제 #12
0
static int rtCrPkcs7VerifySignedDataUsingOpenSsl(PCRTCRPKCS7CONTENTINFO pContentInfo, uint32_t fFlags,
                                                 RTCRSTORE hAdditionalCerts, RTCRSTORE hTrustedCerts,
                                                 void const *pvContent, uint32_t cbContent, PRTERRINFO pErrInfo)
{
    /*
     * Verify using OpenSSL.
     */
    int rcOssl;
    unsigned char const *pbRawContent = RTASN1CORE_GET_RAW_ASN1_PTR(&pContentInfo->SeqCore.Asn1Core);
    PKCS7 *pOsslPkcs7 = NULL;
    if (d2i_PKCS7(&pOsslPkcs7, &pbRawContent, RTASN1CORE_GET_RAW_ASN1_SIZE(&pContentInfo->SeqCore.Asn1Core)) == pOsslPkcs7)
    {
        STACK_OF(X509) *pAddCerts = NULL;
        if (hAdditionalCerts != NIL_RTCRSTORE)
            rcOssl = RTCrStoreConvertToOpenSslCertStack(hAdditionalCerts, 0, (void **)&pAddCerts);
        else
        {
            pAddCerts = sk_X509_new_null();
            rcOssl = RT_LIKELY(pAddCerts != NULL) ? VINF_SUCCESS : VERR_NO_MEMORY;
        }
        if (RT_SUCCESS(rcOssl))
        {
            PCRTCRPKCS7SETOFCERTS pCerts = &pContentInfo->u.pSignedData->Certificates;
            for (uint32_t i = 0; i < pCerts->cItems; i++)
                if (pCerts->paItems[i].enmChoice == RTCRPKCS7CERTCHOICE_X509)
                    rtCrOpenSslAddX509CertToStack(pAddCerts, pCerts->paItems[i].u.pX509Cert);


            X509_STORE *pTrustedCerts = NULL;
            if (hTrustedCerts != NIL_RTCRSTORE)
                rcOssl = RTCrStoreConvertToOpenSslCertStore(hTrustedCerts, 0, (void **)&pTrustedCerts);
            if (RT_SUCCESS(rcOssl))
            {
                rtCrOpenSslInit();

                BIO *pBioContent = BIO_new_mem_buf((void *)pvContent, cbContent);
                if (pBioContent)
                {
                    uint32_t fOsslFlags = PKCS7_NOCHAIN;
                    fOsslFlags |= PKCS7_NOVERIFY; // temporary hack.
                    if (PKCS7_verify(pOsslPkcs7, pAddCerts, pTrustedCerts, pBioContent, NULL /*out*/, fOsslFlags))
                        rcOssl = VINF_SUCCESS;
                    else
                    {
                        rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_OSSL_VERIFY_FAILED, "PKCS7_verify failed: ");
                        if (pErrInfo)
                            ERR_print_errors_cb(rtCrOpenSslErrInfoCallback, pErrInfo);
                    }
                    BIO_free(pBioContent);
                }
                if (pTrustedCerts)
                    X509_STORE_free(pTrustedCerts);
            }
            else
                rcOssl = RTErrInfoSet(pErrInfo, rcOssl, "RTCrStoreConvertToOpenSslCertStack failed");
            if (pAddCerts)
                sk_X509_pop_free(pAddCerts, X509_free);
        }
        else
            rcOssl = RTErrInfoSet(pErrInfo, rcOssl, "RTCrStoreConvertToOpenSslCertStack failed");
        PKCS7_free(pOsslPkcs7);
    }
    else
        rcOssl = RTErrInfoSet(pErrInfo, VERR_CR_PKCS7_OSSL_D2I_FAILED, "d2i_PKCS7 failed");

    return rcOssl;
}
예제 #13
0
/**
  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;
}