Add new interfaces to support PKCS7#7 signed data and authenticode signature. Update Cryptest to validate functionality of new interfaces.
Signed-off-by: tye1 Reviewed-by: hhuan13 Reviewed-by: qlong git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@12142 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
143
CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c
Normal file
143
CryptoPkg/Library/BaseCryptLib/Pk/CryptAuthenticode.c
Normal file
@@ -0,0 +1,143 @@
|
||||
/** @file
|
||||
Authenticode Portable Executable Signature Verification over OpenSSL.
|
||||
|
||||
Copyright (c) 2011, 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
|
||||
http://opensource.org/licenses/bsd-license.php
|
||||
|
||||
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
|
||||
**/
|
||||
|
||||
#include "InternalCryptLib.h"
|
||||
|
||||
#include <openssl/objects.h>
|
||||
#include <openssl/x509.h>
|
||||
#include <openssl/pkcs7.h>
|
||||
|
||||
|
||||
/**
|
||||
Verifies the validility of a PE/COFF Authenticode Signature as described in "Windows
|
||||
Authenticode Portable Executable Signature Format".
|
||||
|
||||
If AuthData is NULL, then ASSERT().
|
||||
If ImageHash is NULL, then ASSERT().
|
||||
|
||||
@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;
|
||||
|
||||
//
|
||||
// ASSERT if Authenticode Signature Data or PE Image Hash is NULL
|
||||
//
|
||||
ASSERT (AuthData != NULL);
|
||||
ASSERT (ImageHash != NULL);
|
||||
|
||||
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.
|
||||
//
|
||||
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 {
|
||||
//
|
||||
// Long Form of Length Encoding (Assume Only two bytes here)
|
||||
//
|
||||
ContentSize = (UINTN) (*(SpcIndirectDataContent + 2));
|
||||
ContentSize = (ContentSize << 8) + (UINTN)(*(SpcIndirectDataContent + 3));
|
||||
//
|
||||
// Skip the SEQUENCE Tag;
|
||||
//
|
||||
SpcIndirectDataContent += 4;
|
||||
}
|
||||
|
||||
//
|
||||
// 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;
|
||||
}
|
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
PKCS#7 SignedData Verification Wrapper Implementation over OpenSSL.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2009 - 2011, 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
|
||||
@@ -19,6 +19,235 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include <openssl/pkcs7.h>
|
||||
|
||||
|
||||
/**
|
||||
Verification callback function to override any existing callbacks in OpenSSL
|
||||
for intermediate certificate supports.
|
||||
|
||||
@param[in] Status Original status before calling this callback.
|
||||
@param[in] Context X509 store context.
|
||||
|
||||
@retval 1 Current X509 certificate is verified successfully.
|
||||
@retval 0 Verification failed.
|
||||
|
||||
**/
|
||||
STATIC int X509VerifyCb (int Status, X509_STORE_CTX *Context)
|
||||
{
|
||||
X509_OBJECT *Obj;
|
||||
int Error;
|
||||
int Index;
|
||||
int Count;
|
||||
|
||||
Obj = NULL;
|
||||
Error = X509_STORE_CTX_get_error (Context);
|
||||
|
||||
//
|
||||
// X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT and X509_V_ERR_UNABLE_TO_GET_ISSUER_
|
||||
// CERT_LOCALLY mean a X509 certificate is not self signed and its issuer
|
||||
// can not be found in X509_verify_cert of X509_vfy.c.
|
||||
// In order to support intermediate certificate node, we override the
|
||||
// errors if the certification is obtained from X509 store, i.e. it is
|
||||
// a trusted ceritifcate node that is enrolled by user.
|
||||
// Besides,X509_V_ERR_CERT_UNTRUSTED and X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE
|
||||
// are also ignored to enable such feature.
|
||||
//
|
||||
if ((Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT) ||
|
||||
(Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY)) {
|
||||
Obj = (X509_OBJECT *) OPENSSL_malloc (sizeof (X509_OBJECT));
|
||||
if (Obj == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
Obj->type = X509_LU_X509;
|
||||
Obj->data.x509 = Context->current_cert;
|
||||
|
||||
CRYPTO_w_lock (CRYPTO_LOCK_X509_STORE);
|
||||
|
||||
if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {
|
||||
Status = 1;
|
||||
} else {
|
||||
//
|
||||
// If any certificate in the chain is enrolled as trusted certificate,
|
||||
// pass the certificate verification.
|
||||
//
|
||||
if (Error == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY) {
|
||||
Count = sk_X509_num (Context->chain);
|
||||
for (Index = 0; Index < Count; Index++) {
|
||||
Obj->data.x509 = sk_X509_value (Context->chain, Index);
|
||||
if (X509_OBJECT_retrieve_match (Context->ctx->objs, Obj)) {
|
||||
Status = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CRYPTO_w_unlock (CRYPTO_LOCK_X509_STORE);
|
||||
}
|
||||
|
||||
if ((Error == X509_V_ERR_CERT_UNTRUSTED) ||
|
||||
(Error == X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE)) {
|
||||
Status = 1;
|
||||
}
|
||||
|
||||
if (Obj != NULL) {
|
||||
OPENSSL_free (Obj);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Creates a PKCS#7 signedData as described in "PKCS #7: Cryptographic Message
|
||||
Syntax Standard, version 1.5". This interface is only intended to be used for
|
||||
application to perform PKCS#7 functionality validation.
|
||||
|
||||
@param[in] PrivateKey Pointer to the PEM-formatted private key data for
|
||||
data signing.
|
||||
@param[in] PrivateKeySize Size of the PEM private key data in bytes.
|
||||
@param[in] KeyPassword NULL-terminated passphrase used for encrypted PEM
|
||||
key data.
|
||||
@param[in] InData Pointer to the content to be signed.
|
||||
@param[in] InDataSize Size of InData in bytes.
|
||||
@param[in] SignCert Pointer to signer's DER-encoded certificate to sign with.
|
||||
@param[in] OtherCerts Pointer to an optional additional set of certificates to
|
||||
include in the PKCS#7 signedData (e.g. any intermediate
|
||||
CAs in the chain).
|
||||
@param[out] SignedData Pointer to output PKCS#7 signedData.
|
||||
@param[out] SignedDataSize Size of SignedData in bytes.
|
||||
|
||||
@retval TRUE PKCS#7 data signing succeeded.
|
||||
@retval FALSE PKCS#7 data signing failed.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
Pkcs7Sign (
|
||||
IN CONST UINT8 *PrivateKey,
|
||||
IN UINTN PrivateKeySize,
|
||||
IN CONST UINT8 *KeyPassword,
|
||||
IN UINT8 *InData,
|
||||
IN UINTN InDataSize,
|
||||
IN UINT8 *SignCert,
|
||||
IN UINT8 *OtherCerts OPTIONAL,
|
||||
OUT UINT8 **SignedData,
|
||||
OUT UINTN *SignedDataSize
|
||||
)
|
||||
{
|
||||
BOOLEAN Status;
|
||||
EVP_PKEY *Key;
|
||||
BIO *DataBio;
|
||||
PKCS7 *Pkcs7;
|
||||
UINT8 *RsaContext;
|
||||
UINT8 *P7Data;
|
||||
|
||||
//
|
||||
// Check input parameters.
|
||||
//
|
||||
if ((PrivateKey == NULL) || (KeyPassword == NULL) || (InData == NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if ((SignCert == NULL) || (SignedData == NULL) || (SignedDataSize == NULL)) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
RsaContext = NULL;
|
||||
Key = NULL;
|
||||
Pkcs7 = NULL;
|
||||
DataBio = NULL;
|
||||
Status = FALSE;
|
||||
|
||||
//
|
||||
// Retrieve RSA private key from PEM data.
|
||||
//
|
||||
Status = RsaGetPrivateKeyFromPem (
|
||||
PrivateKey,
|
||||
PrivateKeySize,
|
||||
(CONST CHAR8 *) KeyPassword,
|
||||
(VOID **) &RsaContext
|
||||
);
|
||||
if (!Status) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Register & Initialize necessary digest algorithms and PRNG for PKCS#7 Handling
|
||||
//
|
||||
EVP_add_digest (EVP_md5());
|
||||
EVP_add_digest (EVP_sha1());
|
||||
EVP_add_digest (EVP_sha256());
|
||||
RandomSeed (NULL, 0);
|
||||
|
||||
//
|
||||
// Construct OpenSSL EVP_PKEY for private key.
|
||||
//
|
||||
Key = EVP_PKEY_new ();
|
||||
if (Key == NULL) {
|
||||
goto _Exit;
|
||||
}
|
||||
Key->save_type = EVP_PKEY_RSA;
|
||||
Key->type = EVP_PKEY_type (EVP_PKEY_RSA);
|
||||
Key->pkey.rsa = (RSA *) RsaContext;
|
||||
|
||||
//
|
||||
// Convert the data to be signed to BIO format.
|
||||
//
|
||||
DataBio = BIO_new (BIO_s_mem ());
|
||||
BIO_write (DataBio, InData, (int) InDataSize);
|
||||
|
||||
//
|
||||
// Create the PKCS#7 signedData structure.
|
||||
//
|
||||
Pkcs7 = PKCS7_sign (
|
||||
(X509 *) SignCert,
|
||||
Key,
|
||||
(STACK_OF(X509) *) OtherCerts,
|
||||
DataBio,
|
||||
PKCS7_BINARY
|
||||
);
|
||||
if (Pkcs7 == NULL) {
|
||||
goto _Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Convert PKCS#7 signedData structure into DER-encoded buffer.
|
||||
//
|
||||
*SignedDataSize = i2d_PKCS7 (Pkcs7, NULL);
|
||||
if (*SignedDataSize == 0) {
|
||||
goto _Exit;
|
||||
}
|
||||
*SignedData = OPENSSL_malloc (*SignedDataSize);
|
||||
P7Data = *SignedData;
|
||||
*SignedDataSize = i2d_PKCS7 (Pkcs7, (unsigned char **) &P7Data);
|
||||
|
||||
Status = TRUE;
|
||||
|
||||
_Exit:
|
||||
//
|
||||
// Release Resources
|
||||
//
|
||||
if (RsaContext != NULL) {
|
||||
RsaFree (RsaContext);
|
||||
if (Key != NULL) {
|
||||
Key->pkey.rsa = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (Key != NULL) {
|
||||
EVP_PKEY_free (Key);
|
||||
}
|
||||
|
||||
if (DataBio != NULL) {
|
||||
BIO_free (DataBio);
|
||||
}
|
||||
|
||||
if (Pkcs7 != NULL) {
|
||||
PKCS7_free (Pkcs7);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Verifies the validility of a PKCS#7 signed data as described in "PKCS #7: Cryptographic
|
||||
Message Syntax Standard".
|
||||
@@ -49,7 +278,6 @@ Pkcs7Verify (
|
||||
)
|
||||
{
|
||||
PKCS7 *Pkcs7;
|
||||
UINT8 *Content;
|
||||
BIO *CertBio;
|
||||
BIO *DataBio;
|
||||
BOOLEAN Status;
|
||||
@@ -73,6 +301,7 @@ Pkcs7Verify (
|
||||
//
|
||||
EVP_add_digest (EVP_md5());
|
||||
EVP_add_digest (EVP_sha1());
|
||||
EVP_add_digest_alias (SN_sha1WithRSAEncryption, SN_sha1WithRSA);
|
||||
EVP_add_digest (EVP_sha256());
|
||||
|
||||
//
|
||||
@@ -90,23 +319,6 @@ Pkcs7Verify (
|
||||
goto _Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Check PKCS#7 embedded signed content with InData.
|
||||
//
|
||||
if (InData != NULL) {
|
||||
//
|
||||
// NOTE: PKCS7_dataDecode() 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.
|
||||
//
|
||||
Content = (UINT8 *)(Pkcs7->d.sign->contents->d.other->value.asn1_string->data);
|
||||
|
||||
// Ignore two bytes for DER encoding of ASN.1 "SEQUENCE"
|
||||
if (CompareMem (Content + 2, InData, DataLength) != 0) {
|
||||
goto _Exit;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Read DER-encoded root certificate and Construct X509 Certificate
|
||||
//
|
||||
@@ -131,6 +343,12 @@ Pkcs7Verify (
|
||||
goto _Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Register customized X509 verification callback function to support
|
||||
// trusted intermediate certificate anchor.
|
||||
//
|
||||
CertStore->verify_cb = X509VerifyCb;
|
||||
|
||||
//
|
||||
// For generic PKCS#7 handling, InData may be NULL if the content is present
|
||||
// in PKCS#7 structure. So ignore NULL checking here.
|
||||
@@ -141,7 +359,7 @@ Pkcs7Verify (
|
||||
//
|
||||
// Verifies the PKCS#7 signedData structure
|
||||
//
|
||||
Status = (BOOLEAN) PKCS7_verify (Pkcs7, NULL, CertStore, DataBio, NULL, 0);
|
||||
Status = (BOOLEAN) PKCS7_verify (Pkcs7, NULL, CertStore, DataBio, NULL, PKCS7_BINARY);
|
||||
|
||||
_Exit:
|
||||
//
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
RSA Asymmetric Cipher Wrapper Implementation over OpenSSL.
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2009 - 2011, 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
|
||||
@@ -545,7 +545,7 @@ DigestInfoEncoding (
|
||||
|
||||
If RsaContext is NULL, then ASSERT().
|
||||
If MessageHash is NULL, then ASSERT().
|
||||
If HashSize is not equal to the size of MD5, SHA-1, SHA-256, SHA-224, SHA-512 or SHA-384 digest, then ASSERT().
|
||||
If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then ASSERT().
|
||||
If SigSize is large enough but Signature is NULL, then ASSERT().
|
||||
|
||||
@param[in] RsaContext Pointer to RSA context for signature generation.
|
||||
@@ -615,7 +615,7 @@ RsaPkcs1Sign (
|
||||
If RsaContext is NULL, then ASSERT().
|
||||
If MessageHash is NULL, then ASSERT().
|
||||
If Signature is NULL, then ASSERT().
|
||||
If HashSize is not equal to the size of MD5, SHA-1, SHA-256, SHA-224, SHA-512 or SHA-384 digest, then ASSERT().
|
||||
If HashSize is not equal to the size of MD5, SHA-1 or SHA-256 digest, then ASSERT().
|
||||
|
||||
@param[in] RsaContext Pointer to RSA context for signature verification.
|
||||
@param[in] MessageHash Pointer to octet message hash to be checked.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
X.509 Certificate Handler Wrapper Implementation over OpenSSL.
|
||||
|
||||
Copyright (c) 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2010 - 2011, 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
|
||||
@@ -15,6 +15,202 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
||||
#include "InternalCryptLib.h"
|
||||
#include <openssl/x509.h>
|
||||
|
||||
|
||||
/**
|
||||
Construct a X509 object from DER-encoded certificate data.
|
||||
|
||||
If Cert is NULL, then ASSERT().
|
||||
If SingleX509Cert is NULL, then ASSERT().
|
||||
|
||||
@param[in] Cert Pointer to the DER-encoded certificate data.
|
||||
@param[in] CertSize The size of certificate data in bytes.
|
||||
@param[out] SingleX509Cert The generated X509 object.
|
||||
|
||||
@retval TRUE The X509 object generation succeeded.
|
||||
@retval FALSE The operation failed.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
X509ConstructCertificate (
|
||||
IN CONST UINT8 *Cert,
|
||||
IN UINTN CertSize,
|
||||
OUT UINT8 **SingleX509Cert
|
||||
)
|
||||
{
|
||||
BIO *CertBio;
|
||||
X509 *X509Cert;
|
||||
BOOLEAN Status;
|
||||
|
||||
//
|
||||
// ASSERT if Cert is NULL or SingleX509Cert is NULL.
|
||||
//
|
||||
ASSERT (Cert != NULL);
|
||||
ASSERT (SingleX509Cert != NULL);
|
||||
|
||||
Status = FALSE;
|
||||
|
||||
//
|
||||
// Read DER-encoded X509 Certificate and Construct X509 object.
|
||||
//
|
||||
CertBio = BIO_new (BIO_s_mem ());
|
||||
BIO_write (CertBio, Cert, (int) CertSize);
|
||||
if (CertBio == NULL) {
|
||||
goto _Exit;
|
||||
}
|
||||
X509Cert = d2i_X509_bio (CertBio, NULL);
|
||||
if (X509Cert == NULL) {
|
||||
goto _Exit;
|
||||
}
|
||||
|
||||
*SingleX509Cert = (UINT8 *) X509Cert;
|
||||
Status = TRUE;
|
||||
|
||||
_Exit:
|
||||
//
|
||||
// Release Resources.
|
||||
//
|
||||
BIO_free (CertBio);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Construct a X509 stack object from a list of DER-encoded certificate data.
|
||||
|
||||
If X509Stack is NULL, then ASSERT().
|
||||
|
||||
@param[in, out] X509Stack On input, pointer to an existing X509 stack object.
|
||||
On output, pointer to the X509 stack object with new
|
||||
inserted X509 certificate.
|
||||
@param ... A list of DER-encoded single certificate data followed
|
||||
by certificate size. A NULL terminates the list. The
|
||||
pairs are the arguments to X509ConstructCertificate().
|
||||
|
||||
@retval TRUE The X509 stack construction succeeded.
|
||||
@retval FALSE The construction operation failed.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
X509ConstructCertificateStack (
|
||||
IN OUT UINT8 **X509Stack,
|
||||
...
|
||||
)
|
||||
{
|
||||
UINT8 *Cert;
|
||||
UINTN CertSize;
|
||||
X509 *X509Cert;
|
||||
STACK_OF(X509) *CertStack;
|
||||
BOOLEAN Status;
|
||||
VA_LIST Args;
|
||||
UINTN Index;
|
||||
|
||||
//
|
||||
// ASSERT if input X509Stack is NULL.
|
||||
//
|
||||
ASSERT (X509Stack != NULL);
|
||||
|
||||
Status = FALSE;
|
||||
|
||||
//
|
||||
// Initialize X509 stack object.
|
||||
//
|
||||
CertStack = (STACK_OF(X509) *) (*X509Stack);
|
||||
if (CertStack == NULL) {
|
||||
CertStack = sk_X509_new_null ();
|
||||
if (CertStack == NULL) {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
VA_START (Args, X509Stack);
|
||||
|
||||
for (Index = 0; ; Index++) {
|
||||
//
|
||||
// If Cert is NULL, then it is the end of the list.
|
||||
//
|
||||
Cert = VA_ARG (Args, UINT8 *);
|
||||
if (Cert == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
CertSize = VA_ARG (Args, UINTN);
|
||||
|
||||
//
|
||||
// Construct X509 Object from the given DER-encoded certificate data.
|
||||
//
|
||||
Status = X509ConstructCertificate (
|
||||
(CONST UINT8 *) Cert,
|
||||
CertSize,
|
||||
(UINT8 **) &X509Cert
|
||||
);
|
||||
if (!Status) {
|
||||
X509_free (X509Cert);
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Insert the new X509 object into X509 stack object.
|
||||
//
|
||||
sk_X509_push (CertStack, X509Cert);
|
||||
}
|
||||
|
||||
VA_END (Args);
|
||||
|
||||
if (!Status) {
|
||||
sk_X509_pop_free (CertStack, X509_free);
|
||||
} else {
|
||||
*X509Stack = (UINT8 *) CertStack;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Release the specified X509 object.
|
||||
|
||||
If X509Cert is NULL, then ASSERT().
|
||||
|
||||
@param[in] X509Cert Pointer to the X509 object to be released.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
X509Free (
|
||||
IN VOID *X509Cert
|
||||
)
|
||||
{
|
||||
ASSERT (X509Cert != NULL);
|
||||
|
||||
//
|
||||
// Free OpenSSL X509 object.
|
||||
//
|
||||
X509_free ((X509 *) X509Cert);
|
||||
}
|
||||
|
||||
/**
|
||||
Release the specified X509 stack object.
|
||||
|
||||
If X509Stack is NULL, then ASSERT().
|
||||
|
||||
@param[in] X509Stack Pointer to the X509 stack object to be released.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
X509StackFree (
|
||||
IN VOID *X509Stack
|
||||
)
|
||||
{
|
||||
ASSERT (X509Stack != NULL);
|
||||
|
||||
//
|
||||
// Free OpenSSL X509 stack object.
|
||||
//
|
||||
sk_X509_pop_free ((STACK_OF(X509) *) X509Stack, X509_free);
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieve the subject bytes from one X.509 certificate.
|
||||
|
||||
@@ -42,7 +238,6 @@ X509GetSubjectName (
|
||||
)
|
||||
{
|
||||
BOOLEAN Status;
|
||||
BIO *CertBio;
|
||||
X509 *X509Cert;
|
||||
X509_NAME *X509Name;
|
||||
|
||||
@@ -58,13 +253,8 @@ X509GetSubjectName (
|
||||
//
|
||||
// Read DER-encoded X509 Certificate and Construct X509 object.
|
||||
//
|
||||
CertBio = BIO_new (BIO_s_mem ());
|
||||
BIO_write (CertBio, Cert, (int)CertSize);
|
||||
if (CertBio == NULL) {
|
||||
goto _Exit;
|
||||
}
|
||||
X509Cert = d2i_X509_bio (CertBio, NULL);
|
||||
if (Cert == NULL) {
|
||||
Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert);
|
||||
if ((X509Cert == NULL) || (!Status)) {
|
||||
goto _Exit;
|
||||
}
|
||||
|
||||
@@ -86,7 +276,6 @@ _Exit:
|
||||
//
|
||||
// Release Resources.
|
||||
//
|
||||
BIO_free (CertBio);
|
||||
X509_free (X509Cert);
|
||||
|
||||
return Status;
|
||||
@@ -118,7 +307,6 @@ RsaGetPublicKeyFromX509 (
|
||||
{
|
||||
BOOLEAN Status;
|
||||
EVP_PKEY *Pkey;
|
||||
BIO *CertBio;
|
||||
X509 *X509Cert;
|
||||
|
||||
//
|
||||
@@ -129,19 +317,13 @@ RsaGetPublicKeyFromX509 (
|
||||
|
||||
Status = FALSE;
|
||||
Pkey = NULL;
|
||||
CertBio = NULL;
|
||||
X509Cert = NULL;
|
||||
|
||||
//
|
||||
// Read DER-encoded X509 Certificate and Construct X509 object.
|
||||
//
|
||||
CertBio = BIO_new (BIO_s_mem ());
|
||||
BIO_write (CertBio, Cert, (int)CertSize);
|
||||
if (CertBio == NULL) {
|
||||
goto _Exit;
|
||||
}
|
||||
X509Cert = d2i_X509_bio (CertBio, NULL);
|
||||
if (X509Cert == NULL) {
|
||||
Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert);
|
||||
if ((X509Cert == NULL) || (!Status)) {
|
||||
goto _Exit;
|
||||
}
|
||||
|
||||
@@ -164,7 +346,6 @@ _Exit:
|
||||
//
|
||||
// Release Resources.
|
||||
//
|
||||
BIO_free (CertBio);
|
||||
X509_free (X509Cert);
|
||||
EVP_PKEY_free (Pkey);
|
||||
|
||||
@@ -197,8 +378,6 @@ X509VerifyCert (
|
||||
)
|
||||
{
|
||||
BOOLEAN Status;
|
||||
BIO *BioCert;
|
||||
BIO *BioCACert;
|
||||
X509 *X509Cert;
|
||||
X509 *X509CACert;
|
||||
X509_STORE *CertStore;
|
||||
@@ -211,8 +390,6 @@ X509VerifyCert (
|
||||
ASSERT (CACert != NULL);
|
||||
|
||||
Status = FALSE;
|
||||
BioCert = NULL;
|
||||
BioCACert = NULL;
|
||||
X509Cert = NULL;
|
||||
X509CACert = NULL;
|
||||
CertStore = NULL;
|
||||
@@ -227,26 +404,16 @@ X509VerifyCert (
|
||||
//
|
||||
// Read DER-encoded certificate to be verified and Construct X509 object.
|
||||
//
|
||||
BioCert = BIO_new (BIO_s_mem ());
|
||||
BIO_write (BioCert, Cert, (int)CertSize);
|
||||
if (BioCert == NULL) {
|
||||
goto _Exit;
|
||||
}
|
||||
X509Cert = d2i_X509_bio (BioCert, NULL);
|
||||
if (X509Cert == NULL) {
|
||||
Status = X509ConstructCertificate (Cert, CertSize, (UINT8 **) &X509Cert);
|
||||
if ((X509Cert == NULL) || (!Status)) {
|
||||
goto _Exit;
|
||||
}
|
||||
|
||||
//
|
||||
// Read DER-encoded root certificate and Construct X509 object.
|
||||
//
|
||||
BioCACert = BIO_new (BIO_s_mem());
|
||||
BIO_write (BioCACert, CACert, (int)CACertSize);
|
||||
if (BioCert == NULL) {
|
||||
goto _Exit;
|
||||
}
|
||||
X509CACert = d2i_X509_bio (BioCACert, NULL);
|
||||
if (CACert == NULL) {
|
||||
Status = X509ConstructCertificate (CACert, CACertSize, (UINT8 **) &X509CACert);
|
||||
if ((X509CACert == NULL) || (!Status)) {
|
||||
goto _Exit;
|
||||
}
|
||||
|
||||
@@ -277,8 +444,6 @@ _Exit:
|
||||
//
|
||||
// Release Resources.
|
||||
//
|
||||
BIO_free (BioCert);
|
||||
BIO_free (BioCACert);
|
||||
X509_free (X509Cert);
|
||||
X509_free (X509CACert);
|
||||
X509_STORE_free (CertStore);
|
||||
|
Reference in New Issue
Block a user